Home | History | Annotate | Download | only in pan
      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