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