OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [bfd/] [doc/] [chew.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.