4 * Operations to dump the type hierarchy in a human readable format.
6 * Copyright (c) 1999 Frank Strauss, Technical University of Braunschweig.
7 * Copyright (c) 1999 J. Schoenwaelder, Technical University of Braunschweig.
9 * See the file "COPYING" for information on usage and redistribution
10 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
12 * @(#) $Id: dump-types.c 8090 2008-04-18 12:56:29Z strauss $
16 * Decide how we want to name the implicitely defined types.
29 static int noimplicit = 0;
32 typedef struct BaseTypeCount {
38 static BaseTypeCount basetypes[] = {
39 { SMI_BASETYPE_INTEGER32, 0 },
40 { SMI_BASETYPE_OCTETSTRING, 0 },
41 { SMI_BASETYPE_OBJECTIDENTIFIER, 0 },
42 { SMI_BASETYPE_UNSIGNED32, 0 },
43 { SMI_BASETYPE_INTEGER64, 0 },
44 { SMI_BASETYPE_UNSIGNED64, 0 },
45 { SMI_BASETYPE_FLOAT32, 0 },
46 { SMI_BASETYPE_FLOAT64, 0 },
47 { SMI_BASETYPE_FLOAT128, 0 },
48 { SMI_BASETYPE_ENUM, 0 },
49 { SMI_BASETYPE_BITS, 0 },
50 { SMI_BASETYPE_UNKNOWN, 0 }
54 typedef struct TypeNode {
57 SmiBasetype smiBasetype;
58 struct TypeNode *nextNodePtr;
59 struct TypeNode *childNodePtr;
63 static TypeNode typeRoot = {
64 NULL, NULL, SMI_BASETYPE_UNKNOWN, NULL, NULL
69 static SmiModule **pmodv = NULL;
72 static char getStatusChar(SmiStatus status)
75 case SMI_STATUS_UNKNOWN:
77 case SMI_STATUS_CURRENT:
79 case SMI_STATUS_DEPRECATED:
81 case SMI_STATUS_MANDATORY:
83 case SMI_STATUS_OPTIONAL:
85 case SMI_STATUS_OBSOLETE:
94 static char *getFlags(SmiModule *smiModule, SmiType *smiType)
99 memset(flags, 0, sizeof(flags));
100 strcpy(flags, "---");
102 switch (smiType->decl) {
103 case SMI_DECL_IMPLICIT_TYPE:
106 case SMI_DECL_TYPEASSIGNMENT:
109 case SMI_DECL_TEXTUALCONVENTION:
110 case SMI_DECL_TYPEDEF:
117 for (i = 0; i < pmodc; i++) {
118 if (strcmp(pmodv[i]->name, smiModule->name) == 0) {
123 if ((!smiModule) || (strlen(smiModule->name) == 0)) {
125 #if 0 /* xxx fixme */
126 } else if (!moduleList) {
140 static void initBaseTypeCount()
144 for (i = 0; i < sizeof(basetypes)/sizeof(BaseTypeCount); i++) {
145 basetypes[i].counter = 0;
151 static void incrBaseTypeCount(SmiBasetype basetype)
155 for (i = 0; i < sizeof(basetypes)/sizeof(BaseTypeCount); i++) {
156 if (basetypes[i].basetype == basetype) {
157 basetypes[i].counter++;
164 static int getBaseTypeCount(SmiBasetype basetype)
168 for (i = 0; i < sizeof(basetypes)/sizeof(BaseTypeCount); i++) {
169 if (basetypes[i].basetype == basetype) {
170 return basetypes[i].counter;
179 static char *getValueString(SmiValue *valuePtr, SmiType *typePtr)
190 switch (valuePtr->basetype) {
191 case SMI_BASETYPE_UNSIGNED32:
192 sprintf(s, "%lu", valuePtr->value.unsigned32);
194 case SMI_BASETYPE_INTEGER32:
195 sprintf(s, "%ld", valuePtr->value.integer32);
197 case SMI_BASETYPE_UNSIGNED64:
198 sprintf(s, UINT64_FORMAT, valuePtr->value.unsigned64);
200 case SMI_BASETYPE_INTEGER64:
201 sprintf(s, INT64_FORMAT, valuePtr->value.integer64);
203 case SMI_BASETYPE_FLOAT32:
204 case SMI_BASETYPE_FLOAT64:
205 case SMI_BASETYPE_FLOAT128:
207 case SMI_BASETYPE_ENUM:
208 for (nn = smiGetFirstNamedNumber(typePtr); nn;
209 nn = smiGetNextNamedNumber(nn)) {
210 if (nn->value.value.unsigned32 == valuePtr->value.unsigned32)
214 sprintf(s, "%s", nn->name);
216 sprintf(s, "%ld", valuePtr->value.integer32);
219 case SMI_BASETYPE_OCTETSTRING:
220 for (i = 0; i < valuePtr->len; i++) {
221 if (!isprint((int)valuePtr->value.ptr[i])) break;
223 if (i == valuePtr->len) {
224 sprintf(s, "\"%s\"", valuePtr->value.ptr);
226 sprintf(s, "0x%*s", 2 * valuePtr->len, "");
227 for (i=0; i < valuePtr->len; i++) {
228 sprintf(ss, "%02x", valuePtr->value.ptr[i]);
229 strncpy(&s[2+2*i], ss, 2);
233 case SMI_BASETYPE_BITS:
235 for (i = 0, n = 0; i < valuePtr->len * 8; i++) {
236 if (valuePtr->value.ptr[i/8] & (1 << (7-(i%8)))) {
238 sprintf(&s[strlen(s)], ", ");
240 for (nn = smiGetFirstNamedNumber(typePtr); nn;
241 nn = smiGetNextNamedNumber(nn)) {
242 if (nn->value.value.unsigned32 == i)
246 sprintf(&s[strlen(s)], "%s", nn->name);
252 sprintf(&s[strlen(s)], ")");
254 case SMI_BASETYPE_UNKNOWN:
256 case SMI_BASETYPE_POINTER:
258 case SMI_BASETYPE_OBJECTIDENTIFIER:
259 nodePtr = smiGetNodeByOID(valuePtr->len, valuePtr->value.oid);
261 sprintf(s, "%s", nodePtr->name);
264 for (i=0; i < valuePtr->len; i++) {
265 if (i) strcat(s, ".");
266 sprintf(&s[strlen(s)], "%u", valuePtr->value.oid[i]);
277 static void addToTypeTree(TypeNode *root,
278 SmiModule *smiModule, SmiType *smiType)
280 TypeNode *newType, **typePtrPtr;
281 SmiType *smiParentType;
282 SmiModule *smiParentModule;
288 smiParentType = smiGetParentType(smiType);
289 smiParentModule = smiParentType ? smiGetTypeModule(smiParentType) : NULL;
291 if ((root->smiModule == smiParentModule && root->smiType == smiParentType)
292 || (! root->smiModule && ! root->smiType
293 && root->smiBasetype == smiType->basetype)) {
295 newType = xmalloc(sizeof(TypeNode));
296 newType->smiModule = smiModule;
297 newType->smiType = smiType;
298 newType->smiBasetype = smiType->basetype;
299 newType->childNodePtr = NULL;
300 newType->nextNodePtr = NULL;
302 for (typePtrPtr = &(root->childNodePtr);
303 *typePtrPtr; typePtrPtr = &((*typePtrPtr)->nextNodePtr)) ;
304 *typePtrPtr = newType;
308 if (root->nextNodePtr) {
309 addToTypeTree(root->nextNodePtr, smiModule, smiType);
312 if (root->childNodePtr) {
313 addToTypeTree(root->childNodePtr, smiModule, smiType);
319 static void freeTypeTree(TypeNode *root)
321 if (root->childNodePtr) {
322 if (root->childNodePtr->smiModule) {
323 freeTypeTree(root->childNodePtr);
324 root->childNodePtr = NULL;
326 freeTypeTree(root->childNodePtr);
330 if (root->nextNodePtr) {
331 if (root->nextNodePtr->smiModule) {
332 freeTypeTree(root->nextNodePtr);
333 root->nextNodePtr = NULL;
335 freeTypeTree(root->nextNodePtr);
339 if (root->smiModule) {
346 static TypeNode *findInTypeTree(TypeNode *root,
347 SmiModule *smiModule, SmiType *smiType)
349 TypeNode *result = NULL;
351 if (root->smiModule && root->smiModule == smiModule
353 && root->smiType && root->smiType == smiType) {
357 if (!result && root->childNodePtr) {
358 result = findInTypeTree(root->childNodePtr, smiModule, smiType);
361 if (!result && root->nextNodePtr) {
362 result = findInTypeTree(root->nextNodePtr, smiModule, smiType);
370 static char* getTypeName(TypeNode *typeNode)
372 SmiRefinement *smiRefinement;
376 if (typeNode->smiType->name) {
378 return xstrdup(typeNode->smiType->name);
381 s = xmalloc(strlen(typeNode->smiType->name)+
382 strlen(typeNode->smiModule ? typeNode->smiModule->name : "") +3);
383 sprintf(s, "%s::%s", typeNode->smiModule ? typeNode->smiModule->name : "",
384 typeNode->smiType->name);
388 } else if (typeNode->smiModule) {
391 for (smiNode = smiGetFirstNode(typeNode->smiModule, SMI_NODEKIND_ANY);
393 smiNode = smiGetNextNode(smiNode, SMI_NODEKIND_ANY)) {
394 if (smiGetNodeType(smiNode) == typeNode->smiType) {
395 name = xmalloc(strlen(smiNode->name) + 3);
396 sprintf(name, "(%s)", smiNode->name);
401 for (smiNode = smiGetFirstNode(typeNode->smiModule,
402 SMI_NODEKIND_COMPLIANCE);
404 smiNode = smiGetNextNode(smiNode, SMI_NODEKIND_COMPLIANCE)) {
405 for(smiRefinement = smiGetFirstRefinement(smiNode);
407 smiRefinement = smiGetNextRefinement(smiRefinement)) {
408 smiType = smiGetRefinementType(smiRefinement);
409 if (smiType == typeNode->smiType) {
410 smiNode = smiGetRefinementNode(smiRefinement);
411 name = xmalloc(strlen(smiNode->name) + 3);
412 sprintf(name, "(%s)", smiNode->name);
415 smiType = smiGetRefinementWriteType(smiRefinement);
416 if (smiType == typeNode->smiType) {
417 smiNode = smiGetRefinementNode(smiRefinement);
418 name = xmalloc(strlen(smiNode->name) + 3);
419 sprintf(name, "(%s)", smiNode->name);
426 return xstrdup(name);
431 static void fprintRestrictions(FILE *f, SmiType *smiType)
438 if ((smiType->basetype == SMI_BASETYPE_ENUM) ||
439 (smiType->basetype == SMI_BASETYPE_BITS)) {
440 for(i = 0, nn = smiGetFirstNamedNumber(smiType);
441 nn ; nn = smiGetNextNamedNumber(nn), i++) {
442 fprintf(f, "%s%s(%ld)", (i == 0) ? " {" : ", ",
443 nn->name, nn->value.value.integer32);
445 if (i) fprintf(f, "}");
447 for(i = 0, range = smiGetFirstRange(smiType);
448 range ; range = smiGetNextRange(range), i++) {
449 strcpy(s1, getValueString(&range->minValue, smiType));
450 strcpy(s2, getValueString(&range->maxValue, smiType));
451 fprintf(f, "%s%s", (i == 0) ? " [" : ", ", s1);
452 if (strcmp(s1, s2)) fprintf(f, "..%s", s2);
454 if (i) fprintf(f, "]");
460 static void fprintTypeTree(FILE *f, TypeNode *root, char *prefix)
462 TypeNode *typeNode, *nextNode;
466 if (root->smiModule) {
467 fprintf(f, "%s |\n", prefix);
470 for (typeNode = root; typeNode; typeNode = typeNode->nextNodePtr) {
471 if (typeNode->smiType) {
473 name = getTypeName(typeNode);
475 if (len > namelen) namelen = len;
480 for (typeNode = root; typeNode; typeNode = typeNode->nextNodePtr) {
481 if (typeNode != &typeRoot) {
482 char c = '+', *flags;
483 if (typeNode->smiType) {
484 name = getTypeName(typeNode);
485 c = getStatusChar(typeNode->smiType->status);
486 if (getBaseTypeCount(typeNode->smiBasetype)) {
487 flags = getFlags(typeNode->smiModule, typeNode->smiType);
488 if (flags && *flags) {
489 fprintf(f, "%s %c-- %s %-*s", prefix, c, flags,
492 fprintf(f, "%s %c--%-*s", prefix, c,
495 fprintRestrictions(f, typeNode->smiType);
496 if (typeNode->smiType->format) {
497 fprintf(f, "\t\"%s\"", typeNode->smiType->format);
503 fprintf(f, "xxxx\n");
506 if (typeNode->childNodePtr) {
508 newprefix = xmalloc(strlen(prefix)+10);
509 strcpy(newprefix, prefix);
510 if (typeNode != &typeRoot) {
511 for (nextNode = typeNode->nextNodePtr;
512 nextNode; nextNode = nextNode->nextNodePtr) {
513 if (getBaseTypeCount(nextNode->smiBasetype)) {
518 strcat(newprefix, " |");
520 strcat(newprefix, " ");
523 fprintTypeTree(f, typeNode->childNodePtr, newprefix);
525 for (nextNode = typeNode->nextNodePtr;
526 nextNode; nextNode = nextNode->nextNodePtr) {
527 if (getBaseTypeCount(nextNode->smiBasetype)) {
532 fprintf(f, "%s |\n", prefix);
540 static void addType(SmiType *smiType)
542 SmiModule *smiModule;
543 SmiType *smiParentType;
545 smiModule = smiGetTypeModule(smiType);
550 if (findInTypeTree(&typeRoot, smiModule, smiType)) {
554 smiParentType = smiGetParentType(smiType);
555 if (smiParentType && smiParentType->name) {
557 addType(smiParentType);
561 addToTypeTree(&typeRoot, smiModule, smiType);
562 incrBaseTypeCount(smiType->basetype);
567 static void dumpTypes(int modc, SmiModule **modv, int flags, char *output)
571 SmiRefinement *smiRefinement;
574 const unsigned int nodekind = SMI_NODEKIND_COLUMN | SMI_NODEKIND_SCALAR;
577 f = fopen(output, "w");
579 fprintf(stderr, "smidump: cannot open %s for writing: ", output);
590 for (i = 0; i < modc; i++) {
592 if (! (flags & SMIDUMP_FLAG_UNITE)) {
596 for (smiType = smiGetFirstType(modv[i]);
598 smiType = smiGetNextType(smiType)) {
602 for (smiNode = smiGetFirstNode(modv[i], nodekind);
604 smiNode = smiGetNextNode(smiNode, nodekind)) {
605 smiType = smiGetNodeType(smiNode);
607 if (!noimplicit && smiType->decl == SMI_DECL_IMPLICIT_TYPE) {
610 incrBaseTypeCount(smiType->basetype);
614 for (smiNode = smiGetFirstNode(modv[i], SMI_NODEKIND_COMPLIANCE);
616 smiNode = smiGetNextNode(smiNode, SMI_NODEKIND_COMPLIANCE)) {
617 for (smiRefinement = smiGetFirstRefinement(smiNode);
619 smiRefinement = smiGetNextRefinement(smiRefinement)) {
620 smiType = smiGetRefinementType(smiRefinement);
623 && smiType->decl == SMI_DECL_IMPLICIT_TYPE) {
626 incrBaseTypeCount(smiType->basetype);
628 smiType = smiGetRefinementWriteType(smiRefinement);
631 && smiType->decl == SMI_DECL_IMPLICIT_TYPE) {
634 incrBaseTypeCount(smiType->basetype);
639 if (! (flags & SMIDUMP_FLAG_UNITE)) {
640 if (! (flags & SMIDUMP_FLAG_SILENT)) {
641 fprintf(f, "# %s type derivation tree (generated by smidump "
642 SMI_VERSION_STRING ")\n\n", modv[i]->name);
644 if (! (flags & SMIDUMP_FLAG_SILENT) && (flags & SMIDUMP_FLAG_ERROR)) {
645 fprintf(f, "# WARNING: this output may be incorrect due to "
646 "significant parse errors\n\n");
648 fprintTypeTree(f, &typeRoot, "");
649 freeTypeTree(&typeRoot);
653 if (flags & SMIDUMP_FLAG_UNITE) {
654 if (! (flags & SMIDUMP_FLAG_SILENT)) {
655 fprintf(f, "# united type derivation tree (generated by smidump "
656 SMI_VERSION_STRING ")\n\n");
658 if (! (flags & SMIDUMP_FLAG_SILENT) && (flags & SMIDUMP_FLAG_ERROR)) {
659 fprintf(f, "# WARNING: this output may be incorrect due to "
660 "significant parse errors\n\n");
662 fprintTypeTree(f, &typeRoot, "");
663 freeTypeTree(&typeRoot);
666 if (fflush(f) || ferror(f)) {
667 perror("smidump: write error");
680 static SmidumpDriverOption opt[] = {
681 { "no-implicit", OPT_FLAG, &noimplicit, 0,
682 "ignore implicit type definitions"},
686 static SmidumpDriver driver = {
691 "recursive list of all derived types",
696 smidumpRegisterDriver(&driver);