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