blob: e807d46b9a0ece7ce8d8def8e4004c557964ed5c [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
Dave Barach557d1282016-11-10 14:22:49 -050031FILE *ifp, *ofp, *pythonfp, *jsonfp;
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;
Dave Barach557d1282016-11-10 14:22:49 -050039unsigned long message_crc;
Ed Warnickecb9cada2015-12-08 15:45:58 -070040int yydebug;
41
42/*
43 * lexer variable definitions
44 */
45
46static const char *version = "0.1";
47static int the_lexer_linenumber = 1;
48static enum lex_state the_lexer_state = START_STATE;
49
50/*
51 * private prototypes
52 */
53static void usage (char *);
54static int name_check (const char *, YYSTYPE *);
55static int name_compare (const char *, const char *);
56extern int yydebug;
Vincent JARDINa5584252016-03-05 00:56:06 +010057extern YYSTYPE yylval;
Ed Warnickecb9cada2015-12-08 15:45:58 -070058
59unsigned int crc32c_table[256] = {
60 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4,
61 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB,
62 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B,
63 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24,
64 0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B,
65 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384,
66 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54,
67 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B,
68 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A,
69 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35,
70 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5,
71 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA,
72 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45,
73 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A,
74 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A,
75 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595,
76 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48,
77 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957,
78 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687,
79 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198,
80 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927,
81 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38,
82 0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8,
83 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7,
84 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096,
85 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789,
86 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859,
87 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46,
88 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9,
89 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6,
90 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36,
91 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829,
92 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C,
93 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93,
94 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043,
95 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C,
96 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3,
97 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC,
98 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C,
99 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033,
100 0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652,
101 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D,
102 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D,
103 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982,
104 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D,
105 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622,
106 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2,
107 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED,
108 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530,
109 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F,
110 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF,
111 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0,
112 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F,
113 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540,
114 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90,
115 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F,
116 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE,
117 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1,
118 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321,
119 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E,
120 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81,
121 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E,
122 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E,
123 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351
124};
125
126static inline unsigned long CRC8 (unsigned long crc,
127 unsigned char d)
128{
129 return ((crc >> 8) ^ crc32c_table[(crc ^ d) & 0xFF]);
130}
131static inline unsigned long CRC16 (unsigned long crc,
132 unsigned short d)
133{
134 crc = CRC8 (crc, d & 0xff);
135 d = d >> 8;
136 crc = CRC8 (crc, d & 0xff);
137 return crc;
138}
139
140
141static unsigned long
142crc_eliding_c_comments (const char *buf, unsigned long crc)
143{
144 const char *p;
145 enum { cOTHER, /* */
146 cSTRING, /* "... */
147 cSBACKSLASH, /* "...\ */
148 cCHAR, /* '... */
149 cCBACKSLASH, /* '...\ */
150 cSLASH, /* / */
151 cSLASH_SLASH, /* //... */
152 cSLASH_STAR, /* / *... */
153 cSTAR /* / *...* */
154 } ss = cOTHER;
155
156 for (p = buf; ;) {
157 unsigned char c = *p++;
158
159 switch (c) {
160 case 0:
161 switch (ss) {
162 case cOTHER:
163 return (crc);
164 case cSTRING: case cSBACKSLASH:
165 case cCHAR: case cCBACKSLASH:
166 case cSLASH: case cSLASH_SLASH: case cSLASH_STAR: case cSTAR:
167 fprintf (stderr, "Inopportune EOF: %s\n", buf);
168 exit (1);
169 }
170 break;
171 case '\"':
172 switch (ss) {
173 case cOTHER: ss = cSTRING; break; /* start string */
174 case cSTRING: ss = cOTHER; break; /* end string */
175 case cSBACKSLASH: ss = cSTRING; break;
176 case cCHAR: break;
177 case cCBACKSLASH: ss = cCHAR; break;
178 case cSLASH: crc = CRC8 (crc, '/'); ss = cOTHER; break;
179 case cSLASH_SLASH: continue; /* in comment */
180 case cSLASH_STAR: continue; /* in comment */
181 case cSTAR: ss = cSLASH_STAR; continue; /* in comment */
182 }
183 break;
184 case '\\':
185 switch (ss) {
186 case cOTHER: break;
187 case cSTRING: ss = cSBACKSLASH; break;
188 case cSBACKSLASH: ss = cSTRING; break;
189 case cCHAR: ss = cCBACKSLASH; break;
190 case cCBACKSLASH: ss = cCHAR; break;
191 case cSLASH: crc = CRC8 (crc, '/'); ; ss = cOTHER; break;
192 case cSLASH_SLASH: continue; /* in comment */
193 case cSLASH_STAR: continue; /* in comment */
194 case cSTAR: ss = cSLASH_STAR; continue; /* in comment */
195 }
196 break;
197 case '/':
198 switch (ss) {
199 case cOTHER: ss = cSLASH; continue; /* potential comment */
200 case cSTRING: break;
201 case cSBACKSLASH: ss = cSTRING; break;
202 case cCHAR: break;
203 case cCBACKSLASH: ss = cCHAR; break;
204 case cSLASH: ss = cSLASH_SLASH; continue; /* start comment */
205 case cSLASH_SLASH: continue; /* in comment */
206 case cSLASH_STAR: continue; /* in comment */
207 case cSTAR: ss = cOTHER; continue; /* end of comment */
208 }
209 break;
210 case '*':
211 switch (ss) {
212 case cOTHER: break;
213 case cSTRING: break;
214 case cSBACKSLASH: ss = cSTRING; break;
215 case cCHAR: break;
216 case cCBACKSLASH: ss = cCHAR; break;
217 case cSLASH: ss = cSLASH_STAR; continue; /* start comment */
218 case cSLASH_SLASH: continue; /* in comment */
219 case cSLASH_STAR: ss = cSTAR; continue; /* potential end */
220 case cSTAR: continue; /* still potential end of comment */
221 }
222 break;
223 case '\n': case '\r': case ' ': case '\t': case '\014':
224 switch (ss) {
225 case cOTHER: continue; /* ignore all whitespace */
226 case cSTRING: break;
227 case cSBACKSLASH: ss = cSTRING; break;
228 case cCHAR: break;
229 case cCBACKSLASH: ss = cCHAR; break;
230 case cSLASH: c = '/'; ss = cOTHER; break;
231 case cSLASH_SLASH:
232 if (c == '\n' || c == '\r') ss = cOTHER; /* end comment */
233 continue;
234 case cSLASH_STAR: continue; /* in comment */
235 case cSTAR: ss = cSLASH_STAR; continue; /* in comment */
236 }
237 default:
238 switch (ss) {
239 case cOTHER: break;
240 case cSTRING: break;
241 case cSBACKSLASH: ss = cSTRING; break;
242 case cCHAR: break;
243 case cCBACKSLASH: ss = cCHAR; break;
244 case cSLASH: crc = CRC8 (crc, '/'); ss = cOTHER; break;
245 case cSLASH_SLASH: continue; /* in comment */
246 case cSLASH_STAR: continue; /* in comment */
247 case cSTAR: ss = cSLASH_STAR; continue; /* in comment */
248 }
249 }
250 crc = CRC8 (crc, c);
251 }
252}
253
254/*
255 * main
256 */
257int main (int argc, char **argv)
258{
259 int curarg = 1;
260 char *ofile=0;
Ole Troan6855f6c2016-04-09 03:16:30 +0200261 char *pythonfile=0;
Dave Barach557d1282016-11-10 14:22:49 -0500262 char *jsonfile=0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700263 char *show_name=0;
264
265 while (curarg < argc) {
266 if (!strncmp (argv [curarg], "--verbose", 3)) {
267 fprintf (stderr, "%s version %s\n", argv [0], version);
268 curarg++;
269 continue;
270 }
271
272 if (!strncmp (argv [curarg], "--yydebug", 3)) {
273 yydebug = 1;
274 curarg++;
275 continue;
276 }
277
278 if (!strncmp (argv [curarg], "--dump", 3)) {
279 dump_tree = 1;
280 curarg++;
281 continue;
282 }
283
284 if (!strncmp (argv[curarg], "--show-name", 3)) {
285 curarg++;
286 if (curarg < argc) {
287 show_name = argv[curarg];
288 curarg++;
289 continue;
290 } else {
291 fprintf(stderr, "Missing filename after --show-name \n");
292 exit(1);
293 }
294 }
295
296 if (!strncmp (argv [curarg], "--input", 3)) {
297 curarg++;
298 if (curarg < argc) {
299 input_filename = argv[curarg];
300 if (!strcmp (argv [curarg], "-"))
301 ifp = stdin;
302 else
303 ifp = fopen (argv [curarg], "r");
304 if (ifp == NULL) {
305 fprintf (stderr, "Couldn't open input file %s\n",
306 argv[curarg]);
307 exit (1);
308 }
309 curarg++;
310 } else {
311 fprintf(stderr, "Missing filename after --input\n");
312 exit(1);
313 }
314 continue;
315 }
316 if (!strncmp (argv [curarg], "--output", 3)) {
317 curarg++;
318 if (curarg < argc) {
319 ofp = fopen (argv[curarg], "w");
320 if (ofp == NULL) {
321 fprintf (stderr, "Couldn't open output file %s\n",
322 argv[curarg]);
323 exit (1);
324 }
325 ofile = argv[curarg];
326 curarg++;
327 } else {
328 fprintf(stderr, "Missing filename after --output\n");
329 exit(1);
330 }
331 continue;
332 }
Ole Troan6855f6c2016-04-09 03:16:30 +0200333 if (!strncmp (argv [curarg], "--python", 8)) {
334 curarg++;
335 if (curarg < argc) {
Ole Troan5f9dcff2016-08-01 04:59:13 +0200336 if (!strcmp(argv[curarg], "-")) {
337 pythonfp = stdout;
338 } else {
339 pythonfp = fopen(argv[curarg], "w");
340 pythonfile = argv[curarg];
341 }
Ole Troan6855f6c2016-04-09 03:16:30 +0200342 if (pythonfp == NULL) {
343 fprintf (stderr, "Couldn't open python output file %s\n",
344 argv[curarg]);
345 exit (1);
346 }
Ole Troan6855f6c2016-04-09 03:16:30 +0200347 curarg++;
348 } else {
349 fprintf(stderr, "Missing filename after --python\n");
350 exit(1);
351 }
352 continue;
353 }
Dave Barach557d1282016-11-10 14:22:49 -0500354 if (!strncmp (argv [curarg], "--json", 6)) {
355 curarg++;
356 if (curarg < argc) {
357 if (!strcmp(argv[curarg], "-")) {
358 jsonfp = stdout;
359 } else {
360 jsonfp = fopen(argv[curarg], "w");
361 jsonfile = argv[curarg];
362 }
363 if (jsonfp == NULL) {
364 fprintf (stderr, "Couldn't open JSON output file %s\n",
365 argv[curarg]);
366 exit (1);
367 }
368 curarg++;
369 } else {
370 fprintf(stderr, "Missing filename after --json\n");
371 exit(1);
372 }
373 continue;
374 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700375 if (!strncmp (argv [curarg], "--app", 4)) {
376 curarg++;
377 if (curarg < argc) {
378 vlib_app_name = argv[curarg];
379 curarg++;
380 } else {
381 fprintf(stderr, "Missing app name after --app\n");
382 exit(1);
383 }
384 continue;
385 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700386
387 usage(argv[0]);
388 exit (1);
389 }
390 if (ofp == NULL) {
391 ofile = 0;
392 }
Ole Troan6855f6c2016-04-09 03:16:30 +0200393 if (pythonfp == NULL) {
394 pythonfile = 0;
395 }
Dave Barach557d1282016-11-10 14:22:49 -0500396 if (jsonfp == NULL) {
397 jsonfile = 0;
398 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700399 if (ifp == NULL) {
400 fprintf(stderr, "No input file specified...\n");
401 exit(1);
402 }
403 if (show_name) {
404 input_filename = show_name;
405 }
406
407 starttime = time (0);
408
409 if (yyparse() == 0) {
410 fclose (ifp);
411 curarg -= 2;
412 if (ofile) {
413 printf ("Output written to %s\n", ofile);
414 fclose (ofp);
415 }
Ole Troan6855f6c2016-04-09 03:16:30 +0200416 if (pythonfile) {
417 printf ("Python bindings written to %s\n", pythonfile);
418 fclose (pythonfp);
419 }
Dave Barach557d1282016-11-10 14:22:49 -0500420 if (jsonfile) {
421 printf ("JSON bindings written to %s\n", jsonfile);
422 fclose (jsonfp);
423 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700424 }
425 else {
426 fclose (ifp);
Dave Barachf9c231e2016-08-05 10:10:18 -0400427 if (ofp)
428 fclose (ofp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700429 if (ofile) {
430 printf ("Removing %s\n", ofile);
431 unlink (ofile);
432 }
Ole Troan6855f6c2016-04-09 03:16:30 +0200433 if (pythonfile) {
434 printf ("Removing %s\n", pythonfile);
435 unlink (pythonfile);
436 }
Dave Barach557d1282016-11-10 14:22:49 -0500437 if (jsonfile) {
438 printf ("Removing %s\n", jsonfile);
439 unlink (jsonfile);
440 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700441 exit (1);
442 }
443 exit (0);
444}
445
446/*
447 * usage
448 */
449static void usage (char *progname)
450{
451 fprintf (stderr,
Dave Barach557d1282016-11-10 14:22:49 -0500452 "usage: %s --input <filename> [--output <filename>] "
453 "[--json <filename>] [--python <filename>]\n%s",
Ed Warnickecb9cada2015-12-08 15:45:58 -0700454 progname,
455 " [--yydebug] [--dump-tree]\n");
456 exit (1);
457}
458
459/*
460 * yyerror
461 */
462void yyerror (char *s)
463{
464 fprintf (stderr, "%s:%d %s\n", current_filename, the_lexer_linenumber, s);
465}
466
467static char namebuf [MAXNAME];
468
Dave Barachf9c231e2016-08-05 10:10:18 -0400469static inline char
470getc_char (FILE *ifp)
471{
472 return ((char)(getc(ifp) & 0x7f));
473}
474
Ed Warnickecb9cada2015-12-08 15:45:58 -0700475/*
476 * yylex (well, yylex_1: The real yylex below does crc-hackery)
477 */
478static int yylex_1 (void)
479{
480 int nameidx=0;
481 char c;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700482 enum { LP_INITIAL_WHITESPACE, LP_LINE_NUMBER,
483 LP_PRE_FILENAME_WHITESPACE, LP_FILENAME,
484 LP_POST_FILENAME,
485 LP_OTHER
486 } lp_substate = LP_INITIAL_WHITESPACE;
487
488 again:
489 switch (the_lexer_state) {
490 /*
491 * START state -- looking for something interesting
492 */
493 case START_STATE:
Dave Barachf9c231e2016-08-05 10:10:18 -0400494 c = getc_char (ifp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700495 if (feof (ifp))
496 return (EOF);
497
498 switch (c) {
499 case '\n':
500 the_lexer_linenumber++;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700501 goto again;
502
503 case '#':
Ed Warnickecb9cada2015-12-08 15:45:58 -0700504 the_lexer_state = LINE_PRAGMA_STATE;
505 lp_substate = LP_INITIAL_WHITESPACE;
506 goto again;
507
508 /* FALLTHROUGH */
509 case '\t':
510 case ' ':
511 goto again;
512
513 case '(':
514 return (LPAR);
515
516 case ')':
517 return (RPAR);
518
519 case ';':
520 return (SEMI);
521
522 case '[':
523 return (LBRACK);
524
525 case ']':
526 return (RBRACK);
527
528 case '{':
529 return (LCURLY);
530
531 case '}':
532 return (RCURLY);
533
534 case ',':
535 return (COMMA);
536
537 case '"':
538 nameidx = 0;
539 the_lexer_state = STRING_STATE;
540 goto again;
541
542 case '@':
543 nameidx = 0;
544 the_lexer_state = HELPER_STATE;
545 goto again;
546
547 case '/':
Dave Barachf9c231e2016-08-05 10:10:18 -0400548 c = getc_char (ifp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700549 if (feof (ifp))
550 return (EOF);
551
552 if (c == '/') {
553 the_lexer_state = CPP_COMMENT_STATE;
554 goto again;
555 } else if (c == '*') {
556 the_lexer_state = C_COMMENT_STATE;
557 goto again;
558 } else {
559 fprintf (stderr, "unknown token /%c at line %d\n",
560 c, the_lexer_linenumber);
561 return (BARF);
562 }
563
564 case '\\':
Dave Barachf9c231e2016-08-05 10:10:18 -0400565 c = getc_char (ifp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700566 if (feof (ifp))
567 return (EOF);
568
569 /* Note fallthrough... */
570
571 default:
572 if (isalpha (c) || c == '_') {
573 namebuf [0] = c;
574 nameidx = 1;
575 the_lexer_state = NAME_STATE;
576 goto again;
577 } else if (isdigit(c)) {
578 namebuf [0] = c;
579 nameidx = 1;
580 the_lexer_state = NUMBER_STATE;
581 goto again;
582 }
583
584 fprintf (stderr, "unknown token %c at line %d\n",
585 c, the_lexer_linenumber);
586 return (BARF);
587 }
588
589 /*
590 * NAME state -- eat the rest of a name
591 */
592 case NAME_STATE:
Dave Barachf9c231e2016-08-05 10:10:18 -0400593 c = getc_char (ifp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700594 if (feof (ifp))
595 return (EOF);
596
597 if (!isalnum (c) && c != '_') {
598 ungetc (c, ifp);
599 namebuf [nameidx] = 0;
600 the_lexer_state = START_STATE;
601 return (name_check (namebuf, &yylval));
602 }
603 if (nameidx >= (MAXNAME-1)) {
604 fprintf(stderr, "lex input buffer overflow...\n");
605 exit(1);
606 }
607 namebuf [nameidx++] = c;
608 goto again;
609
610 /*
611 * NUMBER state -- eat the rest of a number
612 */
613 case NUMBER_STATE:
Dave Barachf9c231e2016-08-05 10:10:18 -0400614 c = getc_char (ifp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700615 if (feof (ifp))
616 return (EOF);
617
618 if (!isdigit (c)) {
619 ungetc (c, ifp);
620 namebuf [nameidx] = 0;
621 the_lexer_state = START_STATE;
622 yylval = (void *) atol(namebuf);
623 return (NUMBER);
624 }
625 if (nameidx >= (MAXNAME-1)) {
626 fprintf(stderr, "lex input buffer overflow...\n");
627 exit(1);
628 }
629 namebuf [nameidx++] = c;
630 goto again;
631
632 /*
633 * C_COMMENT state -- eat a peach
634 */
635 case C_COMMENT_STATE:
Dave Barachf9c231e2016-08-05 10:10:18 -0400636 c = getc_char (ifp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700637 if (feof (ifp))
638 return (EOF);
639 if (c == '*') {
Dave Barachf9c231e2016-08-05 10:10:18 -0400640 c = getc_char (ifp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700641 if (feof (ifp))
642 return (EOF);
643 if (c == '/') {
644 the_lexer_state = START_STATE;
645 goto again;
646 }
647 }
648 if (c == '\n')
649 the_lexer_linenumber++;
650 goto again;
651
652 /*
653 * CPP_COMMENT state -- eat a plum
654 */
655
656 case CPP_COMMENT_STATE:
Dave Barachf9c231e2016-08-05 10:10:18 -0400657 c = getc_char (ifp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700658 if (feof (ifp))
659 return (EOF);
660 if (c == '\n') {
661 the_lexer_linenumber++;
662 the_lexer_state = START_STATE;
663 goto again;
664 }
665 goto again;
666
667 case STRING_STATE:
Dave Barachf9c231e2016-08-05 10:10:18 -0400668 c = getc_char (ifp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700669 if (feof (ifp))
670 return (EOF);
671 switch (c) {
672 case '\\':
Dave Barachf9c231e2016-08-05 10:10:18 -0400673 c = getc_char (ifp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700674 if (feof (ifp))
675 return (EOF);
676 namebuf[nameidx++] = c;
677 goto again;
678
679 case '"':
680 namebuf[nameidx] = 0;
681 yylval = (YYSTYPE) sxerox (namebuf);
682 the_lexer_state = START_STATE;
683 return (STRING);
684
685 default:
686 if (c == '\n')
687 the_lexer_linenumber++;
688
689 if (nameidx >= (MAXNAME-1)) {
690 fprintf(stderr, "lex input buffer overflow...\n");
691 exit(1);
692 }
693 namebuf[nameidx++] = c;
694 goto again;
695 }
696 break;
697
698 case HELPER_STATE:
Dave Barachf9c231e2016-08-05 10:10:18 -0400699 c = getc_char (ifp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700700 if (feof (ifp))
701 return (EOF);
702 switch (c) {
703 case '\\':
Dave Barachf9c231e2016-08-05 10:10:18 -0400704 c = getc_char (ifp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700705 if (feof (ifp))
706 return (EOF);
707 namebuf[nameidx] = c;
708 goto again;
709
710 case '@':
711 namebuf[nameidx] = 0;
712 yylval = (YYSTYPE) sxerox (namebuf);
713 the_lexer_state = START_STATE;
714 return (HELPER_STRING);
715
716 default:
717 if (c == '\n')
718 the_lexer_linenumber++;
719
720 /*
721 * CPP makes it approximately impossible to
722 * type "#define FOO 123", so we provide a
723 * lexical trick to achieve that result
724 */
725
726 if (c == '$')
727 c = '#';
728
729 if (nameidx >= (MAXNAME-1)) {
730 fprintf(stderr, "lex input buffer overflow...\n");
731 exit(1);
732 }
733 namebuf[nameidx++] = c;
734 goto again;
735 }
736 break;
737
738 case LINE_PRAGMA_STATE:
739 /* We're only interested in lines of the form # 259 "foo.c" 17 */
740
741 switch (lp_substate) {
742
743 case LP_INITIAL_WHITESPACE: /* no number seen yet */
Dave Barachf9c231e2016-08-05 10:10:18 -0400744 c = getc_char(ifp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700745 if (feof(ifp))
746 return(EOF);
747 if (c >= '0' && c <= '9') {
748 namebuf[nameidx++] = c;
749 lp_substate = LP_LINE_NUMBER;
750 } else if (c == '\n') {
751 goto lp_end_of_line;
752 } else if (c != ' ' && c != '\t') {
753 /* Nothing */
754 } else {
755 lp_substate = LP_OTHER;
756 }
757 goto again;
758
759 case LP_LINE_NUMBER: /* eating linenumber */
Dave Barachf9c231e2016-08-05 10:10:18 -0400760 c = getc_char(ifp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700761 if (feof(ifp))
762 return(EOF);
763 if (c >= '0' && c <= '9') {
764 namebuf[nameidx++] = c;
765 } else if (c == ' ' || c == '\t') {
766 namebuf[nameidx++] = 0;
767 the_lexer_linenumber = atol(namebuf);
768 lp_substate = LP_PRE_FILENAME_WHITESPACE;
769 } else if (c == '\n') {
770 goto lp_end_of_line;
771 } else {
772 lp_substate = LP_OTHER;
773 }
774 goto again;
775
776 case LP_PRE_FILENAME_WHITESPACE: /* awaiting filename */
Dave Barachf9c231e2016-08-05 10:10:18 -0400777 c = getc_char(ifp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700778 if (feof(ifp))
779 return(EOF);
780
781 if (c == '"') {
782 lp_substate = LP_FILENAME;
783 nameidx = 0;
784 } else if (c == ' ' || c == '\t') {
785 /* nothing */
786 } else if (c == '\n') {
787 goto lp_end_of_line;
788 } else {
789 lp_substate = LP_OTHER;
790 }
791 goto again;
792
793 case LP_FILENAME: /* eating filename */
Dave Barachf9c231e2016-08-05 10:10:18 -0400794 c = getc_char(ifp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700795 if (feof(ifp))
796 return(EOF);
797
798 if (c == '"') {
799 lp_substate = LP_POST_FILENAME;
800 namebuf[nameidx] = 0;
801 } else if (c == '\n') {
802 goto lp_end_of_line; /* syntax error... */
803 } else {
804 namebuf[nameidx++] = c;
805 }
806 goto again;
807
808 case LP_POST_FILENAME: /* ignoring rest of line */
809 case LP_OTHER:
Dave Barachf9c231e2016-08-05 10:10:18 -0400810 c = getc_char(ifp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700811 if (feof(ifp))
812 return(EOF);
813
814 if (c == '\n') {
815 if (lp_substate == LP_POST_FILENAME) {
816 if (current_filename_allocated) {
817 current_filename_allocated = 0;
818 free(current_filename);
819 }
820
821 if (!strcmp(namebuf, "<stdin>")) {
822 current_filename = input_filename;
823 } else {
824 current_filename = sxerox(namebuf);
825 current_filename_allocated = 1;
826 }
827 }
828 lp_end_of_line:
829 the_lexer_state = START_STATE;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700830 nameidx = 0;
831 }
832 goto again;
833 }
834 break;
835 }
836 fprintf (stderr, "LEXER BUG!\n");
837 exit (1);
838 /* NOTREACHED */
839 return (0);
840}
841
842/*
843 * Parse a token and side-effect input_crc
844 * in a whitespace- and comment-insensitive fashion.
845 */
846int yylex (void)
847{
848 /*
849 * Accumulate a crc32-based signature while processing the
850 * input file. The goal is to come up with a magic number
851 * which changes precisely when the original input file changes
852 * but which ignores whitespace changes.
853 */
854 unsigned long crc = input_crc;
855 int node_type = yylex_1 ();
Dave Barach557d1282016-11-10 14:22:49 -0500856 unsigned long crc2 = message_crc;
857 int use_helper_string = 0;
858 unsigned short code;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700859
860 switch (node_type) {
861 case PRIMTYPE:
862 case NAME:
863 case NUMBER:
864 case STRING:
Dave Barach557d1282016-11-10 14:22:49 -0500865 case HELPER_STRING:
866 use_helper_string = 1;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700867 break;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700868
869 /* Other node types have no "substate" */
870 /* This code is written in this curious fashion because we
871 * want the generated CRC to be independent of the particular
872 * values a particular version of lex/bison assigned to various states.
873 */
874
Dave Barach557d1282016-11-10 14:22:49 -0500875 case RPAR: code = 258; break;
876 case LPAR: code = 259; break;
877 case SEMI: code = 260; break;
878 case LBRACK: code = 261; break;
879 case RBRACK: code = 262; break;
880 case BARF: code = 265; break;
881 case TPACKED: code = 266; break;
882 case DEFINE: code = 267; break;
883 case LCURLY: code = 268; break;
884 case RCURLY: code = 269; break;
885 case UNION: code = 271; break;
886 case COMMA: code = 273; break;
887 case NOVERSION: code = 274; break;
888 case MANUAL_PRINT: code = 275; break;
889 case MANUAL_ENDIAN: code = 276; break;
890 case TYPEONLY: code = 278; break;
891 case DONT_TRACE: code = 279; break;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700892
Dave Barach557d1282016-11-10 14:22:49 -0500893 case EOF: code = ~0; break; /* hysterical compatibility */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700894
895 default:
896 fprintf(stderr, "yylex: node_type %d missing state CRC cookie\n",
897 node_type);
898 exit(1);
899 }
900
Dave Barach557d1282016-11-10 14:22:49 -0500901 if (use_helper_string)
902 {
903 /* We know these types accumulated token text into namebuf */
904 /* HELPER_STRING may still contain C comments. Argh. */
905 crc = crc_eliding_c_comments (namebuf, crc);
906 crc2 = crc_eliding_c_comments (namebuf, crc2);
907 } else
908 {
909 crc = CRC16 (crc, code);
910 crc2 = CRC16 (crc2, code);
911 }
912
Ed Warnickecb9cada2015-12-08 15:45:58 -0700913 input_crc = crc;
Dave Barach557d1282016-11-10 14:22:49 -0500914 message_crc = crc2;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700915 return (node_type);
916}
917
Ed Warnickecb9cada2015-12-08 15:45:58 -0700918/*
919 * name_check -- see if the name we just ate
920 * matches a known keyword. If so, set yylval
921 * to a new instance of <subclass of node>, and return PARSER_MACRO
922 *
923 * Otherwise, set yylval to sxerox (s) and return NAME
924 */
925
926static struct keytab {
927 char *name;
928 enum node_subclass subclass_id;
929} keytab [] =
930/* Keep the table sorted, binary search used below! */
931{
932 {"define", NODE_DEFINE},
933 {"dont_trace", NODE_DONT_TRACE},
934 {"f64", NODE_F64},
935 {"i16", NODE_I16},
936 {"i32", NODE_I32},
937 {"i64", NODE_I64},
938 {"i8", NODE_I8},
939 {"manual_endian", NODE_MANUAL_ENDIAN},
Ed Warnickecb9cada2015-12-08 15:45:58 -0700940 {"manual_print", NODE_MANUAL_PRINT},
941 {"noversion", NODE_NOVERSION},
942 {"packed", NODE_PACKED},
943 {"typeonly", NODE_TYPEONLY},
944 {"u16", NODE_U16},
945 {"u32", NODE_U32},
946 {"u64", NODE_U64},
947 {"u8", NODE_U8},
948 {"union", NODE_UNION},
949 {"uword", NODE_UWORD},
950};
951
952static int name_check (const char *s, YYSTYPE *token_value)
953{
954 enum node_subclass subclass_id;
955 int top, bot, mid;
956 int result;
957
958 for (top = 0, bot = (sizeof(keytab) / sizeof(struct keytab))-1;
959 bot >= top; ) {
960 mid = (top + bot) / 2;
961 result = name_compare (s, keytab[mid].name);
962 if (result < 0)
963 bot = mid - 1;
964 else if (result > 0)
965 top = mid + 1;
966 else {
967 subclass_id = keytab[mid].subclass_id;
968
969 switch (subclass_id) {
970 case NODE_U8:
971 case NODE_U16:
972 case NODE_U32:
973 case NODE_U64:
974 case NODE_I8:
975 case NODE_I16:
976 case NODE_I32:
977 case NODE_I64:
978 case NODE_F64:
979 case NODE_UWORD:
980 *token_value = make_node(subclass_id);
981 return (PRIMTYPE);
982
983 case NODE_PACKED:
984 *token_value = make_node(subclass_id);
985 return (TPACKED);
986
987 case NODE_DEFINE:
Dave Barach557d1282016-11-10 14:22:49 -0500988 message_crc = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700989 *token_value = make_node(subclass_id);
990 return(DEFINE);
991
992 case NODE_MANUAL_PRINT:
993 *token_value = (YYSTYPE) NODE_FLAG_MANUAL_PRINT;
994 return (MANUAL_PRINT);
995
996 case NODE_MANUAL_ENDIAN:
997 *token_value = (YYSTYPE) NODE_FLAG_MANUAL_ENDIAN;
998 return (MANUAL_ENDIAN);
999
Ed Warnickecb9cada2015-12-08 15:45:58 -07001000 case NODE_TYPEONLY:
1001 *token_value = (YYSTYPE) NODE_FLAG_TYPEONLY;
1002 return(TYPEONLY);
1003
1004 case NODE_DONT_TRACE:
1005 *token_value = (YYSTYPE) NODE_FLAG_DONT_TRACE;
1006 return(DONT_TRACE);
1007
1008 case NODE_NOVERSION:
1009 return(NOVERSION);
1010
1011 case NODE_UNION:
1012 return(UNION);
1013
1014 default:
1015 fprintf (stderr, "fatal: keytab botch!\n");
1016 exit (1);
1017 }
1018 }
1019 }
1020 *token_value = (YYSTYPE) sxerox (s);
1021 return (NAME);
1022}
1023
1024/*
1025 * sxerox
1026 */
1027
1028char *sxerox (const char *s)
1029{
1030 int len = strlen (s);
1031 char *rv;
1032
1033 rv = (char *) malloc (len+1);
Dave Barachf9c231e2016-08-05 10:10:18 -04001034 if (rv == 0) {
1035 fprintf(stderr, "Out of memory...");
1036 exit (1);
1037 }
1038
Ed Warnickecb9cada2015-12-08 15:45:58 -07001039 strcpy (rv, s);
1040 return (rv);
1041}
1042
1043/*
1044 * name_compare
1045 */
1046
1047int name_compare (const char *s1, const char *s2)
1048{
1049 char c1, c2;
1050
1051 while (*s1 && *s2) {
1052 c1 = *s1++;
1053 c2 = *s2++;
1054
1055 c1 = tolower (c1);
1056 c2 = tolower (c2);
1057 if (c1 < c2)
1058 return (-1);
1059 else if (c1 > c2)
1060 return (1);
1061 }
1062 if (*s1 < *s2)
1063 return (-1);
1064 else if (*s1 > *s2)
1065 return (1);
1066 return (0);
1067}