0773f9c1b02a9729f29054c57d4dff6cd3c863d3
2 Copyright (C) 1990-2014 Free Software Foundation, Inc.
3 Contributed by steve chamberlain @cygnus
5 This file is part of BFD, the Binary File Descriptor library.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20 MA 02110-1301, 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.
99 /* Here is a string type ... */
101 typedef struct buffer
104 unsigned long write_idx
;
109 static void init_string_with_size (string_type
*, unsigned int);
110 static void init_string (string_type
*);
111 static int find (string_type
*, char *);
112 static void write_buffer (string_type
*, FILE *);
113 static void delete_string (string_type
*);
114 static char *addr (string_type
*, unsigned int);
115 static char at (string_type
*, unsigned int);
116 static void catchar (string_type
*, int);
117 static void overwrite_string (string_type
*, string_type
*);
118 static void catbuf (string_type
*, char *, unsigned int);
119 static void cattext (string_type
*, char *);
120 static void catstr (string_type
*, string_type
*);
121 static void die (char *);
125 init_string_with_size (buffer
, size
)
129 buffer
->write_idx
= 0;
131 buffer
->ptr
= (char *) malloc (size
);
138 init_string_with_size (buffer
, DEF_SIZE
);
149 for (i
= 0; i
< str
->write_idx
&& *p
; i
++)
151 if (*p
== str
->ptr
[i
])
160 write_buffer (buffer
, f
)
164 if (buffer
->write_idx
!= 0
165 && fwrite (buffer
->ptr
, buffer
->write_idx
, 1, f
) != 1)
166 die ("cannot write output");
170 delete_string (buffer
)
181 return buffer
->ptr
+ idx
;
189 if (pos
>= buffer
->write_idx
)
191 return buffer
->ptr
[pos
];
199 if (buffer
->write_idx
== buffer
->size
)
202 buffer
->ptr
= (char *) realloc (buffer
->ptr
, buffer
->size
);
205 buffer
->ptr
[buffer
->write_idx
++] = ch
;
209 overwrite_string (dst
, src
)
214 dst
->size
= src
->size
;
215 dst
->write_idx
= src
->write_idx
;
220 catbuf (buffer
, buf
, len
)
225 if (buffer
->write_idx
+ len
>= buffer
->size
)
227 while (buffer
->write_idx
+ len
>= buffer
->size
)
229 buffer
->ptr
= (char *) realloc (buffer
->ptr
, buffer
->size
);
231 memcpy (buffer
->ptr
+ buffer
->write_idx
, buf
, len
);
232 buffer
->write_idx
+= len
;
236 cattext (buffer
, string
)
240 catbuf (buffer
, string
, (unsigned int) strlen (string
));
248 catbuf (dst
, src
->ptr
, src
->write_idx
);
252 skip_white_and_stars (src
, idx
)
257 while ((c
= at (src
, idx
)),
258 isspace ((unsigned char) c
)
260 /* Don't skip past end-of-comment or star as first
261 character on its line. */
262 && at (src
, idx
+1) != '/'
263 && at (src
, idx
-1) != '\n'))
268 /***********************************************************************/
270 string_type stack
[STACK
];
273 unsigned int idx
= 0; /* Pos in input buffer */
274 string_type
*ptr
; /* and the buffer */
275 typedef void (*stinst_type
)();
277 stinst_type sstack
[STACK
];
278 stinst_type
*ssp
= &sstack
[0];
280 long *isp
= &istack
[0];
282 typedef int *word_type
;
287 struct dict_struct
*next
;
294 typedef struct dict_struct dict_type
;
300 fprintf (stderr
, "%s\n", msg
);
308 die ("underflow in string stack");
309 if (tos
>= stack
+ STACK
)
310 die ("overflow in string stack");
317 die ("underflow in integer stack");
318 if (isp
>= istack
+ STACK
)
319 die ("overflow in integer stack");
323 static void exec (dict_type
*);
324 static void call (void);
325 static void remchar (void), strip_trailing_newlines (void), push_number (void);
326 static void push_text (void);
327 static void remove_noncomments (string_type
*, string_type
*);
328 static void print_stack_level (void);
329 static void paramstuff (void), translatecomments (void);
330 static void outputdots (void), courierize (void), bulletize (void);
331 static void do_fancy_stuff (void);
332 static int iscommand (string_type
*, unsigned int);
333 static int copy_past_newline (string_type
*, unsigned int, string_type
*);
334 static void icopy_past_newline (void), kill_bogus_lines (void), indent (void);
335 static void get_stuff_in_command (void), swap (void), other_dup (void);
336 static void drop (void), idrop (void);
337 static void icatstr (void), skip_past_newline (void), internalmode (void);
338 static void maybecatstr (void);
339 static char *nextword (char *, char **);
340 dict_type
*lookup_word (char *);
341 static void perform (void);
342 dict_type
*newentry (char *);
343 unsigned int add_to_definition (dict_type
*, stinst_type
);
344 void add_intrinsic (char *, void (*)());
345 void add_var (char *);
346 void compile (char *);
347 static void bang (void);
348 static void atsign (void);
349 static void hello (void);
350 static void stdout_ (void);
351 static void stderr_ (void);
352 static void print (void);
353 static void read_in (string_type
*, FILE *);
354 static void usage (void);
355 static void chew_exit (void);
370 stinst_type
*oldpc
= pc
;
372 e
= (dict_type
*) (pc
[1]);
386 strip_trailing_newlines ()
388 while ((isspace ((unsigned char) at (tos
, tos
->write_idx
- 1))
389 || at (tos
, tos
->write_idx
- 1) == '\n')
390 && tos
->write_idx
> 0)
412 cattext (tos
, *((char **) pc
));
416 /* This function removes everything not inside comments starting on
417 the first char of the line from the string, also when copying
418 comments, removes blank space and leading *'s.
419 Blank lines are turned into one blank line. */
422 remove_noncomments (src
, dst
)
426 unsigned int idx
= 0;
428 while (at (src
, idx
))
430 /* Now see if we have a comment at the start of the line. */
431 if (at (src
, idx
) == '\n'
432 && at (src
, idx
+ 1) == '/'
433 && at (src
, idx
+ 2) == '*')
437 idx
= skip_white_and_stars (src
, idx
);
439 /* Remove leading dot */
440 if (at (src
, idx
) == '.')
443 /* Copy to the end of the line, or till the end of the
445 while (at (src
, idx
))
447 if (at (src
, idx
) == '\n')
449 /* end of line, echo and scrape of leading blanks */
450 if (at (src
, idx
+ 1) == '\n')
454 idx
= skip_white_and_stars (src
, idx
);
456 else if (at (src
, idx
) == '*' && at (src
, idx
+ 1) == '/')
459 cattext (dst
, "\nENDDD\n");
464 catchar (dst
, at (src
, idx
));
477 fprintf (stderr
, "current string stack depth = %ld, ",
478 (long) (tos
- stack
));
479 fprintf (stderr
, "current integer stack depth = %ld\n",
480 (long) (isp
- istack
));
488 name PARAMS ((stuff));
504 /* Make sure that it's not already param'd or proto'd. */
506 || find (tos
, "PARAMS") || find (tos
, "PROTO") || !find (tos
, "("))
512 /* Find the open paren. */
513 for (openp
= 0; at (tos
, openp
) != '(' && at (tos
, openp
); openp
++)
517 /* Step back to the fname. */
519 while (fname
&& isspace ((unsigned char) at (tos
, fname
)))
522 && !isspace ((unsigned char) at (tos
,fname
))
523 && at (tos
,fname
) != '*')
528 /* Output type, omitting trailing whitespace character(s), if
530 for (len
= fname
; 0 < len
; len
--)
532 if (!isspace ((unsigned char) at (tos
, len
- 1)))
535 for (idx
= 0; idx
< len
; idx
++)
536 catchar (&out
, at (tos
, idx
));
538 cattext (&out
, "\n"); /* Insert a newline between type and fnname */
540 /* Output function name, omitting trailing whitespace
541 character(s), if any. */
542 for (len
= openp
; 0 < len
; len
--)
544 if (!isspace ((unsigned char) at (tos
, len
- 1)))
547 for (idx
= fname
; idx
< len
; idx
++)
548 catchar (&out
, at (tos
, idx
));
550 cattext (&out
, " PARAMS (");
552 for (idx
= openp
; at (tos
, idx
) && at (tos
, idx
) != ';'; idx
++)
553 catchar (&out
, at (tos
, idx
));
555 cattext (&out
, ");\n\n");
557 overwrite_string (tos
, &out
);
563 and *} into comments */
568 unsigned int idx
= 0;
572 while (at (tos
, idx
))
574 if (at (tos
, idx
) == '{' && at (tos
, idx
+ 1) == '*')
576 cattext (&out
, "/*");
579 else if (at (tos
, idx
) == '*' && at (tos
, idx
+ 1) == '}')
581 cattext (&out
, "*/");
586 catchar (&out
, at (tos
, idx
));
591 overwrite_string (tos
, &out
);
596 /* Mod tos so that only lines with leading dots remain */
600 unsigned int idx
= 0;
604 while (at (tos
, idx
))
606 if (at (tos
, idx
) == '\n' && at (tos
, idx
+ 1) == '.')
611 while ((c
= at (tos
, idx
)) && c
!= '\n')
613 if (c
== '{' && at (tos
, idx
+ 1) == '*')
615 cattext (&out
, "/*");
618 else if (c
== '*' && at (tos
, idx
+ 1) == '}')
620 cattext (&out
, "*/");
629 catchar (&out
, '\n');
637 overwrite_string (tos
, &out
);
641 /* Find lines starting with . and | and put example around them on tos */
646 unsigned int idx
= 0;
651 while (at (tos
, idx
))
653 if (at (tos
, idx
) == '\n'
654 && (at (tos
, idx
+1 ) == '.'
655 || at (tos
, idx
+ 1) == '|'))
657 cattext (&out
, "\n@example\n");
662 while (at (tos
, idx
) && at (tos
, idx
) != '\n')
666 /* We are inside {} parameters of some command;
667 Just pass through until matching brace. */
668 if (at (tos
, idx
) == '{')
670 else if (at (tos
, idx
) == '}')
673 else if (command
!= 0)
675 if (at (tos
, idx
) == '{')
677 else if (!islower ((unsigned char) at (tos
, idx
)))
680 else if (at (tos
, idx
) == '@'
681 && islower ((unsigned char) at (tos
, idx
+ 1)))
685 else if (at (tos
, idx
) == '{' && at (tos
, idx
+ 1) == '*')
687 cattext (&out
, "/*");
691 else if (at (tos
, idx
) == '*' && at (tos
, idx
+ 1) == '}')
693 cattext (&out
, "*/");
697 else if (at (tos
, idx
) == '{'
698 || at (tos
, idx
) == '}')
703 catchar (&out
, at (tos
, idx
));
706 catchar (&out
, '\n');
708 while (at (tos
, idx
) == '\n'
709 && ((at (tos
, idx
+ 1) == '.')
710 || (at (tos
, idx
+ 1) == '|')))
712 cattext (&out
, "@end example");
716 catchar (&out
, at (tos
, idx
));
721 overwrite_string (tos
, &out
);
725 /* Finds any lines starting with "o ", if there are any, then turns
726 on @itemize @bullet, and @items each of them. Then ends with @end
727 itemize, inplace at TOS*/
732 unsigned int idx
= 0;
737 while (at (tos
, idx
))
739 if (at (tos
, idx
) == '@'
740 && at (tos
, idx
+ 1) == '*')
745 else if (at (tos
, idx
) == '\n'
746 && at (tos
, idx
+ 1) == 'o'
747 && isspace ((unsigned char) at (tos
, idx
+ 2)))
751 cattext (&out
, "\n@itemize @bullet\n");
755 cattext (&out
, "\n@item\n");
760 catchar (&out
, at (tos
, idx
));
761 if (on
&& at (tos
, idx
) == '\n'
762 && at (tos
, idx
+ 1) == '\n'
763 && at (tos
, idx
+ 2) != 'o')
765 cattext (&out
, "@end itemize");
774 cattext (&out
, "@end itemize\n");
782 /* Turn <<foo>> into @code{foo} in place at TOS*/
787 unsigned int idx
= 0;
790 while (at (tos
, idx
))
792 if (at (tos
, idx
) == '<'
793 && at (tos
, idx
+ 1) == '<'
794 && !isspace ((unsigned char) at (tos
, idx
+ 2)))
796 /* This qualifies as a << startup. */
798 cattext (&out
, "@code{");
800 && at (tos
, idx
) != '>' )
802 catchar (&out
, at (tos
, idx
));
811 catchar (&out
, at (tos
, idx
));
821 /* A command is all upper case,and alone on a line. */
828 unsigned int len
= 0;
829 while (at (ptr
, idx
))
831 if (isupper ((unsigned char) at (ptr
, idx
))
832 || at (ptr
, idx
) == ' ' || at (ptr
, idx
) == '_')
837 else if (at (ptr
, idx
) == '\n')
850 copy_past_newline (ptr
, idx
, dst
)
857 while (at (ptr
, idx
) && at (ptr
, idx
) != '\n')
859 if (at (ptr
, idx
) == '\t')
861 /* Expand tabs. Neither makeinfo nor TeX can cope well with
865 while (++column
& 7);
869 catchar (dst
, at (ptr
, idx
));
875 catchar (dst
, at (ptr
, idx
));
882 icopy_past_newline ()
887 idx
= copy_past_newline (ptr
, idx
, tos
);
892 Take the string at the top of the stack, do some prettying. */
905 /* Drop leading nl. */
906 while (at (tos
, idx
) == '\n')
912 /* If the first char is a '.' prepend a newline so that it is
913 recognized properly later. */
914 if (at (tos
, idx
) == '.')
915 catchar (&out
, '\n');
917 /* Find the last char. */
918 while (at (tos
, idx
))
923 /* Find the last non white before the nl. */
926 while (idx
&& isspace ((unsigned char) at (tos
, idx
)))
930 /* Copy buffer upto last char, but blank lines before and after
936 if (at (tos
, c
) == '\n'
937 && at (tos
, c
+ 1) == '\n'
938 && at (tos
, c
+ 2) == '.')
940 /* Ignore two newlines before a dot. */
943 else if (at (tos
, c
) == '.' && sl
)
945 /* remember that this line started with a dot. */
948 else if (at (tos
, c
) == '\n'
949 && at (tos
, c
+ 1) == '\n'
953 /* Ignore two newlines when last line was dot. */
956 catchar (&out
, at (tos
, c
));
957 if (at (tos
, c
) == '\n')
974 catchar (&out
, '\n');
989 while (at (tos
, idx
))
991 switch (at (tos
, idx
))
994 cattext (&out
, "\n");
996 if (tab
&& at (tos
, idx
))
1005 cattext (&out
, " ");
1007 cattext (&out
, "(");
1012 cattext (&out
, ")");
1018 catchar (&out
, at (tos
, idx
));
1027 delete_string (tos
);
1033 get_stuff_in_command ()
1039 while (at (ptr
, idx
))
1041 if (iscommand (ptr
, idx
))
1043 idx
= copy_past_newline (ptr
, idx
, tos
);
1065 catstr (tos
, tos
- 1);
1090 catstr (tos
, tos
+ 1);
1091 delete_string (tos
+ 1);
1096 skip_past_newline ()
1098 while (at (ptr
, idx
)
1099 && at (ptr
, idx
) != '\n')
1108 internal_mode
= *(isp
);
1117 if (internal_wanted
== internal_mode
)
1119 catstr (tos
- 1, tos
);
1121 delete_string (tos
);
1128 nextword (string
, word
)
1139 while (isspace ((unsigned char) *string
) || *string
== '-')
1143 while (*string
&& *string
!= '\n')
1155 word_start
= string
;
1162 if (*string
== '\\')
1168 while (*string
!= '"');
1172 while (!isspace ((unsigned char) *string
))
1180 *word
= (char *) malloc (length
+ 1);
1185 for (idx
= 0; idx
< length
; idx
++)
1187 if (src
[idx
] == '\\')
1188 switch (src
[idx
+ 1])
1196 *dst
++ = src
[idx
+ 1];
1220 dict_type
*ptr
= root
;
1223 if (strcmp (ptr
->word
, word
) == 0)
1228 fprintf (stderr
, "Can't find %s\n", word
);
1237 while (at (ptr
, idx
))
1239 /* It's worth looking through the command list. */
1240 if (iscommand (ptr
, idx
))
1245 (void) nextword (addr (ptr
, idx
), &next
);
1247 word
= lookup_word (next
);
1256 fprintf (stderr
, "warning, %s is not recognised\n", next
);
1257 skip_past_newline ();
1262 skip_past_newline ();
1270 dict_type
*new_d
= (dict_type
*) malloc (sizeof (dict_type
));
1274 new_d
->code
= (stinst_type
*) malloc (sizeof (stinst_type
));
1275 new_d
->code_length
= 1;
1276 new_d
->code_end
= 0;
1281 add_to_definition (entry
, word
)
1285 if (entry
->code_end
== entry
->code_length
)
1287 entry
->code_length
+= 2;
1289 (stinst_type
*) realloc ((char *) (entry
->code
),
1290 entry
->code_length
* sizeof (word_type
));
1292 entry
->code
[entry
->code_end
] = word
;
1294 return entry
->code_end
++;
1298 add_intrinsic (name
, func
)
1302 dict_type
*new_d
= newentry (name
);
1303 add_to_definition (new_d
, func
);
1304 add_to_definition (new_d
, 0);
1311 dict_type
*new_d
= newentry (name
);
1312 add_to_definition (new_d
, push_number
);
1313 add_to_definition (new_d
, (stinst_type
) (&(new_d
->var
)));
1314 add_to_definition (new_d
, 0);
1321 /* Add words to the dictionary. */
1323 string
= nextword (string
, &word
);
1324 while (string
&& *string
&& word
[0])
1326 if (strcmp (word
, "var") == 0)
1328 string
= nextword (string
, &word
);
1331 string
= nextword (string
, &word
);
1333 else if (word
[0] == ':')
1336 /* Compile a word and add to dictionary. */
1337 string
= nextword (string
, &word
);
1339 ptr
= newentry (word
);
1340 string
= nextword (string
, &word
);
1341 while (word
[0] != ';')
1346 /* got a string, embed magic push string
1348 add_to_definition (ptr
, push_text
);
1349 add_to_definition (ptr
, (stinst_type
) (word
+ 1));
1361 /* Got a number, embedd the magic push number
1363 add_to_definition (ptr
, push_number
);
1364 add_to_definition (ptr
, (stinst_type
) atol (word
));
1367 add_to_definition (ptr
, call
);
1368 add_to_definition (ptr
, (stinst_type
) lookup_word (word
));
1371 string
= nextword (string
, &word
);
1373 add_to_definition (ptr
, 0);
1374 string
= nextword (string
, &word
);
1378 fprintf (stderr
, "syntax error at %s\n", string
- 1);
1386 *(long *) ((isp
[0])) = isp
[-1];
1395 isp
[0] = *(long *) (isp
[0]);
1428 write_buffer (tos
, stdout
);
1430 write_buffer (tos
, stderr
);
1432 fprintf (stderr
, "print: illegal print destination `%ld'\n", *isp
);
1449 r
= fread (buff
, 1, sizeof (buff
), file
);
1450 catbuf (str
, buff
, r
);
1455 catbuf (str
, buff
, 1);
1461 fprintf (stderr
, "usage: -[d|i|g] <file >file\n");
1465 /* There is no reliable way to declare exit. Sometimes it returns
1466 int, and sometimes it returns void. Sometimes it changes between
1467 OS releases. Trying to get it declared correctly in the hosts file
1468 is a pointless waste of time. */
1485 init_string (&buffer
);
1486 init_string (&pptr
);
1487 init_string (stack
+ 0);
1491 add_intrinsic ("push_text", push_text
);
1492 add_intrinsic ("!", bang
);
1493 add_intrinsic ("@", atsign
);
1494 add_intrinsic ("hello", hello
);
1495 add_intrinsic ("stdout", stdout_
);
1496 add_intrinsic ("stderr", stderr_
);
1497 add_intrinsic ("print", print
);
1498 add_intrinsic ("skip_past_newline", skip_past_newline
);
1499 add_intrinsic ("catstr", icatstr
);
1500 add_intrinsic ("copy_past_newline", icopy_past_newline
);
1501 add_intrinsic ("dup", other_dup
);
1502 add_intrinsic ("drop", drop
);
1503 add_intrinsic ("idrop", idrop
);
1504 add_intrinsic ("remchar", remchar
);
1505 add_intrinsic ("get_stuff_in_command", get_stuff_in_command
);
1506 add_intrinsic ("do_fancy_stuff", do_fancy_stuff
);
1507 add_intrinsic ("bulletize", bulletize
);
1508 add_intrinsic ("courierize", courierize
);
1509 /* If the following line gives an error, exit() is not declared in the
1510 ../hosts/foo.h file for this host. Fix it there, not here! */
1511 /* No, don't fix it anywhere; see comment on chew_exit--Ian Taylor. */
1512 add_intrinsic ("exit", chew_exit
);
1513 add_intrinsic ("swap", swap
);
1514 add_intrinsic ("outputdots", outputdots
);
1515 add_intrinsic ("paramstuff", paramstuff
);
1516 add_intrinsic ("maybecatstr", maybecatstr
);
1517 add_intrinsic ("translatecomments", translatecomments
);
1518 add_intrinsic ("kill_bogus_lines", kill_bogus_lines
);
1519 add_intrinsic ("indent", indent
);
1520 add_intrinsic ("internalmode", internalmode
);
1521 add_intrinsic ("print_stack_level", print_stack_level
);
1522 add_intrinsic ("strip_trailing_newlines", strip_trailing_newlines
);
1524 /* Put a nl at the start. */
1525 catchar (&buffer
, '\n');
1527 read_in (&buffer
, stdin
);
1528 remove_noncomments (&buffer
, ptr
);
1529 for (i
= 1; i
< (unsigned int) ac
; i
++)
1531 if (av
[i
][0] == '-')
1533 if (av
[i
][1] == 'f')
1539 f
= fopen (av
[i
+ 1], "r");
1542 fprintf (stderr
, "Can't open the input file %s\n",
1551 else if (av
[i
][1] == 'i')
1553 internal_wanted
= 1;
1555 else if (av
[i
][1] == 'w')
1563 write_buffer (stack
+ 0, stdout
);
1566 fprintf (stderr
, "finishing with current stack level %ld\n",
1567 (long) (tos
- stack
));
This page took 0.062739 seconds and 4 git commands to generate.