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