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