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