GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
Line | Branch | Exec | Source |
1 |
/* $OpenBSD: reader.c,v 1.34 2017/05/25 20:11:03 tedu 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 |
{ |
||
112 |
✗✓ | 47176 |
assert(cinc >= 0); |
113 |
✗✓ | 23588 |
if (cinc >= cache_size) { |
114 |
cache_size += 256; |
||
115 |
cache = realloc(cache, cache_size); |
||
116 |
if (cache == NULL) |
||
117 |
no_space(); |
||
118 |
} |
||
119 |
23588 |
cache[cinc] = c; |
|
120 |
23588 |
++cinc; |
|
121 |
23588 |
} |
|
122 |
|||
123 |
|||
124 |
void |
||
125 |
get_line(void) |
||
126 |
{ |
||
127 |
14154 |
FILE *f = input_file; |
|
128 |
int c, i; |
||
129 |
|||
130 |
✓✗✓✗ ✓✓✗✓ |
35385 |
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 |
✓✓ | 7077 |
if (line == NULL || linesize != (LINESIZE + 1)) { |
140 |
11 |
free(line); |
|
141 |
11 |
linesize = LINESIZE + 1; |
|
142 |
11 |
line = malloc(linesize); |
|
143 |
✗✓ | 11 |
if (line == NULL) |
144 |
no_space(); |
||
145 |
} |
||
146 |
i = 0; |
||
147 |
7077 |
++lineno; |
|
148 |
151933 |
for (;;) { |
|
149 |
151933 |
line[i] = c; |
|
150 |
✓✓ | 151933 |
if (c == '\n') { |
151 |
7077 |
cptr = line; |
|
152 |
7077 |
return; |
|
153 |
} |
||
154 |
✓✓ | 144856 |
if (++i >= linesize) { |
155 |
2 |
linesize += LINESIZE; |
|
156 |
2 |
line = realloc(line, linesize); |
|
157 |
✗✓ | 2 |
if (line == NULL) |
158 |
no_space(); |
||
159 |
} |
||
160 |
✓✗✓✓ |
579424 |
c = getc(f); |
161 |
✗✓ | 144856 |
if (c == EOF) { |
162 |
line[i] = '\n'; |
||
163 |
saw_eof = 1; |
||
164 |
cptr = line; |
||
165 |
return; |
||
166 |
} |
||
167 |
} |
||
168 |
7077 |
} |
|
169 |
|||
170 |
|||
171 |
char * |
||
172 |
dup_line(void) |
||
173 |
{ |
||
174 |
char *p, *s, *t; |
||
175 |
|||
176 |
✗✓ | 3332 |
if (line == NULL) |
177 |
return (0); |
||
178 |
s = line; |
||
179 |
✓✓ | 96854 |
while (*s != '\n') |
180 |
46761 |
++s; |
|
181 |
1666 |
p = malloc(s - line + 1); |
|
182 |
✗✓ | 1666 |
if (p == NULL) |
183 |
no_space(); |
||
184 |
|||
185 |
1666 |
s = line; |
|
186 |
t = p; |
||
187 |
✓✓ | 50093 |
while ((*t++ = *s++) != '\n') |
188 |
46761 |
continue; |
|
189 |
1666 |
return (p); |
|
190 |
1666 |
} |
|
191 |
|||
192 |
|||
193 |
void |
||
194 |
skip_comment(void) |
||
195 |
{ |
||
196 |
char *s; |
||
197 |
162 |
int st_lineno = lineno; |
|
198 |
81 |
char *st_line = dup_line(); |
|
199 |
81 |
char *st_cptr = st_line + (cptr - line); |
|
200 |
|||
201 |
81 |
s = cptr + 2; |
|
202 |
13867 |
for (;;) { |
|
203 |
✓✓✓✓ |
14192 |
if (*s == '*' && s[1] == '/') { |
204 |
81 |
cptr = s + 2; |
|
205 |
81 |
free(st_line); |
|
206 |
return; |
||
207 |
} |
||
208 |
✓✓ | 13786 |
if (*s == '\n') { |
209 |
266 |
get_line(); |
|
210 |
✗✓ | 266 |
if (line == NULL) |
211 |
unterminated_comment(st_lineno, st_line, st_cptr); |
||
212 |
266 |
s = cptr; |
|
213 |
266 |
} else |
|
214 |
13520 |
++s; |
|
215 |
} |
||
216 |
81 |
} |
|
217 |
|||
218 |
|||
219 |
int |
||
220 |
nextc(void) |
||
221 |
{ |
||
222 |
char *s; |
||
223 |
|||
224 |
✓✓ | 16682 |
if (line == NULL) { |
225 |
9 |
get_line(); |
|
226 |
✗✓ | 9 |
if (line == NULL) |
227 |
return (EOF); |
||
228 |
} |
||
229 |
8341 |
s = cptr; |
|
230 |
18140 |
for (;;) { |
|
231 |
✓✗✗✗ ✗✗✗✓ ✗✓✓ |
18140 |
switch (*s) { |
232 |
case '\n': |
||
233 |
2159 |
get_line(); |
|
234 |
✗✓ | 2159 |
if (line == NULL) |
235 |
return (EOF); |
||
236 |
2159 |
s = cptr; |
|
237 |
2159 |
break; |
|
238 |
|||
239 |
case ' ': |
||
240 |
case '\t': |
||
241 |
case '\f': |
||
242 |
case '\r': |
||
243 |
case '\v': |
||
244 |
case ',': |
||
245 |
case ';': |
||
246 |
7559 |
++s; |
|
247 |
7559 |
break; |
|
248 |
|||
249 |
case '\\': |
||
250 |
cptr = s; |
||
251 |
return ('%'); |
||
252 |
|||
253 |
case '/': |
||
254 |
✓✗ | 81 |
if (s[1] == '*') { |
255 |
81 |
cptr = s; |
|
256 |
81 |
skip_comment(); |
|
257 |
81 |
s = cptr; |
|
258 |
81 |
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 |
8341 |
cptr = s; |
|
270 |
8341 |
return ((unsigned char) *s); |
|
271 |
} |
||
272 |
} |
||
273 |
8341 |
} |
|
274 |
|||
275 |
|||
276 |
int |
||
277 |
keyword(void) |
||
278 |
{ |
||
279 |
int c; |
||
280 |
362 |
char *t_cptr = cptr; |
|
281 |
|||
282 |
181 |
c = (unsigned char) *++cptr; |
|
283 |
✓✓ | 181 |
if (isalpha(c)) { |
284 |
163 |
cinc = 0; |
|
285 |
923 |
for (;;) { |
|
286 |
✓✓ | 923 |
if (isalpha(c)) { |
287 |
✗✓ | 760 |
if (isupper(c)) |
288 |
c = tolower(c); |
||
289 |
760 |
cachec(c); |
|
290 |
✗✓ | 923 |
} else if (isdigit(c) || c == '_' || c == '.' || c == '$') |
291 |
cachec(c); |
||
292 |
else |
||
293 |
break; |
||
294 |
760 |
c = (unsigned char) *++cptr; |
|
295 |
} |
||
296 |
163 |
cachec(NUL); |
|
297 |
|||
298 |
✓✓✗✓ |
268 |
if (strcmp(cache, "token") == 0 || strcmp(cache, "term") == 0) |
299 |
58 |
return (TOKEN); |
|
300 |
✓✓ | 105 |
if (strcmp(cache, "type") == 0) |
301 |
57 |
return (TYPE); |
|
302 |
✓✓ | 48 |
if (strcmp(cache, "left") == 0) |
303 |
22 |
return (LEFT); |
|
304 |
✓✓ | 26 |
if (strcmp(cache, "right") == 0) |
305 |
2 |
return (RIGHT); |
|
306 |
✓✓✗✓ |
40 |
if (strcmp(cache, "nonassoc") == 0 || strcmp(cache, "binary") == 0) |
307 |
8 |
return (NONASSOC); |
|
308 |
✓✓ | 16 |
if (strcmp(cache, "start") == 0) |
309 |
7 |
return (START); |
|
310 |
✓✗ | 9 |
if (strcmp(cache, "union") == 0) |
311 |
9 |
return (UNION); |
|
312 |
if (strcmp(cache, "ident") == 0) |
||
313 |
return (IDENT); |
||
314 |
if (strcmp(cache, "expect") == 0) |
||
315 |
return (EXPECT); |
||
316 |
} else { |
||
317 |
18 |
++cptr; |
|
318 |
✓✓ | 18 |
if (c == '{') |
319 |
9 |
return (TEXT); |
|
320 |
✓✗ | 9 |
if (c == '%' || c == '\\') |
321 |
9 |
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 |
181 |
} |
|
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 |
{ |
||
369 |
int c; |
||
370 |
int quote; |
||
371 |
18 |
FILE *f = text_file; |
|
372 |
int need_newline = 0; |
||
373 |
9 |
int t_lineno = lineno; |
|
374 |
9 |
char *t_line = dup_line(); |
|
375 |
9 |
char *t_cptr = t_line + (cptr - line - 2); |
|
376 |
|||
377 |
✓✗ | 9 |
if (*cptr == '\n') { |
378 |
9 |
get_line(); |
|
379 |
✗✓ | 9 |
if (line == NULL) |
380 |
unterminated_text(t_lineno, t_line, t_cptr); |
||
381 |
} |
||
382 |
✓✗ | 18 |
if (!lflag) |
383 |
9 |
fprintf(f, line_format, lineno, input_file_name); |
|
384 |
|||
385 |
loop: |
||
386 |
7308 |
c = (unsigned char) *cptr++; |
|
387 |
✓✗✓✓ ✗✓✓ |
7308 |
switch (c) { |
388 |
case '\n': |
||
389 |
next_line: |
||
390 |
✓✗ | 870 |
putc('\n', f); |
391 |
need_newline = 0; |
||
392 |
435 |
get_line(); |
|
393 |
✓✗ | 435 |
if (line) |
394 |
435 |
goto loop; |
|
395 |
unterminated_text(t_lineno, t_line, t_cptr); |
||
396 |
|||
397 |
case '\'': |
||
398 |
case '"': { |
||
399 |
22 |
int s_lineno = lineno; |
|
400 |
22 |
char *s_line = dup_line(); |
|
401 |
22 |
char *s_cptr = s_line + (cptr - line - 1); |
|
402 |
|||
403 |
quote = c; |
||
404 |
✓✗ | 44 |
putc(c, f); |
405 |
209 |
for (;;) { |
|
406 |
209 |
c = (unsigned char) *cptr++; |
|
407 |
✓✗ | 418 |
putc(c, f); |
408 |
✓✓ | 209 |
if (c == quote) { |
409 |
need_newline = 1; |
||
410 |
22 |
free(s_line); |
|
411 |
goto loop; |
||
412 |
} |
||
413 |
✗✓ | 187 |
if (c == '\n') |
414 |
unterminated_string(s_lineno, s_line, s_cptr); |
||
415 |
✗✓ | 187 |
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 |
✓✗ | 98 |
putc(c, f); |
429 |
need_newline = 1; |
||
430 |
49 |
c = (unsigned char) *cptr; |
|
431 |
✗✓ | 49 |
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 |
✓✓ | 49 |
if (c == '*') { |
443 |
6 |
int c_lineno = lineno; |
|
444 |
6 |
char *c_line = dup_line(); |
|
445 |
6 |
char *c_cptr = c_line + (cptr - line - 1); |
|
446 |
|||
447 |
✓✗ | 12 |
putc('*', f); |
448 |
6 |
++cptr; |
|
449 |
2568 |
for (;;) { |
|
450 |
2568 |
c = (unsigned char) *cptr++; |
|
451 |
✓✗ | 5136 |
putc(c, f); |
452 |
✓✓✓✓ |
2612 |
if (c == '*' && *cptr == '/') { |
453 |
✓✗ | 12 |
putc('/', f); |
454 |
6 |
++cptr; |
|
455 |
6 |
free(c_line); |
|
456 |
goto loop; |
||
457 |
} |
||
458 |
✓✓ | 2562 |
if (c == '\n') { |
459 |
40 |
get_line(); |
|
460 |
✗✓ | 40 |
if (line == NULL) |
461 |
unterminated_comment(c_lineno, c_line, c_cptr); |
||
462 |
} |
||
463 |
} |
||
464 |
} |
||
465 |
need_newline = 1; |
||
466 |
43 |
goto loop; |
|
467 |
|||
468 |
case '%': |
||
469 |
case '\\': |
||
470 |
✓✓ | 13 |
if (*cptr == '}') { |
471 |
✗✓ | 9 |
if (need_newline) |
472 |
putc('\n', f); |
||
473 |
9 |
++cptr; |
|
474 |
9 |
free(t_line); |
|
475 |
return; |
||
476 |
} |
||
477 |
/* fall through */ |
||
478 |
|||
479 |
default: |
||
480 |
✓✗ | 13578 |
putc(c, f); |
481 |
need_newline = 1; |
||
482 |
6789 |
goto loop; |
|
483 |
} |
||
484 |
9 |
} |
|
485 |
|||
486 |
|||
487 |
void |
||
488 |
copy_union(void) |
||
489 |
{ |
||
490 |
int c, quote, depth; |
||
491 |
18 |
int u_lineno = lineno; |
|
492 |
9 |
char *u_line = dup_line(); |
|
493 |
9 |
char *u_cptr = u_line + (cptr - line - 6); |
|
494 |
|||
495 |
✗✓ | 9 |
if (unionized) |
496 |
over_unionized(cptr - 6); |
||
497 |
9 |
unionized = 1; |
|
498 |
|||
499 |
✓✗ | 9 |
if (!lflag) |
500 |
9 |
fprintf(text_file, line_format, lineno, input_file_name); |
|
501 |
|||
502 |
9 |
fprintf(text_file, "#ifndef YYSTYPE_DEFINED\n"); |
|
503 |
9 |
fprintf(text_file, "#define YYSTYPE_DEFINED\n"); |
|
504 |
9 |
fprintf(text_file, "typedef union"); |
|
505 |
✓✓ | 9 |
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 |
4 |
} |
|
510 |
|||
511 |
9 |
depth = 0; |
|
512 |
loop: |
||
513 |
660 |
c = (unsigned char) *cptr++; |
|
514 |
✓✗ | 1320 |
putc(c, text_file); |
515 |
✓✓ | 660 |
if (dflag) |
516 |
✓✗ | 980 |
putc(c, union_file); |
517 |
✓✓✓✗ ✗✗✓ |
660 |
switch (c) { |
518 |
case '\n': |
||
519 |
next_line: |
||
520 |
54 |
get_line(); |
|
521 |
✗✓ | 54 |
if (line == NULL) |
522 |
unterminated_union(u_lineno, u_line, u_cptr); |
||
523 |
54 |
goto loop; |
|
524 |
|||
525 |
case '{': |
||
526 |
11 |
++depth; |
|
527 |
11 |
goto loop; |
|
528 |
|||
529 |
case '}': |
||
530 |
✓✓ | 11 |
if (--depth == 0) { |
531 |
9 |
fprintf(text_file, " YYSTYPE;\n"); |
|
532 |
9 |
fprintf(text_file, "#endif /* YYSTYPE_DEFINED */\n"); |
|
533 |
9 |
free(u_line); |
|
534 |
return; |
||
535 |
} |
||
536 |
2 |
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 |
584 |
goto loop; |
|
627 |
} |
||
628 |
9 |
} |
|
629 |
|||
630 |
|||
631 |
bucket * |
||
632 |
get_literal(void) |
||
633 |
{ |
||
634 |
int c, quote, i, n; |
||
635 |
140 |
char *s; |
|
636 |
bucket *bp; |
||
637 |
70 |
int s_lineno = lineno; |
|
638 |
70 |
char *s_line = dup_line(); |
|
639 |
70 |
char *s_cptr = s_line + (cptr - line); |
|
640 |
|||
641 |
70 |
quote = (unsigned char) *cptr++; |
|
642 |
70 |
cinc = 0; |
|
643 |
140 |
for (;;) { |
|
644 |
140 |
c = (unsigned char) *cptr++; |
|
645 |
✓✓ | 140 |
if (c == quote) |
646 |
break; |
||
647 |
✗✓ | 70 |
if (c == '\n') |
648 |
unterminated_string(s_lineno, s_line, s_cptr); |
||
649 |
✗✓ | 70 |
if (c == '\\') { |
650 |
char *c_cptr = cptr - 1; |
||
651 |
unsigned long ulval; |
||
652 |
|||
653 |
c = (unsigned char) *cptr++; |
||
654 |
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 |
c = '\n'; |
||
696 |
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 |
70 |
cachec(c); |
|
709 |
} |
||
710 |
70 |
free(s_line); |
|
711 |
|||
712 |
70 |
n = cinc; |
|
713 |
70 |
s = malloc(n); |
|
714 |
✗✓ | 70 |
if (s == NULL) |
715 |
no_space(); |
||
716 |
|||
717 |
70 |
memcpy(s, cache, n); |
|
718 |
|||
719 |
70 |
cinc = 0; |
|
720 |
✓✗ | 70 |
if (n == 1) |
721 |
70 |
cachec('\''); |
|
722 |
else |
||
723 |
cachec('"'); |
||
724 |
|||
725 |
✓✓ | 280 |
for (i = 0; i < n; ++i) { |
726 |
70 |
c = ((unsigned char *) s)[i]; |
|
727 |
✓✗✗✓ |
140 |
if (c == '\\' || c == cache[0]) { |
728 |
cachec('\\'); |
||
729 |
cachec(c); |
||
730 |
✓✗ | 70 |
} else if (isprint(c)) |
731 |
70 |
cachec(c); |
|
732 |
else { |
||
733 |
cachec('\\'); |
||
734 |
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 |
cachec('n'); |
||
746 |
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 |
✓✗ | 70 |
if (n == 1) |
766 |
70 |
cachec('\''); |
|
767 |
else |
||
768 |
cachec('"'); |
||
769 |
|||
770 |
70 |
cachec(NUL); |
|
771 |
70 |
bp = lookup(cache); |
|
772 |
70 |
bp->class = TERM; |
|
773 |
✓✗✓✓ |
140 |
if (n == 1 && bp->value == UNDEFINED) |
774 |
30 |
bp->value = *(unsigned char *) s; |
|
775 |
70 |
free(s); |
|
776 |
|||
777 |
70 |
return (bp); |
|
778 |
70 |
} |
|
779 |
|||
780 |
|||
781 |
int |
||
782 |
is_reserved(char *name) |
||
783 |
{ |
||
784 |
char *s; |
||
785 |
|||
786 |
✓✗✗✓ |
10332 |
if (strcmp(name, ".") == 0 || |
787 |
✓✗ | 3444 |
strcmp(name, "$accept") == 0 || |
788 |
3444 |
strcmp(name, "$end") == 0) |
|
789 |
return (1); |
||
790 |
|||
791 |
✗✓✗✗ ✗✗ |
3444 |
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 |
3444 |
return (0); |
|
799 |
3444 |
} |
|
800 |
|||
801 |
|||
802 |
bucket * |
||
803 |
get_name(void) |
||
804 |
{ |
||
805 |
int c; |
||
806 |
|||
807 |
6888 |
cinc = 0; |
|
808 |
✓✓ | 44002 |
for (c = (unsigned char) *cptr; IS_IDENT(c); c = (unsigned char) *++cptr) |
809 |
18557 |
cachec(c); |
|
810 |
3444 |
cachec(NUL); |
|
811 |
|||
812 |
✗✓ | 3444 |
if (is_reserved(cache)) |
813 |
used_reserved(cache); |
||
814 |
|||
815 |
3444 |
return (lookup(cache)); |
|
816 |
} |
||
817 |
|||
818 |
|||
819 |
int |
||
820 |
get_number(void) |
||
821 |
{ |
||
822 |
unsigned long ul; |
||
823 |
3944 |
char *p; |
|
824 |
|||
825 |
1972 |
ul = strtoul(cptr, &p, 10); |
|
826 |
✗✓ | 1972 |
if (ul > INT_MAX) |
827 |
syntax_error(lineno, line, cptr); |
||
828 |
1972 |
cptr = p; |
|
829 |
3944 |
return (ul); |
|
830 |
1972 |
} |
|
831 |
|||
832 |
|||
833 |
char * |
||
834 |
get_tag(void) |
||
835 |
{ |
||
836 |
int c, i; |
||
837 |
char *s; |
||
838 |
196 |
int t_lineno = lineno; |
|
839 |
98 |
char *t_line = dup_line(); |
|
840 |
98 |
char *t_cptr = t_line + (cptr - line); |
|
841 |
|||
842 |
98 |
++cptr; |
|
843 |
98 |
c = nextc(); |
|
844 |
✗✓ | 98 |
if (c == EOF) |
845 |
unexpected_EOF(); |
||
846 |
✗✓ | 98 |
if (!isalpha(c) && c != '_' && c != '$') |
847 |
illegal_tag(t_lineno, t_line, t_cptr); |
||
848 |
|||
849 |
98 |
cinc = 0; |
|
850 |
98 |
do { |
|
851 |
216 |
cachec(c); |
|
852 |
216 |
c = (unsigned char) *++cptr; |
|
853 |
✓✓✗✓ |
314 |
} while (IS_IDENT(c)); |
854 |
98 |
cachec(NUL); |
|
855 |
|||
856 |
98 |
c = nextc(); |
|
857 |
✗✓ | 98 |
if (c == EOF) |
858 |
unexpected_EOF(); |
||
859 |
✗✓ | 98 |
if (c != '>') |
860 |
illegal_tag(t_lineno, t_line, t_cptr); |
||
861 |
98 |
free(t_line); |
|
862 |
98 |
++cptr; |
|
863 |
|||
864 |
✓✓ | 388 |
for (i = 0; i < ntags; ++i) { |
865 |
✓✓ | 159 |
if (strcmp(cache, tag_table[i]) == 0) |
866 |
63 |
return (tag_table[i]); |
|
867 |
} |
||
868 |
|||
869 |
✓✓ | 35 |
if (ntags >= tagmax) { |
870 |
9 |
tagmax += 16; |
|
871 |
9 |
tag_table = reallocarray(tag_table, tagmax, sizeof(char *)); |
|
872 |
✗✓ | 9 |
if (tag_table == NULL) |
873 |
no_space(); |
||
874 |
} |
||
875 |
35 |
s = malloc(cinc); |
|
876 |
✗✓ | 35 |
if (s == NULL) |
877 |
no_space(); |
||
878 |
35 |
strlcpy(s, cache, cinc); |
|
879 |
35 |
tag_table[ntags] = s; |
|
880 |
35 |
++ntags; |
|
881 |
35 |
return (s); |
|
882 |
98 |
} |
|
883 |
|||
884 |
|||
885 |
void |
||
886 |
declare_tokens(int assoc) |
||
887 |
{ |
||
888 |
int c; |
||
889 |
bucket *bp; |
||
890 |
int value; |
||
891 |
char *tag = 0; |
||
892 |
|||
893 |
✓✓ | 180 |
if (assoc != TOKEN) |
894 |
32 |
++prec; |
|
895 |
|||
896 |
90 |
c = nextc(); |
|
897 |
✗✓ | 90 |
if (c == EOF) |
898 |
unexpected_EOF(); |
||
899 |
✓✓ | 90 |
if (c == '<') { |
900 |
15 |
tag = get_tag(); |
|
901 |
15 |
c = nextc(); |
|
902 |
✗✓ | 15 |
if (c == EOF) |
903 |
unexpected_EOF(); |
||
904 |
} |
||
905 |
675 |
for (;;) { |
|
906 |
✓✓ | 675 |
if (isalpha(c) || c == '_' || c == '.' || c == '$') |
907 |
571 |
bp = get_name(); |
|
908 |
✓✓ | 104 |
else if (c == '\'' || c == '"') |
909 |
14 |
bp = get_literal(); |
|
910 |
else |
||
911 |
return; |
||
912 |
|||
913 |
✗✓ | 585 |
if (bp == goal) |
914 |
tokenized_start(bp->name); |
||
915 |
585 |
bp->class = TERM; |
|
916 |
|||
917 |
✓✓ | 585 |
if (tag) { |
918 |
✗✓✗✗ |
15 |
if (bp->tag && tag != bp->tag) |
919 |
retyped_warning(bp->name); |
||
920 |
15 |
bp->tag = tag; |
|
921 |
15 |
} |
|
922 |
✓✓ | 585 |
if (assoc != TOKEN) { |
923 |
✗✓✗✗ |
66 |
if (bp->prec && prec != bp->prec) |
924 |
reprec_warning(bp->name); |
||
925 |
66 |
bp->assoc = assoc; |
|
926 |
66 |
bp->prec = prec; |
|
927 |
66 |
} |
|
928 |
585 |
c = nextc(); |
|
929 |
✗✓ | 585 |
if (c == EOF) |
930 |
unexpected_EOF(); |
||
931 |
✗✓ | 585 |
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 |
90 |
} |
|
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 |
static 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 |
{ |
||
987 |
int c; |
||
988 |
bucket *bp; |
||
989 |
char *tag; |
||
990 |
|||
991 |
114 |
c = nextc(); |
|
992 |
✗✓ | 57 |
if (c == EOF) |
993 |
unexpected_EOF(); |
||
994 |
✗✓ | 57 |
if (c != '<') |
995 |
syntax_error(lineno, line, cptr); |
||
996 |
57 |
tag = get_tag(); |
|
997 |
|||
998 |
253 |
for (;;) { |
|
999 |
253 |
c = nextc(); |
|
1000 |
✓✓ | 253 |
if (isalpha(c) || c == '_' || c == '.' || c == '$') |
1001 |
196 |
bp = get_name(); |
|
1002 |
✗✓ | 57 |
else if (c == '\'' || c == '"') |
1003 |
bp = get_literal(); |
||
1004 |
else |
||
1005 |
return; |
||
1006 |
|||
1007 |
✗✓✗✗ |
196 |
if (bp->tag && tag != bp->tag) |
1008 |
retyped_warning(bp->name); |
||
1009 |
196 |
bp->tag = tag; |
|
1010 |
} |
||
1011 |
57 |
} |
|
1012 |
|||
1013 |
|||
1014 |
void |
||
1015 |
declare_start(void) |
||
1016 |
{ |
||
1017 |
int c; |
||
1018 |
bucket *bp; |
||
1019 |
|||
1020 |
14 |
c = nextc(); |
|
1021 |
✗✓ | 7 |
if (c == EOF) |
1022 |
unexpected_EOF(); |
||
1023 |
✗✓ | 7 |
if (!isalpha(c) && c != '_' && c != '.' && c != '$') |
1024 |
syntax_error(lineno, line, cptr); |
||
1025 |
7 |
bp = get_name(); |
|
1026 |
✗✓ | 7 |
if (bp->class == TERM) |
1027 |
terminal_start(bp->name); |
||
1028 |
✗✓✗✗ |
7 |
if (goal && goal != bp) |
1029 |
restarted_warning(); |
||
1030 |
7 |
goal = bp; |
|
1031 |
7 |
} |
|
1032 |
|||
1033 |
|||
1034 |
void |
||
1035 |
read_declarations(void) |
||
1036 |
{ |
||
1037 |
int c, k; |
||
1038 |
|||
1039 |
18 |
cache_size = 256; |
|
1040 |
9 |
cache = malloc(cache_size); |
|
1041 |
✗✓ | 9 |
if (cache == NULL) |
1042 |
no_space(); |
||
1043 |
|||
1044 |
181 |
for (;;) { |
|
1045 |
181 |
c = nextc(); |
|
1046 |
✗✓ | 181 |
if (c == EOF) |
1047 |
unexpected_EOF(); |
||
1048 |
✗✓ | 181 |
if (c != '%') |
1049 |
syntax_error(lineno, line, cptr); |
||
1050 |
✓✗✓✓ ✗✗✗✓ ✗✓✓✓ |
353 |
switch (k = keyword()) { |
1051 |
case MARK: |
||
1052 |
return; |
||
1053 |
|||
1054 |
case IDENT: |
||
1055 |
copy_ident(); |
||
1056 |
break; |
||
1057 |
|||
1058 |
case TEXT: |
||
1059 |
9 |
copy_text(); |
|
1060 |
9 |
break; |
|
1061 |
|||
1062 |
case UNION: |
||
1063 |
9 |
copy_union(); |
|
1064 |
9 |
break; |
|
1065 |
|||
1066 |
case TOKEN: |
||
1067 |
case LEFT: |
||
1068 |
case RIGHT: |
||
1069 |
case NONASSOC: |
||
1070 |
90 |
declare_tokens(k); |
|
1071 |
90 |
break; |
|
1072 |
|||
1073 |
case EXPECT: |
||
1074 |
declare_expect(k); |
||
1075 |
break; |
||
1076 |
|||
1077 |
case TYPE: |
||
1078 |
57 |
declare_types(); |
|
1079 |
57 |
break; |
|
1080 |
|||
1081 |
case START: |
||
1082 |
7 |
declare_start(); |
|
1083 |
7 |
break; |
|
1084 |
} |
||
1085 |
} |
||
1086 |
9 |
} |
|
1087 |
|||
1088 |
|||
1089 |
void |
||
1090 |
initialize_grammar(void) |
||
1091 |
{ |
||
1092 |
18 |
nitems = 4; |
|
1093 |
9 |
maxitems = 300; |
|
1094 |
9 |
pitem = calloc(maxitems, sizeof(bucket *)); |
|
1095 |
✗✓ | 9 |
if (pitem == NULL) |
1096 |
no_space(); |
||
1097 |
|||
1098 |
9 |
nrules = 3; |
|
1099 |
9 |
maxrules = 100; |
|
1100 |
9 |
plhs = reallocarray(NULL, maxrules, sizeof(bucket *)); |
|
1101 |
✗✓ | 9 |
if (plhs == NULL) |
1102 |
no_space(); |
||
1103 |
9 |
plhs[0] = 0; |
|
1104 |
9 |
plhs[1] = 0; |
|
1105 |
9 |
plhs[2] = 0; |
|
1106 |
9 |
rprec = reallocarray(NULL, maxrules, sizeof(short)); |
|
1107 |
✗✓ | 9 |
if (rprec == NULL) |
1108 |
no_space(); |
||
1109 |
9 |
rprec[0] = 0; |
|
1110 |
9 |
rprec[1] = 0; |
|
1111 |
9 |
rprec[2] = 0; |
|
1112 |
9 |
rassoc = reallocarray(NULL, maxrules, sizeof(char)); |
|
1113 |
✗✓ | 9 |
if (rassoc == NULL) |
1114 |
no_space(); |
||
1115 |
9 |
rassoc[0] = TOKEN; |
|
1116 |
9 |
rassoc[1] = TOKEN; |
|
1117 |
9 |
rassoc[2] = TOKEN; |
|
1118 |
9 |
} |
|
1119 |
|||
1120 |
|||
1121 |
void |
||
1122 |
expand_items(void) |
||
1123 |
{ |
||
1124 |
14 |
int olditems = maxitems; |
|
1125 |
|||
1126 |
7 |
maxitems += 300; |
|
1127 |
7 |
pitem = reallocarray(pitem, maxitems, sizeof(bucket *)); |
|
1128 |
✗✓ | 7 |
if (pitem == NULL) |
1129 |
no_space(); |
||
1130 |
7 |
memset(pitem + olditems, 0, (maxitems - olditems) * sizeof(bucket *)); |
|
1131 |
7 |
} |
|
1132 |
|||
1133 |
|||
1134 |
void |
||
1135 |
expand_rules(void) |
||
1136 |
{ |
||
1137 |
4 |
maxrules += 100; |
|
1138 |
2 |
plhs = reallocarray(plhs, maxrules, sizeof(bucket *)); |
|
1139 |
✗✓ | 2 |
if (plhs == NULL) |
1140 |
no_space(); |
||
1141 |
2 |
rprec = reallocarray(rprec, maxrules, sizeof(short)); |
|
1142 |
✗✓ | 2 |
if (rprec == NULL) |
1143 |
no_space(); |
||
1144 |
2 |
rassoc = reallocarray(rassoc, maxrules, sizeof(char)); |
|
1145 |
✗✓ | 2 |
if (rassoc == NULL) |
1146 |
no_space(); |
||
1147 |
2 |
} |
|
1148 |
|||
1149 |
|||
1150 |
void |
||
1151 |
advance_to_start(void) |
||
1152 |
{ |
||
1153 |
int c; |
||
1154 |
bucket *bp; |
||
1155 |
char *s_cptr; |
||
1156 |
int s_lineno; |
||
1157 |
|||
1158 |
18 |
for (;;) { |
|
1159 |
9 |
c = nextc(); |
|
1160 |
✗✓ | 9 |
if (c != '%') |
1161 |
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 |
9 |
c = nextc(); |
|
1181 |
✗✓ | 9 |
if (!isalpha(c) && c != '_' && c != '.' && c != '_') |
1182 |
syntax_error(lineno, line, cptr); |
||
1183 |
9 |
bp = get_name(); |
|
1184 |
✓✓ | 9 |
if (goal == NULL) { |
1185 |
✗✓ | 2 |
if (bp->class == TERM) |
1186 |
terminal_start(bp->name); |
||
1187 |
2 |
goal = bp; |
|
1188 |
2 |
} |
|
1189 |
9 |
s_lineno = lineno; |
|
1190 |
9 |
c = nextc(); |
|
1191 |
✗✓ | 9 |
if (c == EOF) |
1192 |
unexpected_EOF(); |
||
1193 |
✗✓ | 9 |
if (c != ':') |
1194 |
syntax_error(lineno, line, cptr); |
||
1195 |
9 |
start_rule(bp, s_lineno); |
|
1196 |
9 |
++cptr; |
|
1197 |
9 |
} |
|
1198 |
|||
1199 |
|||
1200 |
void |
||
1201 |
start_rule(bucket * bp, int s_lineno) |
||
1202 |
{ |
||
1203 |
✗✓ | 1728 |
if (bp->class == TERM) |
1204 |
terminal_lhs(s_lineno); |
||
1205 |
864 |
bp->class = NONTERM; |
|
1206 |
✓✓ | 864 |
if (nrules >= maxrules) |
1207 |
2 |
expand_rules(); |
|
1208 |
864 |
plhs[nrules] = bp; |
|
1209 |
864 |
rprec[nrules] = UNDEFINED; |
|
1210 |
864 |
rassoc[nrules] = TOKEN; |
|
1211 |
864 |
} |
|
1212 |
|||
1213 |
|||
1214 |
void |
||
1215 |
end_rule(void) |
||
1216 |
{ |
||
1217 |
int i; |
||
1218 |
|||
1219 |
✓✓✓✓ |
1798 |
if (!last_was_action && plhs[nrules]->tag) { |
1220 |
✓✓ | 176 |
for (i = nitems - 1; pitem[i]; --i) |
1221 |
continue; |
||
1222 |
✓✗✓✗ ✗✓ |
132 |
if (i == maxitems - 1 || pitem[i + 1] == 0 || |
1223 |
44 |
pitem[i + 1]->tag != plhs[nrules]->tag) |
|
1224 |
default_action_warning(); |
||
1225 |
} |
||
1226 |
864 |
last_was_action = 0; |
|
1227 |
✗✓ | 864 |
if (nitems >= maxitems) |
1228 |
expand_items(); |
||
1229 |
864 |
pitem[nitems] = 0; |
|
1230 |
864 |
++nitems; |
|
1231 |
864 |
++nrules; |
|
1232 |
864 |
} |
|
1233 |
|||
1234 |
|||
1235 |
void |
||
1236 |
insert_empty_rule(void) |
||
1237 |
{ |
||
1238 |
bucket *bp, **bpp; |
||
1239 |
|||
1240 |
✗✓ | 60 |
assert(cache); |
1241 |
30 |
snprintf(cache, cache_size, "$$%d", ++gensym); |
|
1242 |
30 |
bp = make_bucket(cache); |
|
1243 |
30 |
last_symbol->next = bp; |
|
1244 |
30 |
last_symbol = bp; |
|
1245 |
30 |
bp->tag = plhs[nrules]->tag; |
|
1246 |
30 |
bp->class = NONTERM; |
|
1247 |
|||
1248 |
✗✓ | 30 |
if ((nitems += 2) > maxitems) |
1249 |
expand_items(); |
||
1250 |
30 |
bpp = pitem + nitems - 1; |
|
1251 |
30 |
*bpp-- = bp; |
|
1252 |
✓✓ | 152 |
while ((bpp[0] = bpp[-1])) |
1253 |
46 |
--bpp; |
|
1254 |
|||
1255 |
✗✓ | 30 |
if (++nrules >= maxrules) |
1256 |
expand_rules(); |
||
1257 |
30 |
plhs[nrules] = plhs[nrules - 1]; |
|
1258 |
30 |
plhs[nrules - 1] = bp; |
|
1259 |
30 |
rprec[nrules] = rprec[nrules - 1]; |
|
1260 |
30 |
rprec[nrules - 1] = 0; |
|
1261 |
30 |
rassoc[nrules] = rassoc[nrules - 1]; |
|
1262 |
30 |
rassoc[nrules - 1] = TOKEN; |
|
1263 |
30 |
} |
|
1264 |
|||
1265 |
|||
1266 |
void |
||
1267 |
add_symbol(void) |
||
1268 |
{ |
||
1269 |
int c; |
||
1270 |
bucket *bp; |
||
1271 |
5422 |
int s_lineno = lineno; |
|
1272 |
|||
1273 |
2711 |
c = (unsigned char) *cptr; |
|
1274 |
✓✓ | 2711 |
if (c == '\'' || c == '"') |
1275 |
56 |
bp = get_literal(); |
|
1276 |
else |
||
1277 |
2655 |
bp = get_name(); |
|
1278 |
|||
1279 |
2711 |
c = nextc(); |
|
1280 |
✓✓ | 2711 |
if (c == ':') { |
1281 |
192 |
end_rule(); |
|
1282 |
192 |
start_rule(bp, s_lineno); |
|
1283 |
192 |
++cptr; |
|
1284 |
192 |
return; |
|
1285 |
} |
||
1286 |
✓✓ | 2519 |
if (last_was_action) |
1287 |
30 |
insert_empty_rule(); |
|
1288 |
2519 |
last_was_action = 0; |
|
1289 |
|||
1290 |
✓✓ | 2519 |
if (++nitems > maxitems) |
1291 |
7 |
expand_items(); |
|
1292 |
2519 |
pitem[nitems - 1] = bp; |
|
1293 |
5230 |
} |
|
1294 |
|||
1295 |
|||
1296 |
void |
||
1297 |
copy_action(void) |
||
1298 |
{ |
||
1299 |
int c, i, n, depth, quote; |
||
1300 |
char *tag; |
||
1301 |
1648 |
FILE *f = action_file; |
|
1302 |
824 |
int a_lineno = lineno; |
|
1303 |
824 |
char *a_line = dup_line(); |
|
1304 |
824 |
char *a_cptr = a_line + (cptr - line); |
|
1305 |
|||
1306 |
✗✓ | 824 |
if (last_was_action) |
1307 |
insert_empty_rule(); |
||
1308 |
824 |
last_was_action = 1; |
|
1309 |
|||
1310 |
824 |
fprintf(f, "case %d:\n", nrules - 2); |
|
1311 |
✓✗ | 824 |
if (!lflag) |
1312 |
824 |
fprintf(f, line_format, lineno, input_file_name); |
|
1313 |
✗✓ | 824 |
if (*cptr == '=') |
1314 |
++cptr; |
||
1315 |
|||
1316 |
n = 0; |
||
1317 |
✓✓ | 6646 |
for (i = nitems - 1; pitem[i]; --i) |
1318 |
2499 |
++n; |
|
1319 |
|||
1320 |
824 |
depth = 0; |
|
1321 |
loop: |
||
1322 |
56252 |
c = (unsigned char) *cptr; |
|
1323 |
✓✓ | 56252 |
if (c == '$') { |
1324 |
✓✓ | 2645 |
if (cptr[1] == '<') { |
1325 |
26 |
int d_lineno = lineno; |
|
1326 |
26 |
char *d_line = dup_line(); |
|
1327 |
26 |
char *d_cptr = d_line + (cptr - line); |
|
1328 |
|||
1329 |
26 |
++cptr; |
|
1330 |
26 |
tag = get_tag(); |
|
1331 |
26 |
c = (unsigned char) *cptr; |
|
1332 |
✗✓ | 26 |
if (c == '$') { |
1333 |
fprintf(f, "yyval.%s", tag); |
||
1334 |
++cptr; |
||
1335 |
free(d_line); |
||
1336 |
goto loop; |
||
1337 |
✓✗ | 26 |
} else if (isdigit(c)) { |
1338 |
26 |
i = get_number(); |
|
1339 |
✗✓ | 26 |
if (i > n) |
1340 |
dollar_warning(d_lineno, i); |
||
1341 |
26 |
fprintf(f, "yyvsp[%d].%s", i - n, tag); |
|
1342 |
26 |
free(d_line); |
|
1343 |
26 |
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 |
✓✓ | 2619 |
} else if (cptr[1] == '$') { |
1353 |
✓✗ | 673 |
if (ntags) { |
1354 |
673 |
tag = plhs[nrules]->tag; |
|
1355 |
✗✓ | 673 |
if (tag == NULL) |
1356 |
untyped_lhs(); |
||
1357 |
673 |
fprintf(f, "yyval.%s", tag); |
|
1358 |
673 |
} else |
|
1359 |
fprintf(f, "yyval"); |
||
1360 |
673 |
cptr += 2; |
|
1361 |
673 |
goto loop; |
|
1362 |
✓✗ | 1946 |
} else if (isdigit((unsigned char) cptr[1])) { |
1363 |
1946 |
++cptr; |
|
1364 |
1946 |
i = get_number(); |
|
1365 |
✓✗ | 1946 |
if (ntags) { |
1366 |
✓✗✗✓ |
3892 |
if (i <= 0 || i > n) |
1367 |
unknown_rhs(i); |
||
1368 |
1946 |
tag = pitem[nitems + i - n - 1]->tag; |
|
1369 |
✗✓ | 1946 |
if (tag == NULL) |
1370 |
untyped_rhs(i, pitem[nitems + i - n - 1]->name); |
||
1371 |
1946 |
fprintf(f, "yyvsp[%d].%s", i - n, tag); |
|
1372 |
1946 |
} else { |
|
1373 |
if (i > n) |
||
1374 |
dollar_warning(lineno, i); |
||
1375 |
fprintf(f, "yyvsp[%d]", i - n); |
||
1376 |
} |
||
1377 |
1946 |
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 |
✓✓ | 53607 |
if (isalpha(c) || c == '_' || c == '$') { |
1388 |
4914 |
do { |
|
1389 |
✓✗ | 59120 |
putc(c, f); |
1390 |
29560 |
c = (unsigned char) *++cptr; |
|
1391 |
✓✓✗✓ |
34474 |
} while (isalnum(c) || c == '_' || c == '$'); |
1392 |
4914 |
goto loop; |
|
1393 |
} |
||
1394 |
✓✗ | 97386 |
putc(c, f); |
1395 |
48693 |
++cptr; |
|
1396 |
✓✓✓✓ ✗✓✓✓ |
48693 |
switch (c) { |
1397 |
case '\n': |
||
1398 |
next_line: |
||
1399 |
4026 |
get_line(); |
|
1400 |
✓✗ | 4026 |
if (line) |
1401 |
4026 |
goto loop; |
|
1402 |
unterminated_action(a_lineno, a_line, a_cptr); |
||
1403 |
|||
1404 |
case ';': |
||
1405 |
✓✗ | 2183 |
if (depth > 0) |
1406 |
2183 |
goto loop; |
|
1407 |
fprintf(f, "\nbreak;\n"); |
||
1408 |
free(a_line); |
||
1409 |
return; |
||
1410 |
|||
1411 |
case '{': |
||
1412 |
1209 |
++depth; |
|
1413 |
1209 |
goto loop; |
|
1414 |
|||
1415 |
case '}': |
||
1416 |
✓✓ | 1209 |
if (--depth > 0) |
1417 |
385 |
goto loop; |
|
1418 |
824 |
fprintf(f, "\nbreak;\n"); |
|
1419 |
824 |
free(a_line); |
|
1420 |
824 |
return; |
|
1421 |
|||
1422 |
case '\'': |
||
1423 |
case '"': { |
||
1424 |
437 |
int s_lineno = lineno; |
|
1425 |
437 |
char *s_line = dup_line(); |
|
1426 |
437 |
char *s_cptr = s_line + (cptr - line - 1); |
|
1427 |
|||
1428 |
quote = c; |
||
1429 |
7316 |
for (;;) { |
|
1430 |
7316 |
c = (unsigned char) *cptr++; |
|
1431 |
✓✗ | 14632 |
putc(c, f); |
1432 |
✓✓ | 7316 |
if (c == quote) { |
1433 |
437 |
free(s_line); |
|
1434 |
goto loop; |
||
1435 |
} |
||
1436 |
✗✓ | 6879 |
if (c == '\n') |
1437 |
unterminated_string(s_lineno, s_line, s_cptr); |
||
1438 |
✓✓ | 6879 |
if (c == '\\') { |
1439 |
2 |
c = (unsigned char) *cptr++; |
|
1440 |
✓✗ | 4 |
putc(c, f); |
1441 |
✗✓ | 2 |
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 |
93 |
c = (unsigned char) *cptr; |
|
1452 |
✗✓ | 93 |
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 |
✓✓ | 93 |
if (c == '*') { |
1464 |
84 |
int c_lineno = lineno; |
|
1465 |
84 |
char *c_line = dup_line(); |
|
1466 |
84 |
char *c_cptr = c_line + (cptr - line - 1); |
|
1467 |
|||
1468 |
✓✗ | 168 |
putc('*', f); |
1469 |
84 |
++cptr; |
|
1470 |
4951 |
for (;;) { |
|
1471 |
4951 |
c = (unsigned char) *cptr++; |
|
1472 |
✓✗ | 9902 |
putc(c, f); |
1473 |
✓✓✓✓ |
5093 |
if (c == '*' && *cptr == '/') { |
1474 |
✓✗ | 168 |
putc('/', f); |
1475 |
84 |
++cptr; |
|
1476 |
84 |
free(c_line); |
|
1477 |
goto loop; |
||
1478 |
} |
||
1479 |
✓✓ | 4867 |
if (c == '\n') { |
1480 |
79 |
get_line(); |
|
1481 |
✗✓ | 79 |
if (line == NULL) |
1482 |
unterminated_comment(c_lineno, c_line, c_cptr); |
||
1483 |
} |
||
1484 |
} |
||
1485 |
} |
||
1486 |
9 |
goto loop; |
|
1487 |
|||
1488 |
default: |
||
1489 |
39536 |
goto loop; |
|
1490 |
} |
||
1491 |
824 |
} |
|
1492 |
|||
1493 |
|||
1494 |
int |
||
1495 |
mark_symbol(void) |
||
1496 |
{ |
||
1497 |
int c; |
||
1498 |
bucket *bp = NULL; |
||
1499 |
|||
1500 |
30 |
c = (unsigned char) cptr[1]; |
|
1501 |
✓✓ | 15 |
if (c == '%' || c == '\\') { |
1502 |
9 |
cptr += 2; |
|
1503 |
9 |
return (1); |
|
1504 |
} |
||
1505 |
✓✗ | 6 |
if (c == '=') |
1506 |
cptr += 2; |
||
1507 |
✓✗✗✓ |
12 |
else if ((c == 'p' || c == 'P') && |
1508 |
✓✗ | 6 |
((c = cptr[2]) == 'r' || c == 'R') && |
1509 |
✓✗ | 6 |
((c = cptr[3]) == 'e' || c == 'E') && |
1510 |
✓✗ | 6 |
((c = cptr[4]) == 'c' || c == 'C') && |
1511 |
✓✗ | 18 |
((c = (unsigned char) cptr[5], !IS_IDENT(c)))) |
1512 |
cptr += 5; |
||
1513 |
else |
||
1514 |
syntax_error(lineno, line, cptr); |
||
1515 |
|||
1516 |
6 |
c = nextc(); |
|
1517 |
✓✗ | 6 |
if (isalpha(c) || c == '_' || c == '.' || c == '$') |
1518 |
6 |
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 |
✗✓✗✗ |
6 |
if (rprec[nrules] != UNDEFINED && bp->prec != rprec[nrules]) |
1527 |
prec_redeclared(); |
||
1528 |
|||
1529 |
6 |
rprec[nrules] = bp->prec; |
|
1530 |
6 |
rassoc[nrules] = bp->assoc; |
|
1531 |
6 |
return (0); |
|
1532 |
15 |
} |
|
1533 |
|||
1534 |
|||
1535 |
void |
||
1536 |
read_grammar(void) |
||
1537 |
{ |
||
1538 |
int c; |
||
1539 |
|||
1540 |
18 |
initialize_grammar(); |
|
1541 |
9 |
advance_to_start(); |
|
1542 |
|||
1543 |
4213 |
for (;;) { |
|
1544 |
4213 |
c = nextc(); |
|
1545 |
✓✗ | 4213 |
if (c == EOF) |
1546 |
break; |
||
1547 |
✓✓ | 8426 |
if (isalpha(c) || c == '_' || c == '.' || c == '$' || c == '\'' || |
1548 |
4213 |
c == '"') |
|
1549 |
2711 |
add_symbol(); |
|
1550 |
✓✓ | 1502 |
else if (c == '{' || c == '=') |
1551 |
824 |
copy_action(); |
|
1552 |
✓✓ | 678 |
else if (c == '|') { |
1553 |
663 |
end_rule(); |
|
1554 |
663 |
start_rule(plhs[nrules - 1], 0); |
|
1555 |
663 |
++cptr; |
|
1556 |
✓✗ | 678 |
} else if (c == '%') { |
1557 |
✓✓ | 15 |
if (mark_symbol()) |
1558 |
break; |
||
1559 |
} else |
||
1560 |
syntax_error(lineno, line, cptr); |
||
1561 |
} |
||
1562 |
9 |
end_rule(); |
|
1563 |
9 |
} |
|
1564 |
|||
1565 |
|||
1566 |
void |
||
1567 |
free_tags(void) |
||
1568 |
{ |
||
1569 |
int i; |
||
1570 |
|||
1571 |
✗✓ | 18 |
if (tag_table == NULL) |
1572 |
return; |
||
1573 |
|||
1574 |
✓✓ | 88 |
for (i = 0; i < ntags; ++i) { |
1575 |
✗✓ | 35 |
assert(tag_table[i]); |
1576 |
35 |
free(tag_table[i]); |
|
1577 |
} |
||
1578 |
9 |
free(tag_table); |
|
1579 |
18 |
} |
|
1580 |
|||
1581 |
|||
1582 |
void |
||
1583 |
pack_names(void) |
||
1584 |
{ |
||
1585 |
bucket *bp; |
||
1586 |
char *p, *s, *t; |
||
1587 |
|||
1588 |
18 |
name_pool_size = 13; /* 13 == sizeof("$end") + sizeof("$accept") */ |
|
1589 |
✓✓ | 1680 |
for (bp = first_symbol; bp; bp = bp->next) |
1590 |
831 |
name_pool_size += strlen(bp->name) + 1; |
|
1591 |
9 |
name_pool = malloc(name_pool_size); |
|
1592 |
✗✓ | 9 |
if (name_pool == NULL) |
1593 |
no_space(); |
||
1594 |
|||
1595 |
9 |
strlcpy(name_pool, "$accept", name_pool_size); |
|
1596 |
9 |
strlcpy(name_pool + 8, "$end", name_pool_size - 8); |
|
1597 |
9 |
t = name_pool + 13; |
|
1598 |
✓✓ | 1680 |
for (bp = first_symbol; bp; bp = bp->next) { |
1599 |
p = t; |
||
1600 |
831 |
s = bp->name; |
|
1601 |
✓✓ | 5763 |
while ((*t++ = *s++)) |
1602 |
4101 |
continue; |
|
1603 |
831 |
free(bp->name); |
|
1604 |
831 |
bp->name = p; |
|
1605 |
} |
||
1606 |
9 |
} |
|
1607 |
|||
1608 |
|||
1609 |
void |
||
1610 |
check_symbols(void) |
||
1611 |
{ |
||
1612 |
bucket *bp; |
||
1613 |
|||
1614 |
✗✓ | 18 |
if (goal->class == UNKNOWN) |
1615 |
undefined_goal(goal->name); |
||
1616 |
|||
1617 |
✓✓ | 1680 |
for (bp = first_symbol; bp; bp = bp->next) { |
1618 |
✗✓ | 831 |
if (bp->class == UNKNOWN) { |
1619 |
undefined_symbol_warning(bp->name); |
||
1620 |
bp->class = TERM; |
||
1621 |
} |
||
1622 |
} |
||
1623 |
9 |
} |
|
1624 |
|||
1625 |
|||
1626 |
void |
||
1627 |
pack_symbols(void) |
||
1628 |
{ |
||
1629 |
bucket *bp; |
||
1630 |
bucket **v; |
||
1631 |
int i, j, k, n; |
||
1632 |
|||
1633 |
18 |
nsyms = 2; |
|
1634 |
9 |
ntokens = 1; |
|
1635 |
✓✓ | 1680 |
for (bp = first_symbol; bp; bp = bp->next) { |
1636 |
831 |
++nsyms; |
|
1637 |
✓✓ | 831 |
if (bp->class == TERM) |
1638 |
600 |
++ntokens; |
|
1639 |
} |
||
1640 |
9 |
start_symbol = ntokens; |
|
1641 |
9 |
nvars = nsyms - ntokens; |
|
1642 |
|||
1643 |
9 |
symbol_name = reallocarray(NULL, nsyms, sizeof(char *)); |
|
1644 |
✗✓ | 9 |
if (symbol_name == NULL) |
1645 |
no_space(); |
||
1646 |
9 |
symbol_value = reallocarray(NULL, nsyms, sizeof(short)); |
|
1647 |
✗✓ | 9 |
if (symbol_value == NULL) |
1648 |
no_space(); |
||
1649 |
9 |
symbol_prec = reallocarray(NULL, nsyms, sizeof(short)); |
|
1650 |
✗✓ | 9 |
if (symbol_prec == NULL) |
1651 |
no_space(); |
||
1652 |
9 |
symbol_assoc = malloc(nsyms); |
|
1653 |
✗✓ | 9 |
if (symbol_assoc == NULL) |
1654 |
no_space(); |
||
1655 |
|||
1656 |
9 |
v = reallocarray(NULL, nsyms, sizeof(bucket *)); |
|
1657 |
✗✓ | 9 |
if (v == NULL) |
1658 |
no_space(); |
||
1659 |
|||
1660 |
9 |
v[0] = 0; |
|
1661 |
9 |
v[start_symbol] = 0; |
|
1662 |
|||
1663 |
i = 1; |
||
1664 |
9 |
j = start_symbol + 1; |
|
1665 |
✓✓ | 1680 |
for (bp = first_symbol; bp; bp = bp->next) { |
1666 |
✓✓ | 831 |
if (bp->class == TERM) |
1667 |
600 |
v[i++] = bp; |
|
1668 |
else |
||
1669 |
231 |
v[j++] = bp; |
|
1670 |
} |
||
1671 |
✓✗✗✓ |
18 |
assert(i == ntokens && j == nsyms); |
1672 |
|||
1673 |
✓✓ | 1218 |
for (i = 1; i < ntokens; ++i) |
1674 |
600 |
v[i]->index = i; |
|
1675 |
|||
1676 |
9 |
goal->index = start_symbol + 1; |
|
1677 |
9 |
k = start_symbol + 2; |
|
1678 |
✓✓ | 480 |
while (++i < nsyms) |
1679 |
✓✓ | 231 |
if (v[i] != goal) { |
1680 |
222 |
v[i]->index = k; |
|
1681 |
222 |
++k; |
|
1682 |
222 |
} |
|
1683 |
9 |
goal->value = 0; |
|
1684 |
k = 1; |
||
1685 |
✓✓ | 480 |
for (i = start_symbol + 1; i < nsyms; ++i) { |
1686 |
✓✓ | 231 |
if (v[i] != goal) { |
1687 |
222 |
v[i]->value = k; |
|
1688 |
222 |
++k; |
|
1689 |
222 |
} |
|
1690 |
} |
||
1691 |
|||
1692 |
k = 0; |
||
1693 |
✓✓ | 1218 |
for (i = 1; i < ntokens; ++i) { |
1694 |
600 |
n = v[i]->value; |
|
1695 |
✗✓ | 600 |
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 |
✓✗ | 9 |
if (v[1]->value == UNDEFINED) |
1703 |
9 |
v[1]->value = 256; |
|
1704 |
|||
1705 |
j = 0; |
||
1706 |
n = 257; |
||
1707 |
✓✓ | 1200 |
for (i = 2; i < ntokens; ++i) { |
1708 |
✓✓ | 591 |
if (v[i]->value == UNDEFINED) { |
1709 |
✗✓✗✗ |
1122 |
while (j < k && n == symbol_value[j]) { |
1710 |
while (++j < k && n == symbol_value[j]) |
||
1711 |
continue; |
||
1712 |
++n; |
||
1713 |
} |
||
1714 |
561 |
v[i]->value = n; |
|
1715 |
561 |
++n; |
|
1716 |
561 |
} |
|
1717 |
} |
||
1718 |
|||
1719 |
9 |
symbol_name[0] = name_pool + 8; |
|
1720 |
9 |
symbol_value[0] = 0; |
|
1721 |
9 |
symbol_prec[0] = 0; |
|
1722 |
9 |
symbol_assoc[0] = TOKEN; |
|
1723 |
✓✓ | 1218 |
for (i = 1; i < ntokens; ++i) { |
1724 |
600 |
symbol_name[i] = v[i]->name; |
|
1725 |
600 |
symbol_value[i] = v[i]->value; |
|
1726 |
600 |
symbol_prec[i] = v[i]->prec; |
|
1727 |
600 |
symbol_assoc[i] = v[i]->assoc; |
|
1728 |
} |
||
1729 |
9 |
symbol_name[start_symbol] = name_pool; |
|
1730 |
9 |
symbol_value[start_symbol] = -1; |
|
1731 |
9 |
symbol_prec[start_symbol] = 0; |
|
1732 |
9 |
symbol_assoc[start_symbol] = TOKEN; |
|
1733 |
✓✓ | 480 |
for (++i; i < nsyms; ++i) { |
1734 |
231 |
k = v[i]->index; |
|
1735 |
231 |
symbol_name[k] = v[i]->name; |
|
1736 |
231 |
symbol_value[k] = v[i]->value; |
|
1737 |
231 |
symbol_prec[k] = v[i]->prec; |
|
1738 |
231 |
symbol_assoc[k] = v[i]->assoc; |
|
1739 |
} |
||
1740 |
|||
1741 |
9 |
free(v); |
|
1742 |
9 |
} |
|
1743 |
|||
1744 |
|||
1745 |
void |
||
1746 |
pack_grammar(void) |
||
1747 |
{ |
||
1748 |
int i, j; |
||
1749 |
int assoc, pprec; |
||
1750 |
|||
1751 |
18 |
ritem = reallocarray(NULL, nitems, sizeof(short)); |
|
1752 |
✗✓ | 9 |
if (ritem == NULL) |
1753 |
no_space(); |
||
1754 |
9 |
rlhs = reallocarray(NULL, nrules, sizeof(short)); |
|
1755 |
✗✓ | 9 |
if (rlhs == NULL) |
1756 |
no_space(); |
||
1757 |
9 |
rrhs = reallocarray(NULL, nrules + 1, sizeof(short)); |
|
1758 |
✗✓ | 9 |
if (rrhs == NULL) |
1759 |
no_space(); |
||
1760 |
9 |
rprec = reallocarray(rprec, nrules, sizeof(short)); |
|
1761 |
✗✓ | 9 |
if (rprec == NULL) |
1762 |
no_space(); |
||
1763 |
9 |
rassoc = realloc(rassoc, nrules); |
|
1764 |
✗✓ | 9 |
if (rassoc == NULL) |
1765 |
no_space(); |
||
1766 |
|||
1767 |
9 |
ritem[0] = -1; |
|
1768 |
9 |
ritem[1] = goal->index; |
|
1769 |
9 |
ritem[2] = 0; |
|
1770 |
9 |
ritem[3] = -2; |
|
1771 |
9 |
rlhs[0] = 0; |
|
1772 |
9 |
rlhs[1] = 0; |
|
1773 |
9 |
rlhs[2] = start_symbol; |
|
1774 |
9 |
rrhs[0] = 0; |
|
1775 |
9 |
rrhs[1] = 0; |
|
1776 |
9 |
rrhs[2] = 1; |
|
1777 |
|||
1778 |
j = 4; |
||
1779 |
✓✓ | 1806 |
for (i = 3; i < nrules; ++i) { |
1780 |
894 |
rlhs[i] = plhs[i]->index; |
|
1781 |
894 |
rrhs[i] = j; |
|
1782 |
assoc = TOKEN; |
||
1783 |
pprec = 0; |
||
1784 |
✓✓ | 6886 |
while (pitem[j]) { |
1785 |
2549 |
ritem[j] = pitem[j]->index; |
|
1786 |
✓✓ | 2549 |
if (pitem[j]->class == TERM) { |
1787 |
1723 |
pprec = pitem[j]->prec; |
|
1788 |
1723 |
assoc = pitem[j]->assoc; |
|
1789 |
1723 |
} |
|
1790 |
2549 |
++j; |
|
1791 |
} |
||
1792 |
894 |
ritem[j] = -i; |
|
1793 |
894 |
++j; |
|
1794 |
✓✓ | 894 |
if (rprec[i] == UNDEFINED) { |
1795 |
858 |
rprec[i] = pprec; |
|
1796 |
858 |
rassoc[i] = assoc; |
|
1797 |
858 |
} |
|
1798 |
} |
||
1799 |
9 |
rrhs[i] = j; |
|
1800 |
|||
1801 |
9 |
free(plhs); |
|
1802 |
9 |
free(pitem); |
|
1803 |
9 |
} |
|
1804 |
|||
1805 |
|||
1806 |
void |
||
1807 |
print_grammar(void) |
||
1808 |
{ |
||
1809 |
int i, j, k; |
||
1810 |
int spacing = 0; |
||
1811 |
18 |
FILE *f = verbose_file; |
|
1812 |
|||
1813 |
✓✗ | 9 |
if (!vflag) |
1814 |
9 |
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 |
9 |
} |
|
1839 |
|||
1840 |
|||
1841 |
void |
||
1842 |
reader(void) |
||
1843 |
{ |
||
1844 |
18 |
write_section(banner); |
|
1845 |
9 |
create_symbol_table(); |
|
1846 |
9 |
read_declarations(); |
|
1847 |
9 |
read_grammar(); |
|
1848 |
9 |
free_symbol_table(); |
|
1849 |
9 |
free_tags(); |
|
1850 |
9 |
pack_names(); |
|
1851 |
9 |
check_symbols(); |
|
1852 |
9 |
pack_symbols(); |
|
1853 |
9 |
pack_grammar(); |
|
1854 |
9 |
free_symbols(); |
|
1855 |
9 |
print_grammar(); |
|
1856 |
9 |
} |
Generated by: GCOVR (Version 3.3) |