Imported Upstream version 0.4.8
[platform/upstream/libsmi.git] / tools / dump-perl.c
1 /*
2  * dump-perl.c --
3  *
4  *      Operations to dump SMIng module information in Perl format.
5  *
6  * Copyright (c) 2000 Frank Strauss, Technical University of Braunschweig.
7  * Copyright (c) 2000 J. Schoenwaelder, Technical University of Braunschweig.
8  * Copyright (c) 2000 WideAwake Ltd.
9  * Copyright (c) 2000 Martin Schulz martin.schulz@myrealbox.com
10  *
11  * See the file "COPYING" for information on usage and redistribution
12  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
13  *
14  * @(#) $Id: dump-perl.c 8090 2008-04-18 12:56:29Z strauss $
15  */
16
17 /*
18  * TODO:
19  *
20  */
21
22 #include <config.h>
23
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <stdarg.h>
27 #include <string.h>
28 #include <ctype.h>
29 #include <time.h>
30
31 #include "smi.h"
32 #include "smidump.h"
33
34
35
36 #define  INDENT         4    /* indent factor */
37 #define  INDENTVALUE    20   /* column to start values, except multiline */
38 #define  INDENTTEXTS    4    /* column to start multiline texts */
39 #define  INDENTMAX      64   /* max column to fill, break lines otherwise */
40
41
42
43 typedef struct PerlEscape {
44     char character;
45     char *escape;
46 } PerlEscape;
47
48 static PerlEscape perlEscapes [] = {
49     { '\'',     "\\'" },
50     { '\\',     "\\\\" },
51     { 0,        NULL }
52 };
53
54
55 static int current_column = 0;
56
57 static char* currentModuleName = NULL;
58
59 static char *getStringLanguage(SmiLanguage lang)
60 {
61     return
62         (lang == SMI_LANGUAGE_SMIV1) ? "SMIv1" :
63         (lang == SMI_LANGUAGE_SMIV2) ? "SMIv2" :
64         (lang == SMI_LANGUAGE_SMING) ? "SMIng" :
65                                         NULL;
66 }
67
68
69
70 static char *getStringStatus(SmiStatus status)
71 {
72     return
73         (status == SMI_STATUS_CURRENT)     ? "current" :
74         (status == SMI_STATUS_DEPRECATED)  ? "deprecated" :
75         (status == SMI_STATUS_OBSOLETE)    ? "obsolete" :
76         (status == SMI_STATUS_MANDATORY)   ? "current" :
77         (status == SMI_STATUS_OPTIONAL)    ? "current" :
78                                              "<unknown>";
79 }
80
81
82
83 static char *getAccessString(SmiAccess access)
84 {
85     return
86         (access == SMI_ACCESS_NOT_ACCESSIBLE) ? "noaccess" :
87         (access == SMI_ACCESS_NOTIFY)         ? "notifyonly" :
88         (access == SMI_ACCESS_READ_ONLY)      ? "readonly" :
89         (access == SMI_ACCESS_READ_WRITE)     ? "readwrite" :
90                                                 "<unknown>";
91 }
92
93
94
95 static char *getStringBasetype(SmiBasetype basetype)
96 {
97     return
98         (basetype == SMI_BASETYPE_UNKNOWN)           ? "<UNKNOWN>" :
99         (basetype == SMI_BASETYPE_OCTETSTRING)       ? "OctetString" :
100         (basetype == SMI_BASETYPE_OBJECTIDENTIFIER)  ? "ObjectIdentifier" :
101         (basetype == SMI_BASETYPE_UNSIGNED32)        ? "Unsigned32" :
102         (basetype == SMI_BASETYPE_INTEGER32)         ? "Integer32" :
103         (basetype == SMI_BASETYPE_UNSIGNED64)        ? "Unsigned64" :
104         (basetype == SMI_BASETYPE_INTEGER64)         ? "Integer64" :
105         (basetype == SMI_BASETYPE_FLOAT32)           ? "Float32" :
106         (basetype == SMI_BASETYPE_FLOAT64)           ? "Float64" :
107         (basetype == SMI_BASETYPE_FLOAT128)          ? "Float128" :
108         (basetype == SMI_BASETYPE_ENUM)              ? "Enumeration" :
109         (basetype == SMI_BASETYPE_BITS)              ? "Bits" :
110                                                    "<unknown>";
111 }
112
113
114
115 static char *getTimeString(time_t t)
116 {
117     static char   s[27];
118     struct tm     *tm;
119
120     tm = gmtime(&t);
121     sprintf(s, "%04d-%02d-%02d %02d:%02d",
122             tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
123             tm->tm_hour, tm->tm_min);
124     return s;
125 }
126
127
128
129 static void fprint(FILE *f, char *fmt, ...)
130 {
131     va_list ap;
132     char    *s;
133     char    *p;
134
135     va_start(ap, fmt);
136     current_column += smiVasprintf(&s, fmt, ap);
137     va_end(ap);
138     fputs(s, f);
139     if ((p = strrchr(s, '\n'))) {
140         current_column = strlen(p) - 1;
141     }
142     free(s);
143 }
144
145
146
147 static void fprintSegment(FILE *f, int column, char *string, int length)
148 {
149     fprint(f, "%*c%s", column, ' ', string);
150     if (length) {
151         fprint(f, "%*c", length - strlen(string) - column, ' ');
152     }
153 }
154
155
156
157 static void fprintMultilineString(FILE *f, int column, const char *s)
158 {
159     int i, j, len;
160
161 #ifdef INDENTTEXTS
162     fprintSegment(f, column + INDENTTEXTS, "", 0);
163 #endif
164     if (s) {
165         fputs ("'", f);
166         current_column += 3;
167         len = strlen(s);
168         for (i=0; i < len; i++) {
169             for (j = 0; perlEscapes[j].character; j++) {
170                 if (perlEscapes[j].character == s[i]) break;
171             }
172             if (perlEscapes[j].character) {
173                 fputs(perlEscapes[j].escape, f);
174                 current_column += strlen(perlEscapes[j].escape);
175             } else {
176                 putc(s[i], f);
177                 current_column++;
178             }
179             if (s[i] == '\n') {
180                 current_column = 0;
181             }
182         }
183         fputs ("'", f);
184         current_column += 3;
185     }
186     current_column++;
187 }
188
189
190
191 static char *getValueString(SmiValue *valuePtr, SmiType *typePtr)
192 {
193     static char    s[1024];
194     char           ss[9];
195     int            n;
196     unsigned int   i;
197     SmiNamedNumber *nn;
198
199     s[0] = 0;
200
201     switch (valuePtr->basetype) {
202     case SMI_BASETYPE_UNSIGNED32:
203         sprintf(s, "%lu", valuePtr->value.unsigned32);
204         break;
205     case SMI_BASETYPE_INTEGER32:
206         sprintf(s, "%ld", valuePtr->value.integer32);
207         break;
208     case SMI_BASETYPE_UNSIGNED64:
209         sprintf(s, UINT64_FORMAT, valuePtr->value.unsigned64);
210         break;
211     case SMI_BASETYPE_INTEGER64:
212         sprintf(s, INT64_FORMAT, valuePtr->value.integer64);
213         break;
214     case SMI_BASETYPE_FLOAT32:
215     case SMI_BASETYPE_FLOAT64:
216     case SMI_BASETYPE_FLOAT128:
217         break;
218     case SMI_BASETYPE_ENUM:
219         for (nn = smiGetFirstNamedNumber(typePtr); nn;
220              nn = smiGetNextNamedNumber(nn)) {
221             if (nn->value.value.unsigned32 == valuePtr->value.unsigned32)
222                 break;
223         }
224         if (nn) {
225             sprintf(s, "%s", nn->name);
226         } else {
227             sprintf(s, "%ld", valuePtr->value.integer32);
228         }
229         break;
230     case SMI_BASETYPE_OCTETSTRING:
231         for (i = 0; i < valuePtr->len; i++) {
232             if (!isprint((int)valuePtr->value.ptr[i])) break;
233         }
234         if (i == valuePtr->len) {
235             sprintf(s, "%s", valuePtr->value.ptr);
236         } else {
237             sprintf(s, "0x%*s", 2 * valuePtr->len, "");
238             for (i=0; i < valuePtr->len; i++) {
239                 sprintf(ss, "%02x", valuePtr->value.ptr[i]);
240                 strncpy(&s[2+2*i], ss, 2);
241             }
242         }
243         break;
244     case SMI_BASETYPE_BITS:
245         sprintf(s, "(");
246         for (i = 0, n = 0; i < valuePtr->len * 8; i++) {
247             if (valuePtr->value.ptr[i/8] & (1 << (7-(i%8)))) {
248                 if (n)
249                     sprintf(&s[strlen(s)], ", ");
250                 n++;
251                 for (nn = smiGetFirstNamedNumber(typePtr); nn;
252                      nn = smiGetNextNamedNumber(nn)) {
253                     if (nn->value.value.unsigned32 == i)
254                         break;
255                 }
256                 if (nn) {
257                     sprintf(&s[strlen(s)], "%s", nn->name);
258                 } else {
259                     sprintf(s, "%d", i);
260                 }
261             }
262         }
263         sprintf(&s[strlen(s)], ")");
264         break;
265     case SMI_BASETYPE_UNKNOWN:
266         break;
267     case SMI_BASETYPE_POINTER:
268         break;
269     case SMI_BASETYPE_OBJECTIDENTIFIER:
270         for (i = 0; i < valuePtr->len; i++) {
271             sprintf(&s[strlen(s)], i ? ".%u" : "%u", valuePtr->value.oid[i]);
272         }
273         break;
274     }
275
276     return s;
277 }
278
279
280
281 static void fprintNodeStartTag(FILE *f, int indent, const char *tag,
282                                SmiNode *smiNode)
283 {
284     unsigned int i;
285
286     fprintSegment(f, indent, "", 0);
287     fprint(f, "{\n", smiNode->name);
288     fprintSegment(f, indent + INDENT, "", 0);
289     fprint(f, "\"name\" => \"%s\",\n", smiNode->name);
290     fprintSegment(f, indent + INDENT, "", 0);
291     fprint(f, "\"type\" => \"%s\",\n", tag);
292     fprintSegment(f, indent + INDENT, "", 0);
293     fprint(f, "\"module\" => \"%s\",\n", currentModuleName);
294     fprintSegment(f, indent + INDENT, "", 0);
295     fprint(f, "\"oid\" => \"");
296     for (i = 0; i < smiNode->oidlen; i++) {
297         fprint(f, i ? ".%u" : "%u", smiNode->oid[i]);
298     }
299     fprint(f, "\"");
300
301     if (smiNode->create) {
302         fprint(f, ",\n");
303         fprintSegment(f, indent + INDENT, "\"create\" => \"true\"", 0);
304     }
305     if (smiNode->status != SMI_STATUS_UNKNOWN) {
306         fprint(f, ",\n");
307         fprintSegment(f, indent + INDENT, "", 0);
308         fprint(f, "\"status\" => \"%s\"", getStringStatus(smiNode->status));
309     }
310     if (smiNode->implied) {
311         fprint(f, ",\n");
312         fprintSegment(f, indent + INDENT, "\"implied\" => \"true\"", 0);
313     }
314     fprint(f, ",\n");
315 }
316
317
318
319 static void fprintNodeEndTag(FILE *f, int indent, const char *tag,
320                              const char *name)
321 {
322     fprintSegment(f, indent, "", 0);
323     fprint(f, "}, # %s\n", name);
324 }
325
326
327
328 static void fprintRanges(FILE *f, int indent, SmiType *smiType)
329 {
330     SmiRange       *range;
331     SmiValue       min, max;
332     int            rc;
333
334     if (! smiGetFirstRange(smiType)) {
335         return;
336     }
337
338     fprintSegment(f, indent, "\"ranges\" => (\n", 0);
339     for (range = smiGetFirstRange(smiType);
340          range;
341          range = smiGetNextRange(range)) {
342         fprintSegment(f, indent, "{\n", 0);
343         fprintSegment(f, indent + INDENT, "", 0);
344         fprint(f, "\"min\" => \"%s\",\n",
345                getValueString(&range->minValue, smiType));
346         fprintSegment(f, indent + INDENT, "", 0);
347         fprint(f, "\"max\" => \"%s\"\n",
348                getValueString(&range->maxValue, smiType));
349         fprintSegment(f, indent, "},\n", 0);
350     }
351     fprintSegment(f, indent, "),\n", 0);
352
353     rc = smiGetMinMaxRange(smiType, &min, &max);
354     
355     if (rc == 0
356         && min.basetype != SMI_BASETYPE_UNKNOWN
357         && max.basetype != SMI_BASETYPE_UNKNOWN) {
358         fprintSegment(f, indent, "\"range\" => {\n", 0);
359         fprintSegment(f, indent + INDENT, "", 0);
360         fprint(f, "\"min\" => \"%s\",\n",
361                getValueString(&min, smiType));
362         fprintSegment(f, indent + INDENT, "", 0);
363         fprint(f, "\"max\" => \"%s\"\n",
364                getValueString(&max, smiType));
365         fprintSegment(f, indent, "},\n", 0);
366     }
367 }
368
369
370
371 static void fprintNamedNumbers(FILE *f, int indent, SmiType *smiType)
372 {
373     SmiNamedNumber *nn;
374
375     if ((smiType->basetype != SMI_BASETYPE_ENUM) &&
376         (smiType->basetype != SMI_BASETYPE_BITS)) {
377         return;
378     }
379
380     for (nn = smiGetFirstNamedNumber(smiType);
381          nn;
382          nn = smiGetNextNamedNumber(nn)) {
383         fprintSegment(f, indent, "\"", 0);
384         fprint(f, "%s\" => ", nn->name);
385         fprint(f, "\"%s\",\n", getValueString(&nn->value, smiType));
386     }
387 }
388
389
390
391 static void fprintValue(FILE *f, int indent, SmiValue *smiValue,
392                         SmiType *smiType)
393 {
394     if (smiType && smiValue && smiValue->basetype != SMI_BASETYPE_UNKNOWN) {
395         fprintSegment(f, indent, "\"DEFVAL\" => ", 0);
396         fprint(f, "\"%s\"", getValueString(smiValue, smiType));
397         fprint(f, ",\n");
398     }
399 }
400
401
402
403 static void fprintDescription(FILE *f, int indent, const char *description)
404 {
405     if (description) {
406         fprintSegment(f, indent, "\"description\" =>\n", 0);
407         fprintMultilineString(f, indent, description);
408         fprint(f, ",\n");
409     }
410 }
411
412
413
414 static void fprintReference(FILE *f, int indent, const char *reference)
415 {
416     if (reference) {
417         fprintSegment(f, indent, "\"reference>\" =>\n", 0);
418         fprintMultilineString(f, indent, reference);
419         fprint(f, ",\n");
420     }
421 }
422
423
424
425 static void fprintFormat(FILE *f, int indent, const char *format)
426 {
427     if (format) {
428         fprintSegment(f, indent, "", 0);
429         fprint(f, "\"DISPLAY-HINT\" => \"%s\",\n", format);
430     }
431 }
432
433
434
435 static void fprintUnits(FILE *f, int indent, const char *units)
436 {
437     if (units) {
438         fprintSegment(f, indent, "", 0);
439         fprint(f, "\"UNITS\" => \"%s\",\n", units);
440     }
441 }
442
443
444
445 static void fprintAccess(FILE *f, int indent, SmiAccess smiAccess)
446 {
447     if (smiAccess != SMI_ACCESS_UNKNOWN) {
448         fprintSegment(f, indent, "", 0);
449         fprint(f, "\"access\" => \"%s\",\n", getAccessString(smiAccess));
450     }
451 }
452
453
454
455 static void fprintElementList(FILE *f, int indent, const char *tag,
456                               SmiElement *smiElement, int asArray)
457 {
458     SmiModule *smiModule;
459     SmiNode   *smiNode;
460
461     for (; smiElement; smiElement = smiGetNextElement(smiElement)) {
462         smiNode = smiGetElementNode(smiElement);
463         smiModule = smiGetNodeModule(smiNode);
464         fprintSegment(f, indent, "", 0);
465         if (tag) {
466             if (asArray) {
467                 fprint(f, "{\n");
468                 fprintSegment(f, indent + INDENT, "", 0);
469                 fprint(f, "\"name\" => \"%s\",\n", smiNode->name);
470             } else {
471                 fprint(f, "\"%s\" => {\n", smiNode->name);
472             }
473             fprintSegment(f, indent + INDENT, "", 0);
474             fprint(f, "\"type\" => \"%s\",\n", tag);
475             fprintSegment(f, indent + INDENT, "", 0);
476             fprint(f, "\"module\" => \"%s\"\n", smiModule->name);
477             fprintSegment(f, indent, "},\n", 0);
478         } else {
479             if (asArray) {
480                 fprint(f, "{ \"module\" => \"%s\", ", smiModule->name);
481                 fprint(f, "\"name\" => \"%s\" },\n", smiNode->name);
482             } else {
483                 fprint(f, "\"%s\" => \"%s\",\n", smiNode->name, smiModule->name);
484             }
485         }
486     }
487 }
488
489
490
491 static void fprintIndexModule(FILE *f, int indent, const char *modname,
492                               const char *nodename, const char *indexkind)
493 {
494     fprintSegment(f, indent, "", 0);
495     fprint(f, "\"%s\" => {\n", indexkind);
496     fprintSegment(f, indent + INDENT, "", 0);
497     fprint(f, "\"module\" => \"%s\",\n", modname);
498     fprintSegment(f, indent + INDENT, "", 0);
499     fprint(f, "\"name\" => \"%s\",\n", nodename);
500     fprintSegment(f, indent, "},\n", 0);
501 }
502
503
504
505 static void fprintIndex(FILE *f, int indent, SmiNode *smiNode)
506 {
507     SmiNode   *relatedNode;
508     SmiModule *relatedModule = NULL;
509
510     if (smiNode->implied) {
511         fprintSegment(f, indent, "\"indeximplied\" => \"true\",\n", 0);
512     }
513
514     relatedNode = smiGetRelatedNode(smiNode);
515     if (relatedNode) {
516         relatedModule = smiGetNodeModule(relatedNode);
517     }
518     switch (smiNode->indexkind) {
519     case SMI_INDEX_INDEX:
520         fprintSegment(f, indent, "\"index\" => [\n", 0);
521         fprintElementList(f, indent + INDENT, NULL,
522                           smiGetFirstElement(smiNode), 1);
523         fprintSegment(f, indent, "], #index\n", 0);
524         break;
525     case SMI_INDEX_AUGMENT:
526         if (relatedNode && relatedModule) {
527             fprintIndexModule(f, indent, relatedModule->name,
528                               relatedNode->name, "augments");
529         } /* TODO: else print error */
530         break;
531     case SMI_INDEX_REORDER:
532         if (relatedNode && relatedModule) {
533             fprintIndexModule(f, indent, relatedModule->name,
534                               relatedNode->name, "reorders");
535             fprintSegment(f, indent, "\"index\" => [\n", 0);
536             fprintElementList(f, indent + INDENT, NULL,
537                               smiGetFirstElement(smiNode), 1);
538             fprintSegment(f, indent, "], #index\n", 0);
539         } /* TODO: else print error */
540         break;
541     case SMI_INDEX_SPARSE:
542         if (relatedNode && relatedModule) {
543             fprintIndexModule(f, indent, relatedModule->name,
544                               relatedNode->name, "sparse");
545         } /* TODO: else print error */
546         break;
547     case SMI_INDEX_EXPAND:
548         if (relatedNode && relatedModule) {
549             fprintIndexModule(f, indent, relatedModule->name,
550                               relatedNode->name, "expands");
551         } /* TODO: else print error */
552         break;
553     case SMI_INDEX_UNKNOWN:
554         break;
555     }
556 }
557
558
559
560 static void fprintModule(FILE *f, SmiModule *smiModule)
561 {
562     SmiRevision *smiRevision;
563     SmiNode     *smiNode;
564     int         i;
565     int         there_were_revisions = 0;
566
567     currentModuleName = smiModule->name;
568
569     if (smiModule->organization) {
570         fprintSegment(f, INDENT, "\"organization\" =>", INDENTVALUE);
571         fprint(f, "\n");
572         fprintMultilineString(f, INDENT, smiModule->organization);
573         fprint(f, ",\n");
574     }
575
576     if (smiModule->contactinfo) {
577         fprintSegment(f, INDENT, "\"contact\" =>", INDENTVALUE);
578         fprint(f, "\n");
579         fprintMultilineString(f, INDENT, smiModule->contactinfo);
580         fprint(f, ",\n");
581     }
582     fprintDescription(f, INDENT, smiModule->description);
583     fprintReference(f, INDENT, smiModule->reference);
584
585     for(i = 0, smiRevision = smiGetFirstRevision(smiModule);
586         smiRevision; smiRevision = smiGetNextRevision(smiRevision)) {
587         if (i == 0) {
588             fprintSegment(f, INDENT, "\"revisions\" => [\n", 0);
589             there_were_revisions = 1;
590         }
591         fprintSegment(f, 2 * INDENT, "{\n", 0);
592         fprintSegment(f, 3 * INDENT, "", 0);
593         fprint(f, "\"date\" => \"%s\",\n",
594                getTimeString(smiRevision->date));
595         fprintDescription(f, 3 * INDENT, smiRevision->description);
596         fprintSegment(f, 2 * INDENT, "},\n", 0);
597         i++;
598     }
599     if (there_were_revisions) {
600         fprintSegment(f, INDENT, "],\n", 0);
601     }
602
603     smiNode = smiGetModuleIdentityNode(smiModule);
604     if (smiNode) {
605         fprintSegment(f, INDENT, "", 0);
606         fprint(f, "\"identity\" => \"%s\",\n", smiNode->name);
607     }
608     fprint(f, "\n");
609 }
610
611
612
613 static void fprintImports(FILE *f, SmiModule *smiModule)
614 {
615     SmiImport *smiImport;
616     SmiIdentifier lastModule = NULL;
617     int        i;
618
619     for (i = 0, smiImport = smiGetFirstImport(smiModule);
620          smiImport;
621          i++,
622          smiImport = smiGetNextImport(smiImport)) {
623         if (i == 0) {
624             fprintSegment(f, INDENT, "\"imports\" => [\n", 0);
625         }
626         if (smiImport->module == NULL)
627             continue;
628         
629         if ( lastModule == NULL || strcmp(lastModule, smiImport->module)) {
630             if ( lastModule ) {
631                 fprintSegment(f, 3 * INDENT, "]\n", 0);
632                 fprintSegment(f, 2 * INDENT, "},\n", 0);
633             }
634             fprintSegment(f, 2 * INDENT, "{\n", 0);
635             fprintSegment(f, 3 * INDENT, "", 0);
636             fprint(f, "\"module\" => \"%s\",\n",
637                    smiImport->module);
638             fprintSegment(f, 3 * INDENT, "\"names\" => [\n", 0);
639         }
640         fprintSegment(f, 4 * INDENT, "", 0);
641         fprint(f, "\"%s\",\n", smiImport->name);
642         lastModule = smiImport->module;
643     }
644     if (lastModule) {
645         fprintSegment(f, 3 * INDENT, "],\n", 0);
646         fprintSegment(f, 2 * INDENT, "}\n", 0);
647     }
648
649     if (i) {
650         fprintSegment(f, INDENT, "], # imports\n\n", 0);
651     }
652 }
653
654
655
656 static void fprintTypedef(FILE *f, int indent, SmiType *smiType)
657 {
658     SmiModule *parentModule;
659     SmiType *parentType;
660
661     fprintSegment(f, indent, "", 0);
662     if (smiType->name) {
663         fprint(f, "\"%s\" => ", smiType->name);
664     }
665     fprint(f, "{\n");
666     fprintSegment(f, indent + INDENT, "", 0);
667     fprint(f, "\"basetype\" => \"%s\",\n",
668            getStringBasetype(smiType->basetype));
669     if (smiType->name && smiType->status != SMI_STATUS_UNKNOWN) {
670         fprintSegment(f, indent + INDENT, "", 0);
671         fprint(f, "\"status\" => \"%s\",\n", getStringStatus(smiType->status));
672     }
673
674     parentType = smiGetParentType(smiType);
675     parentModule = smiGetTypeModule(parentType);
676     if (parentType && parentModule && strlen(parentModule->name)) {
677         fprintSegment(f, indent + INDENT, "\"parent\" => {\n", 0);
678         fprintSegment(f, indent + (2 * INDENT), "", 0);
679         fprint(f, "\"module\" => \"%s\",\n", parentModule->name);
680         fprintSegment(f, indent + (2 * INDENT), "", 0);
681         fprint(f, "\"name\" => \"%s\",\n", parentType->name);
682         fprintSegment(f, indent + INDENT, "},\n", 0);
683     }
684     fprintRanges(f, indent + INDENT, smiType);
685     fprintNamedNumbers(f, indent + INDENT, smiType);
686     fprintValue(f, indent + INDENT, &smiType->value, smiType);
687     fprintFormat(f, indent + INDENT, smiType->format);
688     fprintUnits(f, indent + INDENT, smiType->units);
689     fprintDescription(f, indent + INDENT, smiType->description);
690     fprintReference(f, indent + INDENT, smiType->reference);
691
692     fprintSegment(f, indent, "},", 0);
693     if (smiType->name) {
694         fprint(f, " # %s\n", smiType->name);
695     } else {
696         fprint(f, "\n", smiType->name);
697     }
698 }
699
700
701
702 static void fprintTypedefs(FILE *f, SmiModule *smiModule)
703 {
704     int          i;
705     SmiType      *smiType;
706
707     for(i = 0, smiType = smiGetFirstType(smiModule);
708         smiType;
709         i++, smiType = smiGetNextType(smiType)) {
710
711         if (i == 0) {
712             fprintSegment(f, INDENT, "\"typedefs\" => {\n", 0);
713         }
714         fprintTypedef(f, 2 * INDENT, smiType);
715     }
716
717     if (i) {
718         fprintSegment(f, INDENT, "}, # typedefs\n\n", 0);
719     }
720 }
721
722
723
724 static void fprintNode(FILE *f, int indent, SmiNode *smiNode,
725                        SmiNode *lastSmiNode)
726 {
727     SmiModule   *smiModule;
728     SmiType     *smiType;
729     char        *tag = NULL;
730
731     if (smiNode->nodekind == SMI_NODEKIND_NODE) {
732         tag = "node";
733     } else if (smiNode->nodekind == SMI_NODEKIND_CAPABILITIES) {
734         tag = "capabilities";
735     } else if (smiNode->nodekind == SMI_NODEKIND_TABLE) {
736         tag = "table";
737     } else if (smiNode->nodekind == SMI_NODEKIND_ROW) {
738         /* indent += INDENT; */
739         tag = "row";
740     } else if (smiNode->nodekind == SMI_NODEKIND_COLUMN) {
741         /* indent += 2 * INDENT; */
742         tag = "column";
743     } else if (smiNode->nodekind == SMI_NODEKIND_SCALAR) {
744         tag = "scalar";
745     }
746
747 /*      if (lastSmiNode */
748 /*      && lastSmiNode->nodekind == SMI_NODEKIND_COLUMN */
749 /*      && smiNode->nodekind != SMI_NODEKIND_COLUMN) { */
750 /*      printNodeEndTag(indent + INDENT, "row", smiNode->name); */
751 /*          printNodeEndTag(indent, "table", smiNode->name); */
752 /*      } */
753
754     smiType = smiGetNodeType(smiNode);
755
756     fprintNodeStartTag(f, indent, tag, smiNode);
757     fprintDescription(f, indent + INDENT, smiNode->description);
758     fprintReference(f, indent + INDENT, smiNode->reference);
759
760     if (smiType && (smiType->basetype != SMI_BASETYPE_UNKNOWN)) {
761         fprintSegment(f, indent + INDENT, "\"syntax\" => {\n", 0);
762         smiModule = smiGetTypeModule(smiType);
763         fprintSegment(f, indent + 2 *INDENT, "", 0);
764         fprint(f, "\"type\" => ");
765         if (smiType->name && smiModule) {
766             fprint(f, "{ \"module\" => \"%s\", \"name\" => \"%s\"},\n",
767                    smiModule->name, smiType->name);
768         } else {
769             fprint(f, "\n");
770             fprintTypedef(f, indent + 2 * INDENT, smiType);
771         }
772         fprintSegment(f, indent + INDENT, "},\n", 0);
773     }
774     if ((smiNode->nodekind != SMI_NODEKIND_TABLE) &&
775         (smiNode->nodekind != SMI_NODEKIND_ROW) &&
776         (smiNode->nodekind != SMI_NODEKIND_CAPABILITIES) &&
777         (smiNode->nodekind != SMI_NODEKIND_NODE)) {
778         fprintAccess(f, indent + INDENT, smiNode->access);
779     }
780     if (smiType) {
781         fprintValue(f, indent + INDENT, &smiNode->value, smiType);
782     }
783     fprintFormat(f, indent + INDENT, smiNode->format);
784     fprintUnits(f, indent + INDENT, smiNode->units);
785     if (smiNode->nodekind == SMI_NODEKIND_ROW) {
786         fprintIndex(f, indent + INDENT, smiNode);
787     }
788
789     fprintNodeEndTag(f, indent, tag, smiNode->name);
790 }
791
792
793
794 static void fprintNodes(FILE *f, SmiModule *smiModule)
795 {
796     int          i;
797     SmiNode      *smiNode, *lastSmiNode;
798     SmiNodekind  nodekinds;
799
800     nodekinds =  SMI_NODEKIND_NODE | SMI_NODEKIND_TABLE |
801         SMI_NODEKIND_ROW | SMI_NODEKIND_COLUMN | SMI_NODEKIND_SCALAR |
802         SMI_NODEKIND_CAPABILITIES;
803
804     for (i = 0,
805              lastSmiNode = NULL,
806              smiNode = smiGetFirstNode(smiModule, nodekinds);
807          smiNode;
808          i++,
809              lastSmiNode = smiNode,
810              smiNode = smiGetNextNode(smiNode, nodekinds)) {
811
812         if (i == 0) {
813             fprintSegment(f, INDENT, "\"nodes\" => [\n", 0);
814         }
815
816         fprintNode(f, 2 * INDENT, smiNode, lastSmiNode);
817     }
818
819 /*      if (lastSmiNode */
820 /*      && lastSmiNode->nodekind == SMI_NODEKIND_COLUMN) { */
821 /*      printNodeEndTag(3 * INDENT, "row", smiNode->name); */
822 /*          printNodeEndTag(2 * INDENT, "table", smiNode->name); */
823 /*      } */
824
825     if (i) {
826         fprintSegment(f, INDENT, "], # nodes\n\n", 0);
827     }
828 }
829
830
831
832 static void fprintNotification(FILE *f, int indent, SmiNode *smiNode)
833 {
834     fprintNodeStartTag(f, indent, "notification", smiNode);
835     fprintDescription(f, indent + INDENT, smiNode->description);
836     fprintReference(f, indent + INDENT, smiNode->reference);
837
838     fprintSegment(f, indent + INDENT, "\"objects\" => [\n", 0);
839     fprintElementList(f, indent + 2 * INDENT, NULL,
840                       smiGetFirstElement(smiNode), 1);
841     fprintSegment(f, indent + INDENT, "],\n", 0);
842
843     fprintNodeEndTag(f, indent, "notification", smiNode->name);
844 }
845
846
847
848 static void fprintNotifications(FILE *f, SmiModule *smiModule)
849 {
850     SmiNode *smiNode;
851     int      i;
852
853     for(i = 0, smiNode = smiGetFirstNode(smiModule, SMI_NODEKIND_NOTIFICATION);
854         smiNode;
855         i++, smiNode = smiGetNextNode(smiNode, SMI_NODEKIND_NOTIFICATION)) {
856
857         if (i == 0) {
858             fprintSegment(f, INDENT, "\"notifications\" => [\n", 0);
859         }
860         fprintNotification(f, 2 * INDENT, smiNode);
861     }
862
863     if (i) {
864         fprintSegment(f, INDENT, "], # notifications\n\n", 0);
865     }
866 }
867
868
869
870 static void fprintGroup(FILE *f, int indent, SmiNode *smiNode)
871 {
872     fprintNodeStartTag(f, indent, "group", smiNode);
873     fprintDescription(f, indent + INDENT, smiNode->description);
874     fprintReference(f, indent + INDENT, smiNode->reference);
875
876     fprintSegment(f, indent + INDENT, "\"members\" => [\n", 0);
877     fprintElementList(f, indent + 2 * INDENT, NULL,
878                       smiGetFirstElement(smiNode), 1);
879     fprintSegment(f, indent + INDENT, "], # members\n", 0);
880
881     fprintNodeEndTag(f, indent, "group", smiNode->name);
882 }
883
884
885
886 static void fprintGroups(FILE *f, SmiModule *smiModule)
887 {
888     SmiNode *smiNode;
889     int      i;
890
891     for(i = 0, smiNode = smiGetFirstNode(smiModule, SMI_NODEKIND_GROUP);
892         smiNode;
893         i++, smiNode = smiGetNextNode(smiNode, SMI_NODEKIND_GROUP)) {
894
895         if (i == 0) {
896             fprintSegment(f, INDENT, "\"groups\" => [\n", 0);
897         }
898         fprintGroup(f, 2 * INDENT, smiNode);
899     }
900
901     if (i) {
902         fprintSegment(f, INDENT, "], # groups\n\n", 0);
903     }
904 }
905
906
907
908 static void fprintComplGroups(FILE *f, int indent, SmiNode *smiNode)
909 {
910     SmiNode   *optSmiNode;
911     SmiModule *optSmiModule;
912     SmiOption *smiOption;
913
914     if (! smiGetFirstElement(smiNode) && !smiGetFirstOption(smiNode)) {
915         return;
916     }
917
918     fprintSegment(f, indent, "\"requires\" => [\n", 0);
919     fprintElementList(f, indent + INDENT, "mandatory",
920                       smiGetFirstElement(smiNode), 1);
921
922     for(smiOption = smiGetFirstOption(smiNode);
923         smiOption;
924         smiOption = smiGetNextOption(smiOption)) {
925         optSmiNode = smiGetOptionNode(smiOption);
926         optSmiModule = smiGetNodeModule(optSmiNode);
927         fprintSegment(f, indent + INDENT, "", 0);
928         fprint(f, "\"%s\" => {\n", optSmiNode->name);
929         fprintSegment(f, indent + 2*INDENT, "\"type\" => \"optional\",\n", 0);
930         fprintSegment(f, indent + 2*INDENT, "", 0);
931         fprint(f, "\"module\" => \"%s\",\n", optSmiModule->name);
932         fprintDescription(f, indent + 2 * INDENT, smiOption->description);
933         fprintSegment(f, indent + INDENT, "},\n", 0);
934     }
935
936     fprintSegment(f, indent, "], # requires\n", 0);
937 }
938
939
940
941 static void fprintRefinement(FILE *f, int indent, SmiRefinement *smiRefinement)
942 {
943     SmiModule *smiModule;
944     SmiNode   *smiNode;
945     SmiType   *smiType;
946
947     smiNode = smiGetRefinementNode(smiRefinement);
948     smiModule = smiGetNodeModule(smiNode);
949
950     fprintSegment(f, indent, "", 0);
951     fprint(f, "\"%s\" => {\n", smiNode->name);
952     fprintSegment(f, indent + INDENT, "", 0);
953     fprint(f, "\"module\" => \"%s\",\n", smiModule->name);
954
955     smiType = smiGetRefinementType(smiRefinement);
956     if (smiType) {
957         fprintSegment(f, indent + INDENT, "\"syntax\" => {\n", 0);
958         fprintSegment(f, indent + 2*INDENT, "\"type\" => ", 0);
959         fprintTypedef(f, indent + 2 * INDENT, smiType);
960         fprintSegment(f, indent + INDENT, "},\n", 0);
961     }
962
963     smiType = smiGetRefinementWriteType(smiRefinement);
964     if (smiType) {
965         fprintSegment(f, indent + INDENT, "\"writesyntax\" => {\n", 0);
966         fprintSegment(f, indent + 2*INDENT, "\"type\" => ", 0);
967         fprintTypedef(f, indent + 2 * INDENT, smiType);
968         fprintSegment(f, indent + INDENT, "},\n", 0);
969     }
970
971     if (smiRefinement->access != SMI_ACCESS_UNKNOWN) {
972         fprintAccess(f, indent + INDENT, smiRefinement->access);
973     }
974     fprintDescription(f, indent + INDENT, smiRefinement->description);
975     fprintSegment(f, indent, "},\n", 0);
976 }
977
978
979
980 static void fprintRefinements(FILE *f, int indent, SmiNode *smiNode)
981 {
982     SmiRefinement *smiRefinement;
983     int            i;
984
985     for(i = 0, smiRefinement = smiGetFirstRefinement(smiNode);
986         smiRefinement;
987         i++, smiRefinement = smiGetNextRefinement(smiRefinement)) {
988
989         if (!i) {
990             fprintSegment(f, indent, "\"refinements\" => {\n", 0);
991         }
992
993         fprintRefinement(f, indent + INDENT, smiRefinement);
994     }
995
996     if (i) {
997         fprintSegment(f, indent, "}, # refinements\n\n", 0);
998     }
999 }
1000
1001
1002
1003 static void fprintCompliance(FILE *f, int indent, SmiNode *smiNode)
1004 {
1005     fprintNodeStartTag(f, indent, "compliance", smiNode);
1006     fprintDescription(f, indent + INDENT, smiNode->description);
1007     fprintReference(f, indent + INDENT, smiNode->reference);
1008
1009     fprintComplGroups(f, indent + INDENT, smiNode);
1010     fprintRefinements(f, indent + INDENT, smiNode);
1011
1012     fprintNodeEndTag(f, indent, "compliance", smiNode->name);
1013 }
1014
1015
1016
1017 static void fprintCompliances(FILE *f, SmiModule *smiModule)
1018 {
1019     SmiNode *smiNode;
1020     int      i;
1021
1022     for(i = 0, smiNode = smiGetFirstNode(smiModule, SMI_NODEKIND_COMPLIANCE);
1023         smiNode;
1024         i++, smiNode = smiGetNextNode(smiNode, SMI_NODEKIND_COMPLIANCE)) {
1025
1026         if (!i) {
1027             fprintSegment(f, INDENT, "\"compliances\" => [\n", 0);
1028         }
1029
1030         fprintCompliance(f, 2 * INDENT, smiNode);
1031     }
1032
1033     if (i) {
1034         fprintSegment(f, INDENT, "], # compliances\n\n", 0);
1035     }
1036 }
1037
1038
1039
1040 static void dumpPerlModule(FILE *f, SmiModule *smiModule)
1041 {
1042     time_t now;
1043     char *lang;
1044
1045     now = time(NULL);
1046     fprint(f, "# Perl version 5\t\t\t\t\t\tDO NOT EDIT\n#\n");
1047     fprint(f, "# Generated by smidump " SMI_VERSION_STRING ":\n#\n");
1048     fprintf(f, "#   smidump -f perl %s\n\n", smiModule->name);
1049     
1050     fprint(f, "{\n");
1051     
1052     fprint(f, "\"%s\" => {\n", smiModule->name);
1053     fprintSegment(f, INDENT, "", 0);
1054     fprint(f, "\"name\" => \"%s\",\n\n", smiModule->name);
1055     
1056     fprintSegment(f, INDENT, "#    Compiler Info\n", 0);
1057     fprint(f, "");
1058     fprintSegment(f, INDENT, "", 0);
1059     fprint(f, "\"path\" => \"%s\",\n", smiModule->path);
1060     
1061     lang = getStringLanguage(smiModule->language);
1062     if (lang) {
1063         fprintSegment(f, INDENT, "", 0);
1064         fprint(f, "\"language\" => \"%s\",\n", lang);
1065     }
1066     
1067     fprint(f, "\n");
1068     fprintSegment(f, INDENT, "#    Module Identity\n", 0);
1069     fprintModule(f, smiModule);
1070     
1071     fprintSegment(f, INDENT, "#    Imports\n", 0);
1072     fprintImports(f, smiModule);
1073     fprintSegment(f, INDENT, "#    Module Body\n", 0);
1074     fprintTypedefs(f, smiModule);
1075     fprintNodes(f, smiModule);
1076     fprintNotifications(f, smiModule);
1077     fprintGroups(f, smiModule);
1078     fprintCompliances(f, smiModule);
1079     
1080     fprint(f, "  } # %s\n", smiModule->name);
1081     fprint(f, "};\n");
1082 }
1083
1084
1085
1086 static void dumpPerl(int modc, SmiModule **modv, int flags, char *output)
1087 {
1088     int  i;
1089     FILE *f = stdout;
1090
1091     if (output) {
1092         f = fopen(output, "w");
1093         if (!f) {
1094             fprintf(stderr, "smidump: cannot open %s for writing: ", output);
1095             perror(NULL);
1096             exit(1);
1097         }
1098     }
1099
1100     for (i = 0; i < modc; i++) {
1101         dumpPerlModule(f, modv[i]);
1102     }
1103
1104     if (fflush(f) || ferror(f)) {
1105         perror("smidump: write error");
1106         exit(1);
1107     }
1108
1109     if (output) {
1110         fclose(f);
1111     }
1112 }
1113
1114
1115
1116 void initPerl()
1117 {
1118     static SmidumpDriver driver = {
1119         "perl",
1120         dumpPerl,
1121         0,
1122         SMIDUMP_DRIVER_CANT_UNITE,
1123         "Perl MIB dictionaries",
1124         NULL,
1125         NULL
1126     };
1127
1128     smidumpRegisterDriver(&driver);
1129 }