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