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