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

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [bfd/] [doc/] [chew.c] - Blame information for rev 97

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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