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