2 Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998, 2000, 2001
3 Free Software Foundation, Inc.
4 Contributed by steve chamberlain @cygnus
6 This file is part of BFD, the Binary File Descriptor library.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
22 /* Yet another way of extracting documentation from source.
23 No, I haven't finished it yet, but I hope you people like it better
28 Basically, this is a sort of string forth, maybe we should call it
31 You define new words thus:
32 : <newword> <oldwords> ;
36 /* Primitives provided by the program:
38 Two stacks are provided, a string stack and an integer stack.
40 Internal state variables:
41 internal_wanted - indicates whether `-i' was passed
42 internal_mode - user-settable
46 ! - pop top of integer stack for address, pop next for value; store
47 @ - treat value on integer stack as the address of an integer; push
48 that integer on the integer stack after popping the "address"
49 hello - print "hello\n" to stdout
50 stdout - put stdout marker on TOS
51 stderr - put stderr marker on TOS
52 print - print TOS-1 on TOS (eg: "hello\n" stdout print)
55 copy_past_newline - append input, up to and including newline into TOS
59 remchar - delete last character from TOS
61 do_fancy_stuff - translate <<foo>> to @code{foo} in TOS
62 bulletize - if "o" lines found, prepend @itemize @bullet to TOS
63 and @item to each "o" line; append @end itemize
64 courierize - put @example around . and | lines, translate {* *} { }
67 outputdots - strip out lines without leading dots
68 paramstuff - convert full declaration into "PARAMS" form if not already
69 maybecatstr - do catstr if internal_mode == internal_wanted, discard
71 translatecomments - turn {* and *} into comment delimiters
72 kill_bogus_lines - get rid of extra newlines
74 internalmode - pop from integer stack, set `internalmode' to that value
75 print_stack_level - print current stack depth to stderr
76 strip_trailing_newlines - go ahead, guess...
77 [quoted string] - push string onto string stack
78 [word starting with digit] - push atol(str) onto integer stack
80 A command must be all upper-case, and alone on a line.
98 /* Here is a string type ... */
100 typedef struct buffer
103 unsigned long write_idx
;
108 static void init_string_with_size (string_type
*, unsigned int);
109 static void init_string (string_type
*);
110 static int find (string_type
*, char *);
111 static void write_buffer (string_type
*, FILE *);
112 static void delete_string (string_type
*);
113 static char *addr (string_type
*, unsigned int);
114 static char at (string_type
*, unsigned int);
115 static void catchar (string_type
*, int);
116 static void overwrite_string (string_type
*, string_type
*);
117 static void catbuf (string_type
*, char *, unsigned int);
118 static void cattext (string_type
*, char *);
119 static void catstr (string_type
*, string_type
*);
123 init_string_with_size (buffer
, size
)
127 buffer
->write_idx
= 0;
129 buffer
->ptr
= malloc (size
);
136 init_string_with_size (buffer
, DEF_SIZE
);
147 for (i
= 0; i
< str
->write_idx
&& *p
; i
++)
149 if (*p
== str
->ptr
[i
])
158 write_buffer (buffer
, f
)
162 fwrite (buffer
->ptr
, buffer
->write_idx
, 1, f
);
166 delete_string (buffer
)
177 return buffer
->ptr
+ idx
;
185 if (pos
>= buffer
->write_idx
)
187 return buffer
->ptr
[pos
];
195 if (buffer
->write_idx
== buffer
->size
)
198 buffer
->ptr
= realloc (buffer
->ptr
, buffer
->size
);
201 buffer
->ptr
[buffer
->write_idx
++] = ch
;
205 overwrite_string (dst
, src
)
210 dst
->size
= src
->size
;
211 dst
->write_idx
= src
->write_idx
;
216 catbuf (buffer
, buf
, len
)
221 if (buffer
->write_idx
+ len
>= buffer
->size
)
223 while (buffer
->write_idx
+ len
>= buffer
->size
)
225 buffer
->ptr
= realloc (buffer
->ptr
, buffer
->size
);
227 memcpy (buffer
->ptr
+ buffer
->write_idx
, buf
, len
);
228 buffer
->write_idx
+= len
;
232 cattext (buffer
, string
)
236 catbuf (buffer
, string
, (unsigned int) strlen (string
));
244 catbuf (dst
, src
->ptr
, src
->write_idx
);
248 skip_white_and_stars (src
, idx
)
253 while ((c
= at (src
, idx
)),
254 isspace ((unsigned char) c
)
256 /* Don't skip past end-of-comment or star as first
257 character on its line. */
258 && at (src
, idx
+1) != '/'
259 && at (src
, idx
-1) != '\n'))
264 /***********************************************************************/
266 string_type stack
[STACK
];
269 unsigned int idx
= 0; /* Pos in input buffer */
270 string_type
*ptr
; /* and the buffer */
271 typedef void (*stinst_type
)();
273 stinst_type sstack
[STACK
];
274 stinst_type
*ssp
= &sstack
[0];
276 long *isp
= &istack
[0];
278 typedef int *word_type
;
283 struct dict_struct
*next
;
290 typedef struct dict_struct dict_type
;
292 #define WORD(x) static void x()
298 fprintf (stderr
, "%s\n", msg
);
306 die ("underflow in string stack");
307 if (tos
>= stack
+ STACK
)
308 die ("overflow in string stack");
315 die ("underflow in integer stack");
316 if (isp
>= istack
+ STACK
)
317 die ("overflow in integer stack");
321 static void exec (dict_type
*);
322 static void call (void);
323 static void remchar (void), strip_trailing_newlines (void), push_number (void);
324 static void push_text (void);
325 static void remove_noncomments (string_type
*, string_type
*);
326 static void print_stack_level (void);
327 static void paramstuff (void), translatecomments (void);
328 static void outputdots (void), courierize (void), bulletize (void);
329 static void do_fancy_stuff (void);
330 static int iscommand (string_type
*, unsigned int);
331 static int copy_past_newline (string_type
*, unsigned int, string_type
*);
332 static void icopy_past_newline (void), kill_bogus_lines (void), indent (void);
333 static void get_stuff_in_command (void), swap (void), other_dup (void);
334 static void drop (void), idrop (void);
335 static void icatstr (void), skip_past_newline (void), internalmode (void);
336 static void maybecatstr (void);
337 static char *nextword (char *, char **);
338 dict_type
*lookup_word (char *);
339 static void perform (void);
340 dict_type
*newentry (char *);
341 unsigned int add_to_definition (dict_type
*, stinst_type
);
342 void add_intrinsic (char *, void (*)());
343 void add_var (char *);
344 void compile (char *);
345 static void bang (void);
346 static void atsign (void);
347 static void hello (void);
348 static void stdout_ (void);
349 static void stderr_ (void);
350 static void print (void);
351 static void read_in (string_type
*, FILE *);
352 static void usage (void);
353 static void chew_exit (void);
367 stinst_type
*oldpc
= pc
;
369 e
= (dict_type
*) (pc
[1]);
382 strip_trailing_newlines ()
384 while ((isspace ((unsigned char) at (tos
, tos
->write_idx
- 1))
385 || at (tos
, tos
->write_idx
- 1) == '\n')
386 && tos
->write_idx
> 0)
406 cattext (tos
, *((char **) pc
));
410 /* This function removes everything not inside comments starting on
411 the first char of the line from the string, also when copying
412 comments, removes blank space and leading *'s.
413 Blank lines are turned into one blank line. */
416 remove_noncomments (src
, dst
)
420 unsigned int idx
= 0;
422 while (at (src
, idx
))
424 /* Now see if we have a comment at the start of the line. */
425 if (at (src
, idx
) == '\n'
426 && at (src
, idx
+ 1) == '/'
427 && at (src
, idx
+ 2) == '*')
431 idx
= skip_white_and_stars (src
, idx
);
433 /* Remove leading dot */
434 if (at (src
, idx
) == '.')
437 /* Copy to the end of the line, or till the end of the
439 while (at (src
, idx
))
441 if (at (src
, idx
) == '\n')
443 /* end of line, echo and scrape of leading blanks */
444 if (at (src
, idx
+ 1) == '\n')
448 idx
= skip_white_and_stars (src
, idx
);
450 else if (at (src
, idx
) == '*' && at (src
, idx
+ 1) == '/')
453 cattext (dst
, "\nENDDD\n");
458 catchar (dst
, at (src
, idx
));
471 fprintf (stderr
, "current string stack depth = %d, ", tos
- stack
);
472 fprintf (stderr
, "current integer stack depth = %d\n", isp
- istack
);
480 name PARAMS ((stuff));
494 /* Make sure that it's not already param'd or proto'd. */
495 if (find (tos
, "PARAMS") || find (tos
, "PROTO") || !find (tos
, "("))
501 /* Find the open paren. */
502 for (openp
= 0; at (tos
, openp
) != '(' && at (tos
, openp
); openp
++)
506 /* Step back to the fname. */
508 while (fname
&& isspace ((unsigned char) at (tos
, fname
)))
511 && !isspace ((unsigned char) at (tos
,fname
))
512 && at (tos
,fname
) != '*')
517 /* Output type, omitting trailing whitespace character(s), if
519 for (len
= fname
; 0 < len
; len
--)
521 if (!isspace ((unsigned char) at (tos
, len
- 1)))
524 for (idx
= 0; idx
< len
; idx
++)
525 catchar (&out
, at (tos
, idx
));
527 cattext (&out
, "\n"); /* Insert a newline between type and fnname */
529 /* Output function name, omitting trailing whitespace
530 character(s), if any. */
531 for (len
= openp
; 0 < len
; len
--)
533 if (!isspace ((unsigned char) at (tos
, len
- 1)))
536 for (idx
= fname
; idx
< len
; idx
++)
537 catchar (&out
, at (tos
, idx
));
539 cattext (&out
, " PARAMS (");
541 for (idx
= openp
; at (tos
, idx
) && at (tos
, idx
) != ';'; idx
++)
542 catchar (&out
, at (tos
, idx
));
544 cattext (&out
, ");\n\n");
546 overwrite_string (tos
, &out
);
552 and *} into comments */
554 WORD (translatecomments
)
556 unsigned int idx
= 0;
560 while (at (tos
, idx
))
562 if (at (tos
, idx
) == '{' && at (tos
, idx
+ 1) == '*')
564 cattext (&out
, "/*");
567 else if (at (tos
, idx
) == '*' && at (tos
, idx
+ 1) == '}')
569 cattext (&out
, "*/");
574 catchar (&out
, at (tos
, idx
));
579 overwrite_string (tos
, &out
);
586 /* This is not currently used. */
588 /* turn everything not starting with a . into a comment */
590 WORD (manglecomments
)
592 unsigned int idx
= 0;
596 while (at (tos
, idx
))
598 if (at (tos
, idx
) == '\n' && at (tos
, idx
+ 1) == '*')
600 cattext (&out
, " /*");
603 else if (at (tos
, idx
) == '*' && at (tos
, idx
+ 1) == '}')
605 cattext (&out
, "*/");
610 catchar (&out
, at (tos
, idx
));
615 overwrite_string (tos
, &out
);
622 /* Mod tos so that only lines with leading dots remain */
626 unsigned int idx
= 0;
630 while (at (tos
, idx
))
632 if (at (tos
, idx
) == '\n' && at (tos
, idx
+ 1) == '.')
637 while ((c
= at (tos
, idx
)) && c
!= '\n')
639 if (c
== '{' && at (tos
, idx
+ 1) == '*')
641 cattext (&out
, "/*");
644 else if (c
== '*' && at (tos
, idx
+ 1) == '}')
646 cattext (&out
, "*/");
655 catchar (&out
, '\n');
663 overwrite_string (tos
, &out
);
667 /* Find lines starting with . and | and put example around them on tos */
671 unsigned int idx
= 0;
676 while (at (tos
, idx
))
678 if (at (tos
, idx
) == '\n'
679 && (at (tos
, idx
+1 ) == '.'
680 || at (tos
, idx
+ 1) == '|'))
682 cattext (&out
, "\n@example\n");
687 while (at (tos
, idx
) && at (tos
, idx
) != '\n')
689 if (at (tos
, idx
) == '{' && at (tos
, idx
+ 1) == '*')
691 cattext (&out
, "/*");
694 else if (at (tos
, idx
) == '*' && at (tos
, idx
+ 1) == '}')
696 cattext (&out
, "*/");
699 else if (at (tos
, idx
) == '{' && !command
)
701 cattext (&out
, "@{");
704 else if (at (tos
, idx
) == '}' && !command
)
706 cattext (&out
, "@}");
711 if (at (tos
, idx
) == '@')
713 else if (isspace ((unsigned char) at (tos
, idx
))
714 || at (tos
, idx
) == '}')
716 catchar (&out
, at (tos
, idx
));
721 catchar (&out
, '\n');
723 while (at (tos
, idx
) == '\n'
724 && ((at (tos
, idx
+ 1) == '.')
725 || (at (tos
, idx
+ 1) == '|')))
727 cattext (&out
, "@end example");
731 catchar (&out
, at (tos
, idx
));
736 overwrite_string (tos
, &out
);
740 /* Finds any lines starting with "o ", if there are any, then turns
741 on @itemize @bullet, and @items each of them. Then ends with @end
742 itemize, inplace at TOS*/
746 unsigned int idx
= 0;
751 while (at (tos
, idx
))
753 if (at (tos
, idx
) == '@'
754 && at (tos
, idx
+ 1) == '*')
759 else if (at (tos
, idx
) == '\n'
760 && at (tos
, idx
+ 1) == 'o'
761 && isspace ((unsigned char) at (tos
, idx
+ 2)))
765 cattext (&out
, "\n@itemize @bullet\n");
769 cattext (&out
, "\n@item\n");
774 catchar (&out
, at (tos
, idx
));
775 if (on
&& at (tos
, idx
) == '\n'
776 && at (tos
, idx
+ 1) == '\n'
777 && at (tos
, idx
+ 2) != 'o')
779 cattext (&out
, "@end itemize");
788 cattext (&out
, "@end itemize\n");
796 /* Turn <<foo>> into @code{foo} in place at TOS*/
798 WORD (do_fancy_stuff
)
800 unsigned int idx
= 0;
803 while (at (tos
, idx
))
805 if (at (tos
, idx
) == '<'
806 && at (tos
, idx
+ 1) == '<'
807 && !isspace ((unsigned char) at (tos
, idx
+ 2)))
809 /* This qualifies as a << startup. */
811 cattext (&out
, "@code{");
813 && at (tos
, idx
) != '>' )
815 catchar (&out
, at (tos
, idx
));
824 catchar (&out
, at (tos
, idx
));
834 /* A command is all upper case,and alone on a line. */
841 unsigned int len
= 0;
842 while (at (ptr
, idx
))
844 if (isupper ((unsigned char) at (ptr
, idx
))
845 || at (ptr
, idx
) == ' ' || at (ptr
, idx
) == '_')
850 else if (at (ptr
, idx
) == '\n')
863 copy_past_newline (ptr
, idx
, dst
)
870 while (at (ptr
, idx
) && at (ptr
, idx
) != '\n')
872 if (at (ptr
, idx
) == '\t')
874 /* Expand tabs. Neither makeinfo nor TeX can cope well with
878 while (++column
& 7);
882 catchar (dst
, at (ptr
, idx
));
888 catchar (dst
, at (ptr
, idx
));
894 WORD (icopy_past_newline
)
899 idx
= copy_past_newline (ptr
, idx
, tos
);
904 Take the string at the top of the stack, do some prettying. */
906 WORD (kill_bogus_lines
)
916 /* Drop leading nl. */
917 while (at (tos
, idx
) == '\n')
923 /* If the first char is a '.' prepend a newline so that it is
924 recognized properly later. */
925 if (at (tos
, idx
) == '.')
926 catchar (&out
, '\n');
928 /* Find the last char. */
929 while (at (tos
, idx
))
934 /* Find the last non white before the nl. */
937 while (idx
&& isspace ((unsigned char) at (tos
, idx
)))
941 /* Copy buffer upto last char, but blank lines before and after
947 if (at (tos
, c
) == '\n'
948 && at (tos
, c
+ 1) == '\n'
949 && at (tos
, c
+ 2) == '.')
951 /* Ignore two newlines before a dot. */
954 else if (at (tos
, c
) == '.' && sl
)
956 /* remember that this line started with a dot. */
959 else if (at (tos
, c
) == '\n'
960 && at (tos
, c
+ 1) == '\n'
964 /* Ignore two newlines when last line was dot. */
967 catchar (&out
, at (tos
, c
));
968 if (at (tos
, c
) == '\n')
985 catchar (&out
, '\n');
999 while (at (tos
, idx
))
1001 switch (at (tos
, idx
))
1004 cattext (&out
, "\n");
1006 if (tab
&& at (tos
, idx
))
1008 cattext (&out
, " ");
1015 cattext (&out
, " ");
1017 cattext (&out
, "(");
1022 cattext (&out
, ")");
1028 catchar (&out
, at (tos
, idx
));
1037 delete_string (tos
);
1042 WORD (get_stuff_in_command
)
1048 while (at (ptr
, idx
))
1050 if (iscommand (ptr
, idx
))
1052 idx
= copy_past_newline (ptr
, idx
, tos
);
1072 catstr (tos
, tos
- 1);
1094 catstr (tos
, tos
+ 1);
1095 delete_string (tos
+ 1);
1099 WORD (skip_past_newline
)
1101 while (at (ptr
, idx
)
1102 && at (ptr
, idx
) != '\n')
1110 internal_mode
= *(isp
);
1118 if (internal_wanted
== internal_mode
)
1120 catstr (tos
- 1, tos
);
1122 delete_string (tos
);
1129 nextword (string
, word
)
1140 while (isspace ((unsigned char) *string
) || *string
== '-')
1144 while (*string
&& *string
!= '\n')
1156 word_start
= string
;
1163 if (*string
== '\\')
1169 while (*string
!= '"');
1173 while (!isspace ((unsigned char) *string
))
1181 *word
= malloc (length
+ 1);
1186 for (idx
= 0; idx
< length
; idx
++)
1188 if (src
[idx
] == '\\')
1189 switch (src
[idx
+ 1])
1197 *dst
++ = src
[idx
+ 1];
1221 dict_type
*ptr
= root
;
1224 if (strcmp (ptr
->word
, word
) == 0)
1229 fprintf (stderr
, "Can't find %s\n", word
);
1238 while (at (ptr
, idx
))
1240 /* It's worth looking through the command list. */
1241 if (iscommand (ptr
, idx
))
1246 (void) nextword (addr (ptr
, idx
), &next
);
1248 word
= lookup_word (next
);
1257 fprintf (stderr
, "warning, %s is not recognised\n", next
);
1258 skip_past_newline ();
1263 skip_past_newline ();
1271 dict_type
*new = (dict_type
*) malloc (sizeof (dict_type
));
1275 new->code
= (stinst_type
*) malloc (sizeof (stinst_type
));
1276 new->code_length
= 1;
1282 add_to_definition (entry
, word
)
1286 if (entry
->code_end
== entry
->code_length
)
1288 entry
->code_length
+= 2;
1290 (stinst_type
*) realloc ((char *) (entry
->code
),
1291 entry
->code_length
* sizeof (word_type
));
1293 entry
->code
[entry
->code_end
] = word
;
1295 return entry
->code_end
++;
1299 add_intrinsic (name
, func
)
1303 dict_type
*new = newentry (name
);
1304 add_to_definition (new, func
);
1305 add_to_definition (new, 0);
1312 dict_type
*new = newentry (name
);
1313 add_to_definition (new, push_number
);
1314 add_to_definition (new, (stinst_type
) (&(new->var
)));
1315 add_to_definition (new, 0);
1322 /* Add words to the dictionary. */
1324 string
= nextword (string
, &word
);
1325 while (string
&& *string
&& word
[0])
1327 if (strcmp (word
, "var") == 0)
1329 string
= nextword (string
, &word
);
1332 string
= nextword (string
, &word
);
1334 else if (word
[0] == ':')
1337 /* Compile a word and add to dictionary. */
1338 string
= nextword (string
, &word
);
1340 ptr
= newentry (word
);
1341 string
= nextword (string
, &word
);
1342 while (word
[0] != ';')
1347 /* got a string, embed magic push string
1349 add_to_definition (ptr
, push_text
);
1350 add_to_definition (ptr
, (stinst_type
) (word
+ 1));
1362 /* Got a number, embedd the magic push number
1364 add_to_definition (ptr
, push_number
);
1365 add_to_definition (ptr
, (stinst_type
) atol (word
));
1368 add_to_definition (ptr
, call
);
1369 add_to_definition (ptr
, (stinst_type
) lookup_word (word
));
1372 string
= nextword (string
, &word
);
1374 add_to_definition (ptr
, 0);
1375 string
= nextword (string
, &word
);
1379 fprintf (stderr
, "syntax error at %s\n", string
- 1);
1387 *(long *) ((isp
[0])) = isp
[-1];
1395 isp
[0] = *(long *) (isp
[0]);
1424 write_buffer (tos
, stdout
);
1426 write_buffer (tos
, stderr
);
1428 fprintf (stderr
, "print: illegal print destination `%ld'\n", *isp
);
1445 r
= fread (buff
, 1, sizeof (buff
), file
);
1446 catbuf (str
, buff
, r
);
1451 catbuf (str
, buff
, 1);
1457 fprintf (stderr
, "usage: -[d|i|g] <file >file\n");
1461 /* There is no reliable way to declare exit. Sometimes it returns
1462 int, and sometimes it returns void. Sometimes it changes between
1463 OS releases. Trying to get it declared correctly in the hosts file
1464 is a pointless waste of time. */
1481 init_string (&buffer
);
1482 init_string (&pptr
);
1483 init_string (stack
+ 0);
1487 add_intrinsic ("push_text", push_text
);
1488 add_intrinsic ("!", bang
);
1489 add_intrinsic ("@", atsign
);
1490 add_intrinsic ("hello", hello
);
1491 add_intrinsic ("stdout", stdout_
);
1492 add_intrinsic ("stderr", stderr_
);
1493 add_intrinsic ("print", print
);
1494 add_intrinsic ("skip_past_newline", skip_past_newline
);
1495 add_intrinsic ("catstr", icatstr
);
1496 add_intrinsic ("copy_past_newline", icopy_past_newline
);
1497 add_intrinsic ("dup", other_dup
);
1498 add_intrinsic ("drop", drop
);
1499 add_intrinsic ("idrop", idrop
);
1500 add_intrinsic ("remchar", remchar
);
1501 add_intrinsic ("get_stuff_in_command", get_stuff_in_command
);
1502 add_intrinsic ("do_fancy_stuff", do_fancy_stuff
);
1503 add_intrinsic ("bulletize", bulletize
);
1504 add_intrinsic ("courierize", courierize
);
1505 /* If the following line gives an error, exit() is not declared in the
1506 ../hosts/foo.h file for this host. Fix it there, not here! */
1507 /* No, don't fix it anywhere; see comment on chew_exit--Ian Taylor. */
1508 add_intrinsic ("exit", chew_exit
);
1509 add_intrinsic ("swap", swap
);
1510 add_intrinsic ("outputdots", outputdots
);
1511 add_intrinsic ("paramstuff", paramstuff
);
1512 add_intrinsic ("maybecatstr", maybecatstr
);
1513 add_intrinsic ("translatecomments", translatecomments
);
1514 add_intrinsic ("kill_bogus_lines", kill_bogus_lines
);
1515 add_intrinsic ("indent", indent
);
1516 add_intrinsic ("internalmode", internalmode
);
1517 add_intrinsic ("print_stack_level", print_stack_level
);
1518 add_intrinsic ("strip_trailing_newlines", strip_trailing_newlines
);
1520 /* Put a nl at the start. */
1521 catchar (&buffer
, '\n');
1523 read_in (&buffer
, stdin
);
1524 remove_noncomments (&buffer
, ptr
);
1525 for (i
= 1; i
< (unsigned int) ac
; i
++)
1527 if (av
[i
][0] == '-')
1529 if (av
[i
][1] == 'f')
1535 f
= fopen (av
[i
+ 1], "r");
1538 fprintf (stderr
, "Can't open the input file %s\n",
1547 else if (av
[i
][1] == 'i')
1549 internal_wanted
= 1;
1551 else if (av
[i
][1] == 'w')
1559 write_buffer (stack
+ 0, stdout
);
1562 fprintf (stderr
, "finishing with current stack level %d\n",
This page took 0.09049 seconds and 4 git commands to generate.