1 /*
2 * dump-xsd.c --
3 *
4 * Operations to dump SMI module information as XML schema definitions.
5 *
6 * Copyright (c) 2001 J. Schoenwaelder, Technical University of Braunschweig.
7 * (c) 2002 T. Klie, Technical University of Braunschweig.
8 * (c) 2002 F. Strauss, Technical University of Braunschweig.
9 * (c) 2007 T. Klie, Technical University of Braunschweig.
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-xsd.c 8090 2008-04-18 12:56:29Z strauss $
15 */
16
17 #include <config.h>
18
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include <stdarg.h>
22 #include <string.h>
23 #include <ctype.h>
24 #include <time.h>
25 #ifdef HAVE_WIN_H
26 #include "win.h"
27 #endif
28
29 #include "smi.h"
30 #include "smidump.h"
31 #include "fortopat.h"
32
33
34 #define INDENT 2 /* indent factor */
35
36 static int ind = 0;
37
38 #ifndef MIN
39 #define MIN(a,b) ((a)) < ((b)) ? ((a)) : ((b))
40 #endif /* #ifndef MIN */
41
42 static char *schemaLocation = "http://www.ibr.cs.tu-bs.de/projects/libsmi/xsd/";
43 static int container = 0;
44 static char *containerBasename = "container";
45 static int *nestAugmentedTables = 0;
46 static int *nestSubtables = 0;
47
48 typedef struct XmlEscape {
49 char character;
50 char *escape;
51 } XmlEscape;
52
53 static XmlEscape xmlEscapes [] = {
54 { '<', "<" },
55 { '>', ">" },
56 { '&', "&" },
57 { 0, NULL }
58 };
59
60 typedef struct TypePrefix {
61 char *type;
62 char *prefix;
63 struct TypePrefix *next;
64 } TypePrefix;
65
66 static TypePrefix *typePrefixes = NULL;
67
68
69
70 /* some forward declarations */
71 static void fprintElement( FILE *f, SmiNode *smiNode, SmiNode *parentNode );
72 static char* getTypePrefix( char *typeName );
73
getStringBasetype(SmiBasetype basetype)74 static char *getStringBasetype(SmiBasetype basetype)
75 {
76 return
77 (basetype == SMI_BASETYPE_UNKNOWN) ? "<UNKNOWN>" :
78 (basetype == SMI_BASETYPE_OCTETSTRING) ? "OctetString" :
79 (basetype == SMI_BASETYPE_OBJECTIDENTIFIER) ? "ObjectIdentifier" :
80 (basetype == SMI_BASETYPE_UNSIGNED32) ? "Unsigned32" :
81 (basetype == SMI_BASETYPE_INTEGER32) ? "Integer32" :
82 (basetype == SMI_BASETYPE_UNSIGNED64) ? "Unsigned64" :
83 (basetype == SMI_BASETYPE_INTEGER64) ? "Integer64" :
84 (basetype == SMI_BASETYPE_FLOAT32) ? "Float32" :
85 (basetype == SMI_BASETYPE_FLOAT64) ? "Float64" :
86 (basetype == SMI_BASETYPE_FLOAT128) ? "Float128" :
87 (basetype == SMI_BASETYPE_ENUM) ? "Enumeration" :
88 (basetype == SMI_BASETYPE_BITS) ? "Bits" :
89 "<unknown>";
90 }
91
getStringStatus(SmiStatus status)92 static char* getStringStatus(SmiStatus status)
93 {
94 char *statStr;
95
96 switch( status ) {
97 case SMI_STATUS_CURRENT:
98 statStr = "current";
99 break;
100 case SMI_STATUS_DEPRECATED:
101 statStr = "deprecated";
102 break;
103 case SMI_STATUS_OBSOLETE:
104 statStr = "obsolete";
105 break;
106 case SMI_STATUS_MANDATORY:
107 statStr = "mandatory";
108 break;
109 case SMI_STATUS_OPTIONAL:
110 statStr = "optional";
111 break;
112 case SMI_STATUS_UNKNOWN:
113 default:
114 statStr = "unknown";
115 break;
116 }
117 return statStr;
118 }
119
getStringAccess(SmiAccess smiAccess)120 static char* getStringAccess( SmiAccess smiAccess )
121 {
122 switch( smiAccess ) {
123 case SMI_ACCESS_NOT_IMPLEMENTED: return "not-implemented";
124 case SMI_ACCESS_NOT_ACCESSIBLE : return "not-accessible";
125 case SMI_ACCESS_NOTIFY : return "notify";
126 case SMI_ACCESS_READ_ONLY : return "read-only";
127 case SMI_ACCESS_READ_WRITE : return "read-write";
128 case SMI_ACCESS_UNKNOWN:
129 default: return "unknown";
130 }
131 }
132 #if 0
133 static char
134 *getStringValue(SmiValue *valuePtr, SmiType *typePtr)
135 {
136 static char s[1024];
137 char ss[9];
138 int n;
139 unsigned int i;
140 SmiNamedNumber *nn;
141 SmiNode *nodePtr;
142
143 s[0] = 0;
144
145 switch (valuePtr->basetype) {
146 case SMI_BASETYPE_UNSIGNED32:
147 sprintf(s, "%lu", valuePtr->value.unsigned32);
148 break;
149 case SMI_BASETYPE_INTEGER32:
150 sprintf(s, "%ld", valuePtr->value.integer32);
151 break;
152 case SMI_BASETYPE_UNSIGNED64:
153 sprintf(s, UINT64_FORMAT, valuePtr->value.unsigned64);
154 break;
155 case SMI_BASETYPE_INTEGER64:
156 sprintf(s, INT64_FORMAT, valuePtr->value.integer64);
157 break;
158 case SMI_BASETYPE_FLOAT32:
159 case SMI_BASETYPE_FLOAT64:
160 case SMI_BASETYPE_FLOAT128:
161 break;
162 case SMI_BASETYPE_ENUM:
163 for (nn = smiGetFirstNamedNumber(typePtr); nn;
164 nn = smiGetNextNamedNumber(nn)) {
165 if (nn->value.value.unsigned32 == valuePtr->value.unsigned32)
166 break;
167 }
168 if (nn) {
169 sprintf(s, "%s", nn->name);
170 } else {
171 sprintf(s, "%ld", valuePtr->value.integer32);
172 }
173 break;
174 case SMI_BASETYPE_OCTETSTRING:
175 for (i = 0; i < valuePtr->len; i++) {
176 if (!isprint((int)valuePtr->value.ptr[i])) break;
177 }
178 if (i == valuePtr->len) {
179 sprintf(s, "\"%s\"", valuePtr->value.ptr);
180 } else {
181 sprintf(s, "0x%*s", 2 * valuePtr->len, "");
182 for (i=0; i < valuePtr->len; i++) {
183 sprintf(ss, "%02x", valuePtr->value.ptr[i]);
184 strncpy(&s[2+2*i], ss, 2);
185 }
186 }
187 break;
188 case SMI_BASETYPE_BITS:
189 sprintf(s, "(");
190 for (i = 0, n = 0; i < valuePtr->len * 8; i++) {
191 if (valuePtr->value.ptr[i/8] & (1 << (7-(i%8)))) {
192 if (n)
193 sprintf(&s[strlen(s)], ", ");
194 n++;
195 for (nn = smiGetFirstNamedNumber(typePtr); nn;
196 nn = smiGetNextNamedNumber(nn)) {
197 if (nn->value.value.unsigned32 == i)
198 break;
199 }
200 if (nn) {
201 sprintf(&s[strlen(s)], "%s", nn->name);
202 } else {
203 sprintf(s, "%d", i);
204 }
205 }
206 }
207 sprintf(&s[strlen(s)], ")");
208 break;
209 case SMI_BASETYPE_UNKNOWN:
210 break;
211 case SMI_BASETYPE_OBJECTIDENTIFIER:
212 nodePtr = smiGetNodeByOID(valuePtr->len, valuePtr->value.oid);
213 if (nodePtr) {
214 sprintf(s, "%s", nodePtr->name);
215 } else {
216 strcpy(s, "");
217 for (i=0; i < valuePtr->len; i++) {
218 if (i) strcat(s, ".");
219 sprintf(&s[strlen(s)], "%u", valuePtr->value.oid[i]);
220 }
221 }
222 break;
223 }
224
225 return s;
226 }
227 #endif /* 0 */
228
smiPow(int base,unsigned int exponent)229 static int smiPow( int base, unsigned int exponent )
230 {
231 unsigned int i;
232 int ret = 1;
233
234 if( exponent == 0 ) {
235 return 1;
236 }
237
238 for( i = 0; i < exponent; i++ ) {
239 ret *= base;
240 }
241 return ret;
242 }
243
fprintSegment(FILE * f,int relindent,char * fmt,...)244 static void fprintSegment(FILE *f, int relindent, char *fmt, ...)
245 {
246 va_list ap;
247
248 va_start(ap, fmt);
249
250 if ((ind == 0) || (ind + relindent == 0)) {
251 ind += relindent;
252 } else {
253 if (relindent < 0) ind += relindent;
254 fprintf(f, "%*c", ind * INDENT, ' ');
255 if (relindent > 0) ind += relindent;
256 }
257 vfprintf(f, fmt, ap);
258
259 va_end(ap);
260 }
261
262
263
fprintMultilineString(FILE * f,const char * s)264 static void fprintMultilineString(FILE *f, const char *s)
265 {
266 int i, j, len;
267
268 fprintSegment(f, 0, "");
269 if (s) {
270 len = strlen(s);
271 for (i=0; i < len; i++) {
272 for (j = 0; xmlEscapes[j].character; j++) {
273 if (xmlEscapes[j].character == s[i]) break;
274 }
275 if (xmlEscapes[j].character) {
276 fputs(xmlEscapes[j].escape, f);
277 } else {
278 putc(s[i], f);
279 }
280 if (s[i] == '\n') {
281 fprintSegment(f, 0, "");
282 }
283 }
284 }
285 }
286
287
288
fprintDocumentation(FILE * f,const char * description)289 static void fprintDocumentation(FILE *f, const char *description)
290 {
291 if (description) {
292 fprintSegment(f, 1, "<xsd:documentation>\n");
293 fprintMultilineString(f, description);
294 fprintf(f, "\n");
295 fprintSegment(f, -1, "</xsd:documentation>\n");
296 }
297 }
298
fprintNamedNumber(FILE * f,SmiNamedNumber * nn)299 static void fprintNamedNumber( FILE *f, SmiNamedNumber *nn )
300 {
301 fprintSegment( f, 1, "<xsd:enumeration value=\"%s\">\n", nn->name );
302 fprintSegment( f, 1, "<xsd:annotation>\n");
303 fprintSegment( f, 1, "<xsd:appinfo>\n");
304 fprintSegment( f, 0, "<intVal>%d</intVal>\n",
305 (int)nn->value.value.integer32 );
306 fprintSegment( f, -1, "</xsd:appinfo>\n");
307 fprintSegment( f, -1, "</xsd:annotation>\n");
308 fprintSegment( f, -1, "</xsd:enumeration>\n");
309 }
310
311
fprintStdRestHead(FILE * f,SmiType * smiType)312 static void fprintStdRestHead( FILE *f, SmiType *smiType )
313 {
314 char *baseTypeName = getStringBasetype(smiType->basetype);
315 char *prefix = getTypePrefix( baseTypeName );
316
317 if( prefix ) {
318 fprintSegment(f, 1, "<xsd:restriction base=\"%s:%s\">\n",
319 prefix, baseTypeName );
320 }
321 else {
322 fprintSegment(f, 1, "<xsd:restriction base=\"%s\">\n", baseTypeName );
323 }
324 }
325
326
fprintHexOrAsciiType(FILE * f,SmiType * parent,SmiInteger32 minLength,SmiInteger32 maxLength,char * name,int hex)327 static void fprintHexOrAsciiType( FILE *f, SmiType *parent,
328 SmiInteger32 minLength,
329 SmiInteger32 maxLength,
330 char *name, int hex )
331 {
332 char *prefix = parent ? getTypePrefix( parent->name ) : NULL;
333 char *typeFlag = hex ? "Hex" : "Ascii";
334
335 if( name ) {
336 fprintSegment( f, 1, "<xsd:simpleType name=\"%s%s\">\n",
337 name, typeFlag );
338 } else {
339 fprintSegment( f, 1, "<xsd:simpleType>\n");
340 }
341 if( prefix ) {
342 fprintSegment( f, 1, "<xsd:restriction base=\"%s:%s%s\">\n",
343 prefix, parent->name, typeFlag );
344 }
345 else {
346 fprintSegment( f, 1, "<xsd:restriction base=\"%s%s\">\n",
347 parent->name, typeFlag );
348 }
349
350 if( minLength > 0 ) {
351 fprintSegment( f, 0, "<xsd:minLength value=\"%d\"/>\n",
352 (int)minLength );
353 }
354 if( maxLength > -1 ) {
355 fprintSegment( f, 0, "<xsd:maxLength value=\"%d\"/>\n",
356 (int)maxLength );
357 }
358
359 fprintSegment( f, -1, "</xsd:restriction>\n");
360 fprintSegment( f, -1, "</xsd:simpleType>\n");
361 }
362
363
dhInParent(SmiType * smiType)364 static int dhInParent( SmiType *smiType )
365 {
366 SmiType *parent = smiGetParentType( smiType );
367
368 if( smiType->format && parent->format ) {
369 return ! strcmp( smiType->format, parent->format );
370 }
371 return 0;
372 }
373
374 #define MD_DH_INT_NORMAL 1
375 #define MD_DH_INT_DECIMAL 2
376 #define MD_DH_INT_BIN 3
377 #define MD_DH_INT_OCT 4
378 #define MD_DH_INT_HEX 5
379
380 /* parse a (integer) display hint and specify the offset, if used */
getIntDHType(char * hint,int * offset)381 static int getIntDHType( char *hint, int *offset )
382 {
383 switch( hint[ 0 ] ) {
384
385 case 'd':
386 if( hint[1] ) {
387 *offset = 0;
388 *offset = atoi( &hint[2] );
389 return MD_DH_INT_DECIMAL;
390 }
391 return MD_DH_INT_NORMAL;
392
393 case 'b':
394 /* binary value */
395 return MD_DH_INT_BIN;
396 case 'o':
397 /* octet value */
398 return MD_DH_INT_OCT;
399 case 'x':
400 /* hex value */
401 return MD_DH_INT_HEX;
402 default:
403 /* should not occur */
404 return 0;
405 }
406 }
407
408
fprintRestriction(FILE * f,SmiType * smiType)409 static void fprintRestriction(FILE *f, SmiType *smiType)
410 {
411 SmiRange *smiRange;
412
413 /* print ranges etc. */
414 switch( smiType->basetype ) {
415
416 case SMI_BASETYPE_INTEGER32:
417 {
418 SmiInteger32 min = SMI_BASETYPE_INTEGER32_MIN;
419 SmiInteger32 max = SMI_BASETYPE_INTEGER32_MAX;
420 int offset = 0, useDecPoint = 0;
421
422 if( smiType->format ) {
423 /* we have a display hint here, so check if we have to use
424 a decimal point */
425 useDecPoint =
426 getIntDHType( smiType->format, &offset ) == MD_DH_INT_DECIMAL;
427 /* xxx: other display hint types (binary, oct, hex) */
428 }
429
430 if( useDecPoint ) {
431 fprintSegment( f, 1, "<xsd:restriction base=\"xsd:decimal\">\n");
432 fprintSegment( f, 0, "<xsd:fractionDigits value=\"%d\"/>\n", offset );
433 }
434 else {
435 fprintStdRestHead( f, smiType );
436 }
437
438 smiRange = smiGetFirstRange( smiType );
439 while( smiRange ) {
440 if( min == SMI_BASETYPE_INTEGER32_MIN ||
441 smiRange->minValue.value.integer32 < min ) {
442 min = smiRange->minValue.value.integer32;
443 }
444 if( max == SMI_BASETYPE_INTEGER32_MAX ||
445 smiRange->maxValue.value.integer32 > max ) {
446 max = smiRange->maxValue.value.integer32;
447 }
448 smiRange = smiGetNextRange( smiRange );
449 }
450
451 /* print minimu value */
452 if( useDecPoint ) {
453 fprintSegment( f, 0, "<xsd:minInclusive value=\"%d.%d\"/>\n",
454 (int)min / smiPow( 10, offset ),
455 abs( (int)min % smiPow( 10, offset ) ) );
456 } else {
457 fprintSegment( f, 0, "<xsd:minInclusive value=\"%d\"/>\n",
458 (int)min );
459 }
460
461 /* print maximum value */
462 if( useDecPoint ) {
463 fprintSegment( f, 0, "<xsd:maxInclusive value=\"%d.%d\"/>\n",
464 (int)max / smiPow( 10, offset ),
465 abs( (int)max % smiPow( 10, offset ) ) );
466 } else {
467 fprintSegment( f, 0, "<xsd:maxInclusive value=\"%d\"/>\n",
468 (int)max );
469 }
470
471 fprintSegment(f, -1, "</xsd:restriction>\n");
472 break;
473 }
474
475 case SMI_BASETYPE_OCTETSTRING:
476 {
477 SmiInteger32 minLength, maxLength;
478 unsigned int numSubRanges = 0;
479
480 minLength = 0;
481 maxLength = -1;
482
483 /* get range details */
484 for( smiRange = smiGetFirstRange( smiType );
485 smiRange;
486 smiRange = smiGetNextRange( smiRange ) ) {
487 if( minLength == 0 ||
488 smiRange->minValue.value.integer32 < minLength ) {
489 minLength = smiRange->minValue.value.integer32;
490 }
491 if( smiRange->maxValue.value.integer32 > maxLength ) {
492 maxLength = smiRange->maxValue.value.integer32;
493 }
494 numSubRanges++;
495 }
496
497
498
499 if( smiType->format &&
500 ( smiType->decl == SMI_DECL_IMPLICIT_TYPE ||
501 smiType->decl == SMI_DECL_TEXTUALCONVENTION ) &&
502 ! dhInParent( smiType ) ) {
503 /*
504 fprintStringUnion( f, indent, smiType,
505 minLength, maxLength, 0, NULL );
506 */
507 char *pattern;
508
509 fprintSegment( f, 1, "<xsd:restriction base=\"xsd:string\">\n" );
510
511 /* create regexp */
512 pattern = smiFormatToPattern(smiType->format,
513 smiGetFirstRange(smiType));
514 if (pattern) {
515 fprintSegment( f, 0, "<xsd:pattern value=\"%s\"/>\n", pattern);
516 xfree(pattern);
517 }
518 else {
519 fprintf( f, "<!-- Warning: repeat in display hint. "
520 "This feature is not supported. -->\n" );
521 }
522 fprintSegment( f, -1, "</xsd:restriction>\n");
523 }
524 else {
525 SmiType *parent = smiGetParentType( smiType );
526 /*
527 fprintStringUnion( f, indent, smiType,
528 minLength, maxLength, secondTime,
529 smiType->name );
530 */
531 if( parent ) {
532 if( parent->format ) {
533 char *pattern;
534
535 pattern = smiFormatToPattern(parent->format,
536 smiGetFirstRange(smiType));
537 if (pattern) {
538 fprintSegment( f, 1, "<xsd:restriction base=\"xsd:string\">\n" );
539 fprintSegment(f, 0, "<xsd:pattern value=\"%s\"/>\n",
540 pattern);
541 fprintSegment( f, -1, "</xsd:restriction>\n");
542 xfree(pattern);
543 }
544 }
545
546
547 else if( smiType->name &&
548 ! strcmp( smiType->name, "IpAddress" ) ) {
549 SmiUnsigned32 lengths[] = {4, 4};
550 lengths[0] = 4; lengths[1] = 4;
551 fprintSegment( f, 1, "<xsd:restriction base=\"xsd:string\">\n" );
552 fprintSegment( f, 0, "<xsd:pattern "
553 "value=\"(0|[1-9](([0-9]){0,2}))."
554 "(0|[1-9](([0-9]){0,2}))."
555 "(0|[1-9](([0-9]){0,2}))."
556 "(0|[1-9](([0-9]){0,2}))\"/>\n" );
557 fprintSegment( f, -1, "</xsd:restriction>\n");
558 }
559
560 else {
561
562
563 char *prefix = getTypePrefix( parent->name );
564
565 if( prefix ) {
566 fprintSegment( f, 1, "<xsd:restriction base=\"%s:%s\">\n",
567 prefix, parent->name );
568 } else {
569 fprintSegment( f, 1, "<xsd:restriction base=\"%s\">\n",
570 parent->name );
571 }
572
573 /* print length restriction */
574 if( minLength > 0 )
575 fprintSegment( f, 0, "<xsd:minLength value=\"%d\"/>\n",
576 (int)minLength );
577 if( maxLength > -1 )
578 fprintSegment( f, 0, "<xsd:maxLength value=\"%d\"/>\n",
579 (int)maxLength );
580 fprintSegment( f, -1, "</xsd:restriction>\n");
581 }
582
583
584 }
585 }
586 break;
587 }
588
589 case SMI_BASETYPE_FLOAT128:
590 {
591 /* SmiFloat128 min, max; */
592 fprintStdRestHead( f, smiType );
593
594 /* xxx, only SMIng */
595 break;
596 }
597
598 case SMI_BASETYPE_FLOAT64:
599 {
600 /* SmiFloat64 min,max;*/
601 fprintStdRestHead( f, smiType );
602
603 /* xxx, only SMIng */
604 break;
605 }
606
607 case SMI_BASETYPE_FLOAT32:
608 {
609 /* SmiFloat32 min,max;*/
610 fprintStdRestHead( f, smiType );
611
612 /* xxx, only SMIng */
613 break;
614 }
615
616 case SMI_BASETYPE_INTEGER64:
617 {
618 /* SmiInteger64 min,max;*/
619 fprintStdRestHead( f, smiType );
620
621 /* xxx, only SMIng */
622 break;
623 }
624
625 case SMI_BASETYPE_UNSIGNED64:
626 {
627 SmiUnsigned64 min, max;
628
629 min = SMI_BASETYPE_UNSIGNED64_MIN;
630 max = SMI_BASETYPE_UNSIGNED64_MAX;
631
632 fprintStdRestHead( f, smiType );
633
634 smiRange = smiGetFirstRange( smiType );
635 while( smiRange ) {
636 if( smiRange->minValue.value.unsigned64 < min ) {
637 min = smiRange->minValue.value.unsigned64;
638 }
639 if( smiRange->maxValue.value.unsigned64 > max ) {
640 max = smiRange->maxValue.value.unsigned64;
641 }
642 smiRange = smiGetNextRange( smiRange );
643 }
644 fprintSegment( f, 0, "<xsd:minInclusive value=\"%lu\"/>\n",
645 (unsigned long)min );
646
647 fprintSegment( f, 0, "<xsd:maxInclusive value=\"%lu\"/>\n",
648 (unsigned long)max );
649
650 fprintSegment(f, -1, "</xsd:restriction>\n");
651
652 break;
653 }
654
655 case SMI_BASETYPE_UNSIGNED32:
656 {
657 SmiUnsigned32 min, max;
658
659 min = 0;
660 max = 4294967295UL;
661
662 fprintStdRestHead( f, smiType );
663
664 smiRange = smiGetFirstRange( smiType );
665 while( smiRange ) {
666 if( smiRange->minValue.value.unsigned32 < min ) {
667 min = smiRange->minValue.value.unsigned32;
668 }
669 if( smiRange->maxValue.value.unsigned32 > max ) {
670 max = smiRange->maxValue.value.unsigned32;
671 }
672 smiRange = smiGetNextRange( smiRange );
673 }
674 fprintSegment( f, 0, "<xsd:minInclusive value=\"%u\"/>\n",
675 (unsigned int)min );
676
677 fprintSegment( f, 0, "<xsd:maxInclusive value=\"%u\"/>\n",
678 (unsigned int)max );
679
680 fprintSegment(f, -1, "</xsd:restriction>\n");
681 break;
682 }
683
684 case SMI_BASETYPE_ENUM:
685 case SMI_BASETYPE_BITS:
686 {
687 SmiNamedNumber *nn;
688
689 fprintSegment(f, 1, "<xsd:restriction base=\"xsd:NMTOKEN\">\n");
690
691 /* iterate named numbers */
692 for( nn = smiGetFirstNamedNumber( smiType );
693 nn;
694 nn = smiGetNextNamedNumber( nn ) ) {
695 fprintNamedNumber( f, nn );
696 }
697 fprintSegment(f, -1, "</xsd:restriction>\n");
698 break;
699 }
700
701 case SMI_BASETYPE_OBJECTIDENTIFIER:
702 fprintSegment( f, 0,
703 "<xsd:restriction base=\"smi:ObjectIdentifier\"/>\n");
704 break;
705 case SMI_BASETYPE_UNKNOWN:
706 /* should not occur */
707 break;
708 case SMI_BASETYPE_POINTER:
709 /* TODO */
710 break;
711 }
712 }
713
714
getNamedNumberCount(SmiType * smiType)715 static unsigned int getNamedNumberCount( SmiType *smiType )
716 {
717 SmiNamedNumber *nn;
718 unsigned int ret = 0;
719
720 for( nn = smiGetFirstNamedNumber( smiType );
721 nn;
722 nn = smiGetNextNamedNumber( nn ) ) {
723 ret++;
724 }
725
726 return ret;
727 }
728
729
fprintBitList(FILE * f,SmiType * smiType)730 static void fprintBitList( FILE *f, SmiType *smiType )
731 {
732 fprintSegment( f, 1, "<xsd:restriction>\n" );
733 fprintSegment( f, 1, "<xsd:simpleType>\n" );
734 fprintSegment( f, 1, "<xsd:list>\n" );
735 fprintSegment( f, 1, "<xsd:simpleType>\n" );
736 fprintRestriction( f, smiType );
737 fprintSegment( f, -1, "</xsd:simpleType>\n" );
738 fprintSegment( f, -1, "</xsd:list>\n" );
739 fprintSegment( f, -1, "</xsd:simpleType>\n");
740 fprintSegment( f, 0, "<xsd:maxLength value=\"%d\"/>\n",
741 getNamedNumberCount( smiType ) );
742 fprintSegment( f, -1, "</xsd:restriction>\n");
743 }
getNumSubRanges(SmiType * smiType)744 static int getNumSubRanges( SmiType *smiType )
745 {
746 SmiRange *smiRange;
747 int num = 0;
748
749 for( smiRange = smiGetFirstRange( smiType );
750 smiRange;
751 smiRange = smiGetNextRange( smiRange ) ) {
752 num++;
753 }
754
755 return num;
756 }
757
758
fprintSubRangeType(FILE * f,SmiRange * smiRange,SmiType * smiType)759 static void fprintSubRangeType( FILE *f,
760 SmiRange *smiRange, SmiType *smiType )
761 {
762
763 switch( smiType->basetype ) {
764
765 case SMI_BASETYPE_UNSIGNED32: {
766 SmiUnsigned32 min, max;
767
768 min = 0;
769 max = 4294967295UL;
770
771 if( smiRange->minValue.value.unsigned32 < min ) {
772 min = smiRange->minValue.value.unsigned32;
773 }
774 if( smiRange->maxValue.value.unsigned32 > max ) {
775 max = smiRange->maxValue.value.unsigned32;
776 }
777
778 fprintSegment( f, 1, "<xsd:simpleType>\n");
779 fprintStdRestHead( f, smiType );
780
781 fprintSegment( f, 0, "<xsd:minInclusive value=\"%u\"/>\n",
782 (unsigned int)min );
783
784 fprintSegment( f, 0, "<xsd:maxInclusive value=\"%u\"/>\n",
785 (unsigned int)max );
786
787 fprintSegment(f, -1, "</xsd:restriction>\n");
788 fprintSegment(f, -1, "</xsd:simpleType>\n");
789 break;
790 }
791
792 case SMI_BASETYPE_INTEGER32: {
793 SmiInteger32 min, max;
794
795 min = SMI_BASETYPE_INTEGER32_MIN;
796 max = SMI_BASETYPE_INTEGER32_MAX;
797
798 if( min == SMI_BASETYPE_INTEGER32_MIN ||
799 smiRange->minValue.value.integer32 < min ) {
800 min = smiRange->minValue.value.integer32;
801 }
802 if( max == SMI_BASETYPE_INTEGER32_MAX ||
803 smiRange->maxValue.value.integer32 > max ) {
804 max = smiRange->maxValue.value.integer32;
805 }
806
807 fprintSegment( f, 1, "<xsd:simpleType>\n");
808 fprintStdRestHead( f, smiType );
809
810 fprintSegment( f, 0, "<xsd:minInclusive value=\"%d\"/>\n", (int)min );
811
812 fprintSegment( f, 0, "<xsd:maxInclusive value=\"%d\"/>\n", (int)max );
813
814 fprintSegment(f, -1, "</xsd:restriction>\n");
815 fprintSegment(f, -1, "</xsd:simpleType>\n");
816 break;
817
818 }
819
820 case SMI_BASETYPE_OCTETSTRING: {
821 SmiInteger32 minLength, maxLength;
822
823 minLength = 0;
824 maxLength = -1;
825
826 if( smiRange->minValue.value.integer32 < minLength ) {
827 minLength = smiRange->minValue.value.integer32;
828 }
829 if( smiRange->maxValue.value.integer32 > maxLength ) {
830 maxLength = smiRange->maxValue.value.integer32;
831 }
832 fprintHexOrAsciiType( f, smiType,
833 minLength, maxLength, NULL, 1 );
834 break;
835 }
836
837 case SMI_BASETYPE_FLOAT128:
838 {
839 /* SmiFloat128 min, max;
840 xxx, only SMIng */
841 break;
842 }
843
844 case SMI_BASETYPE_FLOAT64:
845 {
846 /* SmiFloat64 min,max;
847 xxx, only SMIng */
848 break;
849 }
850
851 case SMI_BASETYPE_FLOAT32:
852 {
853 /* SmiFloat32 min,max;
854 xxx, only SMIng */
855 break;
856 }
857
858 case SMI_BASETYPE_INTEGER64:
859 {
860 /* SmiInteger64 min,max;
861 xxx, only SMIng */
862 break;
863 }
864
865 case SMI_BASETYPE_UNSIGNED64:
866 {
867 SmiUnsigned64 min, max;
868
869 min = SMI_BASETYPE_UNSIGNED64_MIN;
870 max = SMI_BASETYPE_UNSIGNED64_MAX;
871
872 if( smiRange->minValue.value.unsigned64 < min ) {
873 min = smiRange->minValue.value.unsigned64;
874 }
875 if( smiRange->maxValue.value.unsigned32 > max ) {
876 max = smiRange->maxValue.value.unsigned64;
877 }
878
879 fprintSegment( f, 1, "<xsd:simpleType>\n");
880 fprintStdRestHead( f, smiType );
881
882 fprintSegment( f, 0, "<xsd:minInclusive value=\"%lu\"/>\n",
883 (unsigned long)min );
884
885 fprintSegment( f, 0, "<xsd:maxInclusive value=\"%lu\"/>\n",
886 (unsigned long)max );
887
888 fprintSegment(f, -1, "</xsd:restriction>\n");
889 fprintSegment(f, -1, "</xsd:simpleType>\n");
890 break;
891 }
892
893 case SMI_BASETYPE_ENUM:
894 case SMI_BASETYPE_BITS:
895 case SMI_BASETYPE_OBJECTIDENTIFIER:
896 case SMI_BASETYPE_UNKNOWN:
897 case SMI_BASETYPE_POINTER:
898 /* should not occur */
899 break;
900
901 }
902 }
903
fprintDisplayHint(FILE * f,char * format)904 static void fprintDisplayHint( FILE *f, char *format )
905 {
906 fprintSegment( f, 0, "<displayHint>%s</displayHint>\n", format );
907 }
908
fprintLengths(FILE * f,SmiType * smiType)909 static void fprintLengths(FILE *f, SmiType *smiType)
910 {
911 SmiRange *smiRange = smiGetFirstRange(smiType);
912
913 if (! smiRange) {
914 return;
915 }
916
917 fprintSegment(f, 1, "<lengths>\n");
918 for (smiRange = smiGetFirstRange(smiType);
919 smiRange; smiRange = smiGetNextRange(smiRange)) {
920 fprintSegment(f, 0, "<length min=\"%u\" max=\"%u\"/>\n",
921 smiRange->minValue.value.unsigned32,
922 smiRange->maxValue.value.unsigned32);
923 }
924 fprintSegment( f, -1, "</lengths>\n");
925 }
926
927
fprintTypedef(FILE * f,SmiType * smiType,const char * name)928 static void fprintTypedef(FILE *f, SmiType *smiType, const char *name)
929 {
930 SmiRange *smiRange;
931 unsigned int numSubRanges = getNumSubRanges( smiType );
932
933 if ( name ) {
934 fprintSegment(f, 1, "<xsd:simpleType name=\"%s\">\n", name);
935 }
936
937 else {
938 /* unnamed simple type */
939 fprintSegment(f, 1, "<xsd:simpleType>\n");
940 }
941
942 if( smiType->description ) {
943 fprintSegment( f, 1, "<xsd:annotation>\n");
944 fprintDocumentation(f, smiType->description);
945 if( smiType->format ) {
946 fprintSegment( f, 1, "<xsd:appinfo>\n");
947 fprintDisplayHint( f, smiType->format );
948 if( smiType->basetype == SMI_BASETYPE_OCTETSTRING ) {
949 fprintLengths( f, smiType );
950 }
951 fprintSegment( f, -1, "</xsd:appinfo>\n");
952 }
953 fprintSegment( f, -1, "</xsd:annotation>\n");
954 }
955
956 if( ( numSubRanges > 1 ) &&
957 ( smiType->basetype != SMI_BASETYPE_OCTETSTRING ) ) {
958
959 fprintSegment( f, 1, "<xsd:union>\n");
960
961 for( smiRange = smiGetFirstRange( smiType );
962 smiRange;
963 smiRange = smiGetNextRange( smiRange ) ) {
964 fprintSubRangeType( f, smiRange, smiType );
965 }
966
967 fprintSegment( f, -1, "</xsd:union>\n");
968 }
969 else if( smiType->basetype == SMI_BASETYPE_BITS ) {
970 fprintBitList( f, smiType );
971 }
972 else {
973 fprintRestriction(f, smiType );
974 }
975 fprintSegment(f, -1, "</xsd:simpleType>\n");
976
977 /* print an empty line after global types */
978 if( smiType->decl != SMI_DECL_IMPLICIT_TYPE && name ) {
979 fprintf( f, "\n" );
980 }
981 }
982
983
getTypePrefix(char * typeName)984 static char* getTypePrefix( char *typeName )
985 {
986 TypePrefix *iterTPr;
987
988 if( !typeName ) {
989 return NULL;
990 }
991
992 for( iterTPr = typePrefixes; iterTPr; iterTPr = iterTPr->next ) {
993 if( ! strcmp( iterTPr->type, typeName ) ) {
994 return iterTPr->prefix;
995 }
996 }
997
998 return NULL;
999 }
1000
1001
fprintAnnotationElem(FILE * f,SmiNode * smiNode)1002 static void fprintAnnotationElem( FILE *f, SmiNode *smiNode ) {
1003 int i;
1004
1005 fprintSegment( f, 1, "<xsd:annotation>\n");
1006 fprintSegment( f, 1, "<xsd:appinfo>\n");
1007
1008 if( smiNode->nodekind == SMI_NODEKIND_ROW &&
1009 ( smiNode->implied || smiNode->create ) ) {
1010 fprintSegment( f, 0, "<flags" );
1011 if( smiNode->implied ) {
1012 fprintf( f, " implied=\"yes\"" );
1013 }
1014 if( smiNode->create ) {
1015 fprintf( f, " create=\"yes\"" );
1016 }
1017 fprintf( f, "/>\n" );
1018 }
1019
1020 fprintSegment( f, 0, "<maxAccess>%s</maxAccess>\n",
1021 getStringAccess( smiNode->access ) );
1022 fprintSegment( f, 0, "<oid>");
1023 for (i = 0; i < smiNode->oidlen; i++) {
1024 fprintf(f, i ? ".%u" : "%u", smiNode->oid[i]);
1025 }
1026 fprintf( f, "</oid>\n" );
1027
1028 fprintSegment( f, 0, "<status>%s</status>\n",
1029 getStringStatus( smiNode->status ) );
1030 if( smiNode->value.basetype != SMI_BASETYPE_UNKNOWN ) {
1031 char *defval = smiRenderValue( &smiNode->value,
1032 smiGetNodeType( smiNode ),
1033 SMI_RENDER_FORMAT | SMI_RENDER_NAME );
1034 fprintSegment( f, 0, "<default>%s</default>\n", defval );
1035
1036 }
1037
1038
1039 if( smiNode->format ) {
1040 fprintDisplayHint( f, smiNode->format );
1041 }
1042
1043 if( smiNode->units ) {
1044 fprintSegment( f, 0, "<units>%s</units>\n", smiNode->units );
1045 }
1046
1047 fprintSegment( f, -1, "</xsd:appinfo>\n");
1048 fprintDocumentation( f, smiNode->description );
1049 fprintSegment( f, -1, "</xsd:annotation>\n");
1050
1051 }
1052
hasChildren(SmiNode * smiNode,SmiNodekind nodekind)1053 static int hasChildren( SmiNode *smiNode, SmiNodekind nodekind )
1054 {
1055 SmiNode *iterNode;
1056 int childNodeCount = 0;
1057
1058 for( iterNode = smiGetFirstChildNode( smiNode );
1059 iterNode;
1060 iterNode = smiGetNextChildNode( iterNode ) ){
1061 if( nodekind & iterNode->nodekind ) {
1062 childNodeCount++;
1063 }
1064 }
1065 return childNodeCount;
1066 }
1067
1068 static void
fprintTypeWithHint(FILE * f,SmiNode * smiNode,SmiType * smiType,char * hint)1069 fprintTypeWithHint( FILE *f, SmiNode *smiNode, SmiType *smiType, char *hint )
1070 {
1071 char *pattern;
1072
1073 fprintSegment( f, 1, "<xsd:simpleType>\n");
1074 fprintSegment( f, 1, "<xsd:annotation>\n");
1075 fprintSegment( f, 1, "<xsd:appinfo>\n");
1076 fprintDisplayHint( f, hint );
1077 fprintSegment( f, -1, "</xsd:appinfo>\n");
1078 fprintSegment( f, -1, "</xsd:annotation>\n");
1079 fprintSegment( f, 1, "<xsd:restriction base=\"xsd:string\">\n");
1080
1081 pattern = smiFormatToPattern(hint, smiGetFirstRange(smiType));
1082 if (pattern) {
1083 fprintSegment( f, 0, "<xsd:pattern value=\"%s\"/>\n", pattern);
1084 xfree(pattern);
1085 }
1086 fprintSegment( f, -1, "</xsd:restriction>\n");
1087 fprintSegment( f, -1, "</xsd:simpleType>\n");
1088 }
1089
1090
getParentDisplayHint(SmiType * smiType)1091 static char *getParentDisplayHint( SmiType *smiType )
1092 {
1093 SmiType *iterType;
1094
1095 for( iterType = smiGetParentType( smiType );
1096 iterType;
1097 iterType = smiGetParentType( iterType ) ) {
1098 if( iterType->format ) {
1099 return iterType->format;
1100 }
1101 }
1102 return NULL;
1103 }
1104
1105
fprintIndexAttr(FILE * f,SmiNode * smiNode,SmiNode * augments)1106 static void fprintIndexAttr( FILE *f, SmiNode *smiNode, SmiNode *augments )
1107 {
1108 char *typeName, *prefix;
1109 SmiType *smiType;
1110
1111 smiType = smiGetNodeType( smiNode );
1112 if( !smiType ) {
1113 /* fprint( f, "<!-- error: no type in %s -->\n", smiNode->name );*/
1114 return;
1115 }
1116
1117 typeName = smiType->name ?
1118 smiType->name :
1119 getStringBasetype( smiType->basetype );
1120 prefix = getTypePrefix( typeName );
1121
1122
1123 if( smiType->basetype == SMI_BASETYPE_BITS ) {
1124 fprintSegment( f, 1, "<xsd:attribute name=\"%s\" type=\"%s%s\" "
1125 "use=\"required\">\n",
1126 smiNode->name,
1127 smiNode->name,
1128 getStringBasetype( smiType->basetype ) );
1129 fprintAnnotationElem( f, smiNode );
1130 }
1131
1132 else if( smiType->basetype == SMI_BASETYPE_OCTETSTRING ) {
1133
1134 if( smiType->decl == SMI_DECL_IMPLICIT_TYPE ) {
1135 char *hint = getParentDisplayHint( smiType );
1136
1137 fprintSegment( f, 1, "<xsd:attribute name=\"%s\" "
1138 "use=\"required\">\n", smiNode->name );
1139 fprintAnnotationElem( f, smiNode );
1140 if( ! hint ) {
1141 fprintTypedef( f, smiType, NULL );
1142 }
1143 else {
1144 fprintTypeWithHint( f, smiNode, smiType, hint );
1145 }
1146 }
1147
1148 else {
1149 if( prefix ) {
1150 fprintSegment( f, 1, "<xsd:attribute name=\"%s\" "
1151 "type=\"%s:%s\" use=\"required\">\n",
1152 smiNode->name, prefix, typeName );
1153 }
1154 else {
1155 fprintSegment( f, 1, "<xsd:attribute name=\"%s\" "
1156 "type=\"%s\" use=\"required\">\n",
1157 smiNode->name, typeName );
1158 }
1159 fprintAnnotationElem( f, smiNode );
1160 }
1161 }
1162
1163 /* check for other (implicit) types */
1164 else if( smiType->decl == SMI_DECL_IMPLICIT_TYPE ) {
1165 fprintSegment( f, 1, "<xsd:attribute name=\"%s\" "
1166 "use=\"required\">\n",
1167 smiNode->name );
1168 fprintAnnotationElem( f, smiNode );
1169 fprintTypedef( f, smiType, NULL );
1170 }
1171
1172 else {
1173 if( prefix ) {
1174 fprintSegment( f, 1,"<xsd:attribute name=\"%s\" type=\"%s:%s\" ",
1175 smiNode->name, prefix, typeName );
1176 fprintf( f, "use=\"required\">\n" );
1177 }
1178 else {
1179 fprintSegment( f, 1, "<xsd:attribute name=\"%s\" type=\"%s\" ",
1180 smiNode->name, typeName );
1181 fprintf( f, "use=\"required\">\n" );
1182 }
1183
1184 if( augments ) {
1185 fprintSegment( f, 1, "<xsd:annotation>\n");
1186 fprintSegment( f, 1, "<xsd:appinfo>\n");
1187 fprintSegment( f, 0, "<augments>%s</augments>\n", augments->name );
1188 fprintSegment( f, -1, "</xsd:appinfo>\n");
1189 fprintSegment( f, -1, "</xsd:annotation>\n");
1190 }
1191 else {
1192 fprintAnnotationElem( f, smiNode );
1193 }
1194 }
1195 fprintSegment( f, -1, "</xsd:attribute>\n");
1196 }
1197
containsIndex(SmiNode * parentNode,SmiNode * idxNode)1198 static int containsIndex( SmiNode *parentNode, SmiNode *idxNode )
1199 {
1200 SmiElement *iterElement;
1201
1202
1203 for( iterElement = smiGetFirstElement( parentNode );
1204 iterElement;
1205 iterElement = smiGetNextElement( iterElement ) ) {
1206 SmiNode *iterNode = smiGetElementNode( iterElement );
1207 if( iterNode == idxNode )
1208 return 1;
1209 }
1210 return 0;
1211 }
1212
fprintIndex(FILE * f,SmiNode * smiNode,SmiNode * augments,SmiNode * parent)1213 static void fprintIndex( FILE *f,
1214 SmiNode *smiNode, SmiNode *augments, SmiNode *parent )
1215 {
1216 SmiNode *iterNode;
1217 SmiElement *iterElem;
1218
1219 /* iterate INDEX columns */
1220 for( iterElem = smiGetFirstElement( smiNode );
1221 iterElem;
1222 iterElem = smiGetNextElement( iterElem ) ) {
1223 iterNode = smiGetElementNode( iterElem );
1224 if( ! parent || (parent && !containsIndex( parent, iterNode ) ) ) {
1225 fprintIndexAttr( f, iterNode, augments );
1226 }
1227 }
1228
1229 /* print AUGMENTS-clause */
1230 iterNode = smiGetRelatedNode( smiNode );
1231 if( iterNode ) {
1232 fprintIndex( f, iterNode, iterNode, NULL );
1233 }
1234 }
1235
1236 /* counts index elements of a table row node */
numIndex(SmiNode * smiNode)1237 static int numIndex( SmiNode *smiNode )
1238 {
1239 SmiElement *iterElem;
1240 int ret = 0;
1241
1242 for( iterElem = smiGetFirstElement( smiNode );
1243 iterElem;
1244 iterElem = smiGetNextElement( iterElem ) ) {
1245 ret++;
1246 }
1247 return ret;
1248 }
1249
1250
1251 /* checks if the second node is a subtable of the first node */
1252 static int
isSubTable(SmiNode * smiNode,SmiNode * subNode)1253 isSubTable( SmiNode *smiNode, SmiNode *subNode )
1254 {
1255 SmiElement *iterElement;
1256 unsigned int numIdx = numIndex( smiNode ), numSubIdx = numIndex( subNode );
1257
1258 /* compare number of index elements */
1259 if( numSubIdx <= numIdx ) {
1260 /* does not have more index elements --> no subtable */
1261 return 0;
1262 }
1263
1264 /* compare all index elements */
1265 for( iterElement = smiGetFirstElement( smiNode );
1266 iterElement;
1267 iterElement = smiGetNextElement( iterElement ) ) {
1268 SmiElement *iterSubElement = smiGetFirstElement( subNode );
1269 SmiNode *iterSubNode;
1270 SmiNode *idxNode = smiGetElementNode( iterElement );
1271
1272 for( iterSubElement = smiGetFirstElement( subNode );
1273 iterSubElement;
1274 iterSubElement = smiGetNextElement( iterSubElement ) ) {
1275
1276 iterSubNode = smiGetElementNode( iterSubElement );
1277 if( idxNode == iterSubNode ){
1278 return 1;
1279 }
1280 }
1281 }
1282 return 0;
1283 }
1284
1285
fprintComplexType(FILE * f,SmiNode * smiNode,const char * name,SmiNode * parent)1286 static void fprintComplexType( FILE *f, SmiNode *smiNode, const char *name,
1287 SmiNode *parent )
1288 {
1289 SmiNode *iterNode;
1290 int numChildren;
1291
1292 if( name ) {
1293 fprintSegment( f, 1, "<xsd:complexType name=\"%sType\">\n",
1294 smiNode->name );
1295 } else {
1296 fprintSegment( f, 1, "<xsd:complexType>\n" );
1297 }
1298
1299 /* fprintAnnotationElem( f, smiNode ); */
1300
1301 numChildren = hasChildren( smiNode, SMI_NODEKIND_ANY );
1302
1303 fprintSegment( f, 1, "<xsd:sequence>\n");
1304
1305 /* print child elements */
1306 for( iterNode = smiGetFirstChildNode( smiNode );
1307 iterNode;
1308 iterNode = smiGetNextChildNode( iterNode ) ) {
1309
1310 fprintElement( f, iterNode, NULL );
1311
1312 }
1313
1314 /* print augmentations */
1315 if( nestAugmentedTables ) {
1316 for( iterNode = smiGetFirstNode( smiGetNodeModule( smiNode ),
1317 SMI_NODEKIND_ROW );
1318 iterNode;
1319 iterNode = smiGetNextNode( iterNode, SMI_NODEKIND_ROW ) ) {
1320 SmiNode *augmNode = smiGetRelatedNode( iterNode );
1321 if( augmNode == smiNode ) {
1322 SmiNode *augIterNode;
1323 for( augIterNode = smiGetFirstChildNode( iterNode );
1324 augIterNode;
1325 augIterNode = smiGetNextChildNode( augIterNode ) ) {
1326
1327 fprintElement( f, augIterNode, NULL );
1328 }
1329 }
1330 }
1331 }
1332
1333 /* print subtables */
1334 if( nestSubtables ) {
1335 for( iterNode = smiGetFirstNode( smiGetNodeModule( smiNode ),
1336 SMI_NODEKIND_ROW );
1337 iterNode;
1338 iterNode = smiGetNextNode( iterNode, SMI_NODEKIND_ROW ) ) {
1339 if( isSubTable( smiNode, iterNode ) ) {
1340 /* fputs( "<!-- Here BEGIN subtable entry -->\n", f );*/
1341 fprintElement( f, iterNode, smiNode );
1342 /* fputs( "<!-- Here END subtable entry -->\n", f );*/
1343 }
1344 }
1345 }
1346
1347 fprintSegment( f, -1, "</xsd:sequence>\n");
1348 fprintIndex( f, smiNode, NULL, parent );
1349
1350 fprintSegment( f, -1, "</xsd:complexType>\n");
1351 if( name ) {
1352 /* we are printing out a global type,
1353 so let's leave a blank line after it. */
1354 fprintf( f, "\n" );
1355 }
1356
1357 for( iterNode = smiGetFirstChildNode( smiNode );
1358 iterNode;
1359 iterNode = smiGetNextChildNode( iterNode ) ) {
1360 if( iterNode->nodekind == SMI_NODEKIND_NODE ) {
1361 fprintComplexType( f, iterNode, iterNode->name, NULL );
1362 }
1363 }
1364
1365 }
1366
1367
fprintElement(FILE * f,SmiNode * smiNode,SmiNode * parentNode)1368 static void fprintElement( FILE *f, SmiNode *smiNode, SmiNode *parentNode )
1369 {
1370 switch( smiNode->nodekind ) {
1371 SmiType *smiType;
1372
1373 case SMI_NODEKIND_NODE :
1374 {
1375 SmiNode *iterNode;
1376
1377 fprintSegment( f, 1, "<xsd:element name=\"%s\">\n", smiNode->name);
1378 fprintSegment( f, 1, "<xsd:complexType>\n");
1379 fprintSegment( f, 1, "<xsd:sequence>\n");
1380 for( iterNode = smiGetFirstChildNode( smiNode );
1381 iterNode;
1382 iterNode = smiGetNextChildNode( iterNode ) ) {
1383 if( iterNode->nodekind == SMI_NODEKIND_SCALAR ) {
1384 fprintElement( f, iterNode, NULL );
1385 }
1386 }
1387 fprintSegment( f, -1, "</xsd:sequence>\n");
1388 fprintSegment( f, -1, "</xsd:complexType>\n");
1389 fprintSegment( f, -1, "</xsd:element>\n");
1390 }
1391 break;
1392
1393 case SMI_NODEKIND_TABLE :
1394 {
1395 SmiNode *iterNode;
1396
1397 /* ignore tables and just include their entries */
1398 for( iterNode = smiGetFirstChildNode( smiNode );
1399 iterNode;
1400 iterNode = smiGetNextChildNode( iterNode ) ) {
1401 fprintElement( f, iterNode, NULL );
1402 }
1403 break;
1404 }
1405
1406 case SMI_NODEKIND_ROW:
1407
1408 fprintSegment( f, 1, "<xsd:element name=\"%s\" "
1409 "minOccurs=\"0\" maxOccurs=\"unbounded\">\n",
1410 smiNode->name );
1411
1412 fprintAnnotationElem( f, smiNode );
1413
1414 fprintComplexType( f, smiNode, NULL, parentNode );
1415 fprintSegment( f, -1, "</xsd:element>\n");
1416 break;
1417
1418 case SMI_NODEKIND_SCALAR:
1419 case SMI_NODEKIND_COLUMN:
1420 {
1421 SmiElement *iterElem;
1422 char *prefix;
1423 char *typeName;
1424
1425 /* check if we are index column */
1426 for( iterElem = smiGetFirstElement( smiGetParentNode( smiNode ) ) ;
1427 iterElem;
1428 iterElem = smiGetNextElement( iterElem ) ) {
1429 if( smiNode == smiGetElementNode( iterElem ) ) {
1430 /* we are index coulumn ==> do not print element */
1431 return;
1432 }
1433 }
1434
1435 if( smiNode->access < SMI_ACCESS_READ_ONLY ) {
1436 /* only print accessible nodes */
1437 return;
1438 }
1439
1440 smiType = smiGetNodeType( smiNode );
1441
1442 if( smiType->name ) {
1443 typeName = smiType->name;
1444 }
1445 else {
1446 typeName = getStringBasetype( smiType->basetype );
1447 }
1448 prefix = getTypePrefix( typeName );
1449
1450 #if 0
1451 if( smiType->basetype == SMI_BASETYPE_BITS ) {
1452 fprintSegment( f, 1, "<xsd:element name=\"%s\" type=\"%s%s\" "
1453 "minOccurs=\"0\">\n",
1454 smiNode->name,
1455 smiNode->name,
1456 getStringBasetype( smiType->basetype ) );
1457 fprintAnnotationElem( f, smiNode );
1458 }
1459
1460 // else if( smiType->basetype == SMI_BASETYPE_OCTETSTRING ) {
1461 #endif /* 0 */
1462
1463 if( smiType->basetype == SMI_BASETYPE_OCTETSTRING ) {
1464 if( smiType->decl == SMI_DECL_IMPLICIT_TYPE ) {
1465
1466 char *hint = getParentDisplayHint( smiType );
1467
1468 fprintSegment( f, 1, "<xsd:element name=\"%s\" "
1469 "minOccurs=\"0\">\n", smiNode->name );
1470 fprintAnnotationElem( f, smiNode );
1471 if( ! hint ) {
1472 fprintTypedef( f, smiType, NULL );
1473 }
1474 else {
1475 fprintTypeWithHint( f, smiNode, smiType, hint );
1476 }
1477 }
1478
1479 else {
1480 if( prefix ) {
1481 fprintSegment( f, 1, "<xsd:element name=\"%s\" "
1482 "type=\"%s:%s\" minOccurs=\"0\">\n",
1483 smiNode->name, prefix, typeName );
1484 }
1485 else {
1486 fprintSegment( f, 1, "<xsd:element name=\"%s\" "
1487 "type=\"%s\" minOccurs=\"0\">\n",
1488 smiNode->name, typeName );
1489 }
1490 fprintAnnotationElem( f, smiNode );
1491 }
1492 }
1493
1494 else if( smiType->decl == SMI_DECL_IMPLICIT_TYPE ) {
1495 fprintSegment( f, 1, "<xsd:element name=\"%s\" minOccurs=\"0\">\n",
1496 smiNode->name );
1497 fprintAnnotationElem( f, smiNode );
1498 fprintTypedef( f, smiType, NULL );
1499 }
1500
1501 else {
1502 if( prefix ) {
1503 fprintSegment( f, 1, "<xsd:element name=\"%s\" type=\"%s:%s\" "
1504 "minOccurs=\"0\">\n",
1505 smiNode->name, prefix, typeName );
1506 }
1507 else {
1508 fprintSegment( f, 1, "<xsd:element name=\"%s\" type=\"%s\" "
1509 "minOccurs=\"0\">\n",
1510 smiNode->name, typeName );
1511 }
1512 fprintAnnotationElem( f, smiNode );
1513 }
1514 fprintSegment( f, -1, "</xsd:element>\n");
1515 break;
1516 }
1517
1518 case SMI_NODEKIND_NOTIFICATION:
1519 fprintSegment( f, 0, "<xsd:element name=\"%s\"/>\n", smiNode->name );
1520 break;
1521
1522 default:
1523 fprintf( f, "<!-- Warning! Unhandled Element! No details available!\n");
1524 fprintf( f, " Nodekind: %#4x -->\n\n", smiNode->nodekind );
1525
1526 }
1527 }
1528
1529
fprintImplicitTypes(FILE * f,SmiModule * smiModule)1530 static void fprintImplicitTypes( FILE *f, SmiModule *smiModule )
1531 {
1532 SmiNode *iterNode;
1533 SmiType *smiType;
1534
1535 for(iterNode = smiGetFirstNode(smiModule,
1536 SMI_NODEKIND_SCALAR | SMI_NODEKIND_COLUMN);
1537 iterNode;
1538 iterNode = smiGetNextNode(iterNode,
1539 SMI_NODEKIND_SCALAR | SMI_NODEKIND_COLUMN)) {
1540 smiType = smiGetNodeType( iterNode );
1541 if( smiType ) {
1542 switch( smiType->basetype ) {
1543
1544 case SMI_BASETYPE_BITS:
1545 if( ! getTypePrefix( smiType->name ) ) {
1546 fprintTypedef( f, smiType, iterNode->name );
1547 break;
1548 }
1549
1550 case SMI_BASETYPE_OCTETSTRING:
1551 #if 0
1552 if( smiType->decl == SMI_DECL_IMPLICIT_TYPE ) {
1553 fprintTypedef( f, INDENT, smiType, iterNode->name );
1554 }
1555 #endif /* 0 */
1556 break;
1557 default:
1558 break;
1559 }
1560 }
1561 }
1562 }
1563
1564
1565 #if 0
1566 static void fprintRows( FILE *f, SmiModule *smiModule )
1567 {
1568 SmiNode *iterNode;
1569
1570 for( iterNode = smiGetFirstNode( smiModule, SMI_NODEKIND_ROW );
1571 iterNode;
1572 iterNode = smiGetNextNode( iterNode, SMI_NODEKIND_ROW ) ) {
1573 if( hasChildren( iterNode, SMI_NODEKIND_COLUMN | SMI_NODEKIND_TABLE ) ){
1574 fprintElement( f, iterNode, NULL );
1575 }
1576 }
1577 }
1578 #endif
1579
fprintImports(FILE * f,SmiModule * smiModule)1580 static void fprintImports( FILE *f, SmiModule *smiModule )
1581 {
1582 SmiImport *iterImp;
1583 char *lastModName = "";
1584
1585 fprintSegment( f, 0, "<xsd:import namespace=\"%ssmi\" schemaLocation=\"%ssmi.xsd\"/>\n", schemaLocation, schemaLocation );
1586 for( iterImp = smiGetFirstImport( smiModule );
1587 iterImp;
1588 iterImp = smiGetNextImport( iterImp ) ) {
1589 /* assume imports to be ordered by module names */
1590 if( strcmp( iterImp->module, lastModName ) ) {
1591 fprintSegment( f, 0, "<xsd:import ");
1592 fprintf( f, "namespace=\"%s%s\" schemaLocation=\"%s%s.xsd\"/>\n",
1593 schemaLocation, iterImp->module,
1594 schemaLocation, iterImp->module );
1595 }
1596 lastModName = iterImp->module;
1597 }
1598 fprintf( f, "\n");
1599
1600 }
1601
1602
1603 /*
1604 * Check if given table io a sub table of another table.
1605 * If so, its parent table is returned (NULL otherwise).
1606 */
isASubTable(SmiNode * smiNode,SmiModule * smiModule)1607 static SmiNode *isASubTable( SmiNode *smiNode, SmiModule *smiModule )
1608 {
1609 SmiNode *iterNode;
1610 int numIdxDiff = -1;
1611 SmiNode *retNode = NULL;
1612
1613 for( iterNode = smiGetFirstNode( smiModule,
1614 SMI_NODEKIND_ROW );
1615 iterNode;
1616 iterNode = smiGetNextNode( iterNode,
1617 SMI_NODEKIND_ROW ) ) {
1618
1619 if( isSubTable( iterNode, smiNode ) ) {
1620
1621 if( (numIdxDiff == -1) ||
1622 ((numIndex( smiNode ) - numIndex( iterNode )) < numIdxDiff) ) {
1623 retNode = iterNode;
1624 numIdxDiff = numIndex( smiNode ) - numIndex( iterNode );
1625 }
1626
1627 }
1628 }
1629 return retNode;
1630 }
1631
1632
fprintGroupTypes(FILE * f,SmiModule * smiModule)1633 static void fprintGroupTypes( FILE *f, SmiModule *smiModule )
1634 {
1635 SmiNode *iterNode, *iterNode2;
1636
1637 /* scalar groups */
1638 for( iterNode = smiGetFirstNode( smiModule, SMI_NODEKIND_NODE );
1639 iterNode;
1640 iterNode = smiGetNextNode( iterNode, SMI_NODEKIND_NODE ) ) {
1641 if( hasChildren( iterNode, SMI_NODEKIND_SCALAR ) ) {
1642 fprintSegment(f, 1, "<xsd:complexType name=\"%sType\">\n",
1643 iterNode->name);
1644 fprintSegment( f, 1, "<xsd:sequence>\n");
1645 for( iterNode2 = smiGetFirstChildNode( iterNode );
1646 iterNode2;
1647 iterNode2 = smiGetNextChildNode( iterNode2 ) ) {
1648 if( iterNode2->nodekind == SMI_NODEKIND_SCALAR ) {
1649 fprintElement( f, iterNode2, NULL );
1650 }
1651 }
1652 fprintSegment( f, -1, "</xsd:sequence>\n");
1653 fprintSegment(f, -1, "</xsd:complexType>\n");
1654 }
1655 }
1656
1657 /* rows */
1658 for( iterNode = smiGetFirstNode( smiModule, SMI_NODEKIND_ROW );
1659 iterNode;
1660 iterNode = smiGetNextNode( iterNode, SMI_NODEKIND_ROW ) ) {
1661 if( hasChildren( iterNode,
1662 SMI_NODEKIND_COLUMN | SMI_NODEKIND_TABLE ) ){
1663
1664 /* skip nested subtables here */
1665 if( nestSubtables ){
1666 if( isASubTable( iterNode, smiModule ) != NULL ) {
1667 continue;
1668 }
1669 }
1670
1671 /* skip table augmentations here */
1672 if( nestAugmentedTables ) {
1673 if( iterNode->indexkind == SMI_INDEX_AUGMENT ) {
1674 continue;
1675 }
1676 }
1677
1678 fprintComplexType( f, iterNode, iterNode->name, NULL );
1679
1680 }
1681 }
1682 }
1683
1684
1685 #if 0
1686 static void fprintNotifications( FILE *f, SmiModule *smiModule )
1687 {
1688 SmiNode *iterNode;
1689
1690 for( iterNode = smiGetFirstNode( smiModule, SMI_NODEKIND_NOTIFICATION );
1691 iterNode;
1692 iterNode = smiGetNextNode( iterNode, SMI_NODEKIND_NOTIFICATION ) ) {
1693 fprintElement( f, iterNode, NULL );
1694 }
1695 }
1696 #endif
1697
1698
fprintModuleHead(FILE * f,SmiModule * smiModule)1699 static void fprintModuleHead(FILE *f, SmiModule *smiModule)
1700 {
1701 if( smiModule->description ) {
1702 fprintSegment(f, 1, "<xsd:annotation>\n");
1703 fprintDocumentation(f, smiModule->description);
1704 fprintSegment(f, -1, "</xsd:annotation>\n\n");
1705 }
1706
1707 }
1708
1709
fprintKey(FILE * f,SmiNode * smiNode)1710 static void fprintKey( FILE *f, SmiNode *smiNode )
1711 {
1712 SmiNode *relNode;
1713 SmiElement *iterElem;
1714
1715 switch( smiNode->indexkind ) {
1716
1717 case SMI_INDEX_INDEX:
1718
1719 /* print key */
1720 /* fprintSegment( f, 1, "<xsd:key " );
1721 fprintf( f, "name=\"%sKey\">\n", smiNode->name );
1722 fprintSegment( f, 0, "<xsd:selector ");
1723 fprintf( f, "xpath=\"%s\"/>\n", smiNode->name );
1724 for( iterElem = smiGetFirstElement( smiNode );
1725 iterElem;
1726 iterElem = smiGetNextElement( iterElem ) ) {
1727 SmiNode *indexNode = smiGetElementNode( iterElem );
1728 fprintSegment( f, 0, "<xsd:field ");
1729 fprintf( f, "xpath=\"@%s\"/>\n", indexNode->name );
1730 }
1731 fprintSegment( f, -1, "</xsd:key>\n\n");*/
1732 break;
1733
1734 case SMI_INDEX_AUGMENT:
1735
1736 /* print keyref */
1737 fprintSegment( f, 1, "<xsd:keyref " );
1738 relNode = smiGetRelatedNode( smiNode );
1739 fprintf( f, "name=\"%sKeyRef\" ", smiNode->name );
1740 fprintf( f, "refer=\"%sKey\">\n", relNode->name );
1741 fprintSegment( f, 0, "<xsd:selector ");
1742 fprintf( f, "xpath=\"%s\"/>\n", smiNode->name );
1743 for( iterElem = smiGetFirstElement( relNode );
1744 iterElem;
1745 iterElem = smiGetNextElement( iterElem ) ) {
1746 SmiNode *indexNode = smiGetElementNode( iterElem );
1747 fprintSegment( f, 0, "<xsd:field ");
1748 fprintf( f, "xpath=\"@%s\"/>\n", indexNode->name );
1749 }
1750 fprintSegment( f, -1, "</xsd:keyref>\n");
1751
1752 /* print unique clause */
1753 fprintSegment( f, 1, "<xsd:unique " );
1754 fprintf( f, "name=\"%sKeyRefUnique\">\n", smiNode->name );
1755 fprintSegment( f, 0, "<xsd:selector ");
1756 fprintf( f, "xpath=\"%s\"/>\n", smiNode->name );
1757 for( iterElem = smiGetFirstElement( relNode );
1758 iterElem;
1759 iterElem = smiGetNextElement( iterElem ) ) {
1760 SmiNode *indexNode = smiGetElementNode( iterElem );
1761 fprintSegment( f, 0, "<xsd:field ");
1762 fprintf( f, "xpath=\"@%s\"/>\n", indexNode->name );
1763 }
1764 fprintSegment( f, -1, "</xsd:unique>\n\n");
1765 break;
1766
1767 case SMI_INDEX_REORDER:
1768 case SMI_INDEX_SPARSE:
1769 case SMI_INDEX_EXPAND:
1770 /* SMIng, not implemented yet */
1771 break;
1772
1773 default:
1774 fprintf( f, "<!-- Error: Unknown index type -->\n" );
1775 break;
1776 }
1777 }
1778
1779
fprintGroupElements(FILE * f,SmiModule * smiModule)1780 static void fprintGroupElements(FILE *f, SmiModule *smiModule)
1781 {
1782 SmiNode *iterNode;
1783
1784 /* scalar groups */
1785 for( iterNode = smiGetFirstNode( smiModule, SMI_NODEKIND_NODE );
1786 iterNode;
1787 iterNode = smiGetNextNode( iterNode, SMI_NODEKIND_NODE ) ) {
1788 if( hasChildren( iterNode, SMI_NODEKIND_SCALAR ) ) {
1789
1790 if (container) {
1791 fprintSegment(f, 1, "<xsd:element name=\"%s\" "
1792 "type=\"%s:%sType\" minOccurs=\"0\">\n",
1793 iterNode->name,
1794 smiModule->name, iterNode->name);
1795 } else {
1796 fprintSegment(f, 1, "<xsd:element name=\"%s\" "
1797 "type=\"%sType\" minOccurs=\"0\">\n",
1798 iterNode->name, iterNode->name);
1799 }
1800 fprintAnnotationElem( f, iterNode );
1801 fprintSegment( f, -1, "</xsd:element>\n" );
1802 }
1803 }
1804
1805 /* rows */
1806 for( iterNode = smiGetFirstNode( smiModule, SMI_NODEKIND_ROW );
1807 iterNode;
1808 iterNode = smiGetNextNode( iterNode, SMI_NODEKIND_ROW ) ) {
1809 if( hasChildren( iterNode, SMI_NODEKIND_COLUMN | SMI_NODEKIND_TABLE ) ){
1810 /* skip nested subtables here */
1811 if( nestSubtables ){
1812 if( isASubTable( iterNode, smiModule ) != NULL ) {
1813 continue;
1814 }
1815 }
1816
1817 /* skip table augmentations here */
1818 if( nestAugmentedTables ) {
1819 if( iterNode->indexkind == SMI_INDEX_AUGMENT ) {
1820 continue;
1821 }
1822 }
1823
1824 if (container) {
1825 fprintSegment(f, 1, "<xsd:element name=\"%s\" "
1826 "type=\"%s:%sType\" minOccurs=\"0\" "
1827 "maxOccurs=\"unbounded\">\n",
1828 iterNode->name,
1829 smiModule->name, iterNode->name);
1830 fprintKey( f, iterNode );
1831 } else {
1832 fprintSegment(f, 1, "<xsd:element name=\"%s\" "
1833 "type=\"%sType\" minOccurs=\"0\" "
1834 "maxOccurs=\"unbounded\">\n",
1835 iterNode->name, iterNode->name);
1836 }
1837 fprintAnnotationElem( f, iterNode );
1838 fprintSegment( f, -1, "</xsd:element>\n" );
1839 }
1840 }
1841 }
1842
1843
getSubTableXPath(SmiNode * smiNode,SmiModule * smiModule)1844 static char *getSubTableXPath( SmiNode *smiNode, SmiModule *smiModule )
1845 {
1846 char *ret;
1847 SmiNode *parentTable = isASubTable( smiNode, smiModule );
1848
1849 if( parentTable ) {
1850 smiAsprintf( &ret, "%s/%s",
1851 getSubTableXPath( parentTable, smiModule ),
1852 smiNode->name );
1853 }
1854 else {
1855 smiAsprintf( &ret, "%s", smiNode->name );
1856 }
1857 return ret;
1858 }
1859
1860
fprintKeys(FILE * f,SmiModule * smiModule)1861 static void fprintKeys( FILE *f, SmiModule *smiModule )
1862 {
1863
1864 SmiNode *iterNode;
1865
1866 for( iterNode = smiGetFirstNode( smiModule, SMI_NODEKIND_ROW );
1867 iterNode;
1868 iterNode = smiGetNextNode( iterNode, SMI_NODEKIND_ROW ) ) {
1869
1870 SmiElement *iterElem;
1871
1872 /* print only keys for base tables */
1873 if( iterNode->indexkind != SMI_INDEX_INDEX ) {
1874 continue;
1875 }
1876
1877 /* print key */
1878 fprintSegment( f, 1, "<xsd:key name=\"%sKey\">\n", iterNode->name );
1879 fprintSegment( f, 0, "<xsd:selector ");
1880 fprintf( f, "xpath=\"%s\"/>\n",
1881 nestSubtables ?
1882 getSubTableXPath( iterNode, smiModule ) : iterNode->name );
1883
1884 for( iterElem = smiGetFirstElement( iterNode );
1885 iterElem;
1886 iterElem = smiGetNextElement( iterElem ) ) {
1887 SmiNode *indexNode = smiGetElementNode( iterElem );
1888 fprintSegment( f, 0, "<xsd:field ");
1889 fprintf( f, "xpath=\"@%s\"/>\n", indexNode->name );
1890 }
1891 fprintSegment( f, -1, "</xsd:key>\n\n");
1892 }
1893
1894
1895 }
1896
1897
fprintContextHead(FILE * f)1898 static void fprintContextHead(FILE *f)
1899 {
1900 fprintSegment( f, 1, "<xsd:element name=\"snmp-data\">\n");
1901 fprintSegment( f, 1, "<xsd:complexType>\n");
1902 fprintSegment( f, 1, "<xsd:sequence>\n");
1903 fprintSegment( f, 1, "<xsd:element name=\"context\" "
1904 "minOccurs=\"0\" maxOccurs=\"unbounded\">\n");
1905 fprintSegment( f, 1, "<xsd:complexType>\n");
1906 fprintSegment( f, 1, "<xsd:sequence>\n");
1907 }
1908
1909
fprintContextFoot(FILE * f,SmiModule ** modv,int modc)1910 static void fprintContextFoot(FILE *f, SmiModule **modv, int modc)
1911 {
1912 int i;
1913
1914 fprintSegment( f, -1, "</xsd:sequence>\n");
1915 fprintSegment( f, 0, "<xsd:attribute name=\"ipaddr\" type=\"xsd:NMTOKEN\" use=\"required\"/>\n");
1916 fprintSegment( f, 0, "<xsd:attribute name=\"hostname\" type=\"xsd:NMTOKEN\"/>\n");
1917 fprintSegment( f, 0, "<xsd:attribute name=\"port\" type=\"xsd:unsignedInt\" use=\"required\"/>\n");
1918 fprintSegment( f, 0, "<xsd:attribute name=\"community\" type=\"xsd:NMTOKEN\" use=\"required\"/>\n");
1919 fprintSegment( f, 0, "<xsd:attribute name=\"caching\" type=\"xsd:NMTOKEN\"/>\n");
1920 fprintSegment( f, 0, "<xsd:attribute name=\"time\" type=\"xsd:dateTime\" use=\"required\"/>\n");
1921 fprintSegment( f, -1, "</xsd:complexType>\n");
1922 fprintSegment( f, -1, "</xsd:element>\n");
1923 fprintSegment( f, -1, "</xsd:sequence>\n");
1924 fprintSegment( f, -1, "</xsd:complexType>\n");
1925
1926 for( i=0; i < modc; i++ ) {
1927 fprintKeys( f, modv[ i ] );
1928 }
1929 fprintSegment( f, -1, "</xsd:element>\n\n");
1930 }
1931
1932
fprintTypedefs(FILE * f,SmiModule * smiModule)1933 static void fprintTypedefs(FILE *f, SmiModule *smiModule)
1934 {
1935 int i;
1936 SmiType *smiType;
1937
1938 for(i = 0, smiType = smiGetFirstType(smiModule);
1939 smiType;
1940 i++, smiType = smiGetNextType(smiType)) {
1941 fprintf(f, "\n");
1942 fprintTypedef(f, smiType, smiType->name);
1943 }
1944 }
1945
1946
registerType(char * type,char * module)1947 static void registerType( char *type, char *module )
1948 {
1949 TypePrefix *oldTPr = NULL, *iterTPr = NULL;
1950
1951 for( iterTPr = typePrefixes; iterTPr; iterTPr = iterTPr->next ) {
1952 oldTPr = iterTPr;
1953 }
1954 if( ! oldTPr ) {
1955 /* type prefixes do not exist yet */
1956 typePrefixes = xmalloc( sizeof( TypePrefix ) );
1957 typePrefixes->type = type;
1958 typePrefixes->prefix = module;
1959 typePrefixes->next = NULL;
1960 }
1961 else {
1962 /* create new TypePrefix */
1963 oldTPr->next = xmalloc( sizeof( TypePrefix ) );
1964 oldTPr->next->type = type;
1965 oldTPr->next->prefix = module;
1966 oldTPr->next->next = NULL;
1967 }
1968 }
1969
1970
dumpXsdModules(int modc,SmiModule ** modv,int flags,char * output)1971 static void dumpXsdModules(int modc, SmiModule **modv, int flags, char *output)
1972 {
1973 int i;
1974 FILE *f = stdout;
1975 SmiImport *iterImp;
1976 char *lastModName = "";
1977
1978 if (output) {
1979 f = fopen(output, "w");
1980 if (!f) {
1981 fprintf(stderr, "smidump: cannot open %s for writing: ", output);
1982 perror(NULL);
1983 exit(1);
1984 }
1985 }
1986
1987 for (i = 0; i < modc; i++) {
1988
1989 fprintf(f, "<?xml version=\"1.0\"?>\n");
1990 fprintf(f, "<!-- This module has been generated by smidump "
1991 SMI_VERSION_STRING ". Do not edit. -->\n");
1992
1993 fputs( "<!-- WARNING: files located at ", f );
1994 fprintf(f, "%s ", schemaLocation);
1995 fputs( "are subject to changes. -->\n\n", f );
1996
1997 fprintSegment(f, 1, "<xsd:schema ");
1998 fprintf(f, "targetNamespace=\"%s%s\"\n",
1999 schemaLocation, modv[i]->name);
2000
2001 fprintf(f, " xmlns=\"%s%s\"\n",
2002 schemaLocation, modv[i]->name);
2003 /* fprintf(f, " xmlns:xmn=\"http://www.w3.org/XML/1998/namespace\"\n"); */
2004 fprintf(f, " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n");
2005 fprintf(f, " xmlns:smi=\"%ssmi\"\n", schemaLocation);
2006
2007 for( iterImp = smiGetFirstImport( modv[i] );
2008 iterImp;
2009 iterImp = smiGetNextImport( iterImp ) ) {
2010 registerType( iterImp->name, iterImp->module );
2011 /* assume imports to be ordered by module names */
2012 if( strcmp( iterImp->module, lastModName ) ) {
2013 fprintf( f, " xmlns:%s=\"%s%s\"\n",
2014 iterImp->module, schemaLocation, iterImp->module );
2015 }
2016 lastModName = iterImp->module;
2017 }
2018
2019 fprintf(f, " xml:lang=\"en\"\n");
2020 fprintf(f, " elementFormDefault=\"qualified\"\n");
2021 fprintf(f, " attributeFormDefault=\"unqualified\">\n\n");
2022
2023 fprintModuleHead(f, modv[i]);
2024 fprintImports(f, modv[i]);
2025 fprintContextHead(f);
2026 fprintGroupElements(f, modv[i]);
2027 fprintContextFoot(f, modv, 0);
2028 fprintGroupTypes(f, modv[i]);
2029 fprintImplicitTypes(f, modv[i]);
2030 fprintTypedefs(f, modv[i]);
2031
2032 fprintSegment(f, -1, "</xsd:schema>\n");
2033 }
2034
2035 if (fflush(f) || ferror(f)) {
2036 perror("smidump: write error");
2037 exit(1);
2038 }
2039
2040 if (output) {
2041 fclose(f);
2042 }
2043 }
2044
2045
dumpXsdContainer(int modc,SmiModule ** modv,int flags,char * output)2046 static void dumpXsdContainer(int modc, SmiModule **modv, int flags,
2047 char *output)
2048 {
2049 int i;
2050 FILE *f = stdout;
2051
2052 if (output) {
2053 f = fopen(output, "w");
2054 if (!f) {
2055 fprintf(stderr, "smidump: cannot open %s for writing: ", output);
2056 perror(NULL);
2057 exit(1);
2058 }
2059 }
2060
2061 fprintf(f, "<?xml version=\"1.0\"?>\n");
2062 fprintf(f, "<!-- This module has been generated by smidump "
2063 SMI_VERSION_STRING ". Do not edit. -->\n");
2064
2065 fputs( "<!-- WARNING: files located at ", f );
2066 fprintf(f, "%s ", schemaLocation);
2067 fputs( "are subject to changes. -->\n\n", f );
2068
2069 fprintSegment(f, 1, "<xsd:schema ");
2070 fprintf(f, "targetNamespace=\"%s%s\"\n", schemaLocation, containerBasename);
2071 fprintf(f, " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n");
2072 fprintf(f, " xmlns:smi=\"%ssmi\"\n", schemaLocation);
2073 for (i = 0; i < modc; i++) {
2074 fprintf(f, " xmlns:%s=\"%s%s\"\n",
2075 modv[i]->name, schemaLocation, modv[i]->name);
2076 }
2077
2078 fprintf(f, " xml:lang=\"en\"\n");
2079 fprintf(f, " elementFormDefault=\"qualified\"\n");
2080 fprintf(f, " attributeFormDefault=\"unqualified\">\n\n");
2081
2082 /* imports */
2083 for (i = 0; i < modc; i++) {
2084 fprintSegment( f, 0, "<xsd:import ");
2085 fprintf( f, "namespace=\"%s%s\" schemaLocation=\"%s%s.xsd\"/>\n",
2086 schemaLocation, modv[i]->name,
2087 schemaLocation, modv[i]->name);
2088 }
2089 fprintf( f, "\n");
2090
2091 /* context */
2092 fprintContextHead(f);
2093 for (i = 0; i < modc; i++) {
2094 /* per module elements */
2095 fprintGroupElements(f, modv[i]);
2096 }
2097 fprintContextFoot(f, modv, modc);
2098
2099 fprintSegment(f, -1, "</xsd:schema>\n");
2100
2101 if (fflush(f) || ferror(f)) {
2102 perror("smidump: write error");
2103 exit(1);
2104 }
2105
2106 if (output) {
2107 fclose(f);
2108 }
2109 }
2110
2111
dumpXsd(int modc,SmiModule ** modv,int flags,char * output)2112 static void dumpXsd(int modc, SmiModule **modv, int flags, char *output)
2113 {
2114 /* register smi basetypes */
2115 registerType( "Integer32", "smi" );
2116 registerType( "ObjectIdentifier", "smi" );
2117 registerType( "OctetString", "smi" );
2118 registerType( "Unsigned32", "smi" );
2119 registerType( "Unsigned64", "smi" );
2120
2121 /* make sure url ends with '/' */
2122 if( schemaLocation[ strlen( schemaLocation ) - 1 ] != '/' ) {
2123 smiAsprintf( &schemaLocation, "%s%c", schemaLocation, '/');
2124 }
2125
2126 if (container) {
2127 dumpXsdContainer(modc, modv, flags, output);
2128 } else {
2129 dumpXsdModules(modc, modv, flags, output);
2130 }
2131
2132 /* delete type-prefix-mapping */
2133 free( typePrefixes ); /* XXX: TODO: free all malloced types in a loop */
2134 }
2135
2136
initXsd()2137 void initXsd()
2138 {
2139
2140 static SmidumpDriverOption opt[] = {
2141 { "schema-url", OPT_STRING, &schemaLocation, 0,
2142 "URI prefix for schema definitions and namespaces" },
2143 { "container", OPT_FLAG, &container, 0,
2144 "generate a container schema" },
2145 { "nest-augments", OPT_FLAG, &nestAugmentedTables, 0,
2146 "Nest rows of augmented tables in the base tables" },
2147 { "nest-subtables", OPT_FLAG, &nestSubtables, 0,
2148 "Nest subtables in the base tables" },
2149 { 0, OPT_END, 0, 0 }
2150 };
2151
2152 static SmidumpDriver driver = {
2153 "xsd",
2154 dumpXsd,
2155 0,
2156 SMIDUMP_DRIVER_CANT_UNITE,
2157 "XML schema definitions",
2158 opt,
2159 NULL
2160 };
2161
2162 smidumpRegisterDriver(&driver);
2163 }
2164