Home | History | Annotate | Download | only in pan
      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  */
     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  */
    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 
    234 static int iscanner_reporter(SYM tags)
    235 {
    236 	return 0;
    237 }
    238 
    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 
    250 int reporter(SYM s)
    251 {
    252 	return reporter_func(s);
    253 }
    254 
    255 int test_end(SYM a, SYM b, SYM c)
    256 {
    257 	return test_end_func(a, b, c);
    258 }
    259 
    260 void set_scanner(void)
    261 {
    262 	reporter_func = scanner_reporter;
    263 	test_end_func = scanner_test_end;
    264 }
    265 
    266 void set_iscanner(void)
    267 {
    268 	reporter_func = iscanner_reporter;
    269 	test_end_func = iscanner_test_end;
    270 }
    271