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