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