• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
52 static int scanner_reporter(SYM);
53 static int iscanner_reporter(SYM);
54 static int scanner_test_end(SYM, SYM, SYM);
55 static int iscanner_test_end(SYM, SYM, SYM);
56 
57 static int (*reporter_func) (SYM) = scanner_reporter;
58 static 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  */
scanner_reporter(SYM tags)82 static 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  */
scanner_test_end(SYM alltags,SYM ctag,SYM keys)181 static 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 
iscanner_reporter(SYM tags)234 static int iscanner_reporter(SYM tags)
235 {
236 	return 0;
237 }
238 
iscanner_test_end(SYM alltags,SYM ctag,SYM keys)239 static 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 
reporter(SYM s)250 int reporter(SYM s)
251 {
252 	return reporter_func(s);
253 }
254 
test_end(SYM a,SYM b,SYM c)255 int test_end(SYM a, SYM b, SYM c)
256 {
257 	return test_end_func(a, b, c);
258 }
259 
set_scanner(void)260 void set_scanner(void)
261 {
262 	reporter_func = scanner_reporter;
263 	test_end_func = scanner_test_end;
264 }
265 
set_iscanner(void)266 void set_iscanner(void)
267 {
268 	reporter_func = iscanner_reporter;
269 	test_end_func = iscanner_test_end;
270 }
271