xref: /netbsd-src/external/gpl3/binutils.old/dist/bfd/doc/chew.c (revision e992f068c547fd6e84b3f104dc2340adcc955732)
175fd0b74Schristos /* chew
2*e992f068Schristos    Copyright (C) 1990-2022 Free Software Foundation, Inc.
375fd0b74Schristos    Contributed by steve chamberlain @cygnus
475fd0b74Schristos 
575fd0b74Schristos    This file is part of BFD, the Binary File Descriptor library.
675fd0b74Schristos 
775fd0b74Schristos    This program is free software; you can redistribute it and/or modify
875fd0b74Schristos    it under the terms of the GNU General Public License as published by
975fd0b74Schristos    the Free Software Foundation; either version 3 of the License, or
1075fd0b74Schristos    (at your option) any later version.
1175fd0b74Schristos 
1275fd0b74Schristos    This program is distributed in the hope that it will be useful,
1375fd0b74Schristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
1475fd0b74Schristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1575fd0b74Schristos    GNU General Public License for more details.
1675fd0b74Schristos 
1775fd0b74Schristos    You should have received a copy of the GNU General Public License
1875fd0b74Schristos    along with this program; if not, write to the Free Software
1975fd0b74Schristos    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
2075fd0b74Schristos    MA 02110-1301, USA.  */
2175fd0b74Schristos 
2275fd0b74Schristos /* Yet another way of extracting documentation from source.
2375fd0b74Schristos    No, I haven't finished it yet, but I hope you people like it better
2475fd0b74Schristos    than the old way
2575fd0b74Schristos 
2675fd0b74Schristos    sac
2775fd0b74Schristos 
2875fd0b74Schristos    Basically, this is a sort of string forth, maybe we should call it
2975fd0b74Schristos    struth?
3075fd0b74Schristos 
3175fd0b74Schristos    You define new words thus:
3275fd0b74Schristos    : <newword> <oldwords> ;
3375fd0b74Schristos 
3475fd0b74Schristos */
3575fd0b74Schristos 
3675fd0b74Schristos /* Primitives provided by the program:
3775fd0b74Schristos 
3875fd0b74Schristos    Two stacks are provided, a string stack and an integer stack.
3975fd0b74Schristos 
4075fd0b74Schristos    Internal state variables:
4175fd0b74Schristos 	internal_wanted - indicates whether `-i' was passed
4275fd0b74Schristos 	internal_mode - user-settable
4375fd0b74Schristos 
4475fd0b74Schristos    Commands:
4575fd0b74Schristos 	push_text
4675fd0b74Schristos 	! - pop top of integer stack for address, pop next for value; store
4775fd0b74Schristos 	@ - treat value on integer stack as the address of an integer; push
4875fd0b74Schristos 		that integer on the integer stack after popping the "address"
4975fd0b74Schristos 	hello - print "hello\n" to stdout
5075fd0b74Schristos 	stdout - put stdout marker on TOS
5175fd0b74Schristos 	stderr - put stderr marker on TOS
5275fd0b74Schristos 	print - print TOS-1 on TOS (eg: "hello\n" stdout print)
5375fd0b74Schristos 	skip_past_newline
5475fd0b74Schristos 	catstr - fn icatstr
5575fd0b74Schristos 	copy_past_newline - append input, up to and including newline into TOS
5675fd0b74Schristos 	dup - fn other_dup
5775fd0b74Schristos 	drop - discard TOS
5875fd0b74Schristos 	idrop - ditto
5975fd0b74Schristos 	remchar - delete last character from TOS
6075fd0b74Schristos 	get_stuff_in_command
6175fd0b74Schristos 	do_fancy_stuff - translate <<foo>> to @code{foo} in TOS
6275fd0b74Schristos 	bulletize - if "o" lines found, prepend @itemize @bullet to TOS
6375fd0b74Schristos 		and @item to each "o" line; append @end itemize
6475fd0b74Schristos 	courierize - put @example around . and | lines, translate {* *} { }
6575fd0b74Schristos 	exit - fn chew_exit
6675fd0b74Schristos 	swap
6775fd0b74Schristos 	outputdots - strip out lines without leading dots
6875fd0b74Schristos 	paramstuff - convert full declaration into "PARAMS" form if not already
6975fd0b74Schristos 	maybecatstr - do catstr if internal_mode == internal_wanted, discard
7075fd0b74Schristos 		value in any case
7175fd0b74Schristos 	translatecomments - turn {* and *} into comment delimiters
7275fd0b74Schristos 	kill_bogus_lines - get rid of extra newlines
7375fd0b74Schristos 	indent
7475fd0b74Schristos 	internalmode - pop from integer stack, set `internalmode' to that value
7575fd0b74Schristos 	print_stack_level - print current stack depth to stderr
7675fd0b74Schristos 	strip_trailing_newlines - go ahead, guess...
7775fd0b74Schristos 	[quoted string] - push string onto string stack
7875fd0b74Schristos 	[word starting with digit] - push atol(str) onto integer stack
7975fd0b74Schristos 
8075fd0b74Schristos    A command must be all upper-case, and alone on a line.
8175fd0b74Schristos 
8275fd0b74Schristos    Foo.  */
8375fd0b74Schristos 
8475fd0b74Schristos #include <assert.h>
8575fd0b74Schristos #include <stdio.h>
8675fd0b74Schristos #include <ctype.h>
8775fd0b74Schristos #include <stdlib.h>
8875fd0b74Schristos #include <string.h>
8975fd0b74Schristos 
9075fd0b74Schristos #define DEF_SIZE 5000
9175fd0b74Schristos #define STACK 50
9275fd0b74Schristos 
9375fd0b74Schristos /* Here is a string type ...  */
9475fd0b74Schristos 
9575fd0b74Schristos typedef struct buffer
9675fd0b74Schristos {
9775fd0b74Schristos   char *ptr;
9875fd0b74Schristos   unsigned long write_idx;
9975fd0b74Schristos   unsigned long size;
10075fd0b74Schristos } string_type;
10175fd0b74Schristos 
102*e992f068Schristos /* Compiled programs consist of arrays of these.  */
103*e992f068Schristos 
104*e992f068Schristos typedef union
105*e992f068Schristos {
106*e992f068Schristos   void (*f) (void);
107*e992f068Schristos   struct dict_struct *e;
108*e992f068Schristos   char *s;
109*e992f068Schristos   long l;
110*e992f068Schristos } pcu;
111*e992f068Schristos 
112*e992f068Schristos typedef struct dict_struct
113*e992f068Schristos {
114*e992f068Schristos   char *word;
115*e992f068Schristos   struct dict_struct *next;
116*e992f068Schristos   pcu *code;
117*e992f068Schristos   int code_length;
118*e992f068Schristos   int code_end;
119*e992f068Schristos } dict_type;
120*e992f068Schristos 
121*e992f068Schristos int internal_wanted;
122*e992f068Schristos int internal_mode;
123*e992f068Schristos 
124*e992f068Schristos int warning;
125*e992f068Schristos 
126*e992f068Schristos string_type stack[STACK];
127*e992f068Schristos string_type *tos;
128*e992f068Schristos 
129*e992f068Schristos unsigned int idx = 0; /* Pos in input buffer */
130*e992f068Schristos string_type *ptr; /* and the buffer */
131*e992f068Schristos 
132*e992f068Schristos long istack[STACK];
133*e992f068Schristos long *isp = &istack[0];
134*e992f068Schristos 
135*e992f068Schristos dict_type *root;
136*e992f068Schristos 
137*e992f068Schristos pcu *pc;
13875fd0b74Schristos 
13975fd0b74Schristos static void
die(char * msg)140*e992f068Schristos die (char *msg)
14175fd0b74Schristos {
142*e992f068Schristos   fprintf (stderr, "%s\n", msg);
143*e992f068Schristos   exit (1);
144*e992f068Schristos }
145*e992f068Schristos 
146*e992f068Schristos void *
xmalloc(size_t size)147*e992f068Schristos xmalloc (size_t size)
148*e992f068Schristos {
149*e992f068Schristos   void *newmem;
150*e992f068Schristos 
151*e992f068Schristos   if (size == 0)
152*e992f068Schristos     size = 1;
153*e992f068Schristos   newmem = malloc (size);
154*e992f068Schristos   if (!newmem)
155*e992f068Schristos     die ("out of memory");
156*e992f068Schristos 
157*e992f068Schristos   return newmem;
158*e992f068Schristos }
159*e992f068Schristos 
160*e992f068Schristos void *
xrealloc(void * oldmem,size_t size)161*e992f068Schristos xrealloc (void *oldmem, size_t size)
162*e992f068Schristos {
163*e992f068Schristos   void *newmem;
164*e992f068Schristos 
165*e992f068Schristos   if (size == 0)
166*e992f068Schristos     size = 1;
167*e992f068Schristos   if (!oldmem)
168*e992f068Schristos     newmem = malloc (size);
169*e992f068Schristos   else
170*e992f068Schristos     newmem = realloc (oldmem, size);
171*e992f068Schristos   if (!newmem)
172*e992f068Schristos     die ("out of memory");
173*e992f068Schristos 
174*e992f068Schristos   return newmem;
175*e992f068Schristos }
176*e992f068Schristos 
177*e992f068Schristos char *
xstrdup(const char * s)178*e992f068Schristos xstrdup (const char *s)
179*e992f068Schristos {
180*e992f068Schristos   size_t len = strlen (s) + 1;
181*e992f068Schristos   char *ret = xmalloc (len);
182*e992f068Schristos   return memcpy (ret, s, len);
18375fd0b74Schristos }
18475fd0b74Schristos 
18575fd0b74Schristos static void
init_string_with_size(string_type * buffer,unsigned int size)186*e992f068Schristos init_string_with_size (string_type *buffer, unsigned int size)
187*e992f068Schristos {
188*e992f068Schristos   buffer->write_idx = 0;
189*e992f068Schristos   buffer->size = size;
190*e992f068Schristos   buffer->ptr = xmalloc (size);
191*e992f068Schristos }
192*e992f068Schristos 
193*e992f068Schristos static void
init_string(string_type * buffer)194*e992f068Schristos init_string (string_type *buffer)
19575fd0b74Schristos {
19675fd0b74Schristos   init_string_with_size (buffer, DEF_SIZE);
19775fd0b74Schristos }
19875fd0b74Schristos 
19975fd0b74Schristos static int
find(string_type * str,char * what)200*e992f068Schristos find (string_type *str, char *what)
20175fd0b74Schristos {
20275fd0b74Schristos   unsigned int i;
20375fd0b74Schristos   char *p;
20475fd0b74Schristos   p = what;
20575fd0b74Schristos   for (i = 0; i < str->write_idx && *p; i++)
20675fd0b74Schristos     {
20775fd0b74Schristos       if (*p == str->ptr[i])
20875fd0b74Schristos 	p++;
20975fd0b74Schristos       else
21075fd0b74Schristos 	p = what;
21175fd0b74Schristos     }
21275fd0b74Schristos   return (*p == 0);
21375fd0b74Schristos }
21475fd0b74Schristos 
21575fd0b74Schristos static void
write_buffer(string_type * buffer,FILE * f)216*e992f068Schristos write_buffer (string_type *buffer, FILE *f)
21775fd0b74Schristos {
21875fd0b74Schristos   if (buffer->write_idx != 0
21975fd0b74Schristos       && fwrite (buffer->ptr, buffer->write_idx, 1, f) != 1)
22075fd0b74Schristos     die ("cannot write output");
22175fd0b74Schristos }
22275fd0b74Schristos 
22375fd0b74Schristos static void
delete_string(string_type * buffer)224*e992f068Schristos delete_string (string_type *buffer)
22575fd0b74Schristos {
22675fd0b74Schristos   free (buffer->ptr);
227ede78133Schristos   buffer->ptr = NULL;
22875fd0b74Schristos }
22975fd0b74Schristos 
23075fd0b74Schristos static char *
addr(string_type * buffer,unsigned int idx)231*e992f068Schristos addr (string_type *buffer, unsigned int idx)
23275fd0b74Schristos {
23375fd0b74Schristos   return buffer->ptr + idx;
23475fd0b74Schristos }
23575fd0b74Schristos 
23675fd0b74Schristos static char
at(string_type * buffer,unsigned int pos)237*e992f068Schristos at (string_type *buffer, unsigned int pos)
23875fd0b74Schristos {
23975fd0b74Schristos   if (pos >= buffer->write_idx)
24075fd0b74Schristos     return 0;
24175fd0b74Schristos   return buffer->ptr[pos];
24275fd0b74Schristos }
24375fd0b74Schristos 
24475fd0b74Schristos static void
catchar(string_type * buffer,int ch)245*e992f068Schristos catchar (string_type *buffer, int ch)
24675fd0b74Schristos {
24775fd0b74Schristos   if (buffer->write_idx == buffer->size)
24875fd0b74Schristos     {
24975fd0b74Schristos       buffer->size *= 2;
250*e992f068Schristos       buffer->ptr = xrealloc (buffer->ptr, buffer->size);
25175fd0b74Schristos     }
25275fd0b74Schristos 
25375fd0b74Schristos   buffer->ptr[buffer->write_idx++] = ch;
25475fd0b74Schristos }
25575fd0b74Schristos 
25675fd0b74Schristos static void
overwrite_string(string_type * dst,string_type * src)257*e992f068Schristos overwrite_string (string_type *dst, string_type *src)
25875fd0b74Schristos {
25975fd0b74Schristos   free (dst->ptr);
26075fd0b74Schristos   dst->size = src->size;
26175fd0b74Schristos   dst->write_idx = src->write_idx;
26275fd0b74Schristos   dst->ptr = src->ptr;
26375fd0b74Schristos }
26475fd0b74Schristos 
26575fd0b74Schristos static void
catbuf(string_type * buffer,char * buf,unsigned int len)266*e992f068Schristos catbuf (string_type *buffer, char *buf, unsigned int len)
26775fd0b74Schristos {
26875fd0b74Schristos   if (buffer->write_idx + len >= buffer->size)
26975fd0b74Schristos     {
27075fd0b74Schristos       while (buffer->write_idx + len >= buffer->size)
27175fd0b74Schristos 	buffer->size *= 2;
272*e992f068Schristos       buffer->ptr = xrealloc (buffer->ptr, buffer->size);
27375fd0b74Schristos     }
27475fd0b74Schristos   memcpy (buffer->ptr + buffer->write_idx, buf, len);
27575fd0b74Schristos   buffer->write_idx += len;
27675fd0b74Schristos }
27775fd0b74Schristos 
27875fd0b74Schristos static void
cattext(string_type * buffer,char * string)279*e992f068Schristos cattext (string_type *buffer, char *string)
28075fd0b74Schristos {
28175fd0b74Schristos   catbuf (buffer, string, (unsigned int) strlen (string));
28275fd0b74Schristos }
28375fd0b74Schristos 
28475fd0b74Schristos static void
catstr(string_type * dst,string_type * src)285*e992f068Schristos catstr (string_type *dst, string_type *src)
28675fd0b74Schristos {
28775fd0b74Schristos   catbuf (dst, src->ptr, src->write_idx);
28875fd0b74Schristos }
28975fd0b74Schristos 
29075fd0b74Schristos static unsigned int
skip_white_and_stars(string_type * src,unsigned int idx)291*e992f068Schristos skip_white_and_stars (string_type *src, unsigned int idx)
29275fd0b74Schristos {
29375fd0b74Schristos   char c;
29475fd0b74Schristos   while ((c = at (src, idx)),
29575fd0b74Schristos 	 isspace ((unsigned char) c)
29675fd0b74Schristos 	 || (c == '*'
29775fd0b74Schristos 	     /* Don't skip past end-of-comment or star as first
29875fd0b74Schristos 		character on its line.  */
29975fd0b74Schristos 	     && at (src, idx +1) != '/'
30075fd0b74Schristos 	     && at (src, idx -1) != '\n'))
30175fd0b74Schristos     idx++;
30275fd0b74Schristos   return idx;
30375fd0b74Schristos }
30475fd0b74Schristos 
30575fd0b74Schristos static unsigned int
skip_past_newline_1(string_type * ptr,unsigned int idx)306*e992f068Schristos skip_past_newline_1 (string_type *ptr, unsigned int idx)
30775fd0b74Schristos {
30875fd0b74Schristos   while (at (ptr, idx)
30975fd0b74Schristos 	 && at (ptr, idx) != '\n')
31075fd0b74Schristos     idx++;
31175fd0b74Schristos   if (at (ptr, idx) == '\n')
31275fd0b74Schristos     return idx + 1;
31375fd0b74Schristos   return idx;
31475fd0b74Schristos }
31575fd0b74Schristos 
31675fd0b74Schristos static void
check_range(void)317*e992f068Schristos check_range (void)
31875fd0b74Schristos {
31975fd0b74Schristos   if (tos < stack)
32075fd0b74Schristos     die ("underflow in string stack");
32175fd0b74Schristos   if (tos >= stack + STACK)
32275fd0b74Schristos     die ("overflow in string stack");
32375fd0b74Schristos }
32475fd0b74Schristos 
32575fd0b74Schristos static void
icheck_range(void)326*e992f068Schristos icheck_range (void)
32775fd0b74Schristos {
32875fd0b74Schristos   if (isp < istack)
32975fd0b74Schristos     die ("underflow in integer stack");
33075fd0b74Schristos   if (isp >= istack + STACK)
33175fd0b74Schristos     die ("overflow in integer stack");
33275fd0b74Schristos }
33375fd0b74Schristos 
33475fd0b74Schristos static void
exec(dict_type * word)335*e992f068Schristos exec (dict_type *word)
33675fd0b74Schristos {
33775fd0b74Schristos   pc = word->code;
338*e992f068Schristos   while (pc->f)
339*e992f068Schristos     pc->f ();
34075fd0b74Schristos }
34175fd0b74Schristos 
34275fd0b74Schristos static void
call(void)343*e992f068Schristos call (void)
34475fd0b74Schristos {
345*e992f068Schristos   pcu *oldpc = pc;
346*e992f068Schristos   dict_type *e = pc[1].e;
34775fd0b74Schristos   exec (e);
34875fd0b74Schristos   pc = oldpc + 2;
34975fd0b74Schristos }
35075fd0b74Schristos 
35175fd0b74Schristos static void
remchar(void)352*e992f068Schristos remchar (void)
35375fd0b74Schristos {
35475fd0b74Schristos   if (tos->write_idx)
35575fd0b74Schristos     tos->write_idx--;
35675fd0b74Schristos   pc++;
35775fd0b74Schristos }
35875fd0b74Schristos 
35975fd0b74Schristos static void
strip_trailing_newlines(void)360*e992f068Schristos strip_trailing_newlines (void)
36175fd0b74Schristos {
36275fd0b74Schristos   while ((isspace ((unsigned char) at (tos, tos->write_idx - 1))
36375fd0b74Schristos 	  || at (tos, tos->write_idx - 1) == '\n')
36475fd0b74Schristos 	 && tos->write_idx > 0)
36575fd0b74Schristos     tos->write_idx--;
36675fd0b74Schristos   pc++;
36775fd0b74Schristos }
36875fd0b74Schristos 
36975fd0b74Schristos static void
push_number(void)370*e992f068Schristos push_number (void)
37175fd0b74Schristos {
37275fd0b74Schristos   isp++;
37375fd0b74Schristos   icheck_range ();
37475fd0b74Schristos   pc++;
375*e992f068Schristos   *isp = pc->l;
37675fd0b74Schristos   pc++;
37775fd0b74Schristos }
37875fd0b74Schristos 
37975fd0b74Schristos static void
push_text(void)380*e992f068Schristos push_text (void)
38175fd0b74Schristos {
38275fd0b74Schristos   tos++;
38375fd0b74Schristos   check_range ();
38475fd0b74Schristos   init_string (tos);
38575fd0b74Schristos   pc++;
386*e992f068Schristos   cattext (tos, pc->s);
38775fd0b74Schristos   pc++;
38875fd0b74Schristos }
38975fd0b74Schristos 
39075fd0b74Schristos /* This function removes everything not inside comments starting on
39175fd0b74Schristos    the first char of the line from the  string, also when copying
39275fd0b74Schristos    comments, removes blank space and leading *'s.
39375fd0b74Schristos    Blank lines are turned into one blank line.  */
39475fd0b74Schristos 
39575fd0b74Schristos static void
remove_noncomments(string_type * src,string_type * dst)396*e992f068Schristos remove_noncomments (string_type *src, string_type *dst)
39775fd0b74Schristos {
39875fd0b74Schristos   unsigned int idx = 0;
39975fd0b74Schristos 
40075fd0b74Schristos   while (at (src, idx))
40175fd0b74Schristos     {
40275fd0b74Schristos       /* Now see if we have a comment at the start of the line.  */
40375fd0b74Schristos       if (at (src, idx) == '\n'
40475fd0b74Schristos 	  && at (src, idx + 1) == '/'
40575fd0b74Schristos 	  && at (src, idx + 2) == '*')
40675fd0b74Schristos 	{
40775fd0b74Schristos 	  idx += 3;
40875fd0b74Schristos 
40975fd0b74Schristos 	  idx = skip_white_and_stars (src, idx);
41075fd0b74Schristos 
41175fd0b74Schristos 	  /* Remove leading dot */
41275fd0b74Schristos 	  if (at (src, idx) == '.')
41375fd0b74Schristos 	    idx++;
41475fd0b74Schristos 
41575fd0b74Schristos 	  /* Copy to the end of the line, or till the end of the
41675fd0b74Schristos 	     comment.  */
41775fd0b74Schristos 	  while (at (src, idx))
41875fd0b74Schristos 	    {
41975fd0b74Schristos 	      if (at (src, idx) == '\n')
42075fd0b74Schristos 		{
42175fd0b74Schristos 		  /* end of line, echo and scrape of leading blanks  */
42275fd0b74Schristos 		  if (at (src, idx + 1) == '\n')
42375fd0b74Schristos 		    catchar (dst, '\n');
42475fd0b74Schristos 		  catchar (dst, '\n');
42575fd0b74Schristos 		  idx++;
42675fd0b74Schristos 		  idx = skip_white_and_stars (src, idx);
42775fd0b74Schristos 		}
42875fd0b74Schristos 	      else if (at (src, idx) == '*' && at (src, idx + 1) == '/')
42975fd0b74Schristos 		{
43075fd0b74Schristos 		  idx += 2;
43175fd0b74Schristos 		  cattext (dst, "\nENDDD\n");
43275fd0b74Schristos 		  break;
43375fd0b74Schristos 		}
43475fd0b74Schristos 	      else
43575fd0b74Schristos 		{
43675fd0b74Schristos 		  catchar (dst, at (src, idx));
43775fd0b74Schristos 		  idx++;
43875fd0b74Schristos 		}
43975fd0b74Schristos 	    }
44075fd0b74Schristos 	}
44175fd0b74Schristos       else
44275fd0b74Schristos 	idx++;
44375fd0b74Schristos     }
44475fd0b74Schristos }
44575fd0b74Schristos 
44675fd0b74Schristos static void
print_stack_level(void)447*e992f068Schristos print_stack_level (void)
44875fd0b74Schristos {
44975fd0b74Schristos   fprintf (stderr, "current string stack depth = %ld, ",
45075fd0b74Schristos 	   (long) (tos - stack));
45175fd0b74Schristos   fprintf (stderr, "current integer stack depth = %ld\n",
45275fd0b74Schristos 	   (long) (isp - istack));
45375fd0b74Schristos   pc++;
45475fd0b74Schristos }
45575fd0b74Schristos 
45675fd0b74Schristos /* turn:
45775fd0b74Schristos      foobar name(stuff);
45875fd0b74Schristos    into:
45975fd0b74Schristos      foobar
46075fd0b74Schristos      name PARAMS ((stuff));
46175fd0b74Schristos    and a blank line.
46275fd0b74Schristos  */
46375fd0b74Schristos 
46475fd0b74Schristos static void
paramstuff(void)465*e992f068Schristos paramstuff (void)
46675fd0b74Schristos {
46775fd0b74Schristos   unsigned int openp;
46875fd0b74Schristos   unsigned int fname;
46975fd0b74Schristos   unsigned int idx;
47075fd0b74Schristos   unsigned int len;
47175fd0b74Schristos   string_type out;
47275fd0b74Schristos   init_string (&out);
47375fd0b74Schristos 
47475fd0b74Schristos #define NO_PARAMS 1
47575fd0b74Schristos 
47675fd0b74Schristos   /* Make sure that it's not already param'd or proto'd.  */
47775fd0b74Schristos   if (NO_PARAMS
47875fd0b74Schristos       || find (tos, "PARAMS") || find (tos, "PROTO") || !find (tos, "("))
47975fd0b74Schristos     {
48075fd0b74Schristos       catstr (&out, tos);
48175fd0b74Schristos     }
48275fd0b74Schristos   else
48375fd0b74Schristos     {
48475fd0b74Schristos       /* Find the open paren.  */
48575fd0b74Schristos       for (openp = 0; at (tos, openp) != '(' && at (tos, openp); openp++)
48675fd0b74Schristos 	;
48775fd0b74Schristos 
48875fd0b74Schristos       fname = openp;
48975fd0b74Schristos       /* Step back to the fname.  */
49075fd0b74Schristos       fname--;
49175fd0b74Schristos       while (fname && isspace ((unsigned char) at (tos, fname)))
49275fd0b74Schristos 	fname--;
49375fd0b74Schristos       while (fname
49475fd0b74Schristos 	     && !isspace ((unsigned char) at (tos,fname))
49575fd0b74Schristos 	     && at (tos,fname) != '*')
49675fd0b74Schristos 	fname--;
49775fd0b74Schristos 
49875fd0b74Schristos       fname++;
49975fd0b74Schristos 
50075fd0b74Schristos       /* Output type, omitting trailing whitespace character(s), if
50175fd0b74Schristos          any.  */
50275fd0b74Schristos       for (len = fname; 0 < len; len--)
50375fd0b74Schristos 	{
50475fd0b74Schristos 	  if (!isspace ((unsigned char) at (tos, len - 1)))
50575fd0b74Schristos 	    break;
50675fd0b74Schristos 	}
50775fd0b74Schristos       for (idx = 0; idx < len; idx++)
50875fd0b74Schristos 	catchar (&out, at (tos, idx));
50975fd0b74Schristos 
51075fd0b74Schristos       cattext (&out, "\n");	/* Insert a newline between type and fnname */
51175fd0b74Schristos 
51275fd0b74Schristos       /* Output function name, omitting trailing whitespace
51375fd0b74Schristos          character(s), if any.  */
51475fd0b74Schristos       for (len = openp; 0 < len; len--)
51575fd0b74Schristos 	{
51675fd0b74Schristos 	  if (!isspace ((unsigned char) at (tos, len - 1)))
51775fd0b74Schristos 	    break;
51875fd0b74Schristos 	}
51975fd0b74Schristos       for (idx = fname; idx < len; idx++)
52075fd0b74Schristos 	catchar (&out, at (tos, idx));
52175fd0b74Schristos 
52275fd0b74Schristos       cattext (&out, " PARAMS (");
52375fd0b74Schristos 
52475fd0b74Schristos       for (idx = openp; at (tos, idx) && at (tos, idx) != ';'; idx++)
52575fd0b74Schristos 	catchar (&out, at (tos, idx));
52675fd0b74Schristos 
52775fd0b74Schristos       cattext (&out, ");\n\n");
52875fd0b74Schristos     }
52975fd0b74Schristos   overwrite_string (tos, &out);
53075fd0b74Schristos   pc++;
53175fd0b74Schristos 
53275fd0b74Schristos }
53375fd0b74Schristos 
53475fd0b74Schristos /* turn {*
53575fd0b74Schristos    and *} into comments */
53675fd0b74Schristos 
53775fd0b74Schristos static void
translatecomments(void)538*e992f068Schristos translatecomments (void)
53975fd0b74Schristos {
54075fd0b74Schristos   unsigned int idx = 0;
54175fd0b74Schristos   string_type out;
54275fd0b74Schristos   init_string (&out);
54375fd0b74Schristos 
54475fd0b74Schristos   while (at (tos, idx))
54575fd0b74Schristos     {
54675fd0b74Schristos       if (at (tos, idx) == '{' && at (tos, idx + 1) == '*')
54775fd0b74Schristos 	{
54875fd0b74Schristos 	  cattext (&out, "/*");
54975fd0b74Schristos 	  idx += 2;
55075fd0b74Schristos 	}
55175fd0b74Schristos       else if (at (tos, idx) == '*' && at (tos, idx + 1) == '}')
55275fd0b74Schristos 	{
55375fd0b74Schristos 	  cattext (&out, "*/");
55475fd0b74Schristos 	  idx += 2;
55575fd0b74Schristos 	}
55675fd0b74Schristos       else
55775fd0b74Schristos 	{
55875fd0b74Schristos 	  catchar (&out, at (tos, idx));
55975fd0b74Schristos 	  idx++;
56075fd0b74Schristos 	}
56175fd0b74Schristos     }
56275fd0b74Schristos 
56375fd0b74Schristos   overwrite_string (tos, &out);
56475fd0b74Schristos 
56575fd0b74Schristos   pc++;
56675fd0b74Schristos }
56775fd0b74Schristos 
56875fd0b74Schristos /* Mod tos so that only lines with leading dots remain */
56975fd0b74Schristos static void
outputdots(void)570*e992f068Schristos outputdots (void)
57175fd0b74Schristos {
57275fd0b74Schristos   unsigned int idx = 0;
57375fd0b74Schristos   string_type out;
57475fd0b74Schristos   init_string (&out);
57575fd0b74Schristos 
57675fd0b74Schristos   while (at (tos, idx))
57775fd0b74Schristos     {
57875fd0b74Schristos       /* Every iteration begins at the start of a line.  */
57975fd0b74Schristos       if (at (tos, idx) == '.')
58075fd0b74Schristos 	{
58175fd0b74Schristos 	  char c;
58275fd0b74Schristos 
58375fd0b74Schristos 	  idx++;
58475fd0b74Schristos 
58575fd0b74Schristos 	  while ((c = at (tos, idx)) && c != '\n')
58675fd0b74Schristos 	    {
58775fd0b74Schristos 	      if (c == '{' && at (tos, idx + 1) == '*')
58875fd0b74Schristos 		{
58975fd0b74Schristos 		  cattext (&out, "/*");
59075fd0b74Schristos 		  idx += 2;
59175fd0b74Schristos 		}
59275fd0b74Schristos 	      else if (c == '*' && at (tos, idx + 1) == '}')
59375fd0b74Schristos 		{
59475fd0b74Schristos 		  cattext (&out, "*/");
59575fd0b74Schristos 		  idx += 2;
59675fd0b74Schristos 		}
59775fd0b74Schristos 	      else
59875fd0b74Schristos 		{
59975fd0b74Schristos 		  catchar (&out, c);
60075fd0b74Schristos 		  idx++;
60175fd0b74Schristos 		}
60275fd0b74Schristos 	    }
60375fd0b74Schristos 	  if (c == '\n')
60475fd0b74Schristos 	    idx++;
60575fd0b74Schristos 	  catchar (&out, '\n');
60675fd0b74Schristos 	}
60775fd0b74Schristos       else
60875fd0b74Schristos 	{
60975fd0b74Schristos 	  idx = skip_past_newline_1 (tos, idx);
61075fd0b74Schristos 	}
61175fd0b74Schristos     }
61275fd0b74Schristos 
61375fd0b74Schristos   overwrite_string (tos, &out);
61475fd0b74Schristos   pc++;
61575fd0b74Schristos }
61675fd0b74Schristos 
61775fd0b74Schristos /* Find lines starting with . and | and put example around them on tos */
61875fd0b74Schristos static void
courierize(void)619*e992f068Schristos courierize (void)
62075fd0b74Schristos {
62175fd0b74Schristos   string_type out;
62275fd0b74Schristos   unsigned int idx = 0;
62375fd0b74Schristos   int command = 0;
62475fd0b74Schristos 
62575fd0b74Schristos   init_string (&out);
62675fd0b74Schristos 
62775fd0b74Schristos   while (at (tos, idx))
62875fd0b74Schristos     {
62975fd0b74Schristos       if (at (tos, idx) == '\n'
63075fd0b74Schristos 	  && (at (tos, idx +1 ) == '.'
63175fd0b74Schristos 	      || at (tos, idx + 1) == '|'))
63275fd0b74Schristos 	{
63375fd0b74Schristos 	  cattext (&out, "\n@example\n");
63475fd0b74Schristos 	  do
63575fd0b74Schristos 	    {
63675fd0b74Schristos 	      idx += 2;
63775fd0b74Schristos 
63875fd0b74Schristos 	      while (at (tos, idx) && at (tos, idx) != '\n')
63975fd0b74Schristos 		{
64075fd0b74Schristos 		  if (command > 1)
64175fd0b74Schristos 		    {
64275fd0b74Schristos 		      /* We are inside {} parameters of some command;
64375fd0b74Schristos 			 Just pass through until matching brace.  */
64475fd0b74Schristos 		      if (at (tos, idx) == '{')
64575fd0b74Schristos 			++command;
64675fd0b74Schristos 		      else if (at (tos, idx) == '}')
64775fd0b74Schristos 			--command;
64875fd0b74Schristos 		    }
64975fd0b74Schristos 		  else if (command != 0)
65075fd0b74Schristos 		    {
65175fd0b74Schristos 		      if (at (tos, idx) == '{')
65275fd0b74Schristos 			++command;
65375fd0b74Schristos 		      else if (!islower ((unsigned char) at (tos, idx)))
65475fd0b74Schristos 			--command;
65575fd0b74Schristos 		    }
65675fd0b74Schristos 		  else if (at (tos, idx) == '@'
65775fd0b74Schristos 			   && islower ((unsigned char) at (tos, idx + 1)))
65875fd0b74Schristos 		    {
65975fd0b74Schristos 		      ++command;
66075fd0b74Schristos 		    }
66175fd0b74Schristos 		  else if (at (tos, idx) == '{' && at (tos, idx + 1) == '*')
66275fd0b74Schristos 		    {
66375fd0b74Schristos 		      cattext (&out, "/*");
66475fd0b74Schristos 		      idx += 2;
66575fd0b74Schristos 		      continue;
66675fd0b74Schristos 		    }
66775fd0b74Schristos 		  else if (at (tos, idx) == '*' && at (tos, idx + 1) == '}')
66875fd0b74Schristos 		    {
66975fd0b74Schristos 		      cattext (&out, "*/");
67075fd0b74Schristos 		      idx += 2;
67175fd0b74Schristos 		      continue;
67275fd0b74Schristos 		    }
67375fd0b74Schristos 		  else if (at (tos, idx) == '{'
67475fd0b74Schristos 			   || at (tos, idx) == '}')
67575fd0b74Schristos 		    {
67675fd0b74Schristos 		      catchar (&out, '@');
67775fd0b74Schristos 		    }
67875fd0b74Schristos 
67975fd0b74Schristos 		  catchar (&out, at (tos, idx));
68075fd0b74Schristos 		  idx++;
68175fd0b74Schristos 		}
68275fd0b74Schristos 	      catchar (&out, '\n');
68375fd0b74Schristos 	    }
68475fd0b74Schristos 	  while (at (tos, idx) == '\n'
68575fd0b74Schristos 		 && ((at (tos, idx + 1) == '.')
68675fd0b74Schristos 		     || (at (tos, idx + 1) == '|')))
68775fd0b74Schristos 	    ;
68875fd0b74Schristos 	  cattext (&out, "@end example");
68975fd0b74Schristos 	}
69075fd0b74Schristos       else
69175fd0b74Schristos 	{
69275fd0b74Schristos 	  catchar (&out, at (tos, idx));
69375fd0b74Schristos 	  idx++;
69475fd0b74Schristos 	}
69575fd0b74Schristos     }
69675fd0b74Schristos 
69775fd0b74Schristos   overwrite_string (tos, &out);
69875fd0b74Schristos   pc++;
69975fd0b74Schristos }
70075fd0b74Schristos 
70175fd0b74Schristos /* Finds any lines starting with "o ", if there are any, then turns
70275fd0b74Schristos    on @itemize @bullet, and @items each of them. Then ends with @end
70375fd0b74Schristos    itemize, inplace at TOS*/
70475fd0b74Schristos 
70575fd0b74Schristos static void
bulletize(void)706*e992f068Schristos bulletize (void)
70775fd0b74Schristos {
70875fd0b74Schristos   unsigned int idx = 0;
70975fd0b74Schristos   int on = 0;
71075fd0b74Schristos   string_type out;
71175fd0b74Schristos   init_string (&out);
71275fd0b74Schristos 
71375fd0b74Schristos   while (at (tos, idx))
71475fd0b74Schristos     {
71575fd0b74Schristos       if (at (tos, idx) == '@'
71675fd0b74Schristos 	  && at (tos, idx + 1) == '*')
71775fd0b74Schristos 	{
71875fd0b74Schristos 	  cattext (&out, "*");
71975fd0b74Schristos 	  idx += 2;
72075fd0b74Schristos 	}
72175fd0b74Schristos       else if (at (tos, idx) == '\n'
72275fd0b74Schristos 	       && at (tos, idx + 1) == 'o'
72375fd0b74Schristos 	       && isspace ((unsigned char) at (tos, idx + 2)))
72475fd0b74Schristos 	{
72575fd0b74Schristos 	  if (!on)
72675fd0b74Schristos 	    {
72775fd0b74Schristos 	      cattext (&out, "\n@itemize @bullet\n");
72875fd0b74Schristos 	      on = 1;
72975fd0b74Schristos 
73075fd0b74Schristos 	    }
73175fd0b74Schristos 	  cattext (&out, "\n@item\n");
73275fd0b74Schristos 	  idx += 3;
73375fd0b74Schristos 	}
73475fd0b74Schristos       else
73575fd0b74Schristos 	{
73675fd0b74Schristos 	  catchar (&out, at (tos, idx));
73775fd0b74Schristos 	  if (on && at (tos, idx) == '\n'
73875fd0b74Schristos 	      && at (tos, idx + 1) == '\n'
73975fd0b74Schristos 	      && at (tos, idx + 2) != 'o')
74075fd0b74Schristos 	    {
74175fd0b74Schristos 	      cattext (&out, "@end itemize");
74275fd0b74Schristos 	      on = 0;
74375fd0b74Schristos 	    }
74475fd0b74Schristos 	  idx++;
74575fd0b74Schristos 
74675fd0b74Schristos 	}
74775fd0b74Schristos     }
74875fd0b74Schristos   if (on)
74975fd0b74Schristos     {
75075fd0b74Schristos       cattext (&out, "@end itemize\n");
75175fd0b74Schristos     }
75275fd0b74Schristos 
75375fd0b74Schristos   delete_string (tos);
75475fd0b74Schristos   *tos = out;
75575fd0b74Schristos   pc++;
75675fd0b74Schristos }
75775fd0b74Schristos 
75875fd0b74Schristos /* Turn <<foo>> into @code{foo} in place at TOS*/
75975fd0b74Schristos 
76075fd0b74Schristos static void
do_fancy_stuff(void)761*e992f068Schristos do_fancy_stuff (void)
76275fd0b74Schristos {
76375fd0b74Schristos   unsigned int idx = 0;
76475fd0b74Schristos   string_type out;
76575fd0b74Schristos   init_string (&out);
76675fd0b74Schristos   while (at (tos, idx))
76775fd0b74Schristos     {
76875fd0b74Schristos       if (at (tos, idx) == '<'
76975fd0b74Schristos 	  && at (tos, idx + 1) == '<'
77075fd0b74Schristos 	  && !isspace ((unsigned char) at (tos, idx + 2)))
77175fd0b74Schristos 	{
77275fd0b74Schristos 	  /* This qualifies as a << startup.  */
77375fd0b74Schristos 	  idx += 2;
77475fd0b74Schristos 	  cattext (&out, "@code{");
77575fd0b74Schristos 	  while (at (tos, idx)
77675fd0b74Schristos 		 && at (tos, idx) != '>' )
77775fd0b74Schristos 	    {
77875fd0b74Schristos 	      catchar (&out, at (tos, idx));
77975fd0b74Schristos 	      idx++;
78075fd0b74Schristos 
78175fd0b74Schristos 	    }
78275fd0b74Schristos 	  cattext (&out, "}");
78375fd0b74Schristos 	  idx += 2;
78475fd0b74Schristos 	}
78575fd0b74Schristos       else
78675fd0b74Schristos 	{
78775fd0b74Schristos 	  catchar (&out, at (tos, idx));
78875fd0b74Schristos 	  idx++;
78975fd0b74Schristos 	}
79075fd0b74Schristos     }
79175fd0b74Schristos   delete_string (tos);
79275fd0b74Schristos   *tos = out;
79375fd0b74Schristos   pc++;
79475fd0b74Schristos 
79575fd0b74Schristos }
79675fd0b74Schristos 
79775fd0b74Schristos /* A command is all upper case,and alone on a line.  */
79875fd0b74Schristos 
79975fd0b74Schristos static int
iscommand(string_type * ptr,unsigned int idx)800*e992f068Schristos iscommand (string_type *ptr, unsigned int idx)
80175fd0b74Schristos {
80275fd0b74Schristos   unsigned int len = 0;
80375fd0b74Schristos   while (at (ptr, idx))
80475fd0b74Schristos     {
80575fd0b74Schristos       if (isupper ((unsigned char) at (ptr, idx))
80675fd0b74Schristos 	  || at (ptr, idx) == ' ' || at (ptr, idx) == '_')
80775fd0b74Schristos 	{
80875fd0b74Schristos 	  len++;
80975fd0b74Schristos 	  idx++;
81075fd0b74Schristos 	}
81175fd0b74Schristos       else if (at (ptr, idx) == '\n')
81275fd0b74Schristos 	{
81375fd0b74Schristos 	  if (len > 3)
81475fd0b74Schristos 	    return 1;
81575fd0b74Schristos 	  return 0;
81675fd0b74Schristos 	}
81775fd0b74Schristos       else
81875fd0b74Schristos 	return 0;
81975fd0b74Schristos     }
82075fd0b74Schristos   return 0;
82175fd0b74Schristos }
82275fd0b74Schristos 
82375fd0b74Schristos static int
copy_past_newline(string_type * ptr,unsigned int idx,string_type * dst)824*e992f068Schristos copy_past_newline (string_type *ptr, unsigned int idx, string_type *dst)
82575fd0b74Schristos {
82675fd0b74Schristos   int column = 0;
82775fd0b74Schristos 
82875fd0b74Schristos   while (at (ptr, idx) && at (ptr, idx) != '\n')
82975fd0b74Schristos     {
83075fd0b74Schristos       if (at (ptr, idx) == '\t')
83175fd0b74Schristos 	{
83275fd0b74Schristos 	  /* Expand tabs.  Neither makeinfo nor TeX can cope well with
83375fd0b74Schristos 	     them.  */
83475fd0b74Schristos 	  do
83575fd0b74Schristos 	    catchar (dst, ' ');
83675fd0b74Schristos 	  while (++column & 7);
83775fd0b74Schristos 	}
83875fd0b74Schristos       else
83975fd0b74Schristos 	{
84075fd0b74Schristos 	  catchar (dst, at (ptr, idx));
84175fd0b74Schristos 	  column++;
84275fd0b74Schristos 	}
84375fd0b74Schristos       idx++;
84475fd0b74Schristos 
84575fd0b74Schristos     }
84675fd0b74Schristos   catchar (dst, at (ptr, idx));
84775fd0b74Schristos   idx++;
84875fd0b74Schristos   return idx;
84975fd0b74Schristos 
85075fd0b74Schristos }
85175fd0b74Schristos 
85275fd0b74Schristos static void
icopy_past_newline(void)853*e992f068Schristos icopy_past_newline (void)
85475fd0b74Schristos {
85575fd0b74Schristos   tos++;
85675fd0b74Schristos   check_range ();
85775fd0b74Schristos   init_string (tos);
85875fd0b74Schristos   idx = copy_past_newline (ptr, idx, tos);
85975fd0b74Schristos   pc++;
86075fd0b74Schristos }
86175fd0b74Schristos 
86275fd0b74Schristos /* indent
86375fd0b74Schristos    Take the string at the top of the stack, do some prettying.  */
86475fd0b74Schristos 
86575fd0b74Schristos static void
kill_bogus_lines(void)866*e992f068Schristos kill_bogus_lines (void)
86775fd0b74Schristos {
86875fd0b74Schristos   int sl;
86975fd0b74Schristos 
87075fd0b74Schristos   int idx = 0;
87175fd0b74Schristos   int c;
87275fd0b74Schristos   int dot = 0;
87375fd0b74Schristos 
87475fd0b74Schristos   string_type out;
87575fd0b74Schristos   init_string (&out);
87675fd0b74Schristos   /* Drop leading nl.  */
87775fd0b74Schristos   while (at (tos, idx) == '\n')
87875fd0b74Schristos     {
87975fd0b74Schristos       idx++;
88075fd0b74Schristos     }
88175fd0b74Schristos   c = idx;
88275fd0b74Schristos 
88375fd0b74Schristos   /* If the first char is a '.' prepend a newline so that it is
88475fd0b74Schristos      recognized properly later.  */
88575fd0b74Schristos   if (at (tos, idx) == '.')
88675fd0b74Schristos     catchar (&out, '\n');
88775fd0b74Schristos 
88875fd0b74Schristos   /* Find the last char.  */
88975fd0b74Schristos   while (at (tos, idx))
89075fd0b74Schristos     {
89175fd0b74Schristos       idx++;
89275fd0b74Schristos     }
89375fd0b74Schristos 
89475fd0b74Schristos   /* Find the last non white before the nl.  */
89575fd0b74Schristos   idx--;
89675fd0b74Schristos 
89775fd0b74Schristos   while (idx && isspace ((unsigned char) at (tos, idx)))
89875fd0b74Schristos     idx--;
89975fd0b74Schristos   idx++;
90075fd0b74Schristos 
90175fd0b74Schristos   /* Copy buffer upto last char, but blank lines before and after
90275fd0b74Schristos      dots don't count.  */
90375fd0b74Schristos   sl = 1;
90475fd0b74Schristos 
90575fd0b74Schristos   while (c < idx)
90675fd0b74Schristos     {
90775fd0b74Schristos       if (at (tos, c) == '\n'
90875fd0b74Schristos 	  && at (tos, c + 1) == '\n'
90975fd0b74Schristos 	  && at (tos, c + 2) == '.')
91075fd0b74Schristos 	{
91175fd0b74Schristos 	  /* Ignore two newlines before a dot.  */
91275fd0b74Schristos 	  c++;
91375fd0b74Schristos 	}
91475fd0b74Schristos       else if (at (tos, c) == '.' && sl)
91575fd0b74Schristos 	{
91675fd0b74Schristos 	  /* remember that this line started with a dot.  */
91775fd0b74Schristos 	  dot = 2;
91875fd0b74Schristos 	}
91975fd0b74Schristos       else if (at (tos, c) == '\n'
92075fd0b74Schristos 	       && at (tos, c + 1) == '\n'
92175fd0b74Schristos 	       && dot)
92275fd0b74Schristos 	{
92375fd0b74Schristos 	  c++;
92475fd0b74Schristos 	  /* Ignore two newlines when last line was dot.  */
92575fd0b74Schristos 	}
92675fd0b74Schristos 
92775fd0b74Schristos       catchar (&out, at (tos, c));
92875fd0b74Schristos       if (at (tos, c) == '\n')
92975fd0b74Schristos 	{
93075fd0b74Schristos 	  sl = 1;
93175fd0b74Schristos 
93275fd0b74Schristos 	  if (dot == 2)
93375fd0b74Schristos 	    dot = 1;
93475fd0b74Schristos 	  else
93575fd0b74Schristos 	    dot = 0;
93675fd0b74Schristos 	}
93775fd0b74Schristos       else
93875fd0b74Schristos 	sl = 0;
93975fd0b74Schristos 
94075fd0b74Schristos       c++;
94175fd0b74Schristos 
94275fd0b74Schristos     }
94375fd0b74Schristos 
94475fd0b74Schristos   /* Append nl.  */
94575fd0b74Schristos   catchar (&out, '\n');
94675fd0b74Schristos   pc++;
94775fd0b74Schristos   delete_string (tos);
94875fd0b74Schristos   *tos = out;
94975fd0b74Schristos 
95075fd0b74Schristos }
95175fd0b74Schristos 
95275fd0b74Schristos static void
indent(void)953*e992f068Schristos indent (void)
95475fd0b74Schristos {
95575fd0b74Schristos   string_type out;
95675fd0b74Schristos   int tab = 0;
95775fd0b74Schristos   int idx = 0;
95875fd0b74Schristos   int ol = 0;
95975fd0b74Schristos   init_string (&out);
96075fd0b74Schristos   while (at (tos, idx))
96175fd0b74Schristos     {
96275fd0b74Schristos       switch (at (tos, idx))
96375fd0b74Schristos 	{
96475fd0b74Schristos 	case '\n':
96575fd0b74Schristos 	  cattext (&out, "\n");
96675fd0b74Schristos 	  idx++;
96775fd0b74Schristos 	  if (tab && at (tos, idx))
96875fd0b74Schristos 	    {
96975fd0b74Schristos 	      cattext (&out, "    ");
97075fd0b74Schristos 	    }
97175fd0b74Schristos 	  ol = 0;
97275fd0b74Schristos 	  break;
97375fd0b74Schristos 	case '(':
97475fd0b74Schristos 	  tab++;
97575fd0b74Schristos 	  if (ol == 0)
97675fd0b74Schristos 	    cattext (&out, "   ");
97775fd0b74Schristos 	  idx++;
97875fd0b74Schristos 	  cattext (&out, "(");
97975fd0b74Schristos 	  ol = 1;
98075fd0b74Schristos 	  break;
98175fd0b74Schristos 	case ')':
98275fd0b74Schristos 	  tab--;
98375fd0b74Schristos 	  cattext (&out, ")");
98475fd0b74Schristos 	  idx++;
98575fd0b74Schristos 	  ol = 1;
98675fd0b74Schristos 
98775fd0b74Schristos 	  break;
98875fd0b74Schristos 	default:
98975fd0b74Schristos 	  catchar (&out, at (tos, idx));
99075fd0b74Schristos 	  ol = 1;
99175fd0b74Schristos 
99275fd0b74Schristos 	  idx++;
99375fd0b74Schristos 	  break;
99475fd0b74Schristos 	}
99575fd0b74Schristos     }
99675fd0b74Schristos 
99775fd0b74Schristos   pc++;
99875fd0b74Schristos   delete_string (tos);
99975fd0b74Schristos   *tos = out;
100075fd0b74Schristos 
100175fd0b74Schristos }
100275fd0b74Schristos 
100375fd0b74Schristos static void
get_stuff_in_command(void)1004*e992f068Schristos get_stuff_in_command (void)
100575fd0b74Schristos {
100675fd0b74Schristos   tos++;
100775fd0b74Schristos   check_range ();
100875fd0b74Schristos   init_string (tos);
100975fd0b74Schristos 
101075fd0b74Schristos   while (at (ptr, idx))
101175fd0b74Schristos     {
101275fd0b74Schristos       if (iscommand (ptr, idx))
101375fd0b74Schristos 	break;
101475fd0b74Schristos       idx = copy_past_newline (ptr, idx, tos);
101575fd0b74Schristos     }
101675fd0b74Schristos   pc++;
101775fd0b74Schristos }
101875fd0b74Schristos 
101975fd0b74Schristos static void
swap(void)1020*e992f068Schristos swap (void)
102175fd0b74Schristos {
102275fd0b74Schristos   string_type t;
102375fd0b74Schristos 
102475fd0b74Schristos   t = tos[0];
102575fd0b74Schristos   tos[0] = tos[-1];
102675fd0b74Schristos   tos[-1] = t;
102775fd0b74Schristos   pc++;
102875fd0b74Schristos }
102975fd0b74Schristos 
103075fd0b74Schristos static void
other_dup(void)1031*e992f068Schristos other_dup (void)
103275fd0b74Schristos {
103375fd0b74Schristos   tos++;
103475fd0b74Schristos   check_range ();
103575fd0b74Schristos   init_string (tos);
103675fd0b74Schristos   catstr (tos, tos - 1);
103775fd0b74Schristos   pc++;
103875fd0b74Schristos }
103975fd0b74Schristos 
104075fd0b74Schristos static void
drop(void)1041*e992f068Schristos drop (void)
104275fd0b74Schristos {
104375fd0b74Schristos   tos--;
104475fd0b74Schristos   check_range ();
1045ede78133Schristos   delete_string (tos + 1);
104675fd0b74Schristos   pc++;
104775fd0b74Schristos }
104875fd0b74Schristos 
104975fd0b74Schristos static void
idrop(void)1050*e992f068Schristos idrop (void)
105175fd0b74Schristos {
105275fd0b74Schristos   isp--;
105375fd0b74Schristos   icheck_range ();
105475fd0b74Schristos   pc++;
105575fd0b74Schristos }
105675fd0b74Schristos 
105775fd0b74Schristos static void
icatstr(void)1058*e992f068Schristos icatstr (void)
105975fd0b74Schristos {
106075fd0b74Schristos   tos--;
106175fd0b74Schristos   check_range ();
106275fd0b74Schristos   catstr (tos, tos + 1);
106375fd0b74Schristos   delete_string (tos + 1);
106475fd0b74Schristos   pc++;
106575fd0b74Schristos }
106675fd0b74Schristos 
106775fd0b74Schristos static void
skip_past_newline(void)1068*e992f068Schristos skip_past_newline (void)
106975fd0b74Schristos {
107075fd0b74Schristos   idx = skip_past_newline_1 (ptr, idx);
107175fd0b74Schristos   pc++;
107275fd0b74Schristos }
107375fd0b74Schristos 
107475fd0b74Schristos static void
internalmode(void)1075*e992f068Schristos internalmode (void)
107675fd0b74Schristos {
107775fd0b74Schristos   internal_mode = *(isp);
107875fd0b74Schristos   isp--;
107975fd0b74Schristos   icheck_range ();
108075fd0b74Schristos   pc++;
108175fd0b74Schristos }
108275fd0b74Schristos 
108375fd0b74Schristos static void
maybecatstr(void)1084*e992f068Schristos maybecatstr (void)
108575fd0b74Schristos {
108675fd0b74Schristos   if (internal_wanted == internal_mode)
108775fd0b74Schristos     {
108875fd0b74Schristos       catstr (tos - 1, tos);
108975fd0b74Schristos     }
109075fd0b74Schristos   delete_string (tos);
109175fd0b74Schristos   tos--;
109275fd0b74Schristos   check_range ();
109375fd0b74Schristos   pc++;
109475fd0b74Schristos }
109575fd0b74Schristos 
109675fd0b74Schristos char *
nextword(char * string,char ** word)1097*e992f068Schristos nextword (char *string, char **word)
109875fd0b74Schristos {
109975fd0b74Schristos   char *word_start;
110075fd0b74Schristos   int idx;
110175fd0b74Schristos   char *dst;
110275fd0b74Schristos   char *src;
110375fd0b74Schristos 
110475fd0b74Schristos   int length = 0;
110575fd0b74Schristos 
110675fd0b74Schristos   while (isspace ((unsigned char) *string) || *string == '-')
110775fd0b74Schristos     {
110875fd0b74Schristos       if (*string == '-')
110975fd0b74Schristos 	{
111075fd0b74Schristos 	  while (*string && *string != '\n')
111175fd0b74Schristos 	    string++;
111275fd0b74Schristos 
111375fd0b74Schristos 	}
111475fd0b74Schristos       else
111575fd0b74Schristos 	{
111675fd0b74Schristos 	  string++;
111775fd0b74Schristos 	}
111875fd0b74Schristos     }
111975fd0b74Schristos   if (!*string)
1120012573ebSchristos     {
1121012573ebSchristos       *word = NULL;
1122012573ebSchristos       return NULL;
1123012573ebSchristos     }
112475fd0b74Schristos 
112575fd0b74Schristos   word_start = string;
112675fd0b74Schristos   if (*string == '"')
112775fd0b74Schristos     {
112875fd0b74Schristos       do
112975fd0b74Schristos 	{
113075fd0b74Schristos 	  string++;
113175fd0b74Schristos 	  length++;
113275fd0b74Schristos 	  if (*string == '\\')
113375fd0b74Schristos 	    {
113475fd0b74Schristos 	      string += 2;
113575fd0b74Schristos 	      length += 2;
113675fd0b74Schristos 	    }
113775fd0b74Schristos 	}
113875fd0b74Schristos       while (*string != '"');
113975fd0b74Schristos     }
114075fd0b74Schristos   else
114175fd0b74Schristos     {
114275fd0b74Schristos       while (!isspace ((unsigned char) *string))
114375fd0b74Schristos 	{
114475fd0b74Schristos 	  string++;
114575fd0b74Schristos 	  length++;
114675fd0b74Schristos 
114775fd0b74Schristos 	}
114875fd0b74Schristos     }
114975fd0b74Schristos 
1150*e992f068Schristos   *word = xmalloc (length + 1);
115175fd0b74Schristos 
115275fd0b74Schristos   dst = *word;
115375fd0b74Schristos   src = word_start;
115475fd0b74Schristos 
115575fd0b74Schristos   for (idx = 0; idx < length; idx++)
115675fd0b74Schristos     {
115775fd0b74Schristos       if (src[idx] == '\\')
115875fd0b74Schristos 	switch (src[idx + 1])
115975fd0b74Schristos 	  {
116075fd0b74Schristos 	  case 'n':
116175fd0b74Schristos 	    *dst++ = '\n';
116275fd0b74Schristos 	    idx++;
116375fd0b74Schristos 	    break;
116475fd0b74Schristos 	  case '"':
116575fd0b74Schristos 	  case '\\':
116675fd0b74Schristos 	    *dst++ = src[idx + 1];
116775fd0b74Schristos 	    idx++;
116875fd0b74Schristos 	    break;
116975fd0b74Schristos 	  default:
117075fd0b74Schristos 	    *dst++ = '\\';
117175fd0b74Schristos 	    break;
117275fd0b74Schristos 	  }
117375fd0b74Schristos       else
117475fd0b74Schristos 	*dst++ = src[idx];
117575fd0b74Schristos     }
117675fd0b74Schristos   *dst++ = 0;
117775fd0b74Schristos 
117875fd0b74Schristos   if (*string)
117975fd0b74Schristos     return string + 1;
118075fd0b74Schristos   else
1181012573ebSchristos     return NULL;
118275fd0b74Schristos }
118375fd0b74Schristos 
118475fd0b74Schristos dict_type *
lookup_word(char * word)1185*e992f068Schristos lookup_word (char *word)
118675fd0b74Schristos {
118775fd0b74Schristos   dict_type *ptr = root;
118875fd0b74Schristos   while (ptr)
118975fd0b74Schristos     {
119075fd0b74Schristos       if (strcmp (ptr->word, word) == 0)
119175fd0b74Schristos 	return ptr;
119275fd0b74Schristos       ptr = ptr->next;
119375fd0b74Schristos     }
119475fd0b74Schristos   if (warning)
119575fd0b74Schristos     fprintf (stderr, "Can't find %s\n", word);
1196012573ebSchristos   return NULL;
119775fd0b74Schristos }
119875fd0b74Schristos 
119975fd0b74Schristos static void
free_words(void)1200ede78133Schristos free_words (void)
1201ede78133Schristos {
1202ede78133Schristos   dict_type *ptr = root;
1203ede78133Schristos 
1204ede78133Schristos   while (ptr)
1205ede78133Schristos     {
1206ede78133Schristos       dict_type *next;
1207ede78133Schristos 
1208ede78133Schristos       free (ptr->word);
1209ede78133Schristos       if (ptr->code)
1210ede78133Schristos 	{
1211ede78133Schristos 	  int i;
1212012573ebSchristos 	  for (i = 0; i < ptr->code_end - 1; i ++)
1213*e992f068Schristos 	    if (ptr->code[i].f == push_text
1214*e992f068Schristos 		&& ptr->code[i + 1].s)
1215ede78133Schristos 	      {
1216*e992f068Schristos 		free (ptr->code[i + 1].s - 1);
1217ede78133Schristos 		++i;
1218ede78133Schristos 	      }
1219ede78133Schristos 	  free (ptr->code);
1220ede78133Schristos 	}
1221ede78133Schristos       next = ptr->next;
1222ede78133Schristos       free (ptr);
1223ede78133Schristos       ptr = next;
1224ede78133Schristos     }
1225ede78133Schristos }
1226ede78133Schristos 
1227ede78133Schristos static void
perform(void)1228012573ebSchristos perform (void)
122975fd0b74Schristos {
123075fd0b74Schristos   tos = stack;
123175fd0b74Schristos 
123275fd0b74Schristos   while (at (ptr, idx))
123375fd0b74Schristos     {
123475fd0b74Schristos       /* It's worth looking through the command list.  */
123575fd0b74Schristos       if (iscommand (ptr, idx))
123675fd0b74Schristos 	{
123775fd0b74Schristos 	  char *next;
123875fd0b74Schristos 	  dict_type *word;
123975fd0b74Schristos 
124075fd0b74Schristos 	  (void) nextword (addr (ptr, idx), &next);
124175fd0b74Schristos 
124275fd0b74Schristos 	  word = lookup_word (next);
124375fd0b74Schristos 
124475fd0b74Schristos 	  if (word)
124575fd0b74Schristos 	    {
124675fd0b74Schristos 	      exec (word);
124775fd0b74Schristos 	    }
124875fd0b74Schristos 	  else
124975fd0b74Schristos 	    {
125075fd0b74Schristos 	      if (warning)
125175fd0b74Schristos 		fprintf (stderr, "warning, %s is not recognised\n", next);
1252*e992f068Schristos 	      idx = skip_past_newline_1 (ptr, idx);
125375fd0b74Schristos 	    }
125475fd0b74Schristos 	  free (next);
125575fd0b74Schristos 	}
125675fd0b74Schristos       else
1257*e992f068Schristos 	idx = skip_past_newline_1 (ptr, idx);
125875fd0b74Schristos     }
125975fd0b74Schristos }
126075fd0b74Schristos 
126175fd0b74Schristos dict_type *
newentry(char * word)1262*e992f068Schristos newentry (char *word)
126375fd0b74Schristos {
1264*e992f068Schristos   dict_type *new_d = xmalloc (sizeof (*new_d));
126575fd0b74Schristos   new_d->word = word;
126675fd0b74Schristos   new_d->next = root;
126775fd0b74Schristos   root = new_d;
1268*e992f068Schristos   new_d->code = xmalloc (sizeof (*new_d->code));
126975fd0b74Schristos   new_d->code_length = 1;
127075fd0b74Schristos   new_d->code_end = 0;
127175fd0b74Schristos   return new_d;
127275fd0b74Schristos }
127375fd0b74Schristos 
127475fd0b74Schristos unsigned int
add_to_definition(dict_type * entry,pcu word)1275*e992f068Schristos add_to_definition (dict_type *entry, pcu word)
127675fd0b74Schristos {
127775fd0b74Schristos   if (entry->code_end == entry->code_length)
127875fd0b74Schristos     {
127975fd0b74Schristos       entry->code_length += 2;
1280*e992f068Schristos       entry->code = xrealloc (entry->code,
1281*e992f068Schristos 			      entry->code_length * sizeof (*entry->code));
128275fd0b74Schristos     }
128375fd0b74Schristos   entry->code[entry->code_end] = word;
128475fd0b74Schristos 
128575fd0b74Schristos   return entry->code_end++;
128675fd0b74Schristos }
128775fd0b74Schristos 
128875fd0b74Schristos void
add_intrinsic(char * name,void (* func)(void))1289*e992f068Schristos add_intrinsic (char *name, void (*func) (void))
129075fd0b74Schristos {
1291*e992f068Schristos   dict_type *new_d = newentry (xstrdup (name));
1292*e992f068Schristos   pcu p = { func };
1293*e992f068Schristos   add_to_definition (new_d, p);
1294*e992f068Schristos   p.f = 0;
1295*e992f068Schristos   add_to_definition (new_d, p);
129675fd0b74Schristos }
129775fd0b74Schristos 
129875fd0b74Schristos void
compile(char * string)1299*e992f068Schristos compile (char *string)
130075fd0b74Schristos {
130175fd0b74Schristos   /* Add words to the dictionary.  */
130275fd0b74Schristos   char *word;
1303ede78133Schristos 
130475fd0b74Schristos   string = nextword (string, &word);
130575fd0b74Schristos   while (string && *string && word[0])
130675fd0b74Schristos     {
1307*e992f068Schristos       if (word[0] == ':')
130875fd0b74Schristos 	{
130975fd0b74Schristos 	  dict_type *ptr;
1310*e992f068Schristos 	  pcu p;
131175fd0b74Schristos 
1312ede78133Schristos 	  /* Compile a word and add to dictionary.  */
1313ede78133Schristos 	  free (word);
1314ede78133Schristos 	  string = nextword (string, &word);
1315012573ebSchristos 	  if (!string)
1316012573ebSchristos 	    continue;
131775fd0b74Schristos 	  ptr = newentry (word);
131875fd0b74Schristos 	  string = nextword (string, &word);
1319012573ebSchristos 	  if (!string)
1320012573ebSchristos 	    {
1321012573ebSchristos 	      free (ptr->code);
1322012573ebSchristos 	      free (ptr);
1323012573ebSchristos 	      continue;
1324012573ebSchristos 	    }
1325ede78133Schristos 
132675fd0b74Schristos 	  while (word[0] != ';')
132775fd0b74Schristos 	    {
132875fd0b74Schristos 	      switch (word[0])
132975fd0b74Schristos 		{
133075fd0b74Schristos 		case '"':
133175fd0b74Schristos 		  /* got a string, embed magic push string
133275fd0b74Schristos 		     function */
1333*e992f068Schristos 		  p.f = push_text;
1334*e992f068Schristos 		  add_to_definition (ptr, p);
1335*e992f068Schristos 		  p.s = word + 1;
1336*e992f068Schristos 		  add_to_definition (ptr, p);
133775fd0b74Schristos 		  break;
133875fd0b74Schristos 		case '0':
133975fd0b74Schristos 		case '1':
134075fd0b74Schristos 		case '2':
134175fd0b74Schristos 		case '3':
134275fd0b74Schristos 		case '4':
134375fd0b74Schristos 		case '5':
134475fd0b74Schristos 		case '6':
134575fd0b74Schristos 		case '7':
134675fd0b74Schristos 		case '8':
134775fd0b74Schristos 		case '9':
134875fd0b74Schristos 		  /* Got a number, embedd the magic push number
134975fd0b74Schristos 		     function */
1350*e992f068Schristos 		  p.f = push_number;
1351*e992f068Schristos 		  add_to_definition (ptr, p);
1352*e992f068Schristos 		  p.l = atol (word);
1353*e992f068Schristos 		  add_to_definition (ptr, p);
1354ede78133Schristos 		  free (word);
135575fd0b74Schristos 		  break;
135675fd0b74Schristos 		default:
1357*e992f068Schristos 		  p.f = call;
1358*e992f068Schristos 		  add_to_definition (ptr, p);
1359*e992f068Schristos 		  p.e = lookup_word (word);
1360*e992f068Schristos 		  add_to_definition (ptr, p);
1361ede78133Schristos 		  free (word);
136275fd0b74Schristos 		}
136375fd0b74Schristos 
136475fd0b74Schristos 	      string = nextword (string, &word);
136575fd0b74Schristos 	    }
1366*e992f068Schristos 	  p.f = 0;
1367*e992f068Schristos 	  add_to_definition (ptr, p);
1368ede78133Schristos 	  free (word);
136975fd0b74Schristos 	  string = nextword (string, &word);
137075fd0b74Schristos 	}
137175fd0b74Schristos       else
137275fd0b74Schristos 	{
137375fd0b74Schristos 	  fprintf (stderr, "syntax error at %s\n", string - 1);
137475fd0b74Schristos 	}
137575fd0b74Schristos     }
1376ede78133Schristos   free (word);
137775fd0b74Schristos }
137875fd0b74Schristos 
137975fd0b74Schristos static void
bang(void)1380*e992f068Schristos bang (void)
138175fd0b74Schristos {
138275fd0b74Schristos   *(long *) ((isp[0])) = isp[-1];
138375fd0b74Schristos   isp -= 2;
138475fd0b74Schristos   icheck_range ();
138575fd0b74Schristos   pc++;
138675fd0b74Schristos }
138775fd0b74Schristos 
138875fd0b74Schristos static void
atsign(void)1389*e992f068Schristos atsign (void)
139075fd0b74Schristos {
139175fd0b74Schristos   isp[0] = *(long *) (isp[0]);
139275fd0b74Schristos   pc++;
139375fd0b74Schristos }
139475fd0b74Schristos 
139575fd0b74Schristos static void
hello(void)1396*e992f068Schristos hello (void)
139775fd0b74Schristos {
139875fd0b74Schristos   printf ("hello\n");
139975fd0b74Schristos   pc++;
140075fd0b74Schristos }
140175fd0b74Schristos 
140275fd0b74Schristos static void
stdout_(void)1403*e992f068Schristos stdout_ (void)
140475fd0b74Schristos {
140575fd0b74Schristos   isp++;
140675fd0b74Schristos   icheck_range ();
140775fd0b74Schristos   *isp = 1;
140875fd0b74Schristos   pc++;
140975fd0b74Schristos }
141075fd0b74Schristos 
141175fd0b74Schristos static void
stderr_(void)1412*e992f068Schristos stderr_ (void)
141375fd0b74Schristos {
141475fd0b74Schristos   isp++;
141575fd0b74Schristos   icheck_range ();
141675fd0b74Schristos   *isp = 2;
141775fd0b74Schristos   pc++;
141875fd0b74Schristos }
141975fd0b74Schristos 
142075fd0b74Schristos static void
print(void)1421*e992f068Schristos print (void)
142275fd0b74Schristos {
142375fd0b74Schristos   if (*isp == 1)
142475fd0b74Schristos     write_buffer (tos, stdout);
142575fd0b74Schristos   else if (*isp == 2)
142675fd0b74Schristos     write_buffer (tos, stderr);
142775fd0b74Schristos   else
142875fd0b74Schristos     fprintf (stderr, "print: illegal print destination `%ld'\n", *isp);
142975fd0b74Schristos   isp--;
143075fd0b74Schristos   tos--;
143175fd0b74Schristos   icheck_range ();
143275fd0b74Schristos   check_range ();
143375fd0b74Schristos   pc++;
143475fd0b74Schristos }
143575fd0b74Schristos 
143675fd0b74Schristos static void
read_in(string_type * str,FILE * file)1437*e992f068Schristos read_in (string_type *str, FILE *file)
143875fd0b74Schristos {
143975fd0b74Schristos   char buff[10000];
144075fd0b74Schristos   unsigned int r;
144175fd0b74Schristos   do
144275fd0b74Schristos     {
144375fd0b74Schristos       r = fread (buff, 1, sizeof (buff), file);
144475fd0b74Schristos       catbuf (str, buff, r);
144575fd0b74Schristos     }
144675fd0b74Schristos   while (r);
144775fd0b74Schristos   buff[0] = 0;
144875fd0b74Schristos 
144975fd0b74Schristos   catbuf (str, buff, 1);
145075fd0b74Schristos }
145175fd0b74Schristos 
145275fd0b74Schristos static void
usage(void)1453*e992f068Schristos usage (void)
145475fd0b74Schristos {
145575fd0b74Schristos   fprintf (stderr, "usage: -[d|i|g] <file >file\n");
145675fd0b74Schristos   exit (33);
145775fd0b74Schristos }
145875fd0b74Schristos 
145975fd0b74Schristos /* There is no reliable way to declare exit.  Sometimes it returns
146075fd0b74Schristos    int, and sometimes it returns void.  Sometimes it changes between
146175fd0b74Schristos    OS releases.  Trying to get it declared correctly in the hosts file
146275fd0b74Schristos    is a pointless waste of time.  */
146375fd0b74Schristos 
146475fd0b74Schristos static void
chew_exit(void)1465*e992f068Schristos chew_exit (void)
146675fd0b74Schristos {
146775fd0b74Schristos   exit (0);
146875fd0b74Schristos }
146975fd0b74Schristos 
147075fd0b74Schristos int
main(int ac,char * av[])1471*e992f068Schristos main (int ac, char *av[])
147275fd0b74Schristos {
147375fd0b74Schristos   unsigned int i;
147475fd0b74Schristos   string_type buffer;
147575fd0b74Schristos   string_type pptr;
147675fd0b74Schristos 
147775fd0b74Schristos   init_string (&buffer);
147875fd0b74Schristos   init_string (&pptr);
147975fd0b74Schristos   init_string (stack + 0);
148075fd0b74Schristos   tos = stack + 1;
148175fd0b74Schristos   ptr = &pptr;
148275fd0b74Schristos 
148375fd0b74Schristos   add_intrinsic ("push_text", push_text);
148475fd0b74Schristos   add_intrinsic ("!", bang);
148575fd0b74Schristos   add_intrinsic ("@", atsign);
148675fd0b74Schristos   add_intrinsic ("hello", hello);
148775fd0b74Schristos   add_intrinsic ("stdout", stdout_);
148875fd0b74Schristos   add_intrinsic ("stderr", stderr_);
148975fd0b74Schristos   add_intrinsic ("print", print);
149075fd0b74Schristos   add_intrinsic ("skip_past_newline", skip_past_newline);
149175fd0b74Schristos   add_intrinsic ("catstr", icatstr);
149275fd0b74Schristos   add_intrinsic ("copy_past_newline", icopy_past_newline);
149375fd0b74Schristos   add_intrinsic ("dup", other_dup);
149475fd0b74Schristos   add_intrinsic ("drop", drop);
149575fd0b74Schristos   add_intrinsic ("idrop", idrop);
149675fd0b74Schristos   add_intrinsic ("remchar", remchar);
149775fd0b74Schristos   add_intrinsic ("get_stuff_in_command", get_stuff_in_command);
149875fd0b74Schristos   add_intrinsic ("do_fancy_stuff", do_fancy_stuff);
149975fd0b74Schristos   add_intrinsic ("bulletize", bulletize);
150075fd0b74Schristos   add_intrinsic ("courierize", courierize);
150175fd0b74Schristos   /* If the following line gives an error, exit() is not declared in the
150275fd0b74Schristos      ../hosts/foo.h file for this host.  Fix it there, not here!  */
150375fd0b74Schristos   /* No, don't fix it anywhere; see comment on chew_exit--Ian Taylor.  */
150475fd0b74Schristos   add_intrinsic ("exit", chew_exit);
150575fd0b74Schristos   add_intrinsic ("swap", swap);
150675fd0b74Schristos   add_intrinsic ("outputdots", outputdots);
150775fd0b74Schristos   add_intrinsic ("paramstuff", paramstuff);
150875fd0b74Schristos   add_intrinsic ("maybecatstr", maybecatstr);
150975fd0b74Schristos   add_intrinsic ("translatecomments", translatecomments);
151075fd0b74Schristos   add_intrinsic ("kill_bogus_lines", kill_bogus_lines);
151175fd0b74Schristos   add_intrinsic ("indent", indent);
151275fd0b74Schristos   add_intrinsic ("internalmode", internalmode);
151375fd0b74Schristos   add_intrinsic ("print_stack_level", print_stack_level);
151475fd0b74Schristos   add_intrinsic ("strip_trailing_newlines", strip_trailing_newlines);
151575fd0b74Schristos 
151675fd0b74Schristos   /* Put a nl at the start.  */
151775fd0b74Schristos   catchar (&buffer, '\n');
151875fd0b74Schristos 
151975fd0b74Schristos   read_in (&buffer, stdin);
152075fd0b74Schristos   remove_noncomments (&buffer, ptr);
152175fd0b74Schristos   for (i = 1; i < (unsigned int) ac; i++)
152275fd0b74Schristos     {
152375fd0b74Schristos       if (av[i][0] == '-')
152475fd0b74Schristos 	{
152575fd0b74Schristos 	  if (av[i][1] == 'f')
152675fd0b74Schristos 	    {
152775fd0b74Schristos 	      string_type b;
152875fd0b74Schristos 	      FILE *f;
152975fd0b74Schristos 	      init_string (&b);
153075fd0b74Schristos 
153175fd0b74Schristos 	      f = fopen (av[i + 1], "r");
153275fd0b74Schristos 	      if (!f)
153375fd0b74Schristos 		{
153475fd0b74Schristos 		  fprintf (stderr, "Can't open the input file %s\n",
153575fd0b74Schristos 			   av[i + 1]);
153675fd0b74Schristos 		  return 33;
153775fd0b74Schristos 		}
153875fd0b74Schristos 
153975fd0b74Schristos 	      read_in (&b, f);
154075fd0b74Schristos 	      compile (b.ptr);
154175fd0b74Schristos 	      perform ();
1542ede78133Schristos 	      delete_string (&b);
154375fd0b74Schristos 	    }
154475fd0b74Schristos 	  else if (av[i][1] == 'i')
154575fd0b74Schristos 	    {
154675fd0b74Schristos 	      internal_wanted = 1;
154775fd0b74Schristos 	    }
154875fd0b74Schristos 	  else if (av[i][1] == 'w')
154975fd0b74Schristos 	    {
155075fd0b74Schristos 	      warning = 1;
155175fd0b74Schristos 	    }
155275fd0b74Schristos 	  else
155375fd0b74Schristos 	    usage ();
155475fd0b74Schristos 	}
155575fd0b74Schristos     }
155675fd0b74Schristos   write_buffer (stack + 0, stdout);
1557ede78133Schristos   free_words ();
1558ede78133Schristos   delete_string (&pptr);
1559ede78133Schristos   delete_string (&buffer);
156075fd0b74Schristos   if (tos != stack)
156175fd0b74Schristos     {
156275fd0b74Schristos       fprintf (stderr, "finishing with current stack level %ld\n",
156375fd0b74Schristos 	       (long) (tos - stack));
156475fd0b74Schristos       return 1;
156575fd0b74Schristos     }
156675fd0b74Schristos   return 0;
156775fd0b74Schristos }
1568