blob: 114eeeedfe1725ba495309f09221677053182d4a [file] [log] [blame]
alaffinf5589902000-09-21 21:35:06 +00001/*
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}