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., 21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 "reporter.h" 44#include "symbol.h" 45#include "tag_report.h" 46#include "splitstr.h" 47 48/************************************************************************ 49 * Report Generation * 50 ************************************************************************/ 51 52static int scanner_reporter(SYM); 53static int iscanner_reporter(SYM); 54static int scanner_test_end(SYM, SYM, SYM); 55static int iscanner_test_end(SYM, SYM, SYM); 56 57static int (*reporter_func) (SYM) = scanner_reporter; 58static int (*test_end_func) (SYM, SYM, SYM) = scanner_test_end; 59 60/* 61 * Do the report generation. 62 * 63 * A problem: I really need multiple cursors. I'd rather not look into 64 * the depths of the current symbol table implimentation (there are the 65 * cursors there that I could use) so that a different (faster!) symbol 66 * table can be used in the future. 67 * 68 * I could get a key (tag), get it's sub-keys (TCIDs), then get the key 69 * again to reset to the top level, _then_ get the next key. That would 70 * be very inefficient. 71 * 72 * The solution I chose is to extract all tags into a list (char array), 73 * then go thru that list with the cursor free for other levels to use. 74 * 75 * (1) make a list (2d char array) of all Tags 76 * (2) search for the first tag that has a "stime" record, and use that as 77 * the date (MMDDYY) that the tests were run. 78 * (3) print the report header 79 * (4) go thru all tags and report each as described at the beginning of 80 * this file 81 */ 82static int scanner_reporter(SYM tags) 83{ 84 DBT Key, Data; 85 SYM Tag, Keys; 86 87 time_t clock; 88 struct tm *tm; 89 90 /* a list of tags, a count of the number of tags allocated to the list, 91 and a pointer to go thru the list */ 92 char **taglist, **tl; 93 int ntags; 94 int tagcount; /* how many tags used */ 95 96 char key_get[KEYSIZE]; 97 char *info; 98 99 /* 100 * extract tag names from data 101 */ 102 ntags = NTAGS_START; 103 taglist = malloc(sizeof(char *) * ntags); 104 tagcount = 0; 105 106 tl = taglist; 107 sym_seq(tags, &Key, &Data, R_FIRST); 108 do { 109 if (tagcount == ntags) { 110 /* exceeded tag array size -- realloc */ 111 ntags += NTAGS_START; 112 taglist = 113 (char **)realloc(taglist, sizeof(char *) * ntags); 114 tl = taglist + tagcount; 115 } 116 117 *tl++ = Key.data; 118 tagcount++; 119 } while (sym_seq(tags, &Key, &Data, R_NEXT) == 0); 120 121 if (tagcount == ntags) { 122 /* exceeded tag array size -- realloc */ 123 ntags += NTAGS_START; 124 taglist = (char **)realloc(taglist, sizeof(char *) * ntags); 125 tl = taglist + tagcount; 126 } 127 128 *tl++ = NULL; 129 ntags = tagcount; 130 /* Retrieve one "stime" to get the date. */ 131 for (tl = taglist; *tl != NULL; tl++) { 132 strcpy(key_get, *tl); 133 strcat(key_get, ",_keys,stime"); 134 if ((info = (char *)sym_get(tags, key_get)) != NULL) { 135 clock = atoi(info); 136 tm = gmtime(&clock); 137 strftime(key_get, KEYSIZE, "%x", tm); 138 sym_put(tags, strdup("_RTS,date"), strdup(key_get), 0); 139 break; 140 } 141 } 142 143 print_header(tags); 144 145 /* 146 * The way that I am using 'Keys' and 'Tag' makes assumptions about the 147 * internals of the sym_* data structure. 148 */ 149 /* dump 'em all */ 150 for (tl = taglist; *tl != NULL; tl++) { 151 if (!strcmp(*tl, "_RTS")) 152 continue; 153 154 strcpy(key_get, *tl); 155 strcat(key_get, ",_keys"); 156 if ((Keys = sym_get(tags, key_get)) == NULL) { 157 return 0; 158 } 159 160 strcpy(key_get, *tl); 161 if ((Tag = sym_get(tags, key_get)) != NULL) { 162 tag_report(NULL, Tag, Keys); 163 } 164 } 165 free(taglist); 166 167 return 0; 168} 169 170/* 171 * End-Of-Test seen, insert this tag into the global tag data. 172 * (1) Get the test's tag 173 * (2) insert the keywords in the "_keys" tag 174 * (3) insert it into the global data under this tag, replacing any existing 175 * data. 176 * 177 * a "feature" of the key implimentation: I can insert a key tree 178 * under another key tree with almost zero brainwork because a SYM 179 * is what the DATA area points to. 180 */ 181static int scanner_test_end(SYM alltags, SYM ctag, SYM keys) 182{ 183 static int notag = 0; /* counter for records with no tag (error) */ 184 char tagname[KEYSIZE]; /* used when creating name (see above) */ 185 char *tag; /* tag name to look things up in */ 186 char *status; /* initiation status of old tag */ 187 SYM rm; /* pointer to old tag -- to remove it */ 188 189 if (alltags == NULL || keys == NULL || ctag == NULL) 190 return -1; /* for really messed up test output */ 191 192 /* insert keys into tag */ 193 sym_put(ctag, "_keys", (void *)keys, 0); 194 195 /* get the tag, or build a new one */ 196 if ((tag = (char *)sym_get(keys, "tag")) == NULL) { 197 /* this is an "impossible" situation: test_output checks for this 198 * and creates a dummy tag. */ 199 sprintf(tagname, "no_tag_%d", notag++); 200 fprintf(stderr, "No TAG key! Using %s\n", tagname); 201 sym_put(keys, "tag", strdup(tagname), 0); 202 tag = strdup(tagname); 203 } 204 205 /* 206 * Special case: duplicate tag that has an initiation_status failure 207 * is thrown away. 208 */ 209 if ((rm = (SYM) sym_get(alltags, tag)) != NULL) { 210 if ((status = 211 (char *)sym_get(keys, "initiation_status")) != NULL) { 212 if (strcmp(status, "ok")) { 213 /* do not take new data. remove new data */ 214 sym_rm(ctag, RM_KEY | RM_DATA); 215 return 1; 216 } else { 217 /* remove old data in alltags */ 218 sym_rm(rm, RM_KEY | RM_DATA); 219 } 220 } else { 221 /* new data does not have an initiation_status -- throw it away */ 222 sym_rm(ctag, RM_KEY | RM_DATA); 223 return 1; 224 } 225 } 226 227 /* put new data.. replaces existing "tag" key if it exists 228 * (it's data should have been removed above) */ 229 sym_put(alltags, tag, ctag, PUT_REPLACE); 230 231 return 0; 232} 233 234static int iscanner_reporter(SYM tags) 235{ 236 return 0; 237} 238 239static int iscanner_test_end(SYM alltags, SYM ctag, SYM keys) 240{ 241 if (alltags == NULL || keys == NULL || ctag == NULL) 242 return -1; /* for really messed up test output */ 243 244 /* insert keys into tag */ 245 sym_put(ctag, "_keys", (void *)keys, 0); 246 247 return tag_report(alltags, ctag, keys); 248} 249 250int reporter(SYM s) 251{ 252 return reporter_func(s); 253} 254 255int test_end(SYM a, SYM b, SYM c) 256{ 257 return test_end_func(a, b, c); 258} 259 260void set_scanner(void) 261{ 262 reporter_func = scanner_reporter; 263 test_end_func = scanner_test_end; 264} 265 266void set_iscanner(void) 267{ 268 reporter_func = iscanner_reporter; 269 test_end_func = iscanner_test_end; 270} 271