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