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