• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 %{
2 /*
3  * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of version 2 of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it would be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12  *
13  * Further, this software is distributed without any warranty that it is
14  * free of the rightful claim of any third person regarding infringement
15  * or the like.  Any license provided herein, whether implied or
16  * otherwise, applies only to this software file.  Patent licenses, if
17  * any, provided herein do not apply to combinations of this program with
18  * other software, or any other product whatsoever.
19  *
20  * You should have received a copy of the GNU General Public License along
21  * with this program; if not, write the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23  *
24  * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
25  * Mountain View, CA  94043, or:
26  *
27  * http://www.sgi.com
28  *
29  * For further information regarding this notice, see:
30  *
31  * http://oss.sgi.com/projects/GenInfo/NoticeExplan/
32  *
33  */
34 /* $Id: scan.l,v 1.1 2000/09/21 21:35:06 alaffin Exp $ */
35 /*
36  * Lex rules for input processing.
37  *
38  * This handles all of the input parsing.  The rules liste here properly
39  * store or process the pertenant input data in the proper ways.  The rules
40  * for the various patterns maintains a "state" to determine if corrupted
41  * input is seen (%Start keys + internal ones that only flag errors).
42  *
43  * See scanner.c for routines called from the actions.
44  *
45  * States:
46  *	SCAN_OUTSIDE
47  *		start-up state, inbetween tests
48  *	SCAN_RTSKEY			valid from SCAN_OUTSIDE
49  *		from rts_keyword_start to _end
50  *		accompanied by lex KEY state.
51  *	SCAN_TSTKEY			valid from SCAN_OUTSIDE
52  *		test_start to test_output or test_end,
53  *		execution_status to test_end
54  *		accompanied by lex KEY state.
55  *	SCAN_OUTPUT
56  *		test_output to execution_status.
57  *		accompanied by lex OUT or CUTS states.
58  */
59 
60 #include <stdarg.h>
61 #include <stdio.h>
62 #include <stdlib.h>
63 #include <string.h>
64 
65 #include "scan.h"
66 #include "reporter.h"
67 #include "symbol.h"
68 #include "tag_report.h"
69 
70 int scan_mode = SCAN_OUTSIDE;	/* current mode */
71 char *key, *cont;	/* keyword pieces */
72 SYM keys=NULL;		/* stored keywords */
73 SYM ctag=NULL;		/* temporary - for storing current tag's info */
74 SYM alltags;		/* entire tag database.  set to scanner 'tags' param.*/
75 SYM k;			/* temporary sym pointer -- for key removal */
76 char info[KEYSIZE];	/* tmp string for inserting line numbers */
77 static int test_output( SYM, SYM);
78 static int check_mode(int, int, ...);
79 
80 /*
81  * Lex Definitions:
82  * UI	Unsigned Integer
83  * A	Alphabetic
84  * W	"Word" characters (Alpha, Numeric, Hyphens, Underscores)
85  * S    Space characters
86  */
87 %}
88 
89 %option noc++
90 %option noinput
91 %option nolex-compat
92 %option nounput
93 %option yylineno
94 
95 UI      [0-9]+
96 A       [a-zA-Z]+
97 W	[a-zA-Z0-9_-]+
98 S	[ \t]+
99 
100 %Start KEY OUT CUTS
101 %%
102 ^<<<rts_keyword_start>>>$	{
103     BEGIN KEY;
104     check_mode(scan_mode, SCAN_OUTSIDE, 0);
105     scan_mode = SCAN_RTSKEY;
106 
107     /* remove any keys that exist right now */
108     if(keys != NULL)
109 	sym_rm(keys, RM_KEY | RM_DATA);
110     /* start a new table of keys */
111     keys = sym_open(0, 0, 0);
112     return(KW_START);
113     /* NOTREACHED */
114 }
115 
116 ^<<<rts_keyword_end>>>$		{
117     BEGIN 0;
118     check_mode(scan_mode, SCAN_RTSKEY, 0);
119     scan_mode = SCAN_OUTSIDE;
120 #ifdef DEBUGGING
121     DEBUG(D_SCAN_LEX, 10) {
122 	printf("RTS Keywords:\n");
123 	sym_dump_s(keys, 0);
124     }
125 #endif
126     /* remove _RTS key, if it exists, before replacing it */
127     if( (k=(SYM)sym_get(alltags, "_RTS")) != NULL) {
128 	sym_rm(k, RM_KEY | RM_DATA);
129     }
130 
131     sym_put(alltags, "_RTS", (void *)keys, PUT_REPLACE);
132     keys = NULL;
133 
134     return(KW_END);
135     /* NOTREACHED */
136 }
137 
138 ^<<<test_start>>>$		{
139     BEGIN KEY;
140     check_mode(scan_mode, SCAN_OUTSIDE, 0);
141     scan_mode = SCAN_TSTKEY;
142 
143     /*
144      * set up new "tag" and "keys" tables
145      * to put the new data into.
146      */
147 
148     /* remove any keys that exist right now */
149     if(keys != NULL)
150 	sym_rm(keys, RM_KEY | RM_DATA);
151     keys = sym_open(0, 0, 0);
152 
153     sprintf(info, "%d", yylineno);
154     sym_put(keys, "_Start_line", strdup(info), 0);
155 
156     /* remove any tag info that exists right now */
157     if(ctag != NULL)
158 	sym_rm(ctag, RM_KEY | RM_DATA);
159     ctag = sym_open(0, 0, 0);
160 
161     return(TEST_START);
162     /* NOTREACHED */
163 }
164 
165 ^<<<test_output>>>$		{
166     BEGIN OUT;
167     check_mode(scan_mode, SCAN_TSTKEY, 0);
168     scan_mode = SCAN_OUTPUT;
169 
170     test_output(ctag, keys);
171 
172     return(TEST_OUTPUT);
173     /* NOTREACHED */
174 }
175 
176 ^<<<execution_status>>>$	{
177     BEGIN KEY;
178     check_mode(scan_mode, SCAN_TSTKEY, SCAN_OUTPUT, 0);
179     scan_mode = SCAN_TSTKEY;
180     return(EXEC_STATUS);
181     /* NOTREACHED */
182 }
183 
184 ^<<<test_end>>>$		{
185     BEGIN 0;
186     check_mode(scan_mode, SCAN_TSTKEY, 0);
187     scan_mode = SCAN_OUTSIDE;
188 
189     sprintf(info, "%d", yylineno);
190 
191     sym_put(keys, "_End_line", strdup(info), 0);
192 #ifdef DEBUGGING
193     DEBUG(D_SCAN_LEX, 10) {
194 	printf("Tag's Keywords:\n");
195 	sym_dump_s(keys, 0);
196     }
197 #endif
198     test_end(alltags, ctag, keys);
199     ctag = keys = NULL;
200 
201     return(TEST_END);
202     /* NOTREACHED */
203 }
204 
205 <KEY>[a-zA-Z_-]+=\"[^\"\n]+\"	{
206     key = yytext;
207     cont = strchr(yytext, '=');
208     *cont++ = '\0';
209     if(*cont == '"') cont++;
210     if(yytext[yyleng-1] == '"')
211 	yytext[yyleng-1] = '\0';
212 #ifdef DEBUGGING
213     DEBUG(D_SCAN_LEX, 5)
214 	printf("A quoted keyword: %s = %s\n", key, cont);
215 #endif
216     sym_put(keys, key, strdup(cont), 0);
217 
218     return(KEYWORD_QUOTED);
219     /* NOTREACHED */
220 }
221 
222 <KEY>[a-zA-Z_-]+=[^\t \n]+	{
223     key = yytext;
224     cont = strchr(yytext, '=');
225     *cont++ = '\0';
226 #ifdef DEBUGGING
227     DEBUG(D_SCAN_LEX, 5)
228 	printf("A keyword: %s = %s\n", key, cont);
229 #endif
230     sym_put(keys, key, strdup(cont), 0);
231 
232     return(KEYWORD);
233     /* NOTREACHED */
234 }
235 
236 <KEY>[ \t\n]*			{
237     return(SPACE);
238     /* NOTREACHED */
239 }
240 
241 <OUT>^.+$			{
242 #ifdef DEBUGGING
243     DEBUG(D_SCAN_LEX, 5)
244 	printf("TEXT_LINE: %s\n", yytext);
245 #endif
246 
247     return(TEXT_LINE);
248     /* NOTREACHED */
249 }
250 
251 <CUTS>^{W}{S}{UI}{S}{A}{S}":"	   {
252 #ifdef DEBUGGING
253     DEBUG(D_SCAN_LEX, 5)
254 	printf("CUTS Result: %s\n", yytext);
255 #endif
256     cuts_testcase(ctag, keys);
257 
258     return(CUTS_RESULT);
259     /* NOTREACHED */
260 }
261 
262 <CUTS>^{W}{S}{UI}-{UI}{S}{A}{S}":" {
263 #ifdef DEBUGGING
264     DEBUG(D_SCAN_LEX, 5)
265 	printf("CUTS Result: %s\n", yytext);
266 #endif
267     cuts_testcase(ctag, keys);
268 
269     return(CUTS_RESULT_R);
270     /* NOTREACHED */
271 }
272 
273 .				{
274     return(SPACE);
275     /* NOTREACHED */
276 
277 }
278 "\n"				{
279     return(SPACE);
280     /* NOTREACHED */
281 }
282 %%
283 /*
284  * the BEGIN macro only exists in the lex file, so define a routine to
285  * BEGIN the CUTS state.
286  */
287 int
288 begin_cuts(void)
289 {
290     BEGIN CUTS;
291     return 0;
292 }
293 
294 /*
295  * Calls lex repeatedly until all input is seen.
296  */
297 int
298 scanner(SYM tags)
299 {
300     alltags = tags;		/* move into global scope for lex actions */
301 
302     while(yylex())
303 	;
304 
305     return 0;
306 }
307 
308 /*
309  * Test-Output record
310  *  check if this is a CUTS test; if so, enter the lex "cuts" state;
311  *  otherwise do nothing and lex will be in a "data" mode that will just
312  *  toss all the output.
313  */
314 static int
315 test_output(SYM tag, SYM keys)
316 {
317     char *at;
318 
319     if((at=(char *)sym_get(keys, "analysis")) != NULL) {
320 	/* CUTS:number_of_testcases  || CUTS-1:number_of_testcases */
321 	if(strncasecmp("cuts", at, 4) == 0) {
322 	    begin_cuts();
323 	    /*printf("CUTS output expected\n");*/
324 	}
325     }
326     return 0;
327 }
328 
329 /* Input Data State Check
330  * RTS driver output goes thru specific
331  * phases; this is used to verify that the new state is a legal state
332  * to change to from the current state.
333  * This accepts a variable number of arguments (valid states to be
334  * in).  The last argument MUST be zero
335  */
336 struct parse_states {
337 	char *name;
338 	int bits;
339 } parse_states[] = {
340   { "outside",				SCAN_OUTSIDE },
341   { "rts_keyword_start",		SCAN_RTSKEY },
342   { "test_start | execution_status", 	SCAN_TSTKEY },
343   { "test_output",			SCAN_OUTPUT },
344   { "unknown",				0 }, /*end sentinel: bits = 0 */
345 };
346 
347 static int
348 check_mode(int scan_mode, int fst, ...)
349 {
350     va_list ap;			/* used for variable argument functions*/
351     int found=0;		/* set to true if a valid state was found */
352     int ckm;			/* Check Mode: the mode to look for */
353     register struct parse_states *ps; /* for looking thru parse_states */
354     char exp_mode[KEYSIZE];	/* expected mode list (for error message) */
355 
356     extern int yylineno;	/* Line number from Lex */
357 
358     /* look thru parse_states; end sentinel is "bits" = 0 */
359     for(ps=parse_states; ps->bits && (ps->bits != fst);ps++)
360 	;
361     strcpy(exp_mode, ps->name);
362 
363     /* look at first variable argument */
364     if(fst == scan_mode)
365 	found++;
366     else {
367 	/* not first... look at variable args */
368 	va_start(ap, fst);
369 	while(((ckm = va_arg(ap, int)) != 0) && (ckm != scan_mode)) {
370 	    for(ps=parse_states; ps->bits && (ps->bits != ckm);ps++)
371 		;
372 	    strcat(exp_mode, ", ");
373 	    strcat(exp_mode, ps->name);
374 	}
375 	va_end(ap);
376 
377 	if(ckm == scan_mode)
378 	    found++;
379     }
380 
381     if(!found) {
382 	for(ps=parse_states; ps->bits && (ps->bits != scan_mode);ps++)
383 	    ;
384 
385 	fprintf(stderr, "PARSE ERROR -- Line %d found %s in mode %s[%d] expected { %s }\n",
386 		yylineno, yytext, ps->name, scan_mode, exp_mode);
387     }
388 
389     return 0;
390 }
391 
392 /*
393  * This part of the file contains subroutines called by a lex scanner which
394  * is parsing rts-driver-format input and putting it into a multi-level
395  * symbol table.
396  */
397 
398 /*
399  * References to lex variables
400  */
401 /*extern char yytext[];		/ * text matched by last pattern */
402 /*extern long yyleng;		/ * length of above */
403 
404 char **filenames;
405 
406 int
407 lex_files(char **names)
408 {
409     /* lex */
410     extern FILE *yyin;
411 
412     filenames = names;
413 
414     if(*filenames != NULL) {
415 #ifdef DEBUGGING
416 	DEBUG(D_SCAN, 1)
417 	    printf("lex_files: first file is %s\n", *filenames);
418 #endif
419 	if((yyin = fopen(*filenames, "r")) == NULL) {
420 	    printf("Error opening %s for reading\n", *filenames);
421 	    exit(1);
422 	}
423     }
424 
425     return 0;
426 }
427 
428 /*
429  * Called by lex's end-of-file processing.
430  *  Open the next file on the command line.  If there is no next file,
431  *  return "-1" and lex will end.
432  */
433 int
434 yywrap(void)
435 {
436     extern FILE *yyin;
437     extern int yylineno;	/* Line number from Lex */
438 
439     if(*filenames != NULL)
440 	if(*++filenames != NULL) {
441 #ifdef DEBUGGING
442 	DEBUG(D_SCAN, 1)
443 	    printf("yywrap: next file is %s\n", *filenames);
444 #endif
445 	    yylineno=1;
446 	    if((yyin = fopen(*filenames, "r")) != NULL)
447 		return(0);
448 	    else {
449 		printf("Error opening %s for reading\n", *filenames);
450 		return(1);
451 	    }
452 	}
453 
454     return(-1);
455 }
456 
457