Imported Upstream version 0.4.8
[platform/upstream/libsmi.git] / tools / dump-sming.c
1 /*
2  * dump-sming.c --
3  *
4  *      Operations to dump SMIng module information.
5  *
6  * Copyright (c) 1999 Frank Strauss, Technical University of Braunschweig.
7  *
8  * See the file "COPYING" for information on usage and redistribution
9  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
10  *
11  * @(#) $Id: dump-sming.c 8090 2008-04-18 12:56:29Z strauss $
12  */
13
14 #include <config.h>
15
16 #include <stdlib.h>
17 #include <stdio.h>
18 #include <stdarg.h>
19 #include <string.h>
20 #include <ctype.h>
21 #include <time.h>
22
23 #include "smi.h"
24 #include "smidump.h"
25
26
27
28 #define  INDENT         2    /* indent factor */
29 #define  INDENTVALUE    20   /* column to start values, except multiline */
30 #define  INDENTTEXTS    4    /* column to start multiline texts */
31 #define  INDENTMAX      64   /* max column to fill, break lines otherwise */
32
33
34
35 static char *excludeType[] = {
36     "ObjectSyntax",
37     "SimpleSyntax",
38     "ApplicationSyntax",
39     NULL };
40     
41 static char *convertType[] = {
42     "INTEGER",             "Integer32",
43     "OCTET STRING",        "OctetString",
44     "OBJECT IDENTIFIER",   "Pointer",
45     
46     "Gauge",               "Gauge32",
47     "Counter",             "Counter32",
48     "NetworkAddress",      "IpAddress", /* ??? */
49     
50     NULL, NULL };
51
52 static char *convertImport[] = {
53     "SNMPv2-SMI",   "MODULE-IDENTITY",    NULL, NULL,
54     "SNMPv2-SMI",   "OBJECT-IDENTITY",    NULL, NULL,
55     "SNMPv2-SMI",   "OBJECT-TYPE",        NULL, NULL,
56     "SNMPv2-SMI",   "NOTIFICATION-TYPE",  NULL, NULL,
57     "SNMPv2-SMI",   "ObjectName",         NULL, NULL,
58     "SNMPv2-SMI",   "NotificationName",   NULL, NULL,
59     "SNMPv2-SMI",   "ObjectSyntax",       NULL, NULL,
60     "SNMPv2-SMI",   "SimpleSyntax",       NULL, NULL,
61     "SNMPv2-SMI",   "Integer32",          NULL, NULL,
62     "SNMPv2-SMI",   "Unsigned32",         NULL, NULL,
63     "SNMPv2-SMI",   "ApplicationSyntax",  NULL, NULL,
64     "SNMPv2-SMI",   "IpAddress",          "IRTF-NMRG-SMING", "IpAddress",
65     "SNMPv2-SMI",   "Counter32",          "IRTF-NMRG-SMING", "Counter32",
66     "SNMPv2-SMI",   "TimeTicks",          "IRTF-NMRG-SMING", "TimeTicks",
67     "SNMPv2-SMI",   "Opaque",             "IRTF-NMRG-SMING", "Opaque",
68     "SNMPv2-SMI",   "Counter64",          "IRTF-NMRG-SMING", "Counter64",
69     "SNMPv2-SMI",   "Gauge32",            "IRTF-NMRG-SMING", "Gauge32",
70     "SNMPv2-SMI",   "mib-2",              "IRTF-NMRG-SMING-SNMP", "mib-2",
71
72     "SNMPv2-TC",   "TimeStamp",           "IRTF-NMRG-SMING", "TimeStamp",
73     "SNMPv2-TC",   "TimeInterval",        "IRTF-NMRG-SMING", "TimeInterval",
74     "SNMPv2-TC",   "DateAndTime",         "IRTF-NMRG-SMING", "DateAndTime",
75     "SNMPv2-TC",   "TruthValue",          "IRTF-NMRG-SMING", "TruthValue",
76     "SNMPv2-TC",   "PhysAddress",         "IRTF-NMRG-SMING", "PhysAddress",
77     "SNMPv2-TC",   "MacAddress",          "IRTF-NMRG-SMING", "MacAddress",
78     "SNMPv2-TC",   "DisplayString",       "IRTF-NMRG-SMING", "DisplayString255",
79     "SNMPv2-TC",   "TestAndIncr",         "IRTF-NMRG-SMING-SNMP", "TestAndIncr",
80     "SNMPv2-TC",   "AutonomousType",      "IRTF-NMRG-SMING-SNMP", "AutonomousType",
81     "SNMPv2-TC",   "VariablePointer",     "IRTF-NMRG-SMING-SNMP", "VariablePointer",
82     "SNMPv2-TC",   "RowPointer",          "IRTF-NMRG-SMING-SNMP", "RowPointer",
83     "SNMPv2-TC",   "RowStatus",           "IRTF-NMRG-SMING-SNMP", "RowStatus",
84     "SNMPv2-TC",   "StorageType",         "IRTF-NMRG-SMING-SNMP", "StorageType",
85     "SNMPv2-TC",   "TDomain",             "IRTF-NMRG-SMING-SNMP", "TDomain",
86     "SNMPv2-TC",   "TAddress",            "IRTF-NMRG-SMING-SNMP", "TAddress",
87     "SNMPv2-SMI",   NULL,                 "IRTF-NMRG-SMING", NULL,
88     "SNMPv2-TC",    "TEXTUAL-CONVENTION", NULL, NULL,
89     "SNMPv2-TC",    NULL,                 "IRTF-NMRG-SMING-TYPES", NULL,
90     "SNMPv2-CONF",  "OBJECT-GROUP",       NULL, NULL,
91     "SNMPv2-CONF",  "NOTIFICATION-GROUP", NULL, NULL,
92     "SNMPv2-CONF",  "MODULE-COMPLIANCE",  NULL, NULL,
93     "SNMPv2-CONF",  "AGENT-CAPABILITIES", NULL, NULL,
94  
95     "RFC1155-SMI",  "OBJECT-TYPE",        NULL, NULL,
96     "RFC1155-SMI",  "ObjectName",         NULL, NULL,
97     "RFC1155-SMI",  "ObjectSyntax",       NULL, NULL,
98     "RFC1155-SMI",  "SimpleSyntax",       NULL, NULL,
99     "RFC1155-SMI",  "ApplicationSyntax",  NULL, NULL,
100     "RFC1155-SMI",  "Gauge",              "IRTF-NMRG-SMING-TYPES", "Gauge32",
101     "RFC1155-SMI",  "Counter",            "IRTF-NMRG-SMING-TYPES", "Counter32",
102     "RFC1155-SMI",  "TimeTicks",          "IRTF-NMRG-SMING-TYPES", "TimeTicks",
103     "RFC1155-SMI",  "IpAddress",          "IRTF-NMRG-SMING-TYPES", "IpAddress",
104     "RFC1155-SMI",  "NetworkAddress",     NULL, NULL, /* ??? */
105     "RFC1155-SMI",  "Opaque",             "IRTF-NMRG-SMING", "Opaque",
106     "RFC1155-SMI",  NULL,                 "IRTF-NMRG-SMING", NULL,
107     "RFC1158-MIB",  "DisplayString",      "IRTF-NMRG-SMING", "DisplayString255",
108     "RFC-1212",     "OBJECT-TYPE",        NULL, NULL,
109     "RFC1213-MIB",  "mib-2",              "IRTF-NMRG-SMING-SNMP", "mib-2",
110     "RFC1213-MIB",  "system",             "SNMPv2-MIB", "system",
111     "RFC1213-MIB",  "interfaces",         "IF-MIB", "interfaces",
112 /*  "RFC1213-MIB",  "at",                 "RFC1213-MIB", "at", */
113     "RFC1213-MIB",  "ip",                 "IP-MIB", "ip",
114     "RFC1213-MIB",  "icmp",               "IP-MIB", "icmp",
115     "RFC1213-MIB",  "tcp",                "TCP-MIB", "tcp",
116     "RFC1213-MIB",  "udp",                "UDP-MIB", "udp",
117 /*  "RFC1213-MIB",  "egp",                "RFC1213-MIB", "egp", */
118     "RFC1213-MIB",  "transmission",       "SNMPv2-SMI", "transmission",
119     "RFC1213-MIB",  "snmp",               "SNMPv2-MIB", "snmp",
120     "RFC1213-MIB",  "sysDescr",           "SNMPv2-MIB", "sysDescr",
121     "RFC1213-MIB",  "sysObjectID",        "SNMPv2-MIB", "sysObjectID",
122     "RFC1213-MIB",  "sysUpTime",          "SNMPv2-MIB", "sysUpTime",
123     "RFC1213-MIB",  "ifIndex",            "IF-MIB", "ifIndex",
124 /* TODO ...many more objects from RFC1213-MIB.. */    
125     "RFC1213-MIB",  "DisplayString",      "IRTF-NMRG-SMING", "DisplayString255",
126     "RFC1213-MIB",  "PhysAddress",        "IRTF-NMRG-SMING", "PhysAddress",
127     "RFC-1215",     "TRAP-TYPE",          NULL, NULL,                          
128
129
130
131     
132     /* TODO: how to convert more SMIv1 information? */
133
134     NULL, NULL, NULL, NULL };
135
136 static int current_column = 0;
137 static int silent = 0;
138
139
140 /*
141  * Structure used to build a list of imported types.
142  */
143
144
145 typedef struct Import {
146     char          *module;
147     char          *name;
148     struct Import *nextPtr;
149 } Import;
150
151 static Import *importList = NULL;
152
153
154
155 static char *getStringStatus(SmiStatus status)
156 {
157     return
158         (status == SMI_STATUS_CURRENT)     ? "current" :
159         (status == SMI_STATUS_DEPRECATED)  ? "deprecated" :
160         (status == SMI_STATUS_OBSOLETE)    ? "obsolete" :
161         (status == SMI_STATUS_MANDATORY)   ? "current" :
162         (status == SMI_STATUS_OPTIONAL)    ? "current" :
163                                              "<unknown>";
164 }
165
166
167
168 static char *getAccessString(SmiAccess access)
169 {
170     return
171         (access == SMI_ACCESS_NOT_ACCESSIBLE) ? "noaccess" :
172         (access == SMI_ACCESS_NOTIFY)         ? "notifyonly" :
173         (access == SMI_ACCESS_READ_ONLY)      ? "readonly" :
174         (access == SMI_ACCESS_READ_WRITE)     ? "readwrite" :
175                                                 "<unknown>";
176 }
177
178
179
180 static char *getStringBasetype(SmiBasetype basetype)
181 {
182     return
183         (basetype == SMI_BASETYPE_UNKNOWN)           ? "<unknown>" :
184         (basetype == SMI_BASETYPE_OCTETSTRING)       ? "OctetString" :
185         (basetype == SMI_BASETYPE_OBJECTIDENTIFIER)  ? "ObjectIdentifier" :
186         (basetype == SMI_BASETYPE_UNSIGNED32)        ? "Unsigned32" :
187         (basetype == SMI_BASETYPE_INTEGER32)         ? "Integer32" :
188         (basetype == SMI_BASETYPE_UNSIGNED64)        ? "Unsigned64" :
189         (basetype == SMI_BASETYPE_INTEGER64)         ? "Integer64" :
190         (basetype == SMI_BASETYPE_FLOAT32)           ? "Float32" :
191         (basetype == SMI_BASETYPE_FLOAT64)           ? "Float64" :
192         (basetype == SMI_BASETYPE_FLOAT128)          ? "Float128" :
193         (basetype == SMI_BASETYPE_ENUM)              ? "Enumeration" :
194         (basetype == SMI_BASETYPE_BITS)              ? "Bits" :
195                                                    "<unknown>";
196 }
197
198
199
200 static char *getStringTime(time_t t)
201 {
202     static char   s[27];
203     struct tm     *tm;
204
205     tm = gmtime(&t);
206     sprintf(s, "%04d-%02d-%02d %02d:%02d",
207             tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
208             tm->tm_hour, tm->tm_min);
209     return s;
210 }
211
212
213
214 static char *getTypeString(SmiBasetype basetype, SmiType *smiType)
215 {
216     int         i;
217     char        *typeModule, *typeName;
218
219     typeName = smiType ? smiType->name : NULL;
220     typeModule = smiType ? smiGetTypeModule(smiType)->name : NULL;
221     
222     if ((!typeModule) && (typeName) &&
223         (basetype != SMI_BASETYPE_ENUM) &&
224         (basetype != SMI_BASETYPE_BITS)) {
225         for(i=0; convertType[i]; i += 2) {
226             if (!strcmp(typeName, convertType[i])) {
227                 return convertType[i+1];
228             }
229         }
230     }
231
232     if ((!typeModule) || (!strlen(typeModule)) || (!typeName)) {
233         if (basetype == SMI_BASETYPE_ENUM) {
234             return "Enumeration";
235         }
236         if (basetype == SMI_BASETYPE_BITS) {
237             return "Bits";
238         }
239     }
240         
241     if (!typeName) {
242         return getStringBasetype(basetype);
243     }
244     
245     /* TODO: fully qualified if unambigous */
246
247     return typeName;
248 }
249
250
251
252 static char *getOidString(SmiNode *smiNode, int importedParent)
253 {
254     SmiNode      *parentNode;
255     SmiModule    *smiModule;
256     static char  s[200];
257     char         append[200];
258     unsigned int i;
259     
260     append[0] = 0;
261
262     parentNode = smiNode;
263     smiModule = smiGetNodeModule(smiNode);
264     
265     do {
266
267         if (parentNode->oidlen <= 1) {
268             break;
269         }
270         
271         /* prepend the cut-off subidentifier to `append'. */
272         strcpy(s, append);
273         sprintf(append, ".%u%s", parentNode->oid[parentNode->oidlen-1], s);
274
275         /* retrieve the parent SmiNode */
276         parentNode = smiGetParentNode(parentNode);
277
278         if (!parentNode) {
279             sprintf(s, "%s", append);
280             return s;
281         }
282
283         /* found an imported or a local parent node? */
284         if ((parentNode->name && strlen(parentNode->name)) &&
285             (smiIsImported(smiModule, NULL, parentNode->name) ||
286              (!importedParent &&
287               (smiGetNodeModule(parentNode) == smiModule)) ||
288              (parentNode->oidlen == 1))) {
289             sprintf(s, "%s%s", parentNode->name, append);
290             return s;
291         }
292         
293     } while (parentNode);
294
295     s[0] = 0;
296     for (i=0; i < smiNode->oidlen; i++) {
297         if (i) strcat(s, ".");
298         sprintf(&s[strlen(s)], "%u", smiNode->oid[i]);
299     }
300     return s;
301 }
302
303
304
305 static Import* addImport(char *module, char *name)
306 {
307     Import **import, *newImport;
308     int i;
309     
310     for (i = 0; convertImport[i]; i += 4) {
311         if (convertImport[i] && convertImport[i+1]
312             && !strcmp(module, convertImport[i])
313             && !strcmp(name, convertImport[i+1])) {
314             module = convertImport[i+2];
315             name = convertImport[i+3];
316             break;
317         } else if (convertImport[i] && !convertImport[i+1]
318                    && !strcmp(module, convertImport[i])) {
319             module = convertImport[i+2];
320             break;
321         }
322     }
323
324     if (!module || !name) {
325         return NULL;
326     }
327             
328     for (import = &importList; *import; import = &(*import)->nextPtr) {
329         int c = strcmp((*import)->module, module);
330         if (c < 0) continue;
331         if (c == 0) {
332             int d = strcmp((*import)->name, name);
333             if (d < 0) continue;
334             if (d == 0) return *import;
335             if (d > 0) break;
336         }
337         if (c > 0) break;
338     }
339
340     newImport = xmalloc(sizeof(Import));
341     newImport->module = module;
342     newImport->name = name;
343     newImport->nextPtr = *import;
344     *import = newImport;
345         
346     return *import;
347 }
348
349
350
351 static void createImportList(SmiModule *smiModule)
352 {
353     SmiNode     *smiNode;
354     SmiType     *smiType;
355     SmiModule   *smiTypeModule;
356     SmiNodekind kind = SMI_NODEKIND_SCALAR | SMI_NODEKIND_COLUMN;
357     SmiImport   *smiImport;
358     
359     for (smiNode = smiGetFirstNode(smiModule, kind);
360          smiNode;
361          smiNode = smiGetNextNode(smiNode, kind)) {
362
363         smiType = smiGetNodeType(smiNode);
364         if (smiType && (smiType->decl == SMI_DECL_IMPLICIT_TYPE)) {
365             smiType = smiGetParentType(smiType);
366         }
367         if (smiType) {
368             smiTypeModule = smiGetTypeModule(smiType);
369             if (smiTypeModule &&
370                 strcmp(smiTypeModule->name, smiModule->name)) {
371                 if (strlen(smiTypeModule->name)) {
372                     addImport(smiTypeModule->name, smiType->name);
373                 }
374             }
375             if (smiType->basetype == SMI_BASETYPE_INTEGER32) {
376                 addImport("SNMPv2-SMI", "Integer32");
377             }
378         }
379     }
380
381     for (smiImport = smiGetFirstImport(smiModule); smiImport;
382          smiImport = smiGetNextImport(smiImport)) {
383         if (islower((int) smiImport->name[0]) ||
384             (smiImport->module && !strcmp(smiImport->module, "SNMPv2-SMI")) ||
385             (smiImport->module && !strcmp(smiImport->module, "SNMPv2-TC"))) {
386             addImport(smiImport->module, smiImport->name);
387         }
388     }
389 }
390
391
392
393 static void freeImportList(void)
394 {
395     Import *import, *freeme;
396
397     for (import = importList; import; ) {
398         freeme = import;
399         import = import->nextPtr;
400         xfree(freeme);
401     }
402     importList = NULL;
403 }
404
405
406
407 static void fprint(FILE *f, char *fmt, ...)
408 {
409     va_list ap;
410     char    s[200];
411     char    *p;
412     
413     va_start(ap, fmt);
414 #ifdef HAVE_VSNPRINTF
415     current_column += vsnprintf(s, sizeof(s), fmt, ap);
416 #else
417     current_column += vsprintf(s, fmt, ap);     /* buffer overwrite */
418 #endif
419     va_end(ap);
420
421     fputs(s, f);
422
423     if ((p = strrchr(s, '\n'))) {
424         current_column = strlen(p) - 1;
425     }
426 }
427
428
429
430 static void fprintSegment(FILE *f, int column, char *string, int length)
431 {
432     fprint(f, "%*c%s", column, ' ', string);
433     if (length) {
434         fprint(f, "%*c", length - strlen(string) - column, ' ');
435     }
436 }
437
438
439
440 static void fprintWrapped(FILE *f, int column, char *string)
441 {
442     if ((current_column + strlen(string)) > INDENTMAX) {
443         putc('\n', f);
444         current_column = 0;
445         fprintSegment(f, column, "", 0);
446     }
447     fprint(f, "%s", string);
448 }
449
450
451
452 static void fprintMultilineString(FILE *f, int column, const char *s)
453 {
454     int i, len;
455     
456     fprintSegment(f, column - 1 + INDENTTEXTS, "\"", 0);
457     if (s) {
458         len = strlen(s);
459         for (i=0; i < len; i++) {
460             putc(s[i], f);
461             current_column++;
462             if (s[i] == '\n') {
463                 current_column = 0;
464                 fprintSegment(f, column + INDENTTEXTS, "", 0);
465             }
466         }
467     }
468     putc('\"', f);
469     current_column++;
470 }
471
472
473
474 static char *getValueString(SmiValue *valuePtr, SmiType *typePtr)
475 {
476     static char    s[100];
477     char           ss[9];
478     int            n;
479     unsigned int   i;
480     SmiNamedNumber *nn;
481     
482     s[0] = 0;
483     
484     switch (valuePtr->basetype) {
485     case SMI_BASETYPE_UNSIGNED32:
486         sprintf(s, "%lu", valuePtr->value.unsigned32);
487         break;
488     case SMI_BASETYPE_INTEGER32:
489         sprintf(s, "%ld", valuePtr->value.integer32);
490         break;
491     case SMI_BASETYPE_UNSIGNED64:
492         sprintf(s, UINT64_FORMAT, valuePtr->value.unsigned64);
493         break;
494     case SMI_BASETYPE_INTEGER64:
495         sprintf(s, INT64_FORMAT, valuePtr->value.integer64);
496         break;
497     case SMI_BASETYPE_FLOAT32:
498     sprintf(s, "%G", valuePtr->value.float32);
499     break;
500     case SMI_BASETYPE_FLOAT64:
501     sprintf(s, "%lG", valuePtr->value.float64);
502     break;
503     case SMI_BASETYPE_FLOAT128:
504     sprintf(s, "%LG", valuePtr->value.float128);
505     break;
506         break;
507     case SMI_BASETYPE_ENUM:
508         for (nn = smiGetFirstNamedNumber(typePtr); nn;
509              nn = smiGetNextNamedNumber(nn)) {
510             if (nn->value.value.integer32 == valuePtr->value.integer32)
511                 break;
512         }
513         if (nn) {
514             sprintf(s, "%s", nn->name);
515         } else {
516             sprintf(s, "%ld", valuePtr->value.integer32);
517         }
518         break;
519     case SMI_BASETYPE_OCTETSTRING:
520         for (i = 0; i < valuePtr->len; i++) {
521             if (!isprint((int)valuePtr->value.ptr[i])) break;
522         }
523         if (i == valuePtr->len) {
524             sprintf(s, "\"%s\"", valuePtr->value.ptr);
525         } else {
526             sprintf(s, "0x%*s", 2 * valuePtr->len, "");
527             for (i=0; i < valuePtr->len; i++) {
528                 sprintf(ss, "%02x", valuePtr->value.ptr[i]);
529                 strncpy(&s[2+2*i], ss, 2);
530             }
531         }
532         break;
533     case SMI_BASETYPE_BITS:
534         sprintf(s, "(");
535         for (i = 0, n = 0; i < valuePtr->len * 8; i++) {
536             if (valuePtr->value.ptr[i/8] & (1 << (7-(i%8)))) {
537                 if (n)
538                     sprintf(&s[strlen(s)], ", ");
539                 n++;
540                 for (nn = smiGetFirstNamedNumber(typePtr); nn;
541                      nn = smiGetNextNamedNumber(nn)) {
542                     /* if (nn->value.value.unsigned64 == ((i/8)*8 + (7-(i%8)))) */
543                     if (nn->value.value.unsigned64 == i)
544                         break;
545                 }
546                 if (nn) {
547                     sprintf(&s[strlen(s)], "%s", nn->name);
548                 } else {
549                     sprintf(&s[strlen(s)], "%d", i);
550                 }
551             }
552         }
553         sprintf(&s[strlen(s)], ")");
554         break;
555     case SMI_BASETYPE_UNKNOWN:
556         break;
557     case SMI_BASETYPE_OBJECTIDENTIFIER:
558         /*nodePtr = smiGetNodeByOID(valuePtr->len, valuePtr->value.oid);
559         if (nodePtr) {
560             sprintf(s, "%s", nodePtr->name);
561         } else {
562             strcpy(s, "");
563             for (i=0; i < valuePtr->len; i++) {
564                 if (i) strcat(s, ".");
565                 sprintf(&s[strlen(s)], "%u", valuePtr->value.oid[i]);
566             }
567         }*/
568         sprintf(s, "%s", typePtr->value.value.ptr);
569         break;
570         case SMI_BASETYPE_POINTER:
571         /*nodePtr = smiGetNodeByOID(valuePtr->len, valuePtr->value.oid);
572         if (nodePtr) {
573             sprintf(s, "%s", nodePtr->name);
574         } else {
575             strcpy(s, "");
576             for (i=0; i < valuePtr->len; i++) {
577                 if (i) strcat(s, ".");
578                 sprintf(&s[strlen(s)], "%u", valuePtr->value.oid[i]);
579             }
580         }*/
581         sprintf(s, "%s", valuePtr->value.ptr);
582         break;
583         default:
584         sprintf(s, "%s", "");
585         break;
586     }
587
588     return s;
589 }
590
591
592
593 static void fprintSubtype(FILE *f, SmiType *smiType)
594 {
595     SmiRange       *range;
596     SmiNamedNumber *nn;
597     char           s[100];
598     int            i;
599
600     if ((smiType->basetype == SMI_BASETYPE_ENUM) ||
601         (smiType->basetype == SMI_BASETYPE_BITS)) {
602         for(i = 0, nn = smiGetFirstNamedNumber(smiType);
603             nn ; i++, nn = smiGetNextNamedNumber(nn)) {
604             if (i) {
605                 fprint(f, ", ");
606             } else {
607                 fprint(f, " (");
608             }
609             sprintf(s, "%s(%s)", nn->name,
610                     getValueString(&nn->value, smiType));
611             fprintWrapped(f, INDENTVALUE + INDENT, s);
612         }
613         if (i) {
614             fprint(f, ")");
615         }
616         } else if(smiType->basetype == SMI_BASETYPE_POINTER) {
617                 nn = smiGetFirstNamedNumber(smiType);
618                 if(nn)
619                         fprint(f, " (%s)",nn->name);
620     } else {
621         for(i = 0, range = smiGetFirstRange(smiType);
622             range ; i++, range = smiGetNextRange(range)) {
623             if (i) {
624                 fprint(f, " | ");
625             } else {
626                 fprint(f, " (");
627             }       
628             if (memcmp(&range->minValue, &range->maxValue,
629                        sizeof(SmiValue))) {
630                 sprintf(s, "%s", getValueString(&range->minValue, smiType));
631                 sprintf(&s[strlen(s)], "..%s", 
632                         getValueString(&range->maxValue, smiType));
633             } else {
634                 sprintf(s, "%s", getValueString(&range->minValue, smiType));
635             }
636             fprintWrapped(f, INDENTVALUE + INDENT, s);
637         }
638         if (i) {
639             fprint(f, ")");
640         }
641     }
642 }
643
644 static void fprintAttributeSubtype(FILE *f, SmiAttribute *smiAttribute)
645 {
646     SmiRange       *range;
647     SmiNamedNumber *nn;
648     char           s[100];
649     int            i;
650
651     if ((smiAttribute->basetype == SMI_BASETYPE_ENUM) ||
652         (smiAttribute->basetype == SMI_BASETYPE_BITS)) {
653         for(i = 0, nn = smiGetAttributeFirstNamedNumber(smiAttribute);
654             nn ; i++, nn = smiGetAttributeNextNamedNumber(nn)) {
655             if (i) {
656                 fprint(f, ", ");
657             } else {
658                 fprint(f, " (");
659             }
660             sprintf(s, "%s(%s)", nn->name,
661                     getValueString(&nn->value, smiGetAttributeParentType(smiAttribute)));
662             fprintWrapped(f, INDENTVALUE + INDENT, s);
663         }
664         if (i) {
665             fprint(f, ")");
666         }
667         } else if(smiAttribute->basetype == SMI_BASETYPE_POINTER) {
668                 nn = smiGetAttributeFirstNamedNumber(smiAttribute);
669                 if(nn)
670                         fprint(f, " (%s)",nn->name);
671     } else {
672         for(i = 0, range = smiGetAttributeFirstRange(smiAttribute);
673             range ; i++, range = smiGetAttributeNextRange(range)) {
674             if (i) {
675                 fprint(f, " | ");
676             } else {
677                 fprint(f, " (");
678             }       
679             if (memcmp(&range->minValue, &range->maxValue,
680                        sizeof(SmiValue))) {
681                 sprintf(s, "%s", getValueString(&range->minValue, smiGetAttributeParentType(smiAttribute)));
682                 sprintf(&s[strlen(s)], "..%s", 
683                         getValueString(&range->maxValue, smiGetAttributeParentType(smiAttribute)));
684             } else {
685                 sprintf(s, "%s", getValueString(&range->minValue, smiGetAttributeParentType(smiAttribute)));
686             }
687             fprintWrapped(f, INDENTVALUE + INDENT, s);
688         }
689         if (i) {
690             fprint(f, ")");
691         }
692     }
693 }
694
695
696
697 static void fprintImports(FILE *f, SmiModule *smiModule)
698 {
699     SmiImport *import;
700     char   *lastModuleName = NULL;
701     int    pos = 0, len, maxlen = 0;
702
703     createImportList(smiModule);
704
705     for (import = smiGetFirstImport(smiModule); import; import = smiGetNextImport(import)) {
706         len = strlen(import->module);
707         maxlen = (len > maxlen) ? len : maxlen;
708     }
709
710     for (import = smiGetFirstImport(smiModule); import; import = smiGetNextImport(import)) {
711         int yaba = !lastModuleName || strcmp(import->module, lastModuleName);
712         if (yaba) {
713             if (lastModuleName) {
714                 fprint(f, ");\n");
715             }
716             fprintSegment(f, INDENT, "", 0);
717             fprint(f, "import %-*s (", maxlen, import->module);
718             pos = INDENT + 12 + maxlen;
719         } else {
720             fprint(f, ", ");
721         }
722         len = strlen(import->name);
723         if (len + pos > INDENTMAX) {
724             fprint(f, "\n");
725             fprintSegment(f, INDENT, "", 0);
726             fprintSegment(f, INDENT, "", 0);
727             fprint(f, "     %-*s  ", maxlen, "");
728             pos = INDENT + 12 + maxlen;
729         }
730         fprint(f, "%s", import->name);
731         pos += len;
732         lastModuleName = import->module;
733     }
734
735     if (lastModuleName) {
736         fprintf(f, ");\n");
737     }
738
739     fprint(f, "\n");
740
741     freeImportList();
742 }
743
744
745
746
747 static void fprintRevisions(FILE *f, SmiModule *smiModule)
748 {
749     int i;
750     SmiRevision *smiRevision;
751     
752     for(i = 0, smiRevision = smiGetFirstRevision(smiModule);
753         smiRevision; smiRevision = smiGetNextRevision(smiRevision)) {
754         fprintSegment(f, INDENT, "revision {\n", 0);
755         fprintSegment(f, 2 * INDENT, "date", INDENTVALUE);
756         fprint(f, "\"%s\";\n", getStringTime(smiRevision->date));
757         fprintSegment(f, 2 * INDENT, "description", INDENTVALUE);
758         fprint(f, "\n");
759         fprintMultilineString(f, 2 * INDENT, smiRevision->description);
760         fprint(f, ";\n");
761         fprintSegment(f, INDENT, "};\n", 0);
762         i++;
763     }
764     if (i) {
765         fprint(f, "\n");
766     }
767 }
768
769
770
771 static void fprintTypedefs(FILE *f, SmiModule *smiModule)
772 {
773     int          i, j;
774     SmiType      *smiType;
775     
776     for(i = 0, smiType = smiGetFirstType(smiModule);
777         smiType; smiType = smiGetNextType(smiType)) {
778         
779         if ((!(strcmp(smiModule->name, "SNMPv2-SMI"))) ||
780             (!(strcmp(smiModule->name, "RFC1155-SMI")))) {
781             for(j=0; excludeType[j]; j++) {
782                 if (!strcmp(smiType->name, excludeType[j])) break;
783             }
784             if (excludeType[j]) break;
785         }
786             
787         if (!i && !silent) {
788             fprint(f, "//\n// TYPE DEFINITIONS\n//\n\n");
789         }
790         fprintSegment(f, INDENT, "", 0);
791         fprint(f, "typedef %s {\n", smiType->name);
792
793         fprintSegment(f, 2 * INDENT, "type", INDENTVALUE);
794         fprint(f, "%s", getTypeString(smiType->basetype,
795                                       smiGetParentType(smiType)));
796         fprintSubtype(f, smiType);
797         fprint(f, ";\n");
798
799         if (smiType->value.basetype != SMI_BASETYPE_UNKNOWN) {
800             fprintSegment(f, 2 * INDENT, "default", INDENTVALUE);
801             fprint(f, "%s", getValueString(&smiType->value, smiType));
802             fprint(f, ";\n");
803         }
804         
805         if (smiType->format) {
806             fprintSegment(f, 2 * INDENT, "format", INDENTVALUE);
807             fprint(f, "\"%s\";\n", smiType->format);
808         }
809         if (smiType->units) {
810             fprintSegment(f, 2 * INDENT, "units", INDENTVALUE);
811             fprint(f, "\"%s\";\n", smiType->units);
812         }
813         if ((smiType->status != SMI_STATUS_UNKNOWN) &&
814             (smiType->status != SMI_STATUS_MANDATORY) &&
815             (smiType->status != SMI_STATUS_OPTIONAL)) {
816             fprintSegment(f, 2 * INDENT, "status", INDENTVALUE);
817             fprint(f, "%s;\n", getStringStatus(smiType->status));
818         }
819         fprintSegment(f, 2 * INDENT, "description", INDENTVALUE);
820         fprint(f, "\n");
821         fprintMultilineString(f, 2 * INDENT, smiType->description);
822         fprint(f, ";\n");
823         if (smiType->reference) {
824             fprintSegment(f, 2 * INDENT, "reference", INDENTVALUE);
825             fprint(f, "\n");
826             fprintMultilineString(f, 2 * INDENT, smiType->reference);
827             fprint(f, ";\n");
828         }
829         fprintSegment(f, INDENT, "};\n\n", 0);
830         i++;
831     }
832 }
833
834 static void fprintIdentities(FILE *f, SmiModule *smiModule)
835 {
836     int          i;
837     SmiIdentity  *smiIdentity;
838     SmiIdentity  *tmpIdentity;
839     
840     for(i = 0, smiIdentity = smiGetFirstIdentity(smiModule);
841         smiIdentity; smiIdentity = smiGetNextIdentity(smiIdentity)) {
842             
843         if (!i && !silent) {
844             fprint(f, "//\n// IDENTITY DEFINITIONS\n//\n\n");
845         }
846         fprintSegment(f, INDENT, "", 0);
847         fprint(f, "identity %s {\n", smiIdentity->name);
848
849         tmpIdentity = smiGetParentIdentity(smiIdentity);
850         if (tmpIdentity) {
851             fprintSegment(f, 2 * INDENT, "parent", INDENTVALUE);
852             fprint(f, "%s", tmpIdentity->name);
853             fprint(f, ";\n");
854         }
855
856         if ((smiIdentity->status != SMI_STATUS_UNKNOWN) &&
857             (smiIdentity->status != SMI_STATUS_MANDATORY) &&
858             (smiIdentity->status != SMI_STATUS_OPTIONAL)) {
859             fprintSegment(f, 2 * INDENT, "status", INDENTVALUE);
860             fprint(f, "%s;\n", getStringStatus(smiIdentity->status));
861         }
862         fprintSegment(f, 2 * INDENT, "description", INDENTVALUE);
863         fprint(f, "\n");
864         fprintMultilineString(f, 2 * INDENT, smiIdentity->description);
865         fprint(f, ";\n");
866         if (smiIdentity->reference) {
867             fprintSegment(f, 2 * INDENT, "reference", INDENTVALUE);
868             fprint(f, "\n");
869             fprintMultilineString(f, 2 * INDENT, smiIdentity->reference);
870             fprint(f, ";\n");
871         }
872         fprintSegment(f, INDENT, "};\n\n", 0);
873         i++;
874     }
875 }
876
877 static void fprintExtensions(FILE *f, SmiModule *smiModule)
878 {
879     int          i;
880     SmiMacro     *smiMacro;
881     
882     for(i = 0, smiMacro = smiGetFirstMacro(smiModule);
883         smiMacro; smiMacro = smiGetNextMacro(smiMacro)) {
884             
885         if (!i && !silent) {
886             fprint(f, "//\n// EXTENSION DEFINITIONS\n//\n\n");
887         }
888         fprintSegment(f, INDENT, "", 0);
889         fprint(f, "extension %s {\n", smiMacro->name);
890         
891         if ((smiMacro->status != SMI_STATUS_UNKNOWN) &&
892             (smiMacro->status != SMI_STATUS_MANDATORY) &&
893             (smiMacro->status != SMI_STATUS_OPTIONAL)) {
894             fprintSegment(f, 2 * INDENT, "status", INDENTVALUE);
895             fprint(f, "%s;\n", getStringStatus(smiMacro->status));
896         }
897         fprintSegment(f, 2 * INDENT, "description", INDENTVALUE);
898         fprint(f, "\n");
899         fprintMultilineString(f, 2 * INDENT, smiMacro->description);
900         fprint(f, ";\n");
901         if (smiMacro->reference) {
902             fprintSegment(f, 2 * INDENT, "reference", INDENTVALUE);
903             fprint(f, "\n");
904             fprintMultilineString(f, 2 * INDENT, smiMacro->reference);
905             fprint(f, ";\n");
906         }
907         
908         if(smiMacro->abnf) {
909                 fprintSegment(f, 2 * INDENT, "abnf", INDENTVALUE);
910             fprint(f, "\n");
911             fprintMultilineString(f, 2 * INDENT, smiMacro->abnf);
912             fprint(f, ";\n");
913         }
914         fprintSegment(f, INDENT, "};\n\n", 0);
915         i++;
916     }
917 }
918
919 static void fprintUniqueStatement(FILE *f, SmiClass *smiClass)
920 {
921     SmiAttribute *attributePtr;
922     int i;
923     
924     if(smiIsClassScalar(smiClass))
925     {
926         fprintSegment(f, 2 * INDENT, "unique", INDENTVALUE);
927             fprint(f, "();\n");
928         }
929     
930     attributePtr = smiGetFirstUniqueAttribute(smiClass);
931     if (attributePtr) {
932         fprintSegment(f, 2 * INDENT, "unique", INDENTVALUE);
933         fprint(f, "(");
934         for (i=0; attributePtr; 
935              attributePtr = smiGetNextUniqueAttribute(attributePtr))
936         {
937             if (i) {
938                 fprint(f, ", %s",attributePtr->name);
939             } else {
940                 fprint(f, "%s",attributePtr->name);
941             }
942             i++;
943         }
944         fprint(f, ");\n\n");
945     }
946 }
947 static void fprintAttributes(FILE *f, SmiClass *smiClass)
948 {
949     int          i;
950     SmiAttribute *smiAttribute;
951     SmiType      *tmpType;
952     SmiClass *tmpClass;
953     
954     for (i = 0, smiAttribute = smiGetFirstAttribute(smiClass);
955          smiAttribute; smiAttribute = smiGetNextAttribute(smiAttribute)) {
956
957         fprintSegment(f, 2*INDENT, "", 0);
958         fprint(f, "attribute %s {\n", smiAttribute->name);
959         
960         tmpType = smiGetAttributeParentType(smiAttribute);
961         if (tmpType) {
962             fprintSegment(f, 3 * INDENT, "type", INDENTVALUE);
963             fprint(f, "%s ", tmpType->name);
964             fprintAttributeSubtype(f, smiAttribute);
965             fprint(f, ";\n");
966             fprintSegment(f, 3 * INDENT, "access", INDENTVALUE);
967             switch (smiAttribute->access) {
968             case SMI_ACCESS_READ_ONLY:
969                 fprint(f, "readonly;\n");
970                 break;
971             case SMI_ACCESS_READ_WRITE:
972                 fprint(f, "readwrite;\n");
973                 break;
974             case SMI_ACCESS_EVENT_ONLY:
975                 fprint(f, "eventonly;\n");
976                 break;
977             default:
978                 fprint(f, ";\n");
979                 break;  
980             }
981             
982             if (smiAttribute->value.basetype != SMI_BASETYPE_UNKNOWN) {
983                 fprintSegment(f, 3 * INDENT, "default", INDENTVALUE);
984                 fprint(f, "%s", getValueString(&smiAttribute->value, smiGetAttributeParentType(smiAttribute)));
985                 fprint(f, ";\n");
986             }
987             
988             if (smiAttribute->format) {
989                 fprintSegment(f, 3 * INDENT, "format", INDENTVALUE);
990                 fprint(f, "\"%s\";\n", smiAttribute->format);
991             }
992             if (smiAttribute->units) {
993                 fprintSegment(f, 3 * INDENT, "units", INDENTVALUE);
994                 fprint(f, "\"%s\";\n", smiAttribute->units);
995             }           
996         }
997         
998         tmpClass = smiGetAttributeParentClass(smiAttribute);
999         if (tmpClass) {
1000             fprintSegment(f, 3 * INDENT, "type", INDENTVALUE);
1001             fprint(f, "%s;\n", tmpClass->name);
1002         }
1003         
1004         if ((smiAttribute->status != SMI_STATUS_UNKNOWN) &&
1005             (smiAttribute->status != SMI_STATUS_MANDATORY) &&
1006             (smiAttribute->status != SMI_STATUS_OPTIONAL)) {
1007             fprintSegment(f, 3 * INDENT, "status", INDENTVALUE);
1008             fprint(f, "%s;\n", getStringStatus(smiAttribute->status));
1009         }
1010         fprintSegment(f, 3 * INDENT, "description", INDENTVALUE);
1011         fprint(f, "\n");
1012         fprintMultilineString(f, 3 * INDENT, smiAttribute->description);
1013         fprint(f, ";\n");
1014         if (smiAttribute->reference) {
1015             fprintSegment(f, 3 * INDENT, "reference", INDENTVALUE);
1016             fprint(f, "\n");
1017             fprintMultilineString(f, 3 * INDENT, smiAttribute->reference);
1018             fprint(f, ";\n");
1019         }
1020         
1021         fprintSegment(f, 2*INDENT, "};\n\n", 0);
1022         i++;
1023     }
1024 }
1025
1026 static void fprintEvents(FILE *f, SmiClass *smiClass)
1027 {
1028     int          i;
1029     SmiEvent *smiEvent;
1030     
1031     for(i = 0, smiEvent = smiGetFirstEvent(smiClass);
1032         smiEvent; smiEvent = smiGetNextEvent(smiEvent)) {
1033         /*    
1034         if (!i && !silent) {
1035                 fprint(f,"\n");
1036                 fprintSegment(f, 2 * INDENT, "// ATTRIBUTE DEFINITIONS\n\n",0);
1037         }*/
1038         fprintSegment(f, 2*INDENT, "", 0);
1039         fprint(f, "event %s {\n", smiEvent->name);
1040         
1041         if ((smiEvent->status != SMI_STATUS_UNKNOWN) &&
1042             (smiEvent->status != SMI_STATUS_MANDATORY) &&
1043             (smiEvent->status != SMI_STATUS_OPTIONAL)) {
1044             fprintSegment(f, 3 * INDENT, "status", INDENTVALUE);
1045             fprint(f, "%s;\n", getStringStatus(smiEvent->status));
1046         }
1047         fprintSegment(f, 3 * INDENT, "description", INDENTVALUE);
1048         fprint(f, "\n");
1049         fprintMultilineString(f, 3 * INDENT, smiEvent->description);
1050         fprint(f, ";\n");
1051         if (smiEvent->reference) {
1052             fprintSegment(f, 3 * INDENT, "reference", INDENTVALUE);
1053             fprint(f, "\n");
1054             fprintMultilineString(f, 3 * INDENT, smiEvent->reference);
1055             fprint(f, ";\n");
1056         }
1057         
1058         fprintSegment(f, 2*INDENT, "};\n\n", 0);
1059         i++;
1060     }
1061 }
1062
1063 static void fprintClasses(FILE *f, SmiModule *smiModule)
1064 {
1065     int          i;
1066     SmiClass     *smiClass;
1067     SmiClass     *tmpClass;
1068     
1069     for (i = 0, smiClass = smiGetFirstClass(smiModule);
1070          smiClass; smiClass = smiGetNextClass(smiClass)) {
1071             
1072         if (!i && !silent) {
1073             fprint(f, "//\n// CLASS DEFINITIONS\n//\n\n");
1074         }
1075         fprintSegment(f, INDENT, "", 0);
1076         fprint(f, "class %s {\n", smiClass->name);
1077
1078         tmpClass = smiGetParentClass(smiClass);
1079         if (tmpClass) {
1080             fprintSegment(f, 2 * INDENT, "extends", INDENTVALUE);
1081             fprint(f, "%s;\n\n", tmpClass->name);
1082         }
1083         
1084         fprintAttributes(f,smiClass);
1085         
1086         fprintUniqueStatement(f,smiClass);
1087         
1088         fprintEvents(f,smiClass);
1089         
1090         if ((smiClass->status != SMI_STATUS_UNKNOWN) &&
1091             (smiClass->status != SMI_STATUS_MANDATORY) &&
1092             (smiClass->status != SMI_STATUS_OPTIONAL)) {
1093             fprintSegment(f, 2 * INDENT, "status", INDENTVALUE);
1094             fprint(f, "%s;\n", getStringStatus(smiClass->status));
1095         }
1096         fprintSegment(f, 2 * INDENT, "description", INDENTVALUE);
1097         fprint(f, "\n");
1098         fprintMultilineString(f, 2 * INDENT, smiClass->description);
1099         fprint(f, ";\n");
1100         if (smiClass->reference) {
1101             fprintSegment(f, 2 * INDENT, "reference", INDENTVALUE);
1102             fprint(f, "\n");
1103             fprintMultilineString(f, 2 * INDENT, smiClass->reference);
1104             fprint(f, ";\n");
1105         }
1106         
1107         fprintSegment(f, INDENT, "};\n\n", 0);
1108         i++;
1109     }
1110 }
1111
1112 static void fprintObjects(FILE *f, SmiModule *smiModule)
1113 {
1114     int          i, j;
1115     SmiNode      *smiNode, *relatedNode;
1116     SmiElement   *smiElement;
1117     SmiType      *smiType;
1118     int          indent = 0;
1119     int          lastindent = -1;
1120     char         *s = NULL;
1121     SmiNodekind  nodekinds;
1122
1123     nodekinds =  SMI_NODEKIND_NODE | SMI_NODEKIND_TABLE |
1124         SMI_NODEKIND_ROW | SMI_NODEKIND_COLUMN | SMI_NODEKIND_SCALAR |
1125         SMI_NODEKIND_CAPABILITIES;
1126     
1127     for(i = 0, smiNode = smiGetFirstNode(smiModule, nodekinds);
1128         smiNode; smiNode = smiGetNextNode(smiNode, nodekinds)) {
1129
1130         if (smiNode->nodekind == SMI_NODEKIND_NODE) {
1131             indent = 0;
1132             s = "node";
1133         } else if (smiNode->nodekind == SMI_NODEKIND_CAPABILITIES) {
1134             indent = 0;
1135             s = "node";
1136         } else if (smiNode->nodekind == SMI_NODEKIND_TABLE) {
1137             indent = 0;
1138             s = "table";
1139         } else if (smiNode->nodekind == SMI_NODEKIND_ROW) {
1140             indent = 1;
1141             s = "row";
1142         } else if (smiNode->nodekind == SMI_NODEKIND_COLUMN) {
1143             indent = 2;
1144             s = "column";
1145         } else if (smiNode->nodekind == SMI_NODEKIND_SCALAR) {
1146             indent = 0;
1147             s = "scalar";
1148         }
1149
1150         if (!i && !silent) {
1151             fprint(f, "//\n// OBJECT DEFINITIONS\n//\n\n");
1152         }
1153
1154         for (j = lastindent; j >= indent; j--) {
1155             fprintSegment(f, (1 + j) * INDENT, "", 0);
1156             fprint(f, "};\n");
1157         }
1158         fprint(f, "\n");
1159         lastindent = indent;
1160         
1161         if (smiNode->nodekind == SMI_NODEKIND_CAPABILITIES) {
1162             fprintSegment(f, (1 + indent) * INDENT, "", 0);
1163             fprint(f, "-- This has been an SMIv2 AGENT-CAPABILITIES node:\n");
1164         }
1165         
1166         fprintSegment(f, (1 + indent) * INDENT, "", 0);
1167         fprint(f, "%s %s {\n", s, smiNode->name);
1168         
1169         if (smiNode->oid) {
1170             fprintSegment(f, (2 + indent) * INDENT, "oid", INDENTVALUE);
1171             fprint(f, "%s;\n", getOidString(smiNode, 0));
1172         }
1173
1174         smiType = smiGetNodeType(smiNode);
1175         if (smiType && (smiType->basetype != SMI_BASETYPE_UNKNOWN)) {
1176             fprintSegment(f, (2 + indent) * INDENT, "type", INDENTVALUE);
1177             if (!smiType->name) {
1178                 /*
1179                  * an implicitly restricted type.
1180                  */
1181                 fprint(f, "%s", getTypeString(smiType->basetype,
1182                                               smiGetParentType(smiType)));
1183                 fprintSubtype(f, smiType);
1184                 fprint(f, ";\n");
1185             } else {
1186                 fprint(f, "%s;\n",
1187                        getTypeString(smiType->basetype, smiType));
1188             }
1189         }
1190
1191         if ((smiNode->nodekind != SMI_NODEKIND_TABLE) &&
1192             (smiNode->nodekind != SMI_NODEKIND_ROW) &&
1193             (smiNode->nodekind != SMI_NODEKIND_CAPABILITIES) &&
1194             (smiNode->nodekind != SMI_NODEKIND_NODE)) {
1195             if (smiNode->access != SMI_ACCESS_UNKNOWN) {
1196                 fprintSegment(f, (2 + indent) * INDENT, "access", INDENTVALUE);
1197                 fprint(f, "%s;\n", getAccessString(smiNode->access));
1198             }
1199         }
1200
1201         relatedNode = smiGetRelatedNode(smiNode);
1202         switch (smiNode->indexkind) {
1203         case SMI_INDEX_INDEX:
1204             if (smiNode->implied) {
1205                 fprintSegment(f, (2 + indent) * INDENT, "index implied",
1206                               INDENTVALUE);
1207             } else {
1208                 fprintSegment(f, (2 + indent) * INDENT, "index", INDENTVALUE);
1209             }
1210             fprint(f, "(");
1211             for (j = 0, smiElement = smiGetFirstElement(smiNode); smiElement;
1212                  j++, smiElement = smiGetNextElement(smiElement)) {
1213                 if (j) {
1214                     fprint(f, ", ");
1215                 }
1216                 fprintWrapped(f, INDENTVALUE + 1,
1217                               smiGetElementNode(smiElement)->name);
1218                 /* TODO: non-local name if non-local */
1219             } /* TODO: empty? -> print error */
1220             fprint(f, ");\n");
1221             break;
1222         case SMI_INDEX_AUGMENT:
1223             if (relatedNode) {
1224                 fprintSegment(f, (2 + indent) * INDENT, "augments",
1225                               INDENTVALUE);
1226                 fprint(f, "%s;\n", relatedNode->name);
1227                 /* TODO: non-local name if non-local */
1228             } /* TODO: else print error */
1229             break;
1230         case SMI_INDEX_REORDER:
1231             if (relatedNode) {
1232                 fprintSegment(f, (2 + indent) * INDENT, "", 0);
1233                 fprint(f, "reorders %s", relatedNode->name);
1234                 /* TODO: non-local name if non-local */
1235                 if (smiNode->implied) {
1236                     fprint(f, " implied");
1237                 }
1238                 fprint(f, " (");
1239                 for (j = 0, smiElement = smiGetFirstElement(smiNode);
1240                      smiElement;
1241                      j++, smiElement = smiGetNextElement(smiElement)) {
1242                     if (j) {
1243                         fprint(f, ", ");
1244                     }
1245                     fprintWrapped(f, INDENTVALUE + 1,
1246                                   smiGetElementNode(smiElement)->name);
1247                     /* TODO: non-local name if non-local */
1248                 } /* TODO: empty? -> print error */
1249                 fprint(f, ");\n");
1250             } /* TODO: else print error */
1251             break;
1252         case SMI_INDEX_SPARSE:
1253             if (relatedNode) {
1254                 fprintSegment(f, (2 + indent) * INDENT, "sparse", INDENTVALUE);
1255                 fprint(f, "%s;\n", relatedNode->name);
1256                 /* TODO: non-local name if non-local */
1257             } /* TODO: else print error */
1258             break;
1259         case SMI_INDEX_EXPAND:
1260             if (relatedNode) {
1261                 fprintSegment(f, (2 + indent) * INDENT, "", 0);
1262                 fprint(f, "expands %s", relatedNode->name);
1263                 /* TODO: non-local name if non-local */
1264                 if (smiNode->implied) {
1265                     fprint(f, " implied");
1266                 }
1267                 fprint(f, " (");
1268                 for (j = 0, smiElement = smiGetFirstElement(smiNode);
1269                      smiElement;
1270                      j++, smiElement = smiGetNextElement(smiElement)) {
1271                     if (j) {
1272                         fprint(f, ", ");
1273                     }
1274                     fprintWrapped(f, INDENTVALUE + 1,
1275                                   smiGetElementNode(smiElement)->name);
1276                     /* TODO: non-local name if non-local */
1277                 } /* TODO: empty? -> print error */
1278                 fprint(f, ");\n");
1279             } /* TODO: else print error */
1280             break;
1281         case SMI_INDEX_UNKNOWN:
1282             break;
1283         }
1284         
1285         if (smiNode->create) {
1286             fprintSegment(f, (2 + indent) * INDENT, "create", INDENTVALUE);
1287             /* TODO: create list */
1288             fprint(f, ";\n");
1289         }
1290         
1291         if (smiNode->value.basetype != SMI_BASETYPE_UNKNOWN) {
1292             fprintSegment(f, (2 + indent) * INDENT, "default", INDENTVALUE);
1293             fprint(f, "%s", getValueString(&smiNode->value, smiType));
1294             fprint(f, ";\n");
1295         }
1296         
1297         if (smiNode->format) {
1298             fprintSegment(f, (2 + indent) * INDENT, "format", INDENTVALUE);
1299             fprint(f, "\"%s\";\n",smiNode->format);
1300         }
1301         if (smiNode->units) {
1302             fprintSegment(f, (2 + indent) * INDENT, "units", INDENTVALUE);
1303             fprint(f, "\"%s\";\n", smiNode->units);
1304         }
1305         if ((smiNode->status != SMI_STATUS_CURRENT) &&
1306             (smiNode->status != SMI_STATUS_UNKNOWN) &&
1307             (smiNode->status != SMI_STATUS_MANDATORY) &&
1308             (smiNode->status != SMI_STATUS_OPTIONAL)) {
1309             fprintSegment(f, (2 + indent) * INDENT, "status", INDENTVALUE);
1310             fprint(f, "%s;\n", getStringStatus(smiNode->status));
1311         }
1312         if (smiNode->description) {
1313             fprintSegment(f, (2 + indent) * INDENT, "description",
1314                           INDENTVALUE);
1315             fprint(f, "\n");
1316             fprintMultilineString(f, (2 + indent) * INDENT,
1317                                   smiNode->description);
1318             fprint(f, ";\n");
1319         }
1320         if (smiNode->reference) {
1321             fprintSegment(f, (2 + indent) * INDENT, "reference",
1322                           INDENTVALUE);
1323             fprint(f, "\n");
1324             fprintMultilineString(f, (2 + indent) * INDENT,
1325                                   smiNode->reference);
1326             fprint(f, ";\n");
1327         }
1328         i++;
1329     }
1330     
1331     if (i) {
1332         fprintSegment(f, (1 + indent) * INDENT, "", 0);
1333         fprint(f, "};\n\n");
1334     }
1335 }
1336
1337
1338
1339 static void fprintNotifications(FILE *f, SmiModule *smiModule)
1340 {
1341     int          i, j;
1342     SmiNode      *smiNode;
1343     SmiElement   *smiElement;
1344     
1345     for(i = 0, smiNode = smiGetFirstNode(smiModule,
1346                                          SMI_NODEKIND_NOTIFICATION);
1347         smiNode;
1348         smiNode = smiGetNextNode(smiNode, SMI_NODEKIND_NOTIFICATION)) {
1349
1350         if (!i && !silent) {
1351             fprint(f, "//\n// NOTIFICATION DEFINITIONS\n//\n\n");
1352         }
1353
1354         fprintSegment(f, INDENT, "", 0);
1355         fprint(f, "notification %s {\n", smiNode->name);
1356
1357         if (smiNode->oid) {
1358             fprintSegment(f, 2 * INDENT, "oid", INDENTVALUE);
1359             fprint(f, "%s;\n", getOidString(smiNode, 0));
1360         }
1361
1362         if ((smiElement = smiGetFirstElement(smiNode))) {
1363             fprintSegment(f, 2 * INDENT, "objects", INDENTVALUE);
1364             fprint(f, "(");
1365             for (j = 0; smiElement;
1366                  j++, smiElement = smiGetNextElement(smiElement)) {
1367                 if (j) {
1368                     fprint(f, ", ");
1369                 }
1370                 fprintWrapped(f, INDENTVALUE + 1,
1371                               smiGetElementNode(smiElement)->name);
1372                 /* TODO: non-local name if non-local */
1373             } /* TODO: empty? -> print error */
1374             fprint(f, ");\n");
1375         }
1376         
1377         if ((smiNode->status != SMI_STATUS_CURRENT) &&
1378             (smiNode->status != SMI_STATUS_UNKNOWN) &&
1379             (smiNode->status != SMI_STATUS_MANDATORY) &&
1380             (smiNode->status != SMI_STATUS_OPTIONAL)) {
1381             fprintSegment(f, 2 * INDENT, "status", INDENTVALUE);
1382             fprint(f, "%s;\n", getStringStatus(smiNode->status));
1383         }
1384         
1385         if (smiNode->description) {
1386             fprintSegment(f, 2 * INDENT, "description", INDENTVALUE);
1387             fprint(f, "\n");
1388             fprintMultilineString(f, 2 * INDENT, smiNode->description);
1389             fprint(f, ";\n");
1390         }
1391
1392         if (smiNode->reference) {
1393             fprintSegment(f, 2 * INDENT, "reference", INDENTVALUE);
1394             fprint(f, "\n");
1395             fprintMultilineString(f, 2 * INDENT, smiNode->reference);
1396             fprint(f, ";\n");
1397         }
1398
1399         fprintSegment(f, INDENT, "", 0);
1400         fprint(f, "};\n\n");
1401         i++;
1402     }
1403 }
1404
1405
1406
1407 static void fprintGroups(FILE *f, SmiModule *smiModule)
1408 {
1409     int          i, j;
1410     SmiNode      *smiNode;
1411     SmiElement   *smiElement;
1412     
1413     for(i = 0, smiNode = smiGetFirstNode(smiModule, SMI_NODEKIND_GROUP);
1414         smiNode; smiNode = smiGetNextNode(smiNode, SMI_NODEKIND_GROUP)) {
1415         
1416         if (!i && !silent) {
1417             fprint(f, "//\n// GROUP DEFINITIONS\n//\n\n");
1418         }
1419         
1420         fprintSegment(f, INDENT, "", 0);
1421         fprint(f, "group %s {\n", smiNode->name);
1422         
1423         if (smiNode->oid) {
1424             fprintSegment(f, 2 * INDENT, "oid", INDENTVALUE);
1425             fprint(f, "%s;\n", getOidString(smiNode, 0));
1426         }
1427         
1428         fprintSegment(f, 2 * INDENT, "members", INDENTVALUE);
1429         fprint(f, "(");
1430         for (j = 0, smiElement = smiGetFirstElement(smiNode); smiElement;
1431                  j++, smiElement = smiGetNextElement(smiElement)) {
1432             if (j) {
1433                 fprint(f, ", ");
1434             }
1435             fprintWrapped(f, INDENTVALUE + 1,
1436                           smiGetElementNode(smiElement)->name);
1437             /* TODO: non-local name if non-local */
1438         } /* TODO: empty? -> print error */
1439         fprint(f, ");\n");
1440             
1441         if ((smiNode->status != SMI_STATUS_CURRENT) &&
1442             (smiNode->status != SMI_STATUS_UNKNOWN) &&
1443             (smiNode->status != SMI_STATUS_MANDATORY) &&
1444             (smiNode->status != SMI_STATUS_OPTIONAL)) {
1445             fprintSegment(f, 2 * INDENT, "status", INDENTVALUE);
1446             fprint(f, "%s;\n", getStringStatus(smiNode->status));
1447         }
1448         
1449         if (smiNode->description) {
1450             fprintSegment(f, 2 * INDENT, "description", INDENTVALUE);
1451             fprint(f, "\n");
1452             fprintMultilineString(f, 2 * INDENT, smiNode->description);
1453             fprint(f, ";\n");
1454         }
1455         
1456         if (smiNode->reference) {
1457             fprintSegment(f, 2 * INDENT, "reference", INDENTVALUE);
1458             fprint(f, "\n");
1459             fprintMultilineString(f, 2 * INDENT, smiNode->reference);
1460             fprint(f, ";\n");
1461         }
1462         
1463         fprintSegment(f, INDENT, "", 0);
1464         fprint(f, "};\n\n");
1465         i++;
1466     }
1467 }
1468
1469
1470
1471 static void fprintCompliances(FILE *f, SmiModule *smiModule)
1472 {
1473     int           i, j;
1474     SmiNode       *smiNode, *smiNode2;
1475     SmiType       *smiType;
1476     SmiOption     *smiOption;
1477     SmiRefinement *smiRefinement;
1478     SmiElement    *smiElement;
1479     
1480     for(i = 0, smiNode = smiGetFirstNode(smiModule, SMI_NODEKIND_COMPLIANCE);
1481         smiNode; smiNode = smiGetNextNode(smiNode, SMI_NODEKIND_COMPLIANCE)) {
1482         
1483         if (!i && !silent) {
1484             fprint(f, "//\n// COMPLIANCE DEFINITIONS\n//\n\n");
1485         }
1486
1487         fprintSegment(f, INDENT, "", 0);
1488         fprint(f, "compliance %s {\n", smiNode->name);
1489             
1490         if (smiNode->oid) {
1491             fprintSegment(f, 2 * INDENT, "oid", INDENTVALUE);
1492             fprint(f, "%s;\n", getOidString(smiNode, 0));
1493         }
1494             
1495         if ((smiNode->status != SMI_STATUS_CURRENT) &&
1496             (smiNode->status != SMI_STATUS_UNKNOWN) &&
1497             (smiNode->status != SMI_STATUS_MANDATORY) &&
1498             (smiNode->status != SMI_STATUS_OPTIONAL)) {
1499             fprintSegment(f, 2 * INDENT, "status", INDENTVALUE);
1500             fprint(f, "%s;\n", getStringStatus(smiNode->status));
1501         }
1502             
1503         if (smiNode->description) {
1504             fprintSegment(f, 2 * INDENT, "description", INDENTVALUE);
1505             fprint(f, "\n");
1506             fprintMultilineString(f, 2 * INDENT, smiNode->description);
1507             fprint(f, ";\n");
1508         }
1509             
1510         if (smiNode->reference) {
1511             fprintSegment(f, 2 * INDENT, "reference", INDENTVALUE);
1512             fprint(f, "\n");
1513             fprintMultilineString(f, 2 * INDENT, smiNode->reference);
1514             fprint(f, ";\n");
1515         }
1516
1517         if ((smiElement = smiGetFirstElement(smiNode))) {
1518             fprint(f, "\n");
1519             fprintSegment(f, 2 * INDENT, "mandatory", INDENTVALUE);
1520             fprint(f, "(");
1521             for (j = 0; smiElement;
1522                  j++, smiElement = smiGetNextElement(smiElement)) {
1523                 if (j) {
1524                     fprint(f, ", ");
1525                 }
1526                 fprintWrapped(f, INDENTVALUE + 1,
1527                               smiGetElementNode(smiElement)->name);
1528                 /* TODO: non-local name if non-local */
1529             } /* TODO: empty? -> print error */
1530             fprint(f, ");\n");
1531         }
1532         
1533         if ((smiOption = smiGetFirstOption(smiNode))) {
1534             fprint(f, "\n");
1535             for(; smiOption; smiOption = smiGetNextOption(smiOption)) {
1536                 smiNode2 = smiGetOptionNode(smiOption);
1537                 fprintSegment(f, 2 * INDENT, "", 0);
1538                 fprint(f, "optional %s {\n", smiNode2->name);
1539                 fprintSegment(f, 3 * INDENT, "description", INDENTVALUE);
1540                 fprint(f, "\n");
1541                 fprintMultilineString(f, 3 * INDENT, smiOption->description);
1542                 fprint(f, ";\n");
1543                 fprintSegment(f, 2 * INDENT, "};\n", 0);
1544             }
1545         }
1546         
1547         if ((smiRefinement = smiGetFirstRefinement(smiNode))) {
1548             fprint(f, "\n");
1549             for(; smiRefinement;
1550                 smiRefinement = smiGetNextRefinement(smiRefinement)) {
1551                 fprintSegment(f, 2 * INDENT, "", 0);
1552                 fprint(f, "refine %s {\n",
1553                        smiGetRefinementNode(smiRefinement)->name);
1554
1555                 smiType = smiGetRefinementType(smiRefinement);
1556                 if (smiType) {
1557                     fprintSegment(f, 3 * INDENT, "type", INDENTVALUE);
1558                     fprint(f, "%s",
1559                            getTypeString(smiType->basetype,
1560                                          smiGetParentType(smiType)));
1561                     fprintSubtype(f, smiType);
1562                     fprint(f, ";\n");
1563                 }
1564
1565                 smiType = smiGetRefinementWriteType(smiRefinement);
1566                 if (smiType) {
1567                     fprintSegment(f, 3 * INDENT, "writetype", INDENTVALUE);
1568                     fprint(f, "%s",
1569                            getTypeString(smiType->basetype,
1570                                          smiGetParentType(smiType)));
1571                     fprintSubtype(f, smiType);
1572                     fprint(f, ";\n");
1573                 }
1574
1575                 if (smiRefinement->access != SMI_ACCESS_UNKNOWN) {
1576                     fprintSegment(f, 3 * INDENT, "access", INDENTVALUE);
1577                     fprint(f, "%s;\n", getAccessString(smiRefinement->access));
1578                 }
1579                 fprintSegment(f, 3 * INDENT, "description", INDENTVALUE);
1580                 fprint(f, "\n");
1581                 fprintMultilineString(f, 3 * INDENT,
1582                                       smiRefinement->description);
1583                 fprint(f, ";\n");
1584                 fprintSegment(f, 2 * INDENT, "};\n", 0);
1585             }
1586         }
1587         
1588         fprintSegment(f, INDENT, "", 0);
1589         fprint(f, "};\n\n");
1590         i++;
1591     }
1592 }
1593
1594
1595
1596 static void dumpSming(int modc, SmiModule **modv, int flags, char *output)
1597 {
1598     SmiModule   *smiModule;
1599     SmiNode     *smiNode;
1600     int         i;
1601     FILE        *f = stdout;
1602
1603     silent = (flags & SMIDUMP_FLAG_SILENT);
1604
1605     if (output) {
1606         f = fopen(output, "w");
1607         if (!f) {
1608             fprintf(stderr, "smidump: cannot open %s for writing: ", output);
1609             perror(NULL);
1610             exit(1);
1611         }
1612     }
1613
1614     for (i = 0; i < modc; i++) {
1615
1616         smiModule = modv[i];
1617     
1618         fprint(f, "//\n");
1619         fprint(f, "// This module has been generated by smidump "
1620                SMI_VERSION_STRING ". Do not edit.\n");
1621         fprint(f, "//\n");
1622         fprint(f, "module %s ", smiModule->name);
1623         fprint(f, "{\n");
1624         fprint(f, "\n");
1625         
1626         fprintImports(f, smiModule);
1627         
1628         if (! silent) {
1629             fprint(f, "//\n// MODULE META INFORMATION\n//\n\n");
1630         }
1631         fprintSegment(f, INDENT, "organization", INDENTVALUE);
1632         fprint(f, "\n");
1633         fprintMultilineString(f, INDENT, smiModule->organization);
1634         fprint(f, ";\n\n");
1635         fprintSegment(f, INDENT, "contact", INDENTVALUE);
1636         fprint(f, "\n");
1637         fprintMultilineString(f, INDENT, smiModule->contactinfo);
1638         fprint(f, ";\n\n");
1639         fprintSegment(f, INDENT, "description", INDENTVALUE);
1640         fprint(f, "\n");
1641         fprintMultilineString(f, INDENT, smiModule->description);
1642         fprint(f, ";\n\n");
1643         if (smiModule->reference) {
1644             fprintSegment(f, INDENT, "reference", INDENTVALUE);
1645             fprint(f, "\n");
1646             fprintMultilineString(f, INDENT, smiModule->reference);
1647             fprint(f, ";\n\n");
1648         }
1649         
1650         fprintRevisions(f, smiModule);
1651         
1652         smiNode = smiGetModuleIdentityNode(smiModule);
1653         if (smiNode) {
1654             fprintSegment(f, INDENT, "identity", INDENTVALUE);
1655             fprint(f, "%s;\n\n", smiNode->name);
1656         }
1657         
1658         fprintExtensions(f, smiModule);
1659         fprintIdentities(f, smiModule);
1660         fprintTypedefs(f, smiModule);
1661         fprintClasses(f, smiModule);
1662         fprintObjects(f, smiModule);
1663         fprintNotifications(f, smiModule);
1664         fprintGroups(f, smiModule);
1665         fprintCompliances(f, smiModule);
1666         
1667         fprint(f, "}; // end of module %s.\n", smiModule->name);
1668     }
1669     
1670     if (fflush(f) || ferror(f)) {
1671         perror("smidump: write error");
1672         exit(1);
1673     }
1674
1675     if (output) {
1676         fclose(f);
1677     }
1678 }
1679
1680
1681
1682 void initSming()
1683 {
1684     static SmidumpDriver driver = {
1685         "sming",
1686         dumpSming,
1687         0,
1688         SMIDUMP_DRIVER_CANT_UNITE,
1689         "SMIng",
1690         NULL,
1691         NULL
1692     };
1693     
1694     smidumpRegisterDriver(&driver);
1695 }