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