Imported Upstream version 0.4.8
[platform/upstream/libsmi.git] / tools / dump-types.c
1 /*
2  * dump-types.c --
3  *
4  *      Operations to dump the type hierarchy 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-types.c 8090 2008-04-18 12:56:29Z strauss $
13  */
14
15 /*
16  * Decide how we want to name the implicitely defined types.
17  */
18
19 #include <config.h>
20
21 #include <stdio.h>
22 #include <string.h>
23 #include <ctype.h>
24
25 #include "smi.h"
26 #include "smidump.h"
27
28
29 static int noimplicit = 0;
30
31
32 typedef struct BaseTypeCount {
33     SmiBasetype basetype;
34     int         counter;
35 } BaseTypeCount;
36
37
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 }
51 };
52
53
54 typedef struct TypeNode {
55     SmiType     *smiType;
56     SmiModule   *smiModule;
57     SmiBasetype smiBasetype;
58     struct TypeNode *nextNodePtr;
59     struct TypeNode *childNodePtr;
60 } TypeNode;
61
62
63 static TypeNode typeRoot = {
64     NULL, NULL, SMI_BASETYPE_UNKNOWN, NULL, NULL
65 };
66
67
68 static int pmodc = 0;
69 static SmiModule **pmodv = NULL;
70
71
72 static char getStatusChar(SmiStatus status)
73 {
74     switch (status) {
75     case SMI_STATUS_UNKNOWN:
76         return '+';
77     case SMI_STATUS_CURRENT:
78         return '+';
79     case SMI_STATUS_DEPRECATED:
80         return 'x';
81     case SMI_STATUS_MANDATORY:
82         return '+';
83     case SMI_STATUS_OPTIONAL:
84         return '+';
85     case SMI_STATUS_OBSOLETE:
86         return 'o';
87     }
88
89     return ' ';
90 }
91
92
93
94 static char *getFlags(SmiModule *smiModule, SmiType *smiType)
95 {
96     static char flags[4];
97     int         i;
98     
99     memset(flags, 0, sizeof(flags));
100     strcpy(flags, "---");
101
102     switch (smiType->decl) {
103     case SMI_DECL_IMPLICIT_TYPE:
104         flags[0] = 'i';
105         break;
106     case SMI_DECL_TYPEASSIGNMENT:
107         flags[0] = 'a';
108         break;
109     case SMI_DECL_TEXTUALCONVENTION:
110     case SMI_DECL_TYPEDEF:
111         flags[0] = 't';
112         break;
113     default:
114         break;
115     }
116
117     for (i = 0; i < pmodc; i++) {
118         if (strcmp(pmodv[i]->name, smiModule->name) == 0) {
119             break;
120         }
121     }
122
123     if ((!smiModule) || (strlen(smiModule->name) == 0)) {
124         flags[2] = 'b';
125 #if 0   /* xxx fixme */
126     } else if (!moduleList) {
127         flags[2] = '-';
128     } else if (mPtr) {
129         flags[2] = 'l';
130 #endif
131     } else {
132         flags[2] = 'i';
133     }
134
135     return flags;
136 }
137
138
139
140 static void initBaseTypeCount()
141 {
142     int i;
143
144     for (i = 0; i < sizeof(basetypes)/sizeof(BaseTypeCount); i++) {
145         basetypes[i].counter = 0;
146     }
147 }
148
149
150
151 static void incrBaseTypeCount(SmiBasetype basetype)
152 {
153     int i;
154
155     for (i = 0; i < sizeof(basetypes)/sizeof(BaseTypeCount); i++) {
156         if (basetypes[i].basetype == basetype) {
157             basetypes[i].counter++;
158         }
159     }
160 }
161
162
163
164 static int getBaseTypeCount(SmiBasetype basetype)
165 {
166     int i;
167
168     for (i = 0; i < sizeof(basetypes)/sizeof(BaseTypeCount); i++) {
169         if (basetypes[i].basetype == basetype) {
170             return basetypes[i].counter;
171         }
172     }
173
174     return -1;
175 }
176
177
178
179 static char *getValueString(SmiValue *valuePtr, SmiType *typePtr)
180 {
181     static char    s[1024];
182     char           ss[9];
183     int            n;
184     unsigned int   i;
185     SmiNamedNumber *nn;
186     SmiNode        *nodePtr;
187     
188     s[0] = 0;
189     
190     switch (valuePtr->basetype) {
191     case SMI_BASETYPE_UNSIGNED32:
192         sprintf(s, "%lu", valuePtr->value.unsigned32);
193         break;
194     case SMI_BASETYPE_INTEGER32:
195         sprintf(s, "%ld", valuePtr->value.integer32);
196         break;
197     case SMI_BASETYPE_UNSIGNED64:
198         sprintf(s, UINT64_FORMAT, valuePtr->value.unsigned64);
199         break;
200     case SMI_BASETYPE_INTEGER64:
201         sprintf(s, INT64_FORMAT, valuePtr->value.integer64);
202         break;
203     case SMI_BASETYPE_FLOAT32:
204     case SMI_BASETYPE_FLOAT64:
205     case SMI_BASETYPE_FLOAT128:
206         break;
207     case SMI_BASETYPE_ENUM:
208         for (nn = smiGetFirstNamedNumber(typePtr); nn;
209              nn = smiGetNextNamedNumber(nn)) {
210             if (nn->value.value.unsigned32 == valuePtr->value.unsigned32)
211                 break;
212         }
213         if (nn) {
214             sprintf(s, "%s", nn->name);
215         } else {
216             sprintf(s, "%ld", valuePtr->value.integer32);
217         }
218         break;
219     case SMI_BASETYPE_OCTETSTRING:
220         for (i = 0; i < valuePtr->len; i++) {
221             if (!isprint((int)valuePtr->value.ptr[i])) break;
222         }
223         if (i == valuePtr->len) {
224             sprintf(s, "\"%s\"", valuePtr->value.ptr);
225         } else {
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);
230             }
231         }
232         break;
233     case SMI_BASETYPE_BITS:
234         sprintf(s, "(");
235         for (i = 0, n = 0; i < valuePtr->len * 8; i++) {
236             if (valuePtr->value.ptr[i/8] & (1 << (7-(i%8)))) {
237                 if (n)
238                     sprintf(&s[strlen(s)], ", ");
239                 n++;
240                 for (nn = smiGetFirstNamedNumber(typePtr); nn;
241                      nn = smiGetNextNamedNumber(nn)) {
242                     if (nn->value.value.unsigned32 == i)
243                         break;
244                 }
245                 if (nn) {
246                     sprintf(&s[strlen(s)], "%s", nn->name);
247                 } else {
248                     sprintf(s, "%d", i);
249                 }
250             }
251         }
252         sprintf(&s[strlen(s)], ")");
253         break;
254     case SMI_BASETYPE_UNKNOWN:
255         break;
256     case SMI_BASETYPE_POINTER:
257         break;
258     case SMI_BASETYPE_OBJECTIDENTIFIER:
259         nodePtr = smiGetNodeByOID(valuePtr->len, valuePtr->value.oid);
260         if (!nodePtr) {
261             sprintf(s, "%s", nodePtr->name);
262         } else {
263             strcpy(s, "");
264             for (i=0; i < valuePtr->len; i++) {
265                 if (i) strcat(s, ".");
266                 sprintf(&s[strlen(s)], "%u", valuePtr->value.oid[i]);
267             }
268         }
269         break;
270     }
271
272     return s;
273 }
274
275
276
277 static void addToTypeTree(TypeNode *root,
278                           SmiModule *smiModule, SmiType *smiType)
279 {
280     TypeNode  *newType, **typePtrPtr;
281     SmiType   *smiParentType;
282     SmiModule *smiParentModule;
283
284     if (! root) {
285         return;
286     }
287
288     smiParentType = smiGetParentType(smiType);
289     smiParentModule = smiParentType ? smiGetTypeModule(smiParentType) : NULL;
290
291     if ((root->smiModule == smiParentModule && root->smiType == smiParentType)
292         || (! root->smiModule && ! root->smiType
293             && root->smiBasetype == smiType->basetype)) {
294
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;
301
302          for (typePtrPtr = &(root->childNodePtr);
303               *typePtrPtr; typePtrPtr = &((*typePtrPtr)->nextNodePtr)) ;
304          *typePtrPtr = newType;
305          return;
306      }
307
308      if (root->nextNodePtr) {
309          addToTypeTree(root->nextNodePtr, smiModule, smiType);
310      }
311      
312      if (root->childNodePtr) {
313          addToTypeTree(root->childNodePtr, smiModule, smiType);
314      }
315 }
316
317
318
319 static void freeTypeTree(TypeNode *root)
320 {
321     if (root->childNodePtr) {
322         if (root->childNodePtr->smiModule) {
323             freeTypeTree(root->childNodePtr);
324             root->childNodePtr = NULL;
325         } else {
326             freeTypeTree(root->childNodePtr);
327         }
328     }
329     
330     if (root->nextNodePtr) {
331         if (root->nextNodePtr->smiModule) {
332             freeTypeTree(root->nextNodePtr);
333             root->nextNodePtr = NULL;
334         } else {
335             freeTypeTree(root->nextNodePtr);
336         }
337     }
338     
339     if (root->smiModule) {
340         xfree(root);
341     }
342 }
343
344
345
346 static TypeNode *findInTypeTree(TypeNode *root,
347                                 SmiModule *smiModule, SmiType *smiType)
348 {
349     TypeNode *result = NULL;
350     
351     if (root->smiModule && root->smiModule == smiModule
352         && smiType->name
353         && root->smiType && root->smiType == smiType) {
354         result = root;
355     }
356     
357     if (!result && root->childNodePtr) {
358         result = findInTypeTree(root->childNodePtr, smiModule, smiType);
359     }
360     
361     if (!result && root->nextNodePtr) {
362         result = findInTypeTree(root->nextNodePtr, smiModule, smiType);
363     }
364     
365     return result;
366 }
367
368
369
370 static char* getTypeName(TypeNode *typeNode)
371 {
372     SmiRefinement *smiRefinement;
373     SmiType *smiType;
374     char *name = "?";
375
376     if (typeNode->smiType->name) {
377 #if 1
378         return xstrdup(typeNode->smiType->name);
379 #else
380         char *s;
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);
385         return s;
386 #endif
387         
388     } else if (typeNode->smiModule) {
389         SmiNode *smiNode;
390
391         for (smiNode = smiGetFirstNode(typeNode->smiModule, SMI_NODEKIND_ANY);
392              smiNode;
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);
397                 return name;
398             }
399         }
400
401         for (smiNode = smiGetFirstNode(typeNode->smiModule,
402                                        SMI_NODEKIND_COMPLIANCE);
403              smiNode;
404              smiNode = smiGetNextNode(smiNode, SMI_NODEKIND_COMPLIANCE)) {
405             for(smiRefinement = smiGetFirstRefinement(smiNode);
406                 smiRefinement;
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);
413                     return name;
414                 }
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);
420                     return name;
421                 }
422             }
423         }
424     }
425
426     return xstrdup(name);
427 }
428
429
430
431 static void fprintRestrictions(FILE *f, SmiType *smiType)
432 {
433     SmiNamedNumber *nn;
434     SmiRange       *range;
435     char           s1[40], s2[40];
436     int            i;
437     
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);
444         }
445         if (i) fprintf(f, "}");
446     } else {
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);
453         }
454         if (i) fprintf(f, "]");
455     }
456 }
457
458
459
460 static void fprintTypeTree(FILE *f, TypeNode *root, char *prefix)
461 {
462     TypeNode *typeNode, *nextNode;
463     char *name;
464     int namelen = -1;
465
466     if (root->smiModule) {
467         fprintf(f, "%s  |\n", prefix);
468     }
469
470     for (typeNode = root; typeNode; typeNode = typeNode->nextNodePtr) {
471         if (typeNode->smiType) {
472             int len;
473             name = getTypeName(typeNode);
474             len = strlen(name);
475             if (len > namelen) namelen = len;
476             xfree(name);
477         }
478     }
479     
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,
490                                 namelen, name);
491                     } else {
492                         fprintf(f, "%s  %c--%-*s", prefix, c,
493                                 namelen, name);
494                     }
495                     fprintRestrictions(f, typeNode->smiType);
496                     if (typeNode->smiType->format) {
497                         fprintf(f, "\t\"%s\"", typeNode->smiType->format);
498                     }
499                     fprintf(f, "\n");
500                 }
501                 xfree(name);
502             } else {
503                 fprintf(f, "xxxx\n");
504             }
505         }
506         if (typeNode->childNodePtr) {
507             char *newprefix;
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)) {
514                         break;
515                     }
516                 }
517                 if (nextNode) {
518                     strcat(newprefix, "  |");
519                 } else {
520                     strcat(newprefix, "   ");
521                 }
522             }
523             fprintTypeTree(f, typeNode->childNodePtr, newprefix);
524             xfree(newprefix);
525             for (nextNode = typeNode->nextNodePtr;
526                  nextNode; nextNode = nextNode->nextNodePtr) {
527                 if (getBaseTypeCount(nextNode->smiBasetype)) {
528                     break;
529                 }
530             }
531             if (nextNode) {
532                 fprintf(f, "%s  |\n", prefix);
533             }
534         }
535     }
536 }
537
538
539
540 static void addType(SmiType *smiType)
541 {
542     SmiModule *smiModule;
543     SmiType   *smiParentType;
544
545     smiModule = smiGetTypeModule(smiType);
546     if (! smiModule) {
547         return;
548     }
549     
550     if (findInTypeTree(&typeRoot, smiModule, smiType)) {
551         return;
552     }
553
554     smiParentType = smiGetParentType(smiType);
555     if (smiParentType && smiParentType->name) {
556         if (smiParentType) {
557             addType(smiParentType);
558         }
559     }
560
561     addToTypeTree(&typeRoot, smiModule, smiType);
562     incrBaseTypeCount(smiType->basetype);
563 }
564
565
566
567 static void dumpTypes(int modc, SmiModule **modv, int flags, char *output)
568 {
569     SmiNode       *smiNode;
570     SmiType       *smiType;
571     SmiRefinement *smiRefinement;
572     int           i;
573     FILE          *f = stdout;
574     const unsigned int nodekind = SMI_NODEKIND_COLUMN | SMI_NODEKIND_SCALAR;
575     
576     if (output) {
577         f = fopen(output, "w");
578         if (!f) {
579             fprintf(stderr, "smidump: cannot open %s for writing: ", output);
580             perror(NULL);
581             exit(1);
582         }
583     }
584
585     pmodc = modc;
586     pmodv = modv;
587     
588     initBaseTypeCount();
589
590     for (i = 0; i < modc; i++) {
591
592         if (! (flags & SMIDUMP_FLAG_UNITE)) {
593             initBaseTypeCount();
594         }
595
596         for (smiType = smiGetFirstType(modv[i]);
597              smiType;
598              smiType = smiGetNextType(smiType)) {
599             addType(smiType);
600         }
601
602         for (smiNode = smiGetFirstNode(modv[i], nodekind);
603              smiNode;
604              smiNode = smiGetNextNode(smiNode, nodekind)) {
605             smiType = smiGetNodeType(smiNode);
606             if (smiType) {
607                 if (!noimplicit && smiType->decl == SMI_DECL_IMPLICIT_TYPE) {
608                     addType(smiType);
609                 }
610                 incrBaseTypeCount(smiType->basetype);
611             }
612         }
613         
614         for (smiNode = smiGetFirstNode(modv[i], SMI_NODEKIND_COMPLIANCE);
615              smiNode;
616              smiNode = smiGetNextNode(smiNode, SMI_NODEKIND_COMPLIANCE)) {
617             for (smiRefinement = smiGetFirstRefinement(smiNode);
618                  smiRefinement;
619                  smiRefinement = smiGetNextRefinement(smiRefinement)) {
620                 smiType = smiGetRefinementType(smiRefinement);
621                 if (smiType) {
622                     if (!noimplicit
623                         && smiType->decl == SMI_DECL_IMPLICIT_TYPE) {
624                         addType(smiType);
625                     }
626                     incrBaseTypeCount(smiType->basetype);
627                 }
628                 smiType = smiGetRefinementWriteType(smiRefinement);
629                 if (smiType) {
630                     if (!noimplicit
631                         && smiType->decl == SMI_DECL_IMPLICIT_TYPE) {
632                         addType(smiType);
633                     }
634                     incrBaseTypeCount(smiType->basetype);
635                 }
636             }
637         }
638
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);
643             }
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");
647             }
648             fprintTypeTree(f, &typeRoot, "");
649             freeTypeTree(&typeRoot);
650         }
651     }
652
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");
657         }
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");
661         }
662         fprintTypeTree(f, &typeRoot, "");
663         freeTypeTree(&typeRoot);
664     }
665
666     if (fflush(f) || ferror(f)) {
667         perror("smidump: write error");
668         exit(1);
669     }
670
671     if (output) {
672         fclose(f);
673     }
674 }
675
676
677
678 void initTypes()
679 {
680     static SmidumpDriverOption opt[] = {
681         { "no-implicit", OPT_FLAG, &noimplicit, 0,
682           "ignore implicit type definitions"},
683         { 0, OPT_END, 0, 0 }
684     };
685     
686     static SmidumpDriver driver = {
687         "types",
688         dumpTypes,
689         SMI_FLAG_NODESCR,
690         0,
691         "recursive list of all derived types",
692         opt,
693         NULL
694     };
695     
696     smidumpRegisterDriver(&driver);
697 }