blob: 88744ff102956c4fc6f87b02998da5af66a77982 [file] [log] [blame]
Ed Warnickecb9cada2015-12-08 15:45:58 -07001/*
2 *------------------------------------------------------------------
3 * lex.c - API generator lexical analyzer
4 *
5 * Copyright (c) 1996-2009 Cisco and/or its affiliates.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at:
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *------------------------------------------------------------------
18 */
19
20#include <stdio.h>
21#include <ctype.h>
22#include <time.h>
23#include <string.h>
24#include <unistd.h>
25#include <stdlib.h>
26
27#include "lex.h"
28#include "node.h"
29#include "gram.h"
30
Marek Gradzki948b95a2016-07-20 14:53:48 +020031FILE *ifp, *ofp, *pythonfp;
Ed Warnickecb9cada2015-12-08 15:45:58 -070032char *vlib_app_name = "vpp";
33int dump_tree;
34time_t starttime;
35char *input_filename;
36char *current_filename;
37int current_filename_allocated;
38unsigned long input_crc;
39int yydebug;
40
41/*
42 * lexer variable definitions
43 */
44
45static const char *version = "0.1";
46static int the_lexer_linenumber = 1;
47static enum lex_state the_lexer_state = START_STATE;
48
49/*
50 * private prototypes
51 */
52static void usage (char *);
53static int name_check (const char *, YYSTYPE *);
54static int name_compare (const char *, const char *);
55extern int yydebug;
Vincent JARDINa5584252016-03-05 00:56:06 +010056extern YYSTYPE yylval;
Ed Warnickecb9cada2015-12-08 15:45:58 -070057
58unsigned int crc32c_table[256] = {
59 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4,
60 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB,
61 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B,
62 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24,
63 0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B,
64 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384,
65 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54,
66 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B,
67 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A,
68 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35,
69 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5,
70 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA,
71 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45,
72 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A,
73 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A,
74 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595,
75 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48,
76 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957,
77 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687,
78 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198,
79 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927,
80 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38,
81 0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8,
82 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7,
83 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096,
84 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789,
85 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859,
86 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46,
87 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9,
88 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6,
89 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36,
90 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829,
91 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C,
92 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93,
93 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043,
94 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C,
95 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3,
96 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC,
97 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C,
98 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033,
99 0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652,
100 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D,
101 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D,
102 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982,
103 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D,
104 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622,
105 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2,
106 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED,
107 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530,
108 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F,
109 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF,
110 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0,
111 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F,
112 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540,
113 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90,
114 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F,
115 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE,
116 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1,
117 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321,
118 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E,
119 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81,
120 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E,
121 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E,
122 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351
123};
124
125static inline unsigned long CRC8 (unsigned long crc,
126 unsigned char d)
127{
128 return ((crc >> 8) ^ crc32c_table[(crc ^ d) & 0xFF]);
129}
130static inline unsigned long CRC16 (unsigned long crc,
131 unsigned short d)
132{
133 crc = CRC8 (crc, d & 0xff);
134 d = d >> 8;
135 crc = CRC8 (crc, d & 0xff);
136 return crc;
137}
138
139
140static unsigned long
141crc_eliding_c_comments (const char *buf, unsigned long crc)
142{
143 const char *p;
144 enum { cOTHER, /* */
145 cSTRING, /* "... */
146 cSBACKSLASH, /* "...\ */
147 cCHAR, /* '... */
148 cCBACKSLASH, /* '...\ */
149 cSLASH, /* / */
150 cSLASH_SLASH, /* //... */
151 cSLASH_STAR, /* / *... */
152 cSTAR /* / *...* */
153 } ss = cOTHER;
154
155 for (p = buf; ;) {
156 unsigned char c = *p++;
157
158 switch (c) {
159 case 0:
160 switch (ss) {
161 case cOTHER:
162 return (crc);
163 case cSTRING: case cSBACKSLASH:
164 case cCHAR: case cCBACKSLASH:
165 case cSLASH: case cSLASH_SLASH: case cSLASH_STAR: case cSTAR:
166 fprintf (stderr, "Inopportune EOF: %s\n", buf);
167 exit (1);
168 }
169 break;
170 case '\"':
171 switch (ss) {
172 case cOTHER: ss = cSTRING; break; /* start string */
173 case cSTRING: ss = cOTHER; break; /* end string */
174 case cSBACKSLASH: ss = cSTRING; break;
175 case cCHAR: break;
176 case cCBACKSLASH: ss = cCHAR; break;
177 case cSLASH: crc = CRC8 (crc, '/'); ss = cOTHER; break;
178 case cSLASH_SLASH: continue; /* in comment */
179 case cSLASH_STAR: continue; /* in comment */
180 case cSTAR: ss = cSLASH_STAR; continue; /* in comment */
181 }
182 break;
183 case '\\':
184 switch (ss) {
185 case cOTHER: break;
186 case cSTRING: ss = cSBACKSLASH; break;
187 case cSBACKSLASH: ss = cSTRING; break;
188 case cCHAR: ss = cCBACKSLASH; break;
189 case cCBACKSLASH: ss = cCHAR; break;
190 case cSLASH: crc = CRC8 (crc, '/'); ; ss = cOTHER; break;
191 case cSLASH_SLASH: continue; /* in comment */
192 case cSLASH_STAR: continue; /* in comment */
193 case cSTAR: ss = cSLASH_STAR; continue; /* in comment */
194 }
195 break;
196 case '/':
197 switch (ss) {
198 case cOTHER: ss = cSLASH; continue; /* potential comment */
199 case cSTRING: break;
200 case cSBACKSLASH: ss = cSTRING; break;
201 case cCHAR: break;
202 case cCBACKSLASH: ss = cCHAR; break;
203 case cSLASH: ss = cSLASH_SLASH; continue; /* start comment */
204 case cSLASH_SLASH: continue; /* in comment */
205 case cSLASH_STAR: continue; /* in comment */
206 case cSTAR: ss = cOTHER; continue; /* end of comment */
207 }
208 break;
209 case '*':
210 switch (ss) {
211 case cOTHER: break;
212 case cSTRING: break;
213 case cSBACKSLASH: ss = cSTRING; break;
214 case cCHAR: break;
215 case cCBACKSLASH: ss = cCHAR; break;
216 case cSLASH: ss = cSLASH_STAR; continue; /* start comment */
217 case cSLASH_SLASH: continue; /* in comment */
218 case cSLASH_STAR: ss = cSTAR; continue; /* potential end */
219 case cSTAR: continue; /* still potential end of comment */
220 }
221 break;
222 case '\n': case '\r': case ' ': case '\t': case '\014':
223 switch (ss) {
224 case cOTHER: continue; /* ignore all whitespace */
225 case cSTRING: break;
226 case cSBACKSLASH: ss = cSTRING; break;
227 case cCHAR: break;
228 case cCBACKSLASH: ss = cCHAR; break;
229 case cSLASH: c = '/'; ss = cOTHER; break;
230 case cSLASH_SLASH:
231 if (c == '\n' || c == '\r') ss = cOTHER; /* end comment */
232 continue;
233 case cSLASH_STAR: continue; /* in comment */
234 case cSTAR: ss = cSLASH_STAR; continue; /* in comment */
235 }
236 default:
237 switch (ss) {
238 case cOTHER: break;
239 case cSTRING: break;
240 case cSBACKSLASH: ss = cSTRING; break;
241 case cCHAR: break;
242 case cCBACKSLASH: ss = cCHAR; break;
243 case cSLASH: crc = CRC8 (crc, '/'); ss = cOTHER; break;
244 case cSLASH_SLASH: continue; /* in comment */
245 case cSLASH_STAR: continue; /* in comment */
246 case cSTAR: ss = cSLASH_STAR; continue; /* in comment */
247 }
248 }
249 crc = CRC8 (crc, c);
250 }
251}
252
253/*
254 * main
255 */
256int main (int argc, char **argv)
257{
258 int curarg = 1;
259 char *ofile=0;
Ole Troan6855f6c2016-04-09 03:16:30 +0200260 char *pythonfile=0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700261 char *show_name=0;
262
263 while (curarg < argc) {
264 if (!strncmp (argv [curarg], "--verbose", 3)) {
265 fprintf (stderr, "%s version %s\n", argv [0], version);
266 curarg++;
267 continue;
268 }
269
270 if (!strncmp (argv [curarg], "--yydebug", 3)) {
271 yydebug = 1;
272 curarg++;
273 continue;
274 }
275
276 if (!strncmp (argv [curarg], "--dump", 3)) {
277 dump_tree = 1;
278 curarg++;
279 continue;
280 }
281
282 if (!strncmp (argv[curarg], "--show-name", 3)) {
283 curarg++;
284 if (curarg < argc) {
285 show_name = argv[curarg];
286 curarg++;
287 continue;
288 } else {
289 fprintf(stderr, "Missing filename after --show-name \n");
290 exit(1);
291 }
292 }
293
294 if (!strncmp (argv [curarg], "--input", 3)) {
295 curarg++;
296 if (curarg < argc) {
297 input_filename = argv[curarg];
298 if (!strcmp (argv [curarg], "-"))
299 ifp = stdin;
300 else
301 ifp = fopen (argv [curarg], "r");
302 if (ifp == NULL) {
303 fprintf (stderr, "Couldn't open input file %s\n",
304 argv[curarg]);
305 exit (1);
306 }
307 curarg++;
308 } else {
309 fprintf(stderr, "Missing filename after --input\n");
310 exit(1);
311 }
312 continue;
313 }
314 if (!strncmp (argv [curarg], "--output", 3)) {
315 curarg++;
316 if (curarg < argc) {
317 ofp = fopen (argv[curarg], "w");
318 if (ofp == NULL) {
319 fprintf (stderr, "Couldn't open output file %s\n",
320 argv[curarg]);
321 exit (1);
322 }
323 ofile = argv[curarg];
324 curarg++;
325 } else {
326 fprintf(stderr, "Missing filename after --output\n");
327 exit(1);
328 }
329 continue;
330 }
Ole Troan6855f6c2016-04-09 03:16:30 +0200331 if (!strncmp (argv [curarg], "--python", 8)) {
332 curarg++;
333 if (curarg < argc) {
334 pythonfp = fopen (argv[curarg], "w");
335 if (pythonfp == NULL) {
336 fprintf (stderr, "Couldn't open python output file %s\n",
337 argv[curarg]);
338 exit (1);
339 }
340 pythonfile = argv[curarg];
341 curarg++;
342 } else {
343 fprintf(stderr, "Missing filename after --python\n");
344 exit(1);
345 }
346 continue;
347 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700348 if (!strncmp (argv [curarg], "--app", 4)) {
349 curarg++;
350 if (curarg < argc) {
351 vlib_app_name = argv[curarg];
352 curarg++;
353 } else {
354 fprintf(stderr, "Missing app name after --app\n");
355 exit(1);
356 }
357 continue;
358 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700359
360 usage(argv[0]);
361 exit (1);
362 }
363 if (ofp == NULL) {
364 ofile = 0;
365 }
Ole Troan6855f6c2016-04-09 03:16:30 +0200366 if (pythonfp == NULL) {
367 pythonfile = 0;
368 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700369 if (ifp == NULL) {
370 fprintf(stderr, "No input file specified...\n");
371 exit(1);
372 }
373 if (show_name) {
374 input_filename = show_name;
375 }
376
377 starttime = time (0);
378
379 if (yyparse() == 0) {
380 fclose (ifp);
381 curarg -= 2;
382 if (ofile) {
383 printf ("Output written to %s\n", ofile);
384 fclose (ofp);
385 }
Ole Troan6855f6c2016-04-09 03:16:30 +0200386 if (pythonfile) {
387 printf ("Python bindings written to %s\n", pythonfile);
388 fclose (pythonfp);
389 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700390 }
391 else {
392 fclose (ifp);
Dave Barachf9c231e2016-08-05 10:10:18 -0400393 if (ofp)
394 fclose (ofp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700395 if (ofile) {
396 printf ("Removing %s\n", ofile);
397 unlink (ofile);
398 }
Ole Troan6855f6c2016-04-09 03:16:30 +0200399 if (pythonfile) {
400 printf ("Removing %s\n", pythonfile);
401 unlink (pythonfile);
402 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700403 exit (1);
404 }
405 exit (0);
406}
407
408/*
409 * usage
410 */
411static void usage (char *progname)
412{
413 fprintf (stderr,
Ole Troan6855f6c2016-04-09 03:16:30 +0200414 "usage: %s --input <filename> [--output <filename>] [--python <filename>]\n%s",
Ed Warnickecb9cada2015-12-08 15:45:58 -0700415 progname,
416 " [--yydebug] [--dump-tree]\n");
417 exit (1);
418}
419
420/*
421 * yyerror
422 */
423void yyerror (char *s)
424{
425 fprintf (stderr, "%s:%d %s\n", current_filename, the_lexer_linenumber, s);
426}
427
428static char namebuf [MAXNAME];
429
Dave Barachf9c231e2016-08-05 10:10:18 -0400430static inline char
431getc_char (FILE *ifp)
432{
433 return ((char)(getc(ifp) & 0x7f));
434}
435
Ed Warnickecb9cada2015-12-08 15:45:58 -0700436/*
437 * yylex (well, yylex_1: The real yylex below does crc-hackery)
438 */
439static int yylex_1 (void)
440{
441 int nameidx=0;
442 char c;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700443 enum { LP_INITIAL_WHITESPACE, LP_LINE_NUMBER,
444 LP_PRE_FILENAME_WHITESPACE, LP_FILENAME,
445 LP_POST_FILENAME,
446 LP_OTHER
447 } lp_substate = LP_INITIAL_WHITESPACE;
448
449 again:
450 switch (the_lexer_state) {
451 /*
452 * START state -- looking for something interesting
453 */
454 case START_STATE:
Dave Barachf9c231e2016-08-05 10:10:18 -0400455 c = getc_char (ifp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700456 if (feof (ifp))
457 return (EOF);
458
459 switch (c) {
460 case '\n':
461 the_lexer_linenumber++;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700462 goto again;
463
464 case '#':
Ed Warnickecb9cada2015-12-08 15:45:58 -0700465 the_lexer_state = LINE_PRAGMA_STATE;
466 lp_substate = LP_INITIAL_WHITESPACE;
467 goto again;
468
469 /* FALLTHROUGH */
470 case '\t':
471 case ' ':
472 goto again;
473
474 case '(':
475 return (LPAR);
476
477 case ')':
478 return (RPAR);
479
480 case ';':
481 return (SEMI);
482
483 case '[':
484 return (LBRACK);
485
486 case ']':
487 return (RBRACK);
488
489 case '{':
490 return (LCURLY);
491
492 case '}':
493 return (RCURLY);
494
495 case ',':
496 return (COMMA);
497
498 case '"':
499 nameidx = 0;
500 the_lexer_state = STRING_STATE;
501 goto again;
502
503 case '@':
504 nameidx = 0;
505 the_lexer_state = HELPER_STATE;
506 goto again;
507
508 case '/':
Dave Barachf9c231e2016-08-05 10:10:18 -0400509 c = getc_char (ifp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700510 if (feof (ifp))
511 return (EOF);
512
513 if (c == '/') {
514 the_lexer_state = CPP_COMMENT_STATE;
515 goto again;
516 } else if (c == '*') {
517 the_lexer_state = C_COMMENT_STATE;
518 goto again;
519 } else {
520 fprintf (stderr, "unknown token /%c at line %d\n",
521 c, the_lexer_linenumber);
522 return (BARF);
523 }
524
525 case '\\':
Dave Barachf9c231e2016-08-05 10:10:18 -0400526 c = getc_char (ifp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700527 if (feof (ifp))
528 return (EOF);
529
530 /* Note fallthrough... */
531
532 default:
533 if (isalpha (c) || c == '_') {
534 namebuf [0] = c;
535 nameidx = 1;
536 the_lexer_state = NAME_STATE;
537 goto again;
538 } else if (isdigit(c)) {
539 namebuf [0] = c;
540 nameidx = 1;
541 the_lexer_state = NUMBER_STATE;
542 goto again;
543 }
544
545 fprintf (stderr, "unknown token %c at line %d\n",
546 c, the_lexer_linenumber);
547 return (BARF);
548 }
549
550 /*
551 * NAME state -- eat the rest of a name
552 */
553 case NAME_STATE:
Dave Barachf9c231e2016-08-05 10:10:18 -0400554 c = getc_char (ifp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700555 if (feof (ifp))
556 return (EOF);
557
558 if (!isalnum (c) && c != '_') {
559 ungetc (c, ifp);
560 namebuf [nameidx] = 0;
561 the_lexer_state = START_STATE;
562 return (name_check (namebuf, &yylval));
563 }
564 if (nameidx >= (MAXNAME-1)) {
565 fprintf(stderr, "lex input buffer overflow...\n");
566 exit(1);
567 }
568 namebuf [nameidx++] = c;
569 goto again;
570
571 /*
572 * NUMBER state -- eat the rest of a number
573 */
574 case NUMBER_STATE:
Dave Barachf9c231e2016-08-05 10:10:18 -0400575 c = getc_char (ifp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700576 if (feof (ifp))
577 return (EOF);
578
579 if (!isdigit (c)) {
580 ungetc (c, ifp);
581 namebuf [nameidx] = 0;
582 the_lexer_state = START_STATE;
583 yylval = (void *) atol(namebuf);
584 return (NUMBER);
585 }
586 if (nameidx >= (MAXNAME-1)) {
587 fprintf(stderr, "lex input buffer overflow...\n");
588 exit(1);
589 }
590 namebuf [nameidx++] = c;
591 goto again;
592
593 /*
594 * C_COMMENT state -- eat a peach
595 */
596 case C_COMMENT_STATE:
Dave Barachf9c231e2016-08-05 10:10:18 -0400597 c = getc_char (ifp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700598 if (feof (ifp))
599 return (EOF);
600 if (c == '*') {
Dave Barachf9c231e2016-08-05 10:10:18 -0400601 c = getc_char (ifp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700602 if (feof (ifp))
603 return (EOF);
604 if (c == '/') {
605 the_lexer_state = START_STATE;
606 goto again;
607 }
608 }
609 if (c == '\n')
610 the_lexer_linenumber++;
611 goto again;
612
613 /*
614 * CPP_COMMENT state -- eat a plum
615 */
616
617 case CPP_COMMENT_STATE:
Dave Barachf9c231e2016-08-05 10:10:18 -0400618 c = getc_char (ifp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700619 if (feof (ifp))
620 return (EOF);
621 if (c == '\n') {
622 the_lexer_linenumber++;
623 the_lexer_state = START_STATE;
624 goto again;
625 }
626 goto again;
627
628 case STRING_STATE:
Dave Barachf9c231e2016-08-05 10:10:18 -0400629 c = getc_char (ifp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700630 if (feof (ifp))
631 return (EOF);
632 switch (c) {
633 case '\\':
Dave Barachf9c231e2016-08-05 10:10:18 -0400634 c = getc_char (ifp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700635 if (feof (ifp))
636 return (EOF);
637 namebuf[nameidx++] = c;
638 goto again;
639
640 case '"':
641 namebuf[nameidx] = 0;
642 yylval = (YYSTYPE) sxerox (namebuf);
643 the_lexer_state = START_STATE;
644 return (STRING);
645
646 default:
647 if (c == '\n')
648 the_lexer_linenumber++;
649
650 if (nameidx >= (MAXNAME-1)) {
651 fprintf(stderr, "lex input buffer overflow...\n");
652 exit(1);
653 }
654 namebuf[nameidx++] = c;
655 goto again;
656 }
657 break;
658
659 case HELPER_STATE:
Dave Barachf9c231e2016-08-05 10:10:18 -0400660 c = getc_char (ifp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700661 if (feof (ifp))
662 return (EOF);
663 switch (c) {
664 case '\\':
Dave Barachf9c231e2016-08-05 10:10:18 -0400665 c = getc_char (ifp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700666 if (feof (ifp))
667 return (EOF);
668 namebuf[nameidx] = c;
669 goto again;
670
671 case '@':
672 namebuf[nameidx] = 0;
673 yylval = (YYSTYPE) sxerox (namebuf);
674 the_lexer_state = START_STATE;
675 return (HELPER_STRING);
676
677 default:
678 if (c == '\n')
679 the_lexer_linenumber++;
680
681 /*
682 * CPP makes it approximately impossible to
683 * type "#define FOO 123", so we provide a
684 * lexical trick to achieve that result
685 */
686
687 if (c == '$')
688 c = '#';
689
690 if (nameidx >= (MAXNAME-1)) {
691 fprintf(stderr, "lex input buffer overflow...\n");
692 exit(1);
693 }
694 namebuf[nameidx++] = c;
695 goto again;
696 }
697 break;
698
699 case LINE_PRAGMA_STATE:
700 /* We're only interested in lines of the form # 259 "foo.c" 17 */
701
702 switch (lp_substate) {
703
704 case LP_INITIAL_WHITESPACE: /* no number seen yet */
Dave Barachf9c231e2016-08-05 10:10:18 -0400705 c = getc_char(ifp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700706 if (feof(ifp))
707 return(EOF);
708 if (c >= '0' && c <= '9') {
709 namebuf[nameidx++] = c;
710 lp_substate = LP_LINE_NUMBER;
711 } else if (c == '\n') {
712 goto lp_end_of_line;
713 } else if (c != ' ' && c != '\t') {
714 /* Nothing */
715 } else {
716 lp_substate = LP_OTHER;
717 }
718 goto again;
719
720 case LP_LINE_NUMBER: /* eating linenumber */
Dave Barachf9c231e2016-08-05 10:10:18 -0400721 c = getc_char(ifp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700722 if (feof(ifp))
723 return(EOF);
724 if (c >= '0' && c <= '9') {
725 namebuf[nameidx++] = c;
726 } else if (c == ' ' || c == '\t') {
727 namebuf[nameidx++] = 0;
728 the_lexer_linenumber = atol(namebuf);
729 lp_substate = LP_PRE_FILENAME_WHITESPACE;
730 } else if (c == '\n') {
731 goto lp_end_of_line;
732 } else {
733 lp_substate = LP_OTHER;
734 }
735 goto again;
736
737 case LP_PRE_FILENAME_WHITESPACE: /* awaiting filename */
Dave Barachf9c231e2016-08-05 10:10:18 -0400738 c = getc_char(ifp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700739 if (feof(ifp))
740 return(EOF);
741
742 if (c == '"') {
743 lp_substate = LP_FILENAME;
744 nameidx = 0;
745 } else if (c == ' ' || c == '\t') {
746 /* nothing */
747 } else if (c == '\n') {
748 goto lp_end_of_line;
749 } else {
750 lp_substate = LP_OTHER;
751 }
752 goto again;
753
754 case LP_FILENAME: /* eating filename */
Dave Barachf9c231e2016-08-05 10:10:18 -0400755 c = getc_char(ifp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700756 if (feof(ifp))
757 return(EOF);
758
759 if (c == '"') {
760 lp_substate = LP_POST_FILENAME;
761 namebuf[nameidx] = 0;
762 } else if (c == '\n') {
763 goto lp_end_of_line; /* syntax error... */
764 } else {
765 namebuf[nameidx++] = c;
766 }
767 goto again;
768
769 case LP_POST_FILENAME: /* ignoring rest of line */
770 case LP_OTHER:
Dave Barachf9c231e2016-08-05 10:10:18 -0400771 c = getc_char(ifp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700772 if (feof(ifp))
773 return(EOF);
774
775 if (c == '\n') {
776 if (lp_substate == LP_POST_FILENAME) {
777 if (current_filename_allocated) {
778 current_filename_allocated = 0;
779 free(current_filename);
780 }
781
782 if (!strcmp(namebuf, "<stdin>")) {
783 current_filename = input_filename;
784 } else {
785 current_filename = sxerox(namebuf);
786 current_filename_allocated = 1;
787 }
788 }
789 lp_end_of_line:
790 the_lexer_state = START_STATE;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700791 nameidx = 0;
792 }
793 goto again;
794 }
795 break;
796 }
797 fprintf (stderr, "LEXER BUG!\n");
798 exit (1);
799 /* NOTREACHED */
800 return (0);
801}
802
803/*
804 * Parse a token and side-effect input_crc
805 * in a whitespace- and comment-insensitive fashion.
806 */
807int yylex (void)
808{
809 /*
810 * Accumulate a crc32-based signature while processing the
811 * input file. The goal is to come up with a magic number
812 * which changes precisely when the original input file changes
813 * but which ignores whitespace changes.
814 */
815 unsigned long crc = input_crc;
816 int node_type = yylex_1 ();
817
818 switch (node_type) {
819 case PRIMTYPE:
820 case NAME:
821 case NUMBER:
822 case STRING:
823 case HELPER_STRING: {
824 /* We know these types accumulated token text into namebuf */
825 /* HELPER_STRING may still contain C comments. Argh. */
826 crc = crc_eliding_c_comments (namebuf, crc);
827 break;
828 }
829
830 /* Other node types have no "substate" */
831 /* This code is written in this curious fashion because we
832 * want the generated CRC to be independent of the particular
833 * values a particular version of lex/bison assigned to various states.
834 */
835
836 /* case NAME: crc = CRC16 (crc, 257); break; */
837 case RPAR: crc = CRC16 (crc, 258); break;
838 case LPAR: crc = CRC16 (crc, 259); break;
839 case SEMI: crc = CRC16 (crc, 260); break;
840 case LBRACK: crc = CRC16 (crc, 261); break;
841 case RBRACK: crc = CRC16 (crc, 262); break;
842 /* case NUMBER: crc = CRC16 (crc, 263); break; */
843 /* case PRIMTYPE: crc = CRC16 (crc, 264); break; */
844 case BARF: crc = CRC16 (crc, 265); break;
845 case TPACKED: crc = CRC16 (crc, 266); break;
846 case DEFINE: crc = CRC16 (crc, 267); break;
847 case LCURLY: crc = CRC16 (crc, 268); break;
848 case RCURLY: crc = CRC16 (crc, 269); break;
849 /* case STRING: crc = CRC16 (crc, 270); break; */
850 case UNION: crc = CRC16 (crc, 271); break;
851 /* case HELPER_STRING: crc = CRC16 (crc, 272); break; */
852 case COMMA: crc = CRC16 (crc, 273); break;
853 case NOVERSION: crc = CRC16 (crc, 274); break;
854 case MANUAL_PRINT: crc = CRC16 (crc, 275); break;
855 case MANUAL_ENDIAN: crc = CRC16 (crc, 276); break;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700856 case TYPEONLY: crc = CRC16 (crc, 278); break;
857 case DONT_TRACE: crc = CRC16 (crc, 279); break;
858
859 case EOF: crc = CRC16 (crc, ~0); break; /* hysterical compatibility */
860
861 default:
862 fprintf(stderr, "yylex: node_type %d missing state CRC cookie\n",
863 node_type);
864 exit(1);
865 }
866
867 input_crc = crc;
868 return (node_type);
869}
870
871
872/*
873 * name_check -- see if the name we just ate
874 * matches a known keyword. If so, set yylval
875 * to a new instance of <subclass of node>, and return PARSER_MACRO
876 *
877 * Otherwise, set yylval to sxerox (s) and return NAME
878 */
879
880static struct keytab {
881 char *name;
882 enum node_subclass subclass_id;
883} keytab [] =
884/* Keep the table sorted, binary search used below! */
885{
886 {"define", NODE_DEFINE},
887 {"dont_trace", NODE_DONT_TRACE},
888 {"f64", NODE_F64},
889 {"i16", NODE_I16},
890 {"i32", NODE_I32},
891 {"i64", NODE_I64},
892 {"i8", NODE_I8},
893 {"manual_endian", NODE_MANUAL_ENDIAN},
Ed Warnickecb9cada2015-12-08 15:45:58 -0700894 {"manual_print", NODE_MANUAL_PRINT},
895 {"noversion", NODE_NOVERSION},
896 {"packed", NODE_PACKED},
897 {"typeonly", NODE_TYPEONLY},
898 {"u16", NODE_U16},
899 {"u32", NODE_U32},
900 {"u64", NODE_U64},
901 {"u8", NODE_U8},
902 {"union", NODE_UNION},
903 {"uword", NODE_UWORD},
904};
905
906static int name_check (const char *s, YYSTYPE *token_value)
907{
908 enum node_subclass subclass_id;
909 int top, bot, mid;
910 int result;
911
912 for (top = 0, bot = (sizeof(keytab) / sizeof(struct keytab))-1;
913 bot >= top; ) {
914 mid = (top + bot) / 2;
915 result = name_compare (s, keytab[mid].name);
916 if (result < 0)
917 bot = mid - 1;
918 else if (result > 0)
919 top = mid + 1;
920 else {
921 subclass_id = keytab[mid].subclass_id;
922
923 switch (subclass_id) {
924 case NODE_U8:
925 case NODE_U16:
926 case NODE_U32:
927 case NODE_U64:
928 case NODE_I8:
929 case NODE_I16:
930 case NODE_I32:
931 case NODE_I64:
932 case NODE_F64:
933 case NODE_UWORD:
934 *token_value = make_node(subclass_id);
935 return (PRIMTYPE);
936
937 case NODE_PACKED:
938 *token_value = make_node(subclass_id);
939 return (TPACKED);
940
941 case NODE_DEFINE:
942 *token_value = make_node(subclass_id);
943 return(DEFINE);
944
945 case NODE_MANUAL_PRINT:
946 *token_value = (YYSTYPE) NODE_FLAG_MANUAL_PRINT;
947 return (MANUAL_PRINT);
948
949 case NODE_MANUAL_ENDIAN:
950 *token_value = (YYSTYPE) NODE_FLAG_MANUAL_ENDIAN;
951 return (MANUAL_ENDIAN);
952
Ed Warnickecb9cada2015-12-08 15:45:58 -0700953 case NODE_TYPEONLY:
954 *token_value = (YYSTYPE) NODE_FLAG_TYPEONLY;
955 return(TYPEONLY);
956
957 case NODE_DONT_TRACE:
958 *token_value = (YYSTYPE) NODE_FLAG_DONT_TRACE;
959 return(DONT_TRACE);
960
961 case NODE_NOVERSION:
962 return(NOVERSION);
963
964 case NODE_UNION:
965 return(UNION);
966
967 default:
968 fprintf (stderr, "fatal: keytab botch!\n");
969 exit (1);
970 }
971 }
972 }
973 *token_value = (YYSTYPE) sxerox (s);
974 return (NAME);
975}
976
977/*
978 * sxerox
979 */
980
981char *sxerox (const char *s)
982{
983 int len = strlen (s);
984 char *rv;
985
986 rv = (char *) malloc (len+1);
Dave Barachf9c231e2016-08-05 10:10:18 -0400987 if (rv == 0) {
988 fprintf(stderr, "Out of memory...");
989 exit (1);
990 }
991
Ed Warnickecb9cada2015-12-08 15:45:58 -0700992 strcpy (rv, s);
993 return (rv);
994}
995
996/*
997 * name_compare
998 */
999
1000int name_compare (const char *s1, const char *s2)
1001{
1002 char c1, c2;
1003
1004 while (*s1 && *s2) {
1005 c1 = *s1++;
1006 c2 = *s2++;
1007
1008 c1 = tolower (c1);
1009 c2 = tolower (c2);
1010 if (c1 < c2)
1011 return (-1);
1012 else if (c1 > c2)
1013 return (1);
1014 }
1015 if (*s1 < *s2)
1016 return (-1);
1017 else if (*s1 > *s2)
1018 return (1);
1019 return (0);
1020}