xref: /freebsd-11-stable/contrib/flex/scan.l (revision d1d015864103b253b3fcb2f72a0da5b0cfeb31b6)
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 			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 	}
1030