Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/byacc/reader.c
39475 views
1
/* $Id: reader.c,v 1.104 2023/05/18 21:18:17 tom Exp $ */
2
3
#include "defs.h"
4
5
/* The line size must be a positive integer. One hundred was chosen */
6
/* because few lines in Yacc input grammars exceed 100 characters. */
7
/* Note that if a line exceeds LINESIZE characters, the line buffer */
8
/* will be expanded to accommodate it. */
9
10
#define LINESIZE 100
11
12
#define L_CURL '{'
13
#define R_CURL '}'
14
#define L_PAREN '('
15
#define R_PAREN ')'
16
#define L_BRAC '['
17
#define R_BRAC ']'
18
19
/* the maximum number of arguments (inherited attributes) to a non-terminal */
20
/* this is a hard limit, but seems more than adequate */
21
#define MAXARGS 20
22
23
/* limit the size of optional names for %union */
24
#define NAME_LEN 32
25
26
#define IS_ALNUM(c) (isalnum(c) || (c) == '_')
27
28
#define begin_case(f,n) fprintf(f, "case %d:\n", (int)(n))
29
30
#define end_case(f) \
31
fprintf(f, "\n"); \
32
fprintf_lineno(f, 1, ""); \
33
fprintf(f, "break;\n")
34
35
#define begin_ainfo(data, offset) do { \
36
data.a_lineno = lineno; \
37
data.a_line = dup_line(); \
38
data.a_cptr = data.a_line + (cptr - line - offset); \
39
} while (0)
40
41
#define end_ainfo(data) do { \
42
FREE(data.a_line); \
43
memset(&data, 0, sizeof(data)); \
44
} while (0)
45
46
static void start_rule(bucket *bp, int s_lineno);
47
#if defined(YYBTYACC)
48
static void copy_initial_action(void);
49
static void copy_destructor(void);
50
static char *process_destructor_XX(char *code, char *tag);
51
#endif
52
53
#define CACHE_SIZE 256
54
static char *cache;
55
static int cinc, cache_size;
56
57
int ntags;
58
static int tagmax, havetags;
59
static char **tag_table;
60
61
static char saw_eof;
62
char unionized;
63
64
char *line; /* current input-line */
65
char *cptr; /* position within current input-line */
66
static size_t linesize; /* length of current input-line */
67
68
typedef struct
69
{
70
char *line_data; /* saved input-line */
71
size_t line_used; /* position within saved input-line */
72
size_t line_size; /* length of saved input-line */
73
fpos_t line_fpos; /* pointer before reading past saved input-line */
74
}
75
SAVE_LINE;
76
77
static SAVE_LINE save_area;
78
static int must_save; /* request > 0, triggered < 0, inactive 0 */
79
80
static bucket *goal;
81
static Value_t prec;
82
static int gensym;
83
static char last_was_action;
84
#if defined(YYBTYACC)
85
static int trialaction;
86
#endif
87
88
static int maxitems;
89
static bucket **pitem;
90
91
static int maxrules;
92
static bucket **plhs;
93
94
static size_t name_pool_size;
95
static char *name_pool;
96
97
char line_format[] = "#line %d \"%s\"\n";
98
99
param *lex_param;
100
param *parse_param;
101
102
static const char *code_keys[] =
103
{
104
"", "requires", "provides", "top", "imports",
105
};
106
107
struct code_lines code_lines[CODE_MAX];
108
109
#if defined(YYBTYACC)
110
int destructor = 0; /* =1 if at least one %destructor */
111
112
static bucket *default_destructor[3] =
113
{0, 0, 0};
114
115
#define UNTYPED_DEFAULT 0
116
#define TYPED_DEFAULT 1
117
#define TYPE_SPECIFIED 2
118
119
static bucket *
120
lookup_type_destructor(char *tag)
121
{
122
const char fmt[] = "%.*s destructor";
123
char name[1024] = "\0";
124
bucket *bp, **bpp = &default_destructor[TYPE_SPECIFIED];
125
126
while ((bp = *bpp) != NULL)
127
{
128
if (bp->tag == tag)
129
return (bp);
130
bpp = &bp->link;
131
}
132
133
sprintf(name, fmt, (int)(sizeof(name) - sizeof(fmt)), tag);
134
*bpp = bp = make_bucket(name);
135
bp->tag = tag;
136
137
return (bp);
138
}
139
#endif /* defined(YYBTYACC) */
140
141
static void
142
cachec(int c)
143
{
144
assert(cinc >= 0);
145
if (cinc >= cache_size)
146
{
147
cache_size += CACHE_SIZE;
148
cache = TREALLOC(char, cache, cache_size);
149
NO_SPACE(cache);
150
}
151
cache[cinc] = (char)c;
152
++cinc;
153
}
154
155
typedef enum
156
{
157
ldSPC1,
158
ldSPC2,
159
ldNAME,
160
ldSPC3,
161
ldNUM,
162
ldSPC4,
163
ldFILE,
164
ldOK,
165
ldERR
166
}
167
LINE_DIR;
168
169
/*
170
* Expect this pattern:
171
* /^[[:space:]]*#[[:space:]]*
172
* line[[:space:]]+
173
* [[:digit:]]+
174
* ([[:space:]]*|[[:space:]]+"[^"]+")/
175
*/
176
static int
177
line_directive(void)
178
{
179
#define UNLESS(what) if (what) { ld = ldERR; break; }
180
int n;
181
int line_1st = -1;
182
int name_1st = -1;
183
int name_end = -1;
184
LINE_DIR ld = ldSPC1;
185
for (n = 0; (ld <= ldOK) && (line[n] != '\0'); ++n)
186
{
187
int ch = UCH(line[n]);
188
switch (ld)
189
{
190
case ldSPC1:
191
if (isspace(UCH(ch)))
192
{
193
break;
194
}
195
else
196
UNLESS(ch != '#');
197
ld = ldSPC2;
198
break;
199
case ldSPC2:
200
if (isspace(UCH(ch)))
201
{
202
break;
203
}
204
/* FALLTHRU */
205
case ldNAME:
206
UNLESS(strncmp(line + n, "line", 4));
207
n += 4;
208
if (line[n] == '\0')
209
{
210
ld = ldOK;
211
break;
212
}
213
else
214
UNLESS(!isspace(UCH(line[n])));
215
ld = ldSPC3;
216
break;
217
case ldSPC3:
218
if (isspace(UCH(ch)))
219
{
220
break;
221
}
222
else
223
UNLESS(!isdigit(UCH(ch)));
224
line_1st = n;
225
ld = ldNUM; /* this is needed, but cppcheck says no... */
226
/* FALLTHRU */
227
case ldNUM:
228
if (isdigit(UCH(ch)))
229
{
230
break;
231
}
232
else
233
UNLESS(!isspace(UCH(ch)));
234
ld = ldSPC4;
235
break;
236
case ldSPC4:
237
if (isspace(UCH(ch)))
238
{
239
break;
240
}
241
else
242
UNLESS(ch != '"');
243
UNLESS(line[n + 1] == '"');
244
ld = ldFILE;
245
name_1st = n;
246
break;
247
case ldFILE:
248
if (ch != '"')
249
{
250
break;
251
}
252
ld = ldOK;
253
name_end = n;
254
/* FALLTHRU */
255
case ldERR:
256
case ldOK:
257
break;
258
}
259
}
260
261
if (ld == ldOK)
262
{
263
size_t need = (size_t)(name_end - name_1st);
264
if ((long)need > (long)input_file_name_len)
265
{
266
input_file_name_len = ((need + 1) * 3) / 2;
267
input_file_name = TREALLOC(char, input_file_name, input_file_name_len);
268
NO_SPACE(input_file_name);
269
}
270
if ((long)need > 0)
271
{
272
memcpy(input_file_name, line + name_1st + 1, need - 1);
273
input_file_name[need - 1] = '\0';
274
}
275
else
276
{
277
input_file_name[0] = '\0';
278
}
279
}
280
281
if (ld >= ldNUM && ld < ldERR)
282
{
283
if (line_1st >= 0)
284
{
285
lineno = (int)strtol(line + line_1st, NULL, 10) - 1;
286
}
287
else
288
{
289
lineno = 0;
290
}
291
}
292
293
return (ld == ldOK);
294
#undef UNLESS
295
}
296
297
static void
298
save_line(void)
299
{
300
/* remember to save the input-line if we call get_line() */
301
if (!must_save)
302
{
303
must_save = 1;
304
save_area.line_used = (size_t)(cptr - line);
305
}
306
}
307
308
static void
309
restore_line(void)
310
{
311
/* if we saved the line, restore it */
312
if (must_save < 0)
313
{
314
free(line);
315
line = save_area.line_data;
316
cptr = save_area.line_used + line;
317
linesize = save_area.line_size;
318
if (fsetpos(input_file, &save_area.line_fpos) != 0)
319
on_error();
320
memset(&save_area, 0, sizeof(save_area));
321
}
322
else if (must_save > 0)
323
{
324
cptr = line + save_area.line_used;
325
}
326
must_save = 0;
327
}
328
329
static void
330
get_line(void)
331
{
332
FILE *f = input_file;
333
334
if (must_save > 0)
335
{
336
save_area.line_data = TMALLOC(char, linesize);
337
save_area.line_used = (size_t)(cptr - line);
338
save_area.line_size = linesize;
339
NO_SPACE(save_area.line_data);
340
memcpy(save_area.line_data, line, linesize);
341
if (fgetpos(f, &save_area.line_fpos) != 0)
342
on_error();
343
must_save = -must_save;
344
}
345
346
do
347
{
348
int c;
349
size_t i;
350
351
if (saw_eof || (c = getc(f)) == EOF)
352
{
353
if (line)
354
{
355
FREE(line);
356
line = 0;
357
}
358
cptr = 0;
359
saw_eof = 1;
360
return;
361
}
362
363
if (line == NULL || linesize != (LINESIZE + 1))
364
{
365
if (line)
366
FREE(line);
367
linesize = LINESIZE + 1;
368
line = TMALLOC(char, linesize);
369
NO_SPACE(line);
370
}
371
372
i = 0;
373
++lineno;
374
for (;;)
375
{
376
line[i++] = (char)c;
377
if (c == '\n')
378
break;
379
if ((i + 3) >= linesize)
380
{
381
linesize += LINESIZE;
382
line = TREALLOC(char, line, linesize);
383
NO_SPACE(line);
384
}
385
c = getc(f);
386
if (c == EOF)
387
{
388
line[i++] = '\n';
389
saw_eof = 1;
390
break;
391
}
392
}
393
line[i] = '\0';
394
}
395
while (line_directive());
396
cptr = line;
397
return;
398
}
399
400
static char *
401
dup_line(void)
402
{
403
char *p, *s, *t;
404
405
if (line == NULL)
406
return (NULL);
407
s = line;
408
while (*s != '\n')
409
++s;
410
p = TMALLOC(char, s - line + 1);
411
NO_SPACE(p);
412
413
s = line;
414
t = p;
415
while ((*t++ = *s++) != '\n')
416
continue;
417
return (p);
418
}
419
420
static void
421
skip_comment(void)
422
{
423
char *s;
424
struct ainfo a;
425
426
begin_ainfo(a, 0);
427
428
s = cptr + 2;
429
for (;;)
430
{
431
if (*s == '*' && s[1] == '/')
432
{
433
cptr = s + 2;
434
end_ainfo(a);
435
return;
436
}
437
if (*s == '\n')
438
{
439
get_line();
440
if (line == NULL)
441
unterminated_comment(&a);
442
s = cptr;
443
}
444
else
445
++s;
446
}
447
}
448
449
static int
450
next_inline(void)
451
{
452
char *s;
453
454
if (line == NULL)
455
{
456
get_line();
457
if (line == NULL)
458
return (EOF);
459
}
460
461
s = cptr;
462
for (;;)
463
{
464
switch (*s)
465
{
466
case '/':
467
if (s[1] == '*')
468
{
469
cptr = s;
470
skip_comment();
471
s = cptr;
472
break;
473
}
474
else if (s[1] == '/')
475
{
476
get_line();
477
if (line == NULL)
478
return (EOF);
479
s = cptr;
480
break;
481
}
482
/* FALLTHRU */
483
484
default:
485
cptr = s;
486
return (*s);
487
}
488
}
489
}
490
491
static int
492
nextc(void)
493
{
494
int ch;
495
int finish = 0;
496
497
do
498
{
499
switch (ch = next_inline())
500
{
501
case '\0':
502
case '\n':
503
get_line();
504
break;
505
case ' ':
506
case '\t':
507
case '\f':
508
case '\r':
509
case '\v':
510
case ',':
511
case ';':
512
++cptr;
513
break;
514
case '\\':
515
ch = '%';
516
/* FALLTHRU */
517
default:
518
finish = 1;
519
break;
520
}
521
}
522
while (!finish);
523
524
return ch;
525
}
526
/* *INDENT-OFF* */
527
static struct keyword
528
{
529
char name[16];
530
int token;
531
}
532
keywords[] = {
533
{ "binary", NONASSOC },
534
{ "code", XCODE },
535
{ "debug", NONPOSIX_DEBUG },
536
{ "define", HACK_DEFINE },
537
#if defined(YYBTYACC)
538
{ "destructor", DESTRUCTOR },
539
#endif
540
{ "error-verbose",ERROR_VERBOSE },
541
{ "expect", EXPECT },
542
{ "expect-rr", EXPECT_RR },
543
{ "ident", IDENT },
544
#if defined(YYBTYACC)
545
{ "initial-action", INITIAL_ACTION },
546
#endif
547
{ "left", LEFT },
548
{ "lex-param", LEX_PARAM },
549
#if defined(YYBTYACC)
550
{ "locations", LOCATIONS },
551
#endif
552
{ "nonassoc", NONASSOC },
553
{ "nterm", TYPE },
554
{ "parse-param", PARSE_PARAM },
555
{ "pure-parser", PURE_PARSER },
556
{ "right", RIGHT },
557
{ "start", START },
558
{ "term", TOKEN },
559
{ "token", TOKEN },
560
{ "token-table", TOKEN_TABLE },
561
{ "type", TYPE },
562
{ "union", UNION },
563
{ "yacc", POSIX_YACC },
564
};
565
/* *INDENT-ON* */
566
567
static int
568
compare_keys(const void *a, const void *b)
569
{
570
const struct keyword *p = (const struct keyword *)a;
571
const struct keyword *q = (const struct keyword *)b;
572
return strcmp(p->name, q->name);
573
}
574
575
static int
576
keyword(void)
577
{
578
int c;
579
char *t_cptr = cptr;
580
581
c = *++cptr;
582
if (isalpha(UCH(c)))
583
{
584
struct keyword *key;
585
586
cinc = 0;
587
for (;;)
588
{
589
if (isalpha(UCH(c)))
590
{
591
if (isupper(UCH(c)))
592
c = tolower(c);
593
cachec(c);
594
}
595
else if (isdigit(UCH(c))
596
|| c == '-'
597
|| c == '.'
598
|| c == '$')
599
{
600
cachec(c);
601
}
602
else if (c == '_')
603
{
604
/* treat keywords spelled with '_' as if it were '-' */
605
cachec('-');
606
}
607
else
608
{
609
break;
610
}
611
c = *++cptr;
612
}
613
cachec(NUL);
614
615
if ((key = bsearch(cache, keywords,
616
sizeof(keywords) / sizeof(*key),
617
sizeof(*key), compare_keys)))
618
return key->token;
619
}
620
else
621
{
622
++cptr;
623
if (c == L_CURL)
624
return (TEXT);
625
if (c == '%' || c == '\\')
626
return (MARK);
627
if (c == '<')
628
return (LEFT);
629
if (c == '>')
630
return (RIGHT);
631
if (c == '0')
632
return (TOKEN);
633
if (c == '2')
634
return (NONASSOC);
635
}
636
syntax_error(lineno, line, t_cptr);
637
/*NOTREACHED */
638
}
639
640
static void
641
copy_ident(void)
642
{
643
int c;
644
FILE *f = output_file;
645
646
c = nextc();
647
if (c == EOF)
648
unexpected_EOF();
649
if (c != '"')
650
syntax_error(lineno, line, cptr);
651
++outline;
652
fprintf(f, "#ident \"");
653
for (;;)
654
{
655
c = *++cptr;
656
if (c == '\n')
657
{
658
fprintf(f, "\"\n");
659
return;
660
}
661
putc(c, f);
662
if (c == '"')
663
{
664
putc('\n', f);
665
++cptr;
666
return;
667
}
668
}
669
}
670
671
static char *
672
copy_string(int quote)
673
{
674
struct mstring *temp = msnew();
675
struct ainfo a;
676
677
begin_ainfo(a, 1);
678
679
for (;;)
680
{
681
int c = *cptr++;
682
683
mputc(temp, c);
684
if (c == quote)
685
{
686
end_ainfo(a);
687
return msdone(temp);
688
}
689
if (c == '\n')
690
unterminated_string(&a);
691
if (c == '\\')
692
{
693
c = *cptr++;
694
mputc(temp, c);
695
if (c == '\n')
696
{
697
get_line();
698
if (line == NULL)
699
unterminated_string(&a);
700
}
701
}
702
}
703
}
704
705
static char *
706
copy_comment(void)
707
{
708
struct mstring *temp = msnew();
709
int c;
710
711
c = *cptr;
712
if (c == '/')
713
{
714
mputc(temp, '*');
715
while ((c = *++cptr) != '\n')
716
{
717
mputc(temp, c);
718
if (c == '*' && cptr[1] == '/')
719
mputc(temp, ' ');
720
}
721
mputc(temp, '*');
722
mputc(temp, '/');
723
}
724
else if (c == '*')
725
{
726
struct ainfo a;
727
728
begin_ainfo(a, 1);
729
730
mputc(temp, c);
731
++cptr;
732
for (;;)
733
{
734
c = *cptr++;
735
mputc(temp, c);
736
if (c == '*' && *cptr == '/')
737
{
738
mputc(temp, '/');
739
++cptr;
740
end_ainfo(a);
741
return msdone(temp);
742
}
743
if (c == '\n')
744
{
745
get_line();
746
if (line == NULL)
747
unterminated_comment(&a);
748
}
749
}
750
}
751
return msdone(temp);
752
}
753
754
static int
755
check_key(int pos)
756
{
757
const char *key = code_keys[pos];
758
while (*cptr && *key)
759
if (*key++ != *cptr++)
760
return 0;
761
if (*key || (!isspace(UCH(*cptr)) && *cptr != L_CURL))
762
return 0;
763
cptr--;
764
return 1;
765
}
766
767
static void
768
copy_code(void)
769
{
770
int c;
771
int curl;
772
int cline;
773
int on_line = 0;
774
int pos = CODE_HEADER;
775
struct mstring *code_mstr;
776
777
/* read %code <keyword> { */
778
for (;;)
779
{
780
c = *++cptr;
781
if (c == EOF)
782
unexpected_EOF();
783
if (c == '\0')
784
{
785
get_line();
786
if (line == NULL)
787
{
788
unexpected_EOF();
789
/*NOTREACHED */
790
}
791
c = *cptr;
792
}
793
if (isspace(UCH(c)))
794
continue;
795
796
if (c == L_CURL)
797
break;
798
799
if (pos == CODE_HEADER)
800
{
801
switch (UCH(c))
802
{
803
case 'r':
804
pos = CODE_REQUIRES;
805
break;
806
case 'p':
807
pos = CODE_PROVIDES;
808
break;
809
case 't':
810
pos = CODE_TOP;
811
break;
812
case 'i':
813
pos = CODE_IMPORTS;
814
break;
815
default:
816
break;
817
}
818
819
if (pos == -1 || !check_key(pos))
820
{
821
syntax_error(lineno, line, cptr);
822
/*NOTREACHED */
823
}
824
}
825
}
826
827
cptr++; /* skip initial curl */
828
while (*cptr && isspace(UCH(*cptr))) /* skip space */
829
cptr++;
830
curl = 1; /* nesting count */
831
832
/* gather text */
833
code_lines[pos].name = code_keys[pos];
834
if ((cline = (int)code_lines[pos].num) != 0)
835
{
836
code_mstr = msrenew(code_lines[pos].lines);
837
}
838
else
839
{
840
code_mstr = msnew();
841
}
842
cline++;
843
if (!lflag)
844
msprintf(code_mstr, line_format, lineno, input_file_name);
845
for (;;)
846
{
847
c = *cptr++;
848
switch (c)
849
{
850
case '\0':
851
get_line();
852
if (line == NULL)
853
{
854
unexpected_EOF();
855
/*NOTREACHED */
856
}
857
continue;
858
case '\n':
859
cline++;
860
on_line = 0;
861
break;
862
case L_CURL:
863
curl++;
864
break;
865
case R_CURL:
866
if (--curl == 0)
867
{
868
if (on_line > 1)
869
{
870
mputc(code_mstr, '\n');
871
cline++;
872
}
873
code_lines[pos].lines = msdone(code_mstr);
874
code_lines[pos].num = (size_t)cline;
875
return;
876
}
877
break;
878
default:
879
break;
880
}
881
mputc(code_mstr, c);
882
on_line++;
883
}
884
}
885
886
static void
887
copy_text(void)
888
{
889
int c;
890
FILE *f = text_file;
891
int need_newline = 0;
892
struct ainfo a;
893
894
begin_ainfo(a, 2);
895
896
if (*cptr == '\n')
897
{
898
get_line();
899
if (line == NULL)
900
unterminated_text(&a);
901
}
902
fprintf_lineno(f, lineno, input_file_name);
903
904
loop:
905
c = *cptr++;
906
switch (c)
907
{
908
case '\n':
909
putc('\n', f);
910
need_newline = 0;
911
get_line();
912
if (line)
913
goto loop;
914
unterminated_text(&a);
915
916
case '\'':
917
case '"':
918
putc(c, f);
919
{
920
char *s = copy_string(c);
921
fputs(s, f);
922
free(s);
923
}
924
need_newline = 1;
925
goto loop;
926
927
case '/':
928
putc(c, f);
929
{
930
char *s = copy_comment();
931
fputs(s, f);
932
free(s);
933
}
934
need_newline = 1;
935
goto loop;
936
937
case '%':
938
case '\\':
939
if (*cptr == R_CURL)
940
{
941
if (need_newline)
942
putc('\n', f);
943
++cptr;
944
end_ainfo(a);
945
return;
946
}
947
/* FALLTHRU */
948
949
default:
950
putc(c, f);
951
need_newline = 1;
952
goto loop;
953
}
954
}
955
956
static void
957
puts_both(const char *s)
958
{
959
if (s && *s)
960
{
961
fputs(s, text_file);
962
if (dflag)
963
fputs(s, union_file);
964
}
965
}
966
967
static void
968
putc_both(int c)
969
{
970
putc(c, text_file);
971
if (dflag)
972
putc(c, union_file);
973
}
974
975
static void
976
copy_union(void)
977
{
978
int c;
979
int depth;
980
struct ainfo a;
981
char prefix_buf[NAME_LEN + 1];
982
size_t prefix_len = 0;
983
char filler_buf[NAME_LEN + 1];
984
size_t filler_len = 0;
985
int in_prefix = 1;
986
987
prefix_buf[0] = '\0';
988
filler_buf[0] = '\0';
989
990
begin_ainfo(a, 6);
991
992
if (unionized)
993
over_unionized(cptr - 6);
994
unionized = 1;
995
996
puts_both("#ifdef YYSTYPE\n");
997
puts_both("#undef YYSTYPE_IS_DECLARED\n");
998
puts_both("#define YYSTYPE_IS_DECLARED 1\n");
999
puts_both("#endif\n");
1000
puts_both("#ifndef YYSTYPE_IS_DECLARED\n");
1001
puts_both("#define YYSTYPE_IS_DECLARED 1\n");
1002
1003
fprintf_lineno(text_file, lineno, input_file_name);
1004
1005
depth = 0;
1006
loop:
1007
c = *cptr++;
1008
if (in_prefix)
1009
{
1010
if (c == L_CURL)
1011
{
1012
in_prefix = 0;
1013
if (prefix_len)
1014
{
1015
puts_both("union ");
1016
puts_both(prefix_buf);
1017
puts_both(filler_buf);
1018
}
1019
else
1020
{
1021
puts_both("typedef union YYSTYPE");
1022
puts_both(filler_buf);
1023
}
1024
}
1025
else if (isspace(c))
1026
{
1027
if (filler_len >= sizeof(filler_buf) - 1)
1028
{
1029
puts_both(filler_buf);
1030
filler_len = 0;
1031
}
1032
filler_buf[filler_len++] = (char)c;
1033
filler_buf[filler_len] = 0;
1034
if (c != '\n')
1035
goto loop;
1036
}
1037
else if (IS_IDENT(c))
1038
{
1039
if (prefix_len < NAME_LEN)
1040
{
1041
prefix_buf[prefix_len++] = (char)c;
1042
prefix_buf[prefix_len] = 0;
1043
}
1044
goto loop;
1045
}
1046
}
1047
if (c != '\n' || !in_prefix)
1048
putc_both(c);
1049
switch (c)
1050
{
1051
case '\n':
1052
get_line();
1053
if (line == NULL)
1054
unterminated_union(&a);
1055
goto loop;
1056
1057
case L_CURL:
1058
++depth;
1059
goto loop;
1060
1061
case R_CURL:
1062
if (--depth == 0)
1063
{
1064
puts_both(prefix_len ? "; " : " YYSTYPE;\n");
1065
if (prefix_len)
1066
{
1067
puts_both("typedef union ");
1068
puts_both(prefix_buf);
1069
puts_both(" YYSTYPE;\n");
1070
}
1071
puts_both("#endif /* !YYSTYPE_IS_DECLARED */\n");
1072
end_ainfo(a);
1073
return;
1074
}
1075
goto loop;
1076
1077
case '\'':
1078
case '"':
1079
{
1080
char *s = copy_string(c);
1081
puts_both(s);
1082
free(s);
1083
}
1084
goto loop;
1085
1086
case '/':
1087
{
1088
char *s = copy_comment();
1089
puts_both(s);
1090
free(s);
1091
}
1092
goto loop;
1093
1094
default:
1095
goto loop;
1096
}
1097
}
1098
1099
static char *
1100
after_blanks(char *s)
1101
{
1102
while (*s != '\0' && isspace(UCH(*s)))
1103
++s;
1104
return s;
1105
}
1106
1107
/*
1108
* Trim leading/trailing blanks, and collapse multiple embedded blanks to a
1109
* single space. Return index to last character in the buffer.
1110
*/
1111
static int
1112
trim_blanks(char *buffer)
1113
{
1114
if (*buffer != '\0')
1115
{
1116
char *d = buffer;
1117
char *s = after_blanks(d);
1118
1119
while ((*d++ = *s++) != '\0')
1120
{
1121
;
1122
}
1123
1124
--d;
1125
while ((--d != buffer) && isspace(UCH(*d)))
1126
*d = '\0';
1127
1128
for (s = d = buffer; (*d++ = *s++) != '\0';)
1129
{
1130
if (isspace(UCH(*s)))
1131
{
1132
*s = ' ';
1133
while (isspace(UCH(*s)))
1134
{
1135
*s++ = ' ';
1136
}
1137
--s;
1138
}
1139
}
1140
}
1141
1142
return (int)strlen(buffer) - 1;
1143
}
1144
1145
/*
1146
* Scan forward in the current line-buffer looking for a right-curly bracket.
1147
*
1148
* Parameters begin with a left-curly bracket, and continue until there are no
1149
* more interesting characters after the last right-curly bracket on the
1150
* current line. Bison documents parameters as separated like this:
1151
* {type param1} {type2 param2}
1152
* but also accepts commas (although some versions of bison mishandle this)
1153
* {type param1, type2 param2}
1154
*/
1155
static int
1156
more_curly(void)
1157
{
1158
int result = 0;
1159
int finish = 0;
1160
save_line();
1161
do
1162
{
1163
switch (next_inline())
1164
{
1165
case 0:
1166
case '\n':
1167
finish = 1;
1168
break;
1169
case R_CURL:
1170
finish = 1;
1171
result = 1;
1172
break;
1173
}
1174
++cptr;
1175
}
1176
while (!finish);
1177
restore_line();
1178
return result;
1179
}
1180
1181
static void
1182
save_param(int k, char *buffer, int name, int type2)
1183
{
1184
param *head, *p;
1185
1186
p = TMALLOC(param, 1);
1187
NO_SPACE(p);
1188
1189
p->type2 = strdup(buffer + type2);
1190
NO_SPACE(p->type2);
1191
buffer[type2] = '\0';
1192
(void)trim_blanks(p->type2);
1193
1194
if (!IS_ALNUM(buffer[name]))
1195
{
1196
int n;
1197
for (n = name - 1; n >= 0; --n)
1198
{
1199
if (!isspace(UCH(buffer[n])))
1200
{
1201
break;
1202
}
1203
}
1204
while (n > 0)
1205
{
1206
if (!IS_ALNUM(UCH(buffer[n - 1])))
1207
break;
1208
--n;
1209
}
1210
name = n;
1211
}
1212
p->name = strdup(buffer + name);
1213
NO_SPACE(p->name);
1214
buffer[name] = '\0';
1215
(void)trim_blanks(p->name);
1216
1217
p->type = strdup(buffer);
1218
NO_SPACE(p->type);
1219
(void)trim_blanks(p->type);
1220
1221
if (k == LEX_PARAM)
1222
head = lex_param;
1223
else
1224
head = parse_param;
1225
1226
if (head != NULL)
1227
{
1228
while (head->next)
1229
head = head->next;
1230
head->next = p;
1231
}
1232
else
1233
{
1234
if (k == LEX_PARAM)
1235
lex_param = p;
1236
else
1237
parse_param = p;
1238
}
1239
p->next = NULL;
1240
}
1241
1242
/*
1243
* Keep a linked list of parameters. This may be multi-line, if the trailing
1244
* right-curly bracket is absent.
1245
*/
1246
static void
1247
copy_param(int k)
1248
{
1249
int c;
1250
int name, type2;
1251
int curly = 0;
1252
char *buf = 0;
1253
int i = -1;
1254
size_t buf_size = 0;
1255
int st_lineno = lineno;
1256
char *comma;
1257
1258
do
1259
{
1260
int state = curly;
1261
c = next_inline();
1262
switch (c)
1263
{
1264
case EOF:
1265
unexpected_EOF();
1266
break;
1267
case L_CURL:
1268
if (curly == 1)
1269
{
1270
goto oops;
1271
}
1272
curly = 1;
1273
st_lineno = lineno;
1274
break;
1275
case R_CURL:
1276
if (curly != 1)
1277
{
1278
goto oops;
1279
}
1280
curly = 2;
1281
break;
1282
case '\n':
1283
if (curly == 0)
1284
{
1285
goto oops;
1286
}
1287
break;
1288
case '%':
1289
if ((curly == 1) && (cptr == line))
1290
{
1291
lineno = st_lineno;
1292
missing_brace();
1293
}
1294
/* FALLTHRU */
1295
case '"':
1296
case '\'':
1297
goto oops;
1298
default:
1299
if (curly == 0 && !isspace(UCH(c)))
1300
{
1301
goto oops;
1302
}
1303
break;
1304
}
1305
if (buf == 0)
1306
{
1307
buf_size = (size_t)linesize;
1308
buf = TMALLOC(char, buf_size);
1309
NO_SPACE(buf);
1310
}
1311
else if (c == '\n')
1312
{
1313
char *tmp;
1314
1315
get_line();
1316
if (line == NULL)
1317
unexpected_EOF();
1318
--cptr;
1319
buf_size += (size_t)linesize;
1320
tmp = TREALLOC(char, buf, buf_size);
1321
NO_SPACE(tmp);
1322
buf = tmp;
1323
}
1324
if (curly)
1325
{
1326
if ((state == 2) && (c == L_CURL))
1327
{
1328
buf[++i] = ',';
1329
}
1330
else if ((state == 2) && isspace(UCH(c)))
1331
{
1332
;
1333
}
1334
else if ((c != L_CURL) && (c != R_CURL))
1335
{
1336
buf[++i] = (char)c;
1337
}
1338
}
1339
cptr++;
1340
}
1341
while (curly < 2 || more_curly());
1342
1343
if (i == 0)
1344
{
1345
if (curly == 1)
1346
{
1347
lineno = st_lineno;
1348
missing_brace();
1349
}
1350
goto oops;
1351
}
1352
1353
buf[++i] = '\0';
1354
(void)trim_blanks(buf);
1355
1356
comma = buf - 1;
1357
do
1358
{
1359
char *parms = (comma + 1);
1360
comma = strchr(parms, ',');
1361
if (comma != 0)
1362
*comma = '\0';
1363
1364
(void)trim_blanks(parms);
1365
i = (int)strlen(parms) - 1;
1366
if (i < 0)
1367
{
1368
goto oops;
1369
}
1370
1371
if (parms[i] == ']')
1372
{
1373
int level = 1;
1374
while (i >= 0)
1375
{
1376
char ch = parms[i--];
1377
if (ch == ']')
1378
{
1379
++level;
1380
}
1381
else if (ch == '[')
1382
{
1383
if (--level <= 1)
1384
{
1385
++i;
1386
break;
1387
}
1388
}
1389
}
1390
if (i <= 0)
1391
unexpected_EOF();
1392
type2 = i--;
1393
}
1394
else
1395
{
1396
type2 = i + 1;
1397
}
1398
1399
while (i > 0 && IS_ALNUM(UCH(parms[i])))
1400
i--;
1401
1402
if (!isspace(UCH(parms[i])) && parms[i] != '*')
1403
goto oops;
1404
1405
name = i + 1;
1406
1407
save_param(k, parms, name, type2);
1408
}
1409
while (comma != 0);
1410
FREE(buf);
1411
return;
1412
1413
oops:
1414
FREE(buf);
1415
syntax_error(lineno, line, cptr);
1416
}
1417
1418
static int
1419
hexval(int c)
1420
{
1421
if (c >= '0' && c <= '9')
1422
return (c - '0');
1423
if (c >= 'A' && c <= 'F')
1424
return (c - 'A' + 10);
1425
if (c >= 'a' && c <= 'f')
1426
return (c - 'a' + 10);
1427
return (-1);
1428
}
1429
1430
static bucket *
1431
get_literal(void)
1432
{
1433
int c, quote;
1434
int i;
1435
int n;
1436
char *s;
1437
bucket *bp;
1438
struct ainfo a;
1439
1440
begin_ainfo(a, 0);
1441
1442
quote = *cptr++;
1443
cinc = 0;
1444
for (;;)
1445
{
1446
c = *cptr++;
1447
if (c == quote)
1448
break;
1449
if (c == '\n')
1450
unterminated_string(&a);
1451
if (c == '\\')
1452
{
1453
char *c_cptr = cptr - 1;
1454
1455
c = *cptr++;
1456
switch (c)
1457
{
1458
case '\n':
1459
get_line();
1460
if (line == NULL)
1461
unterminated_string(&a);
1462
continue;
1463
1464
case '0':
1465
case '1':
1466
case '2':
1467
case '3':
1468
case '4':
1469
case '5':
1470
case '6':
1471
case '7':
1472
n = c - '0';
1473
c = *cptr;
1474
if (IS_OCTAL(c))
1475
{
1476
n = (n << 3) + (c - '0');
1477
c = *++cptr;
1478
if (IS_OCTAL(c))
1479
{
1480
n = (n << 3) + (c - '0');
1481
++cptr;
1482
}
1483
}
1484
if (n > MAXCHAR)
1485
illegal_character(c_cptr);
1486
c = n;
1487
break;
1488
1489
case 'x':
1490
c = *cptr++;
1491
n = hexval(c);
1492
if (n < 0 || n >= 16)
1493
illegal_character(c_cptr);
1494
for (;;)
1495
{
1496
c = *cptr;
1497
i = hexval(c);
1498
if (i < 0 || i >= 16)
1499
break;
1500
++cptr;
1501
n = (n << 4) + i;
1502
if (n > MAXCHAR)
1503
illegal_character(c_cptr);
1504
}
1505
c = n;
1506
break;
1507
1508
case 'a':
1509
c = 7;
1510
break;
1511
case 'b':
1512
c = '\b';
1513
break;
1514
case 'f':
1515
c = '\f';
1516
break;
1517
case 'n':
1518
c = '\n';
1519
break;
1520
case 'r':
1521
c = '\r';
1522
break;
1523
case 't':
1524
c = '\t';
1525
break;
1526
case 'v':
1527
c = '\v';
1528
break;
1529
}
1530
}
1531
cachec(c);
1532
}
1533
end_ainfo(a);
1534
1535
n = cinc;
1536
s = TMALLOC(char, n);
1537
NO_SPACE(s);
1538
1539
for (i = 0; i < n; ++i)
1540
s[i] = cache[i];
1541
1542
cinc = 0;
1543
if (n == 1)
1544
cachec('\'');
1545
else
1546
cachec('"');
1547
1548
for (i = 0; i < n; ++i)
1549
{
1550
c = UCH(s[i]);
1551
if (c == '\\' || c == cache[0])
1552
{
1553
cachec('\\');
1554
cachec(c);
1555
}
1556
else if (isprint(UCH(c)))
1557
cachec(c);
1558
else
1559
{
1560
cachec('\\');
1561
switch (c)
1562
{
1563
case 7:
1564
cachec('a');
1565
break;
1566
case '\b':
1567
cachec('b');
1568
break;
1569
case '\f':
1570
cachec('f');
1571
break;
1572
case '\n':
1573
cachec('n');
1574
break;
1575
case '\r':
1576
cachec('r');
1577
break;
1578
case '\t':
1579
cachec('t');
1580
break;
1581
case '\v':
1582
cachec('v');
1583
break;
1584
default:
1585
cachec(((c >> 6) & 7) + '0');
1586
cachec(((c >> 3) & 7) + '0');
1587
cachec((c & 7) + '0');
1588
break;
1589
}
1590
}
1591
}
1592
1593
if (n == 1)
1594
cachec('\'');
1595
else
1596
cachec('"');
1597
1598
cachec(NUL);
1599
bp = lookup(cache);
1600
bp->class = TERM;
1601
if (n == 1 && bp->value == UNDEFINED)
1602
bp->value = UCH(*s);
1603
FREE(s);
1604
1605
return (bp);
1606
}
1607
1608
static int
1609
is_reserved(char *name)
1610
{
1611
if (strcmp(name, ".") == 0 ||
1612
strcmp(name, "$accept") == 0 ||
1613
strcmp(name, "$end") == 0)
1614
return (1);
1615
1616
if (name[0] == '$' && name[1] == '$' && isdigit(UCH(name[2])))
1617
{
1618
char *s = name + 3;
1619
1620
while (isdigit(UCH(*s)))
1621
++s;
1622
if (*s == NUL)
1623
return (1);
1624
}
1625
1626
return (0);
1627
}
1628
1629
static bucket *
1630
get_name(void)
1631
{
1632
int c;
1633
1634
cinc = 0;
1635
for (c = *cptr; IS_IDENT(c); c = *++cptr)
1636
cachec(c);
1637
cachec(NUL);
1638
1639
if (is_reserved(cache))
1640
used_reserved(cache);
1641
1642
return (lookup(cache));
1643
}
1644
1645
static Value_t
1646
get_number(void)
1647
{
1648
int c;
1649
long n;
1650
char *base = cptr;
1651
1652
n = 0;
1653
for (c = *cptr; isdigit(UCH(c)); c = *++cptr)
1654
{
1655
n = (10 * n + (c - '0'));
1656
if (n > MAXYYINT)
1657
{
1658
syntax_error(lineno, line, base);
1659
/*NOTREACHED */
1660
}
1661
}
1662
1663
return (Value_t)(n);
1664
}
1665
1666
static char *
1667
cache_tag(char *tag, size_t len)
1668
{
1669
int i;
1670
char *s;
1671
1672
for (i = 0; i < ntags; ++i)
1673
{
1674
if (strncmp(tag, tag_table[i], len) == 0 &&
1675
tag_table[i][len] == NUL)
1676
return (tag_table[i]);
1677
}
1678
1679
if (ntags >= tagmax)
1680
{
1681
tagmax += 16;
1682
tag_table =
1683
(tag_table
1684
? TREALLOC(char *, tag_table, tagmax)
1685
: TMALLOC(char *, tagmax));
1686
NO_SPACE(tag_table);
1687
}
1688
1689
s = TMALLOC(char, len + 1);
1690
NO_SPACE(s);
1691
1692
strncpy(s, tag, len);
1693
s[len] = 0;
1694
tag_table[ntags++] = s;
1695
return s;
1696
}
1697
1698
static char *
1699
get_tag(void)
1700
{
1701
int c;
1702
int t_lineno = lineno;
1703
char *t_line = dup_line();
1704
char *t_cptr = t_line + (cptr - line);
1705
1706
++cptr;
1707
c = nextc();
1708
if (c == EOF)
1709
unexpected_EOF();
1710
if (!IS_NAME1(c))
1711
illegal_tag(t_lineno, t_line, t_cptr);
1712
1713
cinc = 0;
1714
do
1715
{
1716
cachec(c);
1717
c = *++cptr;
1718
}
1719
while (IS_IDENT(c));
1720
cachec(NUL);
1721
1722
c = nextc();
1723
if (c == EOF)
1724
unexpected_EOF();
1725
if (c != '>')
1726
illegal_tag(t_lineno, t_line, t_cptr);
1727
++cptr;
1728
1729
FREE(t_line);
1730
havetags = 1;
1731
return cache_tag(cache, (size_t)cinc);
1732
}
1733
1734
#if defined(YYBTYACC)
1735
static char *
1736
scan_id(void)
1737
{
1738
char *b = cptr;
1739
1740
while (IS_NAME2(UCH(*cptr)))
1741
cptr++;
1742
return cache_tag(b, (size_t)(cptr - b));
1743
}
1744
#endif
1745
1746
static void
1747
declare_tokens(int assoc)
1748
{
1749
int c;
1750
bucket *bp;
1751
Value_t value;
1752
char *tag = 0;
1753
1754
if (assoc != TOKEN)
1755
++prec;
1756
1757
c = nextc();
1758
if (c == EOF)
1759
unexpected_EOF();
1760
if (c == '<')
1761
{
1762
tag = get_tag();
1763
c = nextc();
1764
if (c == EOF)
1765
unexpected_EOF();
1766
}
1767
1768
for (;;)
1769
{
1770
if (isalpha(UCH(c)) || c == '_' || c == '.' || c == '$')
1771
bp = get_name();
1772
else if (c == '\'' || c == '"')
1773
bp = get_literal();
1774
else
1775
return;
1776
1777
if (bp == goal)
1778
tokenized_start(bp->name);
1779
bp->class = TERM;
1780
1781
if (tag)
1782
{
1783
if (bp->tag && tag != bp->tag)
1784
retyped_warning(bp->name);
1785
bp->tag = tag;
1786
}
1787
1788
if (assoc != TOKEN)
1789
{
1790
if (bp->prec && prec != bp->prec)
1791
reprec_warning(bp->name);
1792
bp->assoc = (Assoc_t)assoc;
1793
bp->prec = prec;
1794
}
1795
1796
c = nextc();
1797
if (c == EOF)
1798
unexpected_EOF();
1799
1800
if (isdigit(UCH(c)))
1801
{
1802
value = get_number();
1803
if (bp->value != UNDEFINED && value != bp->value)
1804
revalued_warning(bp->name);
1805
bp->value = value;
1806
c = nextc();
1807
if (c == EOF)
1808
unexpected_EOF();
1809
}
1810
}
1811
}
1812
1813
/*
1814
* %expect requires special handling
1815
* as it really isn't part of the yacc
1816
* grammar only a flag for yacc proper.
1817
*/
1818
static void
1819
declare_expect(int assoc)
1820
{
1821
int c;
1822
1823
if (assoc != EXPECT && assoc != EXPECT_RR)
1824
++prec;
1825
1826
/*
1827
* Stay away from nextc - doesn't
1828
* detect EOL and will read to EOF.
1829
*/
1830
c = *++cptr;
1831
if (c == EOF)
1832
unexpected_EOF();
1833
1834
for (;;)
1835
{
1836
if (isdigit(UCH(c)))
1837
{
1838
if (assoc == EXPECT)
1839
SRexpect = get_number();
1840
else
1841
RRexpect = get_number();
1842
break;
1843
}
1844
/*
1845
* Looking for number before EOL.
1846
* Spaces, tabs, and numbers are ok,
1847
* words, punc., etc. are syntax errors.
1848
*/
1849
else if (c == '\n' || isalpha(UCH(c)) || !isspace(UCH(c)))
1850
{
1851
syntax_error(lineno, line, cptr);
1852
}
1853
else
1854
{
1855
c = *++cptr;
1856
if (c == EOF)
1857
unexpected_EOF();
1858
}
1859
}
1860
}
1861
1862
#if defined(YYBTYACC)
1863
static void
1864
declare_argtypes(bucket *bp)
1865
{
1866
char *tags[MAXARGS];
1867
int args = 0;
1868
1869
if (bp->args >= 0)
1870
retyped_warning(bp->name);
1871
cptr++; /* skip open paren */
1872
for (;;)
1873
{
1874
int c = nextc();
1875
if (c == EOF)
1876
unexpected_EOF();
1877
if (c != '<')
1878
syntax_error(lineno, line, cptr);
1879
tags[args++] = get_tag();
1880
c = nextc();
1881
if (c == R_PAREN)
1882
break;
1883
if (c == EOF)
1884
unexpected_EOF();
1885
}
1886
cptr++; /* skip close paren */
1887
bp->args = args;
1888
bp->argnames = TMALLOC(char *, args);
1889
NO_SPACE(bp->argnames);
1890
bp->argtags = CALLOC(sizeof(char *), args + 1);
1891
NO_SPACE(bp->argtags);
1892
while (--args >= 0)
1893
{
1894
bp->argtags[args] = tags[args];
1895
bp->argnames[args] = NULL;
1896
}
1897
}
1898
#endif
1899
1900
static int
1901
scan_blanks(void)
1902
{
1903
int c;
1904
1905
do
1906
{
1907
c = next_inline();
1908
if (c == '\n')
1909
{
1910
++cptr;
1911
return 0;
1912
}
1913
else if (c == ' ' || c == '\t')
1914
++cptr;
1915
else
1916
break;
1917
}
1918
while (c == ' ' || c == '\t');
1919
1920
return 1;
1921
}
1922
1923
static int
1924
scan_ident(void)
1925
{
1926
int c;
1927
1928
cinc = 0;
1929
for (c = *cptr; IS_IDENT(c); c = *++cptr)
1930
cachec(c);
1931
cachec(NUL);
1932
1933
return cinc;
1934
}
1935
1936
static void
1937
hack_defines(void)
1938
{
1939
struct ainfo a;
1940
1941
if (!scan_blanks())
1942
return;
1943
1944
begin_ainfo(a, 0);
1945
if (!scan_ident())
1946
{
1947
end_ainfo(a);
1948
}
1949
1950
if (!strcmp(cache, "api.pure"))
1951
{
1952
end_ainfo(a);
1953
scan_blanks();
1954
begin_ainfo(a, 0);
1955
scan_ident();
1956
1957
if (!strcmp(cache, "false"))
1958
pure_parser = 0;
1959
else if (!strcmp(cache, "true")
1960
|| !strcmp(cache, "full")
1961
|| *cache == 0)
1962
pure_parser = 1;
1963
else
1964
unexpected_value(&a);
1965
end_ainfo(a);
1966
}
1967
else
1968
{
1969
unexpected_value(&a);
1970
}
1971
1972
while (next_inline() != '\n')
1973
++cptr;
1974
}
1975
1976
static void
1977
declare_types(void)
1978
{
1979
int c;
1980
bucket *bp = NULL;
1981
char *tag = NULL;
1982
1983
c = nextc();
1984
if (c == EOF)
1985
unexpected_EOF();
1986
if (c == '<')
1987
tag = get_tag();
1988
1989
for (;;)
1990
{
1991
c = nextc();
1992
if (c == EOF)
1993
unexpected_EOF();
1994
if (isalpha(UCH(c)) || c == '_' || c == '.' || c == '$')
1995
{
1996
bp = get_name();
1997
#if defined(YYBTYACC)
1998
if (nextc() == L_PAREN)
1999
declare_argtypes(bp);
2000
else
2001
bp->args = 0;
2002
#endif
2003
}
2004
else if (c == '\'' || c == '"')
2005
{
2006
bp = get_literal();
2007
#if defined(YYBTYACC)
2008
bp->args = 0;
2009
#endif
2010
}
2011
else
2012
return;
2013
2014
if (tag)
2015
{
2016
if (bp->tag && tag != bp->tag)
2017
retyped_warning(bp->name);
2018
bp->tag = tag;
2019
}
2020
}
2021
}
2022
2023
static void
2024
declare_start(void)
2025
{
2026
int c;
2027
bucket *bp;
2028
2029
c = nextc();
2030
if (c == EOF)
2031
unexpected_EOF();
2032
if (!isalpha(UCH(c)) && c != '_' && c != '.' && c != '$')
2033
syntax_error(lineno, line, cptr);
2034
bp = get_name();
2035
if (bp->class == TERM)
2036
terminal_start(bp->name);
2037
if (goal && goal != bp)
2038
restarted_warning();
2039
goal = bp;
2040
}
2041
2042
static void
2043
read_declarations(void)
2044
{
2045
cache_size = CACHE_SIZE;
2046
cache = TMALLOC(char, cache_size);
2047
NO_SPACE(cache);
2048
2049
for (;;)
2050
{
2051
int k;
2052
int c = nextc();
2053
2054
if (c == EOF)
2055
unexpected_EOF();
2056
if (c != '%')
2057
syntax_error(lineno, line, cptr);
2058
switch (k = keyword())
2059
{
2060
case MARK:
2061
return;
2062
2063
case IDENT:
2064
copy_ident();
2065
break;
2066
2067
case XCODE:
2068
copy_code();
2069
break;
2070
2071
case TEXT:
2072
copy_text();
2073
break;
2074
2075
case UNION:
2076
copy_union();
2077
break;
2078
2079
case TOKEN:
2080
case LEFT:
2081
case RIGHT:
2082
case NONASSOC:
2083
declare_tokens(k);
2084
break;
2085
2086
case EXPECT:
2087
case EXPECT_RR:
2088
declare_expect(k);
2089
break;
2090
2091
case TYPE:
2092
declare_types();
2093
break;
2094
2095
case START:
2096
declare_start();
2097
break;
2098
2099
case PURE_PARSER:
2100
pure_parser = 1;
2101
break;
2102
2103
case PARSE_PARAM:
2104
case LEX_PARAM:
2105
copy_param(k);
2106
break;
2107
2108
case TOKEN_TABLE:
2109
token_table = 1;
2110
break;
2111
2112
case ERROR_VERBOSE:
2113
error_verbose = 1;
2114
break;
2115
2116
#if defined(YYBTYACC)
2117
case LOCATIONS:
2118
locations = 1;
2119
break;
2120
2121
case DESTRUCTOR:
2122
destructor = 1;
2123
copy_destructor();
2124
break;
2125
case INITIAL_ACTION:
2126
copy_initial_action();
2127
break;
2128
#endif
2129
2130
case NONPOSIX_DEBUG:
2131
tflag = 1;
2132
break;
2133
2134
case HACK_DEFINE:
2135
hack_defines();
2136
break;
2137
2138
case POSIX_YACC:
2139
/* noop for bison compatibility. byacc is already designed to be posix
2140
* yacc compatible. */
2141
break;
2142
}
2143
}
2144
}
2145
2146
static void
2147
initialize_grammar(void)
2148
{
2149
nitems = 4;
2150
maxitems = 300;
2151
2152
pitem = TMALLOC(bucket *, maxitems);
2153
NO_SPACE(pitem);
2154
2155
pitem[0] = 0;
2156
pitem[1] = 0;
2157
pitem[2] = 0;
2158
pitem[3] = 0;
2159
2160
nrules = 3;
2161
maxrules = 100;
2162
2163
plhs = TMALLOC(bucket *, maxrules);
2164
NO_SPACE(plhs);
2165
2166
plhs[0] = 0;
2167
plhs[1] = 0;
2168
plhs[2] = 0;
2169
2170
rprec = TMALLOC(Value_t, maxrules);
2171
NO_SPACE(rprec);
2172
2173
rprec[0] = 0;
2174
rprec[1] = 0;
2175
rprec[2] = 0;
2176
2177
rassoc = TMALLOC(Assoc_t, maxrules);
2178
NO_SPACE(rassoc);
2179
2180
rassoc[0] = TOKEN;
2181
rassoc[1] = TOKEN;
2182
rassoc[2] = TOKEN;
2183
}
2184
2185
static void
2186
expand_items(void)
2187
{
2188
maxitems += 300;
2189
pitem = TREALLOC(bucket *, pitem, maxitems);
2190
NO_SPACE(pitem);
2191
}
2192
2193
static void
2194
expand_rules(void)
2195
{
2196
maxrules += 100;
2197
2198
plhs = TREALLOC(bucket *, plhs, maxrules);
2199
NO_SPACE(plhs);
2200
2201
rprec = TREALLOC(Value_t, rprec, maxrules);
2202
NO_SPACE(rprec);
2203
2204
rassoc = TREALLOC(Assoc_t, rassoc, maxrules);
2205
NO_SPACE(rassoc);
2206
}
2207
2208
/* set immediately prior to where copy_args() could be called, and incremented by
2209
the various routines that will rescan the argument list as appropriate */
2210
static int rescan_lineno;
2211
#if defined(YYBTYACC)
2212
2213
static char *
2214
copy_args(int *alen)
2215
{
2216
struct mstring *s = msnew();
2217
int depth = 0, len = 1;
2218
char c, quote = 0;
2219
struct ainfo a;
2220
2221
begin_ainfo(a, 1);
2222
2223
while ((c = *cptr++) != R_PAREN || depth || quote)
2224
{
2225
if (c == ',' && !quote && !depth)
2226
{
2227
len++;
2228
mputc(s, 0);
2229
continue;
2230
}
2231
mputc(s, c);
2232
if (c == '\n')
2233
{
2234
get_line();
2235
if (!line)
2236
{
2237
if (quote)
2238
unterminated_string(&a);
2239
else
2240
unterminated_arglist(&a);
2241
}
2242
}
2243
else if (quote)
2244
{
2245
if (c == quote)
2246
quote = 0;
2247
else if (c == '\\')
2248
{
2249
if (*cptr != '\n')
2250
mputc(s, *cptr++);
2251
}
2252
}
2253
else
2254
{
2255
if (c == L_PAREN)
2256
depth++;
2257
else if (c == R_PAREN)
2258
depth--;
2259
else if (c == '\"' || c == '\'')
2260
quote = c;
2261
}
2262
}
2263
if (alen)
2264
*alen = len;
2265
end_ainfo(a);
2266
return msdone(s);
2267
}
2268
2269
static char *
2270
parse_id(char *p, char **save)
2271
{
2272
char *b;
2273
2274
while (isspace(UCH(*p)))
2275
if (*p++ == '\n')
2276
rescan_lineno++;
2277
if (!isalpha(UCH(*p)) && *p != '_')
2278
return NULL;
2279
b = p;
2280
while (IS_NAME2(UCH(*p)))
2281
p++;
2282
if (save)
2283
{
2284
*save = cache_tag(b, (size_t)(p - b));
2285
}
2286
return p;
2287
}
2288
2289
static char *
2290
parse_int(char *p, int *save)
2291
{
2292
int neg = 0, val = 0;
2293
2294
while (isspace(UCH(*p)))
2295
if (*p++ == '\n')
2296
rescan_lineno++;
2297
if (*p == '-')
2298
{
2299
neg = 1;
2300
p++;
2301
}
2302
if (!isdigit(UCH(*p)))
2303
return NULL;
2304
while (isdigit(UCH(*p)))
2305
val = val * 10 + *p++ - '0';
2306
if (neg)
2307
val = -val;
2308
if (save)
2309
*save = val;
2310
return p;
2311
}
2312
2313
static void
2314
parse_arginfo(bucket *a, char *args, int argslen)
2315
{
2316
char *p = args, *tmp;
2317
int i, redec = 0;
2318
2319
if (a->args >= 0)
2320
{
2321
if (a->args != argslen)
2322
arg_number_disagree_warning(rescan_lineno, a->name);
2323
redec = 1;
2324
}
2325
else
2326
{
2327
if ((a->args = argslen) == 0)
2328
return;
2329
a->argnames = TMALLOC(char *, argslen);
2330
NO_SPACE(a->argnames);
2331
a->argtags = TMALLOC(char *, argslen);
2332
NO_SPACE(a->argtags);
2333
}
2334
if (!args)
2335
return;
2336
for (i = 0; i < argslen; i++)
2337
{
2338
while (isspace(UCH(*p)))
2339
if (*p++ == '\n')
2340
rescan_lineno++;
2341
if (*p++ != '$')
2342
bad_formals();
2343
while (isspace(UCH(*p)))
2344
if (*p++ == '\n')
2345
rescan_lineno++;
2346
if (*p == '<')
2347
{
2348
havetags = 1;
2349
if (!(p = parse_id(p + 1, &tmp)))
2350
bad_formals();
2351
while (isspace(UCH(*p)))
2352
if (*p++ == '\n')
2353
rescan_lineno++;
2354
if (*p++ != '>')
2355
bad_formals();
2356
if (redec)
2357
{
2358
if (a->argtags[i] != tmp)
2359
arg_type_disagree_warning(rescan_lineno, i + 1, a->name);
2360
}
2361
else
2362
a->argtags[i] = tmp;
2363
}
2364
else if (!redec)
2365
a->argtags[i] = NULL;
2366
if (!(p = parse_id(p, &a->argnames[i])))
2367
bad_formals();
2368
while (isspace(UCH(*p)))
2369
if (*p++ == '\n')
2370
rescan_lineno++;
2371
if (*p++)
2372
bad_formals();
2373
}
2374
free(args);
2375
}
2376
2377
static char *
2378
compile_arg(char **theptr, char *yyvaltag)
2379
{
2380
char *p = *theptr;
2381
struct mstring *c = msnew();
2382
int i, n;
2383
Value_t *offsets = NULL, maxoffset;
2384
bucket **rhs;
2385
2386
maxoffset = 0;
2387
n = 0;
2388
for (i = nitems - 1; pitem[i]; --i)
2389
{
2390
n++;
2391
if (pitem[i]->class != ARGUMENT)
2392
maxoffset++;
2393
}
2394
if (maxoffset > 0)
2395
{
2396
int j;
2397
2398
offsets = TCMALLOC(Value_t, maxoffset + 1);
2399
NO_SPACE(offsets);
2400
2401
for (j = 0, i++; i < nitems; i++)
2402
if (pitem[i]->class != ARGUMENT)
2403
offsets[++j] = (Value_t)(i - nitems + 1);
2404
}
2405
rhs = pitem + nitems - 1;
2406
2407
if (yyvaltag)
2408
msprintf(c, "yyval.%s = ", yyvaltag);
2409
else
2410
msprintf(c, "yyval = ");
2411
while (*p)
2412
{
2413
if (*p == '$')
2414
{
2415
char *tag = NULL;
2416
if (*++p == '<')
2417
if (!(p = parse_id(++p, &tag)) || *p++ != '>')
2418
illegal_tag(rescan_lineno, NULL, NULL);
2419
if (isdigit(UCH(*p)) || *p == '-')
2420
{
2421
int val;
2422
if (!(p = parse_int(p, &val)))
2423
dollar_error(rescan_lineno, NULL, NULL);
2424
if (val <= 0)
2425
i = val - n;
2426
else if (val > maxoffset)
2427
{
2428
dollar_warning(rescan_lineno, val);
2429
i = val - maxoffset;
2430
}
2431
else if (maxoffset > 0)
2432
{
2433
i = offsets[val];
2434
if (!tag && !(tag = rhs[i]->tag) && havetags)
2435
untyped_rhs(val, rhs[i]->name);
2436
}
2437
msprintf(c, "yystack.l_mark[%d]", i);
2438
if (tag)
2439
msprintf(c, ".%s", tag);
2440
else if (havetags)
2441
unknown_rhs(val);
2442
}
2443
else if (isalpha(UCH(*p)) || *p == '_')
2444
{
2445
char *arg;
2446
if (!(p = parse_id(p, &arg)))
2447
dollar_error(rescan_lineno, NULL, NULL);
2448
for (i = plhs[nrules]->args - 1; i >= 0; i--)
2449
if (arg == plhs[nrules]->argnames[i])
2450
break;
2451
if (i < 0)
2452
unknown_arg_warning(rescan_lineno, "$", arg, NULL, NULL);
2453
else if (!tag)
2454
tag = plhs[nrules]->argtags[i];
2455
msprintf(c, "yystack.l_mark[%d]",
2456
i - plhs[nrules]->args + 1 - n);
2457
if (tag)
2458
msprintf(c, ".%s", tag);
2459
else if (havetags)
2460
untyped_arg_warning(rescan_lineno, "$", arg);
2461
}
2462
else
2463
dollar_error(rescan_lineno, NULL, NULL);
2464
}
2465
else if (*p == '@')
2466
{
2467
at_error(rescan_lineno, NULL, NULL);
2468
}
2469
else
2470
{
2471
if (*p == '\n')
2472
rescan_lineno++;
2473
mputc(c, *p++);
2474
}
2475
}
2476
*theptr = p;
2477
if (maxoffset > 0)
2478
FREE(offsets);
2479
return msdone(c);
2480
}
2481
2482
static int
2483
can_elide_arg(char **theptr, char *yyvaltag)
2484
{
2485
char *p = *theptr;
2486
int rv = 0;
2487
int i, n = 0;
2488
Value_t *offsets = NULL, maxoffset = 0;
2489
bucket **rhs;
2490
char *tag = 0;
2491
2492
if (*p++ != '$')
2493
return 0;
2494
if (*p == '<')
2495
{
2496
if (!(p = parse_id(++p, &tag)) || *p++ != '>')
2497
return 0;
2498
}
2499
for (i = nitems - 1; pitem[i]; --i)
2500
{
2501
n++;
2502
if (pitem[i]->class != ARGUMENT)
2503
maxoffset++;
2504
}
2505
if (maxoffset > 0)
2506
{
2507
int j;
2508
2509
offsets = TCMALLOC(Value_t, maxoffset + 1);
2510
NO_SPACE(offsets);
2511
2512
for (j = 0, i++; i < nitems; i++)
2513
if (pitem[i]->class != ARGUMENT)
2514
offsets[++j] = (Value_t)(i - nitems + 1);
2515
}
2516
rhs = pitem + nitems - 1;
2517
2518
if (isdigit(UCH(*p)) || *p == '-')
2519
{
2520
int val;
2521
if (!(p = parse_int(p, &val)))
2522
rv = 0;
2523
else
2524
{
2525
if (val <= 0)
2526
rv = 1 - val + n;
2527
else if (val > maxoffset)
2528
rv = 0;
2529
else
2530
{
2531
i = offsets[val];
2532
rv = 1 - i;
2533
if (!tag)
2534
tag = rhs[i]->tag;
2535
}
2536
}
2537
}
2538
else if (isalpha(UCH(*p)) || *p == '_')
2539
{
2540
char *arg;
2541
if (!(p = parse_id(p, &arg)))
2542
{
2543
FREE(offsets);
2544
return 0;
2545
}
2546
for (i = plhs[nrules]->args - 1; i >= 0; i--)
2547
if (arg == plhs[nrules]->argnames[i])
2548
break;
2549
if (i >= 0)
2550
{
2551
if (!tag)
2552
tag = plhs[nrules]->argtags[i];
2553
rv = plhs[nrules]->args + n - i;
2554
}
2555
}
2556
if (tag && yyvaltag)
2557
{
2558
if (strcmp(tag, yyvaltag))
2559
rv = 0;
2560
}
2561
else if (tag || yyvaltag)
2562
rv = 0;
2563
if (maxoffset > 0)
2564
FREE(offsets);
2565
if (p == 0 || *p || rv <= 0)
2566
return 0;
2567
*theptr = p + 1;
2568
return rv;
2569
}
2570
2571
#define ARG_CACHE_SIZE 1024
2572
static struct arg_cache
2573
{
2574
struct arg_cache *next;
2575
char *code;
2576
int rule;
2577
}
2578
*arg_cache[ARG_CACHE_SIZE];
2579
2580
static int
2581
lookup_arg_cache(char *code)
2582
{
2583
struct arg_cache *entry;
2584
2585
entry = arg_cache[strnshash(code) % ARG_CACHE_SIZE];
2586
while (entry)
2587
{
2588
if (!strnscmp(entry->code, code))
2589
return entry->rule;
2590
entry = entry->next;
2591
}
2592
return -1;
2593
}
2594
2595
static void
2596
insert_arg_cache(char *code, int rule)
2597
{
2598
struct arg_cache *entry = NEW(struct arg_cache);
2599
int i;
2600
2601
NO_SPACE(entry);
2602
i = strnshash(code) % ARG_CACHE_SIZE;
2603
entry->code = code;
2604
entry->rule = rule;
2605
entry->next = arg_cache[i];
2606
arg_cache[i] = entry;
2607
}
2608
2609
static void
2610
clean_arg_cache(void)
2611
{
2612
struct arg_cache *e, *t;
2613
int i;
2614
2615
for (i = 0; i < ARG_CACHE_SIZE; i++)
2616
{
2617
for (e = arg_cache[i]; (t = e); e = e->next, FREE(t))
2618
free(e->code);
2619
arg_cache[i] = NULL;
2620
}
2621
}
2622
#endif /* defined(YYBTYACC) */
2623
2624
static void
2625
advance_to_start(void)
2626
{
2627
int c;
2628
bucket *bp;
2629
int s_lineno;
2630
#if defined(YYBTYACC)
2631
char *args = NULL;
2632
int argslen = 0;
2633
#endif
2634
2635
for (;;)
2636
{
2637
char *s_cptr;
2638
2639
c = nextc();
2640
if (c != '%')
2641
break;
2642
s_cptr = cptr;
2643
switch (keyword())
2644
{
2645
case XCODE:
2646
copy_code();
2647
break;
2648
2649
case MARK:
2650
no_grammar();
2651
2652
case TEXT:
2653
copy_text();
2654
break;
2655
2656
case START:
2657
declare_start();
2658
break;
2659
2660
default:
2661
syntax_error(lineno, line, s_cptr);
2662
}
2663
}
2664
2665
c = nextc();
2666
if (!isalpha(UCH(c)) && c != '_' && c != '.' && c != '_')
2667
syntax_error(lineno, line, cptr);
2668
bp = get_name();
2669
if (goal == 0)
2670
{
2671
if (bp->class == TERM)
2672
terminal_start(bp->name);
2673
goal = bp;
2674
}
2675
2676
s_lineno = lineno;
2677
c = nextc();
2678
if (c == EOF)
2679
unexpected_EOF();
2680
rescan_lineno = lineno; /* line# for possible inherited args rescan */
2681
#if defined(YYBTYACC)
2682
if (c == L_PAREN)
2683
{
2684
++cptr;
2685
args = copy_args(&argslen);
2686
NO_SPACE(args);
2687
c = nextc();
2688
}
2689
#endif
2690
if (c != ':')
2691
syntax_error(lineno, line, cptr);
2692
start_rule(bp, s_lineno);
2693
#if defined(YYBTYACC)
2694
parse_arginfo(bp, args, argslen);
2695
#endif
2696
++cptr;
2697
}
2698
2699
static void
2700
start_rule(bucket *bp, int s_lineno)
2701
{
2702
if (bp->class == TERM)
2703
terminal_lhs(s_lineno);
2704
bp->class = NONTERM;
2705
if (!bp->index)
2706
bp->index = nrules;
2707
if (nrules >= maxrules)
2708
expand_rules();
2709
plhs[nrules] = bp;
2710
rprec[nrules] = UNDEFINED;
2711
rassoc[nrules] = TOKEN;
2712
}
2713
2714
static void
2715
end_rule(void)
2716
{
2717
if (!last_was_action && plhs[nrules]->tag)
2718
{
2719
if (pitem[nitems - 1])
2720
{
2721
int i;
2722
2723
for (i = nitems - 1; (i > 0) && pitem[i]; --i)
2724
continue;
2725
if (pitem[i + 1] == 0 || pitem[i + 1]->tag != plhs[nrules]->tag)
2726
default_action_warning(plhs[nrules]->name);
2727
}
2728
else
2729
default_action_warning(plhs[nrules]->name);
2730
}
2731
2732
last_was_action = 0;
2733
if (nitems >= maxitems)
2734
expand_items();
2735
pitem[nitems] = 0;
2736
++nitems;
2737
++nrules;
2738
}
2739
2740
static void
2741
insert_empty_rule(void)
2742
{
2743
bucket *bp, **bpp;
2744
2745
assert(cache);
2746
assert(cache_size >= CACHE_SIZE);
2747
sprintf(cache, "$$%d", ++gensym);
2748
bp = make_bucket(cache);
2749
last_symbol->next = bp;
2750
last_symbol = bp;
2751
bp->tag = plhs[nrules]->tag;
2752
bp->class = ACTION;
2753
#if defined(YYBTYACC)
2754
bp->args = 0;
2755
#endif
2756
2757
nitems = (Value_t)(nitems + 2);
2758
if (nitems > maxitems)
2759
expand_items();
2760
bpp = pitem + nitems - 1;
2761
*bpp-- = bp;
2762
while ((bpp[0] = bpp[-1]) != 0)
2763
--bpp;
2764
2765
if (++nrules >= maxrules)
2766
expand_rules();
2767
plhs[nrules] = plhs[nrules - 1];
2768
plhs[nrules - 1] = bp;
2769
rprec[nrules] = rprec[nrules - 1];
2770
rprec[nrules - 1] = 0;
2771
rassoc[nrules] = rassoc[nrules - 1];
2772
rassoc[nrules - 1] = TOKEN;
2773
}
2774
2775
#if defined(YYBTYACC)
2776
static char *
2777
insert_arg_rule(char *arg, char *tag)
2778
{
2779
int line_number = rescan_lineno;
2780
char *code = compile_arg(&arg, tag);
2781
int rule = lookup_arg_cache(code);
2782
FILE *f = action_file;
2783
2784
if (rule < 0)
2785
{
2786
rule = nrules;
2787
insert_arg_cache(code, rule);
2788
trialaction = 1; /* arg rules always run in trial mode */
2789
begin_case(f, rule - 2);
2790
fprintf_lineno(f, line_number, input_file_name);
2791
fprintf(f, "%s;", code);
2792
end_case(f);
2793
insert_empty_rule();
2794
plhs[rule]->tag = cache_tag(tag, strlen(tag));
2795
plhs[rule]->class = ARGUMENT;
2796
}
2797
else
2798
{
2799
if (++nitems > maxitems)
2800
expand_items();
2801
pitem[nitems - 1] = plhs[rule];
2802
free(code);
2803
}
2804
return arg + 1;
2805
}
2806
#endif
2807
2808
static void
2809
add_symbol(void)
2810
{
2811
int c;
2812
bucket *bp;
2813
int s_lineno = lineno;
2814
#if defined(YYBTYACC)
2815
char *args = NULL;
2816
int argslen = 0;
2817
#endif
2818
2819
c = *cptr;
2820
if (c == '\'' || c == '"')
2821
bp = get_literal();
2822
else
2823
bp = get_name();
2824
2825
c = nextc();
2826
rescan_lineno = lineno; /* line# for possible inherited args rescan */
2827
#if defined(YYBTYACC)
2828
if (c == L_PAREN)
2829
{
2830
++cptr;
2831
args = copy_args(&argslen);
2832
NO_SPACE(args);
2833
c = nextc();
2834
}
2835
#endif
2836
if (c == ':')
2837
{
2838
end_rule();
2839
start_rule(bp, s_lineno);
2840
#if defined(YYBTYACC)
2841
parse_arginfo(bp, args, argslen);
2842
#endif
2843
++cptr;
2844
return;
2845
}
2846
2847
if (last_was_action)
2848
insert_empty_rule();
2849
last_was_action = 0;
2850
2851
#if defined(YYBTYACC)
2852
if (bp->args < 0)
2853
bp->args = argslen;
2854
if (argslen == 0 && bp->args > 0 && pitem[nitems - 1] == NULL)
2855
{
2856
int i;
2857
if (plhs[nrules]->args != bp->args)
2858
wrong_number_args_warning("default ", bp->name);
2859
for (i = bp->args - 1; i >= 0; i--)
2860
if (plhs[nrules]->argtags[i] != bp->argtags[i])
2861
wrong_type_for_arg_warning(i + 1, bp->name);
2862
}
2863
else if (bp->args != argslen)
2864
wrong_number_args_warning("", bp->name);
2865
if (args != 0)
2866
{
2867
char *ap = args;
2868
int i = 0;
2869
int elide_cnt = can_elide_arg(&ap, bp->argtags[0]);
2870
2871
if (elide_cnt > argslen)
2872
elide_cnt = 0;
2873
if (elide_cnt)
2874
{
2875
for (i = 1; i < elide_cnt; i++)
2876
if (can_elide_arg(&ap, bp->argtags[i]) != elide_cnt - i)
2877
{
2878
elide_cnt = 0;
2879
break;
2880
}
2881
}
2882
if (elide_cnt)
2883
{
2884
assert(i == elide_cnt);
2885
}
2886
else
2887
{
2888
ap = args;
2889
i = 0;
2890
}
2891
for (; i < argslen; i++)
2892
ap = insert_arg_rule(ap, bp->argtags[i]);
2893
free(args);
2894
}
2895
#endif /* defined(YYBTYACC) */
2896
2897
if (++nitems > maxitems)
2898
expand_items();
2899
pitem[nitems - 1] = bp;
2900
}
2901
2902
static void
2903
copy_action(void)
2904
{
2905
int c;
2906
int i, j, n;
2907
int depth;
2908
#if defined(YYBTYACC)
2909
int haveyyval = 0;
2910
#endif
2911
char *tag;
2912
FILE *f = action_file;
2913
struct ainfo a;
2914
Value_t *offsets = NULL, maxoffset;
2915
bucket **rhs;
2916
2917
begin_ainfo(a, 0);
2918
2919
if (last_was_action)
2920
insert_empty_rule();
2921
last_was_action = 1;
2922
#if defined(YYBTYACC)
2923
trialaction = (*cptr == L_BRAC);
2924
#endif
2925
2926
begin_case(f, nrules - 2);
2927
#if defined(YYBTYACC)
2928
if (backtrack)
2929
{
2930
if (!trialaction)
2931
fprintf(f, " if (!yytrial)\n");
2932
}
2933
#endif
2934
fprintf_lineno(f, lineno, input_file_name);
2935
if (*cptr == '=')
2936
++cptr;
2937
2938
/* avoid putting curly-braces in first column, to ease editing */
2939
if (*after_blanks(cptr) == L_CURL)
2940
{
2941
putc('\t', f);
2942
cptr = after_blanks(cptr);
2943
}
2944
2945
maxoffset = 0;
2946
n = 0;
2947
for (i = nitems - 1; pitem[i]; --i)
2948
{
2949
++n;
2950
if (pitem[i]->class != ARGUMENT)
2951
maxoffset++;
2952
}
2953
if (maxoffset > 0)
2954
{
2955
offsets = TMALLOC(Value_t, maxoffset + 1);
2956
NO_SPACE(offsets);
2957
2958
for (j = 0, i++; i < nitems; i++)
2959
{
2960
if (pitem[i]->class != ARGUMENT)
2961
{
2962
offsets[++j] = (Value_t)(i - nitems + 1);
2963
}
2964
}
2965
}
2966
rhs = pitem + nitems - 1;
2967
2968
depth = 0;
2969
loop:
2970
c = *cptr;
2971
if (c == '$')
2972
{
2973
if (cptr[1] == '<')
2974
{
2975
int d_lineno = lineno;
2976
char *d_line = dup_line();
2977
char *d_cptr = d_line + (cptr - line);
2978
2979
++cptr;
2980
tag = get_tag();
2981
c = *cptr;
2982
if (c == '$')
2983
{
2984
fprintf(f, "yyval.%s", tag);
2985
++cptr;
2986
FREE(d_line);
2987
goto loop;
2988
}
2989
else if (isdigit(UCH(c)))
2990
{
2991
i = get_number();
2992
if (i == 0)
2993
fprintf(f, "yystack.l_mark[%d].%s", -n, tag);
2994
else if (i > maxoffset)
2995
{
2996
dollar_warning(d_lineno, i);
2997
fprintf(f, "yystack.l_mark[%ld].%s",
2998
(long)(i - maxoffset), tag);
2999
}
3000
else if (offsets)
3001
fprintf(f, "yystack.l_mark[%ld].%s",
3002
(long)offsets[i], tag);
3003
FREE(d_line);
3004
goto loop;
3005
}
3006
else if (c == '-' && isdigit(UCH(cptr[1])))
3007
{
3008
++cptr;
3009
i = -get_number() - n;
3010
fprintf(f, "yystack.l_mark[%d].%s", i, tag);
3011
FREE(d_line);
3012
goto loop;
3013
}
3014
#if defined(YYBTYACC)
3015
else if (isalpha(UCH(c)) || c == '_')
3016
{
3017
char *arg = scan_id();
3018
for (i = plhs[nrules]->args - 1; i >= 0; i--)
3019
if (arg == plhs[nrules]->argnames[i])
3020
break;
3021
if (i < 0)
3022
unknown_arg_warning(d_lineno, "$", arg, d_line, d_cptr);
3023
fprintf(f, "yystack.l_mark[%d].%s",
3024
i - plhs[nrules]->args + 1 - n, tag);
3025
FREE(d_line);
3026
goto loop;
3027
}
3028
#endif
3029
else
3030
dollar_error(d_lineno, d_line, d_cptr);
3031
}
3032
else if (cptr[1] == '$')
3033
{
3034
if (havetags)
3035
{
3036
tag = plhs[nrules]->tag;
3037
if (tag == 0)
3038
untyped_lhs();
3039
fprintf(f, "yyval.%s", tag);
3040
}
3041
else
3042
fprintf(f, "yyval");
3043
cptr += 2;
3044
#if defined(YYBTYACC)
3045
haveyyval = 1;
3046
#endif
3047
goto loop;
3048
}
3049
else if (isdigit(UCH(cptr[1])))
3050
{
3051
++cptr;
3052
i = get_number();
3053
if (havetags && offsets)
3054
{
3055
if (i <= 0 || i > maxoffset)
3056
unknown_rhs(i);
3057
tag = rhs[offsets[i]]->tag;
3058
if (tag == 0)
3059
untyped_rhs(i, rhs[offsets[i]]->name);
3060
fprintf(f, "yystack.l_mark[%ld].%s", (long)offsets[i], tag);
3061
}
3062
else
3063
{
3064
if (i == 0)
3065
fprintf(f, "yystack.l_mark[%d]", -n);
3066
else if (i > maxoffset)
3067
{
3068
dollar_warning(lineno, i);
3069
fprintf(f, "yystack.l_mark[%ld]", (long)(i - maxoffset));
3070
}
3071
else if (offsets)
3072
fprintf(f, "yystack.l_mark[%ld]", (long)offsets[i]);
3073
}
3074
goto loop;
3075
}
3076
else if (cptr[1] == '-')
3077
{
3078
cptr += 2;
3079
i = get_number();
3080
if (havetags)
3081
unknown_rhs(-i);
3082
fprintf(f, "yystack.l_mark[%d]", -i - n);
3083
goto loop;
3084
}
3085
#if defined(YYBTYACC)
3086
else if (isalpha(UCH(cptr[1])) || cptr[1] == '_')
3087
{
3088
char *arg;
3089
++cptr;
3090
arg = scan_id();
3091
for (i = plhs[nrules]->args - 1; i >= 0; i--)
3092
if (arg == plhs[nrules]->argnames[i])
3093
break;
3094
if (i < 0)
3095
unknown_arg_warning(lineno, "$", arg, line, cptr);
3096
tag = (i < 0 ? NULL : plhs[nrules]->argtags[i]);
3097
fprintf(f, "yystack.l_mark[%d]", i - plhs[nrules]->args + 1 - n);
3098
if (tag)
3099
fprintf(f, ".%s", tag);
3100
else if (havetags)
3101
untyped_arg_warning(lineno, "$", arg);
3102
goto loop;
3103
}
3104
#endif
3105
}
3106
#if defined(YYBTYACC)
3107
if (c == '@')
3108
{
3109
if (!locations)
3110
{
3111
dislocations_warning();
3112
locations = 1;
3113
}
3114
if (cptr[1] == '$')
3115
{
3116
fprintf(f, "yyloc");
3117
cptr += 2;
3118
goto loop;
3119
}
3120
else if (isdigit(UCH(cptr[1])))
3121
{
3122
++cptr;
3123
i = get_number();
3124
if (i == 0)
3125
fprintf(f, "yystack.p_mark[%d]", -n);
3126
else if (i > maxoffset)
3127
{
3128
at_warning(lineno, i);
3129
fprintf(f, "yystack.p_mark[%d]", i - maxoffset);
3130
}
3131
else if (offsets)
3132
fprintf(f, "yystack.p_mark[%d]", offsets[i]);
3133
goto loop;
3134
}
3135
else if (cptr[1] == '-')
3136
{
3137
cptr += 2;
3138
i = get_number();
3139
fprintf(f, "yystack.p_mark[%d]", -i - n);
3140
goto loop;
3141
}
3142
}
3143
#endif
3144
if (IS_NAME1(c))
3145
{
3146
do
3147
{
3148
putc(c, f);
3149
c = *++cptr;
3150
}
3151
while (IS_NAME2(c));
3152
goto loop;
3153
}
3154
++cptr;
3155
#if defined(YYBTYACC)
3156
if (backtrack)
3157
{
3158
if (trialaction && c == L_BRAC && depth == 0)
3159
{
3160
++depth;
3161
putc(L_CURL, f);
3162
goto loop;
3163
}
3164
if (trialaction && c == R_BRAC && depth == 1)
3165
{
3166
--depth;
3167
putc(R_CURL, f);
3168
c = nextc();
3169
if (c == L_BRAC && !haveyyval)
3170
{
3171
goto loop;
3172
}
3173
if (c == L_CURL && !haveyyval)
3174
{
3175
fprintf(f, " if (!yytrial)\n");
3176
fprintf_lineno(f, lineno, input_file_name);
3177
trialaction = 0;
3178
goto loop;
3179
}
3180
end_case(f);
3181
end_ainfo(a);
3182
if (maxoffset > 0)
3183
FREE(offsets);
3184
return;
3185
}
3186
}
3187
#endif
3188
putc(c, f);
3189
switch (c)
3190
{
3191
case '\n':
3192
get_line();
3193
if (line)
3194
goto loop;
3195
unterminated_action(&a);
3196
3197
case ';':
3198
if (depth > 0)
3199
goto loop;
3200
end_case(f);
3201
end_ainfo(a);
3202
if (maxoffset > 0)
3203
FREE(offsets);
3204
return;
3205
3206
#if defined(YYBTYACC)
3207
case L_BRAC:
3208
if (backtrack)
3209
++depth;
3210
goto loop;
3211
3212
case R_BRAC:
3213
if (backtrack)
3214
--depth;
3215
goto loop;
3216
#endif
3217
3218
case L_CURL:
3219
++depth;
3220
goto loop;
3221
3222
case R_CURL:
3223
if (--depth > 0)
3224
goto loop;
3225
#if defined(YYBTYACC)
3226
if (backtrack)
3227
{
3228
c = nextc();
3229
if (c == L_BRAC && !haveyyval)
3230
{
3231
trialaction = 1;
3232
goto loop;
3233
}
3234
if (c == L_CURL && !haveyyval)
3235
{
3236
fprintf(f, " if (!yytrial)\n");
3237
fprintf_lineno(f, lineno, input_file_name);
3238
goto loop;
3239
}
3240
}
3241
#endif
3242
end_case(f);
3243
end_ainfo(a);
3244
if (maxoffset > 0)
3245
FREE(offsets);
3246
return;
3247
3248
case '\'':
3249
case '"':
3250
{
3251
char *s = copy_string(c);
3252
fputs(s, f);
3253
free(s);
3254
}
3255
goto loop;
3256
3257
case '/':
3258
{
3259
char *s = copy_comment();
3260
fputs(s, f);
3261
free(s);
3262
}
3263
goto loop;
3264
3265
default:
3266
goto loop;
3267
}
3268
}
3269
3270
#if defined(YYBTYACC)
3271
static char *
3272
get_code(struct ainfo *a, const char *loc)
3273
{
3274
int c;
3275
int depth;
3276
char *tag;
3277
struct mstring *code_mstr = msnew();
3278
3279
if (!lflag)
3280
msprintf(code_mstr, line_format, lineno, input_file_name);
3281
3282
cptr = after_blanks(cptr);
3283
if (*cptr == L_CURL)
3284
/* avoid putting curly-braces in first column, to ease editing */
3285
mputc(code_mstr, '\t');
3286
else
3287
syntax_error(lineno, line, cptr);
3288
3289
begin_ainfo((*a), 0);
3290
3291
depth = 0;
3292
loop:
3293
c = *cptr;
3294
if (c == '$')
3295
{
3296
if (cptr[1] == '<')
3297
{
3298
int d_lineno = lineno;
3299
char *d_line = dup_line();
3300
char *d_cptr = d_line + (cptr - line);
3301
3302
++cptr;
3303
tag = get_tag();
3304
c = *cptr;
3305
if (c == '$')
3306
{
3307
msprintf(code_mstr, "(*val).%s", tag);
3308
++cptr;
3309
FREE(d_line);
3310
goto loop;
3311
}
3312
else
3313
dollar_error(d_lineno, d_line, d_cptr);
3314
}
3315
else if (cptr[1] == '$')
3316
{
3317
/* process '$$' later; replacement is context dependent */
3318
msprintf(code_mstr, "$$");
3319
cptr += 2;
3320
goto loop;
3321
}
3322
}
3323
if (c == '@' && cptr[1] == '$')
3324
{
3325
if (!locations)
3326
{
3327
dislocations_warning();
3328
locations = 1;
3329
}
3330
msprintf(code_mstr, "%s", loc);
3331
cptr += 2;
3332
goto loop;
3333
}
3334
if (IS_NAME1(c))
3335
{
3336
do
3337
{
3338
mputc(code_mstr, c);
3339
c = *++cptr;
3340
}
3341
while (IS_NAME2(c));
3342
goto loop;
3343
}
3344
++cptr;
3345
mputc(code_mstr, c);
3346
switch (c)
3347
{
3348
case '\n':
3349
get_line();
3350
if (line)
3351
goto loop;
3352
unterminated_action(a);
3353
3354
case L_CURL:
3355
++depth;
3356
goto loop;
3357
3358
case R_CURL:
3359
if (--depth > 0)
3360
goto loop;
3361
goto out;
3362
3363
case '\'':
3364
case '"':
3365
{
3366
char *s = copy_string(c);
3367
msprintf(code_mstr, "%s", s);
3368
free(s);
3369
}
3370
goto loop;
3371
3372
case '/':
3373
{
3374
char *s = copy_comment();
3375
msprintf(code_mstr, "%s", s);
3376
free(s);
3377
}
3378
goto loop;
3379
3380
default:
3381
goto loop;
3382
}
3383
out:
3384
return msdone(code_mstr);
3385
}
3386
3387
static void
3388
copy_initial_action(void)
3389
{
3390
struct ainfo a;
3391
3392
initial_action = get_code(&a, "yyloc");
3393
end_ainfo(a);
3394
}
3395
3396
static void
3397
copy_destructor(void)
3398
{
3399
char *code_text;
3400
struct ainfo a;
3401
bucket *bp;
3402
3403
code_text = get_code(&a, "(*loc)");
3404
3405
for (;;)
3406
{
3407
int c = nextc();
3408
if (c == EOF)
3409
unexpected_EOF();
3410
if (c == '<')
3411
{
3412
if (cptr[1] == '>')
3413
{ /* "no semantic type" default destructor */
3414
cptr += 2;
3415
if ((bp = default_destructor[UNTYPED_DEFAULT]) == NULL)
3416
{
3417
static char untyped_default[] = "<>";
3418
bp = make_bucket("untyped default");
3419
bp->tag = untyped_default;
3420
default_destructor[UNTYPED_DEFAULT] = bp;
3421
}
3422
if (bp->destructor != NULL)
3423
destructor_redeclared_warning(&a);
3424
else
3425
/* replace "$$" with "(*val)" in destructor code */
3426
bp->destructor = process_destructor_XX(code_text, NULL);
3427
}
3428
else if (cptr[1] == '*' && cptr[2] == '>')
3429
{ /* "no per-symbol or per-type" default destructor */
3430
cptr += 3;
3431
if ((bp = default_destructor[TYPED_DEFAULT]) == NULL)
3432
{
3433
static char typed_default[] = "<*>";
3434
bp = make_bucket("typed default");
3435
bp->tag = typed_default;
3436
default_destructor[TYPED_DEFAULT] = bp;
3437
}
3438
if (bp->destructor != NULL)
3439
destructor_redeclared_warning(&a);
3440
else
3441
{
3442
/* postpone re-processing destructor $$s until end of grammar spec */
3443
bp->destructor = TMALLOC(char, strlen(code_text) + 1);
3444
NO_SPACE(bp->destructor);
3445
strcpy(bp->destructor, code_text);
3446
}
3447
}
3448
else
3449
{ /* "semantic type" default destructor */
3450
char *tag = get_tag();
3451
bp = lookup_type_destructor(tag);
3452
if (bp->destructor != NULL)
3453
destructor_redeclared_warning(&a);
3454
else
3455
/* replace "$$" with "(*val).tag" in destructor code */
3456
bp->destructor = process_destructor_XX(code_text, tag);
3457
}
3458
}
3459
else if (isalpha(UCH(c)) || c == '_' || c == '.' || c == '$')
3460
{ /* "symbol" destructor */
3461
bp = get_name();
3462
if (bp->destructor != NULL)
3463
destructor_redeclared_warning(&a);
3464
else
3465
{
3466
/* postpone re-processing destructor $$s until end of grammar spec */
3467
bp->destructor = TMALLOC(char, strlen(code_text) + 1);
3468
NO_SPACE(bp->destructor);
3469
strcpy(bp->destructor, code_text);
3470
}
3471
}
3472
else
3473
break;
3474
}
3475
end_ainfo(a);
3476
free(code_text);
3477
}
3478
3479
static char *
3480
process_destructor_XX(char *code, char *tag)
3481
{
3482
int c;
3483
int quote;
3484
int depth;
3485
struct mstring *new_code = msnew();
3486
char *codeptr = code;
3487
3488
depth = 0;
3489
loop: /* step thru code */
3490
c = *codeptr;
3491
if (c == '$' && codeptr[1] == '$')
3492
{
3493
codeptr += 2;
3494
if (tag == NULL)
3495
msprintf(new_code, "(*val)");
3496
else
3497
msprintf(new_code, "(*val).%s", tag);
3498
goto loop;
3499
}
3500
if (IS_NAME1(c))
3501
{
3502
do
3503
{
3504
mputc(new_code, c);
3505
c = *++codeptr;
3506
}
3507
while (IS_NAME2(c));
3508
goto loop;
3509
}
3510
++codeptr;
3511
mputc(new_code, c);
3512
switch (c)
3513
{
3514
case L_CURL:
3515
++depth;
3516
goto loop;
3517
3518
case R_CURL:
3519
if (--depth > 0)
3520
goto loop;
3521
return msdone(new_code);
3522
3523
case '\'':
3524
case '"':
3525
quote = c;
3526
for (;;)
3527
{
3528
c = *codeptr++;
3529
mputc(new_code, c);
3530
if (c == quote)
3531
goto loop;
3532
if (c == '\\')
3533
{
3534
c = *codeptr++;
3535
mputc(new_code, c);
3536
}
3537
}
3538
3539
case '/':
3540
c = *codeptr;
3541
if (c == '*')
3542
{
3543
mputc(new_code, c);
3544
++codeptr;
3545
for (;;)
3546
{
3547
c = *codeptr++;
3548
mputc(new_code, c);
3549
if (c == '*' && *codeptr == '/')
3550
{
3551
mputc(new_code, '/');
3552
++codeptr;
3553
goto loop;
3554
}
3555
}
3556
}
3557
goto loop;
3558
3559
default:
3560
goto loop;
3561
}
3562
}
3563
#endif /* defined(YYBTYACC) */
3564
3565
static int
3566
mark_symbol(void)
3567
{
3568
int c;
3569
bucket *bp = NULL;
3570
3571
c = cptr[1];
3572
if (c == '%' || c == '\\')
3573
{
3574
cptr += 2;
3575
return (1);
3576
}
3577
3578
if (c == '=')
3579
cptr += 2;
3580
else if ((c == 'p' || c == 'P') &&
3581
((c = cptr[2]) == 'r' || c == 'R') &&
3582
((c = cptr[3]) == 'e' || c == 'E') &&
3583
((c = cptr[4]) == 'c' || c == 'C') &&
3584
((c = cptr[5], !IS_IDENT(c))))
3585
cptr += 5;
3586
else if ((c == 'e' || c == 'E') &&
3587
((c = cptr[2]) == 'm' || c == 'M') &&
3588
((c = cptr[3]) == 'p' || c == 'P') &&
3589
((c = cptr[4]) == 't' || c == 'T') &&
3590
((c = cptr[5]) == 'y' || c == 'Y') &&
3591
((c = cptr[6], !IS_IDENT(c))))
3592
{
3593
cptr += 6;
3594
return (1);
3595
}
3596
else
3597
syntax_error(lineno, line, cptr);
3598
3599
c = nextc();
3600
if (isalpha(UCH(c)) || c == '_' || c == '.' || c == '$')
3601
bp = get_name();
3602
else if (c == '\'' || c == '"')
3603
bp = get_literal();
3604
else
3605
{
3606
syntax_error(lineno, line, cptr);
3607
/*NOTREACHED */
3608
}
3609
3610
if (rprec[nrules] != UNDEFINED && bp->prec != rprec[nrules])
3611
prec_redeclared();
3612
3613
rprec[nrules] = bp->prec;
3614
rassoc[nrules] = bp->assoc;
3615
return (0);
3616
}
3617
3618
static void
3619
read_grammar(void)
3620
{
3621
initialize_grammar();
3622
advance_to_start();
3623
3624
for (;;)
3625
{
3626
int c = nextc();
3627
3628
if (c == EOF)
3629
break;
3630
if (isalpha(UCH(c))
3631
|| c == '_'
3632
|| c == '.'
3633
|| c == '$'
3634
|| c == '\''
3635
|| c == '"')
3636
{
3637
add_symbol();
3638
}
3639
else if (c == L_CURL || c == '='
3640
#if defined(YYBTYACC)
3641
|| (backtrack && c == L_BRAC)
3642
#endif
3643
)
3644
{
3645
copy_action();
3646
}
3647
else if (c == '|')
3648
{
3649
end_rule();
3650
start_rule(plhs[nrules - 1], 0);
3651
++cptr;
3652
}
3653
else if (c == '%')
3654
{
3655
if (mark_symbol())
3656
break;
3657
}
3658
else
3659
syntax_error(lineno, line, cptr);
3660
}
3661
end_rule();
3662
#if defined(YYBTYACC)
3663
if (goal->args > 0)
3664
start_requires_args(goal->name);
3665
#endif
3666
}
3667
3668
static void
3669
free_tags(void)
3670
{
3671
int i;
3672
3673
if (tag_table == 0)
3674
return;
3675
3676
for (i = 0; i < ntags; ++i)
3677
{
3678
assert(tag_table[i]);
3679
FREE(tag_table[i]);
3680
}
3681
FREE(tag_table);
3682
}
3683
3684
static void
3685
pack_names(void)
3686
{
3687
bucket *bp;
3688
char *p;
3689
char *t;
3690
3691
name_pool_size = 13; /* 13 == sizeof("$end") + sizeof("$accept") */
3692
for (bp = first_symbol; bp; bp = bp->next)
3693
name_pool_size += strlen(bp->name) + 1;
3694
3695
name_pool = TMALLOC(char, name_pool_size);
3696
NO_SPACE(name_pool);
3697
3698
strcpy(name_pool, "$accept");
3699
strcpy(name_pool + 8, "$end");
3700
t = name_pool + 13;
3701
for (bp = first_symbol; bp; bp = bp->next)
3702
{
3703
char *s = bp->name;
3704
3705
p = t;
3706
while ((*t++ = *s++) != 0)
3707
continue;
3708
FREE(bp->name);
3709
bp->name = p;
3710
}
3711
}
3712
3713
static void
3714
check_symbols(void)
3715
{
3716
bucket *bp;
3717
3718
if (goal->class == UNKNOWN)
3719
undefined_goal(goal->name);
3720
3721
for (bp = first_symbol; bp; bp = bp->next)
3722
{
3723
if (bp->class == UNKNOWN)
3724
{
3725
undefined_symbol_warning(bp->name);
3726
bp->class = TERM;
3727
}
3728
}
3729
}
3730
3731
static void
3732
protect_string(char *src, char **des)
3733
{
3734
*des = src;
3735
if (src)
3736
{
3737
char *s;
3738
char *d;
3739
3740
unsigned len = 1;
3741
3742
s = src;
3743
while (*s)
3744
{
3745
if ('\\' == *s || '"' == *s)
3746
len++;
3747
s++;
3748
len++;
3749
}
3750
3751
*des = d = TMALLOC(char, len);
3752
NO_SPACE(d);
3753
3754
s = src;
3755
while (*s)
3756
{
3757
if ('\\' == *s || '"' == *s)
3758
*d++ = '\\';
3759
*d++ = *s++;
3760
}
3761
*d = '\0';
3762
}
3763
}
3764
3765
static void
3766
pack_symbols(void)
3767
{
3768
bucket *bp;
3769
bucket **v;
3770
Value_t i, j, k, n;
3771
#if defined(YYBTYACC)
3772
Value_t max_tok_pval;
3773
#endif
3774
3775
nsyms = 2;
3776
ntokens = 1;
3777
for (bp = first_symbol; bp; bp = bp->next)
3778
{
3779
++nsyms;
3780
if (bp->class == TERM)
3781
++ntokens;
3782
}
3783
start_symbol = (Value_t)ntokens;
3784
nvars = (Value_t)(nsyms - ntokens);
3785
3786
symbol_name = TMALLOC(char *, nsyms);
3787
NO_SPACE(symbol_name);
3788
3789
symbol_value = TMALLOC(Value_t, nsyms);
3790
NO_SPACE(symbol_value);
3791
3792
symbol_prec = TMALLOC(Value_t, nsyms);
3793
NO_SPACE(symbol_prec);
3794
3795
symbol_assoc = TMALLOC(char, nsyms);
3796
NO_SPACE(symbol_assoc);
3797
3798
#if defined(YYBTYACC)
3799
symbol_pval = TMALLOC(Value_t, nsyms);
3800
NO_SPACE(symbol_pval);
3801
3802
if (destructor)
3803
{
3804
symbol_destructor = CALLOC(sizeof(char *), nsyms);
3805
NO_SPACE(symbol_destructor);
3806
3807
symbol_type_tag = CALLOC(sizeof(char *), nsyms);
3808
NO_SPACE(symbol_type_tag);
3809
}
3810
#endif
3811
3812
v = TMALLOC(bucket *, nsyms);
3813
NO_SPACE(v);
3814
3815
v[0] = 0;
3816
v[start_symbol] = 0;
3817
3818
i = 1;
3819
j = (Value_t)(start_symbol + 1);
3820
for (bp = first_symbol; bp; bp = bp->next)
3821
{
3822
if (bp->class == TERM)
3823
v[i++] = bp;
3824
else
3825
v[j++] = bp;
3826
}
3827
assert(i == ntokens && j == nsyms);
3828
3829
for (i = 1; i < ntokens; ++i)
3830
v[i]->index = i;
3831
3832
goal->index = (Index_t)(start_symbol + 1);
3833
k = (Value_t)(start_symbol + 2);
3834
while (++i < nsyms)
3835
if (v[i] != goal)
3836
{
3837
v[i]->index = k;
3838
++k;
3839
}
3840
3841
goal->value = 0;
3842
k = 1;
3843
for (i = (Value_t)(start_symbol + 1); i < nsyms; ++i)
3844
{
3845
if (v[i] != goal)
3846
{
3847
v[i]->value = k;
3848
++k;
3849
}
3850
}
3851
3852
k = 0;
3853
for (i = 1; i < ntokens; ++i)
3854
{
3855
n = v[i]->value;
3856
if (n > 256)
3857
{
3858
for (j = k++; j > 0 && symbol_value[j - 1] > n; --j)
3859
symbol_value[j] = symbol_value[j - 1];
3860
symbol_value[j] = n;
3861
}
3862
}
3863
3864
assert(v[1] != 0);
3865
3866
if (v[1]->value == UNDEFINED)
3867
v[1]->value = 256;
3868
3869
j = 0;
3870
n = 257;
3871
for (i = 2; i < ntokens; ++i)
3872
{
3873
if (v[i]->value == UNDEFINED)
3874
{
3875
while (j < k && n == symbol_value[j])
3876
{
3877
while (++j < k && n == symbol_value[j])
3878
continue;
3879
++n;
3880
}
3881
v[i]->value = n;
3882
++n;
3883
}
3884
}
3885
3886
symbol_name[0] = name_pool + 8;
3887
symbol_value[0] = 0;
3888
symbol_prec[0] = 0;
3889
symbol_assoc[0] = TOKEN;
3890
#if defined(YYBTYACC)
3891
symbol_pval[0] = 0;
3892
max_tok_pval = 0;
3893
#endif
3894
for (i = 1; i < ntokens; ++i)
3895
{
3896
symbol_name[i] = v[i]->name;
3897
symbol_value[i] = v[i]->value;
3898
symbol_prec[i] = v[i]->prec;
3899
symbol_assoc[i] = v[i]->assoc;
3900
#if defined(YYBTYACC)
3901
symbol_pval[i] = v[i]->value;
3902
if (symbol_pval[i] > max_tok_pval)
3903
max_tok_pval = symbol_pval[i];
3904
if (destructor)
3905
{
3906
symbol_destructor[i] = v[i]->destructor;
3907
symbol_type_tag[i] = v[i]->tag;
3908
}
3909
#endif
3910
}
3911
symbol_name[start_symbol] = name_pool;
3912
symbol_value[start_symbol] = -1;
3913
symbol_prec[start_symbol] = 0;
3914
symbol_assoc[start_symbol] = TOKEN;
3915
#if defined(YYBTYACC)
3916
symbol_pval[start_symbol] = (Value_t)(max_tok_pval + 1);
3917
#endif
3918
for (++i; i < nsyms; ++i)
3919
{
3920
k = v[i]->index;
3921
symbol_name[k] = v[i]->name;
3922
symbol_value[k] = v[i]->value;
3923
symbol_prec[k] = v[i]->prec;
3924
symbol_assoc[k] = v[i]->assoc;
3925
#if defined(YYBTYACC)
3926
symbol_pval[k] = (Value_t)((max_tok_pval + 1) + v[i]->value + 1);
3927
if (destructor)
3928
{
3929
symbol_destructor[k] = v[i]->destructor;
3930
symbol_type_tag[k] = v[i]->tag;
3931
}
3932
#endif
3933
}
3934
3935
if (gflag)
3936
{
3937
symbol_pname = TMALLOC(char *, nsyms);
3938
NO_SPACE(symbol_pname);
3939
3940
for (i = 0; i < nsyms; ++i)
3941
protect_string(symbol_name[i], &(symbol_pname[i]));
3942
}
3943
3944
FREE(v);
3945
}
3946
3947
static void
3948
pack_grammar(void)
3949
{
3950
int i;
3951
Value_t j;
3952
3953
ritem = TMALLOC(Value_t, nitems);
3954
NO_SPACE(ritem);
3955
3956
rlhs = TMALLOC(Value_t, nrules);
3957
NO_SPACE(rlhs);
3958
3959
rrhs = TMALLOC(Value_t, nrules + 1);
3960
NO_SPACE(rrhs);
3961
3962
rprec = TREALLOC(Value_t, rprec, nrules);
3963
NO_SPACE(rprec);
3964
3965
rassoc = TREALLOC(Assoc_t, rassoc, nrules);
3966
NO_SPACE(rassoc);
3967
3968
ritem[0] = -1;
3969
ritem[1] = goal->index;
3970
ritem[2] = 0;
3971
ritem[3] = -2;
3972
rlhs[0] = 0;
3973
rlhs[1] = 0;
3974
rlhs[2] = start_symbol;
3975
rrhs[0] = 0;
3976
rrhs[1] = 0;
3977
rrhs[2] = 1;
3978
3979
j = 4;
3980
for (i = 3; i < nrules; ++i)
3981
{
3982
Assoc_t assoc;
3983
Value_t prec2;
3984
3985
#if defined(YYBTYACC)
3986
if (plhs[i]->args > 0)
3987
{
3988
if (plhs[i]->argnames)
3989
{
3990
FREE(plhs[i]->argnames);
3991
plhs[i]->argnames = NULL;
3992
}
3993
if (plhs[i]->argtags)
3994
{
3995
FREE(plhs[i]->argtags);
3996
plhs[i]->argtags = NULL;
3997
}
3998
}
3999
#endif /* defined(YYBTYACC) */
4000
rlhs[i] = plhs[i]->index;
4001
rrhs[i] = j;
4002
assoc = TOKEN;
4003
prec2 = 0;
4004
while (pitem[j])
4005
{
4006
ritem[j] = pitem[j]->index;
4007
if (pitem[j]->class == TERM)
4008
{
4009
prec2 = pitem[j]->prec;
4010
assoc = pitem[j]->assoc;
4011
}
4012
++j;
4013
}
4014
ritem[j] = (Value_t)-i;
4015
++j;
4016
if (rprec[i] == UNDEFINED)
4017
{
4018
rprec[i] = prec2;
4019
rassoc[i] = assoc;
4020
}
4021
}
4022
rrhs[i] = j;
4023
4024
FREE(plhs);
4025
FREE(pitem);
4026
#if defined(YYBTYACC)
4027
clean_arg_cache();
4028
#endif
4029
}
4030
4031
static void
4032
print_grammar(void)
4033
{
4034
int i, k;
4035
size_t j, spacing = 0;
4036
FILE *f = verbose_file;
4037
4038
if (!vflag)
4039
return;
4040
4041
k = 1;
4042
for (i = 2; i < nrules; ++i)
4043
{
4044
if (rlhs[i] != rlhs[i - 1])
4045
{
4046
if (i != 2)
4047
fprintf(f, "\n");
4048
fprintf(f, "%4d %s :", i - 2, symbol_name[rlhs[i]]);
4049
spacing = strlen(symbol_name[rlhs[i]]) + 1;
4050
}
4051
else
4052
{
4053
fprintf(f, "%4d ", i - 2);
4054
j = spacing;
4055
while (j-- != 0)
4056
putc(' ', f);
4057
putc('|', f);
4058
}
4059
4060
while (ritem[k] >= 0)
4061
{
4062
fprintf(f, " %s", symbol_name[ritem[k]]);
4063
++k;
4064
}
4065
++k;
4066
putc('\n', f);
4067
}
4068
}
4069
4070
#if defined(YYBTYACC)
4071
static void
4072
finalize_destructors(void)
4073
{
4074
int i;
4075
bucket *bp;
4076
4077
for (i = 2; i < nsyms; ++i)
4078
{
4079
char *tag = symbol_type_tag[i];
4080
4081
if (symbol_destructor[i] == NULL)
4082
{
4083
if (tag == NULL)
4084
{ /* use <> destructor, if there is one */
4085
if ((bp = default_destructor[UNTYPED_DEFAULT]) != NULL)
4086
{
4087
symbol_destructor[i] = TMALLOC(char,
4088
strlen(bp->destructor) + 1);
4089
NO_SPACE(symbol_destructor[i]);
4090
strcpy(symbol_destructor[i], bp->destructor);
4091
}
4092
}
4093
else
4094
{ /* use type destructor for this tag, if there is one */
4095
bp = lookup_type_destructor(tag);
4096
if (bp->destructor != NULL)
4097
{
4098
symbol_destructor[i] = TMALLOC(char,
4099
strlen(bp->destructor) + 1);
4100
NO_SPACE(symbol_destructor[i]);
4101
strcpy(symbol_destructor[i], bp->destructor);
4102
}
4103
else
4104
{ /* use <*> destructor, if there is one */
4105
if ((bp = default_destructor[TYPED_DEFAULT]) != NULL)
4106
/* replace "$$" with "(*val).tag" in destructor code */
4107
symbol_destructor[i]
4108
= process_destructor_XX(bp->destructor, tag);
4109
}
4110
}
4111
}
4112
else
4113
{ /* replace "$$" with "(*val)[.tag]" in destructor code */
4114
char *destructor_source = symbol_destructor[i];
4115
symbol_destructor[i]
4116
= process_destructor_XX(destructor_source, tag);
4117
FREE(destructor_source);
4118
}
4119
}
4120
/* 'symbol_type_tag[]' elements are freed by 'free_tags()' */
4121
DO_FREE(symbol_type_tag); /* no longer needed */
4122
if ((bp = default_destructor[UNTYPED_DEFAULT]) != NULL)
4123
{
4124
FREE(bp->name);
4125
/* 'bp->tag' is a static value, don't free */
4126
FREE(bp->destructor);
4127
FREE(bp);
4128
}
4129
if ((bp = default_destructor[TYPED_DEFAULT]) != NULL)
4130
{
4131
FREE(bp->name);
4132
/* 'bp->tag' is a static value, don't free */
4133
FREE(bp->destructor);
4134
FREE(bp);
4135
}
4136
if ((bp = default_destructor[TYPE_SPECIFIED]) != NULL)
4137
{
4138
bucket *p;
4139
for (; bp; bp = p)
4140
{
4141
p = bp->link;
4142
FREE(bp->name);
4143
/* 'bp->tag' freed by 'free_tags()' */
4144
FREE(bp->destructor);
4145
FREE(bp);
4146
}
4147
}
4148
}
4149
#endif /* defined(YYBTYACC) */
4150
4151
void
4152
reader(void)
4153
{
4154
write_section(code_file, banner);
4155
create_symbol_table();
4156
read_declarations();
4157
read_grammar();
4158
free_symbol_table();
4159
pack_names();
4160
check_symbols();
4161
pack_symbols();
4162
pack_grammar();
4163
free_symbols();
4164
print_grammar();
4165
#if defined(YYBTYACC)
4166
if (destructor)
4167
finalize_destructors();
4168
#endif
4169
free_tags();
4170
}
4171
4172
#ifdef NO_LEAKS
4173
static param *
4174
free_declarations(param *list)
4175
{
4176
while (list != 0)
4177
{
4178
param *next = list->next;
4179
free(list->type);
4180
free(list->name);
4181
free(list->type2);
4182
free(list);
4183
list = next;
4184
}
4185
return list;
4186
}
4187
4188
void
4189
reader_leaks(void)
4190
{
4191
lex_param = free_declarations(lex_param);
4192
parse_param = free_declarations(parse_param);
4193
4194
DO_FREE(line);
4195
DO_FREE(rrhs);
4196
DO_FREE(rlhs);
4197
DO_FREE(rprec);
4198
DO_FREE(ritem);
4199
DO_FREE(rassoc);
4200
DO_FREE(cache);
4201
DO_FREE(name_pool);
4202
DO_FREE(symbol_name);
4203
DO_FREE(symbol_prec);
4204
DO_FREE(symbol_assoc);
4205
DO_FREE(symbol_value);
4206
#if defined(YYBTYACC)
4207
DO_FREE(symbol_pval);
4208
DO_FREE(symbol_destructor);
4209
DO_FREE(symbol_type_tag);
4210
#endif
4211
}
4212
#endif
4213
4214