blob: d3e9b289bf451ab59f1121bbd8320d54fae51937 [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
21 * with this program; if not, write the Free Software Foundation, Inc., 59
22 * Temple Place - Suite 330, Boston MA 02111-1307, 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 <stdio.h>
61#include <stdlib.h>
62#include <string.h>
63#include <malloc.h> /* malloc / realloc */
64#include <stdarg.h>
65
66#include "scan.h"
67#include "reporter.h"
68#include "symbol.h"
69#include "tag_report.h"
70
71int scan_mode = SCAN_OUTSIDE; /* current mode */
72char *key, *cont; /* keyword pieces */
73SYM keys=NULL; /* stored keywords */
74SYM ctag=NULL; /* temporary - for storing current tag's info */
75SYM alltags; /* entire tag database. set to scanner 'tags' param.*/
76SYM k; /* temporary sym pointer -- for key removal */
77char info[KEYSIZE]; /* tmp string for inserting line numbers */
78static int test_output( SYM, SYM);
79static int check_mode(int, int, ...);
80
81/*
82 * Lex Definitions:
83 * UI Unsigned Integer
84 * A Alphabetic
85 * W "Word" characters (Alpha, Numeric, Hyphens, Underscores)
86 * S Space characters
87 */
88%}
89
90UI [0-9]+
91A [a-zA-Z]+
92W [a-zA-Z0-9_-]+
93S [ \t]+
94
95%Start KEY OUT CUTS
96%%
97^<<<rts_keyword_start>>>$ {
98 BEGIN KEY;
99 check_mode(scan_mode, SCAN_OUTSIDE, 0);
100 scan_mode = SCAN_RTSKEY;
101
102 /* remove any keys that exist right now */
103 if(keys != NULL)
104 sym_rm(keys, RM_KEY | RM_DATA);
105 /* start a new table of keys */
106 keys = sym_open(0, 0, 0);
107 return(KW_START);
108 /* NOTREACHED */
109}
110
111^<<<rts_keyword_end>>>$ {
112 BEGIN 0;
113 check_mode(scan_mode, SCAN_RTSKEY, 0);
114 scan_mode = SCAN_OUTSIDE;
115#ifdef DEBUGGING
116 DEBUG(D_SCAN_LEX, 10) {
117 printf("RTS Keywords:\n");
118 sym_dump_s(keys, 0);
119 }
120#endif
121 /* remove _RTS key, if it exists, before replacing it */
122 if( (k=(SYM)sym_get(alltags, "_RTS")) != NULL) {
123 sym_rm(k, RM_KEY | RM_DATA);
124 }
125
126 sym_put(alltags, "_RTS", (void *)keys, PUT_REPLACE);
127 keys = NULL;
128
129 return(KW_END);
130 /* NOTREACHED */
131}
132
133^<<<test_start>>>$ {
134 BEGIN KEY;
135 check_mode(scan_mode, SCAN_OUTSIDE, 0);
136 scan_mode = SCAN_TSTKEY;
137
138 /*
139 * set up new "tag" and "keys" tables
140 * to put the new data into.
141 */
142
143 /* remove any keys that exist right now */
144 if(keys != NULL)
145 sym_rm(keys, RM_KEY | RM_DATA);
146 keys = sym_open(0, 0, 0);
147
148 sprintf(info, "%d", yylineno);
149 sym_put(keys, "_Start_line", strdup(info), 0);
150
151 /* remove any tag info that exists right now */
152 if(ctag != NULL)
153 sym_rm(ctag, RM_KEY | RM_DATA);
154 ctag = sym_open(0, 0, 0);
155
156 return(TEST_START);
157 /* NOTREACHED */
158}
159
160^<<<test_output>>>$ {
161 BEGIN OUT;
162 check_mode(scan_mode, SCAN_TSTKEY, 0);
163 scan_mode = SCAN_OUTPUT;
164
165 test_output(ctag, keys);
166
167 return(TEST_OUTPUT);
168 /* NOTREACHED */
169}
170
171^<<<execution_status>>>$ {
172 BEGIN KEY;
173 check_mode(scan_mode, SCAN_TSTKEY, SCAN_OUTPUT, 0);
174 scan_mode = SCAN_TSTKEY;
175 return(EXEC_STATUS);
176 /* NOTREACHED */
177}
178
179^<<<test_end>>>$ {
180 BEGIN 0;
181 check_mode(scan_mode, SCAN_TSTKEY, 0);
182 scan_mode = SCAN_OUTSIDE;
183
184 sprintf(info, "%d", yylineno);
185
186 sym_put(keys, "_End_line", strdup(info), 0);
187#ifdef DEBUGGING
188 DEBUG(D_SCAN_LEX, 10) {
189 printf("Tag's Keywords:\n");
190 sym_dump_s(keys, 0);
191 }
192#endif
193 test_end(alltags, ctag, keys);
194 ctag = keys = NULL;
195
196 return(TEST_END);
197 /* NOTREACHED */
198}
199
200<KEY>[a-zA-Z_-]+=\"[^\"\n]+\" {
201 key = yytext;
202 cont = strchr(yytext, '=');
203 *cont++ = '\0';
204 if(*cont == '"') cont++;
205 if(yytext[yyleng-1] == '"')
206 yytext[yyleng-1] = '\0';
207#ifdef DEBUGGING
208 DEBUG(D_SCAN_LEX, 5)
209 printf("A quoted keyword: %s = %s\n", key, cont);
210#endif
211 sym_put(keys, key, strdup(cont), 0);
212
213 return(KEYWORD_QUOTED);
214 /* NOTREACHED */
215}
216
217<KEY>[a-zA-Z_-]+=[^\t \n]+ {
218 key = yytext;
219 cont = strchr(yytext, '=');
220 *cont++ = '\0';
221#ifdef DEBUGGING
222 DEBUG(D_SCAN_LEX, 5)
223 printf("A keyword: %s = %s\n", key, cont);
224#endif
225 sym_put(keys, key, strdup(cont), 0);
226
227 return(KEYWORD);
228 /* NOTREACHED */
229}
230
231<KEY>[ \t\n]* {
232 return(SPACE);
233 /* NOTREACHED */
234}
235
236<OUT>^.+$ {
237#ifdef DEBUGGING
238 DEBUG(D_SCAN_LEX, 5)
239 printf("TEXT_LINE: %s\n", yytext);
240#endif
241
242 return(TEXT_LINE);
243 /* NOTREACHED */
244}
245
246<CUTS>^{W}{S}{UI}{S}{A}{S}":" {
247#ifdef DEBUGGING
248 DEBUG(D_SCAN_LEX, 5)
249 printf("CUTS Result: %s\n", yytext);
250#endif
251 cuts_testcase(ctag, keys);
252
253 return(CUTS_RESULT);
254 /* NOTREACHED */
255}
256
257<CUTS>^{W}{S}{UI}-{UI}{S}{A}{S}":" {
258#ifdef DEBUGGING
259 DEBUG(D_SCAN_LEX, 5)
260 printf("CUTS Result: %s\n", yytext);
261#endif
262 cuts_testcase(ctag, keys);
263
264 return(CUTS_RESULT_R);
265 /* NOTREACHED */
266}
267
268. {
269 return(SPACE);
270 /* NOTREACHED */
271
272}
273"\n" {
274 return(SPACE);
275 /* NOTREACHED */
276}
277%%
278/*
279 * the BEGIN macro only exists in the lex file, so define a routine to
280 * BEGIN the CUTS state.
281 */
282int
283begin_cuts()
284{
285 BEGIN CUTS;
286 return 0;
287}
288
289/*
290 * Calls lex repeatedly until all input is seen.
291 */
292int
293scanner(tags)
294 SYM tags;
295{
296 alltags = tags; /* move into global scope for lex actions */
297
298 while(yylex())
299 ;
300
301 return 0;
302}
303
304/*
305 * Test-Output record
306 * check if this is a CUTS test; if so, enter the lex "cuts" state;
307 * otherwise do nothing and lex will be in a "data" mode that will just
308 * toss all the output.
309 */
310static int
311test_output(tag, keys)
312 SYM tag, keys;
313{
314 char *at;
315
316 if((at=(char *)sym_get(keys, "analysis")) != NULL) {
317 /* CUTS:number_of_testcases || CUTS-1:number_of_testcases */
318 if(strncasecmp("cuts", at, 4) == 0) {
319 begin_cuts();
320 /*printf("CUTS output expected\n");*/
321 }
322 }
323 return 0;
324}
325
326/* Input Data State Check
327 * RTS driver output goes thru specific
328 * phases; this is used to verify that the new state is a legal state
329 * to change to from the current state.
330 * This accepts a variable number of arguments (valid states to be
331 * in). The last argument MUST be zero
332 */
333struct parse_states {
334 char *name;
335 int bits;
336} parse_states[] = {
337 { "outside", SCAN_OUTSIDE },
338 { "rts_keyword_start", SCAN_RTSKEY },
339 { "test_start | execution_status", SCAN_TSTKEY },
340 { "test_output", SCAN_OUTPUT },
341 { "unknown", 0 }, /*end sentinel: bits = 0 */
342};
343
344static int
345check_mode(int scan_mode, int fst, ...)
346{
347 va_list ap; /* used for variable argument functions*/
348 int found=0; /* set to true if a valid state was found */
349 int ckm; /* Check Mode: the mode to look for */
350 register struct parse_states *ps; /* for looking thru parse_states */
351 char exp_mode[KEYSIZE]; /* expected mode list (for error message) */
352
353 extern int yylineno; /* Line number from Lex */
354
355 /* look thru parse_states; end sentinel is "bits" = 0 */
356 for(ps=parse_states; ps->bits && (ps->bits != fst);ps++)
357 ;
358 strcpy(exp_mode, ps->name);
359
360 /* look at first variable argument */
361 if(fst == scan_mode)
362 found++;
363 else {
364 /* not first... look at variable args */
365 va_start(ap, fst);
366 while(((ckm = va_arg(ap, int)) != 0) && (ckm != scan_mode)) {
367 for(ps=parse_states; ps->bits && (ps->bits != ckm);ps++)
368 ;
369 strcat(exp_mode, ", ");
370 strcat(exp_mode, ps->name);
371 }
372 va_end(ap);
373
374 if(ckm == scan_mode)
375 found++;
376 }
377
378 if(!found) {
379 for(ps=parse_states; ps->bits && (ps->bits != scan_mode);ps++)
380 ;
381
382 fprintf(stderr, "PARSE ERROR -- Line %d found %s in mode %s[%d] expected { %s }\n",
383 yylineno, yytext, ps->name, scan_mode, exp_mode);
384 }
385
386 return 0;
387}
388
389/*
390 * This part of the file contains subroutines called by a lex scanner which
391 * is parsing rts-driver-format input and putting it into a multi-level
392 * symbol table.
393 */
394
395/*
396 * References to lex variables
397 */
398/*extern char yytext[]; / * text matched by last pattern */
399/*extern long yyleng; / * length of above */
400
401char **filenames;
402
403int
404lex_files(char **names)
405{
406 /* lex */
407 extern FILE *yyin;
408
409 filenames = names;
410
411 if(*filenames != NULL) {
412#ifdef DEBUGGING
413 DEBUG(D_SCAN, 1)
414 printf("lex_files: first file is %s\n", *filenames);
415#endif
416 if((yyin = fopen(*filenames, "r")) == NULL) {
417 printf("Error opening %s for reading\n", *filenames);
418 exit(1);
419 }
420 }
421
422 return 0;
423}
424
425/*
426 * Called by lex's end-of-file processing.
427 * Open the next file on the command line. If there is no next file,
428 * return "-1" and lex will end.
429 */
430int
431yywrap()
432{
433 extern FILE *yyin;
434 extern int yylineno; /* Line number from Lex */
435
436 if(*filenames != NULL)
437 if(*++filenames != NULL) {
438#ifdef DEBUGGING
439 DEBUG(D_SCAN, 1)
440 printf("yywrap: next file is %s\n", *filenames);
441#endif
442 yylineno=1;
443 if((yyin = fopen(*filenames, "r")) != NULL)
444 return(0);
445 else {
446 printf("Error opening %s for reading\n", *filenames);
447 return(1);
448 }
449 }
450
451 return(-1);
452}
453