/* * dump-types.c -- * * Operations to dump the type hierarchy 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-types.c 8090 2008-04-18 12:56:29Z strauss $ */ /* * Decide how we want to name the implicitely defined types. */ #include #include #include #include #include "smi.h" #include "smidump.h" static int noimplicit = 0; typedef struct BaseTypeCount { SmiBasetype basetype; int counter; } BaseTypeCount; static BaseTypeCount basetypes[] = { { SMI_BASETYPE_INTEGER32, 0 }, { SMI_BASETYPE_OCTETSTRING, 0 }, { SMI_BASETYPE_OBJECTIDENTIFIER, 0 }, { SMI_BASETYPE_UNSIGNED32, 0 }, { SMI_BASETYPE_INTEGER64, 0 }, { SMI_BASETYPE_UNSIGNED64, 0 }, { SMI_BASETYPE_FLOAT32, 0 }, { SMI_BASETYPE_FLOAT64, 0 }, { SMI_BASETYPE_FLOAT128, 0 }, { SMI_BASETYPE_ENUM, 0 }, { SMI_BASETYPE_BITS, 0 }, { SMI_BASETYPE_UNKNOWN, 0 } }; typedef struct TypeNode { SmiType *smiType; SmiModule *smiModule; SmiBasetype smiBasetype; struct TypeNode *nextNodePtr; struct TypeNode *childNodePtr; } TypeNode; static TypeNode typeRoot = { NULL, NULL, SMI_BASETYPE_UNKNOWN, NULL, NULL }; static int pmodc = 0; static SmiModule **pmodv = NULL; 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 *getFlags(SmiModule *smiModule, SmiType *smiType) { static char flags[4]; int i; memset(flags, 0, sizeof(flags)); strcpy(flags, "---"); switch (smiType->decl) { case SMI_DECL_IMPLICIT_TYPE: flags[0] = 'i'; break; case SMI_DECL_TYPEASSIGNMENT: flags[0] = 'a'; break; case SMI_DECL_TEXTUALCONVENTION: case SMI_DECL_TYPEDEF: flags[0] = 't'; break; default: break; } for (i = 0; i < pmodc; i++) { if (strcmp(pmodv[i]->name, smiModule->name) == 0) { break; } } if ((!smiModule) || (strlen(smiModule->name) == 0)) { flags[2] = 'b'; #if 0 /* xxx fixme */ } else if (!moduleList) { flags[2] = '-'; } else if (mPtr) { flags[2] = 'l'; #endif } else { flags[2] = 'i'; } return flags; } static void initBaseTypeCount() { int i; for (i = 0; i < sizeof(basetypes)/sizeof(BaseTypeCount); i++) { basetypes[i].counter = 0; } } static void incrBaseTypeCount(SmiBasetype basetype) { int i; for (i = 0; i < sizeof(basetypes)/sizeof(BaseTypeCount); i++) { if (basetypes[i].basetype == basetype) { basetypes[i].counter++; } } } static int getBaseTypeCount(SmiBasetype basetype) { int i; for (i = 0; i < sizeof(basetypes)/sizeof(BaseTypeCount); i++) { if (basetypes[i].basetype == basetype) { return basetypes[i].counter; } } return -1; } static char *getValueString(SmiValue *valuePtr, SmiType *typePtr) { static char s[1024]; char ss[9]; int n; unsigned int i; SmiNamedNumber *nn; SmiNode *nodePtr; s[0] = 0; switch (valuePtr->basetype) { case SMI_BASETYPE_UNSIGNED32: sprintf(s, "%lu", valuePtr->value.unsigned32); break; case SMI_BASETYPE_INTEGER32: sprintf(s, "%ld", valuePtr->value.integer32); break; case SMI_BASETYPE_UNSIGNED64: sprintf(s, UINT64_FORMAT, valuePtr->value.unsigned64); break; case SMI_BASETYPE_INTEGER64: sprintf(s, INT64_FORMAT, valuePtr->value.integer64); break; case SMI_BASETYPE_FLOAT32: case SMI_BASETYPE_FLOAT64: case SMI_BASETYPE_FLOAT128: break; case SMI_BASETYPE_ENUM: for (nn = smiGetFirstNamedNumber(typePtr); nn; nn = smiGetNextNamedNumber(nn)) { if (nn->value.value.unsigned32 == valuePtr->value.unsigned32) break; } if (nn) { sprintf(s, "%s", nn->name); } else { sprintf(s, "%ld", valuePtr->value.integer32); } break; case SMI_BASETYPE_OCTETSTRING: for (i = 0; i < valuePtr->len; i++) { if (!isprint((int)valuePtr->value.ptr[i])) break; } if (i == valuePtr->len) { sprintf(s, "\"%s\"", valuePtr->value.ptr); } else { sprintf(s, "0x%*s", 2 * valuePtr->len, ""); for (i=0; i < valuePtr->len; i++) { sprintf(ss, "%02x", valuePtr->value.ptr[i]); strncpy(&s[2+2*i], ss, 2); } } break; case SMI_BASETYPE_BITS: sprintf(s, "("); for (i = 0, n = 0; i < valuePtr->len * 8; i++) { if (valuePtr->value.ptr[i/8] & (1 << (7-(i%8)))) { if (n) sprintf(&s[strlen(s)], ", "); n++; for (nn = smiGetFirstNamedNumber(typePtr); nn; nn = smiGetNextNamedNumber(nn)) { if (nn->value.value.unsigned32 == i) break; } if (nn) { sprintf(&s[strlen(s)], "%s", nn->name); } else { sprintf(s, "%d", i); } } } sprintf(&s[strlen(s)], ")"); break; case SMI_BASETYPE_UNKNOWN: break; case SMI_BASETYPE_POINTER: break; case SMI_BASETYPE_OBJECTIDENTIFIER: nodePtr = smiGetNodeByOID(valuePtr->len, valuePtr->value.oid); if (!nodePtr) { sprintf(s, "%s", nodePtr->name); } else { strcpy(s, ""); for (i=0; i < valuePtr->len; i++) { if (i) strcat(s, "."); sprintf(&s[strlen(s)], "%u", valuePtr->value.oid[i]); } } break; } return s; } static void addToTypeTree(TypeNode *root, SmiModule *smiModule, SmiType *smiType) { TypeNode *newType, **typePtrPtr; SmiType *smiParentType; SmiModule *smiParentModule; if (! root) { return; } smiParentType = smiGetParentType(smiType); smiParentModule = smiParentType ? smiGetTypeModule(smiParentType) : NULL; if ((root->smiModule == smiParentModule && root->smiType == smiParentType) || (! root->smiModule && ! root->smiType && root->smiBasetype == smiType->basetype)) { newType = xmalloc(sizeof(TypeNode)); newType->smiModule = smiModule; newType->smiType = smiType; newType->smiBasetype = smiType->basetype; newType->childNodePtr = NULL; newType->nextNodePtr = NULL; for (typePtrPtr = &(root->childNodePtr); *typePtrPtr; typePtrPtr = &((*typePtrPtr)->nextNodePtr)) ; *typePtrPtr = newType; return; } if (root->nextNodePtr) { addToTypeTree(root->nextNodePtr, smiModule, smiType); } if (root->childNodePtr) { addToTypeTree(root->childNodePtr, smiModule, smiType); } } static void freeTypeTree(TypeNode *root) { if (root->childNodePtr) { if (root->childNodePtr->smiModule) { freeTypeTree(root->childNodePtr); root->childNodePtr = NULL; } else { freeTypeTree(root->childNodePtr); } } if (root->nextNodePtr) { if (root->nextNodePtr->smiModule) { freeTypeTree(root->nextNodePtr); root->nextNodePtr = NULL; } else { freeTypeTree(root->nextNodePtr); } } if (root->smiModule) { xfree(root); } } static TypeNode *findInTypeTree(TypeNode *root, SmiModule *smiModule, SmiType *smiType) { TypeNode *result = NULL; if (root->smiModule && root->smiModule == smiModule && smiType->name && root->smiType && root->smiType == smiType) { result = root; } if (!result && root->childNodePtr) { result = findInTypeTree(root->childNodePtr, smiModule, smiType); } if (!result && root->nextNodePtr) { result = findInTypeTree(root->nextNodePtr, smiModule, smiType); } return result; } static char* getTypeName(TypeNode *typeNode) { SmiRefinement *smiRefinement; SmiType *smiType; char *name = "?"; if (typeNode->smiType->name) { #if 1 return xstrdup(typeNode->smiType->name); #else char *s; s = xmalloc(strlen(typeNode->smiType->name)+ strlen(typeNode->smiModule ? typeNode->smiModule->name : "") +3); sprintf(s, "%s::%s", typeNode->smiModule ? typeNode->smiModule->name : "", typeNode->smiType->name); return s; #endif } else if (typeNode->smiModule) { SmiNode *smiNode; for (smiNode = smiGetFirstNode(typeNode->smiModule, SMI_NODEKIND_ANY); smiNode; smiNode = smiGetNextNode(smiNode, SMI_NODEKIND_ANY)) { if (smiGetNodeType(smiNode) == typeNode->smiType) { name = xmalloc(strlen(smiNode->name) + 3); sprintf(name, "(%s)", smiNode->name); return name; } } for (smiNode = smiGetFirstNode(typeNode->smiModule, SMI_NODEKIND_COMPLIANCE); smiNode; smiNode = smiGetNextNode(smiNode, SMI_NODEKIND_COMPLIANCE)) { for(smiRefinement = smiGetFirstRefinement(smiNode); smiRefinement; smiRefinement = smiGetNextRefinement(smiRefinement)) { smiType = smiGetRefinementType(smiRefinement); if (smiType == typeNode->smiType) { smiNode = smiGetRefinementNode(smiRefinement); name = xmalloc(strlen(smiNode->name) + 3); sprintf(name, "(%s)", smiNode->name); return name; } smiType = smiGetRefinementWriteType(smiRefinement); if (smiType == typeNode->smiType) { smiNode = smiGetRefinementNode(smiRefinement); name = xmalloc(strlen(smiNode->name) + 3); sprintf(name, "(%s)", smiNode->name); return name; } } } } return xstrdup(name); } static void fprintRestrictions(FILE *f, SmiType *smiType) { SmiNamedNumber *nn; SmiRange *range; char s1[40], s2[40]; int i; if ((smiType->basetype == SMI_BASETYPE_ENUM) || (smiType->basetype == SMI_BASETYPE_BITS)) { for(i = 0, nn = smiGetFirstNamedNumber(smiType); nn ; nn = smiGetNextNamedNumber(nn), i++) { fprintf(f, "%s%s(%ld)", (i == 0) ? " {" : ", ", nn->name, nn->value.value.integer32); } if (i) fprintf(f, "}"); } else { for(i = 0, range = smiGetFirstRange(smiType); range ; range = smiGetNextRange(range), i++) { strcpy(s1, getValueString(&range->minValue, smiType)); strcpy(s2, getValueString(&range->maxValue, smiType)); fprintf(f, "%s%s", (i == 0) ? " [" : ", ", s1); if (strcmp(s1, s2)) fprintf(f, "..%s", s2); } if (i) fprintf(f, "]"); } } static void fprintTypeTree(FILE *f, TypeNode *root, char *prefix) { TypeNode *typeNode, *nextNode; char *name; int namelen = -1; if (root->smiModule) { fprintf(f, "%s |\n", prefix); } for (typeNode = root; typeNode; typeNode = typeNode->nextNodePtr) { if (typeNode->smiType) { int len; name = getTypeName(typeNode); len = strlen(name); if (len > namelen) namelen = len; xfree(name); } } for (typeNode = root; typeNode; typeNode = typeNode->nextNodePtr) { if (typeNode != &typeRoot) { char c = '+', *flags; if (typeNode->smiType) { name = getTypeName(typeNode); c = getStatusChar(typeNode->smiType->status); if (getBaseTypeCount(typeNode->smiBasetype)) { flags = getFlags(typeNode->smiModule, typeNode->smiType); if (flags && *flags) { fprintf(f, "%s %c-- %s %-*s", prefix, c, flags, namelen, name); } else { fprintf(f, "%s %c--%-*s", prefix, c, namelen, name); } fprintRestrictions(f, typeNode->smiType); if (typeNode->smiType->format) { fprintf(f, "\t\"%s\"", typeNode->smiType->format); } fprintf(f, "\n"); } xfree(name); } else { fprintf(f, "xxxx\n"); } } if (typeNode->childNodePtr) { char *newprefix; newprefix = xmalloc(strlen(prefix)+10); strcpy(newprefix, prefix); if (typeNode != &typeRoot) { for (nextNode = typeNode->nextNodePtr; nextNode; nextNode = nextNode->nextNodePtr) { if (getBaseTypeCount(nextNode->smiBasetype)) { break; } } if (nextNode) { strcat(newprefix, " |"); } else { strcat(newprefix, " "); } } fprintTypeTree(f, typeNode->childNodePtr, newprefix); xfree(newprefix); for (nextNode = typeNode->nextNodePtr; nextNode; nextNode = nextNode->nextNodePtr) { if (getBaseTypeCount(nextNode->smiBasetype)) { break; } } if (nextNode) { fprintf(f, "%s |\n", prefix); } } } } static void addType(SmiType *smiType) { SmiModule *smiModule; SmiType *smiParentType; smiModule = smiGetTypeModule(smiType); if (! smiModule) { return; } if (findInTypeTree(&typeRoot, smiModule, smiType)) { return; } smiParentType = smiGetParentType(smiType); if (smiParentType && smiParentType->name) { if (smiParentType) { addType(smiParentType); } } addToTypeTree(&typeRoot, smiModule, smiType); incrBaseTypeCount(smiType->basetype); } static void dumpTypes(int modc, SmiModule **modv, int flags, char *output) { SmiNode *smiNode; SmiType *smiType; SmiRefinement *smiRefinement; int i; FILE *f = stdout; const unsigned int nodekind = SMI_NODEKIND_COLUMN | SMI_NODEKIND_SCALAR; if (output) { f = fopen(output, "w"); if (!f) { fprintf(stderr, "smidump: cannot open %s for writing: ", output); perror(NULL); exit(1); } } pmodc = modc; pmodv = modv; initBaseTypeCount(); for (i = 0; i < modc; i++) { if (! (flags & SMIDUMP_FLAG_UNITE)) { initBaseTypeCount(); } for (smiType = smiGetFirstType(modv[i]); smiType; smiType = smiGetNextType(smiType)) { addType(smiType); } for (smiNode = smiGetFirstNode(modv[i], nodekind); smiNode; smiNode = smiGetNextNode(smiNode, nodekind)) { smiType = smiGetNodeType(smiNode); if (smiType) { if (!noimplicit && smiType->decl == SMI_DECL_IMPLICIT_TYPE) { addType(smiType); } incrBaseTypeCount(smiType->basetype); } } for (smiNode = smiGetFirstNode(modv[i], SMI_NODEKIND_COMPLIANCE); smiNode; smiNode = smiGetNextNode(smiNode, SMI_NODEKIND_COMPLIANCE)) { for (smiRefinement = smiGetFirstRefinement(smiNode); smiRefinement; smiRefinement = smiGetNextRefinement(smiRefinement)) { smiType = smiGetRefinementType(smiRefinement); if (smiType) { if (!noimplicit && smiType->decl == SMI_DECL_IMPLICIT_TYPE) { addType(smiType); } incrBaseTypeCount(smiType->basetype); } smiType = smiGetRefinementWriteType(smiRefinement); if (smiType) { if (!noimplicit && smiType->decl == SMI_DECL_IMPLICIT_TYPE) { addType(smiType); } incrBaseTypeCount(smiType->basetype); } } } if (! (flags & SMIDUMP_FLAG_UNITE)) { if (! (flags & SMIDUMP_FLAG_SILENT)) { fprintf(f, "# %s type derivation 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"); } fprintTypeTree(f, &typeRoot, ""); freeTypeTree(&typeRoot); } } if (flags & SMIDUMP_FLAG_UNITE) { if (! (flags & SMIDUMP_FLAG_SILENT)) { fprintf(f, "# united type derivation tree (generated by smidump " SMI_VERSION_STRING ")\n\n"); } if (! (flags & SMIDUMP_FLAG_SILENT) && (flags & SMIDUMP_FLAG_ERROR)) { fprintf(f, "# WARNING: this output may be incorrect due to " "significant parse errors\n\n"); } fprintTypeTree(f, &typeRoot, ""); freeTypeTree(&typeRoot); } if (fflush(f) || ferror(f)) { perror("smidump: write error"); exit(1); } if (output) { fclose(f); } } void initTypes() { static SmidumpDriverOption opt[] = { { "no-implicit", OPT_FLAG, &noimplicit, 0, "ignore implicit type definitions"}, { 0, OPT_END, 0, 0 } }; static SmidumpDriver driver = { "types", dumpTypes, SMI_FLAG_NODESCR, 0, "recursive list of all derived types", opt, NULL }; smidumpRegisterDriver(&driver); }