xref: /dragonfly/contrib/flex/src/scan.l (revision 37de577a)
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