1 /* $NetBSD: scan.l,v 1.6 2014/10/30 18:44:05 christos Exp $ */ 2 3 /* scan.l - scanner for flex input -*-C-*- */ 4 5 %{ 6 /* Copyright (c) 1990 The Regents of the University of California. */ 7 /* All rights reserved. */ 8 9 /* This code is derived from software contributed to Berkeley by */ 10 /* Vern Paxson. */ 11 12 /* The United States Government has rights in this work pursuant */ 13 /* to contract no. DE-AC03-76SF00098 between the United States */ 14 /* Department of Energy and the University of California. */ 15 16 /* This file is part of flex. */ 17 18 /* Redistribution and use in source and binary forms, with or without */ 19 /* modification, are permitted provided that the following conditions */ 20 /* are met: */ 21 22 /* 1. Redistributions of source code must retain the above copyright */ 23 /* notice, this list of conditions and the following disclaimer. */ 24 /* 2. Redistributions in binary form must reproduce the above copyright */ 25 /* notice, this list of conditions and the following disclaimer in the */ 26 /* documentation and/or other materials provided with the distribution. */ 27 28 /* Neither the name of the University nor the names of its contributors */ 29 /* may be used to endorse or promote products derived from this software */ 30 /* without specific prior written permission. */ 31 32 /* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR */ 33 /* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED */ 34 /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */ 35 /* PURPOSE. */ 36 #include "flexdef.h" 37 __RCSID("$NetBSD: scan.l,v 1.6 2014/10/30 18:44:05 christos Exp $"); 38 39 #include "parse.h" 40 extern bool tablesverify, tablesext; 41 extern int trlcontxt; /* Set in parse.y for each rule. */ 42 extern const char *escaped_qstart, *escaped_qend; 43 44 #define ACTION_ECHO add_action( yytext ) 45 #define ACTION_IFDEF(def, should_define) \ 46 { \ 47 if ( should_define ) \ 48 action_define( def, 1 ); \ 49 } 50 51 #define ACTION_ECHO_QSTART add_action (escaped_qstart) 52 #define ACTION_ECHO_QEND add_action (escaped_qend) 53 54 #define ACTION_M4_IFDEF(def, should_define) \ 55 do{ \ 56 if ( should_define ) \ 57 buf_m4_define( &m4defs_buf, def, NULL);\ 58 else \ 59 buf_m4_undefine( &m4defs_buf, def);\ 60 } while(0) 61 62 #define MARK_END_OF_PROLOG mark_prolog(); 63 64 #define YY_DECL \ 65 int flexscan() 66 67 #define RETURNCHAR \ 68 yylval = (unsigned char) yytext[0]; \ 69 return CHAR; 70 71 #define RETURNNAME \ 72 if(yyleng < MAXLINE) \ 73 { \ 74 strlcpy( nmstr, yytext, sizeof(nmstr) ); \ 75 } \ 76 else \ 77 { \ 78 synerr(_("Input line too long\n")); \ 79 FLEX_EXIT(EXIT_FAILURE); \ 80 } \ 81 return NAME; 82 83 #define PUT_BACK_STRING(str, start) \ 84 for ( i = strlen( str ) - 1; i >= start; --i ) \ 85 unput((str)[i]) 86 87 #define CHECK_RE_JECT(str) \ 88 if ( all_upper( str ) ) \ 89 reject = true 90 91 #define CHECK_YYMORE(str) \ 92 if ( all_lower( str ) ) \ 93 yymore_used = true; 94 95 #define YY_USER_INIT \ 96 if ( getenv("POSIXLY_CORRECT") ) \ 97 posix_compat = true; 98 99 %} 100 101 %option caseless nodefault stack noyy_top_state 102 %option nostdinit 103 104 %x SECT2 SECT2PROLOG SECT3 CODEBLOCK PICKUPDEF SC CARETISBOL NUM QUOTE 105 %x FIRSTCCL CCL ACTION RECOVER COMMENT ACTION_STRING PERCENT_BRACE_ACTION 106 %x OPTION LINEDIR CODEBLOCK_MATCH_BRACE 107 %x GROUP_WITH_PARAMS 108 %x GROUP_MINUS_PARAMS 109 %x EXTENDED_COMMENT 110 %x COMMENT_DISCARD 111 112 WS [[:blank:]]+ 113 OPTWS [[:blank:]]* 114 NOT_WS [^[:blank:]\r\n] 115 116 NL \r?\n 117 118 NAME ([[:alpha:]_][[:alnum:]_-]*) 119 NOT_NAME [^[:alpha:]_*\n]+ 120 121 SCNAME {NAME} 122 123 ESCSEQ (\\([^\n]|[0-7]{1,3}|x[[:xdigit:]]{1,2})) 124 125 FIRST_CCL_CHAR ([^\\\n]|{ESCSEQ}) 126 CCL_CHAR ([^\\\n\]]|{ESCSEQ}) 127 CCL_EXPR ("[:"^?[[:alpha:]]+":]") 128 129 LEXOPT [aceknopr] 130 131 M4QSTART "[[" 132 M4QEND "]]" 133 134 %% 135 static int bracelevel, didadef, indented_code; 136 static int doing_rule_action = false; 137 static int option_sense; 138 139 int doing_codeblock = false; 140 int i, brace_depth=0, brace_start_line=0; 141 Char nmdef[MAXLINE]; 142 143 144 <INITIAL>{ 145 ^{WS} indented_code = true; BEGIN(CODEBLOCK); 146 ^"/*" ACTION_ECHO; yy_push_state( COMMENT ); 147 ^#{OPTWS}line{WS} yy_push_state( LINEDIR ); 148 ^"%s"{NAME}? return SCDECL; 149 ^"%x"{NAME}? return XSCDECL; 150 ^"%{".*{NL} { 151 ++linenum; 152 line_directive_out( (FILE *) 0, 1 ); 153 indented_code = false; 154 BEGIN(CODEBLOCK); 155 } 156 ^"%top"[[:blank:]]*"{"[[:blank:]]*{NL} { 157 brace_start_line = linenum; 158 ++linenum; 159 buf_linedir( &top_buf, infilename?infilename:"<stdin>", linenum); 160 brace_depth = 1; 161 yy_push_state(CODEBLOCK_MATCH_BRACE); 162 } 163 164 ^"%top".* synerr( _("malformed '%top' directive") ); 165 166 {WS} /* discard */ 167 168 ^"%%".* { 169 sectnum = 2; 170 bracelevel = 0; 171 mark_defs1(); 172 line_directive_out( (FILE *) 0, 1 ); 173 BEGIN(SECT2PROLOG); 174 return SECTEND; 175 } 176 177 ^"%pointer".*{NL} yytext_is_array = false; ++linenum; 178 ^"%array".*{NL} yytext_is_array = true; ++linenum; 179 180 ^"%option" BEGIN(OPTION); return OPTION_OP; 181 182 ^"%"{LEXOPT}{OPTWS}[[:digit:]]*{OPTWS}{NL} ++linenum; /* ignore */ 183 ^"%"{LEXOPT}{WS}.*{NL} ++linenum; /* ignore */ 184 185 /* xgettext: no-c-format */ 186 ^"%"[^sxaceknopr{}].* synerr( _( "unrecognized '%' directive" ) ); 187 188 ^{NAME} { 189 if(yyleng < MAXLINE) 190 { 191 strlcpy( nmstr, yytext, sizeof(nmstr) ); 192 } 193 else 194 { 195 synerr( _("Definition name too long\n")); 196 FLEX_EXIT(EXIT_FAILURE); 197 } 198 199 didadef = false; 200 BEGIN(PICKUPDEF); 201 } 202 203 {SCNAME} RETURNNAME; 204 ^{OPTWS}{NL} ++linenum; /* allows blank lines in section 1 */ 205 {OPTWS}{NL} ACTION_ECHO; ++linenum; /* maybe end of comment line */ 206 } 207 208 209 <COMMENT>{ 210 "*/" ACTION_ECHO; yy_pop_state(); 211 "*" ACTION_ECHO; 212 {M4QSTART} ACTION_ECHO_QSTART; 213 {M4QEND} ACTION_ECHO_QEND; 214 [^*\n] ACTION_ECHO; 215 {NL} ++linenum; ACTION_ECHO; 216 } 217 218 <COMMENT_DISCARD>{ 219 /* This is the same as COMMENT, but is discarded rather than output. */ 220 "*/" yy_pop_state(); 221 "*" ; 222 [^*\n] ; 223 {NL} ++linenum; 224 } 225 226 <EXTENDED_COMMENT>{ 227 ")" yy_pop_state(); 228 [^\n\)]+ ; 229 {NL} ++linenum; 230 } 231 232 <LINEDIR>{ 233 \n yy_pop_state(); 234 [[:digit:]]+ linenum = myctoi( yytext ); 235 236 \"[^"\n]*\" { 237 flex_free( (void *) infilename ); 238 infilename = copy_string( yytext + 1 ); 239 infilename[strlen( infilename ) - 1] = '\0'; 240 } 241 . /* ignore spurious characters */ 242 } 243 244 <CODEBLOCK>{ 245 ^"%}".*{NL} ++linenum; BEGIN(INITIAL); 246 247 {M4QSTART} ACTION_ECHO_QSTART; 248 {M4QEND} ACTION_ECHO_QEND; 249 . ACTION_ECHO; 250 251 {NL} { 252 ++linenum; 253 ACTION_ECHO; 254 if ( indented_code ) 255 BEGIN(INITIAL); 256 } 257 } 258 259 <CODEBLOCK_MATCH_BRACE>{ 260 "}" { 261 if( --brace_depth == 0){ 262 /* TODO: Matched. */ 263 yy_pop_state(); 264 }else 265 buf_strnappend(&top_buf, yytext, yyleng); 266 } 267 268 "{" { 269 brace_depth++; 270 buf_strnappend(&top_buf, yytext, yyleng); 271 } 272 273 {NL} { 274 ++linenum; 275 buf_strnappend(&top_buf, yytext, yyleng); 276 } 277 278 {M4QSTART} buf_strnappend(&top_buf, escaped_qstart, strlen(escaped_qstart)); 279 {M4QEND} buf_strnappend(&top_buf, escaped_qend, strlen(escaped_qend)); 280 281 [^{}\r\n] { 282 buf_strnappend(&top_buf, yytext, yyleng); 283 } 284 285 <<EOF>> { 286 linenum = brace_start_line; 287 synerr(_("Unmatched '{'")); 288 yyterminate(); 289 } 290 } 291 292 293 <PICKUPDEF>{ 294 {WS} /* separates name and definition */ 295 296 {NOT_WS}[^\r\n]* { 297 if(yyleng < MAXLINE) 298 { 299 strlcpy( (char *) nmdef, yytext, sizeof(nmdef) ); 300 } 301 else 302 { 303 format_synerr( _("Definition value for {%s} too long\n"), nmstr); 304 FLEX_EXIT(EXIT_FAILURE); 305 } 306 /* Skip trailing whitespace. */ 307 for ( i = strlen( (char *) nmdef ) - 1; 308 i >= 0 && (nmdef[i] == ' ' || nmdef[i] == '\t'); 309 --i ) 310 ; 311 312 nmdef[i + 1] = '\0'; 313 314 ndinstal( nmstr, nmdef ); 315 didadef = true; 316 } 317 318 {NL} { 319 if ( ! didadef ) 320 synerr( _( "incomplete name definition" ) ); 321 BEGIN(INITIAL); 322 ++linenum; 323 } 324 } 325 326 327 <OPTION>{ 328 {NL} ++linenum; BEGIN(INITIAL); 329 {WS} option_sense = true; 330 331 "=" return '='; 332 333 no option_sense = ! option_sense; 334 335 7bit csize = option_sense ? 128 : 256; 336 8bit csize = option_sense ? 256 : 128; 337 338 align long_align = option_sense; 339 always-interactive { 340 ACTION_M4_IFDEF( "M4""_YY_ALWAYS_INTERACTIVE", option_sense ); 341 interactive = option_sense; 342 } 343 array yytext_is_array = option_sense; 344 ansi-definitions ansi_func_defs = option_sense; 345 ansi-prototypes ansi_func_protos = option_sense; 346 backup backing_up_report = option_sense; 347 batch interactive = ! option_sense; 348 bison-bridge bison_bridge_lval = option_sense; 349 bison-locations { if((bison_bridge_lloc = option_sense)) 350 bison_bridge_lval = true; 351 } 352 "c++" C_plus_plus = option_sense; 353 caseful|case-sensitive sf_set_case_ins(!option_sense); 354 caseless|case-insensitive sf_set_case_ins(option_sense); 355 debug ddebug = option_sense; 356 default spprdflt = ! option_sense; 357 ecs useecs = option_sense; 358 fast { 359 useecs = usemecs = false; 360 use_read = fullspd = true; 361 } 362 full { 363 useecs = usemecs = false; 364 use_read = fulltbl = true; 365 } 366 input ACTION_IFDEF("YY_NO_INPUT", ! option_sense); 367 interactive interactive = option_sense; 368 lex-compat lex_compat = option_sense; 369 posix-compat posix_compat = option_sense; 370 main { 371 ACTION_M4_IFDEF( "M4""_YY_MAIN", option_sense); 372 /* Override yywrap */ 373 if( option_sense == true ) 374 do_yywrap = false; 375 } 376 meta-ecs usemecs = option_sense; 377 never-interactive { 378 ACTION_M4_IFDEF( "M4""_YY_NEVER_INTERACTIVE", option_sense ); 379 interactive = !option_sense; 380 } 381 perf-report performance_report += option_sense ? 1 : -1; 382 pointer yytext_is_array = ! option_sense; 383 read use_read = option_sense; 384 reentrant reentrant = option_sense; 385 reject reject_really_used = option_sense; 386 stack ACTION_M4_IFDEF( "M4""_YY_STACK_USED", option_sense ); 387 stdinit do_stdinit = option_sense; 388 stdout use_stdout = option_sense; 389 unistd ACTION_IFDEF("YY_NO_UNISTD_H", ! option_sense); 390 unput ACTION_M4_IFDEF("M4""_YY_NO_UNPUT", ! option_sense); 391 verbose printstats = option_sense; 392 warn nowarn = ! option_sense; 393 yylineno do_yylineno = option_sense; ACTION_M4_IFDEF("M4""_YY_USE_LINENO", option_sense); 394 yymore yymore_really_used = option_sense; 395 yywrap do_yywrap = option_sense; 396 397 yy_push_state ACTION_M4_IFDEF("M4""_YY_NO_PUSH_STATE", ! option_sense); 398 yy_pop_state ACTION_M4_IFDEF("M4""_YY_NO_POP_STATE", ! option_sense); 399 yy_top_state ACTION_M4_IFDEF("M4""_YY_NO_TOP_STATE", ! option_sense); 400 401 yy_scan_buffer ACTION_M4_IFDEF("M4""_YY_NO_SCAN_BUFFER", ! option_sense); 402 yy_scan_bytes ACTION_M4_IFDEF("M4""_YY_NO_SCAN_BYTES", ! option_sense); 403 yy_scan_string ACTION_M4_IFDEF("M4""_YY_NO_SCAN_STRING", ! option_sense); 404 405 yyalloc ACTION_M4_IFDEF("M4""_YY_NO_FLEX_ALLOC", ! option_sense); 406 yyrealloc ACTION_M4_IFDEF("M4""_YY_NO_FLEX_REALLOC", ! option_sense); 407 yyfree ACTION_M4_IFDEF("M4""_YY_NO_FLEX_FREE", ! option_sense); 408 409 yyget_debug ACTION_M4_IFDEF("M4""_YY_NO_GET_DEBUG", ! option_sense); 410 yyset_debug ACTION_M4_IFDEF("M4""_YY_NO_SET_DEBUG", ! option_sense); 411 yyget_extra ACTION_M4_IFDEF("M4""_YY_NO_GET_EXTRA", ! option_sense); 412 yyset_extra ACTION_M4_IFDEF("M4""_YY_NO_SET_EXTRA", ! option_sense); 413 yyget_leng ACTION_M4_IFDEF("M4""_YY_NO_GET_LENG", ! option_sense); 414 yyget_text ACTION_M4_IFDEF("M4""_YY_NO_GET_TEXT", ! option_sense); 415 yyget_lineno ACTION_M4_IFDEF("M4""_YY_NO_GET_LINENO", ! option_sense); 416 yyset_lineno ACTION_M4_IFDEF("M4""_YY_NO_SET_LINENO", ! option_sense); 417 yyget_in ACTION_M4_IFDEF("M4""_YY_NO_GET_IN", ! option_sense); 418 yyset_in ACTION_M4_IFDEF("M4""_YY_NO_SET_IN", ! option_sense); 419 yyget_out ACTION_M4_IFDEF("M4""_YY_NO_GET_OUT", ! option_sense); 420 yyset_out ACTION_M4_IFDEF("M4""_YY_NO_SET_OUT", ! option_sense); 421 yyget_lval ACTION_M4_IFDEF("M4""_YY_NO_GET_LVAL", ! option_sense); 422 yyset_lval ACTION_M4_IFDEF("M4""_YY_NO_SET_LVAL", ! option_sense); 423 yyget_lloc ACTION_M4_IFDEF("M4""_YY_NO_GET_LLOC", ! option_sense); 424 yyset_lloc ACTION_M4_IFDEF("M4""_YY_NO_SET_LLOC", ! option_sense); 425 426 extra-type return OPT_EXTRA_TYPE; 427 outfile return OPT_OUTFILE; 428 prefix return OPT_PREFIX; 429 yyclass return OPT_YYCLASS; 430 header(-file)? return OPT_HEADER; 431 tables-file return OPT_TABLES; 432 tables-verify { 433 tablesverify = option_sense; 434 if(!tablesext && option_sense) 435 tablesext = true; 436 } 437 438 439 \"[^"\n]*\" { 440 if(yyleng-1 < MAXLINE) 441 { 442 strlcpy( nmstr, yytext + 1, sizeof(nmstr) ); 443 } 444 else 445 { 446 synerr( _("Option line too long\n")); 447 FLEX_EXIT(EXIT_FAILURE); 448 } 449 nmstr[strlen( nmstr ) - 1] = '\0'; 450 return NAME; 451 } 452 453 (([a-mo-z]|n[a-np-z])[[:alpha:]\-+]*)|. { 454 format_synerr( _( "unrecognized %%option: %s" ), 455 yytext ); 456 BEGIN(RECOVER); 457 } 458 } 459 460 <RECOVER>.*{NL} ++linenum; BEGIN(INITIAL); 461 462 463 <SECT2PROLOG>{ 464 ^"%{".* ++bracelevel; yyless( 2 ); /* eat only %{ */ 465 ^"%}".* --bracelevel; yyless( 2 ); /* eat only %} */ 466 467 ^{WS}.* ACTION_ECHO; /* indented code in prolog */ 468 469 ^{NOT_WS}.* { /* non-indented code */ 470 if ( bracelevel <= 0 ) 471 { /* not in %{ ... %} */ 472 yyless( 0 ); /* put it all back */ 473 yy_set_bol( 1 ); 474 mark_prolog(); 475 BEGIN(SECT2); 476 } 477 else 478 ACTION_ECHO; 479 } 480 481 . ACTION_ECHO; 482 {NL} ++linenum; ACTION_ECHO; 483 484 <<EOF>> { 485 mark_prolog(); 486 sectnum = 0; 487 yyterminate(); /* to stop the parser */ 488 } 489 } 490 491 <SECT2>{ 492 ^{OPTWS}{NL} ++linenum; /* allow blank lines in section 2 */ 493 494 ^{OPTWS}"%{" { 495 indented_code = false; 496 doing_codeblock = true; 497 bracelevel = 1; 498 BEGIN(PERCENT_BRACE_ACTION); 499 } 500 501 ^{OPTWS}"<" { 502 /* Allow "<" to appear in (?x) patterns. */ 503 if (!sf_skip_ws()) 504 BEGIN(SC); 505 return '<'; 506 } 507 ^{OPTWS}"^" return '^'; 508 \" BEGIN(QUOTE); return '"'; 509 "{"/[[:digit:]] { 510 BEGIN(NUM); 511 if ( lex_compat || posix_compat ) 512 return BEGIN_REPEAT_POSIX; 513 else 514 return BEGIN_REPEAT_FLEX; 515 } 516 "$"/([[:blank:]]|{NL}) return '$'; 517 518 {WS}"%{" { 519 bracelevel = 1; 520 BEGIN(PERCENT_BRACE_ACTION); 521 522 if ( in_rule ) 523 { 524 doing_rule_action = true; 525 in_rule = false; 526 return '\n'; 527 } 528 } 529 {WS}"|".*{NL} { 530 if (sf_skip_ws()){ 531 /* We're in the middle of a (?x: ) pattern. */ 532 /* Push back everything starting at the "|" */ 533 size_t amt; 534 amt = strchr (yytext, '|') - yytext; 535 yyless(amt); 536 } 537 else { 538 continued_action = true; 539 ++linenum; 540 return '\n'; 541 } 542 } 543 544 ^{WS}"/*" { 545 546 if (sf_skip_ws()){ 547 /* We're in the middle of a (?x: ) pattern. */ 548 yy_push_state(COMMENT_DISCARD); 549 } 550 else{ 551 yyless( yyleng - 2 ); /* put back '/', '*' */ 552 bracelevel = 0; 553 continued_action = false; 554 BEGIN(ACTION); 555 } 556 } 557 558 ^{WS} /* allow indented rules */ ; 559 560 {WS} { 561 if (sf_skip_ws()){ 562 /* We're in the middle of a (?x: ) pattern. */ 563 } 564 else{ 565 /* This rule is separate from the one below because 566 * otherwise we get variable trailing context, so 567 * we can't build the scanner using -{f,F}. 568 */ 569 bracelevel = 0; 570 continued_action = false; 571 BEGIN(ACTION); 572 573 if ( in_rule ) 574 { 575 doing_rule_action = true; 576 in_rule = false; 577 return '\n'; 578 } 579 } 580 } 581 582 {OPTWS}{NL} { 583 if (sf_skip_ws()){ 584 /* We're in the middle of a (?x: ) pattern. */ 585 ++linenum; 586 } 587 else{ 588 bracelevel = 0; 589 continued_action = false; 590 BEGIN(ACTION); 591 unput( '\n' ); /* so <ACTION> sees it */ 592 593 if ( in_rule ) 594 { 595 doing_rule_action = true; 596 in_rule = false; 597 return '\n'; 598 } 599 } 600 } 601 602 ^{OPTWS}"<<EOF>>" | 603 "<<EOF>>" return EOF_OP; 604 605 ^"%%".* { 606 sectnum = 3; 607 BEGIN(SECT3); 608 outn("/* Begin user sect3 */"); 609 yyterminate(); /* to stop the parser */ 610 } 611 612 "["({FIRST_CCL_CHAR}|{CCL_EXPR})({CCL_CHAR}|{CCL_EXPR})* { 613 int cclval; 614 615 if(yyleng < MAXLINE) 616 { 617 strlcpy( nmstr, yytext, sizeof(nmstr) ); 618 } 619 else 620 { 621 synerr( _("Input line too long\n")); 622 FLEX_EXIT(EXIT_FAILURE); 623 } 624 625 /* Check to see if we've already encountered this 626 * ccl. 627 */ 628 if (0 /* <--- This "0" effectively disables the reuse of a 629 * character class (purely based on its source text). 630 * The reason it was disabled is so yacc/bison can parse 631 * ccl operations, such as ccl difference and union. 632 */ 633 && (cclval = ccllookup( (Char *) nmstr )) != 0 ) 634 { 635 if ( input() != ']' ) 636 synerr( _( "bad character class" ) ); 637 638 yylval = cclval; 639 ++cclreuse; 640 return PREVCCL; 641 } 642 else 643 { 644 /* We fudge a bit. We know that this ccl will 645 * soon be numbered as lastccl + 1 by cclinit. 646 */ 647 cclinstal( (Char *) nmstr, lastccl + 1 ); 648 649 /* Push back everything but the leading bracket 650 * so the ccl can be rescanned. 651 */ 652 yyless( 1 ); 653 654 BEGIN(FIRSTCCL); 655 return '['; 656 } 657 } 658 "{-}" return CCL_OP_DIFF; 659 "{+}" return CCL_OP_UNION; 660 661 662 /* Check for :space: at the end of the rule so we don't 663 * wrap the expanded regex in '(' ')' -- breaking trailing 664 * context. 665 */ 666 "{"{NAME}"}"[[:space:]]? { 667 register Char *nmdefptr; 668 int end_is_ws, end_ch; 669 670 end_ch = yytext[yyleng-1]; 671 end_is_ws = end_ch != '}' ? 1 : 0; 672 673 if(yyleng-1 < MAXLINE) 674 { 675 strlcpy( nmstr, yytext + 1, sizeof(nmstr) ); 676 } 677 else 678 { 679 synerr( _("Input line too long\n")); 680 FLEX_EXIT(EXIT_FAILURE); 681 } 682 nmstr[yyleng - 2 - end_is_ws] = '\0'; /* chop trailing brace */ 683 684 if ( (nmdefptr = ndlookup( nmstr )) == 0 ) 685 format_synerr( 686 _( "undefined definition {%s}" ), 687 nmstr ); 688 689 else 690 { /* push back name surrounded by ()'s */ 691 int len = strlen( (char *) nmdefptr ); 692 if (end_is_ws) 693 unput(end_ch); 694 695 if ( lex_compat || nmdefptr[0] == '^' || 696 (len > 0 && nmdefptr[len - 1] == '$') 697 || (end_is_ws && trlcontxt && !sf_skip_ws())) 698 { /* don't use ()'s after all */ 699 PUT_BACK_STRING((char *) nmdefptr, 0); 700 701 if ( nmdefptr[0] == '^' ) 702 BEGIN(CARETISBOL); 703 } 704 705 else 706 { 707 unput(')'); 708 PUT_BACK_STRING((char *) nmdefptr, 0); 709 unput('('); 710 } 711 } 712 } 713 714 "/*" { 715 if (sf_skip_ws()) 716 yy_push_state(COMMENT_DISCARD); 717 else{ 718 /* Push back the "*" and return "/" as usual. */ 719 yyless(1); 720 return '/'; 721 } 722 } 723 724 "(?#" { 725 if (lex_compat || posix_compat){ 726 /* Push back the "?#" and treat it like a normal parens. */ 727 yyless(1); 728 sf_push(); 729 return '('; 730 } 731 else 732 yy_push_state(EXTENDED_COMMENT); 733 } 734 "(?" { 735 sf_push(); 736 if (lex_compat || posix_compat) 737 /* Push back the "?" and treat it like a normal parens. */ 738 yyless(1); 739 else 740 BEGIN(GROUP_WITH_PARAMS); 741 return '('; 742 } 743 "(" sf_push(); return '('; 744 ")" sf_pop(); return ')'; 745 746 [/|*+?.(){}] return (unsigned char) yytext[0]; 747 . RETURNCHAR; 748 } 749 750 751 <SC>{ 752 {OPTWS}{NL}{OPTWS} ++linenum; /* Allow blank lines & continuations */ 753 [,*] return (unsigned char) yytext[0]; 754 ">" BEGIN(SECT2); return '>'; 755 ">"/^ BEGIN(CARETISBOL); return '>'; 756 {SCNAME} RETURNNAME; 757 . { 758 format_synerr( _( "bad <start condition>: %s" ), 759 yytext ); 760 } 761 } 762 763 <CARETISBOL>"^" BEGIN(SECT2); return '^'; 764 765 766 <QUOTE>{ 767 [^"\n] RETURNCHAR; 768 \" BEGIN(SECT2); return '"'; 769 770 {NL} { 771 synerr( _( "missing quote" ) ); 772 BEGIN(SECT2); 773 ++linenum; 774 return '"'; 775 } 776 } 777 778 <GROUP_WITH_PARAMS>{ 779 ":" BEGIN(SECT2); 780 "-" BEGIN(GROUP_MINUS_PARAMS); 781 i sf_set_case_ins(1); 782 s sf_set_dot_all(1); 783 x sf_set_skip_ws(1); 784 } 785 <GROUP_MINUS_PARAMS>{ 786 ":" BEGIN(SECT2); 787 i sf_set_case_ins(0); 788 s sf_set_dot_all(0); 789 x sf_set_skip_ws(0); 790 } 791 792 <FIRSTCCL>{ 793 "^"/[^-\]\n] BEGIN(CCL); return '^'; 794 "^"/("-"|"]") return '^'; 795 . BEGIN(CCL); RETURNCHAR; 796 } 797 798 <CCL>{ 799 -/[^\]\n] return '-'; 800 [^\]\n] RETURNCHAR; 801 "]" BEGIN(SECT2); return ']'; 802 .|{NL} { 803 synerr( _( "bad character class" ) ); 804 BEGIN(SECT2); 805 return ']'; 806 } 807 } 808 809 <FIRSTCCL,CCL>{ 810 "[:alnum:]" BEGIN(CCL); return CCE_ALNUM; 811 "[:alpha:]" BEGIN(CCL); return CCE_ALPHA; 812 "[:blank:]" BEGIN(CCL); return CCE_BLANK; 813 "[:cntrl:]" BEGIN(CCL); return CCE_CNTRL; 814 "[:digit:]" BEGIN(CCL); return CCE_DIGIT; 815 "[:graph:]" BEGIN(CCL); return CCE_GRAPH; 816 "[:lower:]" BEGIN(CCL); return CCE_LOWER; 817 "[:print:]" BEGIN(CCL); return CCE_PRINT; 818 "[:punct:]" BEGIN(CCL); return CCE_PUNCT; 819 "[:space:]" BEGIN(CCL); return CCE_SPACE; 820 "[:upper:]" BEGIN(CCL); return CCE_UPPER; 821 "[:xdigit:]" BEGIN(CCL); return CCE_XDIGIT; 822 823 "[:^alnum:]" BEGIN(CCL); return CCE_NEG_ALNUM; 824 "[:^alpha:]" BEGIN(CCL); return CCE_NEG_ALPHA; 825 "[:^blank:]" BEGIN(CCL); return CCE_NEG_BLANK; 826 "[:^cntrl:]" BEGIN(CCL); return CCE_NEG_CNTRL; 827 "[:^digit:]" BEGIN(CCL); return CCE_NEG_DIGIT; 828 "[:^graph:]" BEGIN(CCL); return CCE_NEG_GRAPH; 829 "[:^lower:]" BEGIN(CCL); return CCE_NEG_LOWER; 830 "[:^print:]" BEGIN(CCL); return CCE_NEG_PRINT; 831 "[:^punct:]" BEGIN(CCL); return CCE_NEG_PUNCT; 832 "[:^space:]" BEGIN(CCL); return CCE_NEG_SPACE; 833 "[:^upper:]" BEGIN(CCL); return CCE_NEG_UPPER; 834 "[:^xdigit:]" BEGIN(CCL); return CCE_NEG_XDIGIT; 835 {CCL_EXPR} { 836 format_synerr( 837 _( "bad character class expression: %s" ), 838 yytext ); 839 BEGIN(CCL); return CCE_ALNUM; 840 } 841 } 842 843 <NUM>{ 844 [[:digit:]]+ { 845 yylval = myctoi( yytext ); 846 return NUMBER; 847 } 848 849 "," return ','; 850 "}" { 851 BEGIN(SECT2); 852 if ( lex_compat || posix_compat ) 853 return END_REPEAT_POSIX; 854 else 855 return END_REPEAT_FLEX; 856 } 857 858 . { 859 synerr( _( "bad character inside {}'s" ) ); 860 BEGIN(SECT2); 861 return '}'; 862 } 863 864 {NL} { 865 synerr( _( "missing }" ) ); 866 BEGIN(SECT2); 867 ++linenum; 868 return '}'; 869 } 870 } 871 872 873 <PERCENT_BRACE_ACTION>{ 874 {OPTWS}"%}".* bracelevel = 0; 875 876 <ACTION>"/*" ACTION_ECHO; yy_push_state( COMMENT ); 877 878 <CODEBLOCK,ACTION>{ 879 "reject" { 880 ACTION_ECHO; 881 CHECK_RE_JECT(yytext); 882 } 883 "yymore" { 884 ACTION_ECHO; 885 CHECK_YYMORE(yytext); 886 } 887 } 888 889 {M4QSTART} ACTION_ECHO_QSTART; 890 {M4QEND} ACTION_ECHO_QEND; 891 . ACTION_ECHO; 892 {NL} { 893 ++linenum; 894 ACTION_ECHO; 895 if ( bracelevel == 0 || 896 (doing_codeblock && indented_code) ) 897 { 898 if ( doing_rule_action ) 899 add_action( "\tYY_BREAK\n" ); 900 901 doing_rule_action = doing_codeblock = false; 902 BEGIN(SECT2); 903 } 904 } 905 } 906 907 908 /* Reject and YYmore() are checked for above, in PERCENT_BRACE_ACTION */ 909 <ACTION>{ 910 "{" ACTION_ECHO; ++bracelevel; 911 "}" ACTION_ECHO; --bracelevel; 912 {M4QSTART} ACTION_ECHO_QSTART; 913 {M4QEND} ACTION_ECHO_QEND; 914 [^[:alpha:]_{}"'/\n\[\]]+ ACTION_ECHO; 915 [\[\]] ACTION_ECHO; 916 {NAME} ACTION_ECHO; 917 "'"([^'\\\n]|\\.)*"'" ACTION_ECHO; /* character constant */ 918 \" ACTION_ECHO; BEGIN(ACTION_STRING); 919 {NL} { 920 ++linenum; 921 ACTION_ECHO; 922 if ( bracelevel == 0 ) 923 { 924 if ( doing_rule_action ) 925 add_action( "\tYY_BREAK\n" ); 926 927 doing_rule_action = false; 928 BEGIN(SECT2); 929 } 930 } 931 . ACTION_ECHO; 932 } 933 934 <ACTION_STRING>{ 935 [^"\\\n]+ ACTION_ECHO; 936 \\. ACTION_ECHO; 937 {NL} ++linenum; ACTION_ECHO; BEGIN(ACTION); 938 \" ACTION_ECHO; BEGIN(ACTION); 939 . ACTION_ECHO; 940 } 941 942 <COMMENT,COMMENT_DISCARD,ACTION,ACTION_STRING><<EOF>> { 943 synerr( _( "EOF encountered inside an action" ) ); 944 yyterminate(); 945 } 946 947 <EXTENDED_COMMENT,GROUP_WITH_PARAMS,GROUP_MINUS_PARAMS><<EOF>> { 948 synerr( _( "EOF encountered inside pattern" ) ); 949 yyterminate(); 950 } 951 952 <SECT2,QUOTE,FIRSTCCL,CCL>{ESCSEQ} { 953 yylval = myesc( (Char *) yytext ); 954 955 if ( YY_START == FIRSTCCL ) 956 BEGIN(CCL); 957 958 return CHAR; 959 } 960 961 962 <SECT3>{ 963 {M4QSTART} fwrite (escaped_qstart, 1, strlen(escaped_qstart), yyout); 964 {M4QEND} fwrite (escaped_qend, 1, strlen(escaped_qend), yyout); 965 [^\[\]\n]*(\n?) ECHO; 966 (.|\n) ECHO; 967 <<EOF>> sectnum = 0; yyterminate(); 968 } 969 970 <*>.|\n format_synerr( _( "bad character: %s" ), yytext ); 971 972 %% 973 974 975 int yywrap() 976 { 977 if ( --num_input_files > 0 ) 978 { 979 set_input_file( *++input_files ); 980 return 0; 981 } 982 983 else 984 return 1; 985 } 986 987 988 /* set_input_file - open the given file (if NULL, stdin) for scanning */ 989 990 void set_input_file( file ) 991 char *file; 992 { 993 if ( file && strcmp( file, "-" ) ) 994 { 995 infilename = copy_string( file ); 996 yyin = fopen( infilename, "r" ); 997 998 if ( yyin == NULL ) 999 lerrsf( _( "can't open %s" ), file ); 1000 } 1001 1002 else 1003 { 1004 yyin = stdin; 1005 infilename = copy_string( "<stdin>" ); 1006 } 1007 1008 linenum = 1; 1009 } 1010 1011 1012 /* Wrapper routines for accessing the scanner's malloc routines. */ 1013 1014 void *flex_alloc( size ) 1015 size_t size; 1016 { 1017 return (void *) malloc( size ); 1018 } 1019 1020 void *flex_realloc( ptr, size ) 1021 void *ptr; 1022 size_t size; 1023 { 1024 return (void *) realloc( ptr, size ); 1025 } 1026 1027 void flex_free( ptr ) 1028 void *ptr; 1029 { 1030 if ( ptr ) 1031 free( ptr ); 1032 } 1033