cint_scanner.l (18076B)
1 /* 2 * 3 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 4 * 5 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 6 * 7 * File: cint_scanner.l 8 * Purpose: CINT Flex input file 9 */ 10 11 D [0-9] 12 L [a-zA-Z_] 13 H [a-fA-F0-9] 14 E [Ee][+-]?{D}+ 15 FS (f|F|l|L) 16 IS (u|U|l|L)* 17 18 19 %top { 20 21 #include "cint_config.h" 22 #include "cint_yy.h" 23 #include "cint_parser.h" 24 25 } 26 27 %{ 28 29 #include "cint_config.h" 30 31 #ifdef FILENAME_MAX 32 #define __INCLUDE_MAX_FILENAME FILENAME_MAX 33 #else 34 #define __INCLUDE_MAX_FILENAME 128 35 #endif 36 37 #ifndef CINT_MAX_INCLUDE_DEPTH 38 #define CINT_MAX_INCLUDE_DEPTH 64 39 #endif 40 41 struct cint_extra_type_s { 42 char currentFileName[__INCLUDE_MAX_FILENAME+1]; 43 char *includedFromFile; 44 int includedFromLine; 45 }; 46 47 #define YY_EXTRA_TYPE struct cint_extra_type_s * 48 49 #define YY_NO_INPUT 50 51 #if CINT_CONFIG_INCLUDE_PARSER == 1 52 53 #include <stdio.h> 54 #include "cint_ast.h" 55 #include "cint_c.tab.h" 56 #include "cint_interpreter.h" 57 #include "cint_porting.h" 58 #include <string.h> 59 60 int check_type(yyscan_t scanner); 61 62 int cint_scanner_prompt = 1; 63 int cint_scanner_echo = 0; 64 65 #define NOPROMPT() cint_scanner_prompt=0 66 67 struct yyguts_t; 68 void __yy_input(char* buf, int* result, int max_size, yyscan_t scanner); 69 70 #define YY_INPUT(buf, result, max_size) __yy_input((buf), &(result), (max_size), yyscanner) 71 72 %} 73 74 /* Rentrant Scanner */ 75 %option yylineno 76 %option nounput 77 %option reentrant 78 %option bison-bridge 79 %option bison-locations 80 %option prefix="cint_c_" 81 %option noyyalloc 82 %option noyyrealloc 83 %option noyyfree 84 %option noyy_scan_string 85 %option always-interactive 86 87 /* Exclusive condition while processing an include directive */ 88 %x incl comment 89 90 %% 91 int commentNesting = 0; 92 93 #include BEGIN(incl); 94 95 <incl>[ \t]+ /* Eat whitespace between include and filename */ 96 <incl>[^ \t\n]+ { 97 /* yytext is now the include filename */ 98 99 #if CINT_CONFIG_INCLUDE_XINCLUDE == 0 100 101 CINT_PRINTF 102 ("Cannot include '%s': #include support is not available in this configuration\n", 103 yytext); 104 BEGIN(INITIAL); 105 106 #else 107 108 FILE *cyyin = yyin; /* Save current input file. */ 109 int len; 110 char* fpath = NULL; 111 char fname[__INCLUDE_MAX_FILENAME]; 112 113 fname[sizeof(fname) - 1] = 0; 114 115 /* Allow quotes and angle brackets in include path */ 116 if (yytext[0] == '\"' || yytext[0] == '<') { 117 CINT_STRNCPY(fname, yytext + 1, sizeof(fname) - 1); 118 } else { 119 CINT_STRNCPY(fname, yytext, sizeof(fname) - 1); 120 } 121 len = CINT_STRLEN(fname); 122 if (fname[len - 1] == '\"' || fname[len - 1] == '>') { 123 fname[len - 1] = 0; 124 } 125 /* 126 * The scanner will allow us to push new files onto the stack until 127 * we run out of memory. In reality, we'll probably reach the process 128 * limit for maximum opened files first. In either case this way more 129 * open files than makes sense. It's more likely that we're run into 130 * some sort of recursive include condition. That being the case, we'll 131 * check against an abitrary maximum include depth here. 132 */ 133 if ((CINT_MAX_INCLUDE_DEPTH - 1) > yyg->yy_buffer_stack_top) { 134 if (cint_interpreter_include_get(fname, &fpath) == CINT_E_NONE) { 135 if (fpath) { 136 yyin = CINT_FOPEN(fpath, "r"); 137 } else { 138 yyin = CINT_FOPEN(fname, "r"); 139 } 140 (void)cint_cparser_include(1); 141 } else { 142 yyin = 0; 143 } 144 145 if (yyin == 0) { 146 CINT_PRINTF("Cannot open include file '%s'\n", fpath ? fpath : fname); 147 yyin = cyyin; 148 } else { 149 struct cint_extra_type_s *extra = cint_c_get_extra(yyscanner); 150 151 if (extra) { 152 struct cint_extra_type_s *lastInclude = &extra[yyg->yy_buffer_stack_top]; 153 struct cint_extra_type_s *newInclude = &extra[yyg->yy_buffer_stack_top + 1]; 154 CINT_STRNCPY(newInclude->currentFileName, fname, 155 __INCLUDE_MAX_FILENAME); 156 newInclude->includedFromFile = lastInclude->currentFileName; 157 newInclude->includedFromLine = cint_c_get_lineno(yyscanner); 158 } 159 yypush_buffer_state(yy_create_buffer(yyin, YY_BUF_SIZE, yyscanner), 160 yyscanner); 161 cint_c_set_lineno(1, yyscanner); 162 YY_CURRENT_BUFFER->yy_is_interactive = 0; 163 } 164 165 if (fpath) { 166 CINT_FREE(fpath); 167 } 168 } else { 169 CINT_PRINTF("Exceeded maximum include file depth of %d at include file '%s'\n", 170 CINT_MAX_INCLUDE_DEPTH, fname); 171 } 172 173 /* All success and error condition should reset to INITIAL state */ 174 BEGIN(INITIAL); 175 176 #endif /* CINT_CONFIG_INCLUDE_XINCLUDE */ 177 178 } 179 180 "/*" { commentNesting = 0; BEGIN(comment); } 181 <comment>[^*/\n]+ { /* Swallow stuff inside comments */ } 182 <comment>"*/" { if (commentNesting-- == 0) { BEGIN(INITIAL); } } 183 <comment>"/*" { commentNesting++; } 184 <comment>\n { /* Swallow newlines */ } 185 <comment>(\/|\*) { /* Swallow lone "*" and "/" */ } 186 <comment><<EOF>> { CINT_PRINTF("EOF encountered while processing comment.\n"); yyterminate(); } 187 188 <<EOF>> { 189 if (yyg->yy_buffer_stack_top) { 190 if (yyin) { 191 #if CINT_CONFIG_FILE_IO == 1 192 CINT_FCLOSE(yyin); 193 #endif 194 (void)cint_cparser_include(-1); 195 yyin = 0; 196 } 197 yypop_buffer_state(yyscanner); 198 } else { 199 yyterminate(); 200 } 201 } 202 203 "//".*$ { /* Swallow C++ style comments */ } 204 205 "auto" { NOPROMPT(); return(AUTO); } 206 "break" { NOPROMPT(); return(BREAK); } 207 "case" { NOPROMPT(); return(CASE); } 208 "char" { NOPROMPT(); return(CHAR); } 209 "const" { NOPROMPT(); return(CONST); } 210 "continue" { NOPROMPT(); return(CONTINUE); } 211 "default" { NOPROMPT(); return(DEFAULT); } 212 "do" { NOPROMPT(); return(DO); } 213 "double" { NOPROMPT(); return(DOUBLE); } 214 "else" { NOPROMPT(); return(ELSE); } 215 "enum" { NOPROMPT(); return(ENUM); } 216 "extern" { NOPROMPT(); return(EXTERN); } 217 "float" { NOPROMPT(); return(FLOAT); } 218 "for" { NOPROMPT(); return(FOR); } 219 "goto" { NOPROMPT(); return(GOTO); } 220 "if" { NOPROMPT(); return(IF); } 221 "int" { NOPROMPT(); return(INT); } 222 "long" { NOPROMPT(); return(LONG); } 223 "register" { NOPROMPT(); return(REGISTER); } 224 "return" { NOPROMPT(); return(RETURN); } 225 "short" { NOPROMPT(); return(SHORT); } 226 "signed" { NOPROMPT(); return(SIGNED); } 227 "sizeof" { NOPROMPT(); return(SIZEOF); } 228 "static" { NOPROMPT(); return(STATIC); } 229 "struct" { NOPROMPT(); return(STRUCT); } 230 "switch" { NOPROMPT(); return(SWITCH); } 231 "typedef" { NOPROMPT(); return(TYPEDEF); } 232 "union" { NOPROMPT(); return(UNION); } 233 "unsigned" { NOPROMPT(); return(UNSIGNED); } 234 "void" { NOPROMPT(); return(T_VOID); } 235 "volatile" { NOPROMPT(); return(VOLATILE); } 236 "while" { NOPROMPT(); return(WHILE); } 237 "print" { NOPROMPT(); return(PRINT); } 238 "cint" { NOPROMPT(); return(CINT); } 239 240 {L}({L}|{D})* { NOPROMPT(); return(check_type(yyscanner)); } 241 242 0[xX]{H}+{IS}? { *yylval = cint_ast_constant(yytext, cintAstConstHex); 243 NOPROMPT(); return(CONSTANT); } 244 0{D}+{IS}? { *yylval = cint_ast_constant(yytext, cintAstConstOctal); 245 NOPROMPT(); return(CONSTANT); } 246 {D}+{IS}? { *yylval = cint_ast_constant(yytext, cintAstConstDecimal); 247 NOPROMPT(); return(CONSTANT); } 248 L?'(\\.|[^\\'])+' { *yylval = cint_ast_constant(yytext, cintAstConstChar); 249 NOPROMPT(); return(CONSTANT); } 250 251 {D}+{E}{FS}? { *yylval = cint_ast_constant(yytext, cintAstConstFloat); 252 NOPROMPT(); return(CONSTANT); } 253 {D}*"."{D}+({E})?{FS}? { *yylval = cint_ast_constant(yytext, cintAstConstFloat); 254 NOPROMPT(); return(CONSTANT); } 255 {D}+"."{D}*({E})?{FS}? { *yylval = cint_ast_constant(yytext, cintAstConstFloat); 256 NOPROMPT(); return(CONSTANT); } 257 258 L?\"(\\.|[^\\"])*\" { *yylval = cint_ast_string(yytext); NOPROMPT(); return(STRING_LITERAL); } 259 260 "..." { NOPROMPT(); return(ELLIPSIS); } 261 ">>=" { NOPROMPT(); return(RIGHT_ASSIGN); } 262 "<<=" { NOPROMPT(); return(LEFT_ASSIGN); } 263 "+=" { NOPROMPT(); return(ADD_ASSIGN); } 264 "-=" { NOPROMPT(); return(SUB_ASSIGN); } 265 "*=" { NOPROMPT(); return(MUL_ASSIGN); } 266 "/=" { NOPROMPT(); return(DIV_ASSIGN); } 267 "%=" { NOPROMPT(); return(MOD_ASSIGN); } 268 "&=" { NOPROMPT(); return(AND_ASSIGN); } 269 "^=" { NOPROMPT(); return(XOR_ASSIGN); } 270 "|=" { NOPROMPT(); return(OR_ASSIGN); } 271 ">>" { NOPROMPT(); return(RIGHT_OP); } 272 "<<" { NOPROMPT(); return(LEFT_OP); } 273 "++" { NOPROMPT(); return(INC_OP); } 274 "--" { NOPROMPT(); return(DEC_OP); } 275 "->" { NOPROMPT(); return(PTR_OP); } 276 "&&" { NOPROMPT(); return(AND_OP); } 277 "||" { NOPROMPT(); return(OR_OP); } 278 "<=" { NOPROMPT(); return(LE_OP); } 279 ">=" { NOPROMPT(); return(GE_OP); } 280 "==" { NOPROMPT(); return(EQ_OP); } 281 "!=" { NOPROMPT(); return(NE_OP); } 282 ";" { NOPROMPT(); return(';'); } 283 ("{"|"<%") { NOPROMPT(); return('{'); } 284 ("}"|"%>") { NOPROMPT(); return('}'); } 285 "," { NOPROMPT(); return(','); } 286 ":" { NOPROMPT(); return(':'); } 287 "=" { NOPROMPT(); return('='); } 288 "(" { NOPROMPT(); return('('); } 289 ")" { NOPROMPT(); return(')'); } 290 ("["|"<:") { NOPROMPT(); return('['); } 291 ("]"|":>") { NOPROMPT(); return(']'); } 292 "." { NOPROMPT(); return('.'); } 293 "&" { NOPROMPT(); return('&'); } 294 "!" { NOPROMPT(); return('!'); } 295 "~" { NOPROMPT(); return('~'); } 296 "-" { NOPROMPT(); return('-'); } 297 "+" { NOPROMPT(); return('+'); } 298 "*" { NOPROMPT(); return('*'); } 299 "/" { NOPROMPT(); return('/'); } 300 "%" { NOPROMPT(); return('%'); } 301 "<" { NOPROMPT(); return('<'); } 302 ">" { NOPROMPT(); return('>'); } 303 "^" { NOPROMPT(); return('^'); } 304 "|" { NOPROMPT(); return('|'); } 305 "?" { NOPROMPT(); return('?'); } 306 307 [ \t\v\f]+ { /* Ignore white space */ } 308 \n+ { /* Swallow newlines, scanner will count them */ } 309 . { /* Swallow unknown characters [DEFAULT RULE] */ } 310 311 %% 312 313 #include "cint_error.h" 314 315 int yywrap(yyscan_t yyscanner) 316 { 317 cint_errno = CINT_E_EXIT; 318 return(1); 319 } 320 321 void cpp_comment(void) 322 { 323 324 } 325 326 /* cint_current_line() 327 * 328 * Get current input line from the scanner. Used to construct error messages 329 * issued from the parser. 330 * 331 * Inputs: 332 * yyscanner: Pointer to scanner control block. 333 * lineBuffer: Character buffer to receive current scan line. 334 * lineLen: Size of character buffer. 335 * column: Pointer to integer that will receive starting column of current 336 * token in scan line. 337 * tokLen: Pointer to integer that will receive length of current token. 338 * 339 * If current scan line doesn't fit into lineBuffer, trailing characters 340 * are truncated. If current token is beyond the truncated buffer, column 341 * and tokLen are set to zero. 342 */ 343 char * 344 cint_current_line(yyscan_t yyscanner, char *const lineBuffer, const int lineLen, 345 int *column, int *tokLen, char **curFile, int *curLine) 346 { 347 struct yyguts_t *yyg = (struct yyguts_t *) yyscanner; 348 struct cint_extra_type_s *extraInfo = cint_c_get_extra(yyscanner); 349 const char *buffStart = yyg->yy_buffer_stack[yyg->yy_buffer_stack_top]->yy_ch_buf; 350 const char *buffEnd = &buffStart[yyg->yy_n_chars]; 351 const char *copyEnd = &lineBuffer[lineLen - 1]; /* Leave room for terminator */ 352 char *copy = lineBuffer; 353 char *strPtr; 354 int tokenLen; 355 356 *column = 0; 357 *tokLen = 0; 358 tokenLen = 0; 359 360 if (*(yyg->yytext_r)) { 361 /* Back up to start of current line */ 362 for (strPtr = yyg->yytext_r; (strPtr >= buffStart) && (*strPtr != '\n'); 363 strPtr--); 364 strPtr++; 365 /* Copy current line. */ 366 for (; (strPtr < buffEnd) && (copy < copyEnd) && (*strPtr != '\n'); strPtr++) { 367 if (*strPtr) { 368 *copy++ = *strPtr; 369 if (strPtr < yyg->yytext_r) { 370 /* Count columns before current token. */ 371 if (*strPtr == '\t') { 372 /* Deal with tabs */ 373 *column = ((*column + 8) / 8) * 8; 374 } else { 375 *column += 1; 376 } 377 } else { 378 /* else count token characters */ 379 tokenLen++; 380 } 381 } else { 382 /* 383 * Scanner puts a null terminator at end of current token in 384 * current line. The saved character is held in "yy_hold_char". 385 */ 386 *tokLen = tokenLen; 387 if (yyg->yy_hold_char == '\n') { 388 /* Held character is the EOL character */ 389 break; 390 } 391 *copy++ = yyg->yy_hold_char; 392 } 393 } 394 } 395 *copy = 0; /* Null terminate */ 396 397 if (cint_cparser_interactive()) { 398 *curLine = 0; 399 *curFile = NULL; 400 } else { 401 *curLine = cint_c_get_lineno(yyscanner); 402 *curFile = 403 (extraInfo && extraInfo[yyg->yy_buffer_stack_top].currentFileName[0]) ? 404 extraInfo[yyg->yy_buffer_stack_top].currentFileName : NULL; 405 } 406 return lineBuffer; 407 } 408 409 int check_type(yyscan_t scanner) 410 { 411 int rv; 412 struct yyguts_t* yyg = (struct yyguts_t*)scanner; 413 414 char* _yytext = yyget_text(scanner); 415 416 if(cint_interpreter_is_type(_yytext)) { 417 rv = TYPE_NAME; 418 *yylval = cint_ast_type(_yytext); 419 } 420 else if(cint_interpreter_is_iterator(_yytext, yylval)) { 421 rv = ITERATOR; 422 } 423 else if(cint_interpreter_is_macro(_yytext, yylval)) { 424 rv = MACRO; 425 426 } 427 else { 428 rv = IDENTIFIER; 429 *yylval = cint_ast_identifier(_yytext); 430 } 431 return rv; 432 } 433 434 435 /******************************************************************************* 436 * 437 * YY_INPUT Functions 438 */ 439 440 #if CINT_CONFIG_INCLUDE_PARSER_READLINE == 1 441 442 /* YY_INPUT behavior using READLINE */ 443 void 444 __yy_input_readline(char* buf, int* result, int max_size, yyscan_t yyscanner) 445 { 446 struct yyguts_t* yyg = (struct yyguts_t*) yyscanner; 447 int rv; 448 449 rv = cint_cparser_input_readline(yyin, buf, result, max_size, 450 cint_scanner_prompt); 451 if (rv < 0) { 452 YY_FATAL_ERROR( "input in flex scanner failed" ); 453 } 454 } 455 456 #define CINT_YY_INPUT __yy_input_readline 457 458 #else 459 460 /* The default YY_INPUT behavior */ 461 void 462 __yy_input_default(char* buf, int* result, int max_size, yyscan_t yyscanner) 463 { 464 struct yyguts_t* yyg = (struct yyguts_t*) yyscanner; 465 int rv; 466 467 rv = cint_cparser_input_default(yyin, buf, result, max_size, 468 cint_scanner_prompt); 469 if (rv < 0) { 470 YY_FATAL_ERROR( "input in flex scanner failed" ); 471 } 472 } 473 474 /* The default YY_INPUT behavior with optional character echo */ 475 void 476 __yy_input_default_echo(char* buf, int* result, int max_size, yyscan_t yyscanner) 477 { 478 struct yyguts_t* yyg = (struct yyguts_t*) yyscanner; 479 int rv; 480 481 rv = cint_cparser_input_default_echo(yyin, buf, result, max_size, 482 cint_scanner_prompt, 483 cint_scanner_echo); 484 if (rv < 0) { 485 YY_FATAL_ERROR( "input in flex scanner failed" ); 486 } 487 } 488 489 #define CINT_YY_INPUT __yy_input_default 490 491 #endif /* CINT_CONFIG_INCLUDE_PARSER_READLINE */ 492 493 /* 494 * This is the YY_INPUT function called by the scanner. 495 */ 496 497 void 498 __yy_input(char* buf, int* result, int max_size, yyscan_t scanner) 499 { 500 CINT_YY_INPUT(buf, result, max_size, scanner); 501 } 502 503 504 void 505 cint_c_scanner_start(FILE* handle, void* scanner) 506 { 507 struct cint_extra_type_s *extraInfo; 508 509 if (handle == 0) { 510 /* Defaults to standard in */ 511 handle = stdin; 512 } 513 cint_c_restart(handle, scanner); 514 extraInfo = cint_c_get_extra(scanner); 515 if (extraInfo == 0) { 516 extraInfo = 517 cint_c_alloc(sizeof(struct cint_extra_type_s) * CINT_MAX_INCLUDE_DEPTH, 518 scanner); 519 extraInfo->currentFileName[0] = 0; 520 extraInfo->includedFromFile = NULL; 521 extraInfo->includedFromLine = -1; 522 cint_c_set_extra(extraInfo, scanner); 523 } 524 } 525 526 int 527 cint_c_scanner_finish(void *scanner) 528 { 529 struct cint_extra_type_s *extraInfo = cint_c_get_extra(scanner); 530 531 if (extraInfo) { 532 cint_c_free(extraInfo, scanner); 533 } 534 return cint_c_lex_destroy(scanner); 535 } 536 537 #else /* CINT_CONFIG_INCLUDE_PARSER */ 538 int cint_lexer_c_not_empty; 539 #endif 540