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