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