/*
* dump-imports.c --
*
* Operations to dump import hierarchies in a human readable format.
*
* Copyright (c) 1999 Frank Strauss, Technical University of Braunschweig.
* Copyright (c) 1999 J. Schoenwaelder, Technical University of Braunschweig.
*
* See the file "COPYING" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
* @(#) $Id: dump-imports.c 5758 2006-08-16 21:10:05Z schoenw $
*/
#include <config.h>
#include <stdio.h>
#include <string.h>
#include "smi.h"
#include "smidump.h"
typedef struct Imports {
char *module;
int count;
struct Imports *nextPtr;
} Imports;
static Imports *getImports(SmiModule *smiModule, int *n)
{
SmiImport *smiImport;
Imports *imports;
int i;
size_t size;
for (smiImport = smiGetFirstImport(smiModule), *n = 0;
smiImport; smiImport = smiGetNextImport(smiImport)) {
(*n)++;
}
size = (*n + 1) * sizeof(Imports);
imports = xmalloc(size);
memset(imports, 0, size);
for (smiImport = smiGetFirstImport(smiModule), *n = 0;
smiImport; smiImport = smiGetNextImport(smiImport)) {
if (!smiImport->module) continue;
for (i = 0; i < *n; i++) {
if (strcmp(smiImport->module, imports[i].module) == 0) {
break;
}
}
if (i == *n) {
imports[i].module = xstrdup(smiImport->module);
if (imports[i].module) {
imports[i].count = 0;
(*n)++;
}
}
imports[i].count++;
}
return imports;
}
static void freeImports(Imports *imports, int n)
{
int i;
for (i = 0; i < n; i++) {
xfree(imports[i].module);
}
xfree(imports);
}
static int fprintImports(FILE *f, SmiModule *smiModule, char *prefix,
Imports *backtrace)
{
SmiModule *smiModule2;
Imports *imports, *imp;
int i, n, recurse = 0, done = 0;
for (imp = backtrace; imp; imp = imp->nextPtr) {
if (strcmp(imp->module, smiModule->name) == 0) {
fprintf(stderr, "%s (recursion - aborted)\n", prefix);
return 0;
}
}
imp = (Imports *) xmalloc(sizeof(Imports));
imp->module = smiModule->name;
imp->nextPtr = backtrace;
backtrace = imp;
imports = getImports(smiModule, &n);
for (i = 0; i < n; i++) {
char *newprefix;
smiModule2 = smiGetModule(imports[i].module);
recurse = (NULL == smiGetFirstImport(smiModule2));
if (recurse) {
fprintf(f, "%s |\n", prefix);
}
fprintf(f, "%s +--%s [%d identifier%s]\n", prefix, imports[i].module,
imports[i].count, imports[i].count > 1 ? "s" : "");
newprefix = xmalloc(strlen(prefix)+10);
strcpy(newprefix, prefix);
if (i == n-1) {
strcat(newprefix, " ");
} else {
strcat(newprefix, " |");
}
done = fprintImports(f, smiModule2, newprefix, backtrace);
if (! recurse && done) {
if (i == n-1) {
fprintf(f, "%s \n", prefix);
} else {
fprintf(f, "%s |\n", prefix);
}
}
xfree(newprefix);
}
freeImports(imports, n);
xfree(backtrace);
return recurse;
}
static void dumpImports(int modc, SmiModule **modv, int flags, char *output)
{
int i;
FILE *f = stdout;
if (output) {
f = fopen(output, "w");
if (!f) {
fprintf(stderr, "smidump: cannot open %s for writing: ", output);
perror(NULL);
exit(1);
}
}
for (i = 0; i < modc; i++) {
if (! (flags & SMIDUMP_FLAG_SILENT)) {
fprintf(f, "# %s imports tree (generated by smidump "
SMI_VERSION_STRING ")\n\n", modv[i]->name);
}
if (! (flags & SMIDUMP_FLAG_SILENT) && (flags & SMIDUMP_FLAG_ERROR)) {
fprintf(f, "# WARNING: this output may be incorrect due to "
"significant parse errors\n\n");
}
fprintf(f, "%s\n", modv[i]->name);
fprintImports(f, modv[i], "", NULL);
}
if (fflush(f) || ferror(f)) {
perror("smidump: write error");
exit(1);
}
if (output) {
fclose(f);
}
}
void initImports()
{
static SmidumpDriver driver = {
"imports",
dumpImports,
SMI_FLAG_NODESCR,
SMIDUMP_DRIVER_CANT_UNITE,
"recursive list of all imports",
NULL,
NULL
};
smidumpRegisterDriver(&driver);
}