133965Sjdp/* chew
291041Sobrien   Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998, 2000, 2001,
3218822Sdim   2002, 2003, 2005
438889Sjdp   Free Software Foundation, Inc.
533965Sjdp   Contributed by steve chamberlain @cygnus
633965Sjdp
733965SjdpThis file is part of BFD, the Binary File Descriptor library.
833965Sjdp
933965SjdpThis program is free software; you can redistribute it and/or modify
1033965Sjdpit under the terms of the GNU General Public License as published by
1133965Sjdpthe Free Software Foundation; either version 2 of the License, or
1233965Sjdp(at your option) any later version.
1333965Sjdp
1433965SjdpThis program is distributed in the hope that it will be useful,
1533965Sjdpbut WITHOUT ANY WARRANTY; without even the implied warranty of
1633965SjdpMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1733965SjdpGNU General Public License for more details.
1833965Sjdp
1933965SjdpYou should have received a copy of the GNU General Public License
2033965Sjdpalong with this program; if not, write to the Free Software
21218822SdimFoundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
2233965Sjdp
2333965Sjdp/* Yet another way of extracting documentation from source.
2433965Sjdp   No, I haven't finished it yet, but I hope you people like it better
2533965Sjdp   than the old way
2677298Sobrien
2733965Sjdp   sac
2833965Sjdp
2933965Sjdp   Basically, this is a sort of string forth, maybe we should call it
3033965Sjdp   struth?
3133965Sjdp
3233965Sjdp   You define new words thus:
3333965Sjdp   : <newword> <oldwords> ;
3433965Sjdp
3533965Sjdp*/
3633965Sjdp
3733965Sjdp/* Primitives provided by the program:
3833965Sjdp
3933965Sjdp   Two stacks are provided, a string stack and an integer stack.
4033965Sjdp
4133965Sjdp   Internal state variables:
4233965Sjdp	internal_wanted - indicates whether `-i' was passed
4333965Sjdp	internal_mode - user-settable
4433965Sjdp
4533965Sjdp   Commands:
4633965Sjdp	push_text
4733965Sjdp	! - pop top of integer stack for address, pop next for value; store
4833965Sjdp	@ - treat value on integer stack as the address of an integer; push
4933965Sjdp		that integer on the integer stack after popping the "address"
5033965Sjdp	hello - print "hello\n" to stdout
5133965Sjdp	stdout - put stdout marker on TOS
5233965Sjdp	stderr - put stderr marker on TOS
5333965Sjdp	print - print TOS-1 on TOS (eg: "hello\n" stdout print)
5433965Sjdp	skip_past_newline
5533965Sjdp	catstr - fn icatstr
5633965Sjdp	copy_past_newline - append input, up to and including newline into TOS
5733965Sjdp	dup - fn other_dup
5833965Sjdp	drop - discard TOS
5933965Sjdp	idrop - ditto
6033965Sjdp	remchar - delete last character from TOS
6133965Sjdp	get_stuff_in_command
6233965Sjdp	do_fancy_stuff - translate <<foo>> to @code{foo} in TOS
6333965Sjdp	bulletize - if "o" lines found, prepend @itemize @bullet to TOS
6433965Sjdp		and @item to each "o" line; append @end itemize
6533965Sjdp	courierize - put @example around . and | lines, translate {* *} { }
6633965Sjdp	exit - fn chew_exit
6733965Sjdp	swap
6833965Sjdp	outputdots - strip out lines without leading dots
6933965Sjdp	paramstuff - convert full declaration into "PARAMS" form if not already
7033965Sjdp	maybecatstr - do catstr if internal_mode == internal_wanted, discard
7133965Sjdp		value in any case
7233965Sjdp	translatecomments - turn {* and *} into comment delimiters
7333965Sjdp	kill_bogus_lines - get rid of extra newlines
7433965Sjdp	indent
7533965Sjdp	internalmode - pop from integer stack, set `internalmode' to that value
7633965Sjdp	print_stack_level - print current stack depth to stderr
7733965Sjdp	strip_trailing_newlines - go ahead, guess...
7833965Sjdp	[quoted string] - push string onto string stack
7933965Sjdp	[word starting with digit] - push atol(str) onto integer stack
8033965Sjdp
8133965Sjdp   A command must be all upper-case, and alone on a line.
8233965Sjdp
8333965Sjdp   Foo.  */
8433965Sjdp
85104834Sobrien#include "ansidecl.h"
8633965Sjdp#include <assert.h>
8733965Sjdp#include <stdio.h>
8833965Sjdp#include <ctype.h>
89218822Sdim#include <stdlib.h>
90218822Sdim#include <string.h>
9133965Sjdp
9233965Sjdp#define DEF_SIZE 5000
9333965Sjdp#define STACK 50
9433965Sjdp
9533965Sjdpint internal_wanted;
9633965Sjdpint internal_mode;
9733965Sjdp
9833965Sjdpint warning;
9933965Sjdp
10077298Sobrien/* Here is a string type ...  */
10133965Sjdp
10277298Sobrientypedef struct buffer
10333965Sjdp{
10433965Sjdp  char *ptr;
10533965Sjdp  unsigned long write_idx;
10633965Sjdp  unsigned long size;
10733965Sjdp} string_type;
10833965Sjdp
10933965Sjdp#ifdef __STDC__
11033965Sjdpstatic void init_string_with_size (string_type *, unsigned int);
11133965Sjdpstatic void init_string (string_type *);
11233965Sjdpstatic int find (string_type *, char *);
11333965Sjdpstatic void write_buffer (string_type *, FILE *);
11433965Sjdpstatic void delete_string (string_type *);
11533965Sjdpstatic char *addr (string_type *, unsigned int);
11633965Sjdpstatic char at (string_type *, unsigned int);
11733965Sjdpstatic void catchar (string_type *, int);
11833965Sjdpstatic void overwrite_string (string_type *, string_type *);
11933965Sjdpstatic void catbuf (string_type *, char *, unsigned int);
12033965Sjdpstatic void cattext (string_type *, char *);
12133965Sjdpstatic void catstr (string_type *, string_type *);
12233965Sjdp#endif
12333965Sjdp
12477298Sobrienstatic void
12577298Sobrieninit_string_with_size (buffer, size)
12677298Sobrien     string_type *buffer;
12777298Sobrien     unsigned int size;
12833965Sjdp{
12977298Sobrien  buffer->write_idx = 0;
13077298Sobrien  buffer->size = size;
13177298Sobrien  buffer->ptr = malloc (size);
13233965Sjdp}
13333965Sjdp
13477298Sobrienstatic void
13577298Sobrieninit_string (buffer)
13677298Sobrien     string_type *buffer;
13733965Sjdp{
13877298Sobrien  init_string_with_size (buffer, DEF_SIZE);
13933965Sjdp}
14033965Sjdp
14177298Sobrienstatic int
14277298Sobrienfind (str, what)
14377298Sobrien     string_type *str;
14477298Sobrien     char *what;
14533965Sjdp{
14677298Sobrien  unsigned int i;
14777298Sobrien  char *p;
14877298Sobrien  p = what;
14977298Sobrien  for (i = 0; i < str->write_idx && *p; i++)
15033965Sjdp    {
15177298Sobrien      if (*p == str->ptr[i])
15277298Sobrien	p++;
15377298Sobrien      else
15477298Sobrien	p = what;
15533965Sjdp    }
15677298Sobrien  return (*p == 0);
15733965Sjdp}
15833965Sjdp
15977298Sobrienstatic void
16077298Sobrienwrite_buffer (buffer, f)
16177298Sobrien     string_type *buffer;
16277298Sobrien     FILE *f;
16333965Sjdp{
16477298Sobrien  fwrite (buffer->ptr, buffer->write_idx, 1, f);
16533965Sjdp}
16633965Sjdp
16777298Sobrienstatic void
16877298Sobriendelete_string (buffer)
16977298Sobrien     string_type *buffer;
17033965Sjdp{
17177298Sobrien  free (buffer->ptr);
17233965Sjdp}
17333965Sjdp
17477298Sobrienstatic char *
17577298Sobrienaddr (buffer, idx)
17677298Sobrien     string_type *buffer;
17777298Sobrien     unsigned int idx;
17833965Sjdp{
17977298Sobrien  return buffer->ptr + idx;
18033965Sjdp}
18133965Sjdp
18277298Sobrienstatic char
18377298Sobrienat (buffer, pos)
18477298Sobrien     string_type *buffer;
18577298Sobrien     unsigned int pos;
18633965Sjdp{
18777298Sobrien  if (pos >= buffer->write_idx)
18833965Sjdp    return 0;
18933965Sjdp  return buffer->ptr[pos];
19033965Sjdp}
19133965Sjdp
19277298Sobrienstatic void
19377298Sobriencatchar (buffer, ch)
19477298Sobrien     string_type *buffer;
19577298Sobrien     int ch;
19633965Sjdp{
19777298Sobrien  if (buffer->write_idx == buffer->size)
19833965Sjdp    {
19977298Sobrien      buffer->size *= 2;
20077298Sobrien      buffer->ptr = realloc (buffer->ptr, buffer->size);
20133965Sjdp    }
20233965Sjdp
20377298Sobrien  buffer->ptr[buffer->write_idx++] = ch;
20433965Sjdp}
20533965Sjdp
20677298Sobrienstatic void
20777298Sobrienoverwrite_string (dst, src)
20877298Sobrien     string_type *dst;
20977298Sobrien     string_type *src;
21033965Sjdp{
21177298Sobrien  free (dst->ptr);
21277298Sobrien  dst->size = src->size;
21377298Sobrien  dst->write_idx = src->write_idx;
21477298Sobrien  dst->ptr = src->ptr;
21533965Sjdp}
21633965Sjdp
21777298Sobrienstatic void
21877298Sobriencatbuf (buffer, buf, len)
21977298Sobrien     string_type *buffer;
22077298Sobrien     char *buf;
22177298Sobrien     unsigned int len;
22233965Sjdp{
22333965Sjdp  if (buffer->write_idx + len >= buffer->size)
22433965Sjdp    {
22533965Sjdp      while (buffer->write_idx + len >= buffer->size)
22633965Sjdp	buffer->size *= 2;
22733965Sjdp      buffer->ptr = realloc (buffer->ptr, buffer->size);
22833965Sjdp    }
22933965Sjdp  memcpy (buffer->ptr + buffer->write_idx, buf, len);
23033965Sjdp  buffer->write_idx += len;
23133965Sjdp}
23233965Sjdp
23377298Sobrienstatic void
23477298Sobriencattext (buffer, string)
23577298Sobrien     string_type *buffer;
23677298Sobrien     char *string;
23733965Sjdp{
23833965Sjdp  catbuf (buffer, string, (unsigned int) strlen (string));
23933965Sjdp}
24033965Sjdp
24177298Sobrienstatic void
24277298Sobriencatstr (dst, src)
24377298Sobrien     string_type *dst;
24477298Sobrien     string_type *src;
24533965Sjdp{
24633965Sjdp  catbuf (dst, src->ptr, src->write_idx);
24733965Sjdp}
24833965Sjdp
24977298Sobrienstatic unsigned int
25077298Sobrienskip_white_and_stars (src, idx)
25177298Sobrien     string_type *src;
25277298Sobrien     unsigned int idx;
25333965Sjdp{
25433965Sjdp  char c;
25577298Sobrien  while ((c = at (src, idx)),
25638889Sjdp	 isspace ((unsigned char) c)
25733965Sjdp	 || (c == '*'
25833965Sjdp	     /* Don't skip past end-of-comment or star as first
25933965Sjdp		character on its line.  */
26077298Sobrien	     && at (src, idx +1) != '/'
26177298Sobrien	     && at (src, idx -1) != '\n'))
26233965Sjdp    idx++;
26333965Sjdp  return idx;
26433965Sjdp}
26533965Sjdp
26633965Sjdp/***********************************************************************/
26733965Sjdp
26833965Sjdpstring_type stack[STACK];
26933965Sjdpstring_type *tos;
27033965Sjdp
27133965Sjdpunsigned int idx = 0; /* Pos in input buffer */
27233965Sjdpstring_type *ptr; /* and the buffer */
27333965Sjdptypedef void (*stinst_type)();
27433965Sjdpstinst_type *pc;
27533965Sjdpstinst_type sstack[STACK];
27633965Sjdpstinst_type *ssp = &sstack[0];
27733965Sjdplong istack[STACK];
27833965Sjdplong *isp = &istack[0];
27933965Sjdp
28033965Sjdptypedef int *word_type;
28133965Sjdp
28233965Sjdpstruct dict_struct
28333965Sjdp{
28477298Sobrien  char *word;
28577298Sobrien  struct dict_struct *next;
28677298Sobrien  stinst_type *code;
28777298Sobrien  int code_length;
28877298Sobrien  int code_end;
28977298Sobrien  int var;
29033965Sjdp};
29177298Sobrien
29233965Sjdptypedef struct dict_struct dict_type;
29377298Sobrien
29433965Sjdpstatic void
29533965Sjdpdie (msg)
29633965Sjdp     char *msg;
29733965Sjdp{
29833965Sjdp  fprintf (stderr, "%s\n", msg);
29933965Sjdp  exit (1);
30033965Sjdp}
30133965Sjdp
30233965Sjdpstatic void
30333965Sjdpcheck_range ()
30433965Sjdp{
30533965Sjdp  if (tos < stack)
30633965Sjdp    die ("underflow in string stack");
30733965Sjdp  if (tos >= stack + STACK)
30833965Sjdp    die ("overflow in string stack");
30933965Sjdp}
31033965Sjdp
31133965Sjdpstatic void
31233965Sjdpicheck_range ()
31333965Sjdp{
31433965Sjdp  if (isp < istack)
31533965Sjdp    die ("underflow in integer stack");
31633965Sjdp  if (isp >= istack + STACK)
31733965Sjdp    die ("overflow in integer stack");
31833965Sjdp}
31933965Sjdp
32033965Sjdp#ifdef __STDC__
32133965Sjdpstatic void exec (dict_type *);
32233965Sjdpstatic void call (void);
32333965Sjdpstatic void remchar (void), strip_trailing_newlines (void), push_number (void);
32433965Sjdpstatic void push_text (void);
32533965Sjdpstatic void remove_noncomments (string_type *, string_type *);
32633965Sjdpstatic void print_stack_level (void);
32738889Sjdpstatic void paramstuff (void), translatecomments (void);
32833965Sjdpstatic void outputdots (void), courierize (void), bulletize (void);
32933965Sjdpstatic void do_fancy_stuff (void);
33033965Sjdpstatic int iscommand (string_type *, unsigned int);
33133965Sjdpstatic int copy_past_newline (string_type *, unsigned int, string_type *);
33233965Sjdpstatic void icopy_past_newline (void), kill_bogus_lines (void), indent (void);
33333965Sjdpstatic void get_stuff_in_command (void), swap (void), other_dup (void);
33433965Sjdpstatic void drop (void), idrop (void);
33533965Sjdpstatic void icatstr (void), skip_past_newline (void), internalmode (void);
33633965Sjdpstatic void maybecatstr (void);
33733965Sjdpstatic char *nextword (char *, char **);
33833965Sjdpdict_type *lookup_word (char *);
33933965Sjdpstatic void perform (void);
34033965Sjdpdict_type *newentry (char *);
34133965Sjdpunsigned int add_to_definition (dict_type *, stinst_type);
34233965Sjdpvoid add_intrinsic (char *, void (*)());
34333965Sjdpvoid add_var (char *);
34433965Sjdpvoid compile (char *);
34533965Sjdpstatic void bang (void);
34633965Sjdpstatic void atsign (void);
34733965Sjdpstatic void hello (void);
34833965Sjdpstatic void stdout_ (void);
34933965Sjdpstatic void stderr_ (void);
35033965Sjdpstatic void print (void);
35133965Sjdpstatic void read_in (string_type *, FILE *);
35233965Sjdpstatic void usage (void);
35333965Sjdpstatic void chew_exit (void);
35433965Sjdp#endif
35533965Sjdp
35677298Sobrienstatic void
35777298Sobrienexec (word)
35877298Sobrien     dict_type *word;
35933965Sjdp{
36033965Sjdp  pc = word->code;
36177298Sobrien  while (*pc)
36277298Sobrien    (*pc) ();
36333965Sjdp}
36477298Sobrien
36591041Sobrienstatic void
36691041Sobriencall ()
36733965Sjdp{
36877298Sobrien  stinst_type *oldpc = pc;
36977298Sobrien  dict_type *e;
37077298Sobrien  e = (dict_type *) (pc[1]);
37177298Sobrien  exec (e);
37277298Sobrien  pc = oldpc + 2;
37333965Sjdp}
37433965Sjdp
37591041Sobrienstatic void
37691041Sobrienremchar ()
37733965Sjdp{
37833965Sjdp  if (tos->write_idx)
37977298Sobrien    tos->write_idx--;
38033965Sjdp  pc++;
38133965Sjdp}
38233965Sjdp
38333965Sjdpstatic void
38433965Sjdpstrip_trailing_newlines ()
38533965Sjdp{
38638889Sjdp  while ((isspace ((unsigned char) at (tos, tos->write_idx - 1))
38733965Sjdp	  || at (tos, tos->write_idx - 1) == '\n')
38833965Sjdp	 && tos->write_idx > 0)
38933965Sjdp    tos->write_idx--;
39033965Sjdp  pc++;
39133965Sjdp}
39233965Sjdp
39391041Sobrienstatic void
39491041Sobrienpush_number ()
39533965Sjdp{
39677298Sobrien  isp++;
39777298Sobrien  icheck_range ();
39877298Sobrien  pc++;
39977298Sobrien  *isp = (long) (*pc);
40077298Sobrien  pc++;
40133965Sjdp}
40233965Sjdp
40391041Sobrienstatic void
40491041Sobrienpush_text ()
40533965Sjdp{
40677298Sobrien  tos++;
40777298Sobrien  check_range ();
40877298Sobrien  init_string (tos);
40977298Sobrien  pc++;
41077298Sobrien  cattext (tos, *((char **) pc));
41177298Sobrien  pc++;
41233965Sjdp}
41333965Sjdp
41433965Sjdp/* This function removes everything not inside comments starting on
41533965Sjdp   the first char of the line from the  string, also when copying
41633965Sjdp   comments, removes blank space and leading *'s.
41733965Sjdp   Blank lines are turned into one blank line.  */
41833965Sjdp
41977298Sobrienstatic void
42077298Sobrienremove_noncomments (src, dst)
42177298Sobrien     string_type *src;
42277298Sobrien     string_type *dst;
42333965Sjdp{
42477298Sobrien  unsigned int idx = 0;
42577298Sobrien
42677298Sobrien  while (at (src, idx))
42733965Sjdp    {
42877298Sobrien      /* Now see if we have a comment at the start of the line.  */
42977298Sobrien      if (at (src, idx) == '\n'
43077298Sobrien	  && at (src, idx + 1) == '/'
43177298Sobrien	  && at (src, idx + 2) == '*')
43233965Sjdp	{
43377298Sobrien	  idx += 3;
43433965Sjdp
43577298Sobrien	  idx = skip_white_and_stars (src, idx);
43677298Sobrien
43777298Sobrien	  /* Remove leading dot */
43877298Sobrien	  if (at (src, idx) == '.')
43977298Sobrien	    idx++;
44077298Sobrien
44177298Sobrien	  /* Copy to the end of the line, or till the end of the
44277298Sobrien	     comment.  */
44377298Sobrien	  while (at (src, idx))
44433965Sjdp	    {
44577298Sobrien	      if (at (src, idx) == '\n')
44633965Sjdp		{
44777298Sobrien		  /* end of line, echo and scrape of leading blanks  */
44877298Sobrien		  if (at (src, idx + 1) == '\n')
44977298Sobrien		    catchar (dst, '\n');
45077298Sobrien		  catchar (dst, '\n');
45177298Sobrien		  idx++;
45277298Sobrien		  idx = skip_white_and_stars (src, idx);
45333965Sjdp		}
45477298Sobrien	      else if (at (src, idx) == '*' && at (src, idx + 1) == '/')
45533965Sjdp		{
45677298Sobrien		  idx += 2;
45777298Sobrien		  cattext (dst, "\nENDDD\n");
45877298Sobrien		  break;
45933965Sjdp		}
46077298Sobrien	      else
46133965Sjdp		{
46277298Sobrien		  catchar (dst, at (src, idx));
46377298Sobrien		  idx++;
46433965Sjdp		}
46533965Sjdp	    }
46633965Sjdp	}
46777298Sobrien      else
46877298Sobrien	idx++;
46933965Sjdp    }
47033965Sjdp}
47133965Sjdp
47233965Sjdpstatic void
47333965Sjdpprint_stack_level ()
47433965Sjdp{
47533965Sjdp  fprintf (stderr, "current string stack depth = %d, ", tos - stack);
47633965Sjdp  fprintf (stderr, "current integer stack depth = %d\n", isp - istack);
47733965Sjdp  pc++;
47833965Sjdp}
47933965Sjdp
48033965Sjdp/* turn:
48133965Sjdp     foobar name(stuff);
48233965Sjdp   into:
48333965Sjdp     foobar
48433965Sjdp     name PARAMS ((stuff));
48533965Sjdp   and a blank line.
48633965Sjdp */
48733965Sjdp
48833965Sjdpstatic void
489104834Sobrienparamstuff ()
49033965Sjdp{
49177298Sobrien  unsigned int openp;
49277298Sobrien  unsigned int fname;
49377298Sobrien  unsigned int idx;
49477298Sobrien  unsigned int len;
49577298Sobrien  string_type out;
49677298Sobrien  init_string (&out);
49733965Sjdp
498130561Sobrien#define NO_PARAMS 1
499130561Sobrien
50077298Sobrien  /* Make sure that it's not already param'd or proto'd.  */
501130561Sobrien  if (NO_PARAMS
502130561Sobrien      || find (tos, "PARAMS") || find (tos, "PROTO") || !find (tos, "("))
50333965Sjdp    {
50477298Sobrien      catstr (&out, tos);
50577298Sobrien    }
50677298Sobrien  else
50777298Sobrien    {
50877298Sobrien      /* Find the open paren.  */
50977298Sobrien      for (openp = 0; at (tos, openp) != '(' && at (tos, openp); openp++)
51077298Sobrien	;
51133965Sjdp
51277298Sobrien      fname = openp;
51377298Sobrien      /* Step back to the fname.  */
51477298Sobrien      fname--;
51577298Sobrien      while (fname && isspace ((unsigned char) at (tos, fname)))
51633965Sjdp	fname--;
51777298Sobrien      while (fname
51877298Sobrien	     && !isspace ((unsigned char) at (tos,fname))
51977298Sobrien	     && at (tos,fname) != '*')
52077298Sobrien	fname--;
52133965Sjdp
52277298Sobrien      fname++;
52377298Sobrien
52477298Sobrien      /* Output type, omitting trailing whitespace character(s), if
52577298Sobrien         any.  */
52677298Sobrien      for (len = fname; 0 < len; len--)
52733965Sjdp	{
52877298Sobrien	  if (!isspace ((unsigned char) at (tos, len - 1)))
52977298Sobrien	    break;
53033965Sjdp	}
53177298Sobrien      for (idx = 0; idx < len; idx++)
53277298Sobrien	catchar (&out, at (tos, idx));
53333965Sjdp
53477298Sobrien      cattext (&out, "\n");	/* Insert a newline between type and fnname */
53577298Sobrien
53677298Sobrien      /* Output function name, omitting trailing whitespace
53777298Sobrien         character(s), if any.  */
53877298Sobrien      for (len = openp; 0 < len; len--)
53933965Sjdp	{
54077298Sobrien	  if (!isspace ((unsigned char) at (tos, len - 1)))
54177298Sobrien	    break;
54233965Sjdp	}
54377298Sobrien      for (idx = fname; idx < len; idx++)
54477298Sobrien	catchar (&out, at (tos, idx));
54533965Sjdp
54677298Sobrien      cattext (&out, " PARAMS (");
54733965Sjdp
54877298Sobrien      for (idx = openp; at (tos, idx) && at (tos, idx) != ';'; idx++)
54977298Sobrien	catchar (&out, at (tos, idx));
55077298Sobrien
55177298Sobrien      cattext (&out, ");\n\n");
55233965Sjdp    }
55377298Sobrien  overwrite_string (tos, &out);
55477298Sobrien  pc++;
55577298Sobrien
55633965Sjdp}
55733965Sjdp
55833965Sjdp/* turn {*
55933965Sjdp   and *} into comments */
56033965Sjdp
56191041Sobrienstatic void
56291041Sobrientranslatecomments ()
56333965Sjdp{
56477298Sobrien  unsigned int idx = 0;
56577298Sobrien  string_type out;
56677298Sobrien  init_string (&out);
56777298Sobrien
56877298Sobrien  while (at (tos, idx))
56933965Sjdp    {
57077298Sobrien      if (at (tos, idx) == '{' && at (tos, idx + 1) == '*')
57133965Sjdp	{
57277298Sobrien	  cattext (&out, "/*");
57377298Sobrien	  idx += 2;
57433965Sjdp	}
57577298Sobrien      else if (at (tos, idx) == '*' && at (tos, idx + 1) == '}')
57633965Sjdp	{
57777298Sobrien	  cattext (&out, "*/");
57877298Sobrien	  idx += 2;
57933965Sjdp	}
58077298Sobrien      else
58133965Sjdp	{
58277298Sobrien	  catchar (&out, at (tos, idx));
58377298Sobrien	  idx++;
58433965Sjdp	}
58533965Sjdp    }
58633965Sjdp
58777298Sobrien  overwrite_string (tos, &out);
58833965Sjdp
58977298Sobrien  pc++;
59033965Sjdp}
59133965Sjdp
59233965Sjdp/* Mod tos so that only lines with leading dots remain */
59333965Sjdpstatic void
594104834Sobrienoutputdots ()
59533965Sjdp{
59677298Sobrien  unsigned int idx = 0;
59777298Sobrien  string_type out;
59877298Sobrien  init_string (&out);
59977298Sobrien
60077298Sobrien  while (at (tos, idx))
60133965Sjdp    {
60277298Sobrien      if (at (tos, idx) == '\n' && at (tos, idx + 1) == '.')
60333965Sjdp	{
60438889Sjdp	  char c;
60533965Sjdp	  idx += 2;
60677298Sobrien
60777298Sobrien	  while ((c = at (tos, idx)) && c != '\n')
60833965Sjdp	    {
60977298Sobrien	      if (c == '{' && at (tos, idx + 1) == '*')
61033965Sjdp		{
61177298Sobrien		  cattext (&out, "/*");
61277298Sobrien		  idx += 2;
61333965Sjdp		}
61477298Sobrien	      else if (c == '*' && at (tos, idx + 1) == '}')
61533965Sjdp		{
61677298Sobrien		  cattext (&out, "*/");
61777298Sobrien		  idx += 2;
61833965Sjdp		}
61933965Sjdp	      else
62033965Sjdp		{
62177298Sobrien		  catchar (&out, c);
62277298Sobrien		  idx++;
62333965Sjdp		}
62433965Sjdp	    }
62577298Sobrien	  catchar (&out, '\n');
62633965Sjdp	}
62777298Sobrien      else
62833965Sjdp	{
62977298Sobrien	  idx++;
63033965Sjdp	}
63177298Sobrien    }
63233965Sjdp
63377298Sobrien  overwrite_string (tos, &out);
63477298Sobrien  pc++;
63533965Sjdp}
63633965Sjdp
63733965Sjdp/* Find lines starting with . and | and put example around them on tos */
63891041Sobrienstatic void
63991041Sobriencourierize ()
64033965Sjdp{
64177298Sobrien  string_type out;
64277298Sobrien  unsigned int idx = 0;
64377298Sobrien  int command = 0;
64477298Sobrien
64577298Sobrien  init_string (&out);
64677298Sobrien
64777298Sobrien  while (at (tos, idx))
64833965Sjdp    {
64977298Sobrien      if (at (tos, idx) == '\n'
65077298Sobrien	  && (at (tos, idx +1 ) == '.'
65177298Sobrien	      || at (tos, idx + 1) == '|'))
65233965Sjdp	{
65377298Sobrien	  cattext (&out, "\n@example\n");
65477298Sobrien	  do
65533965Sjdp	    {
65677298Sobrien	      idx += 2;
65777298Sobrien
65877298Sobrien	      while (at (tos, idx) && at (tos, idx) != '\n')
65933965Sjdp		{
66091041Sobrien		  if (command > 1)
66133965Sjdp		    {
66291041Sobrien		      /* We are inside {} parameters of some command;
66391041Sobrien			 Just pass through until matching brace.  */
66491041Sobrien		      if (at (tos, idx) == '{')
66591041Sobrien			++command;
66691041Sobrien		      else if (at (tos, idx) == '}')
66791041Sobrien			--command;
66891041Sobrien		    }
66991041Sobrien		  else if (command != 0)
67091041Sobrien		    {
67191041Sobrien		      if (at (tos, idx) == '{')
67291041Sobrien			++command;
67391041Sobrien		      else if (!islower ((unsigned char) at (tos, idx)))
67491041Sobrien			--command;
67591041Sobrien		    }
67691041Sobrien		  else if (at (tos, idx) == '@'
67791041Sobrien			   && islower ((unsigned char) at (tos, idx + 1)))
67891041Sobrien		    {
67991041Sobrien		      ++command;
68091041Sobrien		    }
68191041Sobrien		  else if (at (tos, idx) == '{' && at (tos, idx + 1) == '*')
68291041Sobrien		    {
68377298Sobrien		      cattext (&out, "/*");
68477298Sobrien		      idx += 2;
68591041Sobrien		      continue;
68633965Sjdp		    }
68777298Sobrien		  else if (at (tos, idx) == '*' && at (tos, idx + 1) == '}')
68833965Sjdp		    {
68977298Sobrien		      cattext (&out, "*/");
69077298Sobrien		      idx += 2;
69191041Sobrien		      continue;
69233965Sjdp		    }
69391041Sobrien		  else if (at (tos, idx) == '{'
69491041Sobrien			   || at (tos, idx) == '}')
69533965Sjdp		    {
69691041Sobrien		      catchar (&out, '@');
69733965Sjdp		    }
69877298Sobrien
69991041Sobrien		  catchar (&out, at (tos, idx));
70091041Sobrien		  idx++;
70133965Sjdp		}
70277298Sobrien	      catchar (&out, '\n');
70377298Sobrien	    }
70477298Sobrien	  while (at (tos, idx) == '\n'
70577298Sobrien		 && ((at (tos, idx + 1) == '.')
70677298Sobrien		     || (at (tos, idx + 1) == '|')))
70777298Sobrien	    ;
70877298Sobrien	  cattext (&out, "@end example");
70933965Sjdp	}
71077298Sobrien      else
71177298Sobrien	{
71277298Sobrien	  catchar (&out, at (tos, idx));
71377298Sobrien	  idx++;
71433965Sjdp	}
71577298Sobrien    }
71633965Sjdp
71777298Sobrien  overwrite_string (tos, &out);
71877298Sobrien  pc++;
71933965Sjdp}
72033965Sjdp
72133965Sjdp/* Finds any lines starting with "o ", if there are any, then turns
72233965Sjdp   on @itemize @bullet, and @items each of them. Then ends with @end
72333965Sjdp   itemize, inplace at TOS*/
72433965Sjdp
72591041Sobrienstatic void
72691041Sobrienbulletize ()
72777298Sobrien{
72877298Sobrien  unsigned int idx = 0;
72977298Sobrien  int on = 0;
73077298Sobrien  string_type out;
73177298Sobrien  init_string (&out);
73233965Sjdp
73377298Sobrien  while (at (tos, idx))
73477298Sobrien    {
73577298Sobrien      if (at (tos, idx) == '@'
73677298Sobrien	  && at (tos, idx + 1) == '*')
73733965Sjdp	{
73877298Sobrien	  cattext (&out, "*");
73977298Sobrien	  idx += 2;
74033965Sjdp	}
74177298Sobrien      else if (at (tos, idx) == '\n'
74277298Sobrien	       && at (tos, idx + 1) == 'o'
74377298Sobrien	       && isspace ((unsigned char) at (tos, idx + 2)))
74477298Sobrien	{
74577298Sobrien	  if (!on)
74633965Sjdp	    {
74777298Sobrien	      cattext (&out, "\n@itemize @bullet\n");
74877298Sobrien	      on = 1;
74977298Sobrien
75033965Sjdp	    }
75177298Sobrien	  cattext (&out, "\n@item\n");
75277298Sobrien	  idx += 3;
75377298Sobrien	}
75477298Sobrien      else
75577298Sobrien	{
75677298Sobrien	  catchar (&out, at (tos, idx));
75777298Sobrien	  if (on && at (tos, idx) == '\n'
75877298Sobrien	      && at (tos, idx + 1) == '\n'
75977298Sobrien	      && at (tos, idx + 2) != 'o')
76033965Sjdp	    {
76177298Sobrien	      cattext (&out, "@end itemize");
76277298Sobrien	      on = 0;
76333965Sjdp	    }
76477298Sobrien	  idx++;
76577298Sobrien
76633965Sjdp	}
76777298Sobrien    }
76877298Sobrien  if (on)
76933965Sjdp    {
77077298Sobrien      cattext (&out, "@end itemize\n");
77177298Sobrien    }
77233965Sjdp
77377298Sobrien  delete_string (tos);
77477298Sobrien  *tos = out;
77577298Sobrien  pc++;
77633965Sjdp}
77733965Sjdp
77833965Sjdp/* Turn <<foo>> into @code{foo} in place at TOS*/
77933965Sjdp
78091041Sobrienstatic void
78191041Sobriendo_fancy_stuff ()
78233965Sjdp{
78377298Sobrien  unsigned int idx = 0;
78477298Sobrien  string_type out;
78577298Sobrien  init_string (&out);
78677298Sobrien  while (at (tos, idx))
78733965Sjdp    {
78877298Sobrien      if (at (tos, idx) == '<'
78977298Sobrien	  && at (tos, idx + 1) == '<'
79077298Sobrien	  && !isspace ((unsigned char) at (tos, idx + 2)))
79133965Sjdp	{
79277298Sobrien	  /* This qualifies as a << startup.  */
79377298Sobrien	  idx += 2;
79477298Sobrien	  cattext (&out, "@code{");
79577298Sobrien	  while (at (tos, idx)
79677298Sobrien		 && at (tos, idx) != '>' )
79733965Sjdp	    {
79877298Sobrien	      catchar (&out, at (tos, idx));
79977298Sobrien	      idx++;
80077298Sobrien
80133965Sjdp	    }
80277298Sobrien	  cattext (&out, "}");
80377298Sobrien	  idx += 2;
80433965Sjdp	}
80577298Sobrien      else
80633965Sjdp	{
80777298Sobrien	  catchar (&out, at (tos, idx));
80877298Sobrien	  idx++;
80933965Sjdp	}
81033965Sjdp    }
81177298Sobrien  delete_string (tos);
81277298Sobrien  *tos = out;
81377298Sobrien  pc++;
81477298Sobrien
81533965Sjdp}
81677298Sobrien
81777298Sobrien/* A command is all upper case,and alone on a line.  */
81877298Sobrien
81977298Sobrienstatic int
82077298Sobrieniscommand (ptr, idx)
82177298Sobrien     string_type *ptr;
82277298Sobrien     unsigned int idx;
82333965Sjdp{
82477298Sobrien  unsigned int len = 0;
82577298Sobrien  while (at (ptr, idx))
82677298Sobrien    {
82777298Sobrien      if (isupper ((unsigned char) at (ptr, idx))
82877298Sobrien	  || at (ptr, idx) == ' ' || at (ptr, idx) == '_')
82977298Sobrien	{
83077298Sobrien	  len++;
83177298Sobrien	  idx++;
83233965Sjdp	}
83377298Sobrien      else if (at (ptr, idx) == '\n')
83477298Sobrien	{
83577298Sobrien	  if (len > 3)
83677298Sobrien	    return 1;
83777298Sobrien	  return 0;
83877298Sobrien	}
83977298Sobrien      else
84077298Sobrien	return 0;
84177298Sobrien    }
84277298Sobrien  return 0;
84333965Sjdp}
84433965Sjdp
84538889Sjdpstatic int
84677298Sobriencopy_past_newline (ptr, idx, dst)
84777298Sobrien     string_type *ptr;
84877298Sobrien     unsigned int idx;
84977298Sobrien     string_type *dst;
85033965Sjdp{
85177298Sobrien  int column = 0;
85238889Sjdp
85377298Sobrien  while (at (ptr, idx) && at (ptr, idx) != '\n')
85433965Sjdp    {
85577298Sobrien      if (at (ptr, idx) == '\t')
85677298Sobrien	{
85777298Sobrien	  /* Expand tabs.  Neither makeinfo nor TeX can cope well with
85877298Sobrien	     them.  */
85977298Sobrien	  do
86077298Sobrien	    catchar (dst, ' ');
86177298Sobrien	  while (++column & 7);
86277298Sobrien	}
86377298Sobrien      else
86477298Sobrien	{
86577298Sobrien	  catchar (dst, at (ptr, idx));
86677298Sobrien	  column++;
86777298Sobrien	}
86877298Sobrien      idx++;
86933965Sjdp
87077298Sobrien    }
87177298Sobrien  catchar (dst, at (ptr, idx));
87277298Sobrien  idx++;
87377298Sobrien  return idx;
87477298Sobrien
87533965Sjdp}
87633965Sjdp
87791041Sobrienstatic void
87891041Sobrienicopy_past_newline ()
87933965Sjdp{
88077298Sobrien  tos++;
88177298Sobrien  check_range ();
88277298Sobrien  init_string (tos);
88377298Sobrien  idx = copy_past_newline (ptr, idx, tos);
88477298Sobrien  pc++;
88533965Sjdp}
88633965Sjdp
88733965Sjdp/* indent
88877298Sobrien   Take the string at the top of the stack, do some prettying.  */
88933965Sjdp
89091041Sobrienstatic void
89191041Sobrienkill_bogus_lines ()
89277298Sobrien{
89377298Sobrien  int sl;
89433965Sjdp
89577298Sobrien  int idx = 0;
89677298Sobrien  int c;
89777298Sobrien  int dot = 0;
89877298Sobrien
89977298Sobrien  string_type out;
90077298Sobrien  init_string (&out);
90177298Sobrien  /* Drop leading nl.  */
90277298Sobrien  while (at (tos, idx) == '\n')
90333965Sjdp    {
90477298Sobrien      idx++;
90533965Sjdp    }
90677298Sobrien  c = idx;
90738889Sjdp
90877298Sobrien  /* If the first char is a '.' prepend a newline so that it is
90977298Sobrien     recognized properly later.  */
91077298Sobrien  if (at (tos, idx) == '.')
91177298Sobrien    catchar (&out, '\n');
91277298Sobrien
91377298Sobrien  /* Find the last char.  */
91477298Sobrien  while (at (tos, idx))
91533965Sjdp    {
91677298Sobrien      idx++;
91733965Sjdp    }
91877298Sobrien
91977298Sobrien  /* Find the last non white before the nl.  */
92077298Sobrien  idx--;
92177298Sobrien
92277298Sobrien  while (idx && isspace ((unsigned char) at (tos, idx)))
92333965Sjdp    idx--;
92477298Sobrien  idx++;
92533965Sjdp
92677298Sobrien  /* Copy buffer upto last char, but blank lines before and after
92777298Sobrien     dots don't count.  */
92877298Sobrien  sl = 1;
92977298Sobrien
93077298Sobrien  while (c < idx)
93133965Sjdp    {
93277298Sobrien      if (at (tos, c) == '\n'
93377298Sobrien	  && at (tos, c + 1) == '\n'
93477298Sobrien	  && at (tos, c + 2) == '.')
93533965Sjdp	{
93677298Sobrien	  /* Ignore two newlines before a dot.  */
93777298Sobrien	  c++;
93833965Sjdp	}
93977298Sobrien      else if (at (tos, c) == '.' && sl)
94033965Sjdp	{
94177298Sobrien	  /* remember that this line started with a dot.  */
94277298Sobrien	  dot = 2;
94333965Sjdp	}
94477298Sobrien      else if (at (tos, c) == '\n'
94577298Sobrien	       && at (tos, c + 1) == '\n'
94677298Sobrien	       && dot)
94733965Sjdp	{
94877298Sobrien	  c++;
94977298Sobrien	  /* Ignore two newlines when last line was dot.  */
95033965Sjdp	}
95133965Sjdp
95277298Sobrien      catchar (&out, at (tos, c));
95377298Sobrien      if (at (tos, c) == '\n')
95433965Sjdp	{
95577298Sobrien	  sl = 1;
95677298Sobrien
95777298Sobrien	  if (dot == 2)
95877298Sobrien	    dot = 1;
95977298Sobrien	  else
96077298Sobrien	    dot = 0;
96133965Sjdp	}
96277298Sobrien      else
96377298Sobrien	sl = 0;
96433965Sjdp
96577298Sobrien      c++;
96677298Sobrien
96733965Sjdp    }
96877298Sobrien
96977298Sobrien  /* Append nl.  */
97077298Sobrien  catchar (&out, '\n');
97177298Sobrien  pc++;
97277298Sobrien  delete_string (tos);
97377298Sobrien  *tos = out;
97477298Sobrien
97533965Sjdp}
97633965Sjdp
97791041Sobrienstatic void
97891041Sobrienindent ()
97933965Sjdp{
98077298Sobrien  string_type out;
98177298Sobrien  int tab = 0;
98277298Sobrien  int idx = 0;
98377298Sobrien  int ol = 0;
98477298Sobrien  init_string (&out);
98577298Sobrien  while (at (tos, idx))
98677298Sobrien    {
98777298Sobrien      switch (at (tos, idx))
98877298Sobrien	{
98977298Sobrien	case '\n':
99077298Sobrien	  cattext (&out, "\n");
99177298Sobrien	  idx++;
99277298Sobrien	  if (tab && at (tos, idx))
99333965Sjdp	    {
99477298Sobrien	      cattext (&out, "    ");
99533965Sjdp	    }
99677298Sobrien	  ol = 0;
99777298Sobrien	  break;
99877298Sobrien	case '(':
99977298Sobrien	  tab++;
100077298Sobrien	  if (ol == 0)
100177298Sobrien	    cattext (&out, "   ");
100277298Sobrien	  idx++;
100377298Sobrien	  cattext (&out, "(");
100477298Sobrien	  ol = 1;
100577298Sobrien	  break;
100677298Sobrien	case ')':
100777298Sobrien	  tab--;
100877298Sobrien	  cattext (&out, ")");
100977298Sobrien	  idx++;
101077298Sobrien	  ol = 1;
101133965Sjdp
101277298Sobrien	  break;
101377298Sobrien	default:
101477298Sobrien	  catchar (&out, at (tos, idx));
101577298Sobrien	  ol = 1;
101633965Sjdp
101777298Sobrien	  idx++;
101877298Sobrien	  break;
101977298Sobrien	}
102077298Sobrien    }
102177298Sobrien
102277298Sobrien  pc++;
102377298Sobrien  delete_string (tos);
102477298Sobrien  *tos = out;
102577298Sobrien
102633965Sjdp}
102733965Sjdp
102891041Sobrienstatic void
102991041Sobrienget_stuff_in_command ()
103033965Sjdp{
103177298Sobrien  tos++;
103277298Sobrien  check_range ();
103377298Sobrien  init_string (tos);
103433965Sjdp
103577298Sobrien  while (at (ptr, idx))
103677298Sobrien    {
103777298Sobrien      if (iscommand (ptr, idx))
103877298Sobrien	break;
103977298Sobrien      idx = copy_past_newline (ptr, idx, tos);
104077298Sobrien    }
104177298Sobrien  pc++;
104233965Sjdp}
104333965Sjdp
104491041Sobrienstatic void
104591041Sobrienswap ()
104633965Sjdp{
104777298Sobrien  string_type t;
104877298Sobrien
104977298Sobrien  t = tos[0];
105077298Sobrien  tos[0] = tos[-1];
105177298Sobrien  tos[-1] = t;
105277298Sobrien  pc++;
105333965Sjdp}
105433965Sjdp
105591041Sobrienstatic void
105691041Sobrienother_dup ()
105733965Sjdp{
105877298Sobrien  tos++;
105977298Sobrien  check_range ();
106077298Sobrien  init_string (tos);
106177298Sobrien  catstr (tos, tos - 1);
106277298Sobrien  pc++;
106333965Sjdp}
106433965Sjdp
106591041Sobrienstatic void
106691041Sobriendrop ()
106733965Sjdp{
106833965Sjdp  tos--;
106933965Sjdp  check_range ();
107033965Sjdp  pc++;
107133965Sjdp}
107233965Sjdp
107391041Sobrienstatic void
107491041Sobrienidrop ()
107533965Sjdp{
107633965Sjdp  isp--;
107733965Sjdp  icheck_range ();
107833965Sjdp  pc++;
107933965Sjdp}
108033965Sjdp
108191041Sobrienstatic void
108291041Sobrienicatstr ()
108333965Sjdp{
108477298Sobrien  tos--;
108577298Sobrien  check_range ();
108677298Sobrien  catstr (tos, tos + 1);
108777298Sobrien  delete_string (tos + 1);
108877298Sobrien  pc++;
108933965Sjdp}
109033965Sjdp
109191041Sobrienstatic void
109291041Sobrienskip_past_newline ()
109333965Sjdp{
109477298Sobrien  while (at (ptr, idx)
109577298Sobrien	 && at (ptr, idx) != '\n')
109633965Sjdp    idx++;
109777298Sobrien  idx++;
109877298Sobrien  pc++;
109933965Sjdp}
110033965Sjdp
110191041Sobrienstatic void
110291041Sobrieninternalmode ()
110333965Sjdp{
110477298Sobrien  internal_mode = *(isp);
110577298Sobrien  isp--;
110677298Sobrien  icheck_range ();
110777298Sobrien  pc++;
110833965Sjdp}
110933965Sjdp
111091041Sobrienstatic void
111191041Sobrienmaybecatstr ()
111233965Sjdp{
111377298Sobrien  if (internal_wanted == internal_mode)
111433965Sjdp    {
111577298Sobrien      catstr (tos - 1, tos);
111633965Sjdp    }
111777298Sobrien  delete_string (tos);
111877298Sobrien  tos--;
111977298Sobrien  check_range ();
112077298Sobrien  pc++;
112133965Sjdp}
112233965Sjdp
112333965Sjdpchar *
112477298Sobriennextword (string, word)
112577298Sobrien     char *string;
112677298Sobrien     char **word;
112733965Sjdp{
112877298Sobrien  char *word_start;
112977298Sobrien  int idx;
113077298Sobrien  char *dst;
113177298Sobrien  char *src;
113277298Sobrien
113377298Sobrien  int length = 0;
113477298Sobrien
113577298Sobrien  while (isspace ((unsigned char) *string) || *string == '-')
113677298Sobrien    {
113777298Sobrien      if (*string == '-')
113833965Sjdp	{
113977298Sobrien	  while (*string && *string != '\n')
114033965Sjdp	    string++;
114177298Sobrien
114233965Sjdp	}
114377298Sobrien      else
114477298Sobrien	{
114577298Sobrien	  string++;
114677298Sobrien	}
114733965Sjdp    }
114877298Sobrien  if (!*string)
114977298Sobrien    return 0;
115033965Sjdp
115177298Sobrien  word_start = string;
115277298Sobrien  if (*string == '"')
115377298Sobrien    {
115477298Sobrien      do
115577298Sobrien	{
115677298Sobrien	  string++;
115777298Sobrien	  length++;
115877298Sobrien	  if (*string == '\\')
115933965Sjdp	    {
116077298Sobrien	      string += 2;
116177298Sobrien	      length += 2;
116233965Sjdp	    }
116377298Sobrien	}
116477298Sobrien      while (*string != '"');
116533965Sjdp    }
116677298Sobrien  else
116777298Sobrien    {
116877298Sobrien      while (!isspace ((unsigned char) *string))
116977298Sobrien	{
117077298Sobrien	  string++;
117177298Sobrien	  length++;
117233965Sjdp
117377298Sobrien	}
117477298Sobrien    }
117533965Sjdp
117677298Sobrien  *word = malloc (length + 1);
117733965Sjdp
117877298Sobrien  dst = *word;
117977298Sobrien  src = word_start;
118033965Sjdp
118177298Sobrien  for (idx = 0; idx < length; idx++)
118277298Sobrien    {
118377298Sobrien      if (src[idx] == '\\')
118477298Sobrien	switch (src[idx + 1])
118577298Sobrien	  {
118677298Sobrien	  case 'n':
118777298Sobrien	    *dst++ = '\n';
118877298Sobrien	    idx++;
118977298Sobrien	    break;
119077298Sobrien	  case '"':
119177298Sobrien	  case '\\':
119277298Sobrien	    *dst++ = src[idx + 1];
119377298Sobrien	    idx++;
119477298Sobrien	    break;
119577298Sobrien	  default:
119677298Sobrien	    *dst++ = '\\';
119777298Sobrien	    break;
119877298Sobrien	  }
119977298Sobrien      else
120077298Sobrien	*dst++ = src[idx];
120177298Sobrien    }
120277298Sobrien  *dst++ = 0;
120333965Sjdp
120477298Sobrien  if (*string)
120577298Sobrien    return string + 1;
120677298Sobrien  else
120777298Sobrien    return 0;
120833965Sjdp}
120977298Sobrien
121033965Sjdpdict_type *root;
121177298Sobrien
121233965Sjdpdict_type *
121377298Sobrienlookup_word (word)
121477298Sobrien     char *word;
121533965Sjdp{
121633965Sjdp  dict_type *ptr = root;
121777298Sobrien  while (ptr)
121877298Sobrien    {
121977298Sobrien      if (strcmp (ptr->word, word) == 0)
122077298Sobrien	return ptr;
122133965Sjdp      ptr = ptr->next;
122233965Sjdp    }
122333965Sjdp  if (warning)
122477298Sobrien    fprintf (stderr, "Can't find %s\n", word);
122533965Sjdp  return 0;
122633965Sjdp}
122733965Sjdp
122877298Sobrienstatic void
1229104834Sobrienperform ()
123033965Sjdp{
123133965Sjdp  tos = stack;
123233965Sjdp
123377298Sobrien  while (at (ptr, idx))
123477298Sobrien    {
123577298Sobrien      /* It's worth looking through the command list.  */
123677298Sobrien      if (iscommand (ptr, idx))
123777298Sobrien	{
123877298Sobrien	  char *next;
123977298Sobrien	  dict_type *word;
124033965Sjdp
124177298Sobrien	  (void) nextword (addr (ptr, idx), &next);
124233965Sjdp
124377298Sobrien	  word = lookup_word (next);
124433965Sjdp
124577298Sobrien	  if (word)
124677298Sobrien	    {
124777298Sobrien	      exec (word);
124877298Sobrien	    }
124977298Sobrien	  else
125077298Sobrien	    {
125177298Sobrien	      if (warning)
125277298Sobrien		fprintf (stderr, "warning, %s is not recognised\n", next);
125377298Sobrien	      skip_past_newline ();
125477298Sobrien	    }
125533965Sjdp
125633965Sjdp	}
125777298Sobrien      else
125877298Sobrien	skip_past_newline ();
125933965Sjdp    }
126033965Sjdp}
126133965Sjdp
126233965Sjdpdict_type *
126377298Sobriennewentry (word)
126477298Sobrien     char *word;
126533965Sjdp{
126677298Sobrien  dict_type *new = (dict_type *) malloc (sizeof (dict_type));
126777298Sobrien  new->word = word;
126877298Sobrien  new->next = root;
126977298Sobrien  root = new;
127077298Sobrien  new->code = (stinst_type *) malloc (sizeof (stinst_type));
127177298Sobrien  new->code_length = 1;
127277298Sobrien  new->code_end = 0;
127377298Sobrien  return new;
127433965Sjdp}
127533965Sjdp
127633965Sjdpunsigned int
127777298Sobrienadd_to_definition (entry, word)
127877298Sobrien     dict_type *entry;
127977298Sobrien     stinst_type word;
128033965Sjdp{
128177298Sobrien  if (entry->code_end == entry->code_length)
128233965Sjdp    {
128377298Sobrien      entry->code_length += 2;
128477298Sobrien      entry->code =
128577298Sobrien	(stinst_type *) realloc ((char *) (entry->code),
128677298Sobrien				 entry->code_length * sizeof (word_type));
128733965Sjdp    }
128877298Sobrien  entry->code[entry->code_end] = word;
128977298Sobrien
129077298Sobrien  return entry->code_end++;
129133965Sjdp}
129233965Sjdp
129333965Sjdpvoid
129477298Sobrienadd_intrinsic (name, func)
129577298Sobrien     char *name;
129677298Sobrien     void (*func) ();
129733965Sjdp{
129877298Sobrien  dict_type *new = newentry (name);
129977298Sobrien  add_to_definition (new, func);
130077298Sobrien  add_to_definition (new, 0);
130133965Sjdp}
130233965Sjdp
130333965Sjdpvoid
130477298Sobrienadd_var (name)
130577298Sobrien     char *name;
130633965Sjdp{
130777298Sobrien  dict_type *new = newentry (name);
130877298Sobrien  add_to_definition (new, push_number);
130977298Sobrien  add_to_definition (new, (stinst_type) (&(new->var)));
131077298Sobrien  add_to_definition (new, 0);
131133965Sjdp}
131233965Sjdp
131377298Sobrienvoid
131477298Sobriencompile (string)
131577298Sobrien     char *string;
131633965Sjdp{
131777298Sobrien  /* Add words to the dictionary.  */
131877298Sobrien  char *word;
131977298Sobrien  string = nextword (string, &word);
132077298Sobrien  while (string && *string && word[0])
132133965Sjdp    {
132277298Sobrien      if (strcmp (word, "var") == 0)
132333965Sjdp	{
132477298Sobrien	  string = nextword (string, &word);
132577298Sobrien
132677298Sobrien	  add_var (word);
132777298Sobrien	  string = nextword (string, &word);
132833965Sjdp	}
132977298Sobrien      else if (word[0] == ':')
133033965Sjdp	{
133177298Sobrien	  dict_type *ptr;
133277298Sobrien	  /* Compile a word and add to dictionary.  */
133377298Sobrien	  string = nextword (string, &word);
133477298Sobrien
133577298Sobrien	  ptr = newentry (word);
133677298Sobrien	  string = nextword (string, &word);
133777298Sobrien	  while (word[0] != ';')
133833965Sjdp	    {
133977298Sobrien	      switch (word[0])
134077298Sobrien		{
134177298Sobrien		case '"':
134277298Sobrien		  /* got a string, embed magic push string
134377298Sobrien		     function */
134477298Sobrien		  add_to_definition (ptr, push_text);
134577298Sobrien		  add_to_definition (ptr, (stinst_type) (word + 1));
134677298Sobrien		  break;
134777298Sobrien		case '0':
134877298Sobrien		case '1':
134977298Sobrien		case '2':
135077298Sobrien		case '3':
135177298Sobrien		case '4':
135277298Sobrien		case '5':
135377298Sobrien		case '6':
135477298Sobrien		case '7':
135577298Sobrien		case '8':
135677298Sobrien		case '9':
135777298Sobrien		  /* Got a number, embedd the magic push number
135877298Sobrien		     function */
135977298Sobrien		  add_to_definition (ptr, push_number);
136077298Sobrien		  add_to_definition (ptr, (stinst_type) atol (word));
136177298Sobrien		  break;
136277298Sobrien		default:
136377298Sobrien		  add_to_definition (ptr, call);
136477298Sobrien		  add_to_definition (ptr, (stinst_type) lookup_word (word));
136577298Sobrien		}
136633965Sjdp
136777298Sobrien	      string = nextword (string, &word);
136833965Sjdp	    }
136977298Sobrien	  add_to_definition (ptr, 0);
137077298Sobrien	  string = nextword (string, &word);
137133965Sjdp	}
137277298Sobrien      else
137333965Sjdp	{
137477298Sobrien	  fprintf (stderr, "syntax error at %s\n", string - 1);
137577298Sobrien	}
137633965Sjdp    }
137733965Sjdp}
137833965Sjdp
137977298Sobrienstatic void
1380104834Sobrienbang ()
138133965Sjdp{
138277298Sobrien  *(long *) ((isp[0])) = isp[-1];
138377298Sobrien  isp -= 2;
138433965Sjdp  icheck_range ();
138533965Sjdp  pc++;
138633965Sjdp}
138733965Sjdp
138891041Sobrienstatic void
138991041Sobrienatsign ()
139033965Sjdp{
139177298Sobrien  isp[0] = *(long *) (isp[0]);
139277298Sobrien  pc++;
139333965Sjdp}
139433965Sjdp
139591041Sobrienstatic void
139691041Sobrienhello ()
139733965Sjdp{
139877298Sobrien  printf ("hello\n");
139977298Sobrien  pc++;
140033965Sjdp}
140133965Sjdp
140291041Sobrienstatic void
140391041Sobrienstdout_ ()
140433965Sjdp{
140533965Sjdp  isp++;
140633965Sjdp  icheck_range ();
140733965Sjdp  *isp = 1;
140833965Sjdp  pc++;
140933965Sjdp}
141033965Sjdp
141191041Sobrienstatic void
141291041Sobrienstderr_ ()
141333965Sjdp{
141433965Sjdp  isp++;
141533965Sjdp  icheck_range ();
141633965Sjdp  *isp = 2;
141733965Sjdp  pc++;
141833965Sjdp}
141933965Sjdp
142091041Sobrienstatic void
142191041Sobrienprint ()
142233965Sjdp{
142333965Sjdp  if (*isp == 1)
142433965Sjdp    write_buffer (tos, stdout);
142533965Sjdp  else if (*isp == 2)
142633965Sjdp    write_buffer (tos, stderr);
142733965Sjdp  else
142838889Sjdp    fprintf (stderr, "print: illegal print destination `%ld'\n", *isp);
142933965Sjdp  isp--;
143033965Sjdp  tos--;
143133965Sjdp  icheck_range ();
143233965Sjdp  check_range ();
143333965Sjdp  pc++;
143433965Sjdp}
143533965Sjdp
143677298Sobrienstatic void
143777298Sobrienread_in (str, file)
143877298Sobrien     string_type *str;
143977298Sobrien     FILE *file;
144033965Sjdp{
144177298Sobrien  char buff[10000];
144277298Sobrien  unsigned int r;
144377298Sobrien  do
144433965Sjdp    {
144577298Sobrien      r = fread (buff, 1, sizeof (buff), file);
144677298Sobrien      catbuf (str, buff, r);
144733965Sjdp    }
144877298Sobrien  while (r);
144977298Sobrien  buff[0] = 0;
145077298Sobrien
145177298Sobrien  catbuf (str, buff, 1);
145233965Sjdp}
145333965Sjdp
145477298Sobrienstatic void
1455104834Sobrienusage ()
145633965Sjdp{
145777298Sobrien  fprintf (stderr, "usage: -[d|i|g] <file >file\n");
145877298Sobrien  exit (33);
145933965Sjdp}
146033965Sjdp
146133965Sjdp/* There is no reliable way to declare exit.  Sometimes it returns
146233965Sjdp   int, and sometimes it returns void.  Sometimes it changes between
146333965Sjdp   OS releases.  Trying to get it declared correctly in the hosts file
146433965Sjdp   is a pointless waste of time.  */
146533965Sjdp
146633965Sjdpstatic void
146733965Sjdpchew_exit ()
146833965Sjdp{
146933965Sjdp  exit (0);
147033965Sjdp}
147133965Sjdp
147277298Sobrienint
147377298Sobrienmain (ac, av)
147477298Sobrien     int ac;
147577298Sobrien     char *av[];
147633965Sjdp{
147733965Sjdp  unsigned int i;
147833965Sjdp  string_type buffer;
147933965Sjdp  string_type pptr;
148033965Sjdp
148177298Sobrien  init_string (&buffer);
148277298Sobrien  init_string (&pptr);
148377298Sobrien  init_string (stack + 0);
148477298Sobrien  tos = stack + 1;
148533965Sjdp  ptr = &pptr;
148677298Sobrien
148777298Sobrien  add_intrinsic ("push_text", push_text);
148877298Sobrien  add_intrinsic ("!", bang);
148977298Sobrien  add_intrinsic ("@", atsign);
149077298Sobrien  add_intrinsic ("hello", hello);
149177298Sobrien  add_intrinsic ("stdout", stdout_);
149277298Sobrien  add_intrinsic ("stderr", stderr_);
149377298Sobrien  add_intrinsic ("print", print);
149477298Sobrien  add_intrinsic ("skip_past_newline", skip_past_newline);
149577298Sobrien  add_intrinsic ("catstr", icatstr);
149677298Sobrien  add_intrinsic ("copy_past_newline", icopy_past_newline);
149777298Sobrien  add_intrinsic ("dup", other_dup);
149877298Sobrien  add_intrinsic ("drop", drop);
149977298Sobrien  add_intrinsic ("idrop", idrop);
150077298Sobrien  add_intrinsic ("remchar", remchar);
150177298Sobrien  add_intrinsic ("get_stuff_in_command", get_stuff_in_command);
150277298Sobrien  add_intrinsic ("do_fancy_stuff", do_fancy_stuff);
150377298Sobrien  add_intrinsic ("bulletize", bulletize);
150477298Sobrien  add_intrinsic ("courierize", courierize);
150533965Sjdp  /* If the following line gives an error, exit() is not declared in the
150633965Sjdp     ../hosts/foo.h file for this host.  Fix it there, not here!  */
150733965Sjdp  /* No, don't fix it anywhere; see comment on chew_exit--Ian Taylor.  */
150877298Sobrien  add_intrinsic ("exit", chew_exit);
150977298Sobrien  add_intrinsic ("swap", swap);
151077298Sobrien  add_intrinsic ("outputdots", outputdots);
151177298Sobrien  add_intrinsic ("paramstuff", paramstuff);
151277298Sobrien  add_intrinsic ("maybecatstr", maybecatstr);
151377298Sobrien  add_intrinsic ("translatecomments", translatecomments);
151477298Sobrien  add_intrinsic ("kill_bogus_lines", kill_bogus_lines);
151577298Sobrien  add_intrinsic ("indent", indent);
151677298Sobrien  add_intrinsic ("internalmode", internalmode);
151777298Sobrien  add_intrinsic ("print_stack_level", print_stack_level);
151877298Sobrien  add_intrinsic ("strip_trailing_newlines", strip_trailing_newlines);
151933965Sjdp
152077298Sobrien  /* Put a nl at the start.  */
152177298Sobrien  catchar (&buffer, '\n');
152277298Sobrien
152377298Sobrien  read_in (&buffer, stdin);
152477298Sobrien  remove_noncomments (&buffer, ptr);
152577298Sobrien  for (i = 1; i < (unsigned int) ac; i++)
152633965Sjdp    {
152777298Sobrien      if (av[i][0] == '-')
152877298Sobrien	{
152977298Sobrien	  if (av[i][1] == 'f')
153077298Sobrien	    {
153177298Sobrien	      string_type b;
153277298Sobrien	      FILE *f;
153377298Sobrien	      init_string (&b);
153433965Sjdp
153577298Sobrien	      f = fopen (av[i + 1], "r");
153677298Sobrien	      if (!f)
153777298Sobrien		{
153877298Sobrien		  fprintf (stderr, "Can't open the input file %s\n",
153977298Sobrien			   av[i + 1]);
154077298Sobrien		  return 33;
154177298Sobrien		}
154277298Sobrien
154377298Sobrien	      read_in (&b, f);
154477298Sobrien	      compile (b.ptr);
154577298Sobrien	      perform ();
154677298Sobrien	    }
154777298Sobrien	  else if (av[i][1] == 'i')
154877298Sobrien	    {
154977298Sobrien	      internal_wanted = 1;
155077298Sobrien	    }
155177298Sobrien	  else if (av[i][1] == 'w')
155277298Sobrien	    {
155377298Sobrien	      warning = 1;
155477298Sobrien	    }
155577298Sobrien	  else
155677298Sobrien	    usage ();
155733965Sjdp	}
155833965Sjdp    }
155977298Sobrien  write_buffer (stack + 0, stdout);
156033965Sjdp  if (tos != stack)
156133965Sjdp    {
156277298Sobrien      fprintf (stderr, "finishing with current stack level %d\n",
156377298Sobrien	       tos - stack);
156433965Sjdp      return 1;
156533965Sjdp    }
156633965Sjdp  return 0;
156733965Sjdp}
1568