GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
Line | Branch | Exec | Source |
1 |
/* $OpenBSD: reader.c,v 1.33 2016/03/22 18:24:34 mmcc Exp $ */ |
||
2 |
/* $NetBSD: reader.c,v 1.5 1996/03/19 03:21:43 jtc Exp $ */ |
||
3 |
|||
4 |
/* |
||
5 |
* Copyright (c) 1989 The Regents of the University of California. |
||
6 |
* All rights reserved. |
||
7 |
* |
||
8 |
* This code is derived from software contributed to Berkeley by |
||
9 |
* Robert Paul Corbett. |
||
10 |
* |
||
11 |
* Redistribution and use in source and binary forms, with or without |
||
12 |
* modification, are permitted provided that the following conditions |
||
13 |
* are met: |
||
14 |
* 1. Redistributions of source code must retain the above copyright |
||
15 |
* notice, this list of conditions and the following disclaimer. |
||
16 |
* 2. Redistributions in binary form must reproduce the above copyright |
||
17 |
* notice, this list of conditions and the following disclaimer in the |
||
18 |
* documentation and/or other materials provided with the distribution. |
||
19 |
* 3. Neither the name of the University nor the names of its contributors |
||
20 |
* may be used to endorse or promote products derived from this software |
||
21 |
* without specific prior written permission. |
||
22 |
* |
||
23 |
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
||
24 |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||
25 |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||
26 |
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
||
27 |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
||
28 |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
||
29 |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
||
30 |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
||
31 |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
||
32 |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
||
33 |
* SUCH DAMAGE. |
||
34 |
*/ |
||
35 |
|||
36 |
#include <limits.h> |
||
37 |
#include "defs.h" |
||
38 |
|||
39 |
/* The line size must be a positive integer. One hundred was chosen */ |
||
40 |
/* because few lines in Yacc input grammars exceed 100 characters. */ |
||
41 |
/* Note that if a line exceeds LINESIZE characters, the line buffer */ |
||
42 |
/* will be expanded to accommodate it. */ |
||
43 |
|||
44 |
#define LINESIZE 100 |
||
45 |
|||
46 |
char *cache; |
||
47 |
int cinc, cache_size; |
||
48 |
|||
49 |
int ntags, tagmax; |
||
50 |
char **tag_table; |
||
51 |
|||
52 |
char saw_eof, unionized; |
||
53 |
char *cptr, *line; |
||
54 |
int linesize; |
||
55 |
|||
56 |
bucket *goal; |
||
57 |
int prec; |
||
58 |
int gensym; |
||
59 |
char last_was_action; |
||
60 |
|||
61 |
int maxitems; |
||
62 |
bucket **pitem; |
||
63 |
|||
64 |
int maxrules; |
||
65 |
bucket **plhs; |
||
66 |
|||
67 |
int name_pool_size; |
||
68 |
char *name_pool; |
||
69 |
|||
70 |
void cachec(int); |
||
71 |
void get_line(void); |
||
72 |
char *dup_line(void); |
||
73 |
void skip_comment(void); |
||
74 |
int nextc(void); |
||
75 |
int keyword(void); |
||
76 |
void copy_ident(void); |
||
77 |
void copy_text(void); |
||
78 |
void copy_union(void); |
||
79 |
bucket *get_literal(void); |
||
80 |
int is_reserved(char *); |
||
81 |
bucket *get_name(void); |
||
82 |
int get_number(void); |
||
83 |
char *get_tag(void); |
||
84 |
void declare_tokens(int); |
||
85 |
void declare_types(void); |
||
86 |
void declare_start(void); |
||
87 |
void handle_expect(void); |
||
88 |
void read_declarations(void); |
||
89 |
void initialize_grammar(void); |
||
90 |
void expand_items(void); |
||
91 |
void expand_rules(void); |
||
92 |
void advance_to_start(void); |
||
93 |
void start_rule(bucket *, int); |
||
94 |
void end_rule(void); |
||
95 |
void insert_empty_rule(void); |
||
96 |
void add_symbol(void); |
||
97 |
void copy_action(void); |
||
98 |
int mark_symbol(void); |
||
99 |
void read_grammar(void); |
||
100 |
void free_tags(void); |
||
101 |
void pack_names(void); |
||
102 |
void check_symbols(void); |
||
103 |
void pack_symbols(void); |
||
104 |
void pack_grammar(void); |
||
105 |
void print_grammar(void); |
||
106 |
|||
107 |
char line_format[] = "#line %d \"%s\"\n"; |
||
108 |
|||
109 |
void |
||
110 |
cachec(int c) |
||
111 |
58992 |
{ |
|
112 |
✗✓ | 58992 |
assert(cinc >= 0); |
113 |
✗✓ | 58992 |
if (cinc >= cache_size) { |
114 |
cache_size += 256; |
||
115 |
cache = realloc(cache, cache_size); |
||
116 |
if (cache == NULL) |
||
117 |
no_space(); |
||
118 |
} |
||
119 |
58992 |
cache[cinc] = c; |
|
120 |
58992 |
++cinc; |
|
121 |
58992 |
} |
|
122 |
|||
123 |
|||
124 |
void |
||
125 |
get_line(void) |
||
126 |
15945 |
{ |
|
127 |
15945 |
FILE *f = input_file; |
|
128 |
int c, i; |
||
129 |
|||
130 |
✓✗✓✗ ✓✓✗✓ |
15945 |
if (saw_eof || (c = getc(f)) == EOF) { |
131 |
if (line) { |
||
132 |
free(line); |
||
133 |
line = 0; |
||
134 |
} |
||
135 |
cptr = 0; |
||
136 |
saw_eof = 1; |
||
137 |
return; |
||
138 |
} |
||
139 |
✓✓✓✓ |
15945 |
if (line == NULL || linesize != (LINESIZE + 1)) { |
140 |
24 |
free(line); |
|
141 |
24 |
linesize = LINESIZE + 1; |
|
142 |
24 |
line = malloc(linesize); |
|
143 |
✗✓ | 24 |
if (line == NULL) |
144 |
no_space(); |
||
145 |
} |
||
146 |
15945 |
i = 0; |
|
147 |
15945 |
++lineno; |
|
148 |
for (;;) { |
||
149 |
382140 |
line[i] = c; |
|
150 |
✓✓ | 382140 |
if (c == '\n') { |
151 |
15945 |
cptr = line; |
|
152 |
15945 |
return; |
|
153 |
} |
||
154 |
✓✓ | 366195 |
if (++i >= linesize) { |
155 |
3 |
linesize += LINESIZE; |
|
156 |
3 |
line = realloc(line, linesize); |
|
157 |
✗✓ | 3 |
if (line == NULL) |
158 |
no_space(); |
||
159 |
} |
||
160 |
✓✗✓✓ |
366195 |
c = getc(f); |
161 |
✓✗ | 366195 |
if (c == EOF) { |
162 |
line[i] = '\n'; |
||
163 |
saw_eof = 1; |
||
164 |
cptr = line; |
||
165 |
return; |
||
166 |
} |
||
167 |
} |
||
168 |
} |
||
169 |
|||
170 |
|||
171 |
char * |
||
172 |
dup_line(void) |
||
173 |
3873 |
{ |
|
174 |
char *p, *s, *t; |
||
175 |
|||
176 |
✗✓ | 3873 |
if (line == NULL) |
177 |
return (0); |
||
178 |
3873 |
s = line; |
|
179 |
✓✓ | 136638 |
while (*s != '\n') |
180 |
128892 |
++s; |
|
181 |
3873 |
p = malloc(s - line + 1); |
|
182 |
✗✓ | 3873 |
if (p == NULL) |
183 |
no_space(); |
||
184 |
|||
185 |
3873 |
s = line; |
|
186 |
3873 |
t = p; |
|
187 |
✓✓ | 132765 |
while ((*t++ = *s++) != '\n') |
188 |
continue; |
||
189 |
3873 |
return (p); |
|
190 |
} |
||
191 |
|||
192 |
|||
193 |
void |
||
194 |
skip_comment(void) |
||
195 |
268 |
{ |
|
196 |
char *s; |
||
197 |
268 |
int st_lineno = lineno; |
|
198 |
268 |
char *st_line = dup_line(); |
|
199 |
268 |
char *st_cptr = st_line + (cptr - line); |
|
200 |
|||
201 |
268 |
s = cptr + 2; |
|
202 |
for (;;) { |
||
203 |
✓✓✓✓ |
23763 |
if (*s == '*' && s[1] == '/') { |
204 |
268 |
cptr = s + 2; |
|
205 |
268 |
free(st_line); |
|
206 |
return; |
||
207 |
} |
||
208 |
✓✓ | 23495 |
if (*s == '\n') { |
209 |
377 |
get_line(); |
|
210 |
✗✓ | 377 |
if (line == NULL) |
211 |
unterminated_comment(st_lineno, st_line, st_cptr); |
||
212 |
377 |
s = cptr; |
|
213 |
} else |
||
214 |
23118 |
++s; |
|
215 |
} |
||
216 |
} |
||
217 |
|||
218 |
|||
219 |
int |
||
220 |
nextc(void) |
||
221 |
16349 |
{ |
|
222 |
char *s; |
||
223 |
|||
224 |
✓✓ | 16349 |
if (line == NULL) { |
225 |
21 |
get_line(); |
|
226 |
✗✓ | 21 |
if (line == NULL) |
227 |
return (EOF); |
||
228 |
} |
||
229 |
16349 |
s = cptr; |
|
230 |
for (;;) { |
||
231 |
✓✓✗✓ ✓ |
37188 |
switch (*s) { |
232 |
case '\n': |
||
233 |
4591 |
get_line(); |
|
234 |
✗✓ | 4591 |
if (line == NULL) |
235 |
return (EOF); |
||
236 |
4591 |
s = cptr; |
|
237 |
4591 |
break; |
|
238 |
|||
239 |
case ' ': |
||
240 |
case '\t': |
||
241 |
case '\f': |
||
242 |
case '\r': |
||
243 |
case '\v': |
||
244 |
case ',': |
||
245 |
case ';': |
||
246 |
15980 |
++s; |
|
247 |
15980 |
break; |
|
248 |
|||
249 |
case '\\': |
||
250 |
cptr = s; |
||
251 |
return ('%'); |
||
252 |
|||
253 |
case '/': |
||
254 |
✓✗ | 268 |
if (s[1] == '*') { |
255 |
268 |
cptr = s; |
|
256 |
268 |
skip_comment(); |
|
257 |
268 |
s = cptr; |
|
258 |
268 |
break; |
|
259 |
} else if (s[1] == '/') { |
||
260 |
get_line(); |
||
261 |
if (line == NULL) |
||
262 |
return (EOF); |
||
263 |
s = cptr; |
||
264 |
break; |
||
265 |
} |
||
266 |
/* fall through */ |
||
267 |
|||
268 |
default: |
||
269 |
16349 |
cptr = s; |
|
270 |
16349 |
return ((unsigned char) *s); |
|
271 |
} |
||
272 |
} |
||
273 |
} |
||
274 |
|||
275 |
|||
276 |
int |
||
277 |
keyword(void) |
||
278 |
453 |
{ |
|
279 |
int c; |
||
280 |
453 |
char *t_cptr = cptr; |
|
281 |
|||
282 |
453 |
c = (unsigned char) *++cptr; |
|
283 |
✓✓ | 453 |
if (isalpha(c)) { |
284 |
411 |
cinc = 0; |
|
285 |
for (;;) { |
||
286 |
✓✓ | 2317 |
if (isalpha(c)) { |
287 |
✗✓ | 1906 |
if (isupper(c)) |
288 |
c = tolower(c); |
||
289 |
1906 |
cachec(c); |
|
290 |
✓✗✗✓ |
411 |
} else if (isdigit(c) || c == '_' || c == '.' || c == '$') |
291 |
cachec(c); |
||
292 |
else |
||
293 |
break; |
||
294 |
1906 |
c = (unsigned char) *++cptr; |
|
295 |
1906 |
} |
|
296 |
411 |
cachec(NUL); |
|
297 |
|||
298 |
✓✓✗✓ |
411 |
if (strcmp(cache, "token") == 0 || strcmp(cache, "term") == 0) |
299 |
257 |
return (TOKEN); |
|
300 |
✓✓ | 154 |
if (strcmp(cache, "type") == 0) |
301 |
145 |
return (TYPE); |
|
302 |
✓✓ | 9 |
if (strcmp(cache, "left") == 0) |
303 |
4 |
return (LEFT); |
|
304 |
✗✓ | 5 |
if (strcmp(cache, "right") == 0) |
305 |
return (RIGHT); |
||
306 |
✓✗✗✓ |
5 |
if (strcmp(cache, "nonassoc") == 0 || strcmp(cache, "binary") == 0) |
307 |
return (NONASSOC); |
||
308 |
✓✓ | 5 |
if (strcmp(cache, "start") == 0) |
309 |
1 |
return (START); |
|
310 |
✓✗ | 4 |
if (strcmp(cache, "union") == 0) |
311 |
4 |
return (UNION); |
|
312 |
if (strcmp(cache, "ident") == 0) |
||
313 |
return (IDENT); |
||
314 |
if (strcmp(cache, "expect") == 0) |
||
315 |
return (EXPECT); |
||
316 |
} else { |
||
317 |
42 |
++cptr; |
|
318 |
✓✓ | 42 |
if (c == '{') |
319 |
21 |
return (TEXT); |
|
320 |
✓✗ | 21 |
if (c == '%' || c == '\\') |
321 |
21 |
return (MARK); |
|
322 |
if (c == '<') |
||
323 |
return (LEFT); |
||
324 |
if (c == '>') |
||
325 |
return (RIGHT); |
||
326 |
if (c == '0') |
||
327 |
return (TOKEN); |
||
328 |
if (c == '2') |
||
329 |
return (NONASSOC); |
||
330 |
} |
||
331 |
syntax_error(lineno, line, t_cptr); |
||
332 |
/* NOTREACHED */ |
||
333 |
return (0); |
||
334 |
} |
||
335 |
|||
336 |
|||
337 |
void |
||
338 |
copy_ident(void) |
||
339 |
{ |
||
340 |
int c; |
||
341 |
FILE *f = output_file; |
||
342 |
|||
343 |
c = nextc(); |
||
344 |
if (c == EOF) |
||
345 |
unexpected_EOF(); |
||
346 |
if (c != '"') |
||
347 |
syntax_error(lineno, line, cptr); |
||
348 |
++outline; |
||
349 |
fprintf(f, "#ident \""); |
||
350 |
for (;;) { |
||
351 |
c = (unsigned char) *++cptr; |
||
352 |
if (c == '\n') { |
||
353 |
fprintf(f, "\"\n"); |
||
354 |
return; |
||
355 |
} |
||
356 |
putc(c, f); |
||
357 |
if (c == '"') { |
||
358 |
putc('\n', f); |
||
359 |
++cptr; |
||
360 |
return; |
||
361 |
} |
||
362 |
} |
||
363 |
} |
||
364 |
|||
365 |
|||
366 |
void |
||
367 |
copy_text(void) |
||
368 |
21 |
{ |
|
369 |
int c; |
||
370 |
int quote; |
||
371 |
21 |
FILE *f = text_file; |
|
372 |
21 |
int need_newline = 0; |
|
373 |
21 |
int t_lineno = lineno; |
|
374 |
21 |
char *t_line = dup_line(); |
|
375 |
21 |
char *t_cptr = t_line + (cptr - line - 2); |
|
376 |
|||
377 |
✓✗ | 21 |
if (*cptr == '\n') { |
378 |
21 |
get_line(); |
|
379 |
✗✓ | 21 |
if (line == NULL) |
380 |
unterminated_text(t_lineno, t_line, t_cptr); |
||
381 |
} |
||
382 |
✓✗ | 21 |
if (!lflag) |
383 |
21 |
fprintf(f, line_format, lineno, input_file_name); |
|
384 |
|||
385 |
40569 |
loop: |
|
386 |
40569 |
c = (unsigned char) *cptr++; |
|
387 |
✓✓✓✓ ✓ |
40569 |
switch (c) { |
388 |
case '\n': |
||
389 |
1772 |
next_line: |
|
390 |
✓✗ | 1772 |
putc('\n', f); |
391 |
1772 |
need_newline = 0; |
|
392 |
1772 |
get_line(); |
|
393 |
✓✗ | 1772 |
if (line) |
394 |
1772 |
goto loop; |
|
395 |
unterminated_text(t_lineno, t_line, t_cptr); |
||
396 |
|||
397 |
case '\'': |
||
398 |
case '"': { |
||
399 |
69 |
int s_lineno = lineno; |
|
400 |
69 |
char *s_line = dup_line(); |
|
401 |
69 |
char *s_cptr = s_line + (cptr - line - 1); |
|
402 |
|||
403 |
69 |
quote = c; |
|
404 |
✓✗ | 69 |
putc(c, f); |
405 |
for (;;) { |
||
406 |
572 |
c = (unsigned char) *cptr++; |
|
407 |
✓✗ | 572 |
putc(c, f); |
408 |
✓✓ | 572 |
if (c == quote) { |
409 |
69 |
need_newline = 1; |
|
410 |
69 |
free(s_line); |
|
411 |
69 |
goto loop; |
|
412 |
} |
||
413 |
✗✓ | 503 |
if (c == '\n') |
414 |
unterminated_string(s_lineno, s_line, s_cptr); |
||
415 |
✓✗ | 503 |
if (c == '\\') { |
416 |
c = (unsigned char) *cptr++; |
||
417 |
putc(c, f); |
||
418 |
if (c == '\n') { |
||
419 |
get_line(); |
||
420 |
if (line == NULL) |
||
421 |
unterminated_string(s_lineno, s_line, s_cptr); |
||
422 |
} |
||
423 |
} |
||
424 |
} |
||
425 |
} |
||
426 |
|||
427 |
case '/': |
||
428 |
✓✗ | 146 |
putc(c, f); |
429 |
146 |
need_newline = 1; |
|
430 |
146 |
c = (unsigned char) *cptr; |
|
431 |
✗✓ | 146 |
if (c == '/') { |
432 |
putc('*', f); |
||
433 |
while ((c = (unsigned char) *++cptr) != '\n') { |
||
434 |
if (c == '*' && cptr[1] == '/') |
||
435 |
fprintf(f, "* "); |
||
436 |
else |
||
437 |
putc(c, f); |
||
438 |
} |
||
439 |
fprintf(f, "*/"); |
||
440 |
goto next_line; |
||
441 |
} |
||
442 |
✓✓ | 146 |
if (c == '*') { |
443 |
23 |
int c_lineno = lineno; |
|
444 |
23 |
char *c_line = dup_line(); |
|
445 |
23 |
char *c_cptr = c_line + (cptr - line - 1); |
|
446 |
|||
447 |
✓✗ | 23 |
putc('*', f); |
448 |
23 |
++cptr; |
|
449 |
for (;;) { |
||
450 |
3790 |
c = (unsigned char) *cptr++; |
|
451 |
✓✗ | 3790 |
putc(c, f); |
452 |
✓✓✓✓ |
3790 |
if (c == '*' && *cptr == '/') { |
453 |
✓✗ | 23 |
putc('/', f); |
454 |
23 |
++cptr; |
|
455 |
23 |
free(c_line); |
|
456 |
23 |
goto loop; |
|
457 |
} |
||
458 |
✓✓ | 3767 |
if (c == '\n') { |
459 |
67 |
get_line(); |
|
460 |
✓✗ | 67 |
if (line == NULL) |
461 |
unterminated_comment(c_lineno, c_line, c_cptr); |
||
462 |
} |
||
463 |
} |
||
464 |
} |
||
465 |
123 |
need_newline = 1; |
|
466 |
123 |
goto loop; |
|
467 |
|||
468 |
case '%': |
||
469 |
case '\\': |
||
470 |
✓✓ | 41 |
if (*cptr == '}') { |
471 |
✗✓ | 21 |
if (need_newline) |
472 |
putc('\n', f); |
||
473 |
21 |
++cptr; |
|
474 |
21 |
free(t_line); |
|
475 |
return; |
||
476 |
} |
||
477 |
/* fall through */ |
||
478 |
|||
479 |
default: |
||
480 |
✓✗ | 38561 |
putc(c, f); |
481 |
38561 |
need_newline = 1; |
|
482 |
38561 |
goto loop; |
|
483 |
} |
||
484 |
} |
||
485 |
|||
486 |
|||
487 |
void |
||
488 |
copy_union(void) |
||
489 |
4 |
{ |
|
490 |
int c, quote, depth; |
||
491 |
4 |
int u_lineno = lineno; |
|
492 |
4 |
char *u_line = dup_line(); |
|
493 |
4 |
char *u_cptr = u_line + (cptr - line - 6); |
|
494 |
|||
495 |
✗✓ | 4 |
if (unionized) |
496 |
over_unionized(cptr - 6); |
||
497 |
4 |
unionized = 1; |
|
498 |
|||
499 |
✓✗ | 4 |
if (!lflag) |
500 |
4 |
fprintf(text_file, line_format, lineno, input_file_name); |
|
501 |
|||
502 |
4 |
fprintf(text_file, "#ifndef YYSTYPE_DEFINED\n"); |
|
503 |
4 |
fprintf(text_file, "#define YYSTYPE_DEFINED\n"); |
|
504 |
4 |
fprintf(text_file, "typedef union"); |
|
505 |
✓✗ | 4 |
if (dflag) { |
506 |
4 |
fprintf(union_file, "#ifndef YYSTYPE_DEFINED\n"); |
|
507 |
4 |
fprintf(union_file, "#define YYSTYPE_DEFINED\n"); |
|
508 |
4 |
fprintf(union_file, "typedef union"); |
|
509 |
} |
||
510 |
|||
511 |
4 |
depth = 0; |
|
512 |
356 |
loop: |
|
513 |
356 |
c = (unsigned char) *cptr++; |
|
514 |
✓✗ | 356 |
putc(c, text_file); |
515 |
✓✗ | 356 |
if (dflag) |
516 |
✓✗ | 356 |
putc(c, union_file); |
517 |
✓✓✓✓ ✗✗ |
356 |
switch (c) { |
518 |
case '\n': |
||
519 |
23 |
next_line: |
|
520 |
23 |
get_line(); |
|
521 |
✓✗ | 23 |
if (line == NULL) |
522 |
unterminated_union(u_lineno, u_line, u_cptr); |
||
523 |
goto loop; |
||
524 |
|||
525 |
case '{': |
||
526 |
4 |
++depth; |
|
527 |
4 |
goto loop; |
|
528 |
|||
529 |
case '}': |
||
530 |
✗✓ | 4 |
if (--depth == 0) { |
531 |
4 |
fprintf(text_file, " YYSTYPE;\n"); |
|
532 |
4 |
fprintf(text_file, "#endif /* YYSTYPE_DEFINED */\n"); |
|
533 |
4 |
free(u_line); |
|
534 |
return; |
||
535 |
} |
||
536 |
goto loop; |
||
537 |
|||
538 |
case '\'': |
||
539 |
case '"': { |
||
540 |
int s_lineno = lineno; |
||
541 |
char *s_line = dup_line(); |
||
542 |
char *s_cptr = s_line + (cptr - line - 1); |
||
543 |
|||
544 |
quote = c; |
||
545 |
for (;;) { |
||
546 |
c = (unsigned char) *cptr++; |
||
547 |
putc(c, text_file); |
||
548 |
if (dflag) |
||
549 |
putc(c, union_file); |
||
550 |
if (c == quote) { |
||
551 |
free(s_line); |
||
552 |
goto loop; |
||
553 |
} |
||
554 |
if (c == '\n') |
||
555 |
unterminated_string(s_lineno, s_line, s_cptr); |
||
556 |
if (c == '\\') { |
||
557 |
c = (unsigned char) *cptr++; |
||
558 |
putc(c, text_file); |
||
559 |
if (dflag) |
||
560 |
putc(c, union_file); |
||
561 |
if (c == '\n') { |
||
562 |
get_line(); |
||
563 |
if (line == NULL) |
||
564 |
unterminated_string(s_lineno, |
||
565 |
s_line, s_cptr); |
||
566 |
} |
||
567 |
} |
||
568 |
} |
||
569 |
} |
||
570 |
|||
571 |
case '/': |
||
572 |
c = (unsigned char) *cptr; |
||
573 |
if (c == '/') { |
||
574 |
putc('*', text_file); |
||
575 |
if (dflag) |
||
576 |
putc('*', union_file); |
||
577 |
while ((c = (unsigned char) *++cptr) != '\n') { |
||
578 |
if (c == '*' && cptr[1] == '/') { |
||
579 |
fprintf(text_file, "* "); |
||
580 |
if (dflag) |
||
581 |
fprintf(union_file, "* "); |
||
582 |
} else { |
||
583 |
putc(c, text_file); |
||
584 |
if (dflag) |
||
585 |
putc(c, union_file); |
||
586 |
} |
||
587 |
} |
||
588 |
fprintf(text_file, "*/\n"); |
||
589 |
if (dflag) |
||
590 |
fprintf(union_file, "*/\n"); |
||
591 |
goto next_line; |
||
592 |
} |
||
593 |
if (c == '*') { |
||
594 |
int c_lineno = lineno; |
||
595 |
char *c_line = dup_line(); |
||
596 |
char *c_cptr = c_line + (cptr - line - 1); |
||
597 |
|||
598 |
putc('*', text_file); |
||
599 |
if (dflag) |
||
600 |
putc('*', union_file); |
||
601 |
++cptr; |
||
602 |
for (;;) { |
||
603 |
c = (unsigned char) *cptr++; |
||
604 |
putc(c, text_file); |
||
605 |
if (dflag) |
||
606 |
putc(c, union_file); |
||
607 |
if (c == '*' && *cptr == '/') { |
||
608 |
putc('/', text_file); |
||
609 |
if (dflag) |
||
610 |
putc('/', union_file); |
||
611 |
++cptr; |
||
612 |
free(c_line); |
||
613 |
goto loop; |
||
614 |
} |
||
615 |
if (c == '\n') { |
||
616 |
get_line(); |
||
617 |
if (line == NULL) |
||
618 |
unterminated_comment(c_lineno, |
||
619 |
c_line, c_cptr); |
||
620 |
} |
||
621 |
} |
||
622 |
} |
||
623 |
goto loop; |
||
624 |
|||
625 |
default: |
||
626 |
goto loop; |
||
627 |
} |
||
628 |
} |
||
629 |
|||
630 |
|||
631 |
bucket * |
||
632 |
get_literal(void) |
||
633 |
434 |
{ |
|
634 |
int c, quote, i, n; |
||
635 |
char *s; |
||
636 |
bucket *bp; |
||
637 |
434 |
int s_lineno = lineno; |
|
638 |
434 |
char *s_line = dup_line(); |
|
639 |
434 |
char *s_cptr = s_line + (cptr - line); |
|
640 |
|||
641 |
434 |
quote = (unsigned char) *cptr++; |
|
642 |
434 |
cinc = 0; |
|
643 |
for (;;) { |
||
644 |
869 |
c = (unsigned char) *cptr++; |
|
645 |
✓✓ | 869 |
if (c == quote) |
646 |
434 |
break; |
|
647 |
✗✓ | 435 |
if (c == '\n') |
648 |
unterminated_string(s_lineno, s_line, s_cptr); |
||
649 |
✓✓ | 435 |
if (c == '\\') { |
650 |
162 |
char *c_cptr = cptr - 1; |
|
651 |
unsigned long ulval; |
||
652 |
|||
653 |
162 |
c = (unsigned char) *cptr++; |
|
654 |
✗✗✗✗ ✗✗✓✗ ✗✗✗ |
162 |
switch (c) { |
655 |
case '\n': |
||
656 |
get_line(); |
||
657 |
if (line == NULL) |
||
658 |
unterminated_string(s_lineno, s_line, |
||
659 |
s_cptr); |
||
660 |
continue; |
||
661 |
|||
662 |
case '0': |
||
663 |
case '1': |
||
664 |
case '2': |
||
665 |
case '3': |
||
666 |
case '4': |
||
667 |
case '5': |
||
668 |
case '6': |
||
669 |
case '7': |
||
670 |
ulval = strtoul(cptr - 1, &s, 8); |
||
671 |
if (s == cptr - 1 || ulval > MAXCHAR) |
||
672 |
illegal_character(c_cptr); |
||
673 |
c = (int) ulval; |
||
674 |
cptr = s; |
||
675 |
break; |
||
676 |
|||
677 |
case 'x': |
||
678 |
ulval = strtoul(cptr, &s, 16); |
||
679 |
if (s == cptr || ulval > MAXCHAR) |
||
680 |
illegal_character(c_cptr); |
||
681 |
c = (int) ulval; |
||
682 |
cptr = s; |
||
683 |
break; |
||
684 |
|||
685 |
case 'a': |
||
686 |
c = 7; |
||
687 |
break; |
||
688 |
case 'b': |
||
689 |
c = '\b'; |
||
690 |
break; |
||
691 |
case 'f': |
||
692 |
c = '\f'; |
||
693 |
break; |
||
694 |
case 'n': |
||
695 |
162 |
c = '\n'; |
|
696 |
162 |
break; |
|
697 |
case 'r': |
||
698 |
c = '\r'; |
||
699 |
break; |
||
700 |
case 't': |
||
701 |
c = '\t'; |
||
702 |
break; |
||
703 |
case 'v': |
||
704 |
c = '\v'; |
||
705 |
break; |
||
706 |
} |
||
707 |
} |
||
708 |
435 |
cachec(c); |
|
709 |
} |
||
710 |
434 |
free(s_line); |
|
711 |
|||
712 |
434 |
n = cinc; |
|
713 |
434 |
s = malloc(n); |
|
714 |
✗✓ | 434 |
if (s == NULL) |
715 |
no_space(); |
||
716 |
|||
717 |
434 |
memcpy(s, cache, n); |
|
718 |
|||
719 |
434 |
cinc = 0; |
|
720 |
✓✓ | 434 |
if (n == 1) |
721 |
433 |
cachec('\''); |
|
722 |
else |
||
723 |
1 |
cachec('"'); |
|
724 |
|||
725 |
✓✓ | 869 |
for (i = 0; i < n; ++i) { |
726 |
435 |
c = ((unsigned char *) s)[i]; |
|
727 |
✓✗✗✓ |
435 |
if (c == '\\' || c == cache[0]) { |
728 |
cachec('\\'); |
||
729 |
cachec(c); |
||
730 |
✓✓ | 435 |
} else if (isprint(c)) |
731 |
273 |
cachec(c); |
|
732 |
else { |
||
733 |
162 |
cachec('\\'); |
|
734 |
✗✗✗✓ ✗✗✗✗ |
162 |
switch (c) { |
735 |
case 7: |
||
736 |
cachec('a'); |
||
737 |
break; |
||
738 |
case '\b': |
||
739 |
cachec('b'); |
||
740 |
break; |
||
741 |
case '\f': |
||
742 |
cachec('f'); |
||
743 |
break; |
||
744 |
case '\n': |
||
745 |
162 |
cachec('n'); |
|
746 |
162 |
break; |
|
747 |
case '\r': |
||
748 |
cachec('r'); |
||
749 |
break; |
||
750 |
case '\t': |
||
751 |
cachec('t'); |
||
752 |
break; |
||
753 |
case '\v': |
||
754 |
cachec('v'); |
||
755 |
break; |
||
756 |
default: |
||
757 |
cachec(((c >> 6) & 7) + '0'); |
||
758 |
cachec(((c >> 3) & 7) + '0'); |
||
759 |
cachec((c & 7) + '0'); |
||
760 |
break; |
||
761 |
} |
||
762 |
} |
||
763 |
} |
||
764 |
|||
765 |
✓✓ | 434 |
if (n == 1) |
766 |
433 |
cachec('\''); |
|
767 |
else |
||
768 |
1 |
cachec('"'); |
|
769 |
|||
770 |
434 |
cachec(NUL); |
|
771 |
434 |
bp = lookup(cache); |
|
772 |
434 |
bp->class = TERM; |
|
773 |
✓✓✓✓ |
434 |
if (n == 1 && bp->value == UNDEFINED) |
774 |
110 |
bp->value = *(unsigned char *) s; |
|
775 |
434 |
free(s); |
|
776 |
|||
777 |
434 |
return (bp); |
|
778 |
} |
||
779 |
|||
780 |
|||
781 |
int |
||
782 |
is_reserved(char *name) |
||
783 |
6202 |
{ |
|
784 |
char *s; |
||
785 |
|||
786 |
✓✗✓✗ ✗✓ |
6202 |
if (strcmp(name, ".") == 0 || |
787 |
strcmp(name, "$accept") == 0 || |
||
788 |
strcmp(name, "$end") == 0) |
||
789 |
return (1); |
||
790 |
|||
791 |
✗✓✗✗ ✗✗ |
6202 |
if (name[0] == '$' && name[1] == '$' && isdigit((unsigned char) name[2])) { |
792 |
s = name + 3; |
||
793 |
while (isdigit((unsigned char) *s)) |
||
794 |
++s; |
||
795 |
if (*s == NUL) |
||
796 |
return (1); |
||
797 |
} |
||
798 |
6202 |
return (0); |
|
799 |
} |
||
800 |
|||
801 |
|||
802 |
bucket * |
||
803 |
get_name(void) |
||
804 |
6202 |
{ |
|
805 |
int c; |
||
806 |
|||
807 |
6202 |
cinc = 0; |
|
808 |
✓✓✗✓ |
105482 |
for (c = (unsigned char) *cptr; IS_IDENT(c); c = (unsigned char) *++cptr) |
809 |
46539 |
cachec(c); |
|
810 |
6202 |
cachec(NUL); |
|
811 |
|||
812 |
✗✓ | 6202 |
if (is_reserved(cache)) |
813 |
used_reserved(cache); |
||
814 |
|||
815 |
6202 |
return (lookup(cache)); |
|
816 |
} |
||
817 |
|||
818 |
|||
819 |
int |
||
820 |
get_number(void) |
||
821 |
3254 |
{ |
|
822 |
unsigned long ul; |
||
823 |
char *p; |
||
824 |
|||
825 |
3254 |
ul = strtoul(cptr, &p, 10); |
|
826 |
✗✓ | 3254 |
if (ul > INT_MAX) |
827 |
syntax_error(lineno, line, cptr); |
||
828 |
3254 |
cptr = p; |
|
829 |
3254 |
return (ul); |
|
830 |
} |
||
831 |
|||
832 |
|||
833 |
char * |
||
834 |
get_tag(void) |
||
835 |
200 |
{ |
|
836 |
int c, i; |
||
837 |
char *s; |
||
838 |
200 |
int t_lineno = lineno; |
|
839 |
200 |
char *t_line = dup_line(); |
|
840 |
200 |
char *t_cptr = t_line + (cptr - line); |
|
841 |
|||
842 |
200 |
++cptr; |
|
843 |
200 |
c = nextc(); |
|
844 |
✗✓ | 200 |
if (c == EOF) |
845 |
unexpected_EOF(); |
||
846 |
✗✓✗✗ |
200 |
if (!isalpha(c) && c != '_' && c != '$') |
847 |
illegal_tag(t_lineno, t_line, t_cptr); |
||
848 |
|||
849 |
200 |
cinc = 0; |
|
850 |
do { |
||
851 |
1400 |
cachec(c); |
|
852 |
1400 |
c = (unsigned char) *++cptr; |
|
853 |
✓✓✓✓ |
1400 |
} while (IS_IDENT(c)); |
854 |
200 |
cachec(NUL); |
|
855 |
|||
856 |
200 |
c = nextc(); |
|
857 |
✗✓ | 200 |
if (c == EOF) |
858 |
unexpected_EOF(); |
||
859 |
✗✓ | 200 |
if (c != '>') |
860 |
illegal_tag(t_lineno, t_line, t_cptr); |
||
861 |
200 |
free(t_line); |
|
862 |
200 |
++cptr; |
|
863 |
|||
864 |
✓✓ | 580 |
for (i = 0; i < ntags; ++i) { |
865 |
✓✓ | 478 |
if (strcmp(cache, tag_table[i]) == 0) |
866 |
98 |
return (tag_table[i]); |
|
867 |
} |
||
868 |
|||
869 |
✓✓ | 102 |
if (ntags >= tagmax) { |
870 |
21 |
tagmax += 16; |
|
871 |
21 |
tag_table = reallocarray(tag_table, tagmax, sizeof(char *)); |
|
872 |
✗✓ | 21 |
if (tag_table == NULL) |
873 |
no_space(); |
||
874 |
} |
||
875 |
102 |
s = malloc(cinc); |
|
876 |
✗✓ | 102 |
if (s == NULL) |
877 |
no_space(); |
||
878 |
102 |
strlcpy(s, cache, cinc); |
|
879 |
102 |
tag_table[ntags] = s; |
|
880 |
102 |
++ntags; |
|
881 |
102 |
return (s); |
|
882 |
} |
||
883 |
|||
884 |
|||
885 |
void |
||
886 |
declare_tokens(int assoc) |
||
887 |
261 |
{ |
|
888 |
int c; |
||
889 |
bucket *bp; |
||
890 |
int value; |
||
891 |
261 |
char *tag = 0; |
|
892 |
|||
893 |
✓✓ | 261 |
if (assoc != TOKEN) |
894 |
4 |
++prec; |
|
895 |
|||
896 |
261 |
c = nextc(); |
|
897 |
✗✓ | 261 |
if (c == EOF) |
898 |
unexpected_EOF(); |
||
899 |
✓✓ | 261 |
if (c == '<') { |
900 |
55 |
tag = get_tag(); |
|
901 |
55 |
c = nextc(); |
|
902 |
✗✓ | 55 |
if (c == EOF) |
903 |
unexpected_EOF(); |
||
904 |
} |
||
905 |
for (;;) { |
||
906 |
✓✓✗✓ |
2311 |
if (isalpha(c) || c == '_' || c == '.' || c == '$') |
907 |
1024 |
bp = get_name(); |
|
908 |
✓✓ | 263 |
else if (c == '\'' || c == '"') |
909 |
2 |
bp = get_literal(); |
|
910 |
else |
||
911 |
261 |
return; |
|
912 |
|||
913 |
✗✓ | 1026 |
if (bp == goal) |
914 |
tokenized_start(bp->name); |
||
915 |
1026 |
bp->class = TERM; |
|
916 |
|||
917 |
✓✓ | 1026 |
if (tag) { |
918 |
✗✓✗✗ |
125 |
if (bp->tag && tag != bp->tag) |
919 |
retyped_warning(bp->name); |
||
920 |
125 |
bp->tag = tag; |
|
921 |
} |
||
922 |
✓✓ | 1026 |
if (assoc != TOKEN) { |
923 |
✗✓✗✗ |
5 |
if (bp->prec && prec != bp->prec) |
924 |
reprec_warning(bp->name); |
||
925 |
5 |
bp->assoc = assoc; |
|
926 |
5 |
bp->prec = prec; |
|
927 |
} |
||
928 |
1026 |
c = nextc(); |
|
929 |
✗✓ | 1026 |
if (c == EOF) |
930 |
unexpected_EOF(); |
||
931 |
✓✗ | 1026 |
if (isdigit(c)) { |
932 |
value = get_number(); |
||
933 |
if (bp->value != UNDEFINED && value != bp->value) |
||
934 |
revalued_warning(bp->name); |
||
935 |
bp->value = value; |
||
936 |
c = nextc(); |
||
937 |
if (c == EOF) |
||
938 |
unexpected_EOF(); |
||
939 |
} |
||
940 |
} |
||
941 |
} |
||
942 |
|||
943 |
|||
944 |
/* |
||
945 |
* %expect requires special handling as it really isn't part of the yacc |
||
946 |
* grammar only a flag for yacc proper. |
||
947 |
*/ |
||
948 |
void |
||
949 |
declare_expect(int assoc) |
||
950 |
{ |
||
951 |
int c; |
||
952 |
|||
953 |
if (assoc != EXPECT) |
||
954 |
++prec; |
||
955 |
|||
956 |
/* |
||
957 |
* Stay away from nextc - doesn't detect EOL and will read to EOF. |
||
958 |
*/ |
||
959 |
c = (unsigned char) *++cptr; |
||
960 |
if (c == EOF) |
||
961 |
unexpected_EOF(); |
||
962 |
|||
963 |
for (;;) { |
||
964 |
if (isdigit(c)) { |
||
965 |
SRexpect = get_number(); |
||
966 |
break; |
||
967 |
} |
||
968 |
/* |
||
969 |
* Looking for number before EOL. |
||
970 |
* Spaces, tabs, and numbers are ok. |
||
971 |
* Words, punc., etc. are syntax errors. |
||
972 |
*/ |
||
973 |
else if (c == '\n' || isalpha(c) || !isspace(c)) { |
||
974 |
syntax_error(lineno, line, cptr); |
||
975 |
} else { |
||
976 |
c = (unsigned char) *++cptr; |
||
977 |
if (c == EOF) |
||
978 |
unexpected_EOF(); |
||
979 |
} |
||
980 |
} |
||
981 |
} |
||
982 |
|||
983 |
|||
984 |
void |
||
985 |
declare_types(void) |
||
986 |
145 |
{ |
|
987 |
int c; |
||
988 |
bucket *bp; |
||
989 |
char *tag; |
||
990 |
|||
991 |
145 |
c = nextc(); |
|
992 |
✗✓ | 145 |
if (c == EOF) |
993 |
unexpected_EOF(); |
||
994 |
✗✓ | 145 |
if (c != '<') |
995 |
syntax_error(lineno, line, cptr); |
||
996 |
145 |
tag = get_tag(); |
|
997 |
|||
998 |
for (;;) { |
||
999 |
416 |
c = nextc(); |
|
1000 |
✓✓✗✓ |
687 |
if (isalpha(c) || c == '_' || c == '.' || c == '$') |
1001 |
271 |
bp = get_name(); |
|
1002 |
✗✓ | 145 |
else if (c == '\'' || c == '"') |
1003 |
bp = get_literal(); |
||
1004 |
else |
||
1005 |
145 |
return; |
|
1006 |
|||
1007 |
✗✓✗✗ |
271 |
if (bp->tag && tag != bp->tag) |
1008 |
retyped_warning(bp->name); |
||
1009 |
271 |
bp->tag = tag; |
|
1010 |
271 |
} |
|
1011 |
} |
||
1012 |
|||
1013 |
|||
1014 |
void |
||
1015 |
declare_start(void) |
||
1016 |
1 |
{ |
|
1017 |
int c; |
||
1018 |
bucket *bp; |
||
1019 |
|||
1020 |
1 |
c = nextc(); |
|
1021 |
✗✓ | 1 |
if (c == EOF) |
1022 |
unexpected_EOF(); |
||
1023 |
✗✓✗✗ |
1 |
if (!isalpha(c) && c != '_' && c != '.' && c != '$') |
1024 |
syntax_error(lineno, line, cptr); |
||
1025 |
1 |
bp = get_name(); |
|
1026 |
✗✓ | 1 |
if (bp->class == TERM) |
1027 |
terminal_start(bp->name); |
||
1028 |
✗✓✗✗ |
1 |
if (goal && goal != bp) |
1029 |
restarted_warning(); |
||
1030 |
1 |
goal = bp; |
|
1031 |
1 |
} |
|
1032 |
|||
1033 |
|||
1034 |
void |
||
1035 |
read_declarations(void) |
||
1036 |
21 |
{ |
|
1037 |
int c, k; |
||
1038 |
|||
1039 |
21 |
cache_size = 256; |
|
1040 |
21 |
cache = malloc(cache_size); |
|
1041 |
✗✓ | 21 |
if (cache == NULL) |
1042 |
no_space(); |
||
1043 |
|||
1044 |
for (;;) { |
||
1045 |
453 |
c = nextc(); |
|
1046 |
✗✓ | 453 |
if (c == EOF) |
1047 |
unexpected_EOF(); |
||
1048 |
✗✓ | 453 |
if (c != '%') |
1049 |
syntax_error(lineno, line, cptr); |
||
1050 |
✗✗✓✓ ✓✗✓✓ ✓ |
453 |
switch (k = keyword()) { |
1051 |
case MARK: |
||
1052 |
return; |
||
1053 |
|||
1054 |
case IDENT: |
||
1055 |
copy_ident(); |
||
1056 |
break; |
||
1057 |
|||
1058 |
case TEXT: |
||
1059 |
21 |
copy_text(); |
|
1060 |
21 |
break; |
|
1061 |
|||
1062 |
case UNION: |
||
1063 |
4 |
copy_union(); |
|
1064 |
4 |
break; |
|
1065 |
|||
1066 |
case TOKEN: |
||
1067 |
case LEFT: |
||
1068 |
case RIGHT: |
||
1069 |
case NONASSOC: |
||
1070 |
261 |
declare_tokens(k); |
|
1071 |
261 |
break; |
|
1072 |
|||
1073 |
case EXPECT: |
||
1074 |
declare_expect(k); |
||
1075 |
break; |
||
1076 |
|||
1077 |
case TYPE: |
||
1078 |
145 |
declare_types(); |
|
1079 |
145 |
break; |
|
1080 |
|||
1081 |
case START: |
||
1082 |
1 |
declare_start(); |
|
1083 |
break; |
||
1084 |
} |
||
1085 |
} |
||
1086 |
} |
||
1087 |
|||
1088 |
|||
1089 |
void |
||
1090 |
initialize_grammar(void) |
||
1091 |
21 |
{ |
|
1092 |
21 |
nitems = 4; |
|
1093 |
21 |
maxitems = 300; |
|
1094 |
21 |
pitem = calloc(maxitems, sizeof(bucket *)); |
|
1095 |
✗✓ | 21 |
if (pitem == NULL) |
1096 |
no_space(); |
||
1097 |
|||
1098 |
21 |
nrules = 3; |
|
1099 |
21 |
maxrules = 100; |
|
1100 |
21 |
plhs = reallocarray(NULL, maxrules, sizeof(bucket *)); |
|
1101 |
✗✓ | 21 |
if (plhs == NULL) |
1102 |
no_space(); |
||
1103 |
21 |
plhs[0] = 0; |
|
1104 |
21 |
plhs[1] = 0; |
|
1105 |
21 |
plhs[2] = 0; |
|
1106 |
21 |
rprec = reallocarray(NULL, maxrules, sizeof(short)); |
|
1107 |
✗✓ | 21 |
if (rprec == NULL) |
1108 |
no_space(); |
||
1109 |
21 |
rprec[0] = 0; |
|
1110 |
21 |
rprec[1] = 0; |
|
1111 |
21 |
rprec[2] = 0; |
|
1112 |
21 |
rassoc = reallocarray(NULL, maxrules, sizeof(char)); |
|
1113 |
✗✓ | 21 |
if (rassoc == NULL) |
1114 |
no_space(); |
||
1115 |
21 |
rassoc[0] = TOKEN; |
|
1116 |
21 |
rassoc[1] = TOKEN; |
|
1117 |
21 |
rassoc[2] = TOKEN; |
|
1118 |
21 |
} |
|
1119 |
|||
1120 |
|||
1121 |
void |
||
1122 |
expand_items(void) |
||
1123 |
14 |
{ |
|
1124 |
14 |
int olditems = maxitems; |
|
1125 |
|||
1126 |
14 |
maxitems += 300; |
|
1127 |
14 |
pitem = reallocarray(pitem, maxitems, sizeof(bucket *)); |
|
1128 |
✗✓ | 14 |
if (pitem == NULL) |
1129 |
no_space(); |
||
1130 |
14 |
memset(pitem + olditems, 0, (maxitems - olditems) * sizeof(bucket *)); |
|
1131 |
14 |
} |
|
1132 |
|||
1133 |
|||
1134 |
void |
||
1135 |
expand_rules(void) |
||
1136 |
13 |
{ |
|
1137 |
13 |
maxrules += 100; |
|
1138 |
13 |
plhs = reallocarray(plhs, maxrules, sizeof(bucket *)); |
|
1139 |
✗✓ | 13 |
if (plhs == NULL) |
1140 |
no_space(); |
||
1141 |
13 |
rprec = reallocarray(rprec, maxrules, sizeof(short)); |
|
1142 |
✗✓ | 13 |
if (rprec == NULL) |
1143 |
no_space(); |
||
1144 |
13 |
rassoc = reallocarray(rassoc, maxrules, sizeof(char)); |
|
1145 |
✗✓ | 13 |
if (rassoc == NULL) |
1146 |
no_space(); |
||
1147 |
13 |
} |
|
1148 |
|||
1149 |
|||
1150 |
void |
||
1151 |
advance_to_start(void) |
||
1152 |
21 |
{ |
|
1153 |
int c; |
||
1154 |
bucket *bp; |
||
1155 |
char *s_cptr; |
||
1156 |
int s_lineno; |
||
1157 |
|||
1158 |
for (;;) { |
||
1159 |
21 |
c = nextc(); |
|
1160 |
✗✓ | 21 |
if (c != '%') |
1161 |
21 |
break; |
|
1162 |
s_cptr = cptr; |
||
1163 |
switch (keyword()) { |
||
1164 |
case MARK: |
||
1165 |
no_grammar(); |
||
1166 |
|||
1167 |
case TEXT: |
||
1168 |
copy_text(); |
||
1169 |
break; |
||
1170 |
|||
1171 |
case START: |
||
1172 |
declare_start(); |
||
1173 |
break; |
||
1174 |
|||
1175 |
default: |
||
1176 |
syntax_error(lineno, line, s_cptr); |
||
1177 |
} |
||
1178 |
} |
||
1179 |
|||
1180 |
21 |
c = nextc(); |
|
1181 |
✗✓ | 21 |
if (!isalpha(c) && c != '_' && c != '.' && c != '_') |
1182 |
syntax_error(lineno, line, cptr); |
||
1183 |
21 |
bp = get_name(); |
|
1184 |
✓✓ | 21 |
if (goal == NULL) { |
1185 |
✗✓ | 20 |
if (bp->class == TERM) |
1186 |
terminal_start(bp->name); |
||
1187 |
20 |
goal = bp; |
|
1188 |
} |
||
1189 |
21 |
s_lineno = lineno; |
|
1190 |
21 |
c = nextc(); |
|
1191 |
✗✓ | 21 |
if (c == EOF) |
1192 |
unexpected_EOF(); |
||
1193 |
✗✓ | 21 |
if (c != ':') |
1194 |
syntax_error(lineno, line, cptr); |
||
1195 |
21 |
start_rule(bp, s_lineno); |
|
1196 |
21 |
++cptr; |
|
1197 |
21 |
} |
|
1198 |
|||
1199 |
|||
1200 |
void |
||
1201 |
start_rule(bucket * bp, int s_lineno) |
||
1202 |
2187 |
{ |
|
1203 |
✗✓ | 2187 |
if (bp->class == TERM) |
1204 |
terminal_lhs(s_lineno); |
||
1205 |
2187 |
bp->class = NONTERM; |
|
1206 |
✓✓ | 2187 |
if (nrules >= maxrules) |
1207 |
13 |
expand_rules(); |
|
1208 |
2187 |
plhs[nrules] = bp; |
|
1209 |
2187 |
rprec[nrules] = UNDEFINED; |
|
1210 |
2187 |
rassoc[nrules] = TOKEN; |
|
1211 |
2187 |
} |
|
1212 |
|||
1213 |
|||
1214 |
void |
||
1215 |
end_rule(void) |
||
1216 |
2187 |
{ |
|
1217 |
int i; |
||
1218 |
|||
1219 |
✓✓✓✓ |
2187 |
if (!last_was_action && plhs[nrules]->tag) { |
1220 |
✓✓ | 97 |
for (i = nitems - 1; pitem[i]; --i) |
1221 |
continue; |
||
1222 |
✓✗✓✗ ✗✓ |
97 |
if (i == maxitems - 1 || pitem[i + 1] == 0 || |
1223 |
pitem[i + 1]->tag != plhs[nrules]->tag) |
||
1224 |
default_action_warning(); |
||
1225 |
} |
||
1226 |
2187 |
last_was_action = 0; |
|
1227 |
✓✓ | 2187 |
if (nitems >= maxitems) |
1228 |
5 |
expand_items(); |
|
1229 |
2187 |
pitem[nitems] = 0; |
|
1230 |
2187 |
++nitems; |
|
1231 |
2187 |
++nrules; |
|
1232 |
2187 |
} |
|
1233 |
|||
1234 |
|||
1235 |
void |
||
1236 |
insert_empty_rule(void) |
||
1237 |
55 |
{ |
|
1238 |
bucket *bp, **bpp; |
||
1239 |
|||
1240 |
✗✓ | 55 |
assert(cache); |
1241 |
55 |
snprintf(cache, cache_size, "$$%d", ++gensym); |
|
1242 |
55 |
bp = make_bucket(cache); |
|
1243 |
55 |
last_symbol->next = bp; |
|
1244 |
55 |
last_symbol = bp; |
|
1245 |
55 |
bp->tag = plhs[nrules]->tag; |
|
1246 |
55 |
bp->class = NONTERM; |
|
1247 |
|||
1248 |
✗✓ | 55 |
if ((nitems += 2) > maxitems) |
1249 |
expand_items(); |
||
1250 |
55 |
bpp = pitem + nitems - 1; |
|
1251 |
55 |
*bpp-- = bp; |
|
1252 |
✓✓ | 236 |
while ((bpp[0] = bpp[-1])) |
1253 |
126 |
--bpp; |
|
1254 |
|||
1255 |
✗✓ | 55 |
if (++nrules >= maxrules) |
1256 |
expand_rules(); |
||
1257 |
55 |
plhs[nrules] = plhs[nrules - 1]; |
|
1258 |
55 |
plhs[nrules - 1] = bp; |
|
1259 |
55 |
rprec[nrules] = rprec[nrules - 1]; |
|
1260 |
55 |
rprec[nrules - 1] = 0; |
|
1261 |
55 |
rassoc[nrules] = rassoc[nrules - 1]; |
|
1262 |
55 |
rassoc[nrules - 1] = TOKEN; |
|
1263 |
55 |
} |
|
1264 |
|||
1265 |
|||
1266 |
void |
||
1267 |
add_symbol(void) |
||
1268 |
5316 |
{ |
|
1269 |
int c; |
||
1270 |
bucket *bp; |
||
1271 |
5316 |
int s_lineno = lineno; |
|
1272 |
|||
1273 |
5316 |
c = (unsigned char) *cptr; |
|
1274 |
✓✓ | 5316 |
if (c == '\'' || c == '"') |
1275 |
432 |
bp = get_literal(); |
|
1276 |
else |
||
1277 |
4884 |
bp = get_name(); |
|
1278 |
|||
1279 |
5316 |
c = nextc(); |
|
1280 |
✓✓ | 5316 |
if (c == ':') { |
1281 |
790 |
end_rule(); |
|
1282 |
790 |
start_rule(bp, s_lineno); |
|
1283 |
790 |
++cptr; |
|
1284 |
790 |
return; |
|
1285 |
} |
||
1286 |
✓✓ | 4526 |
if (last_was_action) |
1287 |
55 |
insert_empty_rule(); |
|
1288 |
4526 |
last_was_action = 0; |
|
1289 |
|||
1290 |
✓✓ | 4526 |
if (++nitems > maxitems) |
1291 |
9 |
expand_items(); |
|
1292 |
4526 |
pitem[nitems - 1] = bp; |
|
1293 |
} |
||
1294 |
|||
1295 |
|||
1296 |
void |
||
1297 |
copy_action(void) |
||
1298 |
1498 |
{ |
|
1299 |
int c, i, n, depth, quote; |
||
1300 |
char *tag; |
||
1301 |
1498 |
FILE *f = action_file; |
|
1302 |
1498 |
int a_lineno = lineno; |
|
1303 |
1498 |
char *a_line = dup_line(); |
|
1304 |
1498 |
char *a_cptr = a_line + (cptr - line); |
|
1305 |
|||
1306 |
✗✓ | 1498 |
if (last_was_action) |
1307 |
insert_empty_rule(); |
||
1308 |
1498 |
last_was_action = 1; |
|
1309 |
|||
1310 |
1498 |
fprintf(f, "case %d:\n", nrules - 2); |
|
1311 |
✓✗ | 1498 |
if (!lflag) |
1312 |
1498 |
fprintf(f, line_format, lineno, input_file_name); |
|
1313 |
✗✓ | 1498 |
if (*cptr == '=') |
1314 |
++cptr; |
||
1315 |
|||
1316 |
1498 |
n = 0; |
|
1317 |
✓✓ | 4811 |
for (i = nitems - 1; pitem[i]; --i) |
1318 |
3313 |
++n; |
|
1319 |
|||
1320 |
1498 |
depth = 0; |
|
1321 |
113029 |
loop: |
|
1322 |
113029 |
c = (unsigned char) *cptr; |
|
1323 |
✓✓ | 113029 |
if (c == '$') { |
1324 |
✗✓ | 4190 |
if (cptr[1] == '<') { |
1325 |
int d_lineno = lineno; |
||
1326 |
char *d_line = dup_line(); |
||
1327 |
char *d_cptr = d_line + (cptr - line); |
||
1328 |
|||
1329 |
++cptr; |
||
1330 |
tag = get_tag(); |
||
1331 |
c = (unsigned char) *cptr; |
||
1332 |
if (c == '$') { |
||
1333 |
fprintf(f, "yyval.%s", tag); |
||
1334 |
++cptr; |
||
1335 |
free(d_line); |
||
1336 |
goto loop; |
||
1337 |
} else if (isdigit(c)) { |
||
1338 |
i = get_number(); |
||
1339 |
if (i > n) |
||
1340 |
dollar_warning(d_lineno, i); |
||
1341 |
fprintf(f, "yyvsp[%d].%s", i - n, tag); |
||
1342 |
free(d_line); |
||
1343 |
goto loop; |
||
1344 |
} else if (c == '-' && isdigit((unsigned char) cptr[1])) { |
||
1345 |
++cptr; |
||
1346 |
i = -get_number() - n; |
||
1347 |
fprintf(f, "yyvsp[%d].%s", i, tag); |
||
1348 |
free(d_line); |
||
1349 |
goto loop; |
||
1350 |
} else |
||
1351 |
dollar_error(d_lineno, d_line, d_cptr); |
||
1352 |
✓✓ | 4190 |
} else if (cptr[1] == '$') { |
1353 |
✓✗ | 936 |
if (ntags) { |
1354 |
936 |
tag = plhs[nrules]->tag; |
|
1355 |
✗✓ | 936 |
if (tag == NULL) |
1356 |
untyped_lhs(); |
||
1357 |
936 |
fprintf(f, "yyval.%s", tag); |
|
1358 |
} else |
||
1359 |
fprintf(f, "yyval"); |
||
1360 |
936 |
cptr += 2; |
|
1361 |
936 |
goto loop; |
|
1362 |
✓✗ | 3254 |
} else if (isdigit((unsigned char) cptr[1])) { |
1363 |
3254 |
++cptr; |
|
1364 |
3254 |
i = get_number(); |
|
1365 |
✓✗ | 3254 |
if (ntags) { |
1366 |
✗✓ | 3254 |
if (i <= 0 || i > n) |
1367 |
unknown_rhs(i); |
||
1368 |
3254 |
tag = pitem[nitems + i - n - 1]->tag; |
|
1369 |
✗✓ | 3254 |
if (tag == NULL) |
1370 |
untyped_rhs(i, pitem[nitems + i - n - 1]->name); |
||
1371 |
3254 |
fprintf(f, "yyvsp[%d].%s", i - n, tag); |
|
1372 |
} else { |
||
1373 |
if (i > n) |
||
1374 |
dollar_warning(lineno, i); |
||
1375 |
fprintf(f, "yyvsp[%d]", i - n); |
||
1376 |
} |
||
1377 |
goto loop; |
||
1378 |
} else if (cptr[1] == '-') { |
||
1379 |
cptr += 2; |
||
1380 |
i = get_number(); |
||
1381 |
if (ntags) |
||
1382 |
unknown_rhs(-i); |
||
1383 |
fprintf(f, "yyvsp[%d]", -i - n); |
||
1384 |
goto loop; |
||
1385 |
} |
||
1386 |
} |
||
1387 |
✓✓✗✓ |
108839 |
if (isalpha(c) || c == '_' || c == '$') { |
1388 |
do { |
||
1389 |
✓✗ | 108503 |
putc(c, f); |
1390 |
108503 |
c = (unsigned char) *++cptr; |
|
1391 |
✓✓✓✗ |
108503 |
} while (isalnum(c) || c == '_' || c == '$'); |
1392 |
goto loop; |
||
1393 |
} |
||
1394 |
✓✗ | 92687 |
putc(c, f); |
1395 |
92687 |
++cptr; |
|
1396 |
✓✓✓✓ ✓✓✓ |
92687 |
switch (c) { |
1397 |
case '\n': |
||
1398 |
9051 |
next_line: |
|
1399 |
9051 |
get_line(); |
|
1400 |
✓✗ | 9051 |
if (line) |
1401 |
9051 |
goto loop; |
|
1402 |
unterminated_action(a_lineno, a_line, a_cptr); |
||
1403 |
|||
1404 |
case ';': |
||
1405 |
✓✗ | 5344 |
if (depth > 0) |
1406 |
5344 |
goto loop; |
|
1407 |
fprintf(f, "\nbreak;\n"); |
||
1408 |
free(a_line); |
||
1409 |
return; |
||
1410 |
|||
1411 |
case '{': |
||
1412 |
2303 |
++depth; |
|
1413 |
2303 |
goto loop; |
|
1414 |
|||
1415 |
case '}': |
||
1416 |
✓✓ | 2303 |
if (--depth > 0) |
1417 |
805 |
goto loop; |
|
1418 |
1498 |
fprintf(f, "\nbreak;\n"); |
|
1419 |
1498 |
free(a_line); |
|
1420 |
1498 |
return; |
|
1421 |
|||
1422 |
case '\'': |
||
1423 |
case '"': { |
||
1424 |
1195 |
int s_lineno = lineno; |
|
1425 |
1195 |
char *s_line = dup_line(); |
|
1426 |
1195 |
char *s_cptr = s_line + (cptr - line - 1); |
|
1427 |
|||
1428 |
1195 |
quote = c; |
|
1429 |
for (;;) { |
||
1430 |
23825 |
c = (unsigned char) *cptr++; |
|
1431 |
✓✗ | 23825 |
putc(c, f); |
1432 |
✓✓ | 23825 |
if (c == quote) { |
1433 |
1195 |
free(s_line); |
|
1434 |
1195 |
goto loop; |
|
1435 |
} |
||
1436 |
✗✓ | 22630 |
if (c == '\n') |
1437 |
unterminated_string(s_lineno, s_line, s_cptr); |
||
1438 |
✓✓ | 22630 |
if (c == '\\') { |
1439 |
245 |
c = (unsigned char) *cptr++; |
|
1440 |
✓✗ | 245 |
putc(c, f); |
1441 |
✓✗ | 245 |
if (c == '\n') { |
1442 |
get_line(); |
||
1443 |
if (line == NULL) |
||
1444 |
unterminated_string(s_lineno, s_line, s_cptr); |
||
1445 |
} |
||
1446 |
} |
||
1447 |
} |
||
1448 |
} |
||
1449 |
|||
1450 |
case '/': |
||
1451 |
169 |
c = (unsigned char) *cptr; |
|
1452 |
✗✓ | 169 |
if (c == '/') { |
1453 |
putc('*', f); |
||
1454 |
while ((c = (unsigned char) *++cptr) != '\n') { |
||
1455 |
if (c == '*' && cptr[1] == '/') |
||
1456 |
fprintf(f, "* "); |
||
1457 |
else |
||
1458 |
putc(c, f); |
||
1459 |
} |
||
1460 |
fprintf(f, "*/\n"); |
||
1461 |
goto next_line; |
||
1462 |
} |
||
1463 |
✓✓ | 169 |
if (c == '*') { |
1464 |
161 |
int c_lineno = lineno; |
|
1465 |
161 |
char *c_line = dup_line(); |
|
1466 |
161 |
char *c_cptr = c_line + (cptr - line - 1); |
|
1467 |
|||
1468 |
✓✗ | 161 |
putc('*', f); |
1469 |
161 |
++cptr; |
|
1470 |
for (;;) { |
||
1471 |
3197 |
c = (unsigned char) *cptr++; |
|
1472 |
✓✗ | 3197 |
putc(c, f); |
1473 |
✓✓✓✓ |
3197 |
if (c == '*' && *cptr == '/') { |
1474 |
✓✗ | 161 |
putc('/', f); |
1475 |
161 |
++cptr; |
|
1476 |
161 |
free(c_line); |
|
1477 |
161 |
goto loop; |
|
1478 |
} |
||
1479 |
✓✓ | 3036 |
if (c == '\n') { |
1480 |
22 |
get_line(); |
|
1481 |
✓✗ | 22 |
if (line == NULL) |
1482 |
unterminated_comment(c_lineno, c_line, c_cptr); |
||
1483 |
} |
||
1484 |
} |
||
1485 |
} |
||
1486 |
goto loop; |
||
1487 |
|||
1488 |
default: |
||
1489 |
goto loop; |
||
1490 |
} |
||
1491 |
} |
||
1492 |
|||
1493 |
|||
1494 |
int |
||
1495 |
mark_symbol(void) |
||
1496 |
22 |
{ |
|
1497 |
int c; |
||
1498 |
22 |
bucket *bp = NULL; |
|
1499 |
|||
1500 |
22 |
c = (unsigned char) cptr[1]; |
|
1501 |
✓✓ | 22 |
if (c == '%' || c == '\\') { |
1502 |
21 |
cptr += 2; |
|
1503 |
21 |
return (1); |
|
1504 |
} |
||
1505 |
✗✓ | 1 |
if (c == '=') |
1506 |
cptr += 2; |
||
1507 |
✓✗✗✓ ✗✗✗✓ ✗✗✗✓ ✗✗✓✗ ✓✗✓✗ |
3 |
else if ((c == 'p' || c == 'P') && |
1508 |
((c = cptr[2]) == 'r' || c == 'R') && |
||
1509 |
((c = cptr[3]) == 'e' || c == 'E') && |
||
1510 |
((c = cptr[4]) == 'c' || c == 'C') && |
||
1511 |
((c = (unsigned char) cptr[5], !IS_IDENT(c)))) |
||
1512 |
1 |
cptr += 5; |
|
1513 |
else |
||
1514 |
syntax_error(lineno, line, cptr); |
||
1515 |
|||
1516 |
1 |
c = nextc(); |
|
1517 |
✗✓✗✗ |
2 |
if (isalpha(c) || c == '_' || c == '.' || c == '$') |
1518 |
1 |
bp = get_name(); |
|
1519 |
else if (c == '\'' || c == '"') |
||
1520 |
bp = get_literal(); |
||
1521 |
else { |
||
1522 |
syntax_error(lineno, line, cptr); |
||
1523 |
/* NOTREACHED */ |
||
1524 |
} |
||
1525 |
|||
1526 |
✗✓✗✗ |
1 |
if (rprec[nrules] != UNDEFINED && bp->prec != rprec[nrules]) |
1527 |
prec_redeclared(); |
||
1528 |
|||
1529 |
1 |
rprec[nrules] = bp->prec; |
|
1530 |
1 |
rassoc[nrules] = bp->assoc; |
|
1531 |
1 |
return (0); |
|
1532 |
} |
||
1533 |
|||
1534 |
|||
1535 |
void |
||
1536 |
read_grammar(void) |
||
1537 |
21 |
{ |
|
1538 |
int c; |
||
1539 |
|||
1540 |
21 |
initialize_grammar(); |
|
1541 |
21 |
advance_to_start(); |
|
1542 |
|||
1543 |
for (;;) { |
||
1544 |
8212 |
c = nextc(); |
|
1545 |
✓✗ | 8212 |
if (c == EOF) |
1546 |
break; |
||
1547 |
✓✓✓✗ ✓✓ |
13528 |
if (isalpha(c) || c == '_' || c == '.' || c == '$' || c == '\'' || |
1548 |
c == '"') |
||
1549 |
5316 |
add_symbol(); |
|
1550 |
✓✓ | 2896 |
else if (c == '{' || c == '=') |
1551 |
1498 |
copy_action(); |
|
1552 |
✓✓ | 1398 |
else if (c == '|') { |
1553 |
1376 |
end_rule(); |
|
1554 |
1376 |
start_rule(plhs[nrules - 1], 0); |
|
1555 |
1376 |
++cptr; |
|
1556 |
✓✗ | 22 |
} else if (c == '%') { |
1557 |
✓✓ | 22 |
if (mark_symbol()) |
1558 |
21 |
break; |
|
1559 |
} else |
||
1560 |
syntax_error(lineno, line, cptr); |
||
1561 |
} |
||
1562 |
21 |
end_rule(); |
|
1563 |
21 |
} |
|
1564 |
|||
1565 |
|||
1566 |
void |
||
1567 |
free_tags(void) |
||
1568 |
21 |
{ |
|
1569 |
int i; |
||
1570 |
|||
1571 |
✗✓ | 21 |
if (tag_table == NULL) |
1572 |
return; |
||
1573 |
|||
1574 |
✓✓ | 123 |
for (i = 0; i < ntags; ++i) { |
1575 |
✗✓ | 102 |
assert(tag_table[i]); |
1576 |
102 |
free(tag_table[i]); |
|
1577 |
} |
||
1578 |
21 |
free(tag_table); |
|
1579 |
} |
||
1580 |
|||
1581 |
|||
1582 |
void |
||
1583 |
pack_names(void) |
||
1584 |
21 |
{ |
|
1585 |
bucket *bp; |
||
1586 |
char *p, *s, *t; |
||
1587 |
|||
1588 |
21 |
name_pool_size = 13; /* 13 == sizeof("$end") + sizeof("$accept") */ |
|
1589 |
✓✓ | 2041 |
for (bp = first_symbol; bp; bp = bp->next) |
1590 |
2020 |
name_pool_size += strlen(bp->name) + 1; |
|
1591 |
21 |
name_pool = malloc(name_pool_size); |
|
1592 |
✗✓ | 21 |
if (name_pool == NULL) |
1593 |
no_space(); |
||
1594 |
|||
1595 |
21 |
strlcpy(name_pool, "$accept", name_pool_size); |
|
1596 |
21 |
strlcpy(name_pool + 8, "$end", name_pool_size - 8); |
|
1597 |
21 |
t = name_pool + 13; |
|
1598 |
✓✓ | 2041 |
for (bp = first_symbol; bp; bp = bp->next) { |
1599 |
2020 |
p = t; |
|
1600 |
2020 |
s = bp->name; |
|
1601 |
✓✓ | 17958 |
while ((*t++ = *s++)) |
1602 |
continue; |
||
1603 |
2020 |
free(bp->name); |
|
1604 |
2020 |
bp->name = p; |
|
1605 |
} |
||
1606 |
21 |
} |
|
1607 |
|||
1608 |
|||
1609 |
void |
||
1610 |
check_symbols(void) |
||
1611 |
21 |
{ |
|
1612 |
bucket *bp; |
||
1613 |
|||
1614 |
✗✓ | 21 |
if (goal->class == UNKNOWN) |
1615 |
undefined_goal(goal->name); |
||
1616 |
|||
1617 |
✓✓ | 2041 |
for (bp = first_symbol; bp; bp = bp->next) { |
1618 |
✗✓ | 2020 |
if (bp->class == UNKNOWN) { |
1619 |
undefined_symbol_warning(bp->name); |
||
1620 |
bp->class = TERM; |
||
1621 |
} |
||
1622 |
} |
||
1623 |
21 |
} |
|
1624 |
|||
1625 |
|||
1626 |
void |
||
1627 |
pack_symbols(void) |
||
1628 |
21 |
{ |
|
1629 |
bucket *bp; |
||
1630 |
bucket **v; |
||
1631 |
int i, j, k, n; |
||
1632 |
|||
1633 |
21 |
nsyms = 2; |
|
1634 |
21 |
ntokens = 1; |
|
1635 |
✓✓ | 2041 |
for (bp = first_symbol; bp; bp = bp->next) { |
1636 |
2020 |
++nsyms; |
|
1637 |
✓✓ | 2020 |
if (bp->class == TERM) |
1638 |
1154 |
++ntokens; |
|
1639 |
} |
||
1640 |
21 |
start_symbol = ntokens; |
|
1641 |
21 |
nvars = nsyms - ntokens; |
|
1642 |
|||
1643 |
21 |
symbol_name = reallocarray(NULL, nsyms, sizeof(char *)); |
|
1644 |
✗✓ | 21 |
if (symbol_name == NULL) |
1645 |
no_space(); |
||
1646 |
21 |
symbol_value = reallocarray(NULL, nsyms, sizeof(short)); |
|
1647 |
✗✓ | 21 |
if (symbol_value == NULL) |
1648 |
no_space(); |
||
1649 |
21 |
symbol_prec = reallocarray(NULL, nsyms, sizeof(short)); |
|
1650 |
✗✓ | 21 |
if (symbol_prec == NULL) |
1651 |
no_space(); |
||
1652 |
21 |
symbol_assoc = malloc(nsyms); |
|
1653 |
✗✓ | 21 |
if (symbol_assoc == NULL) |
1654 |
no_space(); |
||
1655 |
|||
1656 |
21 |
v = reallocarray(NULL, nsyms, sizeof(bucket *)); |
|
1657 |
✗✓ | 21 |
if (v == NULL) |
1658 |
no_space(); |
||
1659 |
|||
1660 |
21 |
v[0] = 0; |
|
1661 |
21 |
v[start_symbol] = 0; |
|
1662 |
|||
1663 |
21 |
i = 1; |
|
1664 |
21 |
j = start_symbol + 1; |
|
1665 |
✓✓ | 2041 |
for (bp = first_symbol; bp; bp = bp->next) { |
1666 |
✓✓ | 2020 |
if (bp->class == TERM) |
1667 |
1154 |
v[i++] = bp; |
|
1668 |
else |
||
1669 |
866 |
v[j++] = bp; |
|
1670 |
} |
||
1671 |
✓✗✗✓ |
21 |
assert(i == ntokens && j == nsyms); |
1672 |
|||
1673 |
✓✓ | 1175 |
for (i = 1; i < ntokens; ++i) |
1674 |
1154 |
v[i]->index = i; |
|
1675 |
|||
1676 |
21 |
goal->index = start_symbol + 1; |
|
1677 |
21 |
k = start_symbol + 2; |
|
1678 |
✓✓ | 908 |
while (++i < nsyms) |
1679 |
✓✓ | 866 |
if (v[i] != goal) { |
1680 |
845 |
v[i]->index = k; |
|
1681 |
845 |
++k; |
|
1682 |
} |
||
1683 |
21 |
goal->value = 0; |
|
1684 |
21 |
k = 1; |
|
1685 |
✓✓ | 887 |
for (i = start_symbol + 1; i < nsyms; ++i) { |
1686 |
✓✓ | 866 |
if (v[i] != goal) { |
1687 |
845 |
v[i]->value = k; |
|
1688 |
845 |
++k; |
|
1689 |
} |
||
1690 |
} |
||
1691 |
|||
1692 |
21 |
k = 0; |
|
1693 |
✓✓ | 1175 |
for (i = 1; i < ntokens; ++i) { |
1694 |
1154 |
n = v[i]->value; |
|
1695 |
✗✓ | 1154 |
if (n > 256) { |
1696 |
for (j = k++; j > 0 && symbol_value[j - 1] > n; --j) |
||
1697 |
symbol_value[j] = symbol_value[j - 1]; |
||
1698 |
symbol_value[j] = n; |
||
1699 |
} |
||
1700 |
} |
||
1701 |
|||
1702 |
✓✗ | 21 |
if (v[1]->value == UNDEFINED) |
1703 |
21 |
v[1]->value = 256; |
|
1704 |
|||
1705 |
21 |
j = 0; |
|
1706 |
21 |
n = 257; |
|
1707 |
✓✓ | 1154 |
for (i = 2; i < ntokens; ++i) { |
1708 |
✓✓ | 1133 |
if (v[i]->value == UNDEFINED) { |
1709 |
✗✓✗✗ |
1023 |
while (j < k && n == symbol_value[j]) { |
1710 |
while (++j < k && n == symbol_value[j]) |
||
1711 |
continue; |
||
1712 |
++n; |
||
1713 |
} |
||
1714 |
1023 |
v[i]->value = n; |
|
1715 |
1023 |
++n; |
|
1716 |
} |
||
1717 |
} |
||
1718 |
|||
1719 |
21 |
symbol_name[0] = name_pool + 8; |
|
1720 |
21 |
symbol_value[0] = 0; |
|
1721 |
21 |
symbol_prec[0] = 0; |
|
1722 |
21 |
symbol_assoc[0] = TOKEN; |
|
1723 |
✓✓ | 1175 |
for (i = 1; i < ntokens; ++i) { |
1724 |
1154 |
symbol_name[i] = v[i]->name; |
|
1725 |
1154 |
symbol_value[i] = v[i]->value; |
|
1726 |
1154 |
symbol_prec[i] = v[i]->prec; |
|
1727 |
1154 |
symbol_assoc[i] = v[i]->assoc; |
|
1728 |
} |
||
1729 |
21 |
symbol_name[start_symbol] = name_pool; |
|
1730 |
21 |
symbol_value[start_symbol] = -1; |
|
1731 |
21 |
symbol_prec[start_symbol] = 0; |
|
1732 |
21 |
symbol_assoc[start_symbol] = TOKEN; |
|
1733 |
✓✓ | 887 |
for (++i; i < nsyms; ++i) { |
1734 |
866 |
k = v[i]->index; |
|
1735 |
866 |
symbol_name[k] = v[i]->name; |
|
1736 |
866 |
symbol_value[k] = v[i]->value; |
|
1737 |
866 |
symbol_prec[k] = v[i]->prec; |
|
1738 |
866 |
symbol_assoc[k] = v[i]->assoc; |
|
1739 |
} |
||
1740 |
|||
1741 |
21 |
free(v); |
|
1742 |
21 |
} |
|
1743 |
|||
1744 |
|||
1745 |
void |
||
1746 |
pack_grammar(void) |
||
1747 |
21 |
{ |
|
1748 |
int i, j; |
||
1749 |
int assoc, prec; |
||
1750 |
|||
1751 |
21 |
ritem = reallocarray(NULL, nitems, sizeof(short)); |
|
1752 |
✗✓ | 21 |
if (ritem == NULL) |
1753 |
no_space(); |
||
1754 |
21 |
rlhs = reallocarray(NULL, nrules, sizeof(short)); |
|
1755 |
✗✓ | 21 |
if (rlhs == NULL) |
1756 |
no_space(); |
||
1757 |
21 |
rrhs = reallocarray(NULL, nrules + 1, sizeof(short)); |
|
1758 |
✗✓ | 21 |
if (rrhs == NULL) |
1759 |
no_space(); |
||
1760 |
21 |
rprec = reallocarray(rprec, nrules, sizeof(short)); |
|
1761 |
✗✓ | 21 |
if (rprec == NULL) |
1762 |
no_space(); |
||
1763 |
21 |
rassoc = realloc(rassoc, nrules); |
|
1764 |
✗✓ | 21 |
if (rassoc == NULL) |
1765 |
no_space(); |
||
1766 |
|||
1767 |
21 |
ritem[0] = -1; |
|
1768 |
21 |
ritem[1] = goal->index; |
|
1769 |
21 |
ritem[2] = 0; |
|
1770 |
21 |
ritem[3] = -2; |
|
1771 |
21 |
rlhs[0] = 0; |
|
1772 |
21 |
rlhs[1] = 0; |
|
1773 |
21 |
rlhs[2] = start_symbol; |
|
1774 |
21 |
rrhs[0] = 0; |
|
1775 |
21 |
rrhs[1] = 0; |
|
1776 |
21 |
rrhs[2] = 1; |
|
1777 |
|||
1778 |
21 |
j = 4; |
|
1779 |
✓✓ | 2263 |
for (i = 3; i < nrules; ++i) { |
1780 |
2242 |
rlhs[i] = plhs[i]->index; |
|
1781 |
2242 |
rrhs[i] = j; |
|
1782 |
2242 |
assoc = TOKEN; |
|
1783 |
2242 |
prec = 0; |
|
1784 |
✓✓ | 9065 |
while (pitem[j]) { |
1785 |
4581 |
ritem[j] = pitem[j]->index; |
|
1786 |
✓✓ | 4581 |
if (pitem[j]->class == TERM) { |
1787 |
2547 |
prec = pitem[j]->prec; |
|
1788 |
2547 |
assoc = pitem[j]->assoc; |
|
1789 |
} |
||
1790 |
4581 |
++j; |
|
1791 |
} |
||
1792 |
2242 |
ritem[j] = -i; |
|
1793 |
2242 |
++j; |
|
1794 |
✓✓ | 2242 |
if (rprec[i] == UNDEFINED) { |
1795 |
2186 |
rprec[i] = prec; |
|
1796 |
2186 |
rassoc[i] = assoc; |
|
1797 |
} |
||
1798 |
} |
||
1799 |
21 |
rrhs[i] = j; |
|
1800 |
|||
1801 |
21 |
free(plhs); |
|
1802 |
21 |
free(pitem); |
|
1803 |
21 |
} |
|
1804 |
|||
1805 |
|||
1806 |
void |
||
1807 |
print_grammar(void) |
||
1808 |
21 |
{ |
|
1809 |
int i, j, k; |
||
1810 |
21 |
int spacing = 0; |
|
1811 |
21 |
FILE *f = verbose_file; |
|
1812 |
|||
1813 |
✓✗ | 21 |
if (!vflag) |
1814 |
21 |
return; |
|
1815 |
|||
1816 |
k = 1; |
||
1817 |
for (i = 2; i < nrules; ++i) { |
||
1818 |
if (rlhs[i] != rlhs[i - 1]) { |
||
1819 |
if (i != 2) |
||
1820 |
fprintf(f, "\n"); |
||
1821 |
fprintf(f, "%4d %s :", i - 2, symbol_name[rlhs[i]]); |
||
1822 |
spacing = strlen(symbol_name[rlhs[i]]) + 1; |
||
1823 |
} else { |
||
1824 |
fprintf(f, "%4d ", i - 2); |
||
1825 |
j = spacing; |
||
1826 |
while (--j >= 0) |
||
1827 |
putc(' ', f); |
||
1828 |
putc('|', f); |
||
1829 |
} |
||
1830 |
|||
1831 |
while (ritem[k] >= 0) { |
||
1832 |
fprintf(f, " %s", symbol_name[ritem[k]]); |
||
1833 |
++k; |
||
1834 |
} |
||
1835 |
++k; |
||
1836 |
putc('\n', f); |
||
1837 |
} |
||
1838 |
} |
||
1839 |
|||
1840 |
|||
1841 |
void |
||
1842 |
reader(void) |
||
1843 |
21 |
{ |
|
1844 |
21 |
write_section(banner); |
|
1845 |
21 |
create_symbol_table(); |
|
1846 |
21 |
read_declarations(); |
|
1847 |
21 |
read_grammar(); |
|
1848 |
21 |
free_symbol_table(); |
|
1849 |
21 |
free_tags(); |
|
1850 |
21 |
pack_names(); |
|
1851 |
21 |
check_symbols(); |
|
1852 |
21 |
pack_symbols(); |
|
1853 |
21 |
pack_grammar(); |
|
1854 |
21 |
free_symbols(); |
|
1855 |
21 |
print_grammar(); |
|
1856 |
21 |
} |
Generated by: GCOVR (Version 3.3) |