xref: /openbsd-src/gnu/usr.bin/binutils/bfd/doc/chew.c (revision 007c2a4539b8b8aaa95c5e73e77620090abe113b)
12159047fSniklas /* chew
2c074d1c9Sdrahn    Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998, 2000, 2001,
3*007c2a45Smiod    2002, 2003
4b305b0f1Sespie    Free Software Foundation, Inc.
52159047fSniklas    Contributed by steve chamberlain @cygnus
62159047fSniklas 
72159047fSniklas This file is part of BFD, the Binary File Descriptor library.
82159047fSniklas 
92159047fSniklas This program is free software; you can redistribute it and/or modify
102159047fSniklas it under the terms of the GNU General Public License as published by
112159047fSniklas the Free Software Foundation; either version 2 of the License, or
122159047fSniklas (at your option) any later version.
132159047fSniklas 
142159047fSniklas This program is distributed in the hope that it will be useful,
152159047fSniklas but WITHOUT ANY WARRANTY; without even the implied warranty of
162159047fSniklas MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
172159047fSniklas GNU General Public License for more details.
182159047fSniklas 
192159047fSniklas You should have received a copy of the GNU General Public License
202159047fSniklas along with this program; if not, write to the Free Software
212159047fSniklas Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
222159047fSniklas 
232159047fSniklas /* Yet another way of extracting documentation from source.
242159047fSniklas    No, I haven't finished it yet, but I hope you people like it better
252159047fSniklas    than the old way
262159047fSniklas 
272159047fSniklas    sac
282159047fSniklas 
292159047fSniklas    Basically, this is a sort of string forth, maybe we should call it
302159047fSniklas    struth?
312159047fSniklas 
322159047fSniklas    You define new words thus:
332159047fSniklas    : <newword> <oldwords> ;
342159047fSniklas 
352159047fSniklas */
362159047fSniklas 
372159047fSniklas /* Primitives provided by the program:
382159047fSniklas 
392159047fSniklas    Two stacks are provided, a string stack and an integer stack.
402159047fSniklas 
412159047fSniklas    Internal state variables:
422159047fSniklas 	internal_wanted - indicates whether `-i' was passed
432159047fSniklas 	internal_mode - user-settable
442159047fSniklas 
452159047fSniklas    Commands:
462159047fSniklas 	push_text
472159047fSniklas 	! - pop top of integer stack for address, pop next for value; store
482159047fSniklas 	@ - treat value on integer stack as the address of an integer; push
492159047fSniklas 		that integer on the integer stack after popping the "address"
502159047fSniklas 	hello - print "hello\n" to stdout
512159047fSniklas 	stdout - put stdout marker on TOS
522159047fSniklas 	stderr - put stderr marker on TOS
532159047fSniklas 	print - print TOS-1 on TOS (eg: "hello\n" stdout print)
542159047fSniklas 	skip_past_newline
552159047fSniklas 	catstr - fn icatstr
562159047fSniklas 	copy_past_newline - append input, up to and including newline into TOS
572159047fSniklas 	dup - fn other_dup
582159047fSniklas 	drop - discard TOS
592159047fSniklas 	idrop - ditto
602159047fSniklas 	remchar - delete last character from TOS
612159047fSniklas 	get_stuff_in_command
622159047fSniklas 	do_fancy_stuff - translate <<foo>> to @code{foo} in TOS
632159047fSniklas 	bulletize - if "o" lines found, prepend @itemize @bullet to TOS
642159047fSniklas 		and @item to each "o" line; append @end itemize
652159047fSniklas 	courierize - put @example around . and | lines, translate {* *} { }
662159047fSniklas 	exit - fn chew_exit
672159047fSniklas 	swap
682159047fSniklas 	outputdots - strip out lines without leading dots
692159047fSniklas 	paramstuff - convert full declaration into "PARAMS" form if not already
702159047fSniklas 	maybecatstr - do catstr if internal_mode == internal_wanted, discard
712159047fSniklas 		value in any case
722159047fSniklas 	translatecomments - turn {* and *} into comment delimiters
732159047fSniklas 	kill_bogus_lines - get rid of extra newlines
742159047fSniklas 	indent
752159047fSniklas 	internalmode - pop from integer stack, set `internalmode' to that value
762159047fSniklas 	print_stack_level - print current stack depth to stderr
772159047fSniklas 	strip_trailing_newlines - go ahead, guess...
782159047fSniklas 	[quoted string] - push string onto string stack
792159047fSniklas 	[word starting with digit] - push atol(str) onto integer stack
802159047fSniklas 
812159047fSniklas    A command must be all upper-case, and alone on a line.
822159047fSniklas 
832159047fSniklas    Foo.  */
842159047fSniklas 
85c074d1c9Sdrahn #include "ansidecl.h"
862159047fSniklas #include "sysdep.h"
872159047fSniklas #include <assert.h>
882159047fSniklas #include <stdio.h>
892159047fSniklas #include <ctype.h>
902159047fSniklas 
912159047fSniklas #define DEF_SIZE 5000
922159047fSniklas #define STACK 50
932159047fSniklas 
942159047fSniklas int internal_wanted;
952159047fSniklas int internal_mode;
962159047fSniklas 
972159047fSniklas int warning;
982159047fSniklas 
992159047fSniklas /* Here is a string type ...  */
1002159047fSniklas 
1012159047fSniklas typedef struct buffer
1022159047fSniklas {
1032159047fSniklas   char *ptr;
1042159047fSniklas   unsigned long write_idx;
1052159047fSniklas   unsigned long size;
1062159047fSniklas } string_type;
1072159047fSniklas 
1082159047fSniklas #ifdef __STDC__
1092159047fSniklas static void init_string_with_size (string_type *, unsigned int);
1102159047fSniklas static void init_string (string_type *);
1112159047fSniklas static int find (string_type *, char *);
1122159047fSniklas static void write_buffer (string_type *, FILE *);
1132159047fSniklas static void delete_string (string_type *);
1142159047fSniklas static char *addr (string_type *, unsigned int);
1152159047fSniklas static char at (string_type *, unsigned int);
1162159047fSniklas static void catchar (string_type *, int);
1172159047fSniklas static void overwrite_string (string_type *, string_type *);
1182159047fSniklas static void catbuf (string_type *, char *, unsigned int);
1192159047fSniklas static void cattext (string_type *, char *);
1202159047fSniklas static void catstr (string_type *, string_type *);
1212159047fSniklas #endif
1222159047fSniklas 
123b55d4692Sfgsch static void
init_string_with_size(buffer,size)124b55d4692Sfgsch init_string_with_size (buffer, size)
125b55d4692Sfgsch      string_type *buffer;
126b55d4692Sfgsch      unsigned int size;
1272159047fSniklas {
1282159047fSniklas   buffer->write_idx = 0;
1292159047fSniklas   buffer->size = size;
1302159047fSniklas   buffer->ptr = malloc (size);
1312159047fSniklas }
1322159047fSniklas 
133b55d4692Sfgsch static void
init_string(buffer)134b55d4692Sfgsch init_string (buffer)
135b55d4692Sfgsch      string_type *buffer;
1362159047fSniklas {
1372159047fSniklas   init_string_with_size (buffer, DEF_SIZE);
1382159047fSniklas }
1392159047fSniklas 
140b55d4692Sfgsch static int
find(str,what)141b55d4692Sfgsch find (str, what)
142b55d4692Sfgsch      string_type *str;
143b55d4692Sfgsch      char *what;
1442159047fSniklas {
1452159047fSniklas   unsigned int i;
1462159047fSniklas   char *p;
1472159047fSniklas   p = what;
1482159047fSniklas   for (i = 0; i < str->write_idx && *p; i++)
1492159047fSniklas     {
1502159047fSniklas       if (*p == str->ptr[i])
1512159047fSniklas 	p++;
1522159047fSniklas       else
1532159047fSniklas 	p = what;
1542159047fSniklas     }
1552159047fSniklas   return (*p == 0);
1562159047fSniklas }
1572159047fSniklas 
158b55d4692Sfgsch static void
write_buffer(buffer,f)159b55d4692Sfgsch write_buffer (buffer, f)
160b55d4692Sfgsch      string_type *buffer;
161b55d4692Sfgsch      FILE *f;
1622159047fSniklas {
1632159047fSniklas   fwrite (buffer->ptr, buffer->write_idx, 1, f);
1642159047fSniklas }
1652159047fSniklas 
166b55d4692Sfgsch static void
delete_string(buffer)167b55d4692Sfgsch delete_string (buffer)
168b55d4692Sfgsch      string_type *buffer;
1692159047fSniklas {
1702159047fSniklas   free (buffer->ptr);
1712159047fSniklas }
1722159047fSniklas 
173b55d4692Sfgsch static char *
addr(buffer,idx)174b55d4692Sfgsch addr (buffer, idx)
175b55d4692Sfgsch      string_type *buffer;
176b55d4692Sfgsch      unsigned int idx;
1772159047fSniklas {
1782159047fSniklas   return buffer->ptr + idx;
1792159047fSniklas }
1802159047fSniklas 
181b55d4692Sfgsch static char
at(buffer,pos)182b55d4692Sfgsch at (buffer, pos)
183b55d4692Sfgsch      string_type *buffer;
184b55d4692Sfgsch      unsigned int pos;
1852159047fSniklas {
1862159047fSniklas   if (pos >= buffer->write_idx)
1872159047fSniklas     return 0;
1882159047fSniklas   return buffer->ptr[pos];
1892159047fSniklas }
1902159047fSniklas 
191b55d4692Sfgsch static void
catchar(buffer,ch)192b55d4692Sfgsch catchar (buffer, ch)
193b55d4692Sfgsch      string_type *buffer;
194b55d4692Sfgsch      int ch;
1952159047fSniklas {
1962159047fSniklas   if (buffer->write_idx == buffer->size)
1972159047fSniklas     {
1982159047fSniklas       buffer->size *= 2;
1992159047fSniklas       buffer->ptr = realloc (buffer->ptr, buffer->size);
2002159047fSniklas     }
2012159047fSniklas 
2022159047fSniklas   buffer->ptr[buffer->write_idx++] = ch;
2032159047fSniklas }
2042159047fSniklas 
205b55d4692Sfgsch static void
overwrite_string(dst,src)206b55d4692Sfgsch overwrite_string (dst, src)
207b55d4692Sfgsch      string_type *dst;
208b55d4692Sfgsch      string_type *src;
2092159047fSniklas {
2102159047fSniklas   free (dst->ptr);
2112159047fSniklas   dst->size = src->size;
2122159047fSniklas   dst->write_idx = src->write_idx;
2132159047fSniklas   dst->ptr = src->ptr;
2142159047fSniklas }
2152159047fSniklas 
216b55d4692Sfgsch static void
catbuf(buffer,buf,len)217b55d4692Sfgsch catbuf (buffer, buf, len)
218b55d4692Sfgsch      string_type *buffer;
219b55d4692Sfgsch      char *buf;
220b55d4692Sfgsch      unsigned int len;
2212159047fSniklas {
2222159047fSniklas   if (buffer->write_idx + len >= buffer->size)
2232159047fSniklas     {
2242159047fSniklas       while (buffer->write_idx + len >= buffer->size)
2252159047fSniklas 	buffer->size *= 2;
2262159047fSniklas       buffer->ptr = realloc (buffer->ptr, buffer->size);
2272159047fSniklas     }
2282159047fSniklas   memcpy (buffer->ptr + buffer->write_idx, buf, len);
2292159047fSniklas   buffer->write_idx += len;
2302159047fSniklas }
2312159047fSniklas 
232b55d4692Sfgsch static void
cattext(buffer,string)233b55d4692Sfgsch cattext (buffer, string)
234b55d4692Sfgsch      string_type *buffer;
235b55d4692Sfgsch      char *string;
2362159047fSniklas {
2372159047fSniklas   catbuf (buffer, string, (unsigned int) strlen (string));
2382159047fSniklas }
2392159047fSniklas 
240b55d4692Sfgsch static void
catstr(dst,src)241b55d4692Sfgsch catstr (dst, src)
242b55d4692Sfgsch      string_type *dst;
243b55d4692Sfgsch      string_type *src;
2442159047fSniklas {
2452159047fSniklas   catbuf (dst, src->ptr, src->write_idx);
2462159047fSniklas }
2472159047fSniklas 
2482159047fSniklas static unsigned int
skip_white_and_stars(src,idx)249b55d4692Sfgsch skip_white_and_stars (src, idx)
250b55d4692Sfgsch      string_type *src;
251b55d4692Sfgsch      unsigned int idx;
2522159047fSniklas {
2532159047fSniklas   char c;
2542159047fSniklas   while ((c = at (src, idx)),
255b305b0f1Sespie 	 isspace ((unsigned char) c)
2562159047fSniklas 	 || (c == '*'
2572159047fSniklas 	     /* Don't skip past end-of-comment or star as first
2582159047fSniklas 		character on its line.  */
2592159047fSniklas 	     && at (src, idx +1) != '/'
2602159047fSniklas 	     && at (src, idx -1) != '\n'))
2612159047fSniklas     idx++;
2622159047fSniklas   return idx;
2632159047fSniklas }
2642159047fSniklas 
2652159047fSniklas /***********************************************************************/
2662159047fSniklas 
2672159047fSniklas string_type stack[STACK];
2682159047fSniklas string_type *tos;
2692159047fSniklas 
2702159047fSniklas unsigned int idx = 0; /* Pos in input buffer */
2712159047fSniklas string_type *ptr; /* and the buffer */
2722159047fSniklas typedef void (*stinst_type)();
2732159047fSniklas stinst_type *pc;
2742159047fSniklas stinst_type sstack[STACK];
2752159047fSniklas stinst_type *ssp = &sstack[0];
2762159047fSniklas long istack[STACK];
2772159047fSniklas long *isp = &istack[0];
2782159047fSniklas 
2792159047fSniklas typedef int *word_type;
2802159047fSniklas 
2812159047fSniklas struct dict_struct
2822159047fSniklas {
2832159047fSniklas   char *word;
2842159047fSniklas   struct dict_struct *next;
2852159047fSniklas   stinst_type *code;
2862159047fSniklas   int code_length;
2872159047fSniklas   int code_end;
2882159047fSniklas   int var;
2892159047fSniklas };
290b55d4692Sfgsch 
2912159047fSniklas typedef struct dict_struct dict_type;
292b55d4692Sfgsch 
2932159047fSniklas static void
die(msg)2942159047fSniklas die (msg)
2952159047fSniklas      char *msg;
2962159047fSniklas {
2972159047fSniklas   fprintf (stderr, "%s\n", msg);
2982159047fSniklas   exit (1);
2992159047fSniklas }
3002159047fSniklas 
3012159047fSniklas static void
check_range()3022159047fSniklas check_range ()
3032159047fSniklas {
3042159047fSniklas   if (tos < stack)
3052159047fSniklas     die ("underflow in string stack");
3062159047fSniklas   if (tos >= stack + STACK)
3072159047fSniklas     die ("overflow in string stack");
3082159047fSniklas }
3092159047fSniklas 
3102159047fSniklas static void
icheck_range()3112159047fSniklas icheck_range ()
3122159047fSniklas {
3132159047fSniklas   if (isp < istack)
3142159047fSniklas     die ("underflow in integer stack");
3152159047fSniklas   if (isp >= istack + STACK)
3162159047fSniklas     die ("overflow in integer stack");
3172159047fSniklas }
3182159047fSniklas 
3192159047fSniklas #ifdef __STDC__
3202159047fSniklas static void exec (dict_type *);
3212159047fSniklas static void call (void);
3222159047fSniklas static void remchar (void), strip_trailing_newlines (void), push_number (void);
3232159047fSniklas static void push_text (void);
3242159047fSniklas static void remove_noncomments (string_type *, string_type *);
3252159047fSniklas static void print_stack_level (void);
326b305b0f1Sespie static void paramstuff (void), translatecomments (void);
3272159047fSniklas static void outputdots (void), courierize (void), bulletize (void);
3282159047fSniklas static void do_fancy_stuff (void);
3292159047fSniklas static int iscommand (string_type *, unsigned int);
3302159047fSniklas static int copy_past_newline (string_type *, unsigned int, string_type *);
3312159047fSniklas static void icopy_past_newline (void), kill_bogus_lines (void), indent (void);
3322159047fSniklas static void get_stuff_in_command (void), swap (void), other_dup (void);
3332159047fSniklas static void drop (void), idrop (void);
3342159047fSniklas static void icatstr (void), skip_past_newline (void), internalmode (void);
3352159047fSniklas static void maybecatstr (void);
3362159047fSniklas static char *nextword (char *, char **);
3372159047fSniklas dict_type *lookup_word (char *);
3382159047fSniklas static void perform (void);
3392159047fSniklas dict_type *newentry (char *);
3402159047fSniklas unsigned int add_to_definition (dict_type *, stinst_type);
3412159047fSniklas void add_intrinsic (char *, void (*)());
3422159047fSniklas void add_var (char *);
3432159047fSniklas void compile (char *);
3442159047fSniklas static void bang (void);
3452159047fSniklas static void atsign (void);
3462159047fSniklas static void hello (void);
3472159047fSniklas static void stdout_ (void);
3482159047fSniklas static void stderr_ (void);
3492159047fSniklas static void print (void);
3502159047fSniklas static void read_in (string_type *, FILE *);
3512159047fSniklas static void usage (void);
3522159047fSniklas static void chew_exit (void);
3532159047fSniklas #endif
3542159047fSniklas 
355b55d4692Sfgsch static void
exec(word)356b55d4692Sfgsch exec (word)
357b55d4692Sfgsch      dict_type *word;
3582159047fSniklas {
3592159047fSniklas   pc = word->code;
3602159047fSniklas   while (*pc)
3612159047fSniklas     (*pc) ();
3622159047fSniklas }
363b55d4692Sfgsch 
364c074d1c9Sdrahn static void
call()365c074d1c9Sdrahn call ()
3662159047fSniklas {
3672159047fSniklas   stinst_type *oldpc = pc;
3682159047fSniklas   dict_type *e;
3692159047fSniklas   e = (dict_type *) (pc[1]);
3702159047fSniklas   exec (e);
3712159047fSniklas   pc = oldpc + 2;
3722159047fSniklas }
3732159047fSniklas 
374c074d1c9Sdrahn static void
remchar()375c074d1c9Sdrahn remchar ()
3762159047fSniklas {
3772159047fSniklas   if (tos->write_idx)
3782159047fSniklas     tos->write_idx--;
3792159047fSniklas   pc++;
3802159047fSniklas }
3812159047fSniklas 
3822159047fSniklas static void
strip_trailing_newlines()3832159047fSniklas strip_trailing_newlines ()
3842159047fSniklas {
385b305b0f1Sespie   while ((isspace ((unsigned char) at (tos, tos->write_idx - 1))
3862159047fSniklas 	  || at (tos, tos->write_idx - 1) == '\n')
3872159047fSniklas 	 && tos->write_idx > 0)
3882159047fSniklas     tos->write_idx--;
3892159047fSniklas   pc++;
3902159047fSniklas }
3912159047fSniklas 
392c074d1c9Sdrahn static void
push_number()393c074d1c9Sdrahn push_number ()
3942159047fSniklas {
3952159047fSniklas   isp++;
3962159047fSniklas   icheck_range ();
3972159047fSniklas   pc++;
3982159047fSniklas   *isp = (long) (*pc);
3992159047fSniklas   pc++;
4002159047fSniklas }
4012159047fSniklas 
402c074d1c9Sdrahn static void
push_text()403c074d1c9Sdrahn push_text ()
4042159047fSniklas {
4052159047fSniklas   tos++;
4062159047fSniklas   check_range ();
4072159047fSniklas   init_string (tos);
4082159047fSniklas   pc++;
4092159047fSniklas   cattext (tos, *((char **) pc));
4102159047fSniklas   pc++;
4112159047fSniklas }
4122159047fSniklas 
4132159047fSniklas /* This function removes everything not inside comments starting on
4142159047fSniklas    the first char of the line from the  string, also when copying
4152159047fSniklas    comments, removes blank space and leading *'s.
4162159047fSniklas    Blank lines are turned into one blank line.  */
4172159047fSniklas 
4182159047fSniklas static void
remove_noncomments(src,dst)419b55d4692Sfgsch remove_noncomments (src, dst)
420b55d4692Sfgsch      string_type *src;
421b55d4692Sfgsch      string_type *dst;
4222159047fSniklas {
4232159047fSniklas   unsigned int idx = 0;
4242159047fSniklas 
4252159047fSniklas   while (at (src, idx))
4262159047fSniklas     {
427b55d4692Sfgsch       /* Now see if we have a comment at the start of the line.  */
4282159047fSniklas       if (at (src, idx) == '\n'
4292159047fSniklas 	  && at (src, idx + 1) == '/'
4302159047fSniklas 	  && at (src, idx + 2) == '*')
4312159047fSniklas 	{
4322159047fSniklas 	  idx += 3;
4332159047fSniklas 
4342159047fSniklas 	  idx = skip_white_and_stars (src, idx);
4352159047fSniklas 
4362159047fSniklas 	  /* Remove leading dot */
4372159047fSniklas 	  if (at (src, idx) == '.')
4382159047fSniklas 	    idx++;
4392159047fSniklas 
4402159047fSniklas 	  /* Copy to the end of the line, or till the end of the
441b55d4692Sfgsch 	     comment.  */
4422159047fSniklas 	  while (at (src, idx))
4432159047fSniklas 	    {
4442159047fSniklas 	      if (at (src, idx) == '\n')
4452159047fSniklas 		{
4462159047fSniklas 		  /* end of line, echo and scrape of leading blanks  */
4472159047fSniklas 		  if (at (src, idx + 1) == '\n')
4482159047fSniklas 		    catchar (dst, '\n');
4492159047fSniklas 		  catchar (dst, '\n');
4502159047fSniklas 		  idx++;
4512159047fSniklas 		  idx = skip_white_and_stars (src, idx);
4522159047fSniklas 		}
4532159047fSniklas 	      else if (at (src, idx) == '*' && at (src, idx + 1) == '/')
4542159047fSniklas 		{
4552159047fSniklas 		  idx += 2;
4562159047fSniklas 		  cattext (dst, "\nENDDD\n");
4572159047fSniklas 		  break;
4582159047fSniklas 		}
4592159047fSniklas 	      else
4602159047fSniklas 		{
4612159047fSniklas 		  catchar (dst, at (src, idx));
4622159047fSniklas 		  idx++;
4632159047fSniklas 		}
4642159047fSniklas 	    }
4652159047fSniklas 	}
466b55d4692Sfgsch       else
467b55d4692Sfgsch 	idx++;
4682159047fSniklas     }
4692159047fSniklas }
4702159047fSniklas 
4712159047fSniklas static void
print_stack_level()4722159047fSniklas print_stack_level ()
4732159047fSniklas {
4742159047fSniklas   fprintf (stderr, "current string stack depth = %d, ", tos - stack);
4752159047fSniklas   fprintf (stderr, "current integer stack depth = %d\n", isp - istack);
4762159047fSniklas   pc++;
4772159047fSniklas }
4782159047fSniklas 
4792159047fSniklas /* turn:
4802159047fSniklas      foobar name(stuff);
4812159047fSniklas    into:
4822159047fSniklas      foobar
4832159047fSniklas      name PARAMS ((stuff));
4842159047fSniklas    and a blank line.
4852159047fSniklas  */
4862159047fSniklas 
4872159047fSniklas static void
paramstuff()488c074d1c9Sdrahn paramstuff ()
4892159047fSniklas {
4902159047fSniklas   unsigned int openp;
4912159047fSniklas   unsigned int fname;
4922159047fSniklas   unsigned int idx;
493b55d4692Sfgsch   unsigned int len;
4942159047fSniklas   string_type out;
4952159047fSniklas   init_string (&out);
4962159047fSniklas 
497*007c2a45Smiod #define NO_PARAMS 1
498*007c2a45Smiod 
499b55d4692Sfgsch   /* Make sure that it's not already param'd or proto'd.  */
500*007c2a45Smiod   if (NO_PARAMS
501*007c2a45Smiod       || find (tos, "PARAMS") || find (tos, "PROTO") || !find (tos, "("))
502b55d4692Sfgsch     {
5032159047fSniklas       catstr (&out, tos);
5042159047fSniklas     }
5052159047fSniklas   else
5062159047fSniklas     {
507b55d4692Sfgsch       /* Find the open paren.  */
5082159047fSniklas       for (openp = 0; at (tos, openp) != '(' && at (tos, openp); openp++)
5092159047fSniklas 	;
5102159047fSniklas 
5112159047fSniklas       fname = openp;
512b55d4692Sfgsch       /* Step back to the fname.  */
5132159047fSniklas       fname--;
514b305b0f1Sespie       while (fname && isspace ((unsigned char) at (tos, fname)))
5152159047fSniklas 	fname--;
516b305b0f1Sespie       while (fname
517b305b0f1Sespie 	     && !isspace ((unsigned char) at (tos,fname))
518b305b0f1Sespie 	     && at (tos,fname) != '*')
5192159047fSniklas 	fname--;
5202159047fSniklas 
5212159047fSniklas       fname++;
5222159047fSniklas 
523b55d4692Sfgsch       /* Output type, omitting trailing whitespace character(s), if
524b55d4692Sfgsch          any.  */
525b55d4692Sfgsch       for (len = fname; 0 < len; len--)
5262159047fSniklas 	{
527b55d4692Sfgsch 	  if (!isspace ((unsigned char) at (tos, len - 1)))
528b55d4692Sfgsch 	    break;
5292159047fSniklas 	}
530b55d4692Sfgsch       for (idx = 0; idx < len; idx++)
531b55d4692Sfgsch 	catchar (&out, at (tos, idx));
5322159047fSniklas 
5332159047fSniklas       cattext (&out, "\n");	/* Insert a newline between type and fnname */
5342159047fSniklas 
535b55d4692Sfgsch       /* Output function name, omitting trailing whitespace
536b55d4692Sfgsch          character(s), if any.  */
537b55d4692Sfgsch       for (len = openp; 0 < len; len--)
5382159047fSniklas 	{
539b55d4692Sfgsch 	  if (!isspace ((unsigned char) at (tos, len - 1)))
540b55d4692Sfgsch 	    break;
5412159047fSniklas 	}
542b55d4692Sfgsch       for (idx = fname; idx < len; idx++)
543b55d4692Sfgsch 	catchar (&out, at (tos, idx));
5442159047fSniklas 
5452159047fSniklas       cattext (&out, " PARAMS (");
5462159047fSniklas 
547b55d4692Sfgsch       for (idx = openp; at (tos, idx) && at (tos, idx) != ';'; idx++)
5482159047fSniklas 	catchar (&out, at (tos, idx));
549b55d4692Sfgsch 
5502159047fSniklas       cattext (&out, ");\n\n");
5512159047fSniklas     }
5522159047fSniklas   overwrite_string (tos, &out);
5532159047fSniklas   pc++;
5542159047fSniklas 
5552159047fSniklas }
5562159047fSniklas 
5572159047fSniklas /* turn {*
5582159047fSniklas    and *} into comments */
5592159047fSniklas 
560c074d1c9Sdrahn static void
translatecomments()561c074d1c9Sdrahn translatecomments ()
5622159047fSniklas {
5632159047fSniklas   unsigned int idx = 0;
5642159047fSniklas   string_type out;
5652159047fSniklas   init_string (&out);
5662159047fSniklas 
5672159047fSniklas   while (at (tos, idx))
5682159047fSniklas     {
5692159047fSniklas       if (at (tos, idx) == '{' && at (tos, idx + 1) == '*')
5702159047fSniklas 	{
5712159047fSniklas 	  cattext (&out, "/*");
5722159047fSniklas 	  idx += 2;
5732159047fSniklas 	}
5742159047fSniklas       else if (at (tos, idx) == '*' && at (tos, idx + 1) == '}')
5752159047fSniklas 	{
5762159047fSniklas 	  cattext (&out, "*/");
5772159047fSniklas 	  idx += 2;
5782159047fSniklas 	}
5792159047fSniklas       else
5802159047fSniklas 	{
5812159047fSniklas 	  catchar (&out, at (tos, idx));
5822159047fSniklas 	  idx++;
5832159047fSniklas 	}
5842159047fSniklas     }
5852159047fSniklas 
5862159047fSniklas   overwrite_string (tos, &out);
5872159047fSniklas 
5882159047fSniklas   pc++;
5892159047fSniklas }
5902159047fSniklas 
591b305b0f1Sespie #if 0
592b305b0f1Sespie 
593b305b0f1Sespie /* This is not currently used.  */
594b305b0f1Sespie 
5952159047fSniklas /* turn everything not starting with a . into a comment */
5962159047fSniklas 
597c074d1c9Sdrahn static void
598c074d1c9Sdrahn manglecomments ()
5992159047fSniklas {
6002159047fSniklas   unsigned int idx = 0;
6012159047fSniklas   string_type out;
6022159047fSniklas   init_string (&out);
6032159047fSniklas 
6042159047fSniklas   while (at (tos, idx))
6052159047fSniklas     {
6062159047fSniklas       if (at (tos, idx) == '\n' && at (tos, idx + 1) == '*')
6072159047fSniklas 	{
6082159047fSniklas 	  cattext (&out, "	/*");
6092159047fSniklas 	  idx += 2;
6102159047fSniklas 	}
6112159047fSniklas       else if (at (tos, idx) == '*' && at (tos, idx + 1) == '}')
6122159047fSniklas 	{
6132159047fSniklas 	  cattext (&out, "*/");
6142159047fSniklas 	  idx += 2;
6152159047fSniklas 	}
6162159047fSniklas       else
6172159047fSniklas 	{
6182159047fSniklas 	  catchar (&out, at (tos, idx));
6192159047fSniklas 	  idx++;
6202159047fSniklas 	}
6212159047fSniklas     }
6222159047fSniklas 
6232159047fSniklas   overwrite_string (tos, &out);
6242159047fSniklas 
6252159047fSniklas   pc++;
6262159047fSniklas }
6272159047fSniklas 
628b305b0f1Sespie #endif
629b305b0f1Sespie 
6302159047fSniklas /* Mod tos so that only lines with leading dots remain */
6312159047fSniklas static void
outputdots()632c074d1c9Sdrahn outputdots ()
6332159047fSniklas {
6342159047fSniklas   unsigned int idx = 0;
6352159047fSniklas   string_type out;
6362159047fSniklas   init_string (&out);
6372159047fSniklas 
6382159047fSniklas   while (at (tos, idx))
6392159047fSniklas     {
6402159047fSniklas       if (at (tos, idx) == '\n' && at (tos, idx + 1) == '.')
6412159047fSniklas 	{
642b305b0f1Sespie 	  char c;
6432159047fSniklas 	  idx += 2;
6442159047fSniklas 
6452159047fSniklas 	  while ((c = at (tos, idx)) && c != '\n')
6462159047fSniklas 	    {
6472159047fSniklas 	      if (c == '{' && at (tos, idx + 1) == '*')
6482159047fSniklas 		{
6492159047fSniklas 		  cattext (&out, "/*");
6502159047fSniklas 		  idx += 2;
6512159047fSniklas 		}
6522159047fSniklas 	      else if (c == '*' && at (tos, idx + 1) == '}')
6532159047fSniklas 		{
6542159047fSniklas 		  cattext (&out, "*/");
6552159047fSniklas 		  idx += 2;
6562159047fSniklas 		}
6572159047fSniklas 	      else
6582159047fSniklas 		{
6592159047fSniklas 		  catchar (&out, c);
6602159047fSniklas 		  idx++;
6612159047fSniklas 		}
6622159047fSniklas 	    }
6632159047fSniklas 	  catchar (&out, '\n');
6642159047fSniklas 	}
6652159047fSniklas       else
6662159047fSniklas 	{
6672159047fSniklas 	  idx++;
6682159047fSniklas 	}
6692159047fSniklas     }
6702159047fSniklas 
6712159047fSniklas   overwrite_string (tos, &out);
6722159047fSniklas   pc++;
6732159047fSniklas }
6742159047fSniklas 
6752159047fSniklas /* Find lines starting with . and | and put example around them on tos */
676c074d1c9Sdrahn static void
courierize()677c074d1c9Sdrahn courierize ()
6782159047fSniklas {
6792159047fSniklas   string_type out;
6802159047fSniklas   unsigned int idx = 0;
6812159047fSniklas   int command = 0;
6822159047fSniklas 
6832159047fSniklas   init_string (&out);
6842159047fSniklas 
6852159047fSniklas   while (at (tos, idx))
6862159047fSniklas     {
6872159047fSniklas       if (at (tos, idx) == '\n'
6882159047fSniklas 	  && (at (tos, idx +1 ) == '.'
6892159047fSniklas 	      || at (tos, idx + 1) == '|'))
6902159047fSniklas 	{
6912159047fSniklas 	  cattext (&out, "\n@example\n");
6922159047fSniklas 	  do
6932159047fSniklas 	    {
6942159047fSniklas 	      idx += 2;
6952159047fSniklas 
6962159047fSniklas 	      while (at (tos, idx) && at (tos, idx) != '\n')
6972159047fSniklas 		{
698c074d1c9Sdrahn 		  if (command > 1)
699c074d1c9Sdrahn 		    {
700c074d1c9Sdrahn 		      /* We are inside {} parameters of some command;
701c074d1c9Sdrahn 			 Just pass through until matching brace.  */
702c074d1c9Sdrahn 		      if (at (tos, idx) == '{')
703c074d1c9Sdrahn 			++command;
704c074d1c9Sdrahn 		      else if (at (tos, idx) == '}')
705c074d1c9Sdrahn 			--command;
706c074d1c9Sdrahn 		    }
707c074d1c9Sdrahn 		  else if (command != 0)
708c074d1c9Sdrahn 		    {
709c074d1c9Sdrahn 		      if (at (tos, idx) == '{')
710c074d1c9Sdrahn 			++command;
711c074d1c9Sdrahn 		      else if (!islower ((unsigned char) at (tos, idx)))
712c074d1c9Sdrahn 			--command;
713c074d1c9Sdrahn 		    }
714c074d1c9Sdrahn 		  else if (at (tos, idx) == '@'
715c074d1c9Sdrahn 			   && islower ((unsigned char) at (tos, idx + 1)))
716c074d1c9Sdrahn 		    {
717c074d1c9Sdrahn 		      ++command;
718c074d1c9Sdrahn 		    }
719c074d1c9Sdrahn 		  else if (at (tos, idx) == '{' && at (tos, idx + 1) == '*')
7202159047fSniklas 		    {
7212159047fSniklas 		      cattext (&out, "/*");
7222159047fSniklas 		      idx += 2;
723c074d1c9Sdrahn 		      continue;
7242159047fSniklas 		    }
7252159047fSniklas 		  else if (at (tos, idx) == '*' && at (tos, idx + 1) == '}')
7262159047fSniklas 		    {
7272159047fSniklas 		      cattext (&out, "*/");
7282159047fSniklas 		      idx += 2;
729c074d1c9Sdrahn 		      continue;
7302159047fSniklas 		    }
731c074d1c9Sdrahn 		  else if (at (tos, idx) == '{'
732b305b0f1Sespie 			   || at (tos, idx) == '}')
733c074d1c9Sdrahn 		    {
734c074d1c9Sdrahn 		      catchar (&out, '@');
7352159047fSniklas 		    }
7362159047fSniklas 
737c074d1c9Sdrahn 		  catchar (&out, at (tos, idx));
738c074d1c9Sdrahn 		  idx++;
7392159047fSniklas 		}
7402159047fSniklas 	      catchar (&out, '\n');
7412159047fSniklas 	    }
7422159047fSniklas 	  while (at (tos, idx) == '\n'
743b305b0f1Sespie 		 && ((at (tos, idx + 1) == '.')
744b305b0f1Sespie 		     || (at (tos, idx + 1) == '|')))
745b305b0f1Sespie 	    ;
7462159047fSniklas 	  cattext (&out, "@end example");
7472159047fSniklas 	}
7482159047fSniklas       else
7492159047fSniklas 	{
7502159047fSniklas 	  catchar (&out, at (tos, idx));
7512159047fSniklas 	  idx++;
7522159047fSniklas 	}
7532159047fSniklas     }
7542159047fSniklas 
7552159047fSniklas   overwrite_string (tos, &out);
7562159047fSniklas   pc++;
7572159047fSniklas }
7582159047fSniklas 
7592159047fSniklas /* Finds any lines starting with "o ", if there are any, then turns
7602159047fSniklas    on @itemize @bullet, and @items each of them. Then ends with @end
7612159047fSniklas    itemize, inplace at TOS*/
7622159047fSniklas 
763c074d1c9Sdrahn static void
bulletize()764c074d1c9Sdrahn bulletize ()
7652159047fSniklas {
7662159047fSniklas   unsigned int idx = 0;
7672159047fSniklas   int on = 0;
7682159047fSniklas   string_type out;
7692159047fSniklas   init_string (&out);
7702159047fSniklas 
771b55d4692Sfgsch   while (at (tos, idx))
772b55d4692Sfgsch     {
773b55d4692Sfgsch       if (at (tos, idx) == '@'
774b55d4692Sfgsch 	  && at (tos, idx + 1) == '*')
7752159047fSniklas 	{
7762159047fSniklas 	  cattext (&out, "*");
7772159047fSniklas 	  idx += 2;
7782159047fSniklas 	}
779b55d4692Sfgsch       else if (at (tos, idx) == '\n'
780b55d4692Sfgsch 	       && at (tos, idx + 1) == 'o'
781b55d4692Sfgsch 	       && isspace ((unsigned char) at (tos, idx + 2)))
7822159047fSniklas 	{
7832159047fSniklas 	  if (!on)
7842159047fSniklas 	    {
7852159047fSniklas 	      cattext (&out, "\n@itemize @bullet\n");
7862159047fSniklas 	      on = 1;
7872159047fSniklas 
7882159047fSniklas 	    }
7892159047fSniklas 	  cattext (&out, "\n@item\n");
7902159047fSniklas 	  idx += 3;
7912159047fSniklas 	}
7922159047fSniklas       else
7932159047fSniklas 	{
7942159047fSniklas 	  catchar (&out, at (tos, idx));
795b55d4692Sfgsch 	  if (on && at (tos, idx) == '\n'
796b55d4692Sfgsch 	      && at (tos, idx + 1) == '\n'
797b55d4692Sfgsch 	      && at (tos, idx + 2) != 'o')
7982159047fSniklas 	    {
7992159047fSniklas 	      cattext (&out, "@end itemize");
8002159047fSniklas 	      on = 0;
8012159047fSniklas 	    }
8022159047fSniklas 	  idx++;
8032159047fSniklas 
8042159047fSniklas 	}
8052159047fSniklas     }
8062159047fSniklas   if (on)
8072159047fSniklas     {
8082159047fSniklas       cattext (&out, "@end itemize\n");
8092159047fSniklas     }
8102159047fSniklas 
8112159047fSniklas   delete_string (tos);
8122159047fSniklas   *tos = out;
8132159047fSniklas   pc++;
8142159047fSniklas }
8152159047fSniklas 
8162159047fSniklas /* Turn <<foo>> into @code{foo} in place at TOS*/
8172159047fSniklas 
818c074d1c9Sdrahn static void
do_fancy_stuff()819c074d1c9Sdrahn do_fancy_stuff ()
8202159047fSniklas {
8212159047fSniklas   unsigned int idx = 0;
8222159047fSniklas   string_type out;
8232159047fSniklas   init_string (&out);
8242159047fSniklas   while (at (tos, idx))
8252159047fSniklas     {
8262159047fSniklas       if (at (tos, idx) == '<'
8272159047fSniklas 	  && at (tos, idx + 1) == '<'
828b305b0f1Sespie 	  && !isspace ((unsigned char) at (tos, idx + 2)))
8292159047fSniklas 	{
830b55d4692Sfgsch 	  /* This qualifies as a << startup.  */
8312159047fSniklas 	  idx += 2;
8322159047fSniklas 	  cattext (&out, "@code{");
833b55d4692Sfgsch 	  while (at (tos, idx)
834b55d4692Sfgsch 		 && at (tos, idx) != '>' )
8352159047fSniklas 	    {
8362159047fSniklas 	      catchar (&out, at (tos, idx));
8372159047fSniklas 	      idx++;
8382159047fSniklas 
8392159047fSniklas 	    }
8402159047fSniklas 	  cattext (&out, "}");
8412159047fSniklas 	  idx += 2;
8422159047fSniklas 	}
8432159047fSniklas       else
8442159047fSniklas 	{
8452159047fSniklas 	  catchar (&out, at (tos, idx));
8462159047fSniklas 	  idx++;
8472159047fSniklas 	}
8482159047fSniklas     }
8492159047fSniklas   delete_string (tos);
8502159047fSniklas   *tos = out;
8512159047fSniklas   pc++;
8522159047fSniklas 
8532159047fSniklas }
854b55d4692Sfgsch 
855b55d4692Sfgsch /* A command is all upper case,and alone on a line.  */
856b55d4692Sfgsch 
8572159047fSniklas static int
iscommand(ptr,idx)858b55d4692Sfgsch iscommand (ptr, idx)
859b55d4692Sfgsch      string_type *ptr;
860b55d4692Sfgsch      unsigned int idx;
8612159047fSniklas {
8622159047fSniklas   unsigned int len = 0;
863b55d4692Sfgsch   while (at (ptr, idx))
864b55d4692Sfgsch     {
865b55d4692Sfgsch       if (isupper ((unsigned char) at (ptr, idx))
866b55d4692Sfgsch 	  || at (ptr, idx) == ' ' || at (ptr, idx) == '_')
8672159047fSniklas 	{
8682159047fSniklas 	  len++;
8692159047fSniklas 	  idx++;
8702159047fSniklas 	}
8712159047fSniklas       else if (at (ptr, idx) == '\n')
8722159047fSniklas 	{
873b55d4692Sfgsch 	  if (len > 3)
874b55d4692Sfgsch 	    return 1;
8752159047fSniklas 	  return 0;
8762159047fSniklas 	}
877b55d4692Sfgsch       else
878b55d4692Sfgsch 	return 0;
8792159047fSniklas     }
8802159047fSniklas   return 0;
8812159047fSniklas }
8822159047fSniklas 
883b305b0f1Sespie static int
copy_past_newline(ptr,idx,dst)884b55d4692Sfgsch copy_past_newline (ptr, idx, dst)
885b55d4692Sfgsch      string_type *ptr;
886b55d4692Sfgsch      unsigned int idx;
887b55d4692Sfgsch      string_type *dst;
8882159047fSniklas {
889b305b0f1Sespie   int column = 0;
890b305b0f1Sespie 
8912159047fSniklas   while (at (ptr, idx) && at (ptr, idx) != '\n')
8922159047fSniklas     {
893b305b0f1Sespie       if (at (ptr, idx) == '\t')
894b305b0f1Sespie 	{
895b305b0f1Sespie 	  /* Expand tabs.  Neither makeinfo nor TeX can cope well with
896b305b0f1Sespie 	     them.  */
897b305b0f1Sespie 	  do
898b305b0f1Sespie 	    catchar (dst, ' ');
899b305b0f1Sespie 	  while (++column & 7);
900b305b0f1Sespie 	}
901b305b0f1Sespie       else
902b305b0f1Sespie 	{
9032159047fSniklas 	  catchar (dst, at (ptr, idx));
904b305b0f1Sespie 	  column++;
905b305b0f1Sespie 	}
9062159047fSniklas       idx++;
9072159047fSniklas 
9082159047fSniklas     }
9092159047fSniklas   catchar (dst, at (ptr, idx));
9102159047fSniklas   idx++;
9112159047fSniklas   return idx;
9122159047fSniklas 
9132159047fSniklas }
9142159047fSniklas 
915c074d1c9Sdrahn static void
icopy_past_newline()916c074d1c9Sdrahn icopy_past_newline ()
9172159047fSniklas {
9182159047fSniklas   tos++;
9192159047fSniklas   check_range ();
9202159047fSniklas   init_string (tos);
9212159047fSniklas   idx = copy_past_newline (ptr, idx, tos);
9222159047fSniklas   pc++;
9232159047fSniklas }
9242159047fSniklas 
9252159047fSniklas /* indent
926b55d4692Sfgsch    Take the string at the top of the stack, do some prettying.  */
9272159047fSniklas 
928c074d1c9Sdrahn static void
kill_bogus_lines()929c074d1c9Sdrahn kill_bogus_lines ()
9302159047fSniklas {
9312159047fSniklas   int sl;
9322159047fSniklas 
9332159047fSniklas   int idx = 0;
9342159047fSniklas   int c;
9352159047fSniklas   int dot = 0;
9362159047fSniklas 
9372159047fSniklas   string_type out;
9382159047fSniklas   init_string (&out);
939b55d4692Sfgsch   /* Drop leading nl.  */
9402159047fSniklas   while (at (tos, idx) == '\n')
9412159047fSniklas     {
9422159047fSniklas       idx++;
9432159047fSniklas     }
9442159047fSniklas   c = idx;
9452159047fSniklas 
946b305b0f1Sespie   /* If the first char is a '.' prepend a newline so that it is
947b305b0f1Sespie      recognized properly later.  */
948b305b0f1Sespie   if (at (tos, idx) == '.')
949b305b0f1Sespie     catchar (&out, '\n');
950b305b0f1Sespie 
951b55d4692Sfgsch   /* Find the last char.  */
9522159047fSniklas   while (at (tos, idx))
9532159047fSniklas     {
9542159047fSniklas       idx++;
9552159047fSniklas     }
9562159047fSniklas 
957b55d4692Sfgsch   /* Find the last non white before the nl.  */
9582159047fSniklas   idx--;
9592159047fSniklas 
960b305b0f1Sespie   while (idx && isspace ((unsigned char) at (tos, idx)))
9612159047fSniklas     idx--;
9622159047fSniklas   idx++;
9632159047fSniklas 
9642159047fSniklas   /* Copy buffer upto last char, but blank lines before and after
965b55d4692Sfgsch      dots don't count.  */
9662159047fSniklas   sl = 1;
9672159047fSniklas 
9682159047fSniklas   while (c < idx)
9692159047fSniklas     {
9702159047fSniklas       if (at (tos, c) == '\n'
9712159047fSniklas 	  && at (tos, c + 1) == '\n'
9722159047fSniklas 	  && at (tos, c + 2) == '.')
9732159047fSniklas 	{
974b55d4692Sfgsch 	  /* Ignore two newlines before a dot.  */
9752159047fSniklas 	  c++;
9762159047fSniklas 	}
9772159047fSniklas       else if (at (tos, c) == '.' && sl)
9782159047fSniklas 	{
979b55d4692Sfgsch 	  /* remember that this line started with a dot.  */
9802159047fSniklas 	  dot = 2;
9812159047fSniklas 	}
9822159047fSniklas       else if (at (tos, c) == '\n'
9832159047fSniklas 	       && at (tos, c + 1) == '\n'
9842159047fSniklas 	       && dot)
9852159047fSniklas 	{
9862159047fSniklas 	  c++;
987b55d4692Sfgsch 	  /* Ignore two newlines when last line was dot.  */
9882159047fSniklas 	}
9892159047fSniklas 
9902159047fSniklas       catchar (&out, at (tos, c));
9912159047fSniklas       if (at (tos, c) == '\n')
9922159047fSniklas 	{
9932159047fSniklas 	  sl = 1;
9942159047fSniklas 
995b55d4692Sfgsch 	  if (dot == 2)
996b55d4692Sfgsch 	    dot = 1;
997b55d4692Sfgsch 	  else
998b55d4692Sfgsch 	    dot = 0;
9992159047fSniklas 	}
10004361b62eSniklas       else
10014361b62eSniklas 	sl = 0;
10022159047fSniklas 
10032159047fSniklas       c++;
10042159047fSniklas 
10052159047fSniklas     }
10062159047fSniklas 
1007b55d4692Sfgsch   /* Append nl.  */
10082159047fSniklas   catchar (&out, '\n');
10092159047fSniklas   pc++;
10102159047fSniklas   delete_string (tos);
10112159047fSniklas   *tos = out;
10122159047fSniklas 
10132159047fSniklas }
10142159047fSniklas 
1015c074d1c9Sdrahn static void
indent()1016c074d1c9Sdrahn indent ()
10172159047fSniklas {
10182159047fSniklas   string_type out;
10192159047fSniklas   int tab = 0;
10202159047fSniklas   int idx = 0;
10212159047fSniklas   int ol = 0;
10222159047fSniklas   init_string (&out);
1023b55d4692Sfgsch   while (at (tos, idx))
1024b55d4692Sfgsch     {
10252159047fSniklas       switch (at (tos, idx))
10262159047fSniklas 	{
10272159047fSniklas 	case '\n':
10282159047fSniklas 	  cattext (&out, "\n");
10292159047fSniklas 	  idx++;
1030b305b0f1Sespie 	  if (tab && at (tos, idx))
10312159047fSniklas 	    {
10322159047fSniklas 	      cattext (&out, "    ");
10332159047fSniklas 	    }
10342159047fSniklas 	  ol = 0;
10352159047fSniklas 	  break;
10362159047fSniklas 	case '(':
10372159047fSniklas 	  tab++;
10382159047fSniklas 	  if (ol == 0)
10392159047fSniklas 	    cattext (&out, "   ");
10402159047fSniklas 	  idx++;
10412159047fSniklas 	  cattext (&out, "(");
10422159047fSniklas 	  ol = 1;
10432159047fSniklas 	  break;
10442159047fSniklas 	case ')':
10452159047fSniklas 	  tab--;
10462159047fSniklas 	  cattext (&out, ")");
10472159047fSniklas 	  idx++;
10482159047fSniklas 	  ol = 1;
10492159047fSniklas 
10502159047fSniklas 	  break;
10512159047fSniklas 	default:
10522159047fSniklas 	  catchar (&out, at (tos, idx));
10532159047fSniklas 	  ol = 1;
10542159047fSniklas 
10552159047fSniklas 	  idx++;
10562159047fSniklas 	  break;
10572159047fSniklas 	}
10582159047fSniklas     }
10592159047fSniklas 
10602159047fSniklas   pc++;
10612159047fSniklas   delete_string (tos);
10622159047fSniklas   *tos = out;
10632159047fSniklas 
10642159047fSniklas }
10652159047fSniklas 
1066c074d1c9Sdrahn static void
get_stuff_in_command()1067c074d1c9Sdrahn get_stuff_in_command ()
10682159047fSniklas {
10692159047fSniklas   tos++;
10702159047fSniklas   check_range ();
10712159047fSniklas   init_string (tos);
10722159047fSniklas 
1073b55d4692Sfgsch   while (at (ptr, idx))
1074b55d4692Sfgsch     {
1075b55d4692Sfgsch       if (iscommand (ptr, idx))
1076b55d4692Sfgsch 	break;
10772159047fSniklas       idx = copy_past_newline (ptr, idx, tos);
10782159047fSniklas     }
10792159047fSniklas   pc++;
10802159047fSniklas }
10812159047fSniklas 
1082c074d1c9Sdrahn static void
swap()1083c074d1c9Sdrahn swap ()
10842159047fSniklas {
10852159047fSniklas   string_type t;
10862159047fSniklas 
10872159047fSniklas   t = tos[0];
10882159047fSniklas   tos[0] = tos[-1];
10892159047fSniklas   tos[-1] = t;
10902159047fSniklas   pc++;
10912159047fSniklas }
10922159047fSniklas 
1093c074d1c9Sdrahn static void
other_dup()1094c074d1c9Sdrahn other_dup ()
10952159047fSniklas {
10962159047fSniklas   tos++;
10972159047fSniklas   check_range ();
10982159047fSniklas   init_string (tos);
10992159047fSniklas   catstr (tos, tos - 1);
11002159047fSniklas   pc++;
11012159047fSniklas }
11022159047fSniklas 
1103c074d1c9Sdrahn static void
drop()1104c074d1c9Sdrahn drop ()
11052159047fSniklas {
11062159047fSniklas   tos--;
11072159047fSniklas   check_range ();
11082159047fSniklas   pc++;
11092159047fSniklas }
11102159047fSniklas 
1111c074d1c9Sdrahn static void
idrop()1112c074d1c9Sdrahn idrop ()
11132159047fSniklas {
11142159047fSniklas   isp--;
11152159047fSniklas   icheck_range ();
11162159047fSniklas   pc++;
11172159047fSniklas }
11182159047fSniklas 
1119c074d1c9Sdrahn static void
icatstr()1120c074d1c9Sdrahn icatstr ()
11212159047fSniklas {
11222159047fSniklas   tos--;
11232159047fSniklas   check_range ();
11242159047fSniklas   catstr (tos, tos + 1);
11252159047fSniklas   delete_string (tos + 1);
11262159047fSniklas   pc++;
11272159047fSniklas }
11282159047fSniklas 
1129c074d1c9Sdrahn static void
skip_past_newline()1130c074d1c9Sdrahn skip_past_newline ()
11312159047fSniklas {
11322159047fSniklas   while (at (ptr, idx)
11332159047fSniklas 	 && at (ptr, idx) != '\n')
11342159047fSniklas     idx++;
11352159047fSniklas   idx++;
11362159047fSniklas   pc++;
11372159047fSniklas }
11382159047fSniklas 
1139c074d1c9Sdrahn static void
internalmode()1140c074d1c9Sdrahn internalmode ()
11412159047fSniklas {
11422159047fSniklas   internal_mode = *(isp);
11432159047fSniklas   isp--;
11442159047fSniklas   icheck_range ();
11452159047fSniklas   pc++;
11462159047fSniklas }
11472159047fSniklas 
1148c074d1c9Sdrahn static void
maybecatstr()1149c074d1c9Sdrahn maybecatstr ()
11502159047fSniklas {
11512159047fSniklas   if (internal_wanted == internal_mode)
11522159047fSniklas     {
11532159047fSniklas       catstr (tos - 1, tos);
11542159047fSniklas     }
11552159047fSniklas   delete_string (tos);
11562159047fSniklas   tos--;
11572159047fSniklas   check_range ();
11582159047fSniklas   pc++;
11592159047fSniklas }
11602159047fSniklas 
11612159047fSniklas char *
nextword(string,word)1162b55d4692Sfgsch nextword (string, word)
1163b55d4692Sfgsch      char *string;
1164b55d4692Sfgsch      char **word;
11652159047fSniklas {
11662159047fSniklas   char *word_start;
11672159047fSniklas   int idx;
11682159047fSniklas   char *dst;
11692159047fSniklas   char *src;
11702159047fSniklas 
11712159047fSniklas   int length = 0;
11722159047fSniklas 
1173b55d4692Sfgsch   while (isspace ((unsigned char) *string) || *string == '-')
1174b55d4692Sfgsch     {
11752159047fSniklas       if (*string == '-')
11762159047fSniklas 	{
11772159047fSniklas 	  while (*string && *string != '\n')
11782159047fSniklas 	    string++;
11792159047fSniklas 
11802159047fSniklas 	}
1181b55d4692Sfgsch       else
1182b55d4692Sfgsch 	{
11832159047fSniklas 	  string++;
11842159047fSniklas 	}
11852159047fSniklas     }
1186b55d4692Sfgsch   if (!*string)
1187b55d4692Sfgsch     return 0;
11882159047fSniklas 
11892159047fSniklas   word_start = string;
11902159047fSniklas   if (*string == '"')
11912159047fSniklas     {
11922159047fSniklas       do
11932159047fSniklas 	{
11942159047fSniklas 	  string++;
11952159047fSniklas 	  length++;
11962159047fSniklas 	  if (*string == '\\')
11972159047fSniklas 	    {
11982159047fSniklas 	      string += 2;
11992159047fSniklas 	      length += 2;
12002159047fSniklas 	    }
12012159047fSniklas 	}
12022159047fSniklas       while (*string != '"');
12032159047fSniklas     }
12042159047fSniklas   else
12052159047fSniklas     {
1206b305b0f1Sespie       while (!isspace ((unsigned char) *string))
12072159047fSniklas 	{
12082159047fSniklas 	  string++;
12092159047fSniklas 	  length++;
12102159047fSniklas 
12112159047fSniklas 	}
12122159047fSniklas     }
12132159047fSniklas 
12142159047fSniklas   *word = malloc (length + 1);
12152159047fSniklas 
12162159047fSniklas   dst = *word;
12172159047fSniklas   src = word_start;
12182159047fSniklas 
12192159047fSniklas   for (idx = 0; idx < length; idx++)
12202159047fSniklas     {
12212159047fSniklas       if (src[idx] == '\\')
12222159047fSniklas 	switch (src[idx + 1])
12232159047fSniklas 	  {
12242159047fSniklas 	  case 'n':
12252159047fSniklas 	    *dst++ = '\n';
12262159047fSniklas 	    idx++;
12272159047fSniklas 	    break;
12282159047fSniklas 	  case '"':
12292159047fSniklas 	  case '\\':
12302159047fSniklas 	    *dst++ = src[idx + 1];
12312159047fSniklas 	    idx++;
12322159047fSniklas 	    break;
12332159047fSniklas 	  default:
12342159047fSniklas 	    *dst++ = '\\';
12352159047fSniklas 	    break;
12362159047fSniklas 	  }
12372159047fSniklas       else
12382159047fSniklas 	*dst++ = src[idx];
12392159047fSniklas     }
12402159047fSniklas   *dst++ = 0;
12412159047fSniklas 
12422159047fSniklas   if (*string)
12432159047fSniklas     return string + 1;
12442159047fSniklas   else
12452159047fSniklas     return 0;
12462159047fSniklas }
1247b55d4692Sfgsch 
12482159047fSniklas dict_type *root;
1249b55d4692Sfgsch 
12502159047fSniklas dict_type *
lookup_word(word)1251b55d4692Sfgsch lookup_word (word)
1252b55d4692Sfgsch      char *word;
12532159047fSniklas {
12542159047fSniklas   dict_type *ptr = root;
1255b55d4692Sfgsch   while (ptr)
1256b55d4692Sfgsch     {
1257b55d4692Sfgsch       if (strcmp (ptr->word, word) == 0)
1258b55d4692Sfgsch 	return ptr;
12592159047fSniklas       ptr = ptr->next;
12602159047fSniklas     }
12612159047fSniklas   if (warning)
12622159047fSniklas     fprintf (stderr, "Can't find %s\n", word);
12632159047fSniklas   return 0;
12642159047fSniklas }
12652159047fSniklas 
1266b55d4692Sfgsch static void
perform()1267c074d1c9Sdrahn perform ()
12682159047fSniklas {
12692159047fSniklas   tos = stack;
12702159047fSniklas 
1271b55d4692Sfgsch   while (at (ptr, idx))
1272b55d4692Sfgsch     {
1273b55d4692Sfgsch       /* It's worth looking through the command list.  */
12742159047fSniklas       if (iscommand (ptr, idx))
12752159047fSniklas 	{
12762159047fSniklas 	  char *next;
12772159047fSniklas 	  dict_type *word;
12782159047fSniklas 
12792159047fSniklas 	  (void) nextword (addr (ptr, idx), &next);
12802159047fSniklas 
12812159047fSniklas 	  word = lookup_word (next);
12822159047fSniklas 
12832159047fSniklas 	  if (word)
12842159047fSniklas 	    {
12852159047fSniklas 	      exec (word);
12862159047fSniklas 	    }
12872159047fSniklas 	  else
12882159047fSniklas 	    {
12892159047fSniklas 	      if (warning)
12902159047fSniklas 		fprintf (stderr, "warning, %s is not recognised\n", next);
12912159047fSniklas 	      skip_past_newline ();
12922159047fSniklas 	    }
12932159047fSniklas 
12942159047fSniklas 	}
1295b55d4692Sfgsch       else
1296b55d4692Sfgsch 	skip_past_newline ();
12972159047fSniklas     }
12982159047fSniklas }
12992159047fSniklas 
13002159047fSniklas dict_type *
newentry(word)1301b55d4692Sfgsch newentry (word)
1302b55d4692Sfgsch      char *word;
13032159047fSniklas {
13042159047fSniklas   dict_type *new = (dict_type *) malloc (sizeof (dict_type));
13052159047fSniklas   new->word = word;
13062159047fSniklas   new->next = root;
13072159047fSniklas   root = new;
13082159047fSniklas   new->code = (stinst_type *) malloc (sizeof (stinst_type));
13092159047fSniklas   new->code_length = 1;
13102159047fSniklas   new->code_end = 0;
13112159047fSniklas   return new;
13122159047fSniklas }
13132159047fSniklas 
13142159047fSniklas unsigned int
add_to_definition(entry,word)1315b55d4692Sfgsch add_to_definition (entry, word)
1316b55d4692Sfgsch      dict_type *entry;
1317b55d4692Sfgsch      stinst_type word;
13182159047fSniklas {
13192159047fSniklas   if (entry->code_end == entry->code_length)
13202159047fSniklas     {
13212159047fSniklas       entry->code_length += 2;
13222159047fSniklas       entry->code =
13232159047fSniklas 	(stinst_type *) realloc ((char *) (entry->code),
13242159047fSniklas 				 entry->code_length * sizeof (word_type));
13252159047fSniklas     }
13262159047fSniklas   entry->code[entry->code_end] = word;
13272159047fSniklas 
13282159047fSniklas   return entry->code_end++;
13292159047fSniklas }
13302159047fSniklas 
13312159047fSniklas void
add_intrinsic(name,func)1332b55d4692Sfgsch add_intrinsic (name, func)
1333b55d4692Sfgsch      char *name;
1334b55d4692Sfgsch      void (*func) ();
13352159047fSniklas {
13362159047fSniklas   dict_type *new = newentry (name);
13372159047fSniklas   add_to_definition (new, func);
13382159047fSniklas   add_to_definition (new, 0);
13392159047fSniklas }
13402159047fSniklas 
13412159047fSniklas void
add_var(name)1342b55d4692Sfgsch add_var (name)
1343b55d4692Sfgsch      char *name;
13442159047fSniklas {
13452159047fSniklas   dict_type *new = newentry (name);
13462159047fSniklas   add_to_definition (new, push_number);
13472159047fSniklas   add_to_definition (new, (stinst_type) (&(new->var)));
13482159047fSniklas   add_to_definition (new, 0);
13492159047fSniklas }
13502159047fSniklas 
13512159047fSniklas void
compile(string)1352b55d4692Sfgsch compile (string)
1353b55d4692Sfgsch      char *string;
13542159047fSniklas {
1355b55d4692Sfgsch   /* Add words to the dictionary.  */
13562159047fSniklas   char *word;
13572159047fSniklas   string = nextword (string, &word);
13582159047fSniklas   while (string && *string && word[0])
13592159047fSniklas     {
13602159047fSniklas       if (strcmp (word, "var") == 0)
13612159047fSniklas 	{
13622159047fSniklas 	  string = nextword (string, &word);
13632159047fSniklas 
13642159047fSniklas 	  add_var (word);
13652159047fSniklas 	  string = nextword (string, &word);
13662159047fSniklas 	}
1367b55d4692Sfgsch       else if (word[0] == ':')
13682159047fSniklas 	{
13692159047fSniklas 	  dict_type *ptr;
1370b55d4692Sfgsch 	  /* Compile a word and add to dictionary.  */
13712159047fSniklas 	  string = nextword (string, &word);
13722159047fSniklas 
13732159047fSniklas 	  ptr = newentry (word);
13742159047fSniklas 	  string = nextword (string, &word);
13752159047fSniklas 	  while (word[0] != ';')
13762159047fSniklas 	    {
13772159047fSniklas 	      switch (word[0])
13782159047fSniklas 		{
13792159047fSniklas 		case '"':
13802159047fSniklas 		  /* got a string, embed magic push string
13812159047fSniklas 		     function */
13822159047fSniklas 		  add_to_definition (ptr, push_text);
13832159047fSniklas 		  add_to_definition (ptr, (stinst_type) (word + 1));
13842159047fSniklas 		  break;
13852159047fSniklas 		case '0':
13862159047fSniklas 		case '1':
13872159047fSniklas 		case '2':
13882159047fSniklas 		case '3':
13892159047fSniklas 		case '4':
13902159047fSniklas 		case '5':
13912159047fSniklas 		case '6':
13922159047fSniklas 		case '7':
13932159047fSniklas 		case '8':
13942159047fSniklas 		case '9':
13952159047fSniklas 		  /* Got a number, embedd the magic push number
13962159047fSniklas 		     function */
13972159047fSniklas 		  add_to_definition (ptr, push_number);
13982159047fSniklas 		  add_to_definition (ptr, (stinst_type) atol (word));
13992159047fSniklas 		  break;
14002159047fSniklas 		default:
14012159047fSniklas 		  add_to_definition (ptr, call);
14022159047fSniklas 		  add_to_definition (ptr, (stinst_type) lookup_word (word));
14032159047fSniklas 		}
14042159047fSniklas 
14052159047fSniklas 	      string = nextword (string, &word);
14062159047fSniklas 	    }
14072159047fSniklas 	  add_to_definition (ptr, 0);
14082159047fSniklas 	  string = nextword (string, &word);
14092159047fSniklas 	}
14102159047fSniklas       else
14112159047fSniklas 	{
14122159047fSniklas 	  fprintf (stderr, "syntax error at %s\n", string - 1);
14132159047fSniklas 	}
14142159047fSniklas     }
14152159047fSniklas }
14162159047fSniklas 
1417b55d4692Sfgsch static void
bang()1418c074d1c9Sdrahn bang ()
14192159047fSniklas {
14202159047fSniklas   *(long *) ((isp[0])) = isp[-1];
14212159047fSniklas   isp -= 2;
14222159047fSniklas   icheck_range ();
14232159047fSniklas   pc++;
14242159047fSniklas }
14252159047fSniklas 
1426c074d1c9Sdrahn static void
atsign()1427c074d1c9Sdrahn atsign ()
14282159047fSniklas {
14292159047fSniklas   isp[0] = *(long *) (isp[0]);
14302159047fSniklas   pc++;
14312159047fSniklas }
14322159047fSniklas 
1433c074d1c9Sdrahn static void
hello()1434c074d1c9Sdrahn hello ()
14352159047fSniklas {
14362159047fSniklas   printf ("hello\n");
14372159047fSniklas   pc++;
14382159047fSniklas }
14392159047fSniklas 
1440c074d1c9Sdrahn static void
stdout_()1441c074d1c9Sdrahn stdout_ ()
14422159047fSniklas {
14432159047fSniklas   isp++;
14442159047fSniklas   icheck_range ();
14452159047fSniklas   *isp = 1;
14462159047fSniklas   pc++;
14472159047fSniklas }
14482159047fSniklas 
1449c074d1c9Sdrahn static void
stderr_()1450c074d1c9Sdrahn stderr_ ()
14512159047fSniklas {
14522159047fSniklas   isp++;
14532159047fSniklas   icheck_range ();
14542159047fSniklas   *isp = 2;
14552159047fSniklas   pc++;
14562159047fSniklas }
14572159047fSniklas 
1458c074d1c9Sdrahn static void
print()1459c074d1c9Sdrahn print ()
14602159047fSniklas {
14612159047fSniklas   if (*isp == 1)
14622159047fSniklas     write_buffer (tos, stdout);
14632159047fSniklas   else if (*isp == 2)
14642159047fSniklas     write_buffer (tos, stderr);
14652159047fSniklas   else
1466b305b0f1Sespie     fprintf (stderr, "print: illegal print destination `%ld'\n", *isp);
14672159047fSniklas   isp--;
14682159047fSniklas   tos--;
14692159047fSniklas   icheck_range ();
14702159047fSniklas   check_range ();
14712159047fSniklas   pc++;
14722159047fSniklas }
14732159047fSniklas 
1474b55d4692Sfgsch static void
read_in(str,file)1475b55d4692Sfgsch read_in (str, file)
1476b55d4692Sfgsch      string_type *str;
1477b55d4692Sfgsch      FILE *file;
14782159047fSniklas {
14792159047fSniklas   char buff[10000];
14802159047fSniklas   unsigned int r;
14812159047fSniklas   do
14822159047fSniklas     {
14832159047fSniklas       r = fread (buff, 1, sizeof (buff), file);
14842159047fSniklas       catbuf (str, buff, r);
14852159047fSniklas     }
14862159047fSniklas   while (r);
14872159047fSniklas   buff[0] = 0;
14882159047fSniklas 
14892159047fSniklas   catbuf (str, buff, 1);
14902159047fSniklas }
14912159047fSniklas 
1492b55d4692Sfgsch static void
usage()1493c074d1c9Sdrahn usage ()
14942159047fSniklas {
14952159047fSniklas   fprintf (stderr, "usage: -[d|i|g] <file >file\n");
14962159047fSniklas   exit (33);
14972159047fSniklas }
14982159047fSniklas 
14992159047fSniklas /* There is no reliable way to declare exit.  Sometimes it returns
15002159047fSniklas    int, and sometimes it returns void.  Sometimes it changes between
15012159047fSniklas    OS releases.  Trying to get it declared correctly in the hosts file
15022159047fSniklas    is a pointless waste of time.  */
15032159047fSniklas 
15042159047fSniklas static void
chew_exit()15052159047fSniklas chew_exit ()
15062159047fSniklas {
15072159047fSniklas   exit (0);
15082159047fSniklas }
15092159047fSniklas 
1510b55d4692Sfgsch int
main(ac,av)1511b55d4692Sfgsch main (ac, av)
1512b55d4692Sfgsch      int ac;
1513b55d4692Sfgsch      char *av[];
15142159047fSniklas {
15152159047fSniklas   unsigned int i;
15162159047fSniklas   string_type buffer;
15172159047fSniklas   string_type pptr;
15182159047fSniklas 
15192159047fSniklas   init_string (&buffer);
15202159047fSniklas   init_string (&pptr);
15212159047fSniklas   init_string (stack + 0);
15222159047fSniklas   tos = stack + 1;
15232159047fSniklas   ptr = &pptr;
15242159047fSniklas 
15252159047fSniklas   add_intrinsic ("push_text", push_text);
15262159047fSniklas   add_intrinsic ("!", bang);
15272159047fSniklas   add_intrinsic ("@", atsign);
15282159047fSniklas   add_intrinsic ("hello", hello);
15292159047fSniklas   add_intrinsic ("stdout", stdout_);
15302159047fSniklas   add_intrinsic ("stderr", stderr_);
15312159047fSniklas   add_intrinsic ("print", print);
15322159047fSniklas   add_intrinsic ("skip_past_newline", skip_past_newline);
15332159047fSniklas   add_intrinsic ("catstr", icatstr);
15342159047fSniklas   add_intrinsic ("copy_past_newline", icopy_past_newline);
15352159047fSniklas   add_intrinsic ("dup", other_dup);
15362159047fSniklas   add_intrinsic ("drop", drop);
15372159047fSniklas   add_intrinsic ("idrop", idrop);
15382159047fSniklas   add_intrinsic ("remchar", remchar);
15392159047fSniklas   add_intrinsic ("get_stuff_in_command", get_stuff_in_command);
15402159047fSniklas   add_intrinsic ("do_fancy_stuff", do_fancy_stuff);
15412159047fSniklas   add_intrinsic ("bulletize", bulletize);
15422159047fSniklas   add_intrinsic ("courierize", courierize);
15432159047fSniklas   /* If the following line gives an error, exit() is not declared in the
15442159047fSniklas      ../hosts/foo.h file for this host.  Fix it there, not here!  */
15452159047fSniklas   /* No, don't fix it anywhere; see comment on chew_exit--Ian Taylor.  */
15462159047fSniklas   add_intrinsic ("exit", chew_exit);
15472159047fSniklas   add_intrinsic ("swap", swap);
15482159047fSniklas   add_intrinsic ("outputdots", outputdots);
15492159047fSniklas   add_intrinsic ("paramstuff", paramstuff);
15502159047fSniklas   add_intrinsic ("maybecatstr", maybecatstr);
15512159047fSniklas   add_intrinsic ("translatecomments", translatecomments);
15522159047fSniklas   add_intrinsic ("kill_bogus_lines", kill_bogus_lines);
15532159047fSniklas   add_intrinsic ("indent", indent);
15542159047fSniklas   add_intrinsic ("internalmode", internalmode);
15552159047fSniklas   add_intrinsic ("print_stack_level", print_stack_level);
15562159047fSniklas   add_intrinsic ("strip_trailing_newlines", strip_trailing_newlines);
15572159047fSniklas 
1558b55d4692Sfgsch   /* Put a nl at the start.  */
15592159047fSniklas   catchar (&buffer, '\n');
15602159047fSniklas 
15612159047fSniklas   read_in (&buffer, stdin);
15622159047fSniklas   remove_noncomments (&buffer, ptr);
1563b305b0f1Sespie   for (i = 1; i < (unsigned int) ac; i++)
15642159047fSniklas     {
15652159047fSniklas       if (av[i][0] == '-')
15662159047fSniklas 	{
15672159047fSniklas 	  if (av[i][1] == 'f')
15682159047fSniklas 	    {
15692159047fSniklas 	      string_type b;
15702159047fSniklas 	      FILE *f;
15712159047fSniklas 	      init_string (&b);
15722159047fSniklas 
15732159047fSniklas 	      f = fopen (av[i + 1], "r");
15742159047fSniklas 	      if (!f)
15752159047fSniklas 		{
1576b55d4692Sfgsch 		  fprintf (stderr, "Can't open the input file %s\n",
1577b55d4692Sfgsch 			   av[i + 1]);
15782159047fSniklas 		  return 33;
15792159047fSniklas 		}
15802159047fSniklas 
15812159047fSniklas 	      read_in (&b, f);
15822159047fSniklas 	      compile (b.ptr);
15832159047fSniklas 	      perform ();
15842159047fSniklas 	    }
15852159047fSniklas 	  else if (av[i][1] == 'i')
15862159047fSniklas 	    {
15872159047fSniklas 	      internal_wanted = 1;
15882159047fSniklas 	    }
15892159047fSniklas 	  else if (av[i][1] == 'w')
15902159047fSniklas 	    {
15912159047fSniklas 	      warning = 1;
15922159047fSniklas 	    }
1593b305b0f1Sespie 	  else
1594b305b0f1Sespie 	    usage ();
15952159047fSniklas 	}
15962159047fSniklas     }
15972159047fSniklas   write_buffer (stack + 0, stdout);
15982159047fSniklas   if (tos != stack)
15992159047fSniklas     {
1600b55d4692Sfgsch       fprintf (stderr, "finishing with current stack level %d\n",
1601b55d4692Sfgsch 	       tos - stack);
16022159047fSniklas       return 1;
16032159047fSniklas     }
16042159047fSniklas   return 0;
16052159047fSniklas }
1606