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