scan.l revision 256281
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"
37extern bool tablesverify, tablesext;
38extern int trlcontxt; /* Set in  parse.y for each rule. */
39extern 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
109WS		[[:blank:]]+
110OPTWS		[[:blank:]]*
111NOT_WS		[^[:blank:]\r\n]
112
113NL		\r?\n
114
115NAME		([[:alpha:]_][[:alnum:]_-]*)
116NOT_NAME	[^[:alpha:]_*\n]+
117
118SCNAME		{NAME}
119
120ESCSEQ		(\\([^\n]|[0-7]{1,3}|x[[:xdigit:]]{1,2}))
121
122FIRST_CCL_CHAR	([^\\\n]|{ESCSEQ})
123CCL_CHAR	([^\\\n\]]|{ESCSEQ})
124CCL_EXPR	("[:"^?[[:alpha:]]+":]")
125
126LEXOPT		[aceknopr]
127
128M4QSTART    "[["
129M4QEND      "]]"
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 			 }
679nmstr[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
972int 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
987void set_input_file( file )
988char *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
1011void *flex_alloc( size )
1012size_t size;
1013	{
1014	return (void *) malloc( size );
1015	}
1016
1017void *flex_realloc( ptr, size )
1018void *ptr;
1019size_t size;
1020	{
1021	return (void *) realloc( ptr, size );
1022	}
1023
1024void flex_free( ptr )
1025void *ptr;
1026	{
1027	if ( ptr )
1028		free( ptr );
1029	}
1030