blob: f1d49a877e8abe2c9a6e64081432747e4e99fb0a [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
Ole Troan6855f6c2016-04-09 03:16:30 +020031FILE *ifp, *ofp, *javafp, *jnifp, *pythonfp;
Ed Warnickecb9cada2015-12-08 15:45:58 -070032char *java_class = "vppApi";
33char *vlib_app_name = "vpp";
34int dump_tree;
35time_t starttime;
36char *input_filename;
37char *current_filename;
38int current_filename_allocated;
39unsigned long input_crc;
40int 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;
261 char *jofile=0;
262 char *jnifile=0;
Ole Troan6855f6c2016-04-09 03:16:30 +0200263 char *pythonfile=0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700264 char *show_name=0;
265
266 while (curarg < argc) {
267 if (!strncmp (argv [curarg], "--verbose", 3)) {
268 fprintf (stderr, "%s version %s\n", argv [0], version);
269 curarg++;
270 continue;
271 }
272
273 if (!strncmp (argv [curarg], "--yydebug", 3)) {
274 yydebug = 1;
275 curarg++;
276 continue;
277 }
278
279 if (!strncmp (argv [curarg], "--dump", 3)) {
280 dump_tree = 1;
281 curarg++;
282 continue;
283 }
284
285 if (!strncmp (argv[curarg], "--show-name", 3)) {
286 curarg++;
287 if (curarg < argc) {
288 show_name = argv[curarg];
289 curarg++;
290 continue;
291 } else {
292 fprintf(stderr, "Missing filename after --show-name \n");
293 exit(1);
294 }
295 }
296
297 if (!strncmp (argv [curarg], "--input", 3)) {
298 curarg++;
299 if (curarg < argc) {
300 input_filename = argv[curarg];
301 if (!strcmp (argv [curarg], "-"))
302 ifp = stdin;
303 else
304 ifp = fopen (argv [curarg], "r");
305 if (ifp == NULL) {
306 fprintf (stderr, "Couldn't open input file %s\n",
307 argv[curarg]);
308 exit (1);
309 }
310 curarg++;
311 } else {
312 fprintf(stderr, "Missing filename after --input\n");
313 exit(1);
314 }
315 continue;
316 }
317 if (!strncmp (argv [curarg], "--output", 3)) {
318 curarg++;
319 if (curarg < argc) {
320 ofp = fopen (argv[curarg], "w");
321 if (ofp == NULL) {
322 fprintf (stderr, "Couldn't open output file %s\n",
323 argv[curarg]);
324 exit (1);
325 }
326 ofile = argv[curarg];
327 curarg++;
328 } else {
329 fprintf(stderr, "Missing filename after --output\n");
330 exit(1);
331 }
332 continue;
333 }
334 if (!strncmp (argv [curarg], "--java", 4)) {
335 curarg++;
336 if (curarg < argc) {
337 javafp = fopen (argv[curarg], "w");
338 if (javafp == NULL) {
339 fprintf (stderr, "Couldn't open java output file %s\n",
340 argv[curarg]);
341 exit (1);
342 }
343 jofile = argv[curarg];
344 curarg++;
345 } else {
346 fprintf(stderr, "Missing filename after --java\n");
347 exit(1);
348 }
349 continue;
350 }
351 if (!strncmp (argv [curarg], "--jni", 4)) {
352 curarg++;
353 if (curarg < argc) {
354 jnifp = fopen (argv[curarg], "w");
355 if (jnifp == NULL) {
356 fprintf (stderr, "Couldn't open jni output file %s\n",
357 argv[curarg]);
358 exit (1);
359 }
360 jnifile = argv[curarg];
361 curarg++;
362 } else {
363 fprintf(stderr, "Missing filename after --jni\n");
364 exit(1);
365 }
366 continue;
367 }
Ole Troan6855f6c2016-04-09 03:16:30 +0200368 if (!strncmp (argv [curarg], "--python", 8)) {
369 curarg++;
370 if (curarg < argc) {
371 pythonfp = fopen (argv[curarg], "w");
372 if (pythonfp == NULL) {
373 fprintf (stderr, "Couldn't open python output file %s\n",
374 argv[curarg]);
375 exit (1);
376 }
377 pythonfile = argv[curarg];
378 curarg++;
379 } else {
380 fprintf(stderr, "Missing filename after --python\n");
381 exit(1);
382 }
383 continue;
384 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700385 if (!strncmp (argv [curarg], "--app", 4)) {
386 curarg++;
387 if (curarg < argc) {
388 vlib_app_name = argv[curarg];
389 curarg++;
390 } else {
391 fprintf(stderr, "Missing app name after --app\n");
392 exit(1);
393 }
394 continue;
395 }
396 if (!strncmp (argv [curarg], "--class", 3)) {
397 curarg++;
398 if (curarg < argc) {
399 java_class = argv[curarg];
400 curarg++;
401 } else {
402 fprintf(stderr, "Missing class name after --class\n");
403 exit(1);
404 }
405 continue;
406 }
407
408 usage(argv[0]);
409 exit (1);
410 }
411 if (ofp == NULL) {
412 ofile = 0;
413 }
414 if (javafp == NULL) {
415 jofile = 0;
416 }
417 if (jnifp == NULL) {
418 jnifile = 0;
419 }
Ole Troan6855f6c2016-04-09 03:16:30 +0200420 if (pythonfp == NULL) {
421 pythonfile = 0;
422 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700423 if (ifp == NULL) {
424 fprintf(stderr, "No input file specified...\n");
425 exit(1);
426 }
427 if (show_name) {
428 input_filename = show_name;
429 }
430
431 starttime = time (0);
432
433 if (yyparse() == 0) {
434 fclose (ifp);
435 curarg -= 2;
436 if (ofile) {
437 printf ("Output written to %s\n", ofile);
438 fclose (ofp);
439 }
440 if (jofile) {
441 printf ("Java class defn written to %s\n", jofile);
442 fclose (javafp);
443 }
444 if (jnifile) {
445 printf ("Java native bindings written to %s\n", jnifile);
446 fclose (jnifp);
447 }
Ole Troan6855f6c2016-04-09 03:16:30 +0200448 if (pythonfile) {
449 printf ("Python bindings written to %s\n", pythonfile);
450 fclose (pythonfp);
451 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700452 }
453 else {
454 fclose (ifp);
455 fclose (ofp);
456 if (ofile) {
457 printf ("Removing %s\n", ofile);
458 unlink (ofile);
459 }
460 fclose (javafp);
461 if (jofile) {
462 printf ("Removing %s\n", jofile);
463 unlink (jofile);
464 }
465 if (jnifile) {
466 printf ("Removing %s\n", jnifile);
467 unlink (jnifile);
468 }
Ole Troan6855f6c2016-04-09 03:16:30 +0200469 if (pythonfile) {
470 printf ("Removing %s\n", pythonfile);
471 unlink (pythonfile);
472 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700473 exit (1);
474 }
475 exit (0);
476}
477
478/*
479 * usage
480 */
481static void usage (char *progname)
482{
483 fprintf (stderr,
Ole Troan6855f6c2016-04-09 03:16:30 +0200484 "usage: %s --input <filename> [--output <filename>] [--python <filename>]\n%s",
Ed Warnickecb9cada2015-12-08 15:45:58 -0700485 progname,
486 " [--yydebug] [--dump-tree]\n");
487 exit (1);
488}
489
490/*
491 * yyerror
492 */
493void yyerror (char *s)
494{
495 fprintf (stderr, "%s:%d %s\n", current_filename, the_lexer_linenumber, s);
496}
497
498static char namebuf [MAXNAME];
499
500/*
501 * yylex (well, yylex_1: The real yylex below does crc-hackery)
502 */
503static int yylex_1 (void)
504{
505 int nameidx=0;
506 char c;
507 int at_bol=1;
508 enum { LP_INITIAL_WHITESPACE, LP_LINE_NUMBER,
509 LP_PRE_FILENAME_WHITESPACE, LP_FILENAME,
510 LP_POST_FILENAME,
511 LP_OTHER
512 } lp_substate = LP_INITIAL_WHITESPACE;
513
514 again:
515 switch (the_lexer_state) {
516 /*
517 * START state -- looking for something interesting
518 */
519 case START_STATE:
520 c = getc (ifp);
521 if (feof (ifp))
522 return (EOF);
523
524 switch (c) {
525 case '\n':
526 the_lexer_linenumber++;
527 at_bol=1;
528 goto again;
529
530 case '#':
531 if (!at_bol) {
532 fprintf (stderr, "unknown token /%c at line %d\n",
533 c, the_lexer_linenumber);
534 return (BARF);
535 }
536
537 the_lexer_state = LINE_PRAGMA_STATE;
538 lp_substate = LP_INITIAL_WHITESPACE;
539 goto again;
540
541 /* FALLTHROUGH */
542 case '\t':
543 case ' ':
544 goto again;
545
546 case '(':
547 return (LPAR);
548
549 case ')':
550 return (RPAR);
551
552 case ';':
553 return (SEMI);
554
555 case '[':
556 return (LBRACK);
557
558 case ']':
559 return (RBRACK);
560
561 case '{':
562 return (LCURLY);
563
564 case '}':
565 return (RCURLY);
566
567 case ',':
568 return (COMMA);
569
570 case '"':
571 nameidx = 0;
572 the_lexer_state = STRING_STATE;
573 goto again;
574
575 case '@':
576 nameidx = 0;
577 the_lexer_state = HELPER_STATE;
578 goto again;
579
580 case '/':
581 c = getc (ifp);
582 if (feof (ifp))
583 return (EOF);
584
585 if (c == '/') {
586 the_lexer_state = CPP_COMMENT_STATE;
587 goto again;
588 } else if (c == '*') {
589 the_lexer_state = C_COMMENT_STATE;
590 goto again;
591 } else {
592 fprintf (stderr, "unknown token /%c at line %d\n",
593 c, the_lexer_linenumber);
594 return (BARF);
595 }
596
597 case '\\':
598 c = getc (ifp);
599 if (feof (ifp))
600 return (EOF);
601
602 /* Note fallthrough... */
603
604 default:
605 if (isalpha (c) || c == '_') {
606 namebuf [0] = c;
607 nameidx = 1;
608 the_lexer_state = NAME_STATE;
609 goto again;
610 } else if (isdigit(c)) {
611 namebuf [0] = c;
612 nameidx = 1;
613 the_lexer_state = NUMBER_STATE;
614 goto again;
615 }
616
617 fprintf (stderr, "unknown token %c at line %d\n",
618 c, the_lexer_linenumber);
619 return (BARF);
620 }
621
622 /*
623 * NAME state -- eat the rest of a name
624 */
625 case NAME_STATE:
626 c = getc (ifp);
627 if (feof (ifp))
628 return (EOF);
629
630 if (!isalnum (c) && c != '_') {
631 ungetc (c, ifp);
632 namebuf [nameidx] = 0;
633 the_lexer_state = START_STATE;
634 return (name_check (namebuf, &yylval));
635 }
636 if (nameidx >= (MAXNAME-1)) {
637 fprintf(stderr, "lex input buffer overflow...\n");
638 exit(1);
639 }
640 namebuf [nameidx++] = c;
641 goto again;
642
643 /*
644 * NUMBER state -- eat the rest of a number
645 */
646 case NUMBER_STATE:
647 c = getc (ifp);
648 if (feof (ifp))
649 return (EOF);
650
651 if (!isdigit (c)) {
652 ungetc (c, ifp);
653 namebuf [nameidx] = 0;
654 the_lexer_state = START_STATE;
655 yylval = (void *) atol(namebuf);
656 return (NUMBER);
657 }
658 if (nameidx >= (MAXNAME-1)) {
659 fprintf(stderr, "lex input buffer overflow...\n");
660 exit(1);
661 }
662 namebuf [nameidx++] = c;
663 goto again;
664
665 /*
666 * C_COMMENT state -- eat a peach
667 */
668 case C_COMMENT_STATE:
669 c = getc (ifp);
670 if (feof (ifp))
671 return (EOF);
672 if (c == '*') {
673 c = getc (ifp);
674 if (feof (ifp))
675 return (EOF);
676 if (c == '/') {
677 the_lexer_state = START_STATE;
678 goto again;
679 }
680 }
681 if (c == '\n')
682 the_lexer_linenumber++;
683 goto again;
684
685 /*
686 * CPP_COMMENT state -- eat a plum
687 */
688
689 case CPP_COMMENT_STATE:
690 c = getc (ifp);
691 if (feof (ifp))
692 return (EOF);
693 if (c == '\n') {
694 the_lexer_linenumber++;
695 the_lexer_state = START_STATE;
696 goto again;
697 }
698 goto again;
699
700 case STRING_STATE:
701 c = getc (ifp);
702 if (feof (ifp))
703 return (EOF);
704 switch (c) {
705 case '\\':
706 c = getc (ifp);
707 if (feof (ifp))
708 return (EOF);
709 namebuf[nameidx++] = c;
710 goto again;
711
712 case '"':
713 namebuf[nameidx] = 0;
714 yylval = (YYSTYPE) sxerox (namebuf);
715 the_lexer_state = START_STATE;
716 return (STRING);
717
718 default:
719 if (c == '\n')
720 the_lexer_linenumber++;
721
722 if (nameidx >= (MAXNAME-1)) {
723 fprintf(stderr, "lex input buffer overflow...\n");
724 exit(1);
725 }
726 namebuf[nameidx++] = c;
727 goto again;
728 }
729 break;
730
731 case HELPER_STATE:
732 c = getc (ifp);
733 if (feof (ifp))
734 return (EOF);
735 switch (c) {
736 case '\\':
737 c = getc (ifp);
738 if (feof (ifp))
739 return (EOF);
740 namebuf[nameidx] = c;
741 goto again;
742
743 case '@':
744 namebuf[nameidx] = 0;
745 yylval = (YYSTYPE) sxerox (namebuf);
746 the_lexer_state = START_STATE;
747 return (HELPER_STRING);
748
749 default:
750 if (c == '\n')
751 the_lexer_linenumber++;
752
753 /*
754 * CPP makes it approximately impossible to
755 * type "#define FOO 123", so we provide a
756 * lexical trick to achieve that result
757 */
758
759 if (c == '$')
760 c = '#';
761
762 if (nameidx >= (MAXNAME-1)) {
763 fprintf(stderr, "lex input buffer overflow...\n");
764 exit(1);
765 }
766 namebuf[nameidx++] = c;
767 goto again;
768 }
769 break;
770
771 case LINE_PRAGMA_STATE:
772 /* We're only interested in lines of the form # 259 "foo.c" 17 */
773
774 switch (lp_substate) {
775
776 case LP_INITIAL_WHITESPACE: /* no number seen yet */
777 c = getc(ifp);
778 if (feof(ifp))
779 return(EOF);
780 if (c >= '0' && c <= '9') {
781 namebuf[nameidx++] = c;
782 lp_substate = LP_LINE_NUMBER;
783 } else if (c == '\n') {
784 goto lp_end_of_line;
785 } else if (c != ' ' && c != '\t') {
786 /* Nothing */
787 } else {
788 lp_substate = LP_OTHER;
789 }
790 goto again;
791
792 case LP_LINE_NUMBER: /* eating linenumber */
793 c = getc(ifp);
794 if (feof(ifp))
795 return(EOF);
796 if (c >= '0' && c <= '9') {
797 namebuf[nameidx++] = c;
798 } else if (c == ' ' || c == '\t') {
799 namebuf[nameidx++] = 0;
800 the_lexer_linenumber = atol(namebuf);
801 lp_substate = LP_PRE_FILENAME_WHITESPACE;
802 } else if (c == '\n') {
803 goto lp_end_of_line;
804 } else {
805 lp_substate = LP_OTHER;
806 }
807 goto again;
808
809 case LP_PRE_FILENAME_WHITESPACE: /* awaiting filename */
810 c = getc(ifp);
811 if (feof(ifp))
812 return(EOF);
813
814 if (c == '"') {
815 lp_substate = LP_FILENAME;
816 nameidx = 0;
817 } else if (c == ' ' || c == '\t') {
818 /* nothing */
819 } else if (c == '\n') {
820 goto lp_end_of_line;
821 } else {
822 lp_substate = LP_OTHER;
823 }
824 goto again;
825
826 case LP_FILENAME: /* eating filename */
827 c = getc(ifp);
828 if (feof(ifp))
829 return(EOF);
830
831 if (c == '"') {
832 lp_substate = LP_POST_FILENAME;
833 namebuf[nameidx] = 0;
834 } else if (c == '\n') {
835 goto lp_end_of_line; /* syntax error... */
836 } else {
837 namebuf[nameidx++] = c;
838 }
839 goto again;
840
841 case LP_POST_FILENAME: /* ignoring rest of line */
842 case LP_OTHER:
843 c = getc(ifp);
844 if (feof(ifp))
845 return(EOF);
846
847 if (c == '\n') {
848 if (lp_substate == LP_POST_FILENAME) {
849 if (current_filename_allocated) {
850 current_filename_allocated = 0;
851 free(current_filename);
852 }
853
854 if (!strcmp(namebuf, "<stdin>")) {
855 current_filename = input_filename;
856 } else {
857 current_filename = sxerox(namebuf);
858 current_filename_allocated = 1;
859 }
860 }
861 lp_end_of_line:
862 the_lexer_state = START_STATE;
863 at_bol = 1;
864 nameidx = 0;
865 }
866 goto again;
867 }
868 break;
869 }
870 fprintf (stderr, "LEXER BUG!\n");
871 exit (1);
872 /* NOTREACHED */
873 return (0);
874}
875
876/*
877 * Parse a token and side-effect input_crc
878 * in a whitespace- and comment-insensitive fashion.
879 */
880int yylex (void)
881{
882 /*
883 * Accumulate a crc32-based signature while processing the
884 * input file. The goal is to come up with a magic number
885 * which changes precisely when the original input file changes
886 * but which ignores whitespace changes.
887 */
888 unsigned long crc = input_crc;
889 int node_type = yylex_1 ();
890
891 switch (node_type) {
892 case PRIMTYPE:
893 case NAME:
894 case NUMBER:
895 case STRING:
896 case HELPER_STRING: {
897 /* We know these types accumulated token text into namebuf */
898 /* HELPER_STRING may still contain C comments. Argh. */
899 crc = crc_eliding_c_comments (namebuf, crc);
900 break;
901 }
902
903 /* Other node types have no "substate" */
904 /* This code is written in this curious fashion because we
905 * want the generated CRC to be independent of the particular
906 * values a particular version of lex/bison assigned to various states.
907 */
908
909 /* case NAME: crc = CRC16 (crc, 257); break; */
910 case RPAR: crc = CRC16 (crc, 258); break;
911 case LPAR: crc = CRC16 (crc, 259); break;
912 case SEMI: crc = CRC16 (crc, 260); break;
913 case LBRACK: crc = CRC16 (crc, 261); break;
914 case RBRACK: crc = CRC16 (crc, 262); break;
915 /* case NUMBER: crc = CRC16 (crc, 263); break; */
916 /* case PRIMTYPE: crc = CRC16 (crc, 264); break; */
917 case BARF: crc = CRC16 (crc, 265); break;
918 case TPACKED: crc = CRC16 (crc, 266); break;
919 case DEFINE: crc = CRC16 (crc, 267); break;
920 case LCURLY: crc = CRC16 (crc, 268); break;
921 case RCURLY: crc = CRC16 (crc, 269); break;
922 /* case STRING: crc = CRC16 (crc, 270); break; */
923 case UNION: crc = CRC16 (crc, 271); break;
924 /* case HELPER_STRING: crc = CRC16 (crc, 272); break; */
925 case COMMA: crc = CRC16 (crc, 273); break;
926 case NOVERSION: crc = CRC16 (crc, 274); break;
927 case MANUAL_PRINT: crc = CRC16 (crc, 275); break;
928 case MANUAL_ENDIAN: crc = CRC16 (crc, 276); break;
929 case MANUAL_JAVA: crc = CRC16 (crc, 277); break;
930 case TYPEONLY: crc = CRC16 (crc, 278); break;
931 case DONT_TRACE: crc = CRC16 (crc, 279); break;
932
933 case EOF: crc = CRC16 (crc, ~0); break; /* hysterical compatibility */
934
935 default:
936 fprintf(stderr, "yylex: node_type %d missing state CRC cookie\n",
937 node_type);
938 exit(1);
939 }
940
941 input_crc = crc;
942 return (node_type);
943}
944
945
946/*
947 * name_check -- see if the name we just ate
948 * matches a known keyword. If so, set yylval
949 * to a new instance of <subclass of node>, and return PARSER_MACRO
950 *
951 * Otherwise, set yylval to sxerox (s) and return NAME
952 */
953
954static struct keytab {
955 char *name;
956 enum node_subclass subclass_id;
957} keytab [] =
958/* Keep the table sorted, binary search used below! */
959{
960 {"define", NODE_DEFINE},
961 {"dont_trace", NODE_DONT_TRACE},
962 {"f64", NODE_F64},
963 {"i16", NODE_I16},
964 {"i32", NODE_I32},
965 {"i64", NODE_I64},
966 {"i8", NODE_I8},
967 {"manual_endian", NODE_MANUAL_ENDIAN},
968 {"manual_java", NODE_MANUAL_JAVA},
969 {"manual_print", NODE_MANUAL_PRINT},
970 {"noversion", NODE_NOVERSION},
971 {"packed", NODE_PACKED},
972 {"typeonly", NODE_TYPEONLY},
973 {"u16", NODE_U16},
974 {"u32", NODE_U32},
975 {"u64", NODE_U64},
976 {"u8", NODE_U8},
977 {"union", NODE_UNION},
978 {"uword", NODE_UWORD},
979};
980
981static int name_check (const char *s, YYSTYPE *token_value)
982{
983 enum node_subclass subclass_id;
984 int top, bot, mid;
985 int result;
986
987 for (top = 0, bot = (sizeof(keytab) / sizeof(struct keytab))-1;
988 bot >= top; ) {
989 mid = (top + bot) / 2;
990 result = name_compare (s, keytab[mid].name);
991 if (result < 0)
992 bot = mid - 1;
993 else if (result > 0)
994 top = mid + 1;
995 else {
996 subclass_id = keytab[mid].subclass_id;
997
998 switch (subclass_id) {
999 case NODE_U8:
1000 case NODE_U16:
1001 case NODE_U32:
1002 case NODE_U64:
1003 case NODE_I8:
1004 case NODE_I16:
1005 case NODE_I32:
1006 case NODE_I64:
1007 case NODE_F64:
1008 case NODE_UWORD:
1009 *token_value = make_node(subclass_id);
1010 return (PRIMTYPE);
1011
1012 case NODE_PACKED:
1013 *token_value = make_node(subclass_id);
1014 return (TPACKED);
1015
1016 case NODE_DEFINE:
1017 *token_value = make_node(subclass_id);
1018 return(DEFINE);
1019
1020 case NODE_MANUAL_PRINT:
1021 *token_value = (YYSTYPE) NODE_FLAG_MANUAL_PRINT;
1022 return (MANUAL_PRINT);
1023
1024 case NODE_MANUAL_ENDIAN:
1025 *token_value = (YYSTYPE) NODE_FLAG_MANUAL_ENDIAN;
1026 return (MANUAL_ENDIAN);
1027
1028 case NODE_MANUAL_JAVA:
1029 *token_value = (YYSTYPE) NODE_FLAG_MANUAL_JAVA;
1030 return (MANUAL_JAVA);
1031
1032 case NODE_TYPEONLY:
1033 *token_value = (YYSTYPE) NODE_FLAG_TYPEONLY;
1034 return(TYPEONLY);
1035
1036 case NODE_DONT_TRACE:
1037 *token_value = (YYSTYPE) NODE_FLAG_DONT_TRACE;
1038 return(DONT_TRACE);
1039
1040 case NODE_NOVERSION:
1041 return(NOVERSION);
1042
1043 case NODE_UNION:
1044 return(UNION);
1045
1046 default:
1047 fprintf (stderr, "fatal: keytab botch!\n");
1048 exit (1);
1049 }
1050 }
1051 }
1052 *token_value = (YYSTYPE) sxerox (s);
1053 return (NAME);
1054}
1055
1056/*
1057 * sxerox
1058 */
1059
1060char *sxerox (const char *s)
1061{
1062 int len = strlen (s);
1063 char *rv;
1064
1065 rv = (char *) malloc (len+1);
1066 strcpy (rv, s);
1067 return (rv);
1068}
1069
1070/*
1071 * name_compare
1072 */
1073
1074int name_compare (const char *s1, const char *s2)
1075{
1076 char c1, c2;
1077
1078 while (*s1 && *s2) {
1079 c1 = *s1++;
1080 c2 = *s2++;
1081
1082 c1 = tolower (c1);
1083 c2 = tolower (c2);
1084 if (c1 < c2)
1085 return (-1);
1086 else if (c1 > c2)
1087 return (1);
1088 }
1089 if (*s1 < *s2)
1090 return (-1);
1091 else if (*s1 > *s2)
1092 return (1);
1093 return (0);
1094}