xref: /third_party/ltp/pan/scan.l (revision f08c3bdf)
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
70int scan_mode = SCAN_OUTSIDE;	/* current mode */
71char *key, *cont;	/* keyword pieces */
72SYM keys=NULL;		/* stored keywords */
73SYM ctag=NULL;		/* temporary - for storing current tag's info */
74SYM alltags;		/* entire tag database.  set to scanner 'tags' param.*/
75SYM k;			/* temporary sym pointer -- for key removal */
76char info[KEYSIZE];	/* tmp string for inserting line numbers */
77static int test_output( SYM, SYM);
78static 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
95UI      [0-9]+
96A       [a-zA-Z]+
97W	[a-zA-Z0-9_-]+
98S	[ \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 */
287int
288begin_cuts(void)
289{
290    BEGIN CUTS;
291    return 0;
292}
293
294/*
295 * Calls lex repeatedly until all input is seen.
296 */
297int
298scanner(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 */
314static int
315test_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 */
336struct 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
347static int
348check_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
404char **filenames;
405
406int
407lex_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 */
433int
434yywrap(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