chew.c revision 1.8 1 1.1 christos /* chew
2 1.8 christos Copyright (C) 1990-2019 Free Software Foundation, Inc.
3 1.1 christos Contributed by steve chamberlain @cygnus
4 1.1 christos
5 1.1 christos This file is part of BFD, the Binary File Descriptor library.
6 1.1 christos
7 1.1 christos This program is free software; you can redistribute it and/or modify
8 1.1 christos it under the terms of the GNU General Public License as published by
9 1.1 christos the Free Software Foundation; either version 3 of the License, or
10 1.1 christos (at your option) any later version.
11 1.1 christos
12 1.1 christos This program is distributed in the hope that it will be useful,
13 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of
14 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 1.1 christos GNU General Public License for more details.
16 1.1 christos
17 1.1 christos You should have received a copy of the GNU General Public License
18 1.1 christos along with this program; if not, write to the Free Software
19 1.1 christos Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20 1.1 christos MA 02110-1301, USA. */
21 1.1 christos
22 1.1 christos /* Yet another way of extracting documentation from source.
23 1.1 christos No, I haven't finished it yet, but I hope you people like it better
24 1.1 christos than the old way
25 1.1 christos
26 1.1 christos sac
27 1.1 christos
28 1.1 christos Basically, this is a sort of string forth, maybe we should call it
29 1.1 christos struth?
30 1.1 christos
31 1.1 christos You define new words thus:
32 1.1 christos : <newword> <oldwords> ;
33 1.1 christos
34 1.1 christos */
35 1.1 christos
36 1.1 christos /* Primitives provided by the program:
37 1.1 christos
38 1.1 christos Two stacks are provided, a string stack and an integer stack.
39 1.1 christos
40 1.1 christos Internal state variables:
41 1.1 christos internal_wanted - indicates whether `-i' was passed
42 1.1 christos internal_mode - user-settable
43 1.1 christos
44 1.1 christos Commands:
45 1.1 christos push_text
46 1.1 christos ! - pop top of integer stack for address, pop next for value; store
47 1.1 christos @ - treat value on integer stack as the address of an integer; push
48 1.1 christos that integer on the integer stack after popping the "address"
49 1.1 christos hello - print "hello\n" to stdout
50 1.1 christos stdout - put stdout marker on TOS
51 1.1 christos stderr - put stderr marker on TOS
52 1.1 christos print - print TOS-1 on TOS (eg: "hello\n" stdout print)
53 1.1 christos skip_past_newline
54 1.1 christos catstr - fn icatstr
55 1.1 christos copy_past_newline - append input, up to and including newline into TOS
56 1.1 christos dup - fn other_dup
57 1.1 christos drop - discard TOS
58 1.1 christos idrop - ditto
59 1.1 christos remchar - delete last character from TOS
60 1.1 christos get_stuff_in_command
61 1.1 christos do_fancy_stuff - translate <<foo>> to @code{foo} in TOS
62 1.1 christos bulletize - if "o" lines found, prepend @itemize @bullet to TOS
63 1.1 christos and @item to each "o" line; append @end itemize
64 1.1 christos courierize - put @example around . and | lines, translate {* *} { }
65 1.1 christos exit - fn chew_exit
66 1.1 christos swap
67 1.1 christos outputdots - strip out lines without leading dots
68 1.1 christos paramstuff - convert full declaration into "PARAMS" form if not already
69 1.1 christos maybecatstr - do catstr if internal_mode == internal_wanted, discard
70 1.1 christos value in any case
71 1.1 christos translatecomments - turn {* and *} into comment delimiters
72 1.1 christos kill_bogus_lines - get rid of extra newlines
73 1.1 christos indent
74 1.1 christos internalmode - pop from integer stack, set `internalmode' to that value
75 1.1 christos print_stack_level - print current stack depth to stderr
76 1.1 christos strip_trailing_newlines - go ahead, guess...
77 1.1 christos [quoted string] - push string onto string stack
78 1.1 christos [word starting with digit] - push atol(str) onto integer stack
79 1.1 christos
80 1.1 christos A command must be all upper-case, and alone on a line.
81 1.1 christos
82 1.1 christos Foo. */
83 1.1 christos
84 1.1 christos #include "ansidecl.h"
85 1.1 christos #include <assert.h>
86 1.1 christos #include <stdio.h>
87 1.1 christos #include <ctype.h>
88 1.1 christos #include <stdlib.h>
89 1.1 christos #include <string.h>
90 1.1 christos
91 1.1 christos #define DEF_SIZE 5000
92 1.1 christos #define STACK 50
93 1.1 christos
94 1.1 christos int internal_wanted;
95 1.1 christos int internal_mode;
96 1.1 christos
97 1.1 christos int warning;
98 1.1 christos
99 1.1 christos /* Here is a string type ... */
100 1.1 christos
101 1.1 christos typedef struct buffer
102 1.1 christos {
103 1.1 christos char *ptr;
104 1.1 christos unsigned long write_idx;
105 1.1 christos unsigned long size;
106 1.1 christos } string_type;
107 1.1 christos
108 1.1 christos #ifdef __STDC__
109 1.1 christos static void init_string_with_size (string_type *, unsigned int);
110 1.1 christos static void init_string (string_type *);
111 1.1 christos static int find (string_type *, char *);
112 1.1 christos static void write_buffer (string_type *, FILE *);
113 1.1 christos static void delete_string (string_type *);
114 1.1 christos static char *addr (string_type *, unsigned int);
115 1.1 christos static char at (string_type *, unsigned int);
116 1.1 christos static void catchar (string_type *, int);
117 1.1 christos static void overwrite_string (string_type *, string_type *);
118 1.1 christos static void catbuf (string_type *, char *, unsigned int);
119 1.1 christos static void cattext (string_type *, char *);
120 1.1 christos static void catstr (string_type *, string_type *);
121 1.1 christos static void die (char *);
122 1.1 christos #endif
123 1.1 christos
124 1.1 christos static void
125 1.1 christos init_string_with_size (buffer, size)
126 1.1 christos string_type *buffer;
127 1.1 christos unsigned int size;
128 1.1 christos {
129 1.1 christos buffer->write_idx = 0;
130 1.1 christos buffer->size = size;
131 1.1 christos buffer->ptr = (char *) malloc (size);
132 1.1 christos }
133 1.1 christos
134 1.1 christos static void
135 1.1 christos init_string (buffer)
136 1.1 christos string_type *buffer;
137 1.1 christos {
138 1.1 christos init_string_with_size (buffer, DEF_SIZE);
139 1.1 christos }
140 1.1 christos
141 1.1 christos static int
142 1.1 christos find (str, what)
143 1.1 christos string_type *str;
144 1.1 christos char *what;
145 1.1 christos {
146 1.1 christos unsigned int i;
147 1.1 christos char *p;
148 1.1 christos p = what;
149 1.1 christos for (i = 0; i < str->write_idx && *p; i++)
150 1.1 christos {
151 1.1 christos if (*p == str->ptr[i])
152 1.1 christos p++;
153 1.1 christos else
154 1.1 christos p = what;
155 1.1 christos }
156 1.1 christos return (*p == 0);
157 1.1 christos }
158 1.1 christos
159 1.1 christos static void
160 1.1 christos write_buffer (buffer, f)
161 1.1 christos string_type *buffer;
162 1.1 christos FILE *f;
163 1.1 christos {
164 1.1 christos if (buffer->write_idx != 0
165 1.1 christos && fwrite (buffer->ptr, buffer->write_idx, 1, f) != 1)
166 1.1 christos die ("cannot write output");
167 1.1 christos }
168 1.1 christos
169 1.1 christos static void
170 1.1 christos delete_string (buffer)
171 1.1 christos string_type *buffer;
172 1.1 christos {
173 1.7 christos if (buffer->ptr)
174 1.7 christos free (buffer->ptr);
175 1.7 christos buffer->ptr = NULL;
176 1.1 christos }
177 1.1 christos
178 1.1 christos static char *
179 1.1 christos addr (buffer, idx)
180 1.1 christos string_type *buffer;
181 1.1 christos unsigned int idx;
182 1.1 christos {
183 1.1 christos return buffer->ptr + idx;
184 1.1 christos }
185 1.1 christos
186 1.1 christos static char
187 1.1 christos at (buffer, pos)
188 1.1 christos string_type *buffer;
189 1.1 christos unsigned int pos;
190 1.1 christos {
191 1.1 christos if (pos >= buffer->write_idx)
192 1.1 christos return 0;
193 1.1 christos return buffer->ptr[pos];
194 1.1 christos }
195 1.1 christos
196 1.1 christos static void
197 1.1 christos catchar (buffer, ch)
198 1.1 christos string_type *buffer;
199 1.1 christos int ch;
200 1.1 christos {
201 1.1 christos if (buffer->write_idx == buffer->size)
202 1.1 christos {
203 1.1 christos buffer->size *= 2;
204 1.1 christos buffer->ptr = (char *) realloc (buffer->ptr, buffer->size);
205 1.1 christos }
206 1.1 christos
207 1.1 christos buffer->ptr[buffer->write_idx++] = ch;
208 1.1 christos }
209 1.1 christos
210 1.1 christos static void
211 1.1 christos overwrite_string (dst, src)
212 1.1 christos string_type *dst;
213 1.1 christos string_type *src;
214 1.1 christos {
215 1.1 christos free (dst->ptr);
216 1.1 christos dst->size = src->size;
217 1.1 christos dst->write_idx = src->write_idx;
218 1.1 christos dst->ptr = src->ptr;
219 1.1 christos }
220 1.1 christos
221 1.1 christos static void
222 1.1 christos catbuf (buffer, buf, len)
223 1.1 christos string_type *buffer;
224 1.1 christos char *buf;
225 1.1 christos unsigned int len;
226 1.1 christos {
227 1.1 christos if (buffer->write_idx + len >= buffer->size)
228 1.1 christos {
229 1.1 christos while (buffer->write_idx + len >= buffer->size)
230 1.1 christos buffer->size *= 2;
231 1.1 christos buffer->ptr = (char *) realloc (buffer->ptr, buffer->size);
232 1.1 christos }
233 1.1 christos memcpy (buffer->ptr + buffer->write_idx, buf, len);
234 1.1 christos buffer->write_idx += len;
235 1.1 christos }
236 1.1 christos
237 1.1 christos static void
238 1.1 christos cattext (buffer, string)
239 1.1 christos string_type *buffer;
240 1.1 christos char *string;
241 1.1 christos {
242 1.1 christos catbuf (buffer, string, (unsigned int) strlen (string));
243 1.1 christos }
244 1.1 christos
245 1.1 christos static void
246 1.1 christos catstr (dst, src)
247 1.1 christos string_type *dst;
248 1.1 christos string_type *src;
249 1.1 christos {
250 1.1 christos catbuf (dst, src->ptr, src->write_idx);
251 1.1 christos }
252 1.1 christos
253 1.1 christos static unsigned int
254 1.1 christos skip_white_and_stars (src, idx)
255 1.1 christos string_type *src;
256 1.1 christos unsigned int idx;
257 1.1 christos {
258 1.1 christos char c;
259 1.1 christos while ((c = at (src, idx)),
260 1.1 christos isspace ((unsigned char) c)
261 1.1 christos || (c == '*'
262 1.1 christos /* Don't skip past end-of-comment or star as first
263 1.1 christos character on its line. */
264 1.1 christos && at (src, idx +1) != '/'
265 1.1 christos && at (src, idx -1) != '\n'))
266 1.1 christos idx++;
267 1.1 christos return idx;
268 1.1 christos }
269 1.1 christos
270 1.3 christos static unsigned int
271 1.3 christos skip_past_newline_1 (ptr, idx)
272 1.3 christos string_type *ptr;
273 1.3 christos unsigned int idx;
274 1.3 christos {
275 1.3 christos while (at (ptr, idx)
276 1.3 christos && at (ptr, idx) != '\n')
277 1.3 christos idx++;
278 1.3 christos if (at (ptr, idx) == '\n')
279 1.3 christos return idx + 1;
280 1.3 christos return idx;
281 1.3 christos }
282 1.3 christos
283 1.1 christos /***********************************************************************/
284 1.1 christos
285 1.1 christos string_type stack[STACK];
286 1.1 christos string_type *tos;
287 1.1 christos
288 1.1 christos unsigned int idx = 0; /* Pos in input buffer */
289 1.1 christos string_type *ptr; /* and the buffer */
290 1.1 christos typedef void (*stinst_type)();
291 1.1 christos stinst_type *pc;
292 1.1 christos stinst_type sstack[STACK];
293 1.1 christos stinst_type *ssp = &sstack[0];
294 1.1 christos long istack[STACK];
295 1.1 christos long *isp = &istack[0];
296 1.1 christos
297 1.1 christos typedef int *word_type;
298 1.1 christos
299 1.1 christos struct dict_struct
300 1.1 christos {
301 1.1 christos char *word;
302 1.1 christos struct dict_struct *next;
303 1.1 christos stinst_type *code;
304 1.1 christos int code_length;
305 1.1 christos int code_end;
306 1.1 christos int var;
307 1.1 christos };
308 1.1 christos
309 1.1 christos typedef struct dict_struct dict_type;
310 1.1 christos
311 1.1 christos static void
312 1.1 christos die (msg)
313 1.1 christos char *msg;
314 1.1 christos {
315 1.1 christos fprintf (stderr, "%s\n", msg);
316 1.1 christos exit (1);
317 1.1 christos }
318 1.1 christos
319 1.1 christos static void
320 1.1 christos check_range ()
321 1.1 christos {
322 1.1 christos if (tos < stack)
323 1.1 christos die ("underflow in string stack");
324 1.1 christos if (tos >= stack + STACK)
325 1.1 christos die ("overflow in string stack");
326 1.1 christos }
327 1.1 christos
328 1.1 christos static void
329 1.1 christos icheck_range ()
330 1.1 christos {
331 1.1 christos if (isp < istack)
332 1.1 christos die ("underflow in integer stack");
333 1.1 christos if (isp >= istack + STACK)
334 1.1 christos die ("overflow in integer stack");
335 1.1 christos }
336 1.1 christos
337 1.1 christos #ifdef __STDC__
338 1.1 christos static void exec (dict_type *);
339 1.1 christos static void call (void);
340 1.1 christos static void remchar (void), strip_trailing_newlines (void), push_number (void);
341 1.1 christos static void push_text (void);
342 1.1 christos static void remove_noncomments (string_type *, string_type *);
343 1.1 christos static void print_stack_level (void);
344 1.1 christos static void paramstuff (void), translatecomments (void);
345 1.1 christos static void outputdots (void), courierize (void), bulletize (void);
346 1.1 christos static void do_fancy_stuff (void);
347 1.1 christos static int iscommand (string_type *, unsigned int);
348 1.1 christos static int copy_past_newline (string_type *, unsigned int, string_type *);
349 1.1 christos static void icopy_past_newline (void), kill_bogus_lines (void), indent (void);
350 1.1 christos static void get_stuff_in_command (void), swap (void), other_dup (void);
351 1.1 christos static void drop (void), idrop (void);
352 1.1 christos static void icatstr (void), skip_past_newline (void), internalmode (void);
353 1.1 christos static void maybecatstr (void);
354 1.1 christos static char *nextword (char *, char **);
355 1.1 christos dict_type *lookup_word (char *);
356 1.1 christos static void perform (void);
357 1.1 christos dict_type *newentry (char *);
358 1.1 christos unsigned int add_to_definition (dict_type *, stinst_type);
359 1.1 christos void add_intrinsic (char *, void (*)());
360 1.1 christos void add_var (char *);
361 1.1 christos void compile (char *);
362 1.1 christos static void bang (void);
363 1.1 christos static void atsign (void);
364 1.1 christos static void hello (void);
365 1.1 christos static void stdout_ (void);
366 1.1 christos static void stderr_ (void);
367 1.1 christos static void print (void);
368 1.1 christos static void read_in (string_type *, FILE *);
369 1.1 christos static void usage (void);
370 1.1 christos static void chew_exit (void);
371 1.1 christos #endif
372 1.1 christos
373 1.1 christos static void
374 1.1 christos exec (word)
375 1.1 christos dict_type *word;
376 1.1 christos {
377 1.1 christos pc = word->code;
378 1.1 christos while (*pc)
379 1.1 christos (*pc) ();
380 1.1 christos }
381 1.1 christos
382 1.1 christos static void
383 1.1 christos call ()
384 1.1 christos {
385 1.1 christos stinst_type *oldpc = pc;
386 1.1 christos dict_type *e;
387 1.1 christos e = (dict_type *) (pc[1]);
388 1.1 christos exec (e);
389 1.1 christos pc = oldpc + 2;
390 1.1 christos }
391 1.1 christos
392 1.1 christos static void
393 1.1 christos remchar ()
394 1.1 christos {
395 1.1 christos if (tos->write_idx)
396 1.1 christos tos->write_idx--;
397 1.1 christos pc++;
398 1.1 christos }
399 1.1 christos
400 1.1 christos static void
401 1.1 christos strip_trailing_newlines ()
402 1.1 christos {
403 1.1 christos while ((isspace ((unsigned char) at (tos, tos->write_idx - 1))
404 1.1 christos || at (tos, tos->write_idx - 1) == '\n')
405 1.1 christos && tos->write_idx > 0)
406 1.1 christos tos->write_idx--;
407 1.1 christos pc++;
408 1.1 christos }
409 1.1 christos
410 1.1 christos static void
411 1.1 christos push_number ()
412 1.1 christos {
413 1.1 christos isp++;
414 1.1 christos icheck_range ();
415 1.1 christos pc++;
416 1.1 christos *isp = (long) (*pc);
417 1.1 christos pc++;
418 1.1 christos }
419 1.1 christos
420 1.1 christos static void
421 1.1 christos push_text ()
422 1.1 christos {
423 1.1 christos tos++;
424 1.1 christos check_range ();
425 1.1 christos init_string (tos);
426 1.1 christos pc++;
427 1.1 christos cattext (tos, *((char **) pc));
428 1.1 christos pc++;
429 1.1 christos }
430 1.1 christos
431 1.1 christos /* This function removes everything not inside comments starting on
432 1.1 christos the first char of the line from the string, also when copying
433 1.1 christos comments, removes blank space and leading *'s.
434 1.1 christos Blank lines are turned into one blank line. */
435 1.1 christos
436 1.1 christos static void
437 1.1 christos remove_noncomments (src, dst)
438 1.1 christos string_type *src;
439 1.1 christos string_type *dst;
440 1.1 christos {
441 1.1 christos unsigned int idx = 0;
442 1.1 christos
443 1.1 christos while (at (src, idx))
444 1.1 christos {
445 1.1 christos /* Now see if we have a comment at the start of the line. */
446 1.1 christos if (at (src, idx) == '\n'
447 1.1 christos && at (src, idx + 1) == '/'
448 1.1 christos && at (src, idx + 2) == '*')
449 1.1 christos {
450 1.1 christos idx += 3;
451 1.1 christos
452 1.1 christos idx = skip_white_and_stars (src, idx);
453 1.1 christos
454 1.1 christos /* Remove leading dot */
455 1.1 christos if (at (src, idx) == '.')
456 1.1 christos idx++;
457 1.1 christos
458 1.1 christos /* Copy to the end of the line, or till the end of the
459 1.1 christos comment. */
460 1.1 christos while (at (src, idx))
461 1.1 christos {
462 1.1 christos if (at (src, idx) == '\n')
463 1.1 christos {
464 1.1 christos /* end of line, echo and scrape of leading blanks */
465 1.1 christos if (at (src, idx + 1) == '\n')
466 1.1 christos catchar (dst, '\n');
467 1.1 christos catchar (dst, '\n');
468 1.1 christos idx++;
469 1.1 christos idx = skip_white_and_stars (src, idx);
470 1.1 christos }
471 1.1 christos else if (at (src, idx) == '*' && at (src, idx + 1) == '/')
472 1.1 christos {
473 1.1 christos idx += 2;
474 1.1 christos cattext (dst, "\nENDDD\n");
475 1.1 christos break;
476 1.1 christos }
477 1.1 christos else
478 1.1 christos {
479 1.1 christos catchar (dst, at (src, idx));
480 1.1 christos idx++;
481 1.1 christos }
482 1.1 christos }
483 1.1 christos }
484 1.1 christos else
485 1.1 christos idx++;
486 1.1 christos }
487 1.1 christos }
488 1.1 christos
489 1.1 christos static void
490 1.1 christos print_stack_level ()
491 1.1 christos {
492 1.3 christos fprintf (stderr, "current string stack depth = %ld, ",
493 1.3 christos (long) (tos - stack));
494 1.3 christos fprintf (stderr, "current integer stack depth = %ld\n",
495 1.3 christos (long) (isp - istack));
496 1.1 christos pc++;
497 1.1 christos }
498 1.1 christos
499 1.1 christos /* turn:
500 1.1 christos foobar name(stuff);
501 1.1 christos into:
502 1.1 christos foobar
503 1.1 christos name PARAMS ((stuff));
504 1.1 christos and a blank line.
505 1.1 christos */
506 1.1 christos
507 1.1 christos static void
508 1.1 christos paramstuff ()
509 1.1 christos {
510 1.1 christos unsigned int openp;
511 1.1 christos unsigned int fname;
512 1.1 christos unsigned int idx;
513 1.1 christos unsigned int len;
514 1.1 christos string_type out;
515 1.1 christos init_string (&out);
516 1.1 christos
517 1.1 christos #define NO_PARAMS 1
518 1.1 christos
519 1.1 christos /* Make sure that it's not already param'd or proto'd. */
520 1.1 christos if (NO_PARAMS
521 1.1 christos || find (tos, "PARAMS") || find (tos, "PROTO") || !find (tos, "("))
522 1.1 christos {
523 1.1 christos catstr (&out, tos);
524 1.1 christos }
525 1.1 christos else
526 1.1 christos {
527 1.1 christos /* Find the open paren. */
528 1.1 christos for (openp = 0; at (tos, openp) != '(' && at (tos, openp); openp++)
529 1.1 christos ;
530 1.1 christos
531 1.1 christos fname = openp;
532 1.1 christos /* Step back to the fname. */
533 1.1 christos fname--;
534 1.1 christos while (fname && isspace ((unsigned char) at (tos, fname)))
535 1.1 christos fname--;
536 1.1 christos while (fname
537 1.1 christos && !isspace ((unsigned char) at (tos,fname))
538 1.1 christos && at (tos,fname) != '*')
539 1.1 christos fname--;
540 1.1 christos
541 1.1 christos fname++;
542 1.1 christos
543 1.1 christos /* Output type, omitting trailing whitespace character(s), if
544 1.1 christos any. */
545 1.1 christos for (len = fname; 0 < len; len--)
546 1.1 christos {
547 1.1 christos if (!isspace ((unsigned char) at (tos, len - 1)))
548 1.1 christos break;
549 1.1 christos }
550 1.1 christos for (idx = 0; idx < len; idx++)
551 1.1 christos catchar (&out, at (tos, idx));
552 1.1 christos
553 1.1 christos cattext (&out, "\n"); /* Insert a newline between type and fnname */
554 1.1 christos
555 1.1 christos /* Output function name, omitting trailing whitespace
556 1.1 christos character(s), if any. */
557 1.1 christos for (len = openp; 0 < len; len--)
558 1.1 christos {
559 1.1 christos if (!isspace ((unsigned char) at (tos, len - 1)))
560 1.1 christos break;
561 1.1 christos }
562 1.1 christos for (idx = fname; idx < len; idx++)
563 1.1 christos catchar (&out, at (tos, idx));
564 1.1 christos
565 1.1 christos cattext (&out, " PARAMS (");
566 1.1 christos
567 1.1 christos for (idx = openp; at (tos, idx) && at (tos, idx) != ';'; idx++)
568 1.1 christos catchar (&out, at (tos, idx));
569 1.1 christos
570 1.1 christos cattext (&out, ");\n\n");
571 1.1 christos }
572 1.1 christos overwrite_string (tos, &out);
573 1.1 christos pc++;
574 1.1 christos
575 1.1 christos }
576 1.1 christos
577 1.1 christos /* turn {*
578 1.1 christos and *} into comments */
579 1.1 christos
580 1.1 christos static void
581 1.1 christos translatecomments ()
582 1.1 christos {
583 1.1 christos unsigned int idx = 0;
584 1.1 christos string_type out;
585 1.1 christos init_string (&out);
586 1.1 christos
587 1.1 christos while (at (tos, idx))
588 1.1 christos {
589 1.1 christos if (at (tos, idx) == '{' && at (tos, idx + 1) == '*')
590 1.1 christos {
591 1.1 christos cattext (&out, "/*");
592 1.1 christos idx += 2;
593 1.1 christos }
594 1.1 christos else if (at (tos, idx) == '*' && at (tos, idx + 1) == '}')
595 1.1 christos {
596 1.1 christos cattext (&out, "*/");
597 1.1 christos idx += 2;
598 1.1 christos }
599 1.1 christos else
600 1.1 christos {
601 1.1 christos catchar (&out, at (tos, idx));
602 1.1 christos idx++;
603 1.1 christos }
604 1.1 christos }
605 1.1 christos
606 1.1 christos overwrite_string (tos, &out);
607 1.1 christos
608 1.1 christos pc++;
609 1.1 christos }
610 1.1 christos
611 1.1 christos /* Mod tos so that only lines with leading dots remain */
612 1.1 christos static void
613 1.1 christos outputdots ()
614 1.1 christos {
615 1.1 christos unsigned int idx = 0;
616 1.1 christos string_type out;
617 1.1 christos init_string (&out);
618 1.1 christos
619 1.1 christos while (at (tos, idx))
620 1.1 christos {
621 1.3 christos /* Every iteration begins at the start of a line. */
622 1.3 christos if (at (tos, idx) == '.')
623 1.1 christos {
624 1.1 christos char c;
625 1.3 christos
626 1.3 christos idx++;
627 1.1 christos
628 1.1 christos while ((c = at (tos, idx)) && c != '\n')
629 1.1 christos {
630 1.1 christos if (c == '{' && at (tos, idx + 1) == '*')
631 1.1 christos {
632 1.1 christos cattext (&out, "/*");
633 1.1 christos idx += 2;
634 1.1 christos }
635 1.1 christos else if (c == '*' && at (tos, idx + 1) == '}')
636 1.1 christos {
637 1.1 christos cattext (&out, "*/");
638 1.1 christos idx += 2;
639 1.1 christos }
640 1.1 christos else
641 1.1 christos {
642 1.1 christos catchar (&out, c);
643 1.1 christos idx++;
644 1.1 christos }
645 1.1 christos }
646 1.3 christos if (c == '\n')
647 1.3 christos idx++;
648 1.1 christos catchar (&out, '\n');
649 1.1 christos }
650 1.1 christos else
651 1.1 christos {
652 1.3 christos idx = skip_past_newline_1 (tos, idx);
653 1.1 christos }
654 1.1 christos }
655 1.1 christos
656 1.1 christos overwrite_string (tos, &out);
657 1.1 christos pc++;
658 1.1 christos }
659 1.1 christos
660 1.1 christos /* Find lines starting with . and | and put example around them on tos */
661 1.1 christos static void
662 1.1 christos courierize ()
663 1.1 christos {
664 1.1 christos string_type out;
665 1.1 christos unsigned int idx = 0;
666 1.1 christos int command = 0;
667 1.1 christos
668 1.1 christos init_string (&out);
669 1.1 christos
670 1.1 christos while (at (tos, idx))
671 1.1 christos {
672 1.1 christos if (at (tos, idx) == '\n'
673 1.1 christos && (at (tos, idx +1 ) == '.'
674 1.1 christos || at (tos, idx + 1) == '|'))
675 1.1 christos {
676 1.1 christos cattext (&out, "\n@example\n");
677 1.1 christos do
678 1.1 christos {
679 1.1 christos idx += 2;
680 1.1 christos
681 1.1 christos while (at (tos, idx) && at (tos, idx) != '\n')
682 1.1 christos {
683 1.1 christos if (command > 1)
684 1.1 christos {
685 1.1 christos /* We are inside {} parameters of some command;
686 1.1 christos Just pass through until matching brace. */
687 1.1 christos if (at (tos, idx) == '{')
688 1.1 christos ++command;
689 1.1 christos else if (at (tos, idx) == '}')
690 1.1 christos --command;
691 1.1 christos }
692 1.1 christos else if (command != 0)
693 1.1 christos {
694 1.1 christos if (at (tos, idx) == '{')
695 1.1 christos ++command;
696 1.1 christos else if (!islower ((unsigned char) at (tos, idx)))
697 1.1 christos --command;
698 1.1 christos }
699 1.1 christos else if (at (tos, idx) == '@'
700 1.1 christos && islower ((unsigned char) at (tos, idx + 1)))
701 1.1 christos {
702 1.1 christos ++command;
703 1.1 christos }
704 1.1 christos else if (at (tos, idx) == '{' && at (tos, idx + 1) == '*')
705 1.1 christos {
706 1.1 christos cattext (&out, "/*");
707 1.1 christos idx += 2;
708 1.1 christos continue;
709 1.1 christos }
710 1.1 christos else if (at (tos, idx) == '*' && at (tos, idx + 1) == '}')
711 1.1 christos {
712 1.1 christos cattext (&out, "*/");
713 1.1 christos idx += 2;
714 1.1 christos continue;
715 1.1 christos }
716 1.1 christos else if (at (tos, idx) == '{'
717 1.1 christos || at (tos, idx) == '}')
718 1.1 christos {
719 1.1 christos catchar (&out, '@');
720 1.1 christos }
721 1.1 christos
722 1.1 christos catchar (&out, at (tos, idx));
723 1.1 christos idx++;
724 1.1 christos }
725 1.1 christos catchar (&out, '\n');
726 1.1 christos }
727 1.1 christos while (at (tos, idx) == '\n'
728 1.1 christos && ((at (tos, idx + 1) == '.')
729 1.1 christos || (at (tos, idx + 1) == '|')))
730 1.1 christos ;
731 1.1 christos cattext (&out, "@end example");
732 1.1 christos }
733 1.1 christos else
734 1.1 christos {
735 1.1 christos catchar (&out, at (tos, idx));
736 1.1 christos idx++;
737 1.1 christos }
738 1.1 christos }
739 1.1 christos
740 1.1 christos overwrite_string (tos, &out);
741 1.1 christos pc++;
742 1.1 christos }
743 1.1 christos
744 1.1 christos /* Finds any lines starting with "o ", if there are any, then turns
745 1.1 christos on @itemize @bullet, and @items each of them. Then ends with @end
746 1.1 christos itemize, inplace at TOS*/
747 1.1 christos
748 1.1 christos static void
749 1.1 christos bulletize ()
750 1.1 christos {
751 1.1 christos unsigned int idx = 0;
752 1.1 christos int on = 0;
753 1.1 christos string_type out;
754 1.1 christos init_string (&out);
755 1.1 christos
756 1.1 christos while (at (tos, idx))
757 1.1 christos {
758 1.1 christos if (at (tos, idx) == '@'
759 1.1 christos && at (tos, idx + 1) == '*')
760 1.1 christos {
761 1.1 christos cattext (&out, "*");
762 1.1 christos idx += 2;
763 1.1 christos }
764 1.1 christos else if (at (tos, idx) == '\n'
765 1.1 christos && at (tos, idx + 1) == 'o'
766 1.1 christos && isspace ((unsigned char) at (tos, idx + 2)))
767 1.1 christos {
768 1.1 christos if (!on)
769 1.1 christos {
770 1.1 christos cattext (&out, "\n@itemize @bullet\n");
771 1.1 christos on = 1;
772 1.1 christos
773 1.1 christos }
774 1.1 christos cattext (&out, "\n@item\n");
775 1.1 christos idx += 3;
776 1.1 christos }
777 1.1 christos else
778 1.1 christos {
779 1.1 christos catchar (&out, at (tos, idx));
780 1.1 christos if (on && at (tos, idx) == '\n'
781 1.1 christos && at (tos, idx + 1) == '\n'
782 1.1 christos && at (tos, idx + 2) != 'o')
783 1.1 christos {
784 1.1 christos cattext (&out, "@end itemize");
785 1.1 christos on = 0;
786 1.1 christos }
787 1.1 christos idx++;
788 1.1 christos
789 1.1 christos }
790 1.1 christos }
791 1.1 christos if (on)
792 1.1 christos {
793 1.1 christos cattext (&out, "@end itemize\n");
794 1.1 christos }
795 1.1 christos
796 1.1 christos delete_string (tos);
797 1.1 christos *tos = out;
798 1.1 christos pc++;
799 1.1 christos }
800 1.1 christos
801 1.1 christos /* Turn <<foo>> into @code{foo} in place at TOS*/
802 1.1 christos
803 1.1 christos static void
804 1.1 christos do_fancy_stuff ()
805 1.1 christos {
806 1.1 christos unsigned int idx = 0;
807 1.1 christos string_type out;
808 1.1 christos init_string (&out);
809 1.1 christos while (at (tos, idx))
810 1.1 christos {
811 1.1 christos if (at (tos, idx) == '<'
812 1.1 christos && at (tos, idx + 1) == '<'
813 1.1 christos && !isspace ((unsigned char) at (tos, idx + 2)))
814 1.1 christos {
815 1.1 christos /* This qualifies as a << startup. */
816 1.1 christos idx += 2;
817 1.1 christos cattext (&out, "@code{");
818 1.1 christos while (at (tos, idx)
819 1.1 christos && at (tos, idx) != '>' )
820 1.1 christos {
821 1.1 christos catchar (&out, at (tos, idx));
822 1.1 christos idx++;
823 1.1 christos
824 1.1 christos }
825 1.1 christos cattext (&out, "}");
826 1.1 christos idx += 2;
827 1.1 christos }
828 1.1 christos else
829 1.1 christos {
830 1.1 christos catchar (&out, at (tos, idx));
831 1.1 christos idx++;
832 1.1 christos }
833 1.1 christos }
834 1.1 christos delete_string (tos);
835 1.1 christos *tos = out;
836 1.1 christos pc++;
837 1.1 christos
838 1.1 christos }
839 1.1 christos
840 1.1 christos /* A command is all upper case,and alone on a line. */
841 1.1 christos
842 1.1 christos static int
843 1.1 christos iscommand (ptr, idx)
844 1.1 christos string_type *ptr;
845 1.1 christos unsigned int idx;
846 1.1 christos {
847 1.1 christos unsigned int len = 0;
848 1.1 christos while (at (ptr, idx))
849 1.1 christos {
850 1.1 christos if (isupper ((unsigned char) at (ptr, idx))
851 1.1 christos || at (ptr, idx) == ' ' || at (ptr, idx) == '_')
852 1.1 christos {
853 1.1 christos len++;
854 1.1 christos idx++;
855 1.1 christos }
856 1.1 christos else if (at (ptr, idx) == '\n')
857 1.1 christos {
858 1.1 christos if (len > 3)
859 1.1 christos return 1;
860 1.1 christos return 0;
861 1.1 christos }
862 1.1 christos else
863 1.1 christos return 0;
864 1.1 christos }
865 1.1 christos return 0;
866 1.1 christos }
867 1.1 christos
868 1.1 christos static int
869 1.1 christos copy_past_newline (ptr, idx, dst)
870 1.1 christos string_type *ptr;
871 1.1 christos unsigned int idx;
872 1.1 christos string_type *dst;
873 1.1 christos {
874 1.1 christos int column = 0;
875 1.1 christos
876 1.1 christos while (at (ptr, idx) && at (ptr, idx) != '\n')
877 1.1 christos {
878 1.1 christos if (at (ptr, idx) == '\t')
879 1.1 christos {
880 1.1 christos /* Expand tabs. Neither makeinfo nor TeX can cope well with
881 1.1 christos them. */
882 1.1 christos do
883 1.1 christos catchar (dst, ' ');
884 1.1 christos while (++column & 7);
885 1.1 christos }
886 1.1 christos else
887 1.1 christos {
888 1.1 christos catchar (dst, at (ptr, idx));
889 1.1 christos column++;
890 1.1 christos }
891 1.1 christos idx++;
892 1.1 christos
893 1.1 christos }
894 1.1 christos catchar (dst, at (ptr, idx));
895 1.1 christos idx++;
896 1.1 christos return idx;
897 1.1 christos
898 1.1 christos }
899 1.1 christos
900 1.1 christos static void
901 1.1 christos icopy_past_newline ()
902 1.1 christos {
903 1.1 christos tos++;
904 1.1 christos check_range ();
905 1.1 christos init_string (tos);
906 1.1 christos idx = copy_past_newline (ptr, idx, tos);
907 1.1 christos pc++;
908 1.1 christos }
909 1.1 christos
910 1.1 christos /* indent
911 1.1 christos Take the string at the top of the stack, do some prettying. */
912 1.1 christos
913 1.1 christos static void
914 1.1 christos kill_bogus_lines ()
915 1.1 christos {
916 1.1 christos int sl;
917 1.1 christos
918 1.1 christos int idx = 0;
919 1.1 christos int c;
920 1.1 christos int dot = 0;
921 1.1 christos
922 1.1 christos string_type out;
923 1.1 christos init_string (&out);
924 1.1 christos /* Drop leading nl. */
925 1.1 christos while (at (tos, idx) == '\n')
926 1.1 christos {
927 1.1 christos idx++;
928 1.1 christos }
929 1.1 christos c = idx;
930 1.1 christos
931 1.1 christos /* If the first char is a '.' prepend a newline so that it is
932 1.1 christos recognized properly later. */
933 1.1 christos if (at (tos, idx) == '.')
934 1.1 christos catchar (&out, '\n');
935 1.1 christos
936 1.1 christos /* Find the last char. */
937 1.1 christos while (at (tos, idx))
938 1.1 christos {
939 1.1 christos idx++;
940 1.1 christos }
941 1.1 christos
942 1.1 christos /* Find the last non white before the nl. */
943 1.1 christos idx--;
944 1.1 christos
945 1.1 christos while (idx && isspace ((unsigned char) at (tos, idx)))
946 1.1 christos idx--;
947 1.1 christos idx++;
948 1.1 christos
949 1.1 christos /* Copy buffer upto last char, but blank lines before and after
950 1.1 christos dots don't count. */
951 1.1 christos sl = 1;
952 1.1 christos
953 1.1 christos while (c < idx)
954 1.1 christos {
955 1.1 christos if (at (tos, c) == '\n'
956 1.1 christos && at (tos, c + 1) == '\n'
957 1.1 christos && at (tos, c + 2) == '.')
958 1.1 christos {
959 1.1 christos /* Ignore two newlines before a dot. */
960 1.1 christos c++;
961 1.1 christos }
962 1.1 christos else if (at (tos, c) == '.' && sl)
963 1.1 christos {
964 1.1 christos /* remember that this line started with a dot. */
965 1.1 christos dot = 2;
966 1.1 christos }
967 1.1 christos else if (at (tos, c) == '\n'
968 1.1 christos && at (tos, c + 1) == '\n'
969 1.1 christos && dot)
970 1.1 christos {
971 1.1 christos c++;
972 1.1 christos /* Ignore two newlines when last line was dot. */
973 1.1 christos }
974 1.1 christos
975 1.1 christos catchar (&out, at (tos, c));
976 1.1 christos if (at (tos, c) == '\n')
977 1.1 christos {
978 1.1 christos sl = 1;
979 1.1 christos
980 1.1 christos if (dot == 2)
981 1.1 christos dot = 1;
982 1.1 christos else
983 1.1 christos dot = 0;
984 1.1 christos }
985 1.1 christos else
986 1.1 christos sl = 0;
987 1.1 christos
988 1.1 christos c++;
989 1.1 christos
990 1.1 christos }
991 1.1 christos
992 1.1 christos /* Append nl. */
993 1.1 christos catchar (&out, '\n');
994 1.1 christos pc++;
995 1.1 christos delete_string (tos);
996 1.1 christos *tos = out;
997 1.1 christos
998 1.1 christos }
999 1.1 christos
1000 1.1 christos static void
1001 1.1 christos indent ()
1002 1.1 christos {
1003 1.1 christos string_type out;
1004 1.1 christos int tab = 0;
1005 1.1 christos int idx = 0;
1006 1.1 christos int ol = 0;
1007 1.1 christos init_string (&out);
1008 1.1 christos while (at (tos, idx))
1009 1.1 christos {
1010 1.1 christos switch (at (tos, idx))
1011 1.1 christos {
1012 1.1 christos case '\n':
1013 1.1 christos cattext (&out, "\n");
1014 1.1 christos idx++;
1015 1.1 christos if (tab && at (tos, idx))
1016 1.1 christos {
1017 1.1 christos cattext (&out, " ");
1018 1.1 christos }
1019 1.1 christos ol = 0;
1020 1.1 christos break;
1021 1.1 christos case '(':
1022 1.1 christos tab++;
1023 1.1 christos if (ol == 0)
1024 1.1 christos cattext (&out, " ");
1025 1.1 christos idx++;
1026 1.1 christos cattext (&out, "(");
1027 1.1 christos ol = 1;
1028 1.1 christos break;
1029 1.1 christos case ')':
1030 1.1 christos tab--;
1031 1.1 christos cattext (&out, ")");
1032 1.1 christos idx++;
1033 1.1 christos ol = 1;
1034 1.1 christos
1035 1.1 christos break;
1036 1.1 christos default:
1037 1.1 christos catchar (&out, at (tos, idx));
1038 1.1 christos ol = 1;
1039 1.1 christos
1040 1.1 christos idx++;
1041 1.1 christos break;
1042 1.1 christos }
1043 1.1 christos }
1044 1.1 christos
1045 1.1 christos pc++;
1046 1.1 christos delete_string (tos);
1047 1.1 christos *tos = out;
1048 1.1 christos
1049 1.1 christos }
1050 1.1 christos
1051 1.1 christos static void
1052 1.1 christos get_stuff_in_command ()
1053 1.1 christos {
1054 1.1 christos tos++;
1055 1.1 christos check_range ();
1056 1.1 christos init_string (tos);
1057 1.1 christos
1058 1.1 christos while (at (ptr, idx))
1059 1.1 christos {
1060 1.1 christos if (iscommand (ptr, idx))
1061 1.1 christos break;
1062 1.1 christos idx = copy_past_newline (ptr, idx, tos);
1063 1.1 christos }
1064 1.1 christos pc++;
1065 1.1 christos }
1066 1.1 christos
1067 1.1 christos static void
1068 1.1 christos swap ()
1069 1.1 christos {
1070 1.1 christos string_type t;
1071 1.1 christos
1072 1.1 christos t = tos[0];
1073 1.1 christos tos[0] = tos[-1];
1074 1.1 christos tos[-1] = t;
1075 1.1 christos pc++;
1076 1.1 christos }
1077 1.1 christos
1078 1.1 christos static void
1079 1.1 christos other_dup ()
1080 1.1 christos {
1081 1.1 christos tos++;
1082 1.1 christos check_range ();
1083 1.1 christos init_string (tos);
1084 1.1 christos catstr (tos, tos - 1);
1085 1.1 christos pc++;
1086 1.1 christos }
1087 1.1 christos
1088 1.1 christos static void
1089 1.1 christos drop ()
1090 1.1 christos {
1091 1.1 christos tos--;
1092 1.1 christos check_range ();
1093 1.7 christos delete_string (tos + 1);
1094 1.1 christos pc++;
1095 1.1 christos }
1096 1.1 christos
1097 1.1 christos static void
1098 1.1 christos idrop ()
1099 1.1 christos {
1100 1.1 christos isp--;
1101 1.1 christos icheck_range ();
1102 1.1 christos pc++;
1103 1.1 christos }
1104 1.1 christos
1105 1.1 christos static void
1106 1.1 christos icatstr ()
1107 1.1 christos {
1108 1.1 christos tos--;
1109 1.1 christos check_range ();
1110 1.1 christos catstr (tos, tos + 1);
1111 1.1 christos delete_string (tos + 1);
1112 1.1 christos pc++;
1113 1.1 christos }
1114 1.1 christos
1115 1.1 christos static void
1116 1.1 christos skip_past_newline ()
1117 1.1 christos {
1118 1.3 christos idx = skip_past_newline_1 (ptr, idx);
1119 1.1 christos pc++;
1120 1.1 christos }
1121 1.1 christos
1122 1.1 christos static void
1123 1.1 christos internalmode ()
1124 1.1 christos {
1125 1.1 christos internal_mode = *(isp);
1126 1.1 christos isp--;
1127 1.1 christos icheck_range ();
1128 1.1 christos pc++;
1129 1.1 christos }
1130 1.1 christos
1131 1.1 christos static void
1132 1.1 christos maybecatstr ()
1133 1.1 christos {
1134 1.1 christos if (internal_wanted == internal_mode)
1135 1.1 christos {
1136 1.1 christos catstr (tos - 1, tos);
1137 1.1 christos }
1138 1.1 christos delete_string (tos);
1139 1.1 christos tos--;
1140 1.1 christos check_range ();
1141 1.1 christos pc++;
1142 1.1 christos }
1143 1.1 christos
1144 1.1 christos char *
1145 1.1 christos nextword (string, word)
1146 1.1 christos char *string;
1147 1.1 christos char **word;
1148 1.1 christos {
1149 1.1 christos char *word_start;
1150 1.1 christos int idx;
1151 1.1 christos char *dst;
1152 1.1 christos char *src;
1153 1.1 christos
1154 1.1 christos int length = 0;
1155 1.1 christos
1156 1.1 christos while (isspace ((unsigned char) *string) || *string == '-')
1157 1.1 christos {
1158 1.1 christos if (*string == '-')
1159 1.1 christos {
1160 1.1 christos while (*string && *string != '\n')
1161 1.1 christos string++;
1162 1.1 christos
1163 1.1 christos }
1164 1.1 christos else
1165 1.1 christos {
1166 1.1 christos string++;
1167 1.1 christos }
1168 1.1 christos }
1169 1.1 christos if (!*string)
1170 1.1 christos return 0;
1171 1.1 christos
1172 1.1 christos word_start = string;
1173 1.1 christos if (*string == '"')
1174 1.1 christos {
1175 1.1 christos do
1176 1.1 christos {
1177 1.1 christos string++;
1178 1.1 christos length++;
1179 1.1 christos if (*string == '\\')
1180 1.1 christos {
1181 1.1 christos string += 2;
1182 1.1 christos length += 2;
1183 1.1 christos }
1184 1.1 christos }
1185 1.1 christos while (*string != '"');
1186 1.1 christos }
1187 1.1 christos else
1188 1.1 christos {
1189 1.1 christos while (!isspace ((unsigned char) *string))
1190 1.1 christos {
1191 1.1 christos string++;
1192 1.1 christos length++;
1193 1.1 christos
1194 1.1 christos }
1195 1.1 christos }
1196 1.1 christos
1197 1.1 christos *word = (char *) malloc (length + 1);
1198 1.1 christos
1199 1.1 christos dst = *word;
1200 1.1 christos src = word_start;
1201 1.1 christos
1202 1.1 christos for (idx = 0; idx < length; idx++)
1203 1.1 christos {
1204 1.1 christos if (src[idx] == '\\')
1205 1.1 christos switch (src[idx + 1])
1206 1.1 christos {
1207 1.1 christos case 'n':
1208 1.1 christos *dst++ = '\n';
1209 1.1 christos idx++;
1210 1.1 christos break;
1211 1.1 christos case '"':
1212 1.1 christos case '\\':
1213 1.1 christos *dst++ = src[idx + 1];
1214 1.1 christos idx++;
1215 1.1 christos break;
1216 1.1 christos default:
1217 1.1 christos *dst++ = '\\';
1218 1.1 christos break;
1219 1.1 christos }
1220 1.1 christos else
1221 1.1 christos *dst++ = src[idx];
1222 1.1 christos }
1223 1.1 christos *dst++ = 0;
1224 1.1 christos
1225 1.1 christos if (*string)
1226 1.1 christos return string + 1;
1227 1.1 christos else
1228 1.1 christos return 0;
1229 1.1 christos }
1230 1.1 christos
1231 1.1 christos dict_type *root;
1232 1.1 christos
1233 1.1 christos dict_type *
1234 1.1 christos lookup_word (word)
1235 1.1 christos char *word;
1236 1.1 christos {
1237 1.1 christos dict_type *ptr = root;
1238 1.1 christos while (ptr)
1239 1.1 christos {
1240 1.1 christos if (strcmp (ptr->word, word) == 0)
1241 1.1 christos return ptr;
1242 1.1 christos ptr = ptr->next;
1243 1.1 christos }
1244 1.1 christos if (warning)
1245 1.1 christos fprintf (stderr, "Can't find %s\n", word);
1246 1.1 christos return 0;
1247 1.1 christos }
1248 1.1 christos
1249 1.1 christos static void
1250 1.7 christos free_words (void)
1251 1.7 christos {
1252 1.7 christos dict_type *ptr = root;
1253 1.7 christos
1254 1.7 christos while (ptr)
1255 1.7 christos {
1256 1.7 christos dict_type *next;
1257 1.7 christos
1258 1.7 christos if (ptr->word)
1259 1.7 christos free (ptr->word);
1260 1.7 christos if (ptr->code)
1261 1.7 christos {
1262 1.7 christos int i;
1263 1.7 christos for (i = 0; i < ptr->code_length; i ++)
1264 1.7 christos if (ptr->code[i] == push_text
1265 1.7 christos && ptr->code[i + 1])
1266 1.7 christos {
1267 1.7 christos free (ptr->code[i + 1] - 1);
1268 1.7 christos ++ i;
1269 1.7 christos }
1270 1.7 christos free (ptr->code);
1271 1.7 christos }
1272 1.7 christos next = ptr->next;
1273 1.7 christos free (ptr);
1274 1.7 christos ptr = next;
1275 1.7 christos }
1276 1.7 christos }
1277 1.7 christos
1278 1.7 christos static void
1279 1.1 christos perform ()
1280 1.1 christos {
1281 1.1 christos tos = stack;
1282 1.1 christos
1283 1.1 christos while (at (ptr, idx))
1284 1.1 christos {
1285 1.1 christos /* It's worth looking through the command list. */
1286 1.1 christos if (iscommand (ptr, idx))
1287 1.1 christos {
1288 1.1 christos char *next;
1289 1.1 christos dict_type *word;
1290 1.1 christos
1291 1.1 christos (void) nextword (addr (ptr, idx), &next);
1292 1.1 christos
1293 1.1 christos word = lookup_word (next);
1294 1.1 christos
1295 1.1 christos if (word)
1296 1.1 christos {
1297 1.1 christos exec (word);
1298 1.1 christos }
1299 1.1 christos else
1300 1.1 christos {
1301 1.1 christos if (warning)
1302 1.1 christos fprintf (stderr, "warning, %s is not recognised\n", next);
1303 1.1 christos skip_past_newline ();
1304 1.1 christos }
1305 1.1 christos free (next);
1306 1.1 christos }
1307 1.1 christos else
1308 1.1 christos skip_past_newline ();
1309 1.1 christos }
1310 1.1 christos }
1311 1.1 christos
1312 1.1 christos dict_type *
1313 1.1 christos newentry (word)
1314 1.1 christos char *word;
1315 1.1 christos {
1316 1.1 christos dict_type *new_d = (dict_type *) malloc (sizeof (dict_type));
1317 1.1 christos new_d->word = word;
1318 1.1 christos new_d->next = root;
1319 1.1 christos root = new_d;
1320 1.1 christos new_d->code = (stinst_type *) malloc (sizeof (stinst_type));
1321 1.1 christos new_d->code_length = 1;
1322 1.1 christos new_d->code_end = 0;
1323 1.1 christos return new_d;
1324 1.1 christos }
1325 1.1 christos
1326 1.1 christos unsigned int
1327 1.1 christos add_to_definition (entry, word)
1328 1.1 christos dict_type *entry;
1329 1.1 christos stinst_type word;
1330 1.1 christos {
1331 1.1 christos if (entry->code_end == entry->code_length)
1332 1.1 christos {
1333 1.1 christos entry->code_length += 2;
1334 1.1 christos entry->code =
1335 1.1 christos (stinst_type *) realloc ((char *) (entry->code),
1336 1.1 christos entry->code_length * sizeof (word_type));
1337 1.1 christos }
1338 1.1 christos entry->code[entry->code_end] = word;
1339 1.1 christos
1340 1.1 christos return entry->code_end++;
1341 1.1 christos }
1342 1.1 christos
1343 1.1 christos void
1344 1.1 christos add_intrinsic (name, func)
1345 1.1 christos char *name;
1346 1.1 christos void (*func) ();
1347 1.1 christos {
1348 1.7 christos dict_type *new_d = newentry (strdup (name));
1349 1.1 christos add_to_definition (new_d, func);
1350 1.1 christos add_to_definition (new_d, 0);
1351 1.1 christos }
1352 1.1 christos
1353 1.1 christos void
1354 1.1 christos add_var (name)
1355 1.1 christos char *name;
1356 1.1 christos {
1357 1.1 christos dict_type *new_d = newentry (name);
1358 1.1 christos add_to_definition (new_d, push_number);
1359 1.1 christos add_to_definition (new_d, (stinst_type) (&(new_d->var)));
1360 1.1 christos add_to_definition (new_d, 0);
1361 1.1 christos }
1362 1.1 christos
1363 1.1 christos void
1364 1.1 christos compile (string)
1365 1.1 christos char *string;
1366 1.1 christos {
1367 1.1 christos /* Add words to the dictionary. */
1368 1.1 christos char *word;
1369 1.7 christos
1370 1.1 christos string = nextword (string, &word);
1371 1.1 christos while (string && *string && word[0])
1372 1.1 christos {
1373 1.1 christos if (strcmp (word, "var") == 0)
1374 1.1 christos {
1375 1.7 christos free (word);
1376 1.1 christos string = nextword (string, &word);
1377 1.1 christos add_var (word);
1378 1.1 christos string = nextword (string, &word);
1379 1.1 christos }
1380 1.1 christos else if (word[0] == ':')
1381 1.1 christos {
1382 1.1 christos dict_type *ptr;
1383 1.7 christos
1384 1.1 christos /* Compile a word and add to dictionary. */
1385 1.7 christos free (word);
1386 1.1 christos string = nextword (string, &word);
1387 1.1 christos ptr = newentry (word);
1388 1.1 christos string = nextword (string, &word);
1389 1.7 christos
1390 1.1 christos while (word[0] != ';')
1391 1.1 christos {
1392 1.1 christos switch (word[0])
1393 1.1 christos {
1394 1.1 christos case '"':
1395 1.1 christos /* got a string, embed magic push string
1396 1.1 christos function */
1397 1.1 christos add_to_definition (ptr, push_text);
1398 1.1 christos add_to_definition (ptr, (stinst_type) (word + 1));
1399 1.1 christos break;
1400 1.1 christos case '0':
1401 1.1 christos case '1':
1402 1.1 christos case '2':
1403 1.1 christos case '3':
1404 1.1 christos case '4':
1405 1.1 christos case '5':
1406 1.1 christos case '6':
1407 1.1 christos case '7':
1408 1.1 christos case '8':
1409 1.1 christos case '9':
1410 1.1 christos /* Got a number, embedd the magic push number
1411 1.1 christos function */
1412 1.1 christos add_to_definition (ptr, push_number);
1413 1.1 christos add_to_definition (ptr, (stinst_type) atol (word));
1414 1.7 christos free (word);
1415 1.1 christos break;
1416 1.1 christos default:
1417 1.1 christos add_to_definition (ptr, call);
1418 1.1 christos add_to_definition (ptr, (stinst_type) lookup_word (word));
1419 1.7 christos free (word);
1420 1.1 christos }
1421 1.1 christos
1422 1.1 christos string = nextword (string, &word);
1423 1.1 christos }
1424 1.1 christos add_to_definition (ptr, 0);
1425 1.7 christos free (word);
1426 1.7 christos word = NULL;
1427 1.1 christos string = nextword (string, &word);
1428 1.1 christos }
1429 1.1 christos else
1430 1.1 christos {
1431 1.1 christos fprintf (stderr, "syntax error at %s\n", string - 1);
1432 1.1 christos }
1433 1.1 christos }
1434 1.7 christos if (word)
1435 1.7 christos free (word);
1436 1.1 christos }
1437 1.1 christos
1438 1.1 christos static void
1439 1.1 christos bang ()
1440 1.1 christos {
1441 1.1 christos *(long *) ((isp[0])) = isp[-1];
1442 1.1 christos isp -= 2;
1443 1.1 christos icheck_range ();
1444 1.1 christos pc++;
1445 1.1 christos }
1446 1.1 christos
1447 1.1 christos static void
1448 1.1 christos atsign ()
1449 1.1 christos {
1450 1.1 christos isp[0] = *(long *) (isp[0]);
1451 1.1 christos pc++;
1452 1.1 christos }
1453 1.1 christos
1454 1.1 christos static void
1455 1.1 christos hello ()
1456 1.1 christos {
1457 1.1 christos printf ("hello\n");
1458 1.1 christos pc++;
1459 1.1 christos }
1460 1.1 christos
1461 1.1 christos static void
1462 1.1 christos stdout_ ()
1463 1.1 christos {
1464 1.1 christos isp++;
1465 1.1 christos icheck_range ();
1466 1.1 christos *isp = 1;
1467 1.1 christos pc++;
1468 1.1 christos }
1469 1.1 christos
1470 1.1 christos static void
1471 1.1 christos stderr_ ()
1472 1.1 christos {
1473 1.1 christos isp++;
1474 1.1 christos icheck_range ();
1475 1.1 christos *isp = 2;
1476 1.1 christos pc++;
1477 1.1 christos }
1478 1.1 christos
1479 1.1 christos static void
1480 1.1 christos print ()
1481 1.1 christos {
1482 1.1 christos if (*isp == 1)
1483 1.1 christos write_buffer (tos, stdout);
1484 1.1 christos else if (*isp == 2)
1485 1.1 christos write_buffer (tos, stderr);
1486 1.1 christos else
1487 1.1 christos fprintf (stderr, "print: illegal print destination `%ld'\n", *isp);
1488 1.1 christos isp--;
1489 1.1 christos tos--;
1490 1.1 christos icheck_range ();
1491 1.1 christos check_range ();
1492 1.1 christos pc++;
1493 1.1 christos }
1494 1.1 christos
1495 1.1 christos static void
1496 1.1 christos read_in (str, file)
1497 1.1 christos string_type *str;
1498 1.1 christos FILE *file;
1499 1.1 christos {
1500 1.1 christos char buff[10000];
1501 1.1 christos unsigned int r;
1502 1.1 christos do
1503 1.1 christos {
1504 1.1 christos r = fread (buff, 1, sizeof (buff), file);
1505 1.1 christos catbuf (str, buff, r);
1506 1.1 christos }
1507 1.1 christos while (r);
1508 1.1 christos buff[0] = 0;
1509 1.1 christos
1510 1.1 christos catbuf (str, buff, 1);
1511 1.1 christos }
1512 1.1 christos
1513 1.1 christos static void
1514 1.1 christos usage ()
1515 1.1 christos {
1516 1.1 christos fprintf (stderr, "usage: -[d|i|g] <file >file\n");
1517 1.1 christos exit (33);
1518 1.1 christos }
1519 1.1 christos
1520 1.1 christos /* There is no reliable way to declare exit. Sometimes it returns
1521 1.1 christos int, and sometimes it returns void. Sometimes it changes between
1522 1.1 christos OS releases. Trying to get it declared correctly in the hosts file
1523 1.1 christos is a pointless waste of time. */
1524 1.1 christos
1525 1.1 christos static void
1526 1.1 christos chew_exit ()
1527 1.1 christos {
1528 1.1 christos exit (0);
1529 1.1 christos }
1530 1.1 christos
1531 1.1 christos int
1532 1.1 christos main (ac, av)
1533 1.1 christos int ac;
1534 1.1 christos char *av[];
1535 1.1 christos {
1536 1.1 christos unsigned int i;
1537 1.1 christos string_type buffer;
1538 1.1 christos string_type pptr;
1539 1.1 christos
1540 1.1 christos init_string (&buffer);
1541 1.1 christos init_string (&pptr);
1542 1.1 christos init_string (stack + 0);
1543 1.1 christos tos = stack + 1;
1544 1.1 christos ptr = &pptr;
1545 1.1 christos
1546 1.1 christos add_intrinsic ("push_text", push_text);
1547 1.1 christos add_intrinsic ("!", bang);
1548 1.1 christos add_intrinsic ("@", atsign);
1549 1.1 christos add_intrinsic ("hello", hello);
1550 1.1 christos add_intrinsic ("stdout", stdout_);
1551 1.1 christos add_intrinsic ("stderr", stderr_);
1552 1.1 christos add_intrinsic ("print", print);
1553 1.1 christos add_intrinsic ("skip_past_newline", skip_past_newline);
1554 1.1 christos add_intrinsic ("catstr", icatstr);
1555 1.1 christos add_intrinsic ("copy_past_newline", icopy_past_newline);
1556 1.1 christos add_intrinsic ("dup", other_dup);
1557 1.1 christos add_intrinsic ("drop", drop);
1558 1.1 christos add_intrinsic ("idrop", idrop);
1559 1.1 christos add_intrinsic ("remchar", remchar);
1560 1.1 christos add_intrinsic ("get_stuff_in_command", get_stuff_in_command);
1561 1.1 christos add_intrinsic ("do_fancy_stuff", do_fancy_stuff);
1562 1.1 christos add_intrinsic ("bulletize", bulletize);
1563 1.1 christos add_intrinsic ("courierize", courierize);
1564 1.1 christos /* If the following line gives an error, exit() is not declared in the
1565 1.1 christos ../hosts/foo.h file for this host. Fix it there, not here! */
1566 1.1 christos /* No, don't fix it anywhere; see comment on chew_exit--Ian Taylor. */
1567 1.1 christos add_intrinsic ("exit", chew_exit);
1568 1.1 christos add_intrinsic ("swap", swap);
1569 1.1 christos add_intrinsic ("outputdots", outputdots);
1570 1.1 christos add_intrinsic ("paramstuff", paramstuff);
1571 1.1 christos add_intrinsic ("maybecatstr", maybecatstr);
1572 1.1 christos add_intrinsic ("translatecomments", translatecomments);
1573 1.1 christos add_intrinsic ("kill_bogus_lines", kill_bogus_lines);
1574 1.1 christos add_intrinsic ("indent", indent);
1575 1.1 christos add_intrinsic ("internalmode", internalmode);
1576 1.1 christos add_intrinsic ("print_stack_level", print_stack_level);
1577 1.1 christos add_intrinsic ("strip_trailing_newlines", strip_trailing_newlines);
1578 1.1 christos
1579 1.1 christos /* Put a nl at the start. */
1580 1.1 christos catchar (&buffer, '\n');
1581 1.1 christos
1582 1.1 christos read_in (&buffer, stdin);
1583 1.1 christos remove_noncomments (&buffer, ptr);
1584 1.1 christos for (i = 1; i < (unsigned int) ac; i++)
1585 1.1 christos {
1586 1.1 christos if (av[i][0] == '-')
1587 1.1 christos {
1588 1.1 christos if (av[i][1] == 'f')
1589 1.1 christos {
1590 1.1 christos string_type b;
1591 1.1 christos FILE *f;
1592 1.1 christos init_string (&b);
1593 1.1 christos
1594 1.1 christos f = fopen (av[i + 1], "r");
1595 1.1 christos if (!f)
1596 1.1 christos {
1597 1.1 christos fprintf (stderr, "Can't open the input file %s\n",
1598 1.1 christos av[i + 1]);
1599 1.1 christos return 33;
1600 1.1 christos }
1601 1.1 christos
1602 1.1 christos read_in (&b, f);
1603 1.1 christos compile (b.ptr);
1604 1.1 christos perform ();
1605 1.7 christos delete_string (&b);
1606 1.1 christos }
1607 1.1 christos else if (av[i][1] == 'i')
1608 1.1 christos {
1609 1.1 christos internal_wanted = 1;
1610 1.1 christos }
1611 1.1 christos else if (av[i][1] == 'w')
1612 1.1 christos {
1613 1.1 christos warning = 1;
1614 1.1 christos }
1615 1.1 christos else
1616 1.1 christos usage ();
1617 1.1 christos }
1618 1.1 christos }
1619 1.1 christos write_buffer (stack + 0, stdout);
1620 1.7 christos free_words ();
1621 1.7 christos delete_string (&pptr);
1622 1.7 christos delete_string (&buffer);
1623 1.1 christos if (tos != stack)
1624 1.1 christos {
1625 1.1 christos fprintf (stderr, "finishing with current stack level %ld\n",
1626 1.3 christos (long) (tos - stack));
1627 1.1 christos return 1;
1628 1.1 christos }
1629 1.1 christos return 0;
1630 1.1 christos }
1631