reporter.c revision f558990ac3f93adbf55881b01bda52b41292667a
1/* 2 * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. 3 * 4 * This program is free software; you can redistribute it and/or modify it 5 * under the terms of version 2 of the GNU General Public License as 6 * published by the Free Software Foundation. 7 * 8 * This program is distributed in the hope that it would be useful, but 9 * WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 11 * 12 * Further, this software is distributed without any warranty that it is 13 * free of the rightful claim of any third person regarding infringement 14 * or the like. Any license provided herein, whether implied or 15 * otherwise, applies only to this software file. Patent licenses, if 16 * any, provided herein do not apply to combinations of this program with 17 * other software, or any other product whatsoever. 18 * 19 * You should have received a copy of the GNU General Public License along 20 * with this program; if not, write the Free Software Foundation, Inc., 59 21 * Temple Place - Suite 330, Boston MA 02111-1307, USA. 22 * 23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, 24 * Mountain View, CA 94043, or: 25 * 26 * http://www.sgi.com 27 * 28 * For further information regarding this notice, see: 29 * 30 * http://oss.sgi.com/projects/GenInfo/NoticeExplan/ 31 * 32 */ 33/* $Id: reporter.c,v 1.1 2000/09/21 21:35:06 alaffin Exp $ */ 34/* 35 * This is the report generator half of the scanner program. 36 */ 37 38#include <stdio.h> 39#include <stdlib.h> 40#include <string.h> 41#include <time.h> 42#include <unistd.h> 43#include <malloc.h> 44#include "reporter.h" 45#include "symbol.h" 46#include "tag_report.h" 47#include "splitstr.h" 48 49/************************************************************************ 50 * Report Generation * 51 ************************************************************************/ 52 53static int scanner_reporter( SYM ); 54static int iscanner_reporter( SYM ); 55static int scanner_test_end( SYM, SYM, SYM ); 56static int iscanner_test_end( SYM, SYM, SYM ); 57 58static int (*reporter_func)( SYM ) = scanner_reporter; 59static int (*test_end_func)( SYM, SYM, SYM ) = scanner_test_end; 60 61/* 62 * Do the report generation. 63 * 64 * A problem: I really need multiple cursors. I'd rather not look into 65 * the depths of the current symbol table implimentation (there are the 66 * cursors there that I could use) so that a different (faster!) symbol 67 * table can be used in the future. 68 * 69 * I could get a key (tag), get it's sub-keys (TCIDs), then get the key 70 * again to reset to the top level, _then_ get the next key. That would 71 * be very inefficient. 72 * 73 * The solution I chose is to extract all tags into a list (char array), 74 * then go thru that list with the cursor free for other levels to use. 75 * 76 * (1) make a list (2d char array) of all Tags 77 * (2) search for the first tag that has a "stime" record, and use that as 78 * the date (MMDDYY) that the tests were run. 79 * (3) print the report header 80 * (4) go thru all tags and report each as described at the beginning of 81 * this file 82 */ 83static int 84scanner_reporter(tags) 85 SYM tags; 86{ 87 DBT Key, Data; 88 SYM Tag, Keys; 89 90 time_t clock; 91 struct tm *tm; 92 93 /* a list of tags, a count of the number of tags allocated to the list, 94 and a pointer to go thru the list */ 95 char **taglist, **tl; 96 int ntags; 97 int tagcount; /* how many tags used */ 98 99 char key_get[KEYSIZE]; 100 char *info; 101 102 103 /* 104 * extract tag names from data 105 */ 106 ntags=NTAGS_START; 107 taglist= (char **)malloc(sizeof(char *) * ntags); 108 tagcount=0; 109 110 tl = taglist; 111 sym_seq(tags, &Key, &Data, R_FIRST); 112 do { 113 if(tagcount == ntags) { 114 /* exceeded tag array size -- realloc */ 115 ntags += NTAGS_START; 116 taglist= (char **)realloc(taglist, sizeof(char *) * ntags); 117 tl = taglist+tagcount; 118 } 119 120 *tl++ = Key.data; 121 tagcount++; 122 } while(sym_seq(tags, &Key, &Data, R_NEXT)==0); 123 124 if(tagcount == ntags) { 125 /* exceeded tag array size -- realloc */ 126 ntags += NTAGS_START; 127 taglist= (char **)realloc(taglist, sizeof(char *) * ntags); 128 tl = taglist+tagcount; 129 } 130 131 *tl++ = NULL; 132 ntags = tagcount; 133 /* Retrieve one "stime" to get the date. */ 134 for(tl=taglist; *tl != NULL; tl++) { 135 strcpy(key_get, *tl); 136 strcat(key_get, ",_keys,stime"); 137 if((info = (char *)sym_get(tags, key_get)) != NULL) { 138 clock = atoi(info); 139 tm = gmtime(&clock); 140 strftime(key_get, KEYSIZE, "%x", tm); 141 sym_put(tags, strdup("_RTS,date"), strdup(key_get), 0); 142 break; 143 } 144 } 145 146 print_header(tags); 147 148 /* 149 * The way that I am using 'Keys' and 'Tag' makes assumptions about the 150 * internals of the sym_* data structure. 151 */ 152 /* dump 'em all */ 153 for(tl=taglist; *tl != NULL; tl++) { 154 if(!strcmp(*tl, "_RTS")) 155 continue; 156 157 strcpy(key_get, *tl); 158 strcat(key_get, ",_keys"); 159 if((Keys = sym_get(tags, key_get)) == NULL) { 160 return 0; 161 } 162 163 strcpy(key_get, *tl); 164 if((Tag = sym_get(tags, key_get)) != NULL) { 165 tag_report(NULL, Tag, Keys); 166 } 167 } 168 free(taglist); 169 170 return 0; 171} 172 173/* 174 * End-Of-Test seen, insert this tag into the global tag data. 175 * (1) Get the test's tag 176 * (2) insert the keywords in the "_keys" tag 177 * (3) insert it into the global data under this tag, replacing any existing 178 * data. 179 * 180 * a "feature" of the key implimentation: I can insert a key tree 181 * under another key tree with almost zero brainwork because a SYM 182 * is what the DATA area points to. 183 */ 184static int 185scanner_test_end(alltags, ctag, keys) 186 SYM alltags, ctag, keys; 187{ 188 static int notag=0; /* counter for records with no tag (error) */ 189 char tagname[KEYSIZE]; /* used when creating name (see above) */ 190 char *tag; /* tag name to look things up in */ 191 char *status; /* initiation status of old tag */ 192 SYM rm; /* pointer to old tag -- to remove it */ 193 194 195 if(alltags == NULL || keys == NULL || ctag == NULL) 196 return -1; /* for really messed up test output */ 197 198 /* insert keys into tag */ 199 sym_put(ctag, "_keys", (void *)keys, 0); 200 201 /* get the tag, or build a new one */ 202 if((tag=(char *)sym_get(keys, "tag")) == NULL) { 203 /* this is an "impossible" situation: test_output checks for this 204 * and creates a dummy tag. */ 205 sprintf(tagname, "no_tag_%d", notag++); 206 fprintf(stderr, "No TAG key! Using %s\n", tagname); 207 sym_put(keys, "tag", strdup(tagname), 0); 208 tag=strdup(tagname); 209 } 210 211 /* 212 * Special case: duplicate tag that has an initiation_status failure 213 * is thrown away. 214 */ 215 if((rm=(SYM)sym_get(alltags, tag)) != NULL) { 216 if( (status=(char *)sym_get(keys, "initiation_status")) != NULL ) { 217 if(strcmp(status, "ok")) { 218 /* do not take new data. remove new data */ 219 sym_rm(ctag, RM_KEY | RM_DATA); 220 return 1; 221 } else { 222 /* remove old data in alltags */ 223 sym_rm(rm, RM_KEY | RM_DATA); 224 } 225 } else { 226 /* new data does not have an initiation_status -- throw it away */ 227 sym_rm(ctag, RM_KEY | RM_DATA); 228 return 1; 229 } 230 } 231 232 /* put new data.. replaces existing "tag" key if it exists 233 * (it's data should have been removed above) */ 234 sym_put(alltags, tag, ctag, PUT_REPLACE); 235 236 return 0; 237} 238 239static int 240iscanner_reporter(tags) 241 SYM tags; 242{ 243 return 0; 244} 245 246static int 247iscanner_test_end(alltags, ctag, keys) 248 SYM alltags, ctag, keys; 249{ 250 if(alltags == NULL || keys == NULL || ctag == NULL) 251 return -1; /* for really messed up test output */ 252 253 /* insert keys into tag */ 254 sym_put(ctag, "_keys", (void *)keys, 0); 255 256 257 return tag_report(alltags, ctag, keys); 258} 259 260int reporter( SYM s ) 261{ 262 return reporter_func( s ); 263} 264 265int test_end( SYM a, SYM b, SYM c ) 266{ 267 return test_end_func( a, b, c ); 268} 269 270void set_scanner(void) 271{ 272 reporter_func = scanner_reporter; 273 test_end_func = scanner_test_end; 274} 275 276void set_iscanner(void) 277{ 278 reporter_func = iscanner_reporter; 279 test_end_func = iscanner_test_end; 280} 281