1 /*
2  * dump-imports.c --
3  *
4  *      Operations to dump import hierarchies in a human readable format.
5  *
6  * Copyright (c) 1999 Frank Strauss, Technical University of Braunschweig.
7  * Copyright (c) 1999 J. Schoenwaelder, Technical University of Braunschweig.
8  *
9  * See the file "COPYING" for information on usage and redistribution
10  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
11  *
12  * @(#) $Id: dump-imports.c 5758 2006-08-16 21:10:05Z schoenw $
13  */
14 
15 #include <config.h>
16 
17 #include <stdio.h>
18 #include <string.h>
19 
20 #include "smi.h"
21 #include "smidump.h"
22 
23 
24 typedef struct Imports {
25     char *module;
26     int  count;
27     struct Imports *nextPtr;
28 } Imports;
29 
30 
31 
getImports(SmiModule * smiModule,int * n)32 static Imports *getImports(SmiModule *smiModule, int *n)
33 {
34     SmiImport *smiImport;
35     Imports   *imports;
36     int       i;
37     size_t    size;
38 
39     for (smiImport = smiGetFirstImport(smiModule), *n = 0;
40 	 smiImport; smiImport = smiGetNextImport(smiImport)) {
41 	(*n)++;
42     }
43 
44     size = (*n + 1) * sizeof(Imports);
45     imports = xmalloc(size);
46     memset(imports, 0, size);
47 
48     for (smiImport = smiGetFirstImport(smiModule), *n = 0;
49 	 smiImport; smiImport = smiGetNextImport(smiImport)) {
50 
51 	if (!smiImport->module) continue;
52 
53 	for (i = 0; i < *n; i++) {
54 	    if (strcmp(smiImport->module, imports[i].module) == 0) {
55 		break;
56 	    }
57 	}
58 
59 	if (i == *n) {
60 	    imports[i].module = xstrdup(smiImport->module);
61 	    if (imports[i].module) {
62 		imports[i].count = 0;
63 		(*n)++;
64 	    }
65 	}
66 	imports[i].count++;
67     }
68 
69     return imports;
70 }
71 
72 
73 
freeImports(Imports * imports,int n)74 static void freeImports(Imports *imports, int n)
75 {
76     int i;
77 
78     for (i = 0; i < n; i++) {
79 	xfree(imports[i].module);
80     }
81 
82     xfree(imports);
83 }
84 
85 
86 
fprintImports(FILE * f,SmiModule * smiModule,char * prefix,Imports * backtrace)87 static int fprintImports(FILE *f, SmiModule *smiModule, char *prefix,
88 			 Imports *backtrace)
89 {
90     SmiModule *smiModule2;
91     Imports *imports, *imp;
92     int     i, n, recurse = 0, done = 0;
93 
94     for (imp = backtrace; imp; imp = imp->nextPtr) {
95 	if (strcmp(imp->module, smiModule->name) == 0) {
96 	    fprintf(stderr, "%s  (recursion - aborted)\n", prefix);
97 	    return 0;
98 	}
99     }
100 
101     imp = (Imports *) xmalloc(sizeof(Imports));
102     imp->module = smiModule->name;
103     imp->nextPtr = backtrace;
104     backtrace = imp;
105 
106     imports = getImports(smiModule, &n);
107 
108     for (i = 0; i < n; i++) {
109 	char *newprefix;
110 
111 	smiModule2 = smiGetModule(imports[i].module);
112 	recurse = (NULL == smiGetFirstImport(smiModule2));
113 	if (recurse) {
114 	    fprintf(f, "%s  |\n", prefix);
115 	}
116 	fprintf(f, "%s  +--%s [%d identifier%s]\n", prefix, imports[i].module,
117 		imports[i].count, imports[i].count > 1 ? "s" : "");
118 	newprefix = xmalloc(strlen(prefix)+10);
119 	strcpy(newprefix, prefix);
120 	if (i == n-1) {
121 	    strcat(newprefix, "   ");
122 	} else {
123 	    strcat(newprefix, "  |");
124 	}
125 	done = fprintImports(f, smiModule2, newprefix, backtrace);
126 	if (! recurse && done) {
127 	    if (i == n-1) {
128 		fprintf(f, "%s   \n", prefix);
129 	    } else {
130 		fprintf(f, "%s  |\n", prefix);
131 	    }
132 	}
133 	xfree(newprefix);
134     }
135 
136     freeImports(imports, n);
137     xfree(backtrace);
138 
139     return recurse;
140 }
141 
142 
143 
dumpImports(int modc,SmiModule ** modv,int flags,char * output)144 static void dumpImports(int modc, SmiModule **modv, int flags, char *output)
145 {
146     int  i;
147     FILE *f = stdout;
148 
149     if (output) {
150 	f = fopen(output, "w");
151 	if (!f) {
152 	    fprintf(stderr, "smidump: cannot open %s for writing: ", output);
153 	    perror(NULL);
154 	    exit(1);
155 	}
156     }
157 
158     for (i = 0; i < modc; i++) {
159 	if (! (flags & SMIDUMP_FLAG_SILENT)) {
160 	    fprintf(f, "# %s imports tree (generated by smidump "
161 		    SMI_VERSION_STRING ")\n\n", modv[i]->name);
162 	}
163 
164 	if (! (flags & SMIDUMP_FLAG_SILENT) && (flags & SMIDUMP_FLAG_ERROR)) {
165 	    fprintf(f, "# WARNING: this output may be incorrect due to "
166 		    "significant parse errors\n\n");
167 	}
168 
169 	fprintf(f, "%s\n", modv[i]->name);
170 	fprintImports(f, modv[i], "", NULL);
171     }
172 
173     if (fflush(f) || ferror(f)) {
174 	perror("smidump: write error");
175 	exit(1);
176     }
177 
178     if (output) {
179 	fclose(f);
180     }
181 }
182 
183 
184 
initImports()185 void initImports()
186 {
187 
188     static SmidumpDriver driver = {
189 	"imports",
190 	dumpImports,
191 	SMI_FLAG_NODESCR,
192 	SMIDUMP_DRIVER_CANT_UNITE,
193 	"recursive list of all imports",
194 	NULL,
195 	NULL
196     };
197 
198     smidumpRegisterDriver(&driver);
199 }
200