/*
* dump-compliances.c --
*
* Operations to dump compliances in a human readable format.
*
* Copyright (c) 2005 J. Schoenwaelder, International University Bremen.
*
* See the file "COPYING" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
* @(#) $Id: dump-compliances.c 1571 2003-07-14 22:58:42Z schoenw $
*/
#include <config.h>
#include <stdio.h>
#include <string.h>
#include "smi.h"
#include "smidump.h"
static char *getFlags(SmiNode *smiNode)
{
switch (smiNode->access) {
case SMI_ACCESS_UNKNOWN:
return "---";
case SMI_ACCESS_NOT_ACCESSIBLE:
return "---";
case SMI_ACCESS_NOTIFY:
return "--n";
case SMI_ACCESS_EVENT_ONLY:
return "--n";
case SMI_ACCESS_READ_ONLY:
return "r-n";
case SMI_ACCESS_READ_WRITE:
return "rwn";
case SMI_ACCESS_NOT_IMPLEMENTED:
return "---";
case SMI_ACCESS_INSTALL:
return "-i-";
case SMI_ACCESS_INSTALL_NOTIFY:
return "-in";
case SMI_ACCESS_REPORT_ONLY:
return "--r";
}
return "";
}
static char getStatusChar(SmiStatus status)
{
switch (status) {
case SMI_STATUS_UNKNOWN:
return '+';
case SMI_STATUS_CURRENT:
return '+';
case SMI_STATUS_DEPRECATED:
return 'x';
case SMI_STATUS_MANDATORY:
return '+';
case SMI_STATUS_OPTIONAL:
return '+';
case SMI_STATUS_OBSOLETE:
return 'o';
}
return ' ';
}
static char *getTypeName(SmiNode *smiNode)
{
char *type;
SmiType *smiType, *parentType;
smiType = smiGetNodeType(smiNode);
if (!smiType || smiNode->nodekind == SMI_NODEKIND_TABLE)
return NULL;
if (smiType->decl == SMI_DECL_IMPLICIT_TYPE) {
parentType = smiGetParentType(smiType);
if (!parentType)
return NULL;
smiType = parentType;
}
type = xstrdup(smiType->name);
return type;
}
static void fprintGroup(FILE *f, SmiNode *smiNode, char c,
int *typelen, int *namelen, int pass)
{
SmiElement *smiElement;
SmiNode *smiObject;
SmiModule *smiModule;
char *type_name;
int tlen = 9, nlen = 9;
switch (smiNode->nodekind) {
case SMI_NODEKIND_GROUP:
for (smiElement = smiGetFirstElement(smiNode);
smiElement;
smiElement = smiGetNextElement(smiElement)) {
smiObject = smiGetElementNode(smiElement);
smiModule = smiGetNodeModule(smiNode);
type_name = getTypeName(smiObject);
if (pass == 1) {
if (type_name) {
int newlen = strlen(type_name);
tlen = (tlen < newlen) ? newlen : tlen;
}
if (smiObject->name) {
int newlen = strlen(smiObject->name);
nlen = (nlen < newlen) ? newlen : nlen;
}
} else if (pass == 2) {
fprintf(f, " %c%c%s %-*s %-*s (%s)\n",
getStatusChar(smiObject->status), c,
getFlags(smiObject),
*typelen, type_name ? type_name : "-",
*namelen, smiObject->name, smiNode->name);
}
xfree(type_name);
}
break;
case SMI_NODEKIND_SCALAR:
case SMI_NODEKIND_COLUMN:
smiObject = smiNode;
type_name = getTypeName(smiObject);
if (pass == 1) {
if (type_name) {
int newlen = strlen(type_name);
tlen = tlen < newlen ? newlen : tlen;
}
if (smiObject->name) {
int newlen = strlen(smiObject->name);
nlen = (nlen < newlen) ? newlen : nlen;
}
} else if (pass == 2) {
fprintf(f, " %c%c%s %-*s %s\n",
getStatusChar(smiObject->status), 'r',
getFlags(smiObject),
*typelen, type_name ? type_name : "-",
smiObject->name);
}
xfree(type_name);
break;
default:
break;
}
if (pass == 1) {
if (typelen) *typelen = tlen;
if (namelen) *namelen = nlen;
}
}
static void fprintCompliance(FILE *f, SmiNode *smiNode,
int *typelen, int *namelen, int pass)
{
SmiElement *smiElement;
SmiOption *smiOption;
SmiRefinement *smiRefinement;
int tlen = 0, nlen = 0;
for (smiElement = smiGetFirstElement(smiNode);
smiElement;
smiElement = smiGetNextElement(smiElement)) {
fprintGroup(f, smiGetElementNode(smiElement), 'm',
(pass == 1) ? &tlen : typelen,
(pass == 1) ? &nlen : namelen, pass);
if (pass == 1) {
if (typelen) {
*typelen = *typelen < tlen ? tlen : *typelen;
}
if (namelen) {
*namelen = *namelen < nlen ? nlen : *namelen;
}
}
}
for(smiOption = smiGetFirstOption(smiNode);
smiOption;
smiOption = smiGetNextOption(smiOption)) {
fprintGroup(f, smiGetOptionNode(smiOption), 'c',
(pass == 1) ? &tlen : typelen,
(pass == 1) ? &nlen : namelen, pass);
if (pass == 1) {
if (typelen) {
*typelen = *typelen < tlen ? tlen : *typelen;
}
if (namelen) {
*namelen = *namelen < nlen ? nlen : *namelen;
}
}
}
for (smiRefinement = smiGetFirstRefinement(smiNode);
smiRefinement;
smiRefinement = smiGetNextRefinement(smiRefinement)) {
fprintGroup(f, smiGetRefinementNode(smiRefinement), 'r',
(pass == 1) ? &tlen : typelen,
(pass == 1) ? &nlen : namelen, pass);
if (pass == 1) {
if (typelen) {
*typelen = *typelen < tlen ? tlen : *typelen;
}
if (namelen) {
*namelen = *namelen < nlen ? nlen : *namelen;
}
}
}
}
static void fprintCompliances(FILE *f, SmiModule *smiModule)
{
SmiNode *smiNode;
int i, typelen = 0, namelen = 0;
for (i = 0, smiNode = smiGetFirstNode(smiModule, SMI_NODEKIND_COMPLIANCE);
smiNode;
smiNode = smiGetNextNode(smiNode, SMI_NODEKIND_COMPLIANCE), i++) {
fprintf(f, "%s%s:\n", i ? "\n" : "", smiNode->name);
fprintCompliance(f, smiNode, &typelen, &namelen, 1);
fprintCompliance(f, smiNode, &typelen, &namelen, 2);
}
}
static void
dumpCompliances(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 compliances (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");
}
fprintCompliances(f, modv[i]);
}
if (fflush(f) || ferror(f)) {
perror("smidump: write error");
exit(1);
}
if (output) {
fclose(f);
}
}
void initCompliances()
{
static SmidumpDriver driver = {
"compliances",
dumpCompliances,
SMI_FLAG_NODESCR,
SMIDUMP_DRIVER_CANT_UNITE,
"compliances with all included objects / notifications",
/* opt, */ NULL,
NULL
};
smidumpRegisterDriver(&driver);
}