PR linker/5099
[deliverable/binutils-gdb.git] / bfd / doc / chew.c
CommitLineData
252b5132 1/* chew
9ee6f9cc 2 Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998, 2000, 2001,
cd123cb7 3 2002, 2003, 2005, 2007
252b5132
RH
4 Free Software Foundation, Inc.
5 Contributed by steve chamberlain @cygnus
6
cd123cb7 7 This file is part of BFD, the Binary File Descriptor library.
252b5132 8
cd123cb7
NC
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
252b5132 13
cd123cb7
NC
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
252b5132 18
cd123cb7
NC
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
22 MA 02110-1301, USA. */
252b5132
RH
23
24/* Yet another way of extracting documentation from source.
25 No, I haven't finished it yet, but I hope you people like it better
26 than the old way
d70910e8 27
252b5132
RH
28 sac
29
30 Basically, this is a sort of string forth, maybe we should call it
31 struth?
32
33 You define new words thus:
34 : <newword> <oldwords> ;
35
36*/
37
38/* Primitives provided by the program:
39
40 Two stacks are provided, a string stack and an integer stack.
41
42 Internal state variables:
43 internal_wanted - indicates whether `-i' was passed
44 internal_mode - user-settable
45
46 Commands:
47 push_text
48 ! - pop top of integer stack for address, pop next for value; store
49 @ - treat value on integer stack as the address of an integer; push
50 that integer on the integer stack after popping the "address"
51 hello - print "hello\n" to stdout
52 stdout - put stdout marker on TOS
53 stderr - put stderr marker on TOS
54 print - print TOS-1 on TOS (eg: "hello\n" stdout print)
55 skip_past_newline
56 catstr - fn icatstr
57 copy_past_newline - append input, up to and including newline into TOS
58 dup - fn other_dup
59 drop - discard TOS
60 idrop - ditto
61 remchar - delete last character from TOS
62 get_stuff_in_command
63 do_fancy_stuff - translate <<foo>> to @code{foo} in TOS
64 bulletize - if "o" lines found, prepend @itemize @bullet to TOS
65 and @item to each "o" line; append @end itemize
66 courierize - put @example around . and | lines, translate {* *} { }
67 exit - fn chew_exit
68 swap
69 outputdots - strip out lines without leading dots
70 paramstuff - convert full declaration into "PARAMS" form if not already
71 maybecatstr - do catstr if internal_mode == internal_wanted, discard
72 value in any case
73 translatecomments - turn {* and *} into comment delimiters
74 kill_bogus_lines - get rid of extra newlines
75 indent
76 internalmode - pop from integer stack, set `internalmode' to that value
77 print_stack_level - print current stack depth to stderr
78 strip_trailing_newlines - go ahead, guess...
79 [quoted string] - push string onto string stack
80 [word starting with digit] - push atol(str) onto integer stack
81
82 A command must be all upper-case, and alone on a line.
83
84 Foo. */
85
f742faa6 86#include "ansidecl.h"
252b5132
RH
87#include <assert.h>
88#include <stdio.h>
89#include <ctype.h>
d4ad1cbf 90#include <stdlib.h>
99356e90 91#include <string.h>
252b5132
RH
92
93#define DEF_SIZE 5000
94#define STACK 50
95
96int internal_wanted;
97int internal_mode;
98
99int warning;
100
d70910e8 101/* Here is a string type ... */
252b5132 102
d70910e8 103typedef struct buffer
252b5132
RH
104{
105 char *ptr;
106 unsigned long write_idx;
107 unsigned long size;
108} string_type;
109
252b5132
RH
110#ifdef __STDC__
111static void init_string_with_size (string_type *, unsigned int);
112static void init_string (string_type *);
113static int find (string_type *, char *);
114static void write_buffer (string_type *, FILE *);
115static void delete_string (string_type *);
116static char *addr (string_type *, unsigned int);
117static char at (string_type *, unsigned int);
118static void catchar (string_type *, int);
119static void overwrite_string (string_type *, string_type *);
120static void catbuf (string_type *, char *, unsigned int);
121static void cattext (string_type *, char *);
122static void catstr (string_type *, string_type *);
123#endif
124
256d98af
KH
125static void
126init_string_with_size (buffer, size)
127 string_type *buffer;
128 unsigned int size;
252b5132 129{
d70910e8
KH
130 buffer->write_idx = 0;
131 buffer->size = size;
132 buffer->ptr = malloc (size);
252b5132
RH
133}
134
256d98af
KH
135static void
136init_string (buffer)
137 string_type *buffer;
252b5132 138{
d70910e8 139 init_string_with_size (buffer, DEF_SIZE);
252b5132
RH
140}
141
256d98af
KH
142static int
143find (str, what)
144 string_type *str;
145 char *what;
252b5132 146{
d70910e8
KH
147 unsigned int i;
148 char *p;
149 p = what;
150 for (i = 0; i < str->write_idx && *p; i++)
252b5132 151 {
d70910e8
KH
152 if (*p == str->ptr[i])
153 p++;
154 else
155 p = what;
252b5132 156 }
d70910e8 157 return (*p == 0);
252b5132
RH
158}
159
256d98af
KH
160static void
161write_buffer (buffer, f)
162 string_type *buffer;
163 FILE *f;
252b5132 164{
d70910e8 165 fwrite (buffer->ptr, buffer->write_idx, 1, f);
252b5132
RH
166}
167
256d98af
KH
168static void
169delete_string (buffer)
170 string_type *buffer;
252b5132 171{
d70910e8 172 free (buffer->ptr);
252b5132
RH
173}
174
256d98af
KH
175static char *
176addr (buffer, idx)
177 string_type *buffer;
178 unsigned int idx;
252b5132 179{
d70910e8 180 return buffer->ptr + idx;
252b5132
RH
181}
182
256d98af
KH
183static char
184at (buffer, pos)
185 string_type *buffer;
186 unsigned int pos;
252b5132 187{
d70910e8 188 if (pos >= buffer->write_idx)
252b5132
RH
189 return 0;
190 return buffer->ptr[pos];
191}
192
256d98af
KH
193static void
194catchar (buffer, ch)
195 string_type *buffer;
196 int ch;
252b5132 197{
d70910e8 198 if (buffer->write_idx == buffer->size)
252b5132 199 {
d70910e8
KH
200 buffer->size *= 2;
201 buffer->ptr = realloc (buffer->ptr, buffer->size);
252b5132
RH
202 }
203
d70910e8 204 buffer->ptr[buffer->write_idx++] = ch;
252b5132
RH
205}
206
256d98af
KH
207static void
208overwrite_string (dst, src)
209 string_type *dst;
210 string_type *src;
252b5132 211{
d70910e8
KH
212 free (dst->ptr);
213 dst->size = src->size;
214 dst->write_idx = src->write_idx;
215 dst->ptr = src->ptr;
252b5132
RH
216}
217
256d98af
KH
218static void
219catbuf (buffer, buf, len)
220 string_type *buffer;
221 char *buf;
222 unsigned int len;
252b5132
RH
223{
224 if (buffer->write_idx + len >= buffer->size)
225 {
226 while (buffer->write_idx + len >= buffer->size)
227 buffer->size *= 2;
228 buffer->ptr = realloc (buffer->ptr, buffer->size);
229 }
230 memcpy (buffer->ptr + buffer->write_idx, buf, len);
231 buffer->write_idx += len;
232}
233
256d98af
KH
234static void
235cattext (buffer, string)
236 string_type *buffer;
237 char *string;
252b5132
RH
238{
239 catbuf (buffer, string, (unsigned int) strlen (string));
240}
241
256d98af
KH
242static void
243catstr (dst, src)
244 string_type *dst;
245 string_type *src;
252b5132
RH
246{
247 catbuf (dst, src->ptr, src->write_idx);
248}
249
d70910e8 250static unsigned int
256d98af
KH
251skip_white_and_stars (src, idx)
252 string_type *src;
253 unsigned int idx;
252b5132
RH
254{
255 char c;
d70910e8 256 while ((c = at (src, idx)),
252b5132
RH
257 isspace ((unsigned char) c)
258 || (c == '*'
259 /* Don't skip past end-of-comment or star as first
260 character on its line. */
d70910e8
KH
261 && at (src, idx +1) != '/'
262 && at (src, idx -1) != '\n'))
252b5132
RH
263 idx++;
264 return idx;
265}
266
267/***********************************************************************/
268
252b5132
RH
269string_type stack[STACK];
270string_type *tos;
271
272unsigned int idx = 0; /* Pos in input buffer */
273string_type *ptr; /* and the buffer */
274typedef void (*stinst_type)();
275stinst_type *pc;
276stinst_type sstack[STACK];
277stinst_type *ssp = &sstack[0];
278long istack[STACK];
279long *isp = &istack[0];
280
281typedef int *word_type;
282
252b5132
RH
283struct dict_struct
284{
d70910e8
KH
285 char *word;
286 struct dict_struct *next;
287 stinst_type *code;
288 int code_length;
289 int code_end;
290 int var;
252b5132 291};
d70910e8 292
252b5132 293typedef struct dict_struct dict_type;
d70910e8 294
252b5132
RH
295static void
296die (msg)
297 char *msg;
298{
299 fprintf (stderr, "%s\n", msg);
300 exit (1);
301}
302
303static void
304check_range ()
305{
306 if (tos < stack)
307 die ("underflow in string stack");
308 if (tos >= stack + STACK)
309 die ("overflow in string stack");
310}
311
312static void
313icheck_range ()
314{
315 if (isp < istack)
316 die ("underflow in integer stack");
317 if (isp >= istack + STACK)
318 die ("overflow in integer stack");
319}
320
321#ifdef __STDC__
322static void exec (dict_type *);
323static void call (void);
324static void remchar (void), strip_trailing_newlines (void), push_number (void);
325static void push_text (void);
326static void remove_noncomments (string_type *, string_type *);
327static void print_stack_level (void);
328static void paramstuff (void), translatecomments (void);
329static void outputdots (void), courierize (void), bulletize (void);
330static void do_fancy_stuff (void);
331static int iscommand (string_type *, unsigned int);
332static int copy_past_newline (string_type *, unsigned int, string_type *);
333static void icopy_past_newline (void), kill_bogus_lines (void), indent (void);
334static void get_stuff_in_command (void), swap (void), other_dup (void);
335static void drop (void), idrop (void);
336static void icatstr (void), skip_past_newline (void), internalmode (void);
337static void maybecatstr (void);
338static char *nextword (char *, char **);
339dict_type *lookup_word (char *);
340static void perform (void);
341dict_type *newentry (char *);
342unsigned int add_to_definition (dict_type *, stinst_type);
343void add_intrinsic (char *, void (*)());
344void add_var (char *);
345void compile (char *);
346static void bang (void);
347static void atsign (void);
348static void hello (void);
349static void stdout_ (void);
350static void stderr_ (void);
351static void print (void);
352static void read_in (string_type *, FILE *);
353static void usage (void);
354static void chew_exit (void);
355#endif
356
256d98af
KH
357static void
358exec (word)
359 dict_type *word;
252b5132
RH
360{
361 pc = word->code;
d70910e8
KH
362 while (*pc)
363 (*pc) ();
252b5132 364}
d70910e8 365
9ee6f9cc
AM
366static void
367call ()
d70910e8
KH
368{
369 stinst_type *oldpc = pc;
370 dict_type *e;
371 e = (dict_type *) (pc[1]);
372 exec (e);
373 pc = oldpc + 2;
252b5132
RH
374}
375
9ee6f9cc
AM
376static void
377remchar ()
252b5132
RH
378{
379 if (tos->write_idx)
d70910e8 380 tos->write_idx--;
252b5132
RH
381 pc++;
382}
383
384static void
385strip_trailing_newlines ()
386{
387 while ((isspace ((unsigned char) at (tos, tos->write_idx - 1))
388 || at (tos, tos->write_idx - 1) == '\n')
389 && tos->write_idx > 0)
390 tos->write_idx--;
391 pc++;
392}
393
9ee6f9cc
AM
394static void
395push_number ()
252b5132 396{
d70910e8
KH
397 isp++;
398 icheck_range ();
399 pc++;
400 *isp = (long) (*pc);
401 pc++;
252b5132
RH
402}
403
9ee6f9cc
AM
404static void
405push_text ()
252b5132 406{
d70910e8
KH
407 tos++;
408 check_range ();
409 init_string (tos);
410 pc++;
411 cattext (tos, *((char **) pc));
412 pc++;
252b5132
RH
413}
414
252b5132
RH
415/* This function removes everything not inside comments starting on
416 the first char of the line from the string, also when copying
417 comments, removes blank space and leading *'s.
418 Blank lines are turned into one blank line. */
419
d70910e8
KH
420static void
421remove_noncomments (src, dst)
256d98af
KH
422 string_type *src;
423 string_type *dst;
252b5132 424{
d70910e8
KH
425 unsigned int idx = 0;
426
427 while (at (src, idx))
252b5132 428 {
d70910e8
KH
429 /* Now see if we have a comment at the start of the line. */
430 if (at (src, idx) == '\n'
431 && at (src, idx + 1) == '/'
432 && at (src, idx + 2) == '*')
252b5132 433 {
d70910e8
KH
434 idx += 3;
435
436 idx = skip_white_and_stars (src, idx);
437
438 /* Remove leading dot */
439 if (at (src, idx) == '.')
440 idx++;
441
442 /* Copy to the end of the line, or till the end of the
443 comment. */
444 while (at (src, idx))
252b5132 445 {
d70910e8 446 if (at (src, idx) == '\n')
252b5132 447 {
d70910e8
KH
448 /* end of line, echo and scrape of leading blanks */
449 if (at (src, idx + 1) == '\n')
450 catchar (dst, '\n');
451 catchar (dst, '\n');
452 idx++;
453 idx = skip_white_and_stars (src, idx);
252b5132 454 }
d70910e8 455 else if (at (src, idx) == '*' && at (src, idx + 1) == '/')
252b5132 456 {
d70910e8
KH
457 idx += 2;
458 cattext (dst, "\nENDDD\n");
459 break;
252b5132 460 }
d70910e8 461 else
252b5132 462 {
d70910e8
KH
463 catchar (dst, at (src, idx));
464 idx++;
252b5132
RH
465 }
466 }
467 }
d70910e8
KH
468 else
469 idx++;
252b5132
RH
470 }
471}
472
473static void
474print_stack_level ()
475{
476 fprintf (stderr, "current string stack depth = %d, ", tos - stack);
477 fprintf (stderr, "current integer stack depth = %d\n", isp - istack);
478 pc++;
479}
480
481/* turn:
482 foobar name(stuff);
483 into:
484 foobar
485 name PARAMS ((stuff));
486 and a blank line.
487 */
488
489static void
51240b8d 490paramstuff ()
252b5132 491{
d70910e8
KH
492 unsigned int openp;
493 unsigned int fname;
494 unsigned int idx;
10bfd974 495 unsigned int len;
d70910e8
KH
496 string_type out;
497 init_string (&out);
252b5132 498
c58b9523
AM
499#define NO_PARAMS 1
500
d70910e8 501 /* Make sure that it's not already param'd or proto'd. */
c58b9523
AM
502 if (NO_PARAMS
503 || find (tos, "PARAMS") || find (tos, "PROTO") || !find (tos, "("))
252b5132 504 {
d70910e8
KH
505 catstr (&out, tos);
506 }
507 else
508 {
509 /* Find the open paren. */
510 for (openp = 0; at (tos, openp) != '(' && at (tos, openp); openp++)
511 ;
512
513 fname = openp;
514 /* Step back to the fname. */
515 fname--;
516 while (fname && isspace ((unsigned char) at (tos, fname)))
517 fname--;
518 while (fname
519 && !isspace ((unsigned char) at (tos,fname))
520 && at (tos,fname) != '*')
252b5132 521 fname--;
d70910e8
KH
522
523 fname++;
524
10bfd974
KH
525 /* Output type, omitting trailing whitespace character(s), if
526 any. */
527 for (len = fname; 0 < len; len--)
252b5132 528 {
10bfd974 529 if (!isspace ((unsigned char) at (tos, len - 1)))
05c6581e 530 break;
252b5132 531 }
10bfd974
KH
532 for (idx = 0; idx < len; idx++)
533 catchar (&out, at (tos, idx));
252b5132 534
d70910e8
KH
535 cattext (&out, "\n"); /* Insert a newline between type and fnname */
536
10bfd974
KH
537 /* Output function name, omitting trailing whitespace
538 character(s), if any. */
539 for (len = openp; 0 < len; len--)
252b5132 540 {
10bfd974
KH
541 if (!isspace ((unsigned char) at (tos, len - 1)))
542 break;
252b5132 543 }
10bfd974
KH
544 for (idx = fname; idx < len; idx++)
545 catchar (&out, at (tos, idx));
252b5132 546
d70910e8 547 cattext (&out, " PARAMS (");
252b5132 548
10bfd974
KH
549 for (idx = openp; at (tos, idx) && at (tos, idx) != ';'; idx++)
550 catchar (&out, at (tos, idx));
551
d70910e8 552 cattext (&out, ");\n\n");
252b5132 553 }
d70910e8
KH
554 overwrite_string (tos, &out);
555 pc++;
252b5132 556
d70910e8 557}
252b5132
RH
558
559/* turn {*
560 and *} into comments */
561
9ee6f9cc
AM
562static void
563translatecomments ()
252b5132 564{
d70910e8
KH
565 unsigned int idx = 0;
566 string_type out;
567 init_string (&out);
568
569 while (at (tos, idx))
252b5132 570 {
d70910e8 571 if (at (tos, idx) == '{' && at (tos, idx + 1) == '*')
252b5132 572 {
d70910e8
KH
573 cattext (&out, "/*");
574 idx += 2;
252b5132 575 }
d70910e8 576 else if (at (tos, idx) == '*' && at (tos, idx + 1) == '}')
252b5132 577 {
d70910e8
KH
578 cattext (&out, "*/");
579 idx += 2;
252b5132 580 }
d70910e8 581 else
252b5132 582 {
d70910e8
KH
583 catchar (&out, at (tos, idx));
584 idx++;
252b5132
RH
585 }
586 }
587
d70910e8 588 overwrite_string (tos, &out);
252b5132 589
d70910e8 590 pc++;
252b5132
RH
591}
592
252b5132
RH
593/* Mod tos so that only lines with leading dots remain */
594static void
51240b8d 595outputdots ()
252b5132 596{
d70910e8
KH
597 unsigned int idx = 0;
598 string_type out;
599 init_string (&out);
600
601 while (at (tos, idx))
252b5132 602 {
d70910e8 603 if (at (tos, idx) == '\n' && at (tos, idx + 1) == '.')
252b5132
RH
604 {
605 char c;
606 idx += 2;
d70910e8
KH
607
608 while ((c = at (tos, idx)) && c != '\n')
252b5132 609 {
d70910e8 610 if (c == '{' && at (tos, idx + 1) == '*')
252b5132 611 {
d70910e8
KH
612 cattext (&out, "/*");
613 idx += 2;
252b5132 614 }
d70910e8 615 else if (c == '*' && at (tos, idx + 1) == '}')
252b5132 616 {
d70910e8
KH
617 cattext (&out, "*/");
618 idx += 2;
252b5132
RH
619 }
620 else
621 {
d70910e8
KH
622 catchar (&out, c);
623 idx++;
252b5132
RH
624 }
625 }
d70910e8 626 catchar (&out, '\n');
252b5132 627 }
d70910e8 628 else
252b5132 629 {
d70910e8 630 idx++;
252b5132 631 }
d70910e8 632 }
252b5132 633
d70910e8
KH
634 overwrite_string (tos, &out);
635 pc++;
252b5132
RH
636}
637
638/* Find lines starting with . and | and put example around them on tos */
9ee6f9cc
AM
639static void
640courierize ()
d70910e8
KH
641{
642 string_type out;
643 unsigned int idx = 0;
644 int command = 0;
645
646 init_string (&out);
647
648 while (at (tos, idx))
252b5132 649 {
d70910e8
KH
650 if (at (tos, idx) == '\n'
651 && (at (tos, idx +1 ) == '.'
652 || at (tos, idx + 1) == '|'))
252b5132 653 {
d70910e8
KH
654 cattext (&out, "\n@example\n");
655 do
252b5132 656 {
d70910e8
KH
657 idx += 2;
658
659 while (at (tos, idx) && at (tos, idx) != '\n')
252b5132 660 {
ba994a14
AM
661 if (command > 1)
662 {
663 /* We are inside {} parameters of some command;
664 Just pass through until matching brace. */
665 if (at (tos, idx) == '{')
666 ++command;
667 else if (at (tos, idx) == '}')
668 --command;
669 }
670 else if (command != 0)
671 {
672 if (at (tos, idx) == '{')
673 ++command;
674 else if (!islower ((unsigned char) at (tos, idx)))
675 --command;
676 }
677 else if (at (tos, idx) == '@'
678 && islower ((unsigned char) at (tos, idx + 1)))
679 {
680 ++command;
681 }
682 else if (at (tos, idx) == '{' && at (tos, idx + 1) == '*')
252b5132 683 {
d70910e8
KH
684 cattext (&out, "/*");
685 idx += 2;
ba994a14 686 continue;
252b5132 687 }
d70910e8 688 else if (at (tos, idx) == '*' && at (tos, idx + 1) == '}')
252b5132 689 {
d70910e8
KH
690 cattext (&out, "*/");
691 idx += 2;
ba994a14 692 continue;
252b5132 693 }
ba994a14
AM
694 else if (at (tos, idx) == '{'
695 || at (tos, idx) == '}')
252b5132 696 {
ba994a14 697 catchar (&out, '@');
252b5132 698 }
d70910e8 699
ba994a14
AM
700 catchar (&out, at (tos, idx));
701 idx++;
252b5132 702 }
d70910e8
KH
703 catchar (&out, '\n');
704 }
705 while (at (tos, idx) == '\n'
706 && ((at (tos, idx + 1) == '.')
707 || (at (tos, idx + 1) == '|')))
708 ;
709 cattext (&out, "@end example");
252b5132 710 }
d70910e8
KH
711 else
712 {
713 catchar (&out, at (tos, idx));
714 idx++;
252b5132 715 }
d70910e8 716 }
252b5132 717
d70910e8
KH
718 overwrite_string (tos, &out);
719 pc++;
252b5132
RH
720}
721
722/* Finds any lines starting with "o ", if there are any, then turns
723 on @itemize @bullet, and @items each of them. Then ends with @end
724 itemize, inplace at TOS*/
725
9ee6f9cc
AM
726static void
727bulletize ()
252b5132 728{
d70910e8
KH
729 unsigned int idx = 0;
730 int on = 0;
731 string_type out;
732 init_string (&out);
733
734 while (at (tos, idx))
735 {
736 if (at (tos, idx) == '@'
737 && at (tos, idx + 1) == '*')
252b5132 738 {
d70910e8
KH
739 cattext (&out, "*");
740 idx += 2;
252b5132 741 }
d70910e8
KH
742 else if (at (tos, idx) == '\n'
743 && at (tos, idx + 1) == 'o'
744 && isspace ((unsigned char) at (tos, idx + 2)))
745 {
746 if (!on)
252b5132 747 {
d70910e8
KH
748 cattext (&out, "\n@itemize @bullet\n");
749 on = 1;
750
252b5132 751 }
d70910e8
KH
752 cattext (&out, "\n@item\n");
753 idx += 3;
754 }
755 else
756 {
757 catchar (&out, at (tos, idx));
758 if (on && at (tos, idx) == '\n'
759 && at (tos, idx + 1) == '\n'
760 && at (tos, idx + 2) != 'o')
252b5132 761 {
d70910e8
KH
762 cattext (&out, "@end itemize");
763 on = 0;
252b5132 764 }
d70910e8
KH
765 idx++;
766
252b5132 767 }
d70910e8
KH
768 }
769 if (on)
252b5132 770 {
d70910e8
KH
771 cattext (&out, "@end itemize\n");
772 }
252b5132 773
d70910e8
KH
774 delete_string (tos);
775 *tos = out;
776 pc++;
252b5132
RH
777}
778
779/* Turn <<foo>> into @code{foo} in place at TOS*/
252b5132 780
9ee6f9cc
AM
781static void
782do_fancy_stuff ()
252b5132 783{
d70910e8
KH
784 unsigned int idx = 0;
785 string_type out;
786 init_string (&out);
787 while (at (tos, idx))
252b5132 788 {
d70910e8
KH
789 if (at (tos, idx) == '<'
790 && at (tos, idx + 1) == '<'
791 && !isspace ((unsigned char) at (tos, idx + 2)))
252b5132 792 {
d70910e8
KH
793 /* This qualifies as a << startup. */
794 idx += 2;
795 cattext (&out, "@code{");
796 while (at (tos, idx)
797 && at (tos, idx) != '>' )
252b5132 798 {
d70910e8
KH
799 catchar (&out, at (tos, idx));
800 idx++;
801
252b5132 802 }
d70910e8
KH
803 cattext (&out, "}");
804 idx += 2;
252b5132 805 }
d70910e8 806 else
252b5132 807 {
d70910e8
KH
808 catchar (&out, at (tos, idx));
809 idx++;
252b5132
RH
810 }
811 }
d70910e8
KH
812 delete_string (tos);
813 *tos = out;
814 pc++;
815
252b5132 816}
d70910e8
KH
817
818/* A command is all upper case,and alone on a line. */
819
820static int
256d98af
KH
821iscommand (ptr, idx)
822 string_type *ptr;
823 unsigned int idx;
252b5132 824{
d70910e8
KH
825 unsigned int len = 0;
826 while (at (ptr, idx))
827 {
828 if (isupper ((unsigned char) at (ptr, idx))
829 || at (ptr, idx) == ' ' || at (ptr, idx) == '_')
830 {
831 len++;
832 idx++;
252b5132 833 }
d70910e8
KH
834 else if (at (ptr, idx) == '\n')
835 {
836 if (len > 3)
837 return 1;
838 return 0;
839 }
840 else
841 return 0;
842 }
843 return 0;
252b5132
RH
844}
845
252b5132 846static int
256d98af
KH
847copy_past_newline (ptr, idx, dst)
848 string_type *ptr;
849 unsigned int idx;
850 string_type *dst;
252b5132 851{
d70910e8 852 int column = 0;
252b5132 853
d70910e8 854 while (at (ptr, idx) && at (ptr, idx) != '\n')
252b5132 855 {
d70910e8
KH
856 if (at (ptr, idx) == '\t')
857 {
858 /* Expand tabs. Neither makeinfo nor TeX can cope well with
859 them. */
860 do
861 catchar (dst, ' ');
862 while (++column & 7);
863 }
864 else
865 {
866 catchar (dst, at (ptr, idx));
867 column++;
868 }
869 idx++;
870
871 }
872 catchar (dst, at (ptr, idx));
873 idx++;
874 return idx;
252b5132
RH
875
876}
877
9ee6f9cc
AM
878static void
879icopy_past_newline ()
252b5132 880{
d70910e8
KH
881 tos++;
882 check_range ();
883 init_string (tos);
884 idx = copy_past_newline (ptr, idx, tos);
885 pc++;
252b5132
RH
886}
887
888/* indent
d70910e8 889 Take the string at the top of the stack, do some prettying. */
252b5132 890
9ee6f9cc
AM
891static void
892kill_bogus_lines ()
252b5132 893{
d70910e8
KH
894 int sl;
895
896 int idx = 0;
897 int c;
898 int dot = 0;
899
900 string_type out;
901 init_string (&out);
902 /* Drop leading nl. */
903 while (at (tos, idx) == '\n')
252b5132 904 {
d70910e8 905 idx++;
252b5132 906 }
d70910e8
KH
907 c = idx;
908
909 /* If the first char is a '.' prepend a newline so that it is
910 recognized properly later. */
911 if (at (tos, idx) == '.')
912 catchar (&out, '\n');
913
914 /* Find the last char. */
915 while (at (tos, idx))
252b5132 916 {
d70910e8 917 idx++;
252b5132 918 }
d70910e8
KH
919
920 /* Find the last non white before the nl. */
921 idx--;
922
923 while (idx && isspace ((unsigned char) at (tos, idx)))
252b5132 924 idx--;
d70910e8 925 idx++;
252b5132 926
d70910e8
KH
927 /* Copy buffer upto last char, but blank lines before and after
928 dots don't count. */
929 sl = 1;
930
931 while (c < idx)
252b5132 932 {
d70910e8
KH
933 if (at (tos, c) == '\n'
934 && at (tos, c + 1) == '\n'
935 && at (tos, c + 2) == '.')
252b5132 936 {
d70910e8
KH
937 /* Ignore two newlines before a dot. */
938 c++;
252b5132 939 }
d70910e8 940 else if (at (tos, c) == '.' && sl)
252b5132 941 {
d70910e8
KH
942 /* remember that this line started with a dot. */
943 dot = 2;
252b5132 944 }
d70910e8
KH
945 else if (at (tos, c) == '\n'
946 && at (tos, c + 1) == '\n'
947 && dot)
252b5132 948 {
d70910e8
KH
949 c++;
950 /* Ignore two newlines when last line was dot. */
252b5132
RH
951 }
952
d70910e8
KH
953 catchar (&out, at (tos, c));
954 if (at (tos, c) == '\n')
252b5132 955 {
d70910e8
KH
956 sl = 1;
957
958 if (dot == 2)
959 dot = 1;
960 else
961 dot = 0;
252b5132 962 }
d70910e8
KH
963 else
964 sl = 0;
965
966 c++;
252b5132
RH
967
968 }
d70910e8
KH
969
970 /* Append nl. */
971 catchar (&out, '\n');
972 pc++;
973 delete_string (tos);
974 *tos = out;
975
252b5132
RH
976}
977
9ee6f9cc
AM
978static void
979indent ()
252b5132 980{
d70910e8
KH
981 string_type out;
982 int tab = 0;
983 int idx = 0;
984 int ol = 0;
985 init_string (&out);
986 while (at (tos, idx))
987 {
988 switch (at (tos, idx))
989 {
990 case '\n':
991 cattext (&out, "\n");
992 idx++;
993 if (tab && at (tos, idx))
252b5132 994 {
d70910e8 995 cattext (&out, " ");
252b5132 996 }
d70910e8
KH
997 ol = 0;
998 break;
999 case '(':
1000 tab++;
1001 if (ol == 0)
1002 cattext (&out, " ");
1003 idx++;
1004 cattext (&out, "(");
1005 ol = 1;
1006 break;
1007 case ')':
1008 tab--;
1009 cattext (&out, ")");
1010 idx++;
1011 ol = 1;
1012
1013 break;
1014 default:
1015 catchar (&out, at (tos, idx));
1016 ol = 1;
1017
1018 idx++;
1019 break;
1020 }
1021 }
252b5132 1022
d70910e8
KH
1023 pc++;
1024 delete_string (tos);
1025 *tos = out;
252b5132
RH
1026
1027}
1028
9ee6f9cc
AM
1029static void
1030get_stuff_in_command ()
252b5132 1031{
d70910e8
KH
1032 tos++;
1033 check_range ();
1034 init_string (tos);
252b5132 1035
d70910e8
KH
1036 while (at (ptr, idx))
1037 {
1038 if (iscommand (ptr, idx))
1039 break;
1040 idx = copy_past_newline (ptr, idx, tos);
1041 }
1042 pc++;
252b5132
RH
1043}
1044
9ee6f9cc
AM
1045static void
1046swap ()
252b5132 1047{
d70910e8
KH
1048 string_type t;
1049
1050 t = tos[0];
1051 tos[0] = tos[-1];
1052 tos[-1] = t;
1053 pc++;
252b5132
RH
1054}
1055
9ee6f9cc
AM
1056static void
1057other_dup ()
252b5132 1058{
d70910e8
KH
1059 tos++;
1060 check_range ();
1061 init_string (tos);
1062 catstr (tos, tos - 1);
1063 pc++;
252b5132
RH
1064}
1065
9ee6f9cc
AM
1066static void
1067drop ()
252b5132
RH
1068{
1069 tos--;
1070 check_range ();
1071 pc++;
1072}
1073
9ee6f9cc
AM
1074static void
1075idrop ()
252b5132
RH
1076{
1077 isp--;
1078 icheck_range ();
1079 pc++;
1080}
1081
9ee6f9cc
AM
1082static void
1083icatstr ()
252b5132 1084{
d70910e8
KH
1085 tos--;
1086 check_range ();
1087 catstr (tos, tos + 1);
1088 delete_string (tos + 1);
1089 pc++;
252b5132
RH
1090}
1091
9ee6f9cc
AM
1092static void
1093skip_past_newline ()
252b5132 1094{
d70910e8
KH
1095 while (at (ptr, idx)
1096 && at (ptr, idx) != '\n')
252b5132 1097 idx++;
d70910e8
KH
1098 idx++;
1099 pc++;
252b5132
RH
1100}
1101
9ee6f9cc
AM
1102static void
1103internalmode ()
252b5132 1104{
d70910e8
KH
1105 internal_mode = *(isp);
1106 isp--;
1107 icheck_range ();
1108 pc++;
252b5132
RH
1109}
1110
9ee6f9cc
AM
1111static void
1112maybecatstr ()
252b5132 1113{
d70910e8 1114 if (internal_wanted == internal_mode)
252b5132 1115 {
d70910e8 1116 catstr (tos - 1, tos);
252b5132 1117 }
d70910e8
KH
1118 delete_string (tos);
1119 tos--;
1120 check_range ();
1121 pc++;
252b5132
RH
1122}
1123
1124char *
256d98af
KH
1125nextword (string, word)
1126 char *string;
1127 char **word;
252b5132 1128{
d70910e8
KH
1129 char *word_start;
1130 int idx;
1131 char *dst;
1132 char *src;
1133
1134 int length = 0;
1135
1136 while (isspace ((unsigned char) *string) || *string == '-')
1137 {
1138 if (*string == '-')
252b5132 1139 {
d70910e8 1140 while (*string && *string != '\n')
252b5132 1141 string++;
d70910e8
KH
1142
1143 }
1144 else
1145 {
1146 string++;
252b5132
RH
1147 }
1148 }
d70910e8
KH
1149 if (!*string)
1150 return 0;
252b5132 1151
d70910e8
KH
1152 word_start = string;
1153 if (*string == '"')
1154 {
1155 do
1156 {
1157 string++;
1158 length++;
1159 if (*string == '\\')
252b5132 1160 {
d70910e8
KH
1161 string += 2;
1162 length += 2;
252b5132 1163 }
d70910e8
KH
1164 }
1165 while (*string != '"');
252b5132 1166 }
d70910e8
KH
1167 else
1168 {
1169 while (!isspace ((unsigned char) *string))
1170 {
1171 string++;
1172 length++;
252b5132 1173
d70910e8
KH
1174 }
1175 }
252b5132 1176
d70910e8 1177 *word = malloc (length + 1);
252b5132 1178
d70910e8
KH
1179 dst = *word;
1180 src = word_start;
252b5132 1181
d70910e8
KH
1182 for (idx = 0; idx < length; idx++)
1183 {
1184 if (src[idx] == '\\')
1185 switch (src[idx + 1])
1186 {
1187 case 'n':
1188 *dst++ = '\n';
1189 idx++;
1190 break;
1191 case '"':
1192 case '\\':
1193 *dst++ = src[idx + 1];
1194 idx++;
1195 break;
1196 default:
1197 *dst++ = '\\';
1198 break;
1199 }
1200 else
1201 *dst++ = src[idx];
1202 }
1203 *dst++ = 0;
252b5132 1204
d70910e8
KH
1205 if (*string)
1206 return string + 1;
1207 else
1208 return 0;
252b5132 1209}
d70910e8 1210
252b5132 1211dict_type *root;
d70910e8 1212
252b5132 1213dict_type *
256d98af
KH
1214lookup_word (word)
1215 char *word;
252b5132
RH
1216{
1217 dict_type *ptr = root;
d70910e8
KH
1218 while (ptr)
1219 {
1220 if (strcmp (ptr->word, word) == 0)
1221 return ptr;
252b5132 1222 ptr = ptr->next;
252b5132
RH
1223 }
1224 if (warning)
d70910e8 1225 fprintf (stderr, "Can't find %s\n", word);
252b5132 1226 return 0;
252b5132
RH
1227}
1228
256d98af 1229static void
51240b8d 1230perform ()
252b5132
RH
1231{
1232 tos = stack;
252b5132 1233
d70910e8
KH
1234 while (at (ptr, idx))
1235 {
1236 /* It's worth looking through the command list. */
1237 if (iscommand (ptr, idx))
1238 {
1239 char *next;
1240 dict_type *word;
252b5132 1241
d70910e8 1242 (void) nextword (addr (ptr, idx), &next);
252b5132 1243
d70910e8 1244 word = lookup_word (next);
252b5132 1245
d70910e8
KH
1246 if (word)
1247 {
1248 exec (word);
1249 }
1250 else
1251 {
1252 if (warning)
1253 fprintf (stderr, "warning, %s is not recognised\n", next);
1254 skip_past_newline ();
1255 }
252b5132 1256
252b5132 1257 }
d70910e8
KH
1258 else
1259 skip_past_newline ();
252b5132
RH
1260 }
1261}
1262
1263dict_type *
256d98af
KH
1264newentry (word)
1265 char *word;
252b5132 1266{
d70910e8
KH
1267 dict_type *new = (dict_type *) malloc (sizeof (dict_type));
1268 new->word = word;
1269 new->next = root;
1270 root = new;
1271 new->code = (stinst_type *) malloc (sizeof (stinst_type));
1272 new->code_length = 1;
1273 new->code_end = 0;
1274 return new;
252b5132
RH
1275}
1276
252b5132 1277unsigned int
256d98af
KH
1278add_to_definition (entry, word)
1279 dict_type *entry;
1280 stinst_type word;
252b5132 1281{
d70910e8 1282 if (entry->code_end == entry->code_length)
252b5132 1283 {
d70910e8
KH
1284 entry->code_length += 2;
1285 entry->code =
1286 (stinst_type *) realloc ((char *) (entry->code),
1287 entry->code_length * sizeof (word_type));
252b5132 1288 }
d70910e8 1289 entry->code[entry->code_end] = word;
252b5132 1290
d70910e8
KH
1291 return entry->code_end++;
1292}
252b5132
RH
1293
1294void
256d98af
KH
1295add_intrinsic (name, func)
1296 char *name;
d70910e8 1297 void (*func) ();
252b5132 1298{
d70910e8
KH
1299 dict_type *new = newentry (name);
1300 add_to_definition (new, func);
1301 add_to_definition (new, 0);
252b5132
RH
1302}
1303
1304void
256d98af
KH
1305add_var (name)
1306 char *name;
252b5132 1307{
d70910e8
KH
1308 dict_type *new = newentry (name);
1309 add_to_definition (new, push_number);
1310 add_to_definition (new, (stinst_type) (&(new->var)));
1311 add_to_definition (new, 0);
252b5132
RH
1312}
1313
d70910e8 1314void
256d98af
KH
1315compile (string)
1316 char *string;
252b5132 1317{
d70910e8
KH
1318 /* Add words to the dictionary. */
1319 char *word;
1320 string = nextword (string, &word);
1321 while (string && *string && word[0])
252b5132 1322 {
d70910e8 1323 if (strcmp (word, "var") == 0)
252b5132 1324 {
d70910e8
KH
1325 string = nextword (string, &word);
1326
1327 add_var (word);
1328 string = nextword (string, &word);
252b5132 1329 }
d70910e8 1330 else if (word[0] == ':')
252b5132 1331 {
d70910e8
KH
1332 dict_type *ptr;
1333 /* Compile a word and add to dictionary. */
1334 string = nextword (string, &word);
1335
1336 ptr = newentry (word);
1337 string = nextword (string, &word);
1338 while (word[0] != ';')
252b5132 1339 {
d70910e8
KH
1340 switch (word[0])
1341 {
1342 case '"':
1343 /* got a string, embed magic push string
1344 function */
1345 add_to_definition (ptr, push_text);
1346 add_to_definition (ptr, (stinst_type) (word + 1));
1347 break;
1348 case '0':
1349 case '1':
1350 case '2':
1351 case '3':
1352 case '4':
1353 case '5':
1354 case '6':
1355 case '7':
1356 case '8':
1357 case '9':
1358 /* Got a number, embedd the magic push number
1359 function */
1360 add_to_definition (ptr, push_number);
1361 add_to_definition (ptr, (stinst_type) atol (word));
1362 break;
1363 default:
1364 add_to_definition (ptr, call);
1365 add_to_definition (ptr, (stinst_type) lookup_word (word));
1366 }
1367
1368 string = nextword (string, &word);
252b5132 1369 }
d70910e8
KH
1370 add_to_definition (ptr, 0);
1371 string = nextword (string, &word);
252b5132 1372 }
d70910e8 1373 else
252b5132 1374 {
d70910e8
KH
1375 fprintf (stderr, "syntax error at %s\n", string - 1);
1376 }
252b5132 1377 }
252b5132
RH
1378}
1379
256d98af 1380static void
51240b8d 1381bang ()
252b5132 1382{
d70910e8
KH
1383 *(long *) ((isp[0])) = isp[-1];
1384 isp -= 2;
252b5132
RH
1385 icheck_range ();
1386 pc++;
1387}
1388
9ee6f9cc
AM
1389static void
1390atsign ()
252b5132 1391{
d70910e8
KH
1392 isp[0] = *(long *) (isp[0]);
1393 pc++;
252b5132
RH
1394}
1395
9ee6f9cc
AM
1396static void
1397hello ()
252b5132 1398{
d70910e8
KH
1399 printf ("hello\n");
1400 pc++;
252b5132
RH
1401}
1402
9ee6f9cc
AM
1403static void
1404stdout_ ()
252b5132
RH
1405{
1406 isp++;
1407 icheck_range ();
1408 *isp = 1;
1409 pc++;
1410}
1411
9ee6f9cc
AM
1412static void
1413stderr_ ()
252b5132
RH
1414{
1415 isp++;
1416 icheck_range ();
1417 *isp = 2;
1418 pc++;
1419}
1420
9ee6f9cc
AM
1421static void
1422print ()
252b5132
RH
1423{
1424 if (*isp == 1)
1425 write_buffer (tos, stdout);
1426 else if (*isp == 2)
1427 write_buffer (tos, stderr);
1428 else
1429 fprintf (stderr, "print: illegal print destination `%ld'\n", *isp);
1430 isp--;
1431 tos--;
1432 icheck_range ();
1433 check_range ();
1434 pc++;
1435}
1436
256d98af
KH
1437static void
1438read_in (str, file)
d70910e8
KH
1439 string_type *str;
1440 FILE *file;
252b5132 1441{
d70910e8
KH
1442 char buff[10000];
1443 unsigned int r;
1444 do
252b5132 1445 {
d70910e8
KH
1446 r = fread (buff, 1, sizeof (buff), file);
1447 catbuf (str, buff, r);
252b5132 1448 }
d70910e8
KH
1449 while (r);
1450 buff[0] = 0;
252b5132 1451
d70910e8
KH
1452 catbuf (str, buff, 1);
1453}
252b5132 1454
256d98af 1455static void
51240b8d 1456usage ()
252b5132 1457{
d70910e8
KH
1458 fprintf (stderr, "usage: -[d|i|g] <file >file\n");
1459 exit (33);
252b5132
RH
1460}
1461
1462/* There is no reliable way to declare exit. Sometimes it returns
1463 int, and sometimes it returns void. Sometimes it changes between
1464 OS releases. Trying to get it declared correctly in the hosts file
1465 is a pointless waste of time. */
1466
1467static void
1468chew_exit ()
1469{
1470 exit (0);
1471}
1472
256d98af 1473int
d70910e8 1474main (ac, av)
256d98af
KH
1475 int ac;
1476 char *av[];
252b5132
RH
1477{
1478 unsigned int i;
1479 string_type buffer;
1480 string_type pptr;
1481
d70910e8
KH
1482 init_string (&buffer);
1483 init_string (&pptr);
1484 init_string (stack + 0);
1485 tos = stack + 1;
252b5132 1486 ptr = &pptr;
d70910e8
KH
1487
1488 add_intrinsic ("push_text", push_text);
1489 add_intrinsic ("!", bang);
1490 add_intrinsic ("@", atsign);
1491 add_intrinsic ("hello", hello);
1492 add_intrinsic ("stdout", stdout_);
1493 add_intrinsic ("stderr", stderr_);
1494 add_intrinsic ("print", print);
1495 add_intrinsic ("skip_past_newline", skip_past_newline);
1496 add_intrinsic ("catstr", icatstr);
1497 add_intrinsic ("copy_past_newline", icopy_past_newline);
1498 add_intrinsic ("dup", other_dup);
1499 add_intrinsic ("drop", drop);
1500 add_intrinsic ("idrop", idrop);
1501 add_intrinsic ("remchar", remchar);
1502 add_intrinsic ("get_stuff_in_command", get_stuff_in_command);
1503 add_intrinsic ("do_fancy_stuff", do_fancy_stuff);
1504 add_intrinsic ("bulletize", bulletize);
1505 add_intrinsic ("courierize", courierize);
252b5132
RH
1506 /* If the following line gives an error, exit() is not declared in the
1507 ../hosts/foo.h file for this host. Fix it there, not here! */
1508 /* No, don't fix it anywhere; see comment on chew_exit--Ian Taylor. */
d70910e8
KH
1509 add_intrinsic ("exit", chew_exit);
1510 add_intrinsic ("swap", swap);
1511 add_intrinsic ("outputdots", outputdots);
1512 add_intrinsic ("paramstuff", paramstuff);
1513 add_intrinsic ("maybecatstr", maybecatstr);
1514 add_intrinsic ("translatecomments", translatecomments);
1515 add_intrinsic ("kill_bogus_lines", kill_bogus_lines);
1516 add_intrinsic ("indent", indent);
1517 add_intrinsic ("internalmode", internalmode);
1518 add_intrinsic ("print_stack_level", print_stack_level);
1519 add_intrinsic ("strip_trailing_newlines", strip_trailing_newlines);
1520
1521 /* Put a nl at the start. */
1522 catchar (&buffer, '\n');
1523
1524 read_in (&buffer, stdin);
1525 remove_noncomments (&buffer, ptr);
1526 for (i = 1; i < (unsigned int) ac; i++)
252b5132 1527 {
d70910e8 1528 if (av[i][0] == '-')
252b5132 1529 {
d70910e8
KH
1530 if (av[i][1] == 'f')
1531 {
1532 string_type b;
1533 FILE *f;
1534 init_string (&b);
252b5132 1535
d70910e8
KH
1536 f = fopen (av[i + 1], "r");
1537 if (!f)
1538 {
1539 fprintf (stderr, "Can't open the input file %s\n",
1540 av[i + 1]);
1541 return 33;
1542 }
1543
1544 read_in (&b, f);
1545 compile (b.ptr);
1546 perform ();
1547 }
1548 else if (av[i][1] == 'i')
1549 {
1550 internal_wanted = 1;
1551 }
1552 else if (av[i][1] == 'w')
1553 {
1554 warning = 1;
1555 }
1556 else
1557 usage ();
1558 }
252b5132 1559 }
d70910e8 1560 write_buffer (stack + 0, stdout);
252b5132
RH
1561 if (tos != stack)
1562 {
d70910e8
KH
1563 fprintf (stderr, "finishing with current stack level %d\n",
1564 tos - stack);
252b5132
RH
1565 return 1;
1566 }
1567 return 0;
1568}
This page took 0.430372 seconds and 4 git commands to generate.