Pristine Ack-5.5
[Ack-5.5.git] / util / flex / scan.l
1
2 /* scan.l - scanner for flex input */
3
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  * Redistribution and use in source and binary forms are permitted provided
17  * that: (1) source distributions retain this entire copyright notice and
18  * comment, and (2) distributions including binaries display the following
19  * acknowledgement:  ``This product includes software developed by the
20  * University of California, Berkeley and its contributors'' in the
21  * documentation or other materials provided with the distribution and in
22  * all advertising materials mentioning features or use of this software.
23  * Neither the name of the University nor the names of its contributors may
24  * be used to endorse or promote products derived from this software without
25  * specific prior written permission.
26  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
27  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
28  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29  */
30
31 #ifndef lint
32 static char rcsid[] =
33     "@(#) $Id: scan.l,v 1.2 1994/06/24 10:57:25 ceriel Exp $ (LBL)";
34 #endif
35
36 #undef yywrap
37
38 #include "flexdef.h"
39 #include "parse.h"
40
41 #define ACTION_ECHO fprintf( temp_action_file, "%s", yytext )
42 #define MARK_END_OF_PROLOG fprintf( temp_action_file, "%%%% end of prolog\n" );
43
44 #undef YY_DECL
45 #define YY_DECL \
46         int flexscan()
47
48 #define RETURNCHAR \
49         yylval = yytext[0]; \
50         return ( CHAR );
51
52 #define RETURNNAME \
53         (void) strcpy( nmstr, (char *) yytext ); \
54         return ( NAME );
55
56 #define PUT_BACK_STRING(str, start) \
57         for ( i = strlen( (char *) (str) ) - 1; i >= start; --i ) \
58             unput((str)[i])
59
60 #define CHECK_REJECT(str) \
61         if ( all_upper( str ) ) \
62             reject = true;
63
64 #define CHECK_YYMORE(str) \
65         if ( all_lower( str ) ) \
66             yymore_used = true;
67 %}
68
69 %x SECT2 SECT2PROLOG SECT3 CODEBLOCK PICKUPDEF SC CARETISBOL NUM QUOTE
70 %x FIRSTCCL CCL ACTION RECOVER BRACEERROR C_COMMENT ACTION_COMMENT
71 %x ACTION_STRING PERCENT_BRACE_ACTION USED_LIST CODEBLOCK_2 XLATION
72
73 WS              [ \t\f]+
74 OPTWS           [ \t\f]*
75 NOT_WS          [^ \t\f\n]
76
77 NAME            [a-z_][a-z_0-9-]*
78 NOT_NAME        [^a-z_\n]+
79
80 SCNAME          {NAME}
81
82 ESCSEQ          \\([^\n]|[0-9]{1,3}|x[0-9a-f]{1,2})
83
84 %%
85     static int bracelevel, didadef;
86     int i, indented_code, checking_used, new_xlation;
87     int doing_codeblock = false;
88     Char nmdef[MAXLINE], myesc();
89
90 ^{WS}                   indented_code = true; BEGIN(CODEBLOCK);
91 ^#.*\n                  ++linenum; /* treat as a comment */
92 ^"/*"                   ECHO; BEGIN(C_COMMENT);
93 ^"%s"{NAME}?            return ( SCDECL );
94 ^"%x"{NAME}?            return ( XSCDECL );
95 ^"%{".*\n               {
96                         ++linenum;
97                         line_directive_out( stdout );
98                         indented_code = false;
99                         BEGIN(CODEBLOCK);
100                         }
101
102 {WS}                    return ( WHITESPACE );
103
104 ^"%%".*                 {
105                         sectnum = 2;
106                         line_directive_out( stdout );
107                         BEGIN(SECT2PROLOG);
108                         return ( SECTEND );
109                         }
110
111 ^"%used"                {
112         pinpoint_message( "warning - %%used/%%unused have been deprecated" );
113                         checking_used = REALLY_USED; BEGIN(USED_LIST);
114                         }
115 ^"%unused"              {
116                         checking_used = REALLY_NOT_USED; BEGIN(USED_LIST);
117         pinpoint_message( "warning - %%used/%%unused have been deprecated" );
118                         checking_used = REALLY_NOT_USED; BEGIN(USED_LIST);
119                         }
120
121
122 ^"%"[aeknopt]" ".*\n    {
123 #ifdef NOTDEF
124                         fprintf( stderr,
125                              "old-style lex command at line %d ignored:\n\t%s",
126                                  linenum, yytext );
127 #endif
128                         ++linenum;
129                         }
130
131 ^"%"[cr]{OPTWS}         /* ignore old lex directive */
132
133 %t{OPTWS}\n             {
134                         ++linenum;
135                         xlation =
136                             (int *) malloc( sizeof( int ) * (unsigned) csize );
137
138                         if ( ! xlation )
139                             flexfatal(
140                                 "dynamic memory failure building %t table" );
141
142                         for ( i = 0; i < csize; ++i )
143                             xlation[i] = 0;
144
145                         num_xlations = 0;
146
147                         BEGIN(XLATION);
148                         }
149
150 ^"%"[^sxanpekotcru{}]{OPTWS}    synerr( "unrecognized '%' directive" );
151
152 ^{NAME}                 {
153                         (void) strcpy( nmstr, (char *) yytext );
154                         didadef = false;
155                         BEGIN(PICKUPDEF);
156                         }
157
158 {SCNAME}                RETURNNAME;
159 ^{OPTWS}\n              ++linenum; /* allows blank lines in section 1 */
160 {OPTWS}\n               ++linenum; return ( '\n' );
161 .                       synerr( "illegal character" ); BEGIN(RECOVER);
162
163
164 <C_COMMENT>"*/"         ECHO; BEGIN(INITIAL);
165 <C_COMMENT>"*/".*\n     ++linenum; ECHO; BEGIN(INITIAL);
166 <C_COMMENT>[^*\n]+      ECHO;
167 <C_COMMENT>"*"          ECHO;
168 <C_COMMENT>\n           ++linenum; ECHO;
169
170
171 <CODEBLOCK>^"%}".*\n    ++linenum; BEGIN(INITIAL);
172 <CODEBLOCK>"reject"     ECHO; CHECK_REJECT(yytext);
173 <CODEBLOCK>"yymore"     ECHO; CHECK_YYMORE(yytext);
174 <CODEBLOCK>{NAME}|{NOT_NAME}|.  ECHO;
175 <CODEBLOCK>\n           {
176                         ++linenum;
177                         ECHO;
178                         if ( indented_code )
179                             BEGIN(INITIAL);
180                         }
181
182
183 <PICKUPDEF>{WS}         /* separates name and definition */
184
185 <PICKUPDEF>{NOT_WS}.*   {
186                         (void) strcpy( (char *) nmdef, (char *) yytext );
187
188                         for ( i = strlen( (char *) nmdef ) - 1;
189                               i >= 0 &&
190                               nmdef[i] == ' ' || nmdef[i] == '\t';
191                               --i )
192                             ;
193
194                         nmdef[i + 1] = '\0';
195
196                         ndinstal( nmstr, nmdef );
197                         didadef = true;
198                         }
199
200 <PICKUPDEF>\n           {
201                         if ( ! didadef )
202                             synerr( "incomplete name definition" );
203                         BEGIN(INITIAL);
204                         ++linenum;
205                         }
206
207 <RECOVER>.*\n           ++linenum; BEGIN(INITIAL); RETURNNAME;
208
209
210 <USED_LIST>\n           ++linenum; BEGIN(INITIAL);
211 <USED_LIST>{WS}
212 <USED_LIST>"reject"     {
213                         if ( all_upper( yytext ) )
214                             reject_really_used = checking_used;
215                         else
216                             synerr( "unrecognized %used/%unused construct" );
217                         }
218 <USED_LIST>"yymore"     {
219                         if ( all_lower( yytext ) )
220                             yymore_really_used = checking_used;
221                         else
222                             synerr( "unrecognized %used/%unused construct" );
223                         }
224 <USED_LIST>{NOT_WS}+    synerr( "unrecognized %used/%unused construct" );
225
226
227 <XLATION>"%t"{OPTWS}\n  ++linenum; BEGIN(INITIAL);
228 <XLATION>^{OPTWS}[0-9]+ ++num_xlations; new_xlation = true;
229 <XLATION>^.             synerr( "bad row in translation table" );
230 <XLATION>{WS}           /* ignore whitespace */
231
232 <XLATION>{ESCSEQ}       {
233                         xlation[myesc( yytext )] =
234                                 (new_xlation ? num_xlations : -num_xlations);
235                         new_xlation = false;
236                         }
237 <XLATION>.              {
238                         xlation[yytext[0]] =
239                                 (new_xlation ? num_xlations : -num_xlations);
240                         new_xlation = false;
241                         }
242
243 <XLATION>\n             ++linenum;
244
245
246 <SECT2PROLOG>.*\n/{NOT_WS}      {
247                         ++linenum;
248                         ACTION_ECHO;
249                         MARK_END_OF_PROLOG;
250                         BEGIN(SECT2);
251                         }
252
253 <SECT2PROLOG>.*\n       ++linenum; ACTION_ECHO;
254
255 <SECT2PROLOG><<EOF>>    MARK_END_OF_PROLOG; yyterminate();
256
257 <SECT2>^{OPTWS}\n       ++linenum; /* allow blank lines in section 2 */
258
259 <SECT2>^({WS}|"%{")     {
260                         indented_code = (yytext[0] != '%');
261                         doing_codeblock = true;
262                         bracelevel = 1;
263
264                         if ( indented_code )
265                             ACTION_ECHO;
266
267                         BEGIN(CODEBLOCK_2);
268                         }
269
270 <SECT2>"<"              BEGIN(SC); return ( '<' );
271 <SECT2>^"^"             return ( '^' );
272 <SECT2>\"               BEGIN(QUOTE); return ( '"' );
273 <SECT2>"{"/[0-9]                BEGIN(NUM); return ( '{' );
274 <SECT2>"{"[^0-9\n][^}\n]*       BEGIN(BRACEERROR);
275 <SECT2>"$"/[ \t\n]      return ( '$' );
276
277 <SECT2>{WS}"%{"         {
278                         bracelevel = 1;
279                         BEGIN(PERCENT_BRACE_ACTION);
280                         return ( '\n' );
281                         }
282 <SECT2>{WS}"|".*\n      continued_action = true; ++linenum; return ( '\n' );
283
284 <SECT2>{WS}             {
285                         /* this rule is separate from the one below because
286                          * otherwise we get variable trailing context, so
287                          * we can't build the scanner using -{f,F}
288                          */
289                         bracelevel = 0;
290                         continued_action = false;
291                         BEGIN(ACTION);
292                         return ( '\n' );
293                         }
294
295 <SECT2>{OPTWS}/\n       {
296                         bracelevel = 0;
297                         continued_action = false;
298                         BEGIN(ACTION);
299                         return ( '\n' );
300                         }
301
302 <SECT2>^{OPTWS}\n       ++linenum; return ( '\n' );
303
304 <SECT2>"<<EOF>>"        return ( EOF_OP );
305
306 <SECT2>^"%%".*          {
307                         sectnum = 3;
308                         BEGIN(SECT3);
309                         return ( EOF ); /* to stop the parser */
310                         }
311
312 <SECT2>"["([^\\\]\n]|{ESCSEQ})+"]"      {
313                         int cclval;
314
315                         (void) strcpy( nmstr, (char *) yytext );
316
317                         /* check to see if we've already encountered this ccl */
318                         if ( (cclval = ccllookup( (Char *) nmstr )) )
319                             {
320                             yylval = cclval;
321                             ++cclreuse;
322                             return ( PREVCCL );
323                             }
324                         else
325                             {
326                             /* we fudge a bit.  We know that this ccl will
327                              * soon be numbered as lastccl + 1 by cclinit
328                              */
329                             cclinstal( (Char *) nmstr, lastccl + 1 );
330
331                             /* push back everything but the leading bracket
332                              * so the ccl can be rescanned
333                              */
334                             PUT_BACK_STRING((Char *) nmstr, 1);
335
336                             BEGIN(FIRSTCCL);
337                             return ( '[' );
338                             }
339                         }
340
341 <SECT2>"{"{NAME}"}"     {
342                         register Char *nmdefptr;
343                         Char *ndlookup();
344
345                         (void) strcpy( nmstr, (char *) yytext );
346                         nmstr[yyleng - 1] = '\0';  /* chop trailing brace */
347
348                         /* lookup from "nmstr + 1" to chop leading brace */
349                         if ( ! (nmdefptr = ndlookup( nmstr + 1 )) )
350                             synerr( "undefined {name}" );
351
352                         else
353                             { /* push back name surrounded by ()'s */
354                             unput(')');
355                             PUT_BACK_STRING(nmdefptr, 0);
356                             unput('(');
357                             }
358                         }
359
360 <SECT2>[/|*+?.()]       return ( yytext[0] );
361 <SECT2>.                RETURNCHAR;
362 <SECT2>\n               ++linenum; return ( '\n' );
363
364
365 <SC>","                 return ( ',' );
366 <SC>">"                 BEGIN(SECT2); return ( '>' );
367 <SC>">"/"^"             BEGIN(CARETISBOL); return ( '>' );
368 <SC>{SCNAME}            RETURNNAME;
369 <SC>.                   synerr( "bad start condition name" );
370
371 <CARETISBOL>"^"         BEGIN(SECT2); return ( '^' );
372
373
374 <QUOTE>[^"\n]           RETURNCHAR;
375 <QUOTE>\"               BEGIN(SECT2); return ( '"' );
376
377 <QUOTE>\n               {
378                         synerr( "missing quote" );
379                         BEGIN(SECT2);
380                         ++linenum;
381                         return ( '"' );
382                         }
383
384
385 <FIRSTCCL>"^"/[^-\n]    BEGIN(CCL); return ( '^' );
386 <FIRSTCCL>"^"/-         return ( '^' );
387 <FIRSTCCL>-             BEGIN(CCL); yylval = '-'; return ( CHAR );
388 <FIRSTCCL>.             BEGIN(CCL); RETURNCHAR;
389
390 <CCL>-/[^\]\n]          return ( '-' );
391 <CCL>[^\]\n]            RETURNCHAR;
392 <CCL>"]"                BEGIN(SECT2); return ( ']' );
393
394
395 <NUM>[0-9]+             {
396                         yylval = myctoi( yytext );
397                         return ( NUMBER );
398                         }
399
400 <NUM>","                        return ( ',' );
401 <NUM>"}"                        BEGIN(SECT2); return ( '}' );
402
403 <NUM>.                  {
404                         synerr( "bad character inside {}'s" );
405                         BEGIN(SECT2);
406                         return ( '}' );
407                         }
408
409 <NUM>\n                 {
410                         synerr( "missing }" );
411                         BEGIN(SECT2);
412                         ++linenum;
413                         return ( '}' );
414                         }
415
416
417 <BRACEERROR>"}"         synerr( "bad name in {}'s" ); BEGIN(SECT2);
418 <BRACEERROR>\n          synerr( "missing }" ); ++linenum; BEGIN(SECT2);
419
420
421 <PERCENT_BRACE_ACTION,CODEBLOCK_2>{OPTWS}"%}".*         bracelevel = 0;
422 <PERCENT_BRACE_ACTION,CODEBLOCK_2,ACTION>"reject"       {
423                         ACTION_ECHO;
424                         CHECK_REJECT(yytext);
425                         }
426 <PERCENT_BRACE_ACTION,CODEBLOCK_2,ACTION>"yymore"       {
427                         ACTION_ECHO;
428                         CHECK_YYMORE(yytext);
429                         }
430 <PERCENT_BRACE_ACTION,CODEBLOCK_2>{NAME}|{NOT_NAME}|.   ACTION_ECHO;
431 <PERCENT_BRACE_ACTION,CODEBLOCK_2>\n                    {
432                         ++linenum;
433                         ACTION_ECHO;
434                         if ( bracelevel == 0 ||
435                              (doing_codeblock && indented_code) )
436                             {
437                             if ( ! doing_codeblock )
438                                 fputs( "\tYY_BREAK\n", temp_action_file );
439                             
440                             doing_codeblock = false;
441                             BEGIN(SECT2);
442                             }
443                         }
444
445
446         /* Reject and YYmore() are checked for above, in PERCENT_BRACE_ACTION */
447 <ACTION>"{"             ACTION_ECHO; ++bracelevel;
448 <ACTION>"}"             ACTION_ECHO; --bracelevel;
449 <ACTION>[^a-z_{}"'/\n]+ ACTION_ECHO;
450 <ACTION>{NAME}          ACTION_ECHO;
451 <ACTION>"/*"            ACTION_ECHO; BEGIN(ACTION_COMMENT);
452 <ACTION>"'"([^'\\\n]|\\.)*"'"   ACTION_ECHO; /* character constant */
453 <ACTION>\"              ACTION_ECHO; BEGIN(ACTION_STRING);
454 <ACTION>\n              {
455                         ++linenum;
456                         ACTION_ECHO;
457                         if ( bracelevel == 0 )
458                             {
459                             fputs( "\tYY_BREAK\n", temp_action_file );
460                             BEGIN(SECT2);
461                             }
462                         }
463 <ACTION>.               ACTION_ECHO;
464
465 <ACTION_COMMENT>"*/"    ACTION_ECHO; BEGIN(ACTION);
466 <ACTION_COMMENT>[^*\n]+ ACTION_ECHO;
467 <ACTION_COMMENT>"*"     ACTION_ECHO;
468 <ACTION_COMMENT>\n      ++linenum; ACTION_ECHO;
469 <ACTION_COMMENT>.       ACTION_ECHO;
470
471 <ACTION_STRING>[^"\\\n]+        ACTION_ECHO;
472 <ACTION_STRING>\\.      ACTION_ECHO;
473 <ACTION_STRING>\n       ++linenum; ACTION_ECHO;
474 <ACTION_STRING>\"       ACTION_ECHO; BEGIN(ACTION);
475 <ACTION_STRING>.        ACTION_ECHO;
476
477 <ACTION,ACTION_COMMENT,ACTION_STRING><<EOF>>    {
478                         synerr( "EOF encountered inside an action" );
479                         yyterminate();
480                         }
481
482
483 <SECT2,QUOTE,CCL>{ESCSEQ}       {
484                         yylval = myesc( yytext );
485                         return ( CHAR );
486                         }
487
488 <FIRSTCCL>{ESCSEQ}      {
489                         yylval = myesc( yytext );
490                         BEGIN(CCL);
491                         return ( CHAR );
492                         }
493
494
495 <SECT3>.*(\n?)          ECHO;
496 %%
497
498
499 int yywrap()
500
501     {
502     if ( --num_input_files > 0 )
503         {
504         set_input_file( *++input_files );
505         return ( 0 );
506         }
507
508     else
509         return ( 1 );
510     }
511
512
513 /* set_input_file - open the given file (if NULL, stdin) for scanning */
514
515 void set_input_file( file )
516 char *file;
517
518     {
519     if ( file )
520         {
521         infilename = file;
522         yyin = fopen( infilename, "r" );
523
524         if ( yyin == NULL )
525             lerrsf( "can't open %s", file );
526         }
527
528     else
529         {
530         yyin = stdin;
531         infilename = "<stdin>";
532         }
533     }