blob: aa5a1c6c84a0e8c0ce908f7c9882a49b2a64edb8 [file] [log] [blame]
alaffinf5589902000-09-21 21:35:06 +00001%{
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
Wanlong Gaofed96412012-10-24 10:10:29 +080021 * with this program; if not, write the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
alaffinf5589902000-09-21 21:35:06 +000023 *
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
Garrett Cooper6ea8c5b2011-02-23 00:14:59 -080060#include <stdarg.h>
alaffinf5589902000-09-21 21:35:06 +000061#include <stdio.h>
62#include <stdlib.h>
63#include <string.h>
alaffinf5589902000-09-21 21:35:06 +000064
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
Garrett Cooper7c66f462010-12-17 03:51:54 -080089%option noc++
90%option noinput
91%option nolex-compat
92%option nounput
Garrett Cooper0b42e492011-02-23 00:19:54 -080093%option yylineno
Garrett Cooper7c66f462010-12-17 03:51:54 -080094
alaffinf5589902000-09-21 21:35:06 +000095UI [0-9]+
96A [a-zA-Z]+
97W [a-zA-Z0-9_-]+
98S [ \t]+
99
100%Start KEY OUT CUTS
101%%
Chris Dearman37550cf2012-10-17 19:54:01 -0700102^<<<rts_keyword_start>>>$ {
alaffinf5589902000-09-21 21:35:06 +0000103 BEGIN KEY;
104 check_mode(scan_mode, SCAN_OUTSIDE, 0);
105 scan_mode = SCAN_RTSKEY;
Chris Dearman37550cf2012-10-17 19:54:01 -0700106
alaffinf5589902000-09-21 21:35:06 +0000107 /* 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;
Chris Dearman37550cf2012-10-17 19:54:01 -0700133
134 return(KW_END);
alaffinf5589902000-09-21 21:35:06 +0000135 /* NOTREACHED */
136}
137
Chris Dearman37550cf2012-10-17 19:54:01 -0700138^<<<test_start>>>$ {
alaffinf5589902000-09-21 21:35:06 +0000139 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
Chris Dearman37550cf2012-10-17 19:54:01 -0700165^<<<test_output>>>$ {
alaffinf5589902000-09-21 21:35:06 +0000166 BEGIN OUT;
167 check_mode(scan_mode, SCAN_TSTKEY, 0);
168 scan_mode = SCAN_OUTPUT;
Chris Dearman37550cf2012-10-17 19:54:01 -0700169
alaffinf5589902000-09-21 21:35:06 +0000170 test_output(ctag, keys);
Chris Dearman37550cf2012-10-17 19:54:01 -0700171
172 return(TEST_OUTPUT);
alaffinf5589902000-09-21 21:35:06 +0000173 /* NOTREACHED */
174}
175
Chris Dearman37550cf2012-10-17 19:54:01 -0700176^<<<execution_status>>>$ {
alaffinf5589902000-09-21 21:35:06 +0000177 BEGIN KEY;
178 check_mode(scan_mode, SCAN_TSTKEY, SCAN_OUTPUT, 0);
179 scan_mode = SCAN_TSTKEY;
Chris Dearman37550cf2012-10-17 19:54:01 -0700180 return(EXEC_STATUS);
alaffinf5589902000-09-21 21:35:06 +0000181 /* 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);
Chris Dearman37550cf2012-10-17 19:54:01 -0700217
alaffinf5589902000-09-21 21:35:06 +0000218 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);
Chris Dearman37550cf2012-10-17 19:54:01 -0700231
232 return(KEYWORD);
alaffinf5589902000-09-21 21:35:06 +0000233 /* NOTREACHED */
234}
235
236<KEY>[ \t\n]* {
237 return(SPACE);
238 /* NOTREACHED */
239}
240
Chris Dearman37550cf2012-10-17 19:54:01 -0700241<OUT>^.+$ {
alaffinf5589902000-09-21 21:35:06 +0000242#ifdef DEBUGGING
243 DEBUG(D_SCAN_LEX, 5)
244 printf("TEXT_LINE: %s\n", yytext);
245#endif
246
Chris Dearman37550cf2012-10-17 19:54:01 -0700247 return(TEXT_LINE);
alaffinf5589902000-09-21 21:35:06 +0000248 /* NOTREACHED */
249}
250
Chris Dearman37550cf2012-10-17 19:54:01 -0700251<CUTS>^{W}{S}{UI}{S}{A}{S}":" {
alaffinf5589902000-09-21 21:35:06 +0000252#ifdef DEBUGGING
253 DEBUG(D_SCAN_LEX, 5)
254 printf("CUTS Result: %s\n", yytext);
255#endif
256 cuts_testcase(ctag, keys);
257
Chris Dearman37550cf2012-10-17 19:54:01 -0700258 return(CUTS_RESULT);
alaffinf5589902000-09-21 21:35:06 +0000259 /* 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()
289{
290 BEGIN CUTS;
291 return 0;
292}
293
294/*
295 * Calls lex repeatedly until all input is seen.
296 */
297int
298scanner(tags)
299 SYM tags;
300{
301 alltags = tags; /* move into global scope for lex actions */
302
303 while(yylex())
304 ;
305
306 return 0;
307}
308
309/*
310 * Test-Output record
Chris Dearman37550cf2012-10-17 19:54:01 -0700311 * check if this is a CUTS test; if so, enter the lex "cuts" state;
alaffinf5589902000-09-21 21:35:06 +0000312 * otherwise do nothing and lex will be in a "data" mode that will just
313 * toss all the output.
314 */
315static int
316test_output(tag, keys)
317 SYM tag, keys;
318{
319 char *at;
Chris Dearman37550cf2012-10-17 19:54:01 -0700320
alaffinf5589902000-09-21 21:35:06 +0000321 if((at=(char *)sym_get(keys, "analysis")) != NULL) {
322 /* CUTS:number_of_testcases || CUTS-1:number_of_testcases */
323 if(strncasecmp("cuts", at, 4) == 0) {
324 begin_cuts();
325 /*printf("CUTS output expected\n");*/
326 }
327 }
328 return 0;
329}
330
331/* Input Data State Check
332 * RTS driver output goes thru specific
333 * phases; this is used to verify that the new state is a legal state
Chris Dearman37550cf2012-10-17 19:54:01 -0700334 * to change to from the current state.
alaffinf5589902000-09-21 21:35:06 +0000335 * This accepts a variable number of arguments (valid states to be
336 * in). The last argument MUST be zero
337 */
338struct parse_states {
339 char *name;
340 int bits;
341} parse_states[] = {
342 { "outside", SCAN_OUTSIDE },
343 { "rts_keyword_start", SCAN_RTSKEY },
344 { "test_start | execution_status", SCAN_TSTKEY },
345 { "test_output", SCAN_OUTPUT },
346 { "unknown", 0 }, /*end sentinel: bits = 0 */
347};
348
349static int
350check_mode(int scan_mode, int fst, ...)
351{
352 va_list ap; /* used for variable argument functions*/
353 int found=0; /* set to true if a valid state was found */
354 int ckm; /* Check Mode: the mode to look for */
355 register struct parse_states *ps; /* for looking thru parse_states */
356 char exp_mode[KEYSIZE]; /* expected mode list (for error message) */
357
358 extern int yylineno; /* Line number from Lex */
359
360 /* look thru parse_states; end sentinel is "bits" = 0 */
361 for(ps=parse_states; ps->bits && (ps->bits != fst);ps++)
362 ;
363 strcpy(exp_mode, ps->name);
364
365 /* look at first variable argument */
366 if(fst == scan_mode)
367 found++;
368 else {
369 /* not first... look at variable args */
370 va_start(ap, fst);
371 while(((ckm = va_arg(ap, int)) != 0) && (ckm != scan_mode)) {
372 for(ps=parse_states; ps->bits && (ps->bits != ckm);ps++)
373 ;
374 strcat(exp_mode, ", ");
375 strcat(exp_mode, ps->name);
376 }
377 va_end(ap);
378
379 if(ckm == scan_mode)
380 found++;
381 }
382
383 if(!found) {
384 for(ps=parse_states; ps->bits && (ps->bits != scan_mode);ps++)
385 ;
386
387 fprintf(stderr, "PARSE ERROR -- Line %d found %s in mode %s[%d] expected { %s }\n",
388 yylineno, yytext, ps->name, scan_mode, exp_mode);
389 }
390
391 return 0;
392}
393
394/*
395 * This part of the file contains subroutines called by a lex scanner which
Chris Dearman37550cf2012-10-17 19:54:01 -0700396 * is parsing rts-driver-format input and putting it into a multi-level
alaffinf5589902000-09-21 21:35:06 +0000397 * symbol table.
398 */
399
400/*
401 * References to lex variables
402 */
403/*extern char yytext[]; / * text matched by last pattern */
404/*extern long yyleng; / * length of above */
405
406char **filenames;
407
408int
409lex_files(char **names)
410{
411 /* lex */
412 extern FILE *yyin;
413
414 filenames = names;
415
416 if(*filenames != NULL) {
417#ifdef DEBUGGING
418 DEBUG(D_SCAN, 1)
419 printf("lex_files: first file is %s\n", *filenames);
420#endif
421 if((yyin = fopen(*filenames, "r")) == NULL) {
422 printf("Error opening %s for reading\n", *filenames);
423 exit(1);
424 }
425 }
426
427 return 0;
428}
429
430/*
431 * Called by lex's end-of-file processing.
432 * Open the next file on the command line. If there is no next file,
433 * return "-1" and lex will end.
434 */
435int
436yywrap()
437{
438 extern FILE *yyin;
439 extern int yylineno; /* Line number from Lex */
440
441 if(*filenames != NULL)
442 if(*++filenames != NULL) {
443#ifdef DEBUGGING
444 DEBUG(D_SCAN, 1)
445 printf("yywrap: next file is %s\n", *filenames);
446#endif
447 yylineno=1;
448 if((yyin = fopen(*filenames, "r")) != NULL)
449 return(0);
450 else {
451 printf("Error opening %s for reading\n", *filenames);
452 return(1);
453 }
454 }
455
456 return(-1);
457}
458