1 /*
2  * dump-python.c --
3  *
4  *      Operations to dump SMIng module information in Python 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  *
10  * See the file "COPYING" for information on usage and redistribution
11  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
12  *
13  * @(#) $Id: dump-python.c 8090 2008-04-18 12:56:29Z strauss $
14  */
15 
16 /*
17  * TODO:
18  *
19  * - value representations (getValueString())
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 static int silent = 0;
43 
44 
45 typedef struct PythonEscape {
46     char character;
47     char *escape;
48 } PythonEscape;
49 
50 static PythonEscape pythonEscapes [] = {
51     { 0,	NULL }
52 };
53 
54 
55 static int current_column = 0;
56 
57 static char* currentModuleName = NULL;
58 
getStringLanguage(SmiLanguage lang)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 
getStringStatus(SmiStatus status)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 
getAccessString(SmiAccess access)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 
getStringBasetype(SmiBasetype basetype)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 
getTimeString(time_t t)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 
fprint(FILE * f,char * fmt,...)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 
fprintSegment(FILE * f,int column,char * string,int length)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 
fprintMultilineString(FILE * f,int column,const char * s)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; pythonEscapes[j].character; j++) {
170 		if (pythonEscapes[j].character == s[i]) break;
171 	    }
172 	    if (pythonEscapes[j].character) {
173 		fputs(pythonEscapes[j].escape, f);
174 		current_column += strlen(pythonEscapes[j].escape);
175 	    } else {
176 		putc(s[i], f);
177 		current_column++;
178 	    }
179 	    if (s[i] == '\n') {
180 		current_column = 0;
181 #ifdef INDENTTEXTS
182 		/* printSegment(column + INDENTTEXTS, "", 0); */
183 #endif
184 	    }
185 	}
186         fputs("\"\"\"", f);
187 	current_column += 3;
188     }
189     current_column++;
190 }
191 
192 
193 
getValueString(SmiValue * valuePtr,SmiType * typePtr)194 static char *getValueString(SmiValue *valuePtr, SmiType *typePtr)
195 {
196     static char    s[1024];
197     char           ss[9];
198     int		   n;
199     unsigned int   i;
200     SmiNamedNumber *nn;
201 
202     s[0] = 0;
203 
204     switch (valuePtr->basetype) {
205     case SMI_BASETYPE_UNSIGNED32:
206 	sprintf(s, "%lu", valuePtr->value.unsigned32);
207 	break;
208     case SMI_BASETYPE_INTEGER32:
209 	sprintf(s, "%ld", valuePtr->value.integer32);
210 	break;
211     case SMI_BASETYPE_UNSIGNED64:
212 	sprintf(s, UINT64_FORMAT, valuePtr->value.unsigned64);
213 	break;
214     case SMI_BASETYPE_INTEGER64:
215 	sprintf(s, INT64_FORMAT, valuePtr->value.integer64);
216 	break;
217     case SMI_BASETYPE_FLOAT32:
218     case SMI_BASETYPE_FLOAT64:
219     case SMI_BASETYPE_FLOAT128:
220 	break;
221     case SMI_BASETYPE_ENUM:
222 	for (nn = smiGetFirstNamedNumber(typePtr); nn;
223 	     nn = smiGetNextNamedNumber(nn)) {
224 	    if (nn->value.value.unsigned32 == valuePtr->value.unsigned32)
225 		break;
226 	}
227 	if (nn) {
228 	    sprintf(s, "%s", nn->name);
229 	} else {
230 	    sprintf(s, "%ld", valuePtr->value.integer32);
231 	}
232 	break;
233     case SMI_BASETYPE_OCTETSTRING:
234 	for (i = 0; i < valuePtr->len; i++) {
235 	    if (!isprint((int)valuePtr->value.ptr[i])) break;
236 	}
237 	if (i == valuePtr->len) {
238 	    sprintf(s, "%s", valuePtr->value.ptr);
239 	} else {
240             sprintf(s, "0x%*s", 2 * valuePtr->len, "");
241             for (i=0; i < valuePtr->len; i++) {
242                 sprintf(ss, "%02x", valuePtr->value.ptr[i]);
243                 strncpy(&s[2+2*i], ss, 2);
244             }
245 	}
246 	break;
247     case SMI_BASETYPE_BITS:
248 	sprintf(s, "(");
249 	for (i = 0, n = 0; i < valuePtr->len * 8; i++) {
250 	    if (valuePtr->value.ptr[i/8] & (1 << (7-(i%8)))) {
251 		if (n)
252 		    sprintf(&s[strlen(s)], ", ");
253 		n++;
254 		for (nn = smiGetFirstNamedNumber(typePtr); nn;
255 		     nn = smiGetNextNamedNumber(nn)) {
256 		    if (nn->value.value.unsigned32 == i)
257 			break;
258 		}
259 		if (nn) {
260 		    sprintf(&s[strlen(s)], "%s", nn->name);
261 		} else {
262 		    sprintf(s, "%d", i);
263 		}
264 	    }
265 	}
266 	sprintf(&s[strlen(s)], ")");
267 	break;
268     case SMI_BASETYPE_UNKNOWN:
269 	break;
270     case SMI_BASETYPE_POINTER:
271 	break;
272     case SMI_BASETYPE_OBJECTIDENTIFIER:
273 	for (i = 0; i < valuePtr->len; i++) {
274 	    sprintf(&s[strlen(s)], i ? ".%u" : "%u", valuePtr->value.oid[i]);
275 	}
276 	break;
277     }
278 
279     return s;
280 }
281 
282 
283 
fprintNodeStartTag(FILE * f,int indent,const char * tag,SmiNode * smiNode)284 static void fprintNodeStartTag(FILE *f, int indent, const char *tag,
285 			       SmiNode *smiNode)
286 {
287     unsigned int i;
288 
289     fprintSegment(f, indent, "", 0);
290     fprint(f, "\"%s\" : {\n", smiNode->name);
291     fprintSegment(f, indent + INDENT, "", 0);
292     fprint(f, "\"nodetype\" : \"%s\",\n", tag);
293     fprintSegment(f, indent + INDENT, "", 0);
294     fprint(f, "\"moduleName\" : \"%s\",\n", currentModuleName);
295     fprintSegment(f, indent + INDENT, "", 0);
296     fprint(f, "\"oid\" : \"");
297     for (i = 0; i < smiNode->oidlen; i++) {
298 	fprint(f, i ? ".%u" : "%u", smiNode->oid[i]);
299     }
300     fprint(f, "\"");
301 
302     if (smiNode->create) {
303 	fprint(f, ",\n");
304 	fprintSegment(f, indent + INDENT, "\"create\" : \"true\"", 0);
305     }
306     if (smiNode->status != SMI_STATUS_UNKNOWN) {
307 	fprint(f, ",\n");
308 	fprintSegment(f, indent + INDENT, "", 0);
309 	fprint(f, "\"status\" : \"%s\"", getStringStatus(smiNode->status));
310     }
311     if (smiNode->implied) {
312 	fprint(f, ",\n");
313 	fprintSegment(f, indent + INDENT, "\"implied\" : \"true\"", 0);
314     }
315     fprint(f, ",\n");
316 }
317 
318 
319 
fprintNodeEndTag(FILE * f,int indent,const char * tag)320 static void fprintNodeEndTag(FILE *f, int indent, const char *tag)
321 {
322     fprintSegment(f, indent, "", 0);
323     fprint(f, "}, # %s\n", tag);
324 }
325 
326 
327 
fprintRanges(FILE * f,int indent,SmiType * smiType)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 
359 	fprintSegment(f, indent, "\"range\" : {\n", 0);
360 	fprintSegment(f, indent + INDENT, "", 0);
361 	fprint(f, "\"min\" : \"%s\",\n", getValueString(&min, smiType));
362 	fprintSegment(f, indent + INDENT, "", 0);
363 	fprint(f, "\"max\" : \"%s\"\n", getValueString(&max, smiType));
364 	fprintSegment(f, indent, "},\n", 0);
365     }
366 }
367 
368 
369 
fprintNamedNumbers(FILE * f,int indent,SmiType * smiType)370 static void fprintNamedNumbers(FILE *f, int indent, SmiType *smiType)
371 {
372     SmiNamedNumber *nn;
373 
374     if ((smiType->basetype != SMI_BASETYPE_ENUM) &&
375 	(smiType->basetype != SMI_BASETYPE_BITS)) {
376 	return;
377     }
378 
379     for (nn = smiGetFirstNamedNumber(smiType);
380 	 nn;
381 	 nn = smiGetNextNamedNumber(nn)) {
382 	fprintSegment(f, indent, "\"", 0);
383 	fprint(f, "%s\" : {\n", nn->name);
384 	fprintSegment(f, indent + INDENT,
385 		      "\"nodetype\" : \"namednumber\",\n", 0);
386 	fprintSegment(f, indent + INDENT, "", 0);
387 	fprint(f, "\"number\" : \"%s\"\n",
388 	       getValueString(&nn->value, smiType));
389 	fprintSegment(f, indent, "},\n", 0);
390     }
391 }
392 
393 
394 
fprintValue(FILE * f,int indent,SmiValue * smiValue,SmiType * smiType)395 static void fprintValue(FILE *f, int indent, SmiValue *smiValue,
396 			SmiType *smiType)
397 {
398     if (smiType && smiValue && smiValue->basetype != SMI_BASETYPE_UNKNOWN) {
399 	fprintSegment(f, indent, "\"default\" : ", 0);
400 	fprint(f, "\"%s\"", getValueString(smiValue, smiType));
401 	fprint(f, ",\n");
402     }
403 }
404 
405 
406 
fprintDescription(FILE * f,int indent,const char * description)407 static void fprintDescription(FILE *f, int indent, const char *description)
408 {
409     if (description) {
410 	fprintSegment(f, indent, "\"description\" :\n", 0);
411 	fprintMultilineString(f, indent, description);
412 	fprint(f, ",\n");
413     }
414 }
415 
416 
417 
fprintReference(FILE * f,int indent,const char * reference)418 static void fprintReference(FILE *f, int indent, const char *reference)
419 {
420     if (reference) {
421 	fprintSegment(f, indent, "\"reference>\" :\n", 0);
422 	fprintMultilineString(f, indent, reference);
423 	fprint(f, ",\n");
424     }
425 }
426 
427 
428 
fprintFormat(FILE * f,int indent,const char * format)429 static void fprintFormat(FILE *f, int indent, const char *format)
430 {
431     if (format) {
432 	fprintSegment(f, indent, "", 0);
433 	fprint(f, "\"format\" : \"%s\",\n", format);
434     }
435 }
436 
437 
438 
fprintUnits(FILE * f,int indent,const char * units)439 static void fprintUnits(FILE *f, int indent, const char *units)
440 {
441     if (units) {
442 	fprintSegment(f, indent, "", 0);
443 	fprint(f, "\"units\" : \"%s\",\n", units);
444     }
445 }
446 
447 
448 
fprintAccess(FILE * f,int indent,SmiAccess smiAccess)449 static void fprintAccess(FILE *f, int indent, SmiAccess smiAccess)
450 {
451     if (smiAccess != SMI_ACCESS_UNKNOWN) {
452 	fprintSegment(f, indent, "", 0);
453 	fprint(f, "\"access\" : \"%s\",\n", getAccessString(smiAccess));
454     }
455 }
456 
457 
458 
fprintElementList(FILE * f,int indent,const char * tag,SmiElement * smiElement)459 static void fprintElementList(FILE *f, int indent, const char *tag,
460 			      SmiElement *smiElement)
461 {
462     SmiModule *smiModule;
463     SmiNode   *smiNode;
464 
465     for (; smiElement; smiElement = smiGetNextElement(smiElement)) {
466 	smiNode = smiGetElementNode(smiElement);
467 	smiModule = smiGetNodeModule(smiNode);
468 	fprintSegment(f, indent, "", 0);
469 	fprint(f, "\"%s\" : {\n", smiNode->name);
470 	fprintSegment(f, indent + INDENT, "", 0);
471 	fprint(f, "\"nodetype\" : \"%s\",\n", tag);
472 	fprintSegment(f, indent + INDENT, "", 0);
473 	fprint(f, "\"module\" : \"%s\"\n", smiModule->name);
474 	fprintSegment(f, indent, "},\n", 0);
475     }
476 }
477 
fprintListElement(FILE * f,int indent,const char * tag,SmiElement * smiElement)478 static void fprintListElement(FILE *f, int indent, const char *tag,
479 			      SmiElement *smiElement)
480 {
481     SmiNode   *smiNode;
482 
483     for (; smiElement; smiElement = smiGetNextElement(smiElement)) {
484 	smiNode = smiGetElementNode(smiElement);
485 	fprintSegment(f, indent, "", 0);
486 	fprint(f, "\"%s\",\n", smiNode->name);
487     }
488 }
489 
490 
491 
fprintIndexModule(FILE * f,int indent,const char * modname,const char * nodename,const char * indexkind)492 static void fprintIndexModule(FILE *f, int indent, const char *modname,
493 			      const char *nodename, const char *indexkind)
494 {
495     fprintSegment(f, indent + INDENT, "", 0);
496     fprint(f, "{ \"%s\" : {\n", modname);
497     fprintSegment(f, indent + (2 * INDENT), "", 0);
498     fprint(f, "\"indexkind\" : \"%s\",\n", indexkind);
499     fprintSegment(f, indent + (2 * INDENT), "", 0);
500     fprint(f, "\"relatedNode\" : \"%s\",\n", nodename);
501     fprintSegment(f, indent + INDENT, "}},\n", 0);
502 }
503 
504 
505 
fprintIndex(FILE * f,int indent,SmiNode * smiNode)506 static void fprintIndex(FILE *f, int indent, SmiNode *smiNode)
507 {
508     SmiNode   *relatedNode;
509     SmiModule *relatedModule = NULL;
510 
511     fprintSegment(f, indent, "\"linkage\" : [\n", 0);
512     if (smiNode->implied) {
513 	/* fprintSegment(f, indent + INDENT, "\"implied\" : \"true\",\n", 0); */
514     }
515 
516     relatedNode = smiGetRelatedNode(smiNode);
517     if (relatedNode) {
518 	relatedModule = smiGetNodeModule(relatedNode);
519     }
520     switch (smiNode->indexkind) {
521     case SMI_INDEX_INDEX:
522 	fprintListElement(f, indent + INDENT, "index",
523 			  smiGetFirstElement(smiNode));
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 	    fprintElementList(f, indent + INDENT, "index",
536 			      smiGetFirstElement(smiNode));
537 	} /* TODO: else print error */
538 	break;
539     case SMI_INDEX_SPARSE:
540 	if (relatedNode && relatedModule) {
541 	    fprintIndexModule(f, indent, relatedModule->name,
542 			      relatedNode->name, "sparse");
543 	} /* TODO: else print error */
544 	break;
545     case SMI_INDEX_EXPAND:
546 	if (relatedNode && relatedModule) {
547 	    fprintIndexModule(f, indent, relatedModule->name,
548 			      relatedNode->name, "expands");
549 	} /* TODO: else print error */
550 	break;
551     case SMI_INDEX_UNKNOWN:
552 	break;
553     }
554     fprintSegment(f, indent, "],\n", 0);
555 }
556 
557 
558 
fprintModule(FILE * f,SmiModule * smiModule)559 static void fprintModule(FILE *f, SmiModule *smiModule)
560 {
561     SmiRevision *smiRevision;
562     SmiNode     *smiNode;
563     int         i;
564     char	*lang;
565     int		there_were_revisions = 0;
566 
567     lang = getStringLanguage(smiModule->language);
568     currentModuleName = smiModule->name;
569 
570     fprintSegment(f, INDENT, "", 0);
571     fprint(f, "\"%s\" : {\n", smiModule->name);
572     fprintSegment(f, 2 * INDENT, "\"nodetype\" : \"module\",\n", 0);
573     if (lang) {
574 	fprintSegment(f, 2 * INDENT, "", 0);
575 	fprint(f, "\"language\" : \"%s\",\n", lang);
576     }
577 
578     if (smiModule->organization) {
579 	fprintSegment(f, 2 * INDENT, "\"organization\" :", INDENTVALUE);
580 	fprint(f, "\n");
581 	fprintMultilineString(f, 2 * INDENT, smiModule->organization);
582 	fprint(f, ",\n");
583     }
584 
585     if (smiModule->contactinfo) {
586 	fprintSegment(f, 2 * INDENT, "\"contact\" :", INDENTVALUE);
587 	fprint(f, "\n");
588 	fprintMultilineString(f, 2 * INDENT, smiModule->contactinfo);
589 	fprint(f, ",\n");
590     }
591     fprintDescription(f, 2 * INDENT, smiModule->description);
592     fprintReference(f, 2 * INDENT, smiModule->reference);
593 
594     for(i = 0, smiRevision = smiGetFirstRevision(smiModule);
595 	smiRevision; smiRevision = smiGetNextRevision(smiRevision)) {
596 	if (i == 0) {
597 	    fprintSegment(f, 2 * INDENT, "\"revisions\" : (\n", 0);
598 	    there_were_revisions = 1;
599 	}
600 	fprintSegment(f, 3 * INDENT, "{\n", 0);
601 	fprintSegment(f, 4 * INDENT, "", 0);
602 	fprint(f, "\"date\" : \"%s\",\n",
603 	       getTimeString(smiRevision->date));
604 	fprintDescription(f, 4 * INDENT, smiRevision->description);
605         fprintSegment(f, 3 * INDENT, "},\n", 0);
606 	i++;
607     }
608     if (there_were_revisions) {
609 	fprintSegment(f, 2 * INDENT, "),\n", 0);
610     }
611 
612     smiNode = smiGetModuleIdentityNode(smiModule);
613     if (smiNode) {
614 	fprintSegment(f, 2 * INDENT, "", 0);
615 	fprint(f, "\"identity node\" : \"%s\",\n", smiNode->name);
616     }
617 
618     fprintSegment(f, INDENT, "},\n\n", 0);
619 }
620 
621 
622 
fprintImport(FILE * f,int indent,SmiImport * smiImport)623 static void fprintImport(FILE *f, int indent, SmiImport *smiImport)
624 {
625     fprintSegment(f, indent, "", 0);
626     fprint(f, "{\"module\" : \"%s\", \"name\" : \"%s\"},\n",
627 	   smiImport->module, smiImport->name);
628 }
629 
630 
631 
fprintImports(FILE * f,SmiModule * smiModule)632 static void fprintImports(FILE *f, SmiModule *smiModule)
633 {
634     SmiImport *smiImport;
635     int        i;
636 
637     for (i = 0, smiImport = smiGetFirstImport(smiModule);
638 	 smiImport;
639 	 i++, smiImport = smiGetNextImport(smiImport)) {
640 	if (i == 0) {
641 	    fprintSegment(f, INDENT, "\"imports\" : (\n", 0);
642 	}
643 	fprintImport(f, 2 * INDENT, smiImport);
644     }
645 
646     if (i) {
647 	fprintSegment(f, INDENT, "),\n\n", 0);
648     }
649 }
650 
651 
652 
fprintTypedef(FILE * f,int indent,SmiType * smiType)653 static void fprintTypedef(FILE *f, int indent, SmiType *smiType)
654 {
655     SmiModule *parentModule;
656     SmiType *parentType;
657 
658     fprintSegment(f, indent, "", 0);
659     if (smiType->name) {
660 	fprint(f, "\"%s\" : ", smiType->name);
661     }
662     fprint(f, "{\n");
663     fprintSegment(f, indent + INDENT, "", 0);
664     fprint(f, "\"basetype\" : \"%s\",\n",
665 	   getStringBasetype(smiType->basetype));
666     if (smiType->name && smiType->status != SMI_STATUS_UNKNOWN) {
667 	fprintSegment(f, indent + INDENT, "", 0);
668 	fprint(f, "\"status\" : \"%s\",\n", getStringStatus(smiType->status));
669     }
670 
671     parentType = smiGetParentType(smiType);
672     parentModule = smiGetTypeModule(parentType);
673     if (parentType && parentType->name &&
674 	parentModule && strlen(parentModule->name)) {
675 	fprintSegment(f, indent + INDENT, "\"parent module\" : {\n", 0);
676 	fprintSegment(f, indent + (2 * INDENT), "", 0);
677 	fprint(f, "\"name\" : \"%s\",\n", parentModule->name);
678 	fprintSegment(f, indent + (2 * INDENT), "", 0);
679 	fprint(f, "\"type\" : \"%s\",\n", parentType->name);
680 	fprintSegment(f, indent + INDENT, "},\n", 0);
681     }
682     fprintRanges(f, indent + INDENT, smiType);
683     fprintNamedNumbers(f, indent + INDENT, smiType);
684     fprintValue(f, indent + INDENT, &smiType->value, smiType);
685     fprintFormat(f, indent + INDENT, smiType->format);
686     fprintUnits(f, indent + INDENT, smiType->units);
687     fprintDescription(f, indent + INDENT, smiType->description);
688     fprintReference(f, indent + INDENT, smiType->reference);
689 
690     fprintSegment(f, indent, "},\n", 0);
691 }
692 
693 
694 
fprintTypedefs(FILE * f,SmiModule * smiModule)695 static void fprintTypedefs(FILE *f, SmiModule *smiModule)
696 {
697     int		 i;
698     SmiType	 *smiType;
699 
700     for(i = 0, smiType = smiGetFirstType(smiModule);
701 	smiType;
702 	i++, smiType = smiGetNextType(smiType)) {
703 
704 	if (i == 0) {
705 	    fprintSegment(f, INDENT, "\"typedefs\" : {\n", 0);
706 	}
707 	fprintTypedef(f, 2 * INDENT, smiType);
708     }
709 
710     if (i) {
711 	fprintSegment(f, INDENT, "}, # typedefs\n\n", 0);
712     }
713 }
714 
715 
716 
fprintNode(FILE * f,int indent,SmiNode * smiNode,SmiNode * lastSmiNode)717 static void fprintNode(FILE *f, int indent, SmiNode *smiNode,
718 		       SmiNode *lastSmiNode)
719 {
720     SmiModule   *smiModule;
721     SmiType     *smiType;
722     char        *tag = NULL;
723 
724     if (smiNode->nodekind == SMI_NODEKIND_NODE) {
725 	tag = "node";
726     } else if (smiNode->nodekind == SMI_NODEKIND_CAPABILITIES) {
727 	tag = "capabilities";
728     } else if (smiNode->nodekind == SMI_NODEKIND_TABLE) {
729 	tag = "table";
730     } else if (smiNode->nodekind == SMI_NODEKIND_ROW) {
731 	/* indent += INDENT; */
732 	tag = "row";
733     } else if (smiNode->nodekind == SMI_NODEKIND_COLUMN) {
734 	/* indent += 2 * INDENT; */
735 	tag = "column";
736     } else if (smiNode->nodekind == SMI_NODEKIND_SCALAR) {
737 	tag = "scalar";
738     }
739 
740 /*      if (lastSmiNode */
741 /*  	&& lastSmiNode->nodekind == SMI_NODEKIND_COLUMN */
742 /*  	&& smiNode->nodekind != SMI_NODEKIND_COLUMN) { */
743 /*  	printNodeEndTag(indent + INDENT, "row"); */
744 /*          printNodeEndTag(indent, "table"); */
745 /*      } */
746 
747     smiType = smiGetNodeType(smiNode);
748 
749     fprintNodeStartTag(f, indent, tag, smiNode);
750     if (smiType && (smiType->basetype != SMI_BASETYPE_UNKNOWN)) {
751 	fprintSegment(f, indent + INDENT, "\"syntax\" : {\n", 0);
752 	smiModule = smiGetTypeModule(smiType);
753 	fprintSegment(f, indent + 2 *INDENT, "", 0);
754 	fprint(f, "\"type\" : ");
755 	if (smiType->name && smiModule) {
756 	    fprintf(f, "{ \"module\" :\"%s\", \"name\" : \"%s\"},\n",
757 		    smiModule->name, smiType->name);
758 	} else {
759 	    fprintTypedef(f, indent + 2 * INDENT, smiType);
760 	}
761 	fprintSegment(f, indent + INDENT, "},\n", 0);
762     }
763     if ((smiNode->nodekind != SMI_NODEKIND_TABLE) &&
764 	(smiNode->nodekind != SMI_NODEKIND_ROW) &&
765 	(smiNode->nodekind != SMI_NODEKIND_CAPABILITIES) &&
766 	(smiNode->nodekind != SMI_NODEKIND_NODE)) {
767 	fprintAccess(f, indent + INDENT, smiNode->access);
768     }
769     if (smiType) {
770 	fprintValue(f, indent + INDENT, &smiNode->value, smiType);
771     }
772     fprintFormat(f, indent + INDENT, smiNode->format);
773     fprintUnits(f, indent + INDENT, smiNode->units);
774     if (smiNode->nodekind == SMI_NODEKIND_ROW) {
775 	fprintIndex(f, indent + INDENT, smiNode);
776     }
777     fprintDescription(f, indent + INDENT, smiNode->description);
778     fprintReference(f, indent + INDENT, smiNode->reference);
779 
780 #if 0
781     if (smiNode->nodekind != SMI_NODEKIND_ROW
782 	&& smiNode->nodekind != SMI_NODEKIND_TABLE) {
783 	fprintNodeEndTag(f, indent, tag);
784     }
785 #else
786     fprintNodeEndTag(f, indent, tag);
787 #endif
788 }
789 
790 
791 
fprintNodes(FILE * f,SmiModule * smiModule)792 static void fprintNodes(FILE *f, SmiModule *smiModule)
793 {
794     int		 i;
795     SmiNode	 *smiNode, *lastSmiNode;
796     SmiNodekind  nodekinds;
797 
798     nodekinds =  SMI_NODEKIND_NODE | SMI_NODEKIND_TABLE |
799 	SMI_NODEKIND_ROW | SMI_NODEKIND_COLUMN | SMI_NODEKIND_SCALAR |
800 	SMI_NODEKIND_CAPABILITIES;
801 
802     for (i = 0,
803 	     lastSmiNode = NULL,
804 	     smiNode = smiGetFirstNode(smiModule, nodekinds);
805 	 smiNode;
806 	 i++,
807 	     lastSmiNode = smiNode,
808 	     smiNode = smiGetNextNode(smiNode, nodekinds)) {
809 
810 	if (i == 0) {
811 	    fprintSegment(f, INDENT, "\"nodes\" : {\n", 0);
812 	}
813 
814 	fprintNode(f, 2 * INDENT, smiNode, lastSmiNode);
815     }
816 
817 /*      if (lastSmiNode */
818 /*  	&& lastSmiNode->nodekind == SMI_NODEKIND_COLUMN) { */
819 /*  	printNodeEndTag(3 * INDENT, "row"); */
820 /*          printNodeEndTag(2 * INDENT, "table"); */
821 /*      } */
822 
823     if (i) {
824 	fprintSegment(f, INDENT, "}, # nodes\n\n", 0);
825     }
826 }
827 
828 
829 
fprintNotification(FILE * f,int indent,SmiNode * smiNode)830 static void fprintNotification(FILE *f, int indent, SmiNode *smiNode)
831 {
832     fprintNodeStartTag(f, indent, "notification", smiNode);
833 
834     fprintSegment(f, indent + INDENT, "\"objects\" : {\n", 0);
835     fprintElementList(f, indent + 2 * INDENT, "object",
836 		      smiGetFirstElement(smiNode));
837     fprintSegment(f, indent + INDENT, "},\n", 0);
838     fprintDescription(f, indent + INDENT, smiNode->description);
839     fprintReference(f, indent + INDENT, smiNode->reference);
840 
841     fprintNodeEndTag(f, indent, "notification");
842 }
843 
844 
845 
fprintNotifications(FILE * f,SmiModule * smiModule)846 static void fprintNotifications(FILE *f, SmiModule *smiModule)
847 {
848     SmiNode *smiNode;
849     int	     i;
850 
851     for(i = 0, smiNode = smiGetFirstNode(smiModule, SMI_NODEKIND_NOTIFICATION);
852 	smiNode;
853 	i++, smiNode = smiGetNextNode(smiNode, SMI_NODEKIND_NOTIFICATION)) {
854 
855 	if (i == 0) {
856 	    fprintSegment(f, INDENT, "\"notifications\" : {\n", 0);
857 	}
858 	fprintNotification(f, 2 * INDENT, smiNode);
859     }
860 
861     if (i) {
862 	fprintSegment(f, INDENT, "}, # notifications\n\n", 0);
863     }
864 }
865 
866 
867 
fprintGroup(FILE * f,int indent,SmiNode * smiNode)868 static void fprintGroup(FILE *f, int indent, SmiNode *smiNode)
869 {
870     fprintNodeStartTag(f, indent, "group", smiNode);
871 
872     fprintSegment(f, indent + INDENT, "\"members\" : {\n", 0);
873     fprintElementList(f, indent + 2 * INDENT, "member",
874 		      smiGetFirstElement(smiNode));
875     fprintSegment(f, indent + INDENT, "}, # members\n", 0);
876     fprintDescription(f, indent + INDENT, smiNode->description);
877     fprintReference(f, indent + INDENT, smiNode->reference);
878 
879     fprintNodeEndTag(f, indent, "group");
880 }
881 
882 
883 
fprintGroups(FILE * f,SmiModule * smiModule)884 static void fprintGroups(FILE *f, SmiModule *smiModule)
885 {
886     SmiNode *smiNode;
887     int	     i;
888 
889     for(i = 0, smiNode = smiGetFirstNode(smiModule, SMI_NODEKIND_GROUP);
890 	smiNode;
891 	i++, smiNode = smiGetNextNode(smiNode, SMI_NODEKIND_GROUP)) {
892 
893 	if (i == 0) {
894 	    fprintSegment(f, INDENT, "\"groups\" : {\n", 0);
895 	}
896 	fprintGroup(f, 2 * INDENT, smiNode);
897     }
898 
899     if (i) {
900 	fprintSegment(f, INDENT, "}, # groups\n\n", 0);
901     }
902 }
903 
904 
905 
fprintComplGroups(FILE * f,int indent,SmiNode * smiNode)906 static void fprintComplGroups(FILE *f, int indent, SmiNode *smiNode)
907 {
908     SmiNode   *optSmiNode;
909     SmiModule *optSmiModule;
910     SmiOption *smiOption;
911 
912     if (! smiGetFirstElement(smiNode) && !smiGetFirstOption(smiNode)) {
913 	return;
914     }
915 
916     fprintSegment(f, indent, "\"requires\" : {\n", 0);
917     fprintElementList(f, indent + INDENT, "mandatory",
918 		      smiGetFirstElement(smiNode));
919 
920     for(smiOption = smiGetFirstOption(smiNode);
921 	smiOption;
922 	smiOption = smiGetNextOption(smiOption)) {
923 	optSmiNode = smiGetOptionNode(smiOption);
924 	optSmiModule = smiGetNodeModule(optSmiNode);
925 	fprintSegment(f, indent + INDENT, "", 0);
926 	fprint(f, "\"%s\" : {\n", optSmiNode->name);
927 	fprintSegment(f, indent + 2*INDENT,
928 		      "\"nodetype\" : \"optional\",\n", 0);
929 	fprintSegment(f, indent + 2*INDENT, "", 0);
930 	fprint(f, "\"module\" : \"%s\",\n", optSmiModule->name);
931 	fprintDescription(f, indent + 2 * INDENT, smiOption->description);
932 	fprintSegment(f, indent + INDENT, "},\n", 0);
933     }
934 
935     fprintSegment(f, indent, "}, # requires\n", 0);
936 }
937 
938 
939 
fprintRefinement(FILE * f,int indent,SmiRefinement * smiRefinement)940 static void fprintRefinement(FILE *f, int indent, SmiRefinement *smiRefinement)
941 {
942     SmiModule *smiModule;
943     SmiNode   *smiNode;
944     SmiType   *smiType;
945 
946     smiNode = smiGetRefinementNode(smiRefinement);
947     smiModule = smiGetNodeModule(smiNode);
948 
949     fprintSegment(f, indent, "", 0);
950     fprint(f, "\"%s\" : {\n", smiNode->name);
951     fprintSegment(f, indent + INDENT, "", 0);
952     fprint(f, "\"module\" : \"%s\",\n", smiModule->name);
953 
954     smiType = smiGetRefinementType(smiRefinement);
955     if (smiType) {
956 	fprintSegment(f, indent + INDENT, "\"syntax\" : {\n", 0);
957 	fprintSegment(f, indent + 2*INDENT, "\"type\" : ", 0);
958 	fprintTypedef(f, indent + 2 * INDENT, smiType);
959 	fprintSegment(f, indent + INDENT, "}, # syntax\n", 0);
960     }
961 
962     smiType = smiGetRefinementWriteType(smiRefinement);
963     if (smiType) {
964 	fprintSegment(f, indent + INDENT, "\"writesyntax\" : {\n", 0);
965 	fprintSegment(f, indent + 2*INDENT, "\"type\" : ", 0);
966 	fprintTypedef(f, indent + 2 * INDENT, smiType);
967 	fprintSegment(f, indent + INDENT, "}, # writesyntax\n", 0);
968     }
969 
970     if (smiRefinement->access != SMI_ACCESS_UNKNOWN) {
971 	fprintAccess(f, indent + INDENT, smiRefinement->access);
972     }
973     fprintDescription(f, indent + INDENT, smiRefinement->description);
974     fprintSegment(f, indent, "},\n", 0);
975 }
976 
977 
978 
fprintRefinements(FILE * f,int indent,SmiNode * smiNode)979 static void fprintRefinements(FILE *f, int indent, SmiNode *smiNode)
980 {
981     SmiRefinement *smiRefinement;
982     int            i;
983 
984     for(i = 0, smiRefinement = smiGetFirstRefinement(smiNode);
985 	smiRefinement;
986 	i++, smiRefinement = smiGetNextRefinement(smiRefinement)) {
987 
988     	if (!i) {
989 	    fprintSegment(f, indent, "\"refinements\" : {\n", 0);
990 	}
991 
992 	fprintRefinement(f, indent + INDENT, smiRefinement);
993     }
994 
995     if (i) {
996 	fprintSegment(f, indent, "}, # refinements\n\n", 0);
997     }
998 }
999 
1000 
1001 
fprintCompliance(FILE * f,int indent,SmiNode * smiNode)1002 static void fprintCompliance(FILE *f, int indent, SmiNode *smiNode)
1003 {
1004     fprintNodeStartTag(f, indent, "compliance", smiNode);
1005 
1006     fprintDescription(f, indent + INDENT, smiNode->description);
1007     fprintReference(f, indent + INDENT, smiNode->reference);
1008     fprintComplGroups(f, indent + INDENT, smiNode);
1009     fprintRefinements(f, indent + INDENT, smiNode);
1010 
1011     fprintNodeEndTag(f, indent, "compliance");
1012 }
1013 
1014 
1015 
fprintCompliances(FILE * f,SmiModule * smiModule)1016 static void fprintCompliances(FILE *f, SmiModule *smiModule)
1017 {
1018     SmiNode *smiNode;
1019     int      i;
1020 
1021     for(i = 0, smiNode = smiGetFirstNode(smiModule, SMI_NODEKIND_COMPLIANCE);
1022 	smiNode;
1023 	i++, smiNode = smiGetNextNode(smiNode, SMI_NODEKIND_COMPLIANCE)) {
1024 
1025 	if (!i) {
1026 	    fprintSegment(f, INDENT, "\"compliances\" : {\n", 0);
1027 	}
1028 
1029 	fprintCompliance(f, 2 * INDENT, smiNode);
1030     }
1031 
1032     if (i) {
1033 	fprintSegment(f, INDENT, "}, # compliances\n\n", 0);
1034     }
1035 }
1036 
1037 
1038 
dumpPythonModule(FILE * f,SmiModule * smiModule)1039 static void dumpPythonModule(FILE *f, SmiModule *smiModule)
1040 {
1041     if (! silent) {
1042 	fprint(f, "# python version 1.0\t\t\t\t\t\tDO NOT EDIT\n#\n");
1043 	fprint(f, "# Generated by smidump version "
1044 	       SMI_VERSION_STRING ":\n#\n");
1045 	fprintf(f, "#   smidump -f python %s\n\n", smiModule->name);
1046     }
1047 
1048     fprint(f, "FILENAME = \"%s\"\n\n", smiModule->path);
1049 
1050     fprint(f, "MIB = {\n");
1051     fprintSegment(f, INDENT, "", 0);
1052     fprint(f, "\"moduleName\" : \"%s\",\n\n", smiModule->name);
1053 
1054     fprintModule(f, smiModule);
1055     fprintImports(f, smiModule);
1056     fprintTypedefs(f, smiModule);
1057     fprintNodes(f, smiModule);
1058     fprintNotifications(f, smiModule);
1059     fprintGroups(f, smiModule);
1060     fprintCompliances(f, smiModule);
1061 
1062     fprint(f, "}\n");
1063 }
1064 
1065 
1066 
dumpPython(int modc,SmiModule ** modv,int flags,char * output)1067 static void dumpPython(int modc, SmiModule **modv, int flags, char *output)
1068 {
1069     int  i;
1070     FILE *f = stdout;
1071 
1072     silent = (flags & SMIDUMP_FLAG_SILENT);
1073 
1074     if (output) {
1075 	f = fopen(output, "w");
1076 	if (!f) {
1077 	    fprintf(stderr, "smidump: cannot open %s for writing: ", output);
1078 	    perror(NULL);
1079 	    exit(1);
1080 	}
1081     }
1082 
1083     for (i = 0; i < modc; i++) {
1084 	dumpPythonModule(f, modv[i]);
1085     }
1086 
1087     if (fflush(f) || ferror(f)) {
1088 	perror("smidump: write error");
1089 	exit(1);
1090     }
1091 
1092     if (output) {
1093 	fclose(f);
1094     }
1095 }
1096 
1097 
1098 
initPython()1099 void initPython()
1100 {
1101     static SmidumpDriver driver = {
1102 	"python",
1103 	dumpPython,
1104 	0,
1105 	SMIDUMP_DRIVER_CANT_UNITE,
1106 	"Python MIB dictionaries",
1107 	NULL,
1108 	NULL
1109     };
1110 
1111     smidumpRegisterDriver(&driver);
1112 }
1113