blob: b011044dd01ab8d4080b66c2ab8cd0b6757499ca [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) {
Ole Troan5f9dcff2016-08-01 04:59:13 +0200334 if (!strcmp(argv[curarg], "-")) {
335 pythonfp = stdout;
336 } else {
337 pythonfp = fopen(argv[curarg], "w");
338 pythonfile = argv[curarg];
339 }
Ole Troan6855f6c2016-04-09 03:16:30 +0200340 if (pythonfp == NULL) {
341 fprintf (stderr, "Couldn't open python output file %s\n",
342 argv[curarg]);
343 exit (1);
344 }
Ole Troan6855f6c2016-04-09 03:16:30 +0200345 curarg++;
346 } else {
347 fprintf(stderr, "Missing filename after --python\n");
348 exit(1);
349 }
350 continue;
351 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700352 if (!strncmp (argv [curarg], "--app", 4)) {
353 curarg++;
354 if (curarg < argc) {
355 vlib_app_name = argv[curarg];
356 curarg++;
357 } else {
358 fprintf(stderr, "Missing app name after --app\n");
359 exit(1);
360 }
361 continue;
362 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700363
364 usage(argv[0]);
365 exit (1);
366 }
367 if (ofp == NULL) {
368 ofile = 0;
369 }
Ole Troan6855f6c2016-04-09 03:16:30 +0200370 if (pythonfp == NULL) {
371 pythonfile = 0;
372 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700373 if (ifp == NULL) {
374 fprintf(stderr, "No input file specified...\n");
375 exit(1);
376 }
377 if (show_name) {
378 input_filename = show_name;
379 }
380
381 starttime = time (0);
382
383 if (yyparse() == 0) {
384 fclose (ifp);
385 curarg -= 2;
386 if (ofile) {
387 printf ("Output written to %s\n", ofile);
388 fclose (ofp);
389 }
Ole Troan6855f6c2016-04-09 03:16:30 +0200390 if (pythonfile) {
391 printf ("Python bindings written to %s\n", pythonfile);
392 fclose (pythonfp);
393 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700394 }
395 else {
396 fclose (ifp);
Dave Barachf9c231e2016-08-05 10:10:18 -0400397 if (ofp)
398 fclose (ofp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700399 if (ofile) {
400 printf ("Removing %s\n", ofile);
401 unlink (ofile);
402 }
Ole Troan6855f6c2016-04-09 03:16:30 +0200403 if (pythonfile) {
404 printf ("Removing %s\n", pythonfile);
405 unlink (pythonfile);
406 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700407 exit (1);
408 }
409 exit (0);
410}
411
412/*
413 * usage
414 */
415static void usage (char *progname)
416{
417 fprintf (stderr,
Ole Troan6855f6c2016-04-09 03:16:30 +0200418 "usage: %s --input <filename> [--output <filename>] [--python <filename>]\n%s",
Ed Warnickecb9cada2015-12-08 15:45:58 -0700419 progname,
420 " [--yydebug] [--dump-tree]\n");
421 exit (1);
422}
423
424/*
425 * yyerror
426 */
427void yyerror (char *s)
428{
429 fprintf (stderr, "%s:%d %s\n", current_filename, the_lexer_linenumber, s);
430}
431
432static char namebuf [MAXNAME];
433
Dave Barachf9c231e2016-08-05 10:10:18 -0400434static inline char
435getc_char (FILE *ifp)
436{
437 return ((char)(getc(ifp) & 0x7f));
438}
439
Ed Warnickecb9cada2015-12-08 15:45:58 -0700440/*
441 * yylex (well, yylex_1: The real yylex below does crc-hackery)
442 */
443static int yylex_1 (void)
444{
445 int nameidx=0;
446 char c;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700447 enum { LP_INITIAL_WHITESPACE, LP_LINE_NUMBER,
448 LP_PRE_FILENAME_WHITESPACE, LP_FILENAME,
449 LP_POST_FILENAME,
450 LP_OTHER
451 } lp_substate = LP_INITIAL_WHITESPACE;
452
453 again:
454 switch (the_lexer_state) {
455 /*
456 * START state -- looking for something interesting
457 */
458 case START_STATE:
Dave Barachf9c231e2016-08-05 10:10:18 -0400459 c = getc_char (ifp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700460 if (feof (ifp))
461 return (EOF);
462
463 switch (c) {
464 case '\n':
465 the_lexer_linenumber++;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700466 goto again;
467
468 case '#':
Ed Warnickecb9cada2015-12-08 15:45:58 -0700469 the_lexer_state = LINE_PRAGMA_STATE;
470 lp_substate = LP_INITIAL_WHITESPACE;
471 goto again;
472
473 /* FALLTHROUGH */
474 case '\t':
475 case ' ':
476 goto again;
477
478 case '(':
479 return (LPAR);
480
481 case ')':
482 return (RPAR);
483
484 case ';':
485 return (SEMI);
486
487 case '[':
488 return (LBRACK);
489
490 case ']':
491 return (RBRACK);
492
493 case '{':
494 return (LCURLY);
495
496 case '}':
497 return (RCURLY);
498
499 case ',':
500 return (COMMA);
501
502 case '"':
503 nameidx = 0;
504 the_lexer_state = STRING_STATE;
505 goto again;
506
507 case '@':
508 nameidx = 0;
509 the_lexer_state = HELPER_STATE;
510 goto again;
511
512 case '/':
Dave Barachf9c231e2016-08-05 10:10:18 -0400513 c = getc_char (ifp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700514 if (feof (ifp))
515 return (EOF);
516
517 if (c == '/') {
518 the_lexer_state = CPP_COMMENT_STATE;
519 goto again;
520 } else if (c == '*') {
521 the_lexer_state = C_COMMENT_STATE;
522 goto again;
523 } else {
524 fprintf (stderr, "unknown token /%c at line %d\n",
525 c, the_lexer_linenumber);
526 return (BARF);
527 }
528
529 case '\\':
Dave Barachf9c231e2016-08-05 10:10:18 -0400530 c = getc_char (ifp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700531 if (feof (ifp))
532 return (EOF);
533
534 /* Note fallthrough... */
535
536 default:
537 if (isalpha (c) || c == '_') {
538 namebuf [0] = c;
539 nameidx = 1;
540 the_lexer_state = NAME_STATE;
541 goto again;
542 } else if (isdigit(c)) {
543 namebuf [0] = c;
544 nameidx = 1;
545 the_lexer_state = NUMBER_STATE;
546 goto again;
547 }
548
549 fprintf (stderr, "unknown token %c at line %d\n",
550 c, the_lexer_linenumber);
551 return (BARF);
552 }
553
554 /*
555 * NAME state -- eat the rest of a name
556 */
557 case NAME_STATE:
Dave Barachf9c231e2016-08-05 10:10:18 -0400558 c = getc_char (ifp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700559 if (feof (ifp))
560 return (EOF);
561
562 if (!isalnum (c) && c != '_') {
563 ungetc (c, ifp);
564 namebuf [nameidx] = 0;
565 the_lexer_state = START_STATE;
566 return (name_check (namebuf, &yylval));
567 }
568 if (nameidx >= (MAXNAME-1)) {
569 fprintf(stderr, "lex input buffer overflow...\n");
570 exit(1);
571 }
572 namebuf [nameidx++] = c;
573 goto again;
574
575 /*
576 * NUMBER state -- eat the rest of a number
577 */
578 case NUMBER_STATE:
Dave Barachf9c231e2016-08-05 10:10:18 -0400579 c = getc_char (ifp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700580 if (feof (ifp))
581 return (EOF);
582
583 if (!isdigit (c)) {
584 ungetc (c, ifp);
585 namebuf [nameidx] = 0;
586 the_lexer_state = START_STATE;
587 yylval = (void *) atol(namebuf);
588 return (NUMBER);
589 }
590 if (nameidx >= (MAXNAME-1)) {
591 fprintf(stderr, "lex input buffer overflow...\n");
592 exit(1);
593 }
594 namebuf [nameidx++] = c;
595 goto again;
596
597 /*
598 * C_COMMENT state -- eat a peach
599 */
600 case C_COMMENT_STATE:
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 == '*') {
Dave Barachf9c231e2016-08-05 10:10:18 -0400605 c = getc_char (ifp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700606 if (feof (ifp))
607 return (EOF);
608 if (c == '/') {
609 the_lexer_state = START_STATE;
610 goto again;
611 }
612 }
613 if (c == '\n')
614 the_lexer_linenumber++;
615 goto again;
616
617 /*
618 * CPP_COMMENT state -- eat a plum
619 */
620
621 case CPP_COMMENT_STATE:
Dave Barachf9c231e2016-08-05 10:10:18 -0400622 c = getc_char (ifp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700623 if (feof (ifp))
624 return (EOF);
625 if (c == '\n') {
626 the_lexer_linenumber++;
627 the_lexer_state = START_STATE;
628 goto again;
629 }
630 goto again;
631
632 case STRING_STATE:
Dave Barachf9c231e2016-08-05 10:10:18 -0400633 c = getc_char (ifp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700634 if (feof (ifp))
635 return (EOF);
636 switch (c) {
637 case '\\':
Dave Barachf9c231e2016-08-05 10:10:18 -0400638 c = getc_char (ifp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700639 if (feof (ifp))
640 return (EOF);
641 namebuf[nameidx++] = c;
642 goto again;
643
644 case '"':
645 namebuf[nameidx] = 0;
646 yylval = (YYSTYPE) sxerox (namebuf);
647 the_lexer_state = START_STATE;
648 return (STRING);
649
650 default:
651 if (c == '\n')
652 the_lexer_linenumber++;
653
654 if (nameidx >= (MAXNAME-1)) {
655 fprintf(stderr, "lex input buffer overflow...\n");
656 exit(1);
657 }
658 namebuf[nameidx++] = c;
659 goto again;
660 }
661 break;
662
663 case HELPER_STATE:
Dave Barachf9c231e2016-08-05 10:10:18 -0400664 c = getc_char (ifp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700665 if (feof (ifp))
666 return (EOF);
667 switch (c) {
668 case '\\':
Dave Barachf9c231e2016-08-05 10:10:18 -0400669 c = getc_char (ifp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700670 if (feof (ifp))
671 return (EOF);
672 namebuf[nameidx] = c;
673 goto again;
674
675 case '@':
676 namebuf[nameidx] = 0;
677 yylval = (YYSTYPE) sxerox (namebuf);
678 the_lexer_state = START_STATE;
679 return (HELPER_STRING);
680
681 default:
682 if (c == '\n')
683 the_lexer_linenumber++;
684
685 /*
686 * CPP makes it approximately impossible to
687 * type "#define FOO 123", so we provide a
688 * lexical trick to achieve that result
689 */
690
691 if (c == '$')
692 c = '#';
693
694 if (nameidx >= (MAXNAME-1)) {
695 fprintf(stderr, "lex input buffer overflow...\n");
696 exit(1);
697 }
698 namebuf[nameidx++] = c;
699 goto again;
700 }
701 break;
702
703 case LINE_PRAGMA_STATE:
704 /* We're only interested in lines of the form # 259 "foo.c" 17 */
705
706 switch (lp_substate) {
707
708 case LP_INITIAL_WHITESPACE: /* no number seen yet */
Dave Barachf9c231e2016-08-05 10:10:18 -0400709 c = getc_char(ifp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700710 if (feof(ifp))
711 return(EOF);
712 if (c >= '0' && c <= '9') {
713 namebuf[nameidx++] = c;
714 lp_substate = LP_LINE_NUMBER;
715 } else if (c == '\n') {
716 goto lp_end_of_line;
717 } else if (c != ' ' && c != '\t') {
718 /* Nothing */
719 } else {
720 lp_substate = LP_OTHER;
721 }
722 goto again;
723
724 case LP_LINE_NUMBER: /* eating linenumber */
Dave Barachf9c231e2016-08-05 10:10:18 -0400725 c = getc_char(ifp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700726 if (feof(ifp))
727 return(EOF);
728 if (c >= '0' && c <= '9') {
729 namebuf[nameidx++] = c;
730 } else if (c == ' ' || c == '\t') {
731 namebuf[nameidx++] = 0;
732 the_lexer_linenumber = atol(namebuf);
733 lp_substate = LP_PRE_FILENAME_WHITESPACE;
734 } else if (c == '\n') {
735 goto lp_end_of_line;
736 } else {
737 lp_substate = LP_OTHER;
738 }
739 goto again;
740
741 case LP_PRE_FILENAME_WHITESPACE: /* awaiting filename */
Dave Barachf9c231e2016-08-05 10:10:18 -0400742 c = getc_char(ifp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700743 if (feof(ifp))
744 return(EOF);
745
746 if (c == '"') {
747 lp_substate = LP_FILENAME;
748 nameidx = 0;
749 } else if (c == ' ' || c == '\t') {
750 /* nothing */
751 } else if (c == '\n') {
752 goto lp_end_of_line;
753 } else {
754 lp_substate = LP_OTHER;
755 }
756 goto again;
757
758 case LP_FILENAME: /* eating filename */
Dave Barachf9c231e2016-08-05 10:10:18 -0400759 c = getc_char(ifp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700760 if (feof(ifp))
761 return(EOF);
762
763 if (c == '"') {
764 lp_substate = LP_POST_FILENAME;
765 namebuf[nameidx] = 0;
766 } else if (c == '\n') {
767 goto lp_end_of_line; /* syntax error... */
768 } else {
769 namebuf[nameidx++] = c;
770 }
771 goto again;
772
773 case LP_POST_FILENAME: /* ignoring rest of line */
774 case LP_OTHER:
Dave Barachf9c231e2016-08-05 10:10:18 -0400775 c = getc_char(ifp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700776 if (feof(ifp))
777 return(EOF);
778
779 if (c == '\n') {
780 if (lp_substate == LP_POST_FILENAME) {
781 if (current_filename_allocated) {
782 current_filename_allocated = 0;
783 free(current_filename);
784 }
785
786 if (!strcmp(namebuf, "<stdin>")) {
787 current_filename = input_filename;
788 } else {
789 current_filename = sxerox(namebuf);
790 current_filename_allocated = 1;
791 }
792 }
793 lp_end_of_line:
794 the_lexer_state = START_STATE;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700795 nameidx = 0;
796 }
797 goto again;
798 }
799 break;
800 }
801 fprintf (stderr, "LEXER BUG!\n");
802 exit (1);
803 /* NOTREACHED */
804 return (0);
805}
806
807/*
808 * Parse a token and side-effect input_crc
809 * in a whitespace- and comment-insensitive fashion.
810 */
811int yylex (void)
812{
813 /*
814 * Accumulate a crc32-based signature while processing the
815 * input file. The goal is to come up with a magic number
816 * which changes precisely when the original input file changes
817 * but which ignores whitespace changes.
818 */
819 unsigned long crc = input_crc;
820 int node_type = yylex_1 ();
821
822 switch (node_type) {
823 case PRIMTYPE:
824 case NAME:
825 case NUMBER:
826 case STRING:
827 case HELPER_STRING: {
828 /* We know these types accumulated token text into namebuf */
829 /* HELPER_STRING may still contain C comments. Argh. */
830 crc = crc_eliding_c_comments (namebuf, crc);
831 break;
832 }
833
834 /* Other node types have no "substate" */
835 /* This code is written in this curious fashion because we
836 * want the generated CRC to be independent of the particular
837 * values a particular version of lex/bison assigned to various states.
838 */
839
840 /* case NAME: crc = CRC16 (crc, 257); break; */
841 case RPAR: crc = CRC16 (crc, 258); break;
842 case LPAR: crc = CRC16 (crc, 259); break;
843 case SEMI: crc = CRC16 (crc, 260); break;
844 case LBRACK: crc = CRC16 (crc, 261); break;
845 case RBRACK: crc = CRC16 (crc, 262); break;
846 /* case NUMBER: crc = CRC16 (crc, 263); break; */
847 /* case PRIMTYPE: crc = CRC16 (crc, 264); break; */
848 case BARF: crc = CRC16 (crc, 265); break;
849 case TPACKED: crc = CRC16 (crc, 266); break;
850 case DEFINE: crc = CRC16 (crc, 267); break;
851 case LCURLY: crc = CRC16 (crc, 268); break;
852 case RCURLY: crc = CRC16 (crc, 269); break;
853 /* case STRING: crc = CRC16 (crc, 270); break; */
854 case UNION: crc = CRC16 (crc, 271); break;
855 /* case HELPER_STRING: crc = CRC16 (crc, 272); break; */
856 case COMMA: crc = CRC16 (crc, 273); break;
857 case NOVERSION: crc = CRC16 (crc, 274); break;
858 case MANUAL_PRINT: crc = CRC16 (crc, 275); break;
859 case MANUAL_ENDIAN: crc = CRC16 (crc, 276); break;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700860 case TYPEONLY: crc = CRC16 (crc, 278); break;
861 case DONT_TRACE: crc = CRC16 (crc, 279); break;
862
863 case EOF: crc = CRC16 (crc, ~0); break; /* hysterical compatibility */
864
865 default:
866 fprintf(stderr, "yylex: node_type %d missing state CRC cookie\n",
867 node_type);
868 exit(1);
869 }
870
871 input_crc = crc;
872 return (node_type);
873}
874
875
876/*
877 * name_check -- see if the name we just ate
878 * matches a known keyword. If so, set yylval
879 * to a new instance of <subclass of node>, and return PARSER_MACRO
880 *
881 * Otherwise, set yylval to sxerox (s) and return NAME
882 */
883
884static struct keytab {
885 char *name;
886 enum node_subclass subclass_id;
887} keytab [] =
888/* Keep the table sorted, binary search used below! */
889{
890 {"define", NODE_DEFINE},
891 {"dont_trace", NODE_DONT_TRACE},
892 {"f64", NODE_F64},
893 {"i16", NODE_I16},
894 {"i32", NODE_I32},
895 {"i64", NODE_I64},
896 {"i8", NODE_I8},
897 {"manual_endian", NODE_MANUAL_ENDIAN},
Ed Warnickecb9cada2015-12-08 15:45:58 -0700898 {"manual_print", NODE_MANUAL_PRINT},
899 {"noversion", NODE_NOVERSION},
900 {"packed", NODE_PACKED},
901 {"typeonly", NODE_TYPEONLY},
902 {"u16", NODE_U16},
903 {"u32", NODE_U32},
904 {"u64", NODE_U64},
905 {"u8", NODE_U8},
906 {"union", NODE_UNION},
907 {"uword", NODE_UWORD},
908};
909
910static int name_check (const char *s, YYSTYPE *token_value)
911{
912 enum node_subclass subclass_id;
913 int top, bot, mid;
914 int result;
915
916 for (top = 0, bot = (sizeof(keytab) / sizeof(struct keytab))-1;
917 bot >= top; ) {
918 mid = (top + bot) / 2;
919 result = name_compare (s, keytab[mid].name);
920 if (result < 0)
921 bot = mid - 1;
922 else if (result > 0)
923 top = mid + 1;
924 else {
925 subclass_id = keytab[mid].subclass_id;
926
927 switch (subclass_id) {
928 case NODE_U8:
929 case NODE_U16:
930 case NODE_U32:
931 case NODE_U64:
932 case NODE_I8:
933 case NODE_I16:
934 case NODE_I32:
935 case NODE_I64:
936 case NODE_F64:
937 case NODE_UWORD:
938 *token_value = make_node(subclass_id);
939 return (PRIMTYPE);
940
941 case NODE_PACKED:
942 *token_value = make_node(subclass_id);
943 return (TPACKED);
944
945 case NODE_DEFINE:
946 *token_value = make_node(subclass_id);
947 return(DEFINE);
948
949 case NODE_MANUAL_PRINT:
950 *token_value = (YYSTYPE) NODE_FLAG_MANUAL_PRINT;
951 return (MANUAL_PRINT);
952
953 case NODE_MANUAL_ENDIAN:
954 *token_value = (YYSTYPE) NODE_FLAG_MANUAL_ENDIAN;
955 return (MANUAL_ENDIAN);
956
Ed Warnickecb9cada2015-12-08 15:45:58 -0700957 case NODE_TYPEONLY:
958 *token_value = (YYSTYPE) NODE_FLAG_TYPEONLY;
959 return(TYPEONLY);
960
961 case NODE_DONT_TRACE:
962 *token_value = (YYSTYPE) NODE_FLAG_DONT_TRACE;
963 return(DONT_TRACE);
964
965 case NODE_NOVERSION:
966 return(NOVERSION);
967
968 case NODE_UNION:
969 return(UNION);
970
971 default:
972 fprintf (stderr, "fatal: keytab botch!\n");
973 exit (1);
974 }
975 }
976 }
977 *token_value = (YYSTYPE) sxerox (s);
978 return (NAME);
979}
980
981/*
982 * sxerox
983 */
984
985char *sxerox (const char *s)
986{
987 int len = strlen (s);
988 char *rv;
989
990 rv = (char *) malloc (len+1);
Dave Barachf9c231e2016-08-05 10:10:18 -0400991 if (rv == 0) {
992 fprintf(stderr, "Out of memory...");
993 exit (1);
994 }
995
Ed Warnickecb9cada2015-12-08 15:45:58 -0700996 strcpy (rv, s);
997 return (rv);
998}
999
1000/*
1001 * name_compare
1002 */
1003
1004int name_compare (const char *s1, const char *s2)
1005{
1006 char c1, c2;
1007
1008 while (*s1 && *s2) {
1009 c1 = *s1++;
1010 c2 = *s2++;
1011
1012 c1 = tolower (c1);
1013 c2 = tolower (c2);
1014 if (c1 < c2)
1015 return (-1);
1016 else if (c1 > c2)
1017 return (1);
1018 }
1019 if (*s1 < *s2)
1020 return (-1);
1021 else if (*s1 > *s2)
1022 return (1);
1023 return (0);
1024}