2002-01-30 Daniel Jacobowitz <drow@mvista.com>
[deliverable/binutils-gdb.git] / bfd / doc / chew.c
CommitLineData
252b5132 1/* chew
7898deda 2 Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998, 2000, 2001
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;
10bfd974 490 unsigned int len;
d70910e8
KH
491 string_type out;
492 init_string (&out);
252b5132 493
d70910e8
KH
494 /* Make sure that it's not already param'd or proto'd. */
495 if (find (tos, "PARAMS") || find (tos, "PROTO") || !find (tos, "("))
252b5132 496 {
d70910e8
KH
497 catstr (&out, tos);
498 }
499 else
500 {
501 /* Find the open paren. */
502 for (openp = 0; at (tos, openp) != '(' && at (tos, openp); openp++)
503 ;
504
505 fname = openp;
506 /* Step back to the fname. */
507 fname--;
508 while (fname && isspace ((unsigned char) at (tos, fname)))
509 fname--;
510 while (fname
511 && !isspace ((unsigned char) at (tos,fname))
512 && at (tos,fname) != '*')
252b5132 513 fname--;
d70910e8
KH
514
515 fname++;
516
10bfd974
KH
517 /* Output type, omitting trailing whitespace character(s), if
518 any. */
519 for (len = fname; 0 < len; len--)
252b5132 520 {
10bfd974 521 if (!isspace ((unsigned char) at (tos, len - 1)))
05c6581e 522 break;
252b5132 523 }
10bfd974
KH
524 for (idx = 0; idx < len; idx++)
525 catchar (&out, at (tos, idx));
252b5132 526
d70910e8
KH
527 cattext (&out, "\n"); /* Insert a newline between type and fnname */
528
10bfd974
KH
529 /* Output function name, omitting trailing whitespace
530 character(s), if any. */
531 for (len = openp; 0 < len; len--)
252b5132 532 {
10bfd974
KH
533 if (!isspace ((unsigned char) at (tos, len - 1)))
534 break;
252b5132 535 }
10bfd974
KH
536 for (idx = fname; idx < len; idx++)
537 catchar (&out, at (tos, idx));
252b5132 538
d70910e8 539 cattext (&out, " PARAMS (");
252b5132 540
10bfd974
KH
541 for (idx = openp; at (tos, idx) && at (tos, idx) != ';'; idx++)
542 catchar (&out, at (tos, idx));
543
d70910e8 544 cattext (&out, ");\n\n");
252b5132 545 }
d70910e8
KH
546 overwrite_string (tos, &out);
547 pc++;
252b5132 548
d70910e8 549}
252b5132
RH
550
551/* turn {*
552 and *} into comments */
553
d70910e8 554WORD (translatecomments)
252b5132 555{
d70910e8
KH
556 unsigned int idx = 0;
557 string_type out;
558 init_string (&out);
559
560 while (at (tos, idx))
252b5132 561 {
d70910e8 562 if (at (tos, idx) == '{' && at (tos, idx + 1) == '*')
252b5132 563 {
d70910e8
KH
564 cattext (&out, "/*");
565 idx += 2;
252b5132 566 }
d70910e8 567 else if (at (tos, idx) == '*' && at (tos, idx + 1) == '}')
252b5132 568 {
d70910e8
KH
569 cattext (&out, "*/");
570 idx += 2;
252b5132 571 }
d70910e8 572 else
252b5132 573 {
d70910e8
KH
574 catchar (&out, at (tos, idx));
575 idx++;
252b5132
RH
576 }
577 }
578
d70910e8 579 overwrite_string (tos, &out);
252b5132 580
d70910e8 581 pc++;
252b5132
RH
582}
583
584#if 0
585
586/* This is not currently used. */
587
588/* turn everything not starting with a . into a comment */
589
d70910e8 590WORD (manglecomments)
252b5132 591{
d70910e8
KH
592 unsigned int idx = 0;
593 string_type out;
594 init_string (&out);
595
596 while (at (tos, idx))
252b5132 597 {
d70910e8 598 if (at (tos, idx) == '\n' && at (tos, idx + 1) == '*')
252b5132 599 {
d70910e8
KH
600 cattext (&out, " /*");
601 idx += 2;
252b5132 602 }
d70910e8 603 else if (at (tos, idx) == '*' && at (tos, idx + 1) == '}')
252b5132 604 {
d70910e8
KH
605 cattext (&out, "*/");
606 idx += 2;
252b5132 607 }
d70910e8 608 else
252b5132 609 {
d70910e8
KH
610 catchar (&out, at (tos, idx));
611 idx++;
252b5132
RH
612 }
613 }
614
d70910e8 615 overwrite_string (tos, &out);
252b5132 616
d70910e8 617 pc++;
252b5132
RH
618}
619
620#endif
621
622/* Mod tos so that only lines with leading dots remain */
623static void
256d98af 624outputdots (void)
252b5132 625{
d70910e8
KH
626 unsigned int idx = 0;
627 string_type out;
628 init_string (&out);
629
630 while (at (tos, idx))
252b5132 631 {
d70910e8 632 if (at (tos, idx) == '\n' && at (tos, idx + 1) == '.')
252b5132
RH
633 {
634 char c;
635 idx += 2;
d70910e8
KH
636
637 while ((c = at (tos, idx)) && c != '\n')
252b5132 638 {
d70910e8 639 if (c == '{' && at (tos, idx + 1) == '*')
252b5132 640 {
d70910e8
KH
641 cattext (&out, "/*");
642 idx += 2;
252b5132 643 }
d70910e8 644 else if (c == '*' && at (tos, idx + 1) == '}')
252b5132 645 {
d70910e8
KH
646 cattext (&out, "*/");
647 idx += 2;
252b5132
RH
648 }
649 else
650 {
d70910e8
KH
651 catchar (&out, c);
652 idx++;
252b5132
RH
653 }
654 }
d70910e8 655 catchar (&out, '\n');
252b5132 656 }
d70910e8 657 else
252b5132 658 {
d70910e8 659 idx++;
252b5132 660 }
d70910e8 661 }
252b5132 662
d70910e8
KH
663 overwrite_string (tos, &out);
664 pc++;
252b5132
RH
665}
666
667/* Find lines starting with . and | and put example around them on tos */
d70910e8
KH
668WORD (courierize)
669{
670 string_type out;
671 unsigned int idx = 0;
672 int command = 0;
673
674 init_string (&out);
675
676 while (at (tos, idx))
252b5132 677 {
d70910e8
KH
678 if (at (tos, idx) == '\n'
679 && (at (tos, idx +1 ) == '.'
680 || at (tos, idx + 1) == '|'))
252b5132 681 {
d70910e8
KH
682 cattext (&out, "\n@example\n");
683 do
252b5132 684 {
d70910e8
KH
685 idx += 2;
686
687 while (at (tos, idx) && at (tos, idx) != '\n')
252b5132 688 {
d70910e8 689 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) == '*' && at (tos, idx + 1) == '}')
252b5132 695 {
d70910e8
KH
696 cattext (&out, "*/");
697 idx += 2;
252b5132 698 }
d70910e8 699 else if (at (tos, idx) == '{' && !command)
252b5132 700 {
d70910e8
KH
701 cattext (&out, "@{");
702 idx++;
252b5132 703 }
d70910e8 704 else if (at (tos, idx) == '}' && !command)
252b5132 705 {
d70910e8
KH
706 cattext (&out, "@}");
707 idx++;
252b5132 708 }
d70910e8 709 else
252b5132 710 {
d70910e8
KH
711 if (at (tos, idx) == '@')
712 command = 1;
713 else if (isspace ((unsigned char) at (tos, idx))
714 || at (tos, idx) == '}')
715 command = 0;
716 catchar (&out, at (tos, idx));
717 idx++;
252b5132 718 }
d70910e8 719
252b5132 720 }
d70910e8
KH
721 catchar (&out, '\n');
722 }
723 while (at (tos, idx) == '\n'
724 && ((at (tos, idx + 1) == '.')
725 || (at (tos, idx + 1) == '|')))
726 ;
727 cattext (&out, "@end example");
252b5132 728 }
d70910e8
KH
729 else
730 {
731 catchar (&out, at (tos, idx));
732 idx++;
252b5132 733 }
d70910e8 734 }
252b5132 735
d70910e8
KH
736 overwrite_string (tos, &out);
737 pc++;
252b5132
RH
738}
739
740/* Finds any lines starting with "o ", if there are any, then turns
741 on @itemize @bullet, and @items each of them. Then ends with @end
742 itemize, inplace at TOS*/
743
d70910e8 744WORD (bulletize)
252b5132 745{
d70910e8
KH
746 unsigned int idx = 0;
747 int on = 0;
748 string_type out;
749 init_string (&out);
750
751 while (at (tos, idx))
752 {
753 if (at (tos, idx) == '@'
754 && at (tos, idx + 1) == '*')
252b5132 755 {
d70910e8
KH
756 cattext (&out, "*");
757 idx += 2;
252b5132 758 }
d70910e8
KH
759 else if (at (tos, idx) == '\n'
760 && at (tos, idx + 1) == 'o'
761 && isspace ((unsigned char) at (tos, idx + 2)))
762 {
763 if (!on)
252b5132 764 {
d70910e8
KH
765 cattext (&out, "\n@itemize @bullet\n");
766 on = 1;
767
252b5132 768 }
d70910e8
KH
769 cattext (&out, "\n@item\n");
770 idx += 3;
771 }
772 else
773 {
774 catchar (&out, at (tos, idx));
775 if (on && at (tos, idx) == '\n'
776 && at (tos, idx + 1) == '\n'
777 && at (tos, idx + 2) != 'o')
252b5132 778 {
d70910e8
KH
779 cattext (&out, "@end itemize");
780 on = 0;
252b5132 781 }
d70910e8
KH
782 idx++;
783
252b5132 784 }
d70910e8
KH
785 }
786 if (on)
252b5132 787 {
d70910e8
KH
788 cattext (&out, "@end itemize\n");
789 }
252b5132 790
d70910e8
KH
791 delete_string (tos);
792 *tos = out;
793 pc++;
252b5132
RH
794}
795
796/* Turn <<foo>> into @code{foo} in place at TOS*/
252b5132 797
d70910e8 798WORD (do_fancy_stuff)
252b5132 799{
d70910e8
KH
800 unsigned int idx = 0;
801 string_type out;
802 init_string (&out);
803 while (at (tos, idx))
252b5132 804 {
d70910e8
KH
805 if (at (tos, idx) == '<'
806 && at (tos, idx + 1) == '<'
807 && !isspace ((unsigned char) at (tos, idx + 2)))
252b5132 808 {
d70910e8
KH
809 /* This qualifies as a << startup. */
810 idx += 2;
811 cattext (&out, "@code{");
812 while (at (tos, idx)
813 && at (tos, idx) != '>' )
252b5132 814 {
d70910e8
KH
815 catchar (&out, at (tos, idx));
816 idx++;
817
252b5132 818 }
d70910e8
KH
819 cattext (&out, "}");
820 idx += 2;
252b5132 821 }
d70910e8 822 else
252b5132 823 {
d70910e8
KH
824 catchar (&out, at (tos, idx));
825 idx++;
252b5132
RH
826 }
827 }
d70910e8
KH
828 delete_string (tos);
829 *tos = out;
830 pc++;
831
252b5132 832}
d70910e8
KH
833
834/* A command is all upper case,and alone on a line. */
835
836static int
256d98af
KH
837iscommand (ptr, idx)
838 string_type *ptr;
839 unsigned int idx;
252b5132 840{
d70910e8
KH
841 unsigned int len = 0;
842 while (at (ptr, idx))
843 {
844 if (isupper ((unsigned char) at (ptr, idx))
845 || at (ptr, idx) == ' ' || at (ptr, idx) == '_')
846 {
847 len++;
848 idx++;
252b5132 849 }
d70910e8
KH
850 else if (at (ptr, idx) == '\n')
851 {
852 if (len > 3)
853 return 1;
854 return 0;
855 }
856 else
857 return 0;
858 }
859 return 0;
252b5132
RH
860}
861
252b5132 862static int
256d98af
KH
863copy_past_newline (ptr, idx, dst)
864 string_type *ptr;
865 unsigned int idx;
866 string_type *dst;
252b5132 867{
d70910e8 868 int column = 0;
252b5132 869
d70910e8 870 while (at (ptr, idx) && at (ptr, idx) != '\n')
252b5132 871 {
d70910e8
KH
872 if (at (ptr, idx) == '\t')
873 {
874 /* Expand tabs. Neither makeinfo nor TeX can cope well with
875 them. */
876 do
877 catchar (dst, ' ');
878 while (++column & 7);
879 }
880 else
881 {
882 catchar (dst, at (ptr, idx));
883 column++;
884 }
885 idx++;
886
887 }
888 catchar (dst, at (ptr, idx));
889 idx++;
890 return idx;
252b5132
RH
891
892}
893
d70910e8 894WORD (icopy_past_newline)
252b5132 895{
d70910e8
KH
896 tos++;
897 check_range ();
898 init_string (tos);
899 idx = copy_past_newline (ptr, idx, tos);
900 pc++;
252b5132
RH
901}
902
903/* indent
d70910e8 904 Take the string at the top of the stack, do some prettying. */
252b5132 905
d70910e8 906WORD (kill_bogus_lines)
252b5132 907{
d70910e8
KH
908 int sl;
909
910 int idx = 0;
911 int c;
912 int dot = 0;
913
914 string_type out;
915 init_string (&out);
916 /* Drop leading nl. */
917 while (at (tos, idx) == '\n')
252b5132 918 {
d70910e8 919 idx++;
252b5132 920 }
d70910e8
KH
921 c = idx;
922
923 /* If the first char is a '.' prepend a newline so that it is
924 recognized properly later. */
925 if (at (tos, idx) == '.')
926 catchar (&out, '\n');
927
928 /* Find the last char. */
929 while (at (tos, idx))
252b5132 930 {
d70910e8 931 idx++;
252b5132 932 }
d70910e8
KH
933
934 /* Find the last non white before the nl. */
935 idx--;
936
937 while (idx && isspace ((unsigned char) at (tos, idx)))
252b5132 938 idx--;
d70910e8 939 idx++;
252b5132 940
d70910e8
KH
941 /* Copy buffer upto last char, but blank lines before and after
942 dots don't count. */
943 sl = 1;
944
945 while (c < idx)
252b5132 946 {
d70910e8
KH
947 if (at (tos, c) == '\n'
948 && at (tos, c + 1) == '\n'
949 && at (tos, c + 2) == '.')
252b5132 950 {
d70910e8
KH
951 /* Ignore two newlines before a dot. */
952 c++;
252b5132 953 }
d70910e8 954 else if (at (tos, c) == '.' && sl)
252b5132 955 {
d70910e8
KH
956 /* remember that this line started with a dot. */
957 dot = 2;
252b5132 958 }
d70910e8
KH
959 else if (at (tos, c) == '\n'
960 && at (tos, c + 1) == '\n'
961 && dot)
252b5132 962 {
d70910e8
KH
963 c++;
964 /* Ignore two newlines when last line was dot. */
252b5132
RH
965 }
966
d70910e8
KH
967 catchar (&out, at (tos, c));
968 if (at (tos, c) == '\n')
252b5132 969 {
d70910e8
KH
970 sl = 1;
971
972 if (dot == 2)
973 dot = 1;
974 else
975 dot = 0;
252b5132 976 }
d70910e8
KH
977 else
978 sl = 0;
979
980 c++;
252b5132
RH
981
982 }
d70910e8
KH
983
984 /* Append nl. */
985 catchar (&out, '\n');
986 pc++;
987 delete_string (tos);
988 *tos = out;
989
252b5132
RH
990}
991
d70910e8 992WORD (indent)
252b5132 993{
d70910e8
KH
994 string_type out;
995 int tab = 0;
996 int idx = 0;
997 int ol = 0;
998 init_string (&out);
999 while (at (tos, idx))
1000 {
1001 switch (at (tos, idx))
1002 {
1003 case '\n':
1004 cattext (&out, "\n");
1005 idx++;
1006 if (tab && at (tos, idx))
252b5132 1007 {
d70910e8 1008 cattext (&out, " ");
252b5132 1009 }
d70910e8
KH
1010 ol = 0;
1011 break;
1012 case '(':
1013 tab++;
1014 if (ol == 0)
1015 cattext (&out, " ");
1016 idx++;
1017 cattext (&out, "(");
1018 ol = 1;
1019 break;
1020 case ')':
1021 tab--;
1022 cattext (&out, ")");
1023 idx++;
1024 ol = 1;
1025
1026 break;
1027 default:
1028 catchar (&out, at (tos, idx));
1029 ol = 1;
1030
1031 idx++;
1032 break;
1033 }
1034 }
252b5132 1035
d70910e8
KH
1036 pc++;
1037 delete_string (tos);
1038 *tos = out;
252b5132
RH
1039
1040}
1041
d70910e8 1042WORD (get_stuff_in_command)
252b5132 1043{
d70910e8
KH
1044 tos++;
1045 check_range ();
1046 init_string (tos);
252b5132 1047
d70910e8
KH
1048 while (at (ptr, idx))
1049 {
1050 if (iscommand (ptr, idx))
1051 break;
1052 idx = copy_past_newline (ptr, idx, tos);
1053 }
1054 pc++;
252b5132
RH
1055}
1056
d70910e8 1057WORD (swap)
252b5132 1058{
d70910e8
KH
1059 string_type t;
1060
1061 t = tos[0];
1062 tos[0] = tos[-1];
1063 tos[-1] = t;
1064 pc++;
252b5132
RH
1065}
1066
d70910e8 1067WORD (other_dup)
252b5132 1068{
d70910e8
KH
1069 tos++;
1070 check_range ();
1071 init_string (tos);
1072 catstr (tos, tos - 1);
1073 pc++;
252b5132
RH
1074}
1075
d70910e8 1076WORD (drop)
252b5132
RH
1077{
1078 tos--;
1079 check_range ();
1080 pc++;
1081}
1082
d70910e8 1083WORD (idrop)
252b5132
RH
1084{
1085 isp--;
1086 icheck_range ();
1087 pc++;
1088}
1089
d70910e8 1090WORD (icatstr)
252b5132 1091{
d70910e8
KH
1092 tos--;
1093 check_range ();
1094 catstr (tos, tos + 1);
1095 delete_string (tos + 1);
1096 pc++;
252b5132
RH
1097}
1098
d70910e8 1099WORD (skip_past_newline)
252b5132 1100{
d70910e8
KH
1101 while (at (ptr, idx)
1102 && at (ptr, idx) != '\n')
252b5132 1103 idx++;
d70910e8
KH
1104 idx++;
1105 pc++;
252b5132
RH
1106}
1107
d70910e8 1108WORD (internalmode)
252b5132 1109{
d70910e8
KH
1110 internal_mode = *(isp);
1111 isp--;
1112 icheck_range ();
1113 pc++;
252b5132
RH
1114}
1115
d70910e8 1116WORD (maybecatstr)
252b5132 1117{
d70910e8 1118 if (internal_wanted == internal_mode)
252b5132 1119 {
d70910e8 1120 catstr (tos - 1, tos);
252b5132 1121 }
d70910e8
KH
1122 delete_string (tos);
1123 tos--;
1124 check_range ();
1125 pc++;
252b5132
RH
1126}
1127
1128char *
256d98af
KH
1129nextword (string, word)
1130 char *string;
1131 char **word;
252b5132 1132{
d70910e8
KH
1133 char *word_start;
1134 int idx;
1135 char *dst;
1136 char *src;
1137
1138 int length = 0;
1139
1140 while (isspace ((unsigned char) *string) || *string == '-')
1141 {
1142 if (*string == '-')
252b5132 1143 {
d70910e8 1144 while (*string && *string != '\n')
252b5132 1145 string++;
d70910e8
KH
1146
1147 }
1148 else
1149 {
1150 string++;
252b5132
RH
1151 }
1152 }
d70910e8
KH
1153 if (!*string)
1154 return 0;
252b5132 1155
d70910e8
KH
1156 word_start = string;
1157 if (*string == '"')
1158 {
1159 do
1160 {
1161 string++;
1162 length++;
1163 if (*string == '\\')
252b5132 1164 {
d70910e8
KH
1165 string += 2;
1166 length += 2;
252b5132 1167 }
d70910e8
KH
1168 }
1169 while (*string != '"');
252b5132 1170 }
d70910e8
KH
1171 else
1172 {
1173 while (!isspace ((unsigned char) *string))
1174 {
1175 string++;
1176 length++;
252b5132 1177
d70910e8
KH
1178 }
1179 }
252b5132 1180
d70910e8 1181 *word = malloc (length + 1);
252b5132 1182
d70910e8
KH
1183 dst = *word;
1184 src = word_start;
252b5132 1185
d70910e8
KH
1186 for (idx = 0; idx < length; idx++)
1187 {
1188 if (src[idx] == '\\')
1189 switch (src[idx + 1])
1190 {
1191 case 'n':
1192 *dst++ = '\n';
1193 idx++;
1194 break;
1195 case '"':
1196 case '\\':
1197 *dst++ = src[idx + 1];
1198 idx++;
1199 break;
1200 default:
1201 *dst++ = '\\';
1202 break;
1203 }
1204 else
1205 *dst++ = src[idx];
1206 }
1207 *dst++ = 0;
252b5132 1208
d70910e8
KH
1209 if (*string)
1210 return string + 1;
1211 else
1212 return 0;
252b5132 1213}
d70910e8 1214
252b5132 1215dict_type *root;
d70910e8 1216
252b5132 1217dict_type *
256d98af
KH
1218lookup_word (word)
1219 char *word;
252b5132
RH
1220{
1221 dict_type *ptr = root;
d70910e8
KH
1222 while (ptr)
1223 {
1224 if (strcmp (ptr->word, word) == 0)
1225 return ptr;
252b5132 1226 ptr = ptr->next;
252b5132
RH
1227 }
1228 if (warning)
d70910e8 1229 fprintf (stderr, "Can't find %s\n", word);
252b5132 1230 return 0;
252b5132
RH
1231}
1232
256d98af
KH
1233static void
1234perform (void)
252b5132
RH
1235{
1236 tos = stack;
252b5132 1237
d70910e8
KH
1238 while (at (ptr, idx))
1239 {
1240 /* It's worth looking through the command list. */
1241 if (iscommand (ptr, idx))
1242 {
1243 char *next;
1244 dict_type *word;
252b5132 1245
d70910e8 1246 (void) nextword (addr (ptr, idx), &next);
252b5132 1247
d70910e8 1248 word = lookup_word (next);
252b5132 1249
d70910e8
KH
1250 if (word)
1251 {
1252 exec (word);
1253 }
1254 else
1255 {
1256 if (warning)
1257 fprintf (stderr, "warning, %s is not recognised\n", next);
1258 skip_past_newline ();
1259 }
252b5132 1260
252b5132 1261 }
d70910e8
KH
1262 else
1263 skip_past_newline ();
252b5132
RH
1264 }
1265}
1266
1267dict_type *
256d98af
KH
1268newentry (word)
1269 char *word;
252b5132 1270{
d70910e8
KH
1271 dict_type *new = (dict_type *) malloc (sizeof (dict_type));
1272 new->word = word;
1273 new->next = root;
1274 root = new;
1275 new->code = (stinst_type *) malloc (sizeof (stinst_type));
1276 new->code_length = 1;
1277 new->code_end = 0;
1278 return new;
252b5132
RH
1279}
1280
252b5132 1281unsigned int
256d98af
KH
1282add_to_definition (entry, word)
1283 dict_type *entry;
1284 stinst_type word;
252b5132 1285{
d70910e8 1286 if (entry->code_end == entry->code_length)
252b5132 1287 {
d70910e8
KH
1288 entry->code_length += 2;
1289 entry->code =
1290 (stinst_type *) realloc ((char *) (entry->code),
1291 entry->code_length * sizeof (word_type));
252b5132 1292 }
d70910e8 1293 entry->code[entry->code_end] = word;
252b5132 1294
d70910e8
KH
1295 return entry->code_end++;
1296}
252b5132
RH
1297
1298void
256d98af
KH
1299add_intrinsic (name, func)
1300 char *name;
d70910e8 1301 void (*func) ();
252b5132 1302{
d70910e8
KH
1303 dict_type *new = newentry (name);
1304 add_to_definition (new, func);
1305 add_to_definition (new, 0);
252b5132
RH
1306}
1307
1308void
256d98af
KH
1309add_var (name)
1310 char *name;
252b5132 1311{
d70910e8
KH
1312 dict_type *new = newentry (name);
1313 add_to_definition (new, push_number);
1314 add_to_definition (new, (stinst_type) (&(new->var)));
1315 add_to_definition (new, 0);
252b5132
RH
1316}
1317
d70910e8 1318void
256d98af
KH
1319compile (string)
1320 char *string;
252b5132 1321{
d70910e8
KH
1322 /* Add words to the dictionary. */
1323 char *word;
1324 string = nextword (string, &word);
1325 while (string && *string && word[0])
252b5132 1326 {
d70910e8 1327 if (strcmp (word, "var") == 0)
252b5132 1328 {
d70910e8
KH
1329 string = nextword (string, &word);
1330
1331 add_var (word);
1332 string = nextword (string, &word);
252b5132 1333 }
d70910e8 1334 else if (word[0] == ':')
252b5132 1335 {
d70910e8
KH
1336 dict_type *ptr;
1337 /* Compile a word and add to dictionary. */
1338 string = nextword (string, &word);
1339
1340 ptr = newentry (word);
1341 string = nextword (string, &word);
1342 while (word[0] != ';')
252b5132 1343 {
d70910e8
KH
1344 switch (word[0])
1345 {
1346 case '"':
1347 /* got a string, embed magic push string
1348 function */
1349 add_to_definition (ptr, push_text);
1350 add_to_definition (ptr, (stinst_type) (word + 1));
1351 break;
1352 case '0':
1353 case '1':
1354 case '2':
1355 case '3':
1356 case '4':
1357 case '5':
1358 case '6':
1359 case '7':
1360 case '8':
1361 case '9':
1362 /* Got a number, embedd the magic push number
1363 function */
1364 add_to_definition (ptr, push_number);
1365 add_to_definition (ptr, (stinst_type) atol (word));
1366 break;
1367 default:
1368 add_to_definition (ptr, call);
1369 add_to_definition (ptr, (stinst_type) lookup_word (word));
1370 }
1371
1372 string = nextword (string, &word);
252b5132 1373 }
d70910e8
KH
1374 add_to_definition (ptr, 0);
1375 string = nextword (string, &word);
252b5132 1376 }
d70910e8 1377 else
252b5132 1378 {
d70910e8
KH
1379 fprintf (stderr, "syntax error at %s\n", string - 1);
1380 }
252b5132 1381 }
252b5132
RH
1382}
1383
256d98af
KH
1384static void
1385bang (void)
252b5132 1386{
d70910e8
KH
1387 *(long *) ((isp[0])) = isp[-1];
1388 isp -= 2;
252b5132
RH
1389 icheck_range ();
1390 pc++;
1391}
1392
d70910e8 1393WORD (atsign)
252b5132 1394{
d70910e8
KH
1395 isp[0] = *(long *) (isp[0]);
1396 pc++;
252b5132
RH
1397}
1398
d70910e8 1399WORD (hello)
252b5132 1400{
d70910e8
KH
1401 printf ("hello\n");
1402 pc++;
252b5132
RH
1403}
1404
d70910e8 1405WORD (stdout_)
252b5132
RH
1406{
1407 isp++;
1408 icheck_range ();
1409 *isp = 1;
1410 pc++;
1411}
1412
d70910e8 1413WORD (stderr_)
252b5132
RH
1414{
1415 isp++;
1416 icheck_range ();
1417 *isp = 2;
1418 pc++;
1419}
1420
d70910e8 1421WORD (print)
252b5132
RH
1422{
1423 if (*isp == 1)
1424 write_buffer (tos, stdout);
1425 else if (*isp == 2)
1426 write_buffer (tos, stderr);
1427 else
1428 fprintf (stderr, "print: illegal print destination `%ld'\n", *isp);
1429 isp--;
1430 tos--;
1431 icheck_range ();
1432 check_range ();
1433 pc++;
1434}
1435
256d98af
KH
1436static void
1437read_in (str, file)
d70910e8
KH
1438 string_type *str;
1439 FILE *file;
252b5132 1440{
d70910e8
KH
1441 char buff[10000];
1442 unsigned int r;
1443 do
252b5132 1444 {
d70910e8
KH
1445 r = fread (buff, 1, sizeof (buff), file);
1446 catbuf (str, buff, r);
252b5132 1447 }
d70910e8
KH
1448 while (r);
1449 buff[0] = 0;
252b5132 1450
d70910e8
KH
1451 catbuf (str, buff, 1);
1452}
252b5132 1453
256d98af
KH
1454static void
1455usage (void)
252b5132 1456{
d70910e8
KH
1457 fprintf (stderr, "usage: -[d|i|g] <file >file\n");
1458 exit (33);
252b5132
RH
1459}
1460
1461/* There is no reliable way to declare exit. Sometimes it returns
1462 int, and sometimes it returns void. Sometimes it changes between
1463 OS releases. Trying to get it declared correctly in the hosts file
1464 is a pointless waste of time. */
1465
1466static void
1467chew_exit ()
1468{
1469 exit (0);
1470}
1471
256d98af 1472int
d70910e8 1473main (ac, av)
256d98af
KH
1474 int ac;
1475 char *av[];
252b5132
RH
1476{
1477 unsigned int i;
1478 string_type buffer;
1479 string_type pptr;
1480
d70910e8
KH
1481 init_string (&buffer);
1482 init_string (&pptr);
1483 init_string (stack + 0);
1484 tos = stack + 1;
252b5132 1485 ptr = &pptr;
d70910e8
KH
1486
1487 add_intrinsic ("push_text", push_text);
1488 add_intrinsic ("!", bang);
1489 add_intrinsic ("@", atsign);
1490 add_intrinsic ("hello", hello);
1491 add_intrinsic ("stdout", stdout_);
1492 add_intrinsic ("stderr", stderr_);
1493 add_intrinsic ("print", print);
1494 add_intrinsic ("skip_past_newline", skip_past_newline);
1495 add_intrinsic ("catstr", icatstr);
1496 add_intrinsic ("copy_past_newline", icopy_past_newline);
1497 add_intrinsic ("dup", other_dup);
1498 add_intrinsic ("drop", drop);
1499 add_intrinsic ("idrop", idrop);
1500 add_intrinsic ("remchar", remchar);
1501 add_intrinsic ("get_stuff_in_command", get_stuff_in_command);
1502 add_intrinsic ("do_fancy_stuff", do_fancy_stuff);
1503 add_intrinsic ("bulletize", bulletize);
1504 add_intrinsic ("courierize", courierize);
252b5132
RH
1505 /* If the following line gives an error, exit() is not declared in the
1506 ../hosts/foo.h file for this host. Fix it there, not here! */
1507 /* No, don't fix it anywhere; see comment on chew_exit--Ian Taylor. */
d70910e8
KH
1508 add_intrinsic ("exit", chew_exit);
1509 add_intrinsic ("swap", swap);
1510 add_intrinsic ("outputdots", outputdots);
1511 add_intrinsic ("paramstuff", paramstuff);
1512 add_intrinsic ("maybecatstr", maybecatstr);
1513 add_intrinsic ("translatecomments", translatecomments);
1514 add_intrinsic ("kill_bogus_lines", kill_bogus_lines);
1515 add_intrinsic ("indent", indent);
1516 add_intrinsic ("internalmode", internalmode);
1517 add_intrinsic ("print_stack_level", print_stack_level);
1518 add_intrinsic ("strip_trailing_newlines", strip_trailing_newlines);
1519
1520 /* Put a nl at the start. */
1521 catchar (&buffer, '\n');
1522
1523 read_in (&buffer, stdin);
1524 remove_noncomments (&buffer, ptr);
1525 for (i = 1; i < (unsigned int) ac; i++)
252b5132 1526 {
d70910e8 1527 if (av[i][0] == '-')
252b5132 1528 {
d70910e8
KH
1529 if (av[i][1] == 'f')
1530 {
1531 string_type b;
1532 FILE *f;
1533 init_string (&b);
252b5132 1534
d70910e8
KH
1535 f = fopen (av[i + 1], "r");
1536 if (!f)
1537 {
1538 fprintf (stderr, "Can't open the input file %s\n",
1539 av[i + 1]);
1540 return 33;
1541 }
1542
1543 read_in (&b, f);
1544 compile (b.ptr);
1545 perform ();
1546 }
1547 else if (av[i][1] == 'i')
1548 {
1549 internal_wanted = 1;
1550 }
1551 else if (av[i][1] == 'w')
1552 {
1553 warning = 1;
1554 }
1555 else
1556 usage ();
1557 }
252b5132 1558 }
d70910e8 1559 write_buffer (stack + 0, stdout);
252b5132
RH
1560 if (tos != stack)
1561 {
d70910e8
KH
1562 fprintf (stderr, "finishing with current stack level %d\n",
1563 tos - stack);
252b5132
RH
1564 return 1;
1565 }
1566 return 0;
1567}
This page took 0.188849 seconds and 4 git commands to generate.