1 /* scan.l - scanner for flex input */ 2 3 %{ 4 /*- 5 * Copyright (c) 1990 The Regents of the University of California. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to Berkeley by 9 * Vern Paxson. 10 * 11 * The United States Government has rights in this work pursuant 12 * to contract no. DE-AC03-76SF00098 between the United States 13 * Department of Energy and the University of California. 14 * 15 * Redistribution and use in source and binary forms with or without 16 * modification are permitted provided that: (1) source distributions retain 17 * this entire copyright notice and comment, and (2) distributions including 18 * binaries display the following acknowledgement: ``This product includes 19 * software developed by the University of California, Berkeley and its 20 * contributors'' in the documentation or other materials provided with the 21 * distribution and in all advertising materials mentioning features or use 22 * of this software. Neither the name of the University nor the names of 23 * its contributors may be used to endorse or promote products derived from 24 * this software without specific prior written permission. 25 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 26 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 27 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 28 */ 29 30 /* $Header: /home/daffy/u0/vern/flex/RCS/scan.l,v 2.56 95/04/24 12:17:19 vern Exp $ */ 31 32 #include "flexdef.h" 33 #include "parse.h" 34 35 #define ACTION_ECHO add_action( yytext ) 36 #define ACTION_IFDEF(def, should_define) \ 37 { \ 38 if ( should_define ) \ 39 action_define( def, 1 ); \ 40 } 41 42 #define MARK_END_OF_PROLOG mark_prolog(); 43 44 #define YY_DECL \ 45 int flexscan() 46 47 #define RETURNCHAR \ 48 yylval = (unsigned char) yytext[0]; \ 49 return CHAR; 50 51 #define RETURNNAME \ 52 strcpy( nmstr, yytext ); \ 53 return NAME; 54 55 #define PUT_BACK_STRING(str, start) \ 56 for ( i = strlen( str ) - 1; i >= start; --i ) \ 57 unput((str)[i]) 58 59 #define CHECK_REJECT(str) \ 60 if ( all_upper( str ) ) \ 61 reject = true; 62 63 #define CHECK_YYMORE(str) \ 64 if ( all_lower( str ) ) \ 65 yymore_used = true; 66 %} 67 68 %option caseless nodefault outfile="scan.c" stack noyy_top_state 69 %option nostdinit 70 71 %x SECT2 SECT2PROLOG SECT3 CODEBLOCK PICKUPDEF SC CARETISBOL NUM QUOTE 72 %x FIRSTCCL CCL ACTION RECOVER COMMENT ACTION_STRING PERCENT_BRACE_ACTION 73 %x OPTION LINEDIR 74 75 WS [[:blank:]]+ 76 OPTWS [[:blank:]]* 77 NOT_WS [^[:blank:]\n] 78 79 NL \r?\n 80 81 NAME ([[:alpha:]_][[:alnum:]_-]*) 82 NOT_NAME [^[:alpha:]_*\n]+ 83 84 SCNAME {NAME} 85 86 ESCSEQ (\\([^\n]|[0-7]{1,3}|x[[:xdigit:]]{1,2})) 87 88 FIRST_CCL_CHAR ([^\\\n]|{ESCSEQ}) 89 CCL_CHAR ([^\\\n\]]|{ESCSEQ}) 90 CCL_EXPR ("[:"[[:alpha:]]+":]") 91 92 LEXOPT [aceknopr] 93 94 %% 95 static int bracelevel, didadef, indented_code; 96 static int doing_rule_action = false; 97 static int option_sense; 98 99 int doing_codeblock = false; 100 int i; 101 Char nmdef[MAXLINE], myesc(); 102 103 104 <INITIAL>{ 105 ^{WS} indented_code = true; BEGIN(CODEBLOCK); 106 ^"/*" ACTION_ECHO; yy_push_state( COMMENT ); 107 ^#{OPTWS}line{WS} yy_push_state( LINEDIR ); 108 ^"%s"{NAME}? return SCDECL; 109 ^"%x"{NAME}? return XSCDECL; 110 ^"%{".*{NL} { 111 ++linenum; 112 line_directive_out( (FILE *) 0, 1 ); 113 indented_code = false; 114 BEGIN(CODEBLOCK); 115 } 116 117 {WS} /* discard */ 118 119 ^"%%".* { 120 sectnum = 2; 121 bracelevel = 0; 122 mark_defs1(); 123 line_directive_out( (FILE *) 0, 1 ); 124 BEGIN(SECT2PROLOG); 125 return SECTEND; 126 } 127 128 ^"%pointer".*{NL} yytext_is_array = false; ++linenum; 129 ^"%array".*{NL} yytext_is_array = true; ++linenum; 130 131 ^"%option" BEGIN(OPTION); return OPTION_OP; 132 133 ^"%"{LEXOPT}{OPTWS}[[:digit:]]*{OPTWS}{NL} ++linenum; /* ignore */ 134 ^"%"{LEXOPT}{WS}.*{NL} ++linenum; /* ignore */ 135 136 ^"%"[^sxaceknopr{}].* synerr( _( "unrecognized '%' directive" ) ); 137 138 ^{NAME} { 139 strcpy( nmstr, yytext ); 140 didadef = false; 141 BEGIN(PICKUPDEF); 142 } 143 144 {SCNAME} RETURNNAME; 145 ^{OPTWS}{NL} ++linenum; /* allows blank lines in section 1 */ 146 {OPTWS}{NL} ACTION_ECHO; ++linenum; /* maybe end of comment line */ 147 } 148 149 150 <COMMENT>{ 151 "*/" ACTION_ECHO; yy_pop_state(); 152 "*" ACTION_ECHO; 153 [^*\n]+ ACTION_ECHO; 154 [^*\n]*{NL} ++linenum; ACTION_ECHO; 155 } 156 157 <LINEDIR>{ 158 \n yy_pop_state(); 159 [[:digit:]]+ linenum = myctoi( yytext ); 160 161 \"[^"\n]*\" { 162 flex_free( (void *) infilename ); 163 infilename = copy_string( yytext + 1 ); 164 infilename[strlen( infilename ) - 1] = '\0'; 165 } 166 . /* ignore spurious characters */ 167 } 168 169 <CODEBLOCK>{ 170 ^"%}".*{NL} ++linenum; BEGIN(INITIAL); 171 172 {NAME}|{NOT_NAME}|. ACTION_ECHO; 173 174 {NL} { 175 ++linenum; 176 ACTION_ECHO; 177 if ( indented_code ) 178 BEGIN(INITIAL); 179 } 180 } 181 182 183 <PICKUPDEF>{ 184 {WS} /* separates name and definition */ 185 186 {NOT_WS}.* { 187 strcpy( (char *) nmdef, yytext ); 188 189 /* Skip trailing whitespace. */ 190 for ( i = strlen( (char *) nmdef ) - 1; 191 i >= 0 && (nmdef[i] == ' ' || nmdef[i] == '\t'); 192 --i ) 193 ; 194 195 nmdef[i + 1] = '\0'; 196 197 ndinstal( nmstr, nmdef ); 198 didadef = true; 199 } 200 201 {NL} { 202 if ( ! didadef ) 203 synerr( _( "incomplete name definition" ) ); 204 BEGIN(INITIAL); 205 ++linenum; 206 } 207 } 208 209 210 <OPTION>{ 211 {NL} ++linenum; BEGIN(INITIAL); 212 {WS} option_sense = true; 213 214 "=" return '='; 215 216 no option_sense = ! option_sense; 217 218 7bit csize = option_sense ? 128 : 256; 219 8bit csize = option_sense ? 256 : 128; 220 221 align long_align = option_sense; 222 always-interactive { 223 action_define( "YY_ALWAYS_INTERACTIVE", option_sense ); 224 } 225 array yytext_is_array = option_sense; 226 backup backing_up_report = option_sense; 227 batch interactive = ! option_sense; 228 "c++" C_plus_plus = option_sense; 229 caseful|case-sensitive caseins = ! option_sense; 230 caseless|case-insensitive caseins = option_sense; 231 debug ddebug = option_sense; 232 default spprdflt = ! option_sense; 233 ecs useecs = option_sense; 234 fast { 235 useecs = usemecs = false; 236 use_read = fullspd = true; 237 } 238 full { 239 useecs = usemecs = false; 240 use_read = fulltbl = true; 241 } 242 input ACTION_IFDEF("YY_NO_INPUT", ! option_sense); 243 interactive interactive = option_sense; 244 lex-compat lex_compat = option_sense; 245 main { 246 action_define( "YY_MAIN", option_sense ); 247 do_yywrap = ! option_sense; 248 } 249 meta-ecs usemecs = option_sense; 250 never-interactive { 251 action_define( "YY_NEVER_INTERACTIVE", option_sense ); 252 } 253 perf-report performance_report += option_sense ? 1 : -1; 254 pointer yytext_is_array = ! option_sense; 255 read use_read = option_sense; 256 reject reject_really_used = option_sense; 257 stack action_define( "YY_STACK_USED", option_sense ); 258 stdinit do_stdinit = option_sense; 259 stdout use_stdout = option_sense; 260 unput ACTION_IFDEF("YY_NO_UNPUT", ! option_sense); 261 verbose printstats = option_sense; 262 warn nowarn = ! option_sense; 263 yylineno do_yylineno = option_sense; 264 yymore yymore_really_used = option_sense; 265 yywrap do_yywrap = option_sense; 266 267 yy_push_state ACTION_IFDEF("YY_NO_PUSH_STATE", ! option_sense); 268 yy_pop_state ACTION_IFDEF("YY_NO_POP_STATE", ! option_sense); 269 yy_top_state ACTION_IFDEF("YY_NO_TOP_STATE", ! option_sense); 270 271 yy_scan_buffer ACTION_IFDEF("YY_NO_SCAN_BUFFER", ! option_sense); 272 yy_scan_bytes ACTION_IFDEF("YY_NO_SCAN_BYTES", ! option_sense); 273 yy_scan_string ACTION_IFDEF("YY_NO_SCAN_STRING", ! option_sense); 274 275 outfile return OPT_OUTFILE; 276 prefix return OPT_PREFIX; 277 yyclass return OPT_YYCLASS; 278 279 \"[^"\n]*\" { 280 strcpy( nmstr, yytext + 1 ); 281 nmstr[strlen( nmstr ) - 1] = '\0'; 282 return NAME; 283 } 284 285 (([a-mo-z]|n[a-np-z])[[:alpha:]\-+]*)|. { 286 format_synerr( _( "unrecognized %%option: %s" ), 287 yytext ); 288 BEGIN(RECOVER); 289 } 290 } 291 292 <RECOVER>.*{NL} ++linenum; BEGIN(INITIAL); 293 294 295 <SECT2PROLOG>{ 296 ^"%{".* ++bracelevel; yyless( 2 ); /* eat only %{ */ 297 ^"%}".* --bracelevel; yyless( 2 ); /* eat only %} */ 298 299 ^{WS}.* ACTION_ECHO; /* indented code in prolog */ 300 301 ^{NOT_WS}.* { /* non-indented code */ 302 if ( bracelevel <= 0 ) 303 { /* not in %{ ... %} */ 304 yyless( 0 ); /* put it all back */ 305 yy_set_bol( 1 ); 306 mark_prolog(); 307 BEGIN(SECT2); 308 } 309 else 310 ACTION_ECHO; 311 } 312 313 .* ACTION_ECHO; 314 {NL} ++linenum; ACTION_ECHO; 315 316 <<EOF>> { 317 mark_prolog(); 318 sectnum = 0; 319 yyterminate(); /* to stop the parser */ 320 } 321 } 322 323 <SECT2>{ 324 ^{OPTWS}{NL} ++linenum; /* allow blank lines in section 2 */ 325 326 ^{OPTWS}"%{" { 327 indented_code = false; 328 doing_codeblock = true; 329 bracelevel = 1; 330 BEGIN(PERCENT_BRACE_ACTION); 331 } 332 333 ^{OPTWS}"<" BEGIN(SC); return '<'; 334 ^{OPTWS}"^" return '^'; 335 \" BEGIN(QUOTE); return '"'; 336 "{"/[[:digit:]] BEGIN(NUM); return '{'; 337 "$"/([[:blank:]]|{NL}) return '$'; 338 339 {WS}"%{" { 340 bracelevel = 1; 341 BEGIN(PERCENT_BRACE_ACTION); 342 343 if ( in_rule ) 344 { 345 doing_rule_action = true; 346 in_rule = false; 347 return '\n'; 348 } 349 } 350 {WS}"|".*{NL} continued_action = true; ++linenum; return '\n'; 351 352 ^{WS}"/*" { 353 yyless( yyleng - 2 ); /* put back '/', '*' */ 354 bracelevel = 0; 355 continued_action = false; 356 BEGIN(ACTION); 357 } 358 359 ^{WS} /* allow indented rules */ 360 361 {WS} { 362 /* This rule is separate from the one below because 363 * otherwise we get variable trailing context, so 364 * we can't build the scanner using -{f,F}. 365 */ 366 bracelevel = 0; 367 continued_action = false; 368 BEGIN(ACTION); 369 370 if ( in_rule ) 371 { 372 doing_rule_action = true; 373 in_rule = false; 374 return '\n'; 375 } 376 } 377 378 {OPTWS}{NL} { 379 bracelevel = 0; 380 continued_action = false; 381 BEGIN(ACTION); 382 unput( '\n' ); /* so <ACTION> sees it */ 383 384 if ( in_rule ) 385 { 386 doing_rule_action = true; 387 in_rule = false; 388 return '\n'; 389 } 390 } 391 392 ^{OPTWS}"<<EOF>>" | 393 "<<EOF>>" return EOF_OP; 394 395 ^"%%".* { 396 sectnum = 3; 397 BEGIN(SECT3); 398 yyterminate(); /* to stop the parser */ 399 } 400 401 "["({FIRST_CCL_CHAR}|{CCL_EXPR})({CCL_CHAR}|{CCL_EXPR})* { 402 int cclval; 403 404 strcpy( nmstr, yytext ); 405 406 /* Check to see if we've already encountered this 407 * ccl. 408 */ 409 if ( (cclval = ccllookup( (Char *) nmstr )) != 0 ) 410 { 411 if ( input() != ']' ) 412 synerr( _( "bad character class" ) ); 413 414 yylval = cclval; 415 ++cclreuse; 416 return PREVCCL; 417 } 418 else 419 { 420 /* We fudge a bit. We know that this ccl will 421 * soon be numbered as lastccl + 1 by cclinit. 422 */ 423 cclinstal( (Char *) nmstr, lastccl + 1 ); 424 425 /* Push back everything but the leading bracket 426 * so the ccl can be rescanned. 427 */ 428 yyless( 1 ); 429 430 BEGIN(FIRSTCCL); 431 return '['; 432 } 433 } 434 435 "{"{NAME}"}" { 436 register Char *nmdefptr; 437 Char *ndlookup(); 438 439 strcpy( nmstr, yytext + 1 ); 440 nmstr[yyleng - 2] = '\0'; /* chop trailing brace */ 441 442 if ( (nmdefptr = ndlookup( nmstr )) == 0 ) 443 format_synerr( 444 _( "undefined definition {%s}" ), 445 nmstr ); 446 447 else 448 { /* push back name surrounded by ()'s */ 449 int len = strlen( (char *) nmdefptr ); 450 451 if ( lex_compat || nmdefptr[0] == '^' || 452 (len > 0 && nmdefptr[len - 1] == '$') ) 453 { /* don't use ()'s after all */ 454 PUT_BACK_STRING((char *) nmdefptr, 0); 455 456 if ( nmdefptr[0] == '^' ) 457 BEGIN(CARETISBOL); 458 } 459 460 else 461 { 462 unput(')'); 463 PUT_BACK_STRING((char *) nmdefptr, 0); 464 unput('('); 465 } 466 } 467 } 468 469 [/|*+?.(){}] return (unsigned char) yytext[0]; 470 . RETURNCHAR; 471 } 472 473 474 <SC>{ 475 [,*] return (unsigned char) yytext[0]; 476 ">" BEGIN(SECT2); return '>'; 477 ">"/^ BEGIN(CARETISBOL); return '>'; 478 {SCNAME} RETURNNAME; 479 . { 480 format_synerr( _( "bad <start condition>: %s" ), 481 yytext ); 482 } 483 } 484 485 <CARETISBOL>"^" BEGIN(SECT2); return '^'; 486 487 488 <QUOTE>{ 489 [^"\n] RETURNCHAR; 490 \" BEGIN(SECT2); return '"'; 491 492 {NL} { 493 synerr( _( "missing quote" ) ); 494 BEGIN(SECT2); 495 ++linenum; 496 return '"'; 497 } 498 } 499 500 501 <FIRSTCCL>{ 502 "^"/[^-\]\n] BEGIN(CCL); return '^'; 503 "^"/("-"|"]") return '^'; 504 . BEGIN(CCL); RETURNCHAR; 505 } 506 507 <CCL>{ 508 -/[^\]\n] return '-'; 509 [^\]\n] RETURNCHAR; 510 "]" BEGIN(SECT2); return ']'; 511 .|{NL} { 512 synerr( _( "bad character class" ) ); 513 BEGIN(SECT2); 514 return ']'; 515 } 516 } 517 518 <FIRSTCCL,CCL>{ 519 "[:alnum:]" BEGIN(CCL); return CCE_ALNUM; 520 "[:alpha:]" BEGIN(CCL); return CCE_ALPHA; 521 "[:blank:]" BEGIN(CCL); return CCE_BLANK; 522 "[:cntrl:]" BEGIN(CCL); return CCE_CNTRL; 523 "[:digit:]" BEGIN(CCL); return CCE_DIGIT; 524 "[:graph:]" BEGIN(CCL); return CCE_GRAPH; 525 "[:lower:]" BEGIN(CCL); return CCE_LOWER; 526 "[:print:]" BEGIN(CCL); return CCE_PRINT; 527 "[:punct:]" BEGIN(CCL); return CCE_PUNCT; 528 "[:space:]" BEGIN(CCL); return CCE_SPACE; 529 "[:upper:]" BEGIN(CCL); return CCE_UPPER; 530 "[:xdigit:]" BEGIN(CCL); return CCE_XDIGIT; 531 {CCL_EXPR} { 532 format_synerr( 533 _( "bad character class expression: %s" ), 534 yytext ); 535 BEGIN(CCL); return CCE_ALNUM; 536 } 537 } 538 539 <NUM>{ 540 [[:digit:]]+ { 541 yylval = myctoi( yytext ); 542 return NUMBER; 543 } 544 545 "," return ','; 546 "}" BEGIN(SECT2); return '}'; 547 548 . { 549 synerr( _( "bad character inside {}'s" ) ); 550 BEGIN(SECT2); 551 return '}'; 552 } 553 554 {NL} { 555 synerr( _( "missing }" ) ); 556 BEGIN(SECT2); 557 ++linenum; 558 return '}'; 559 } 560 } 561 562 563 <PERCENT_BRACE_ACTION>{ 564 {OPTWS}"%}".* bracelevel = 0; 565 566 <ACTION>"/*" ACTION_ECHO; yy_push_state( COMMENT ); 567 568 <CODEBLOCK,ACTION>{ 569 "reject" { 570 ACTION_ECHO; 571 CHECK_REJECT(yytext); 572 } 573 "yymore" { 574 ACTION_ECHO; 575 CHECK_YYMORE(yytext); 576 } 577 } 578 579 {NAME}|{NOT_NAME}|. ACTION_ECHO; 580 {NL} { 581 ++linenum; 582 ACTION_ECHO; 583 if ( bracelevel == 0 || 584 (doing_codeblock && indented_code) ) 585 { 586 if ( doing_rule_action ) 587 add_action( "\tYY_BREAK\n" ); 588 589 doing_rule_action = doing_codeblock = false; 590 BEGIN(SECT2); 591 } 592 } 593 } 594 595 596 /* Reject and YYmore() are checked for above, in PERCENT_BRACE_ACTION */ 597 <ACTION>{ 598 "{" ACTION_ECHO; ++bracelevel; 599 "}" ACTION_ECHO; --bracelevel; 600 [^[:alpha:]_{}"'/\n]+ ACTION_ECHO; 601 {NAME} ACTION_ECHO; 602 "'"([^'\\\n]|\\.)*"'" ACTION_ECHO; /* character constant */ 603 \" ACTION_ECHO; BEGIN(ACTION_STRING); 604 {NL} { 605 ++linenum; 606 ACTION_ECHO; 607 if ( bracelevel == 0 ) 608 { 609 if ( doing_rule_action ) 610 add_action( "\tYY_BREAK\n" ); 611 612 doing_rule_action = false; 613 BEGIN(SECT2); 614 } 615 } 616 . ACTION_ECHO; 617 } 618 619 <ACTION_STRING>{ 620 [^"\\\n]+ ACTION_ECHO; 621 \\. ACTION_ECHO; 622 {NL} ++linenum; ACTION_ECHO; 623 \" ACTION_ECHO; BEGIN(ACTION); 624 . ACTION_ECHO; 625 } 626 627 <COMMENT,ACTION,ACTION_STRING><<EOF>> { 628 synerr( _( "EOF encountered inside an action" ) ); 629 yyterminate(); 630 } 631 632 633 <SECT2,QUOTE,FIRSTCCL,CCL>{ESCSEQ} { 634 yylval = myesc( (Char *) yytext ); 635 636 if ( YY_START == FIRSTCCL ) 637 BEGIN(CCL); 638 639 return CHAR; 640 } 641 642 643 <SECT3>{ 644 .*(\n?) ECHO; 645 <<EOF>> sectnum = 0; yyterminate(); 646 } 647 648 <*>.|\n format_synerr( _( "bad character: %s" ), yytext ); 649 650 %% 651 652 653 int yywrap() 654 { 655 if ( --num_input_files > 0 ) 656 { 657 set_input_file( *++input_files ); 658 return 0; 659 } 660 661 else 662 return 1; 663 } 664 665 666 /* set_input_file - open the given file (if NULL, stdin) for scanning */ 667 668 void set_input_file( file ) 669 char *file; 670 { 671 if ( file && strcmp( file, "-" ) ) 672 { 673 infilename = copy_string( file ); 674 yyin = fopen( infilename, "r" ); 675 676 if ( yyin == NULL ) 677 lerrsf( _( "can't open %s" ), file ); 678 } 679 680 else 681 { 682 yyin = stdin; 683 infilename = copy_string( "<stdin>" ); 684 } 685 686 linenum = 1; 687 } 688 689 690 /* Wrapper routines for accessing the scanner's malloc routines. */ 691 692 void *flex_alloc( size ) 693 size_t size; 694 { 695 return (void *) malloc( size ); 696 } 697 698 void *flex_realloc( ptr, size ) 699 void *ptr; 700 size_t size; 701 { 702 return (void *) realloc( ptr, size ); 703 } 704 705 void flex_free( ptr ) 706 void *ptr; 707 { 708 if ( ptr ) 709 free( ptr ); 710 } 711