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