Blame tools/dump-xsd.c

Packit 022b05
/*
Packit 022b05
 * dump-xsd.c --
Packit 022b05
 *
Packit 022b05
 *      Operations to dump SMI module information as XML schema definitions.
Packit 022b05
 *
Packit 022b05
 * Copyright (c) 2001 J. Schoenwaelder, Technical University of Braunschweig.
Packit 022b05
 *           (c) 2002 T. Klie, Technical University of Braunschweig.
Packit 022b05
 *           (c) 2002 F. Strauss, Technical University of Braunschweig.
Packit 022b05
 *           (c) 2007 T. Klie, Technical University of Braunschweig.
Packit 022b05
 *
Packit 022b05
 * See the file "COPYING" for information on usage and redistribution
Packit 022b05
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
Packit 022b05
 *
Packit 022b05
 * @(#) $Id: dump-xsd.c 8090 2008-04-18 12:56:29Z strauss $
Packit 022b05
 */
Packit 022b05
Packit 022b05
#include <config.h>
Packit 022b05
Packit 022b05
#include <stdlib.h>
Packit 022b05
#include <stdio.h>
Packit 022b05
#include <stdarg.h>
Packit 022b05
#include <string.h>
Packit 022b05
#include <ctype.h>
Packit 022b05
#include <time.h>
Packit 022b05
#ifdef HAVE_WIN_H
Packit 022b05
#include "win.h"
Packit 022b05
#endif
Packit 022b05
Packit 022b05
#include "smi.h"
Packit 022b05
#include "smidump.h"
Packit 022b05
#include "fortopat.h"
Packit 022b05
Packit 022b05
Packit 022b05
#define  INDENT		2    /* indent factor */
Packit 022b05
Packit 022b05
static int ind = 0;
Packit 022b05
Packit 022b05
#ifndef MIN
Packit 022b05
#define MIN(a,b) ((a)) < ((b)) ? ((a)) : ((b))
Packit 022b05
#endif /* #ifndef MIN */
Packit 022b05
Packit 022b05
static char *schemaLocation = "http://www.ibr.cs.tu-bs.de/projects/libsmi/xsd/";
Packit 022b05
static int container = 0;
Packit 022b05
static char *containerBasename = "container";
Packit 022b05
static int *nestAugmentedTables = 0;
Packit 022b05
static int *nestSubtables = 0;
Packit 022b05
Packit 022b05
typedef struct XmlEscape {
Packit 022b05
    char character;
Packit 022b05
    char *escape;
Packit 022b05
} XmlEscape;
Packit 022b05
Packit 022b05
static XmlEscape xmlEscapes [] = {
Packit 022b05
    { '<',	"<" },
Packit 022b05
    { '>',	">" },
Packit 022b05
    { '&',	"&" },
Packit 022b05
    { 0,	NULL }
Packit 022b05
};
Packit 022b05
Packit 022b05
typedef struct TypePrefix {
Packit 022b05
    char *type;
Packit 022b05
    char *prefix;
Packit 022b05
    struct TypePrefix *next;
Packit 022b05
} TypePrefix;
Packit 022b05
Packit 022b05
static TypePrefix *typePrefixes = NULL;
Packit 022b05
Packit 022b05
Packit 022b05
Packit 022b05
/* some forward declarations */
Packit 022b05
static void fprintElement( FILE *f, SmiNode *smiNode, SmiNode *parentNode );
Packit 022b05
static char* getTypePrefix( char *typeName );
Packit 022b05
Packit 022b05
static char *getStringBasetype(SmiBasetype basetype)
Packit 022b05
{
Packit 022b05
    return
Packit 022b05
        (basetype == SMI_BASETYPE_UNKNOWN)           ? "<UNKNOWN>" :
Packit 022b05
        (basetype == SMI_BASETYPE_OCTETSTRING)       ? "OctetString" :
Packit 022b05
        (basetype == SMI_BASETYPE_OBJECTIDENTIFIER)  ? "ObjectIdentifier" :
Packit 022b05
        (basetype == SMI_BASETYPE_UNSIGNED32)        ? "Unsigned32" :
Packit 022b05
        (basetype == SMI_BASETYPE_INTEGER32)         ? "Integer32" :
Packit 022b05
        (basetype == SMI_BASETYPE_UNSIGNED64)        ? "Unsigned64" :
Packit 022b05
        (basetype == SMI_BASETYPE_INTEGER64)         ? "Integer64" :
Packit 022b05
        (basetype == SMI_BASETYPE_FLOAT32)           ? "Float32" :
Packit 022b05
        (basetype == SMI_BASETYPE_FLOAT64)           ? "Float64" :
Packit 022b05
        (basetype == SMI_BASETYPE_FLOAT128)          ? "Float128" :
Packit 022b05
        (basetype == SMI_BASETYPE_ENUM)              ? "Enumeration" :
Packit 022b05
        (basetype == SMI_BASETYPE_BITS)              ? "Bits" :
Packit 022b05
                                                   "<unknown>";
Packit 022b05
}
Packit 022b05
Packit 022b05
static char* getStringStatus(SmiStatus status)
Packit 022b05
{
Packit 022b05
    char *statStr;
Packit 022b05
    
Packit 022b05
    switch( status ) {
Packit 022b05
    case SMI_STATUS_CURRENT:
Packit 022b05
	statStr = "current";
Packit 022b05
	break;
Packit 022b05
    case SMI_STATUS_DEPRECATED:
Packit 022b05
	statStr = "deprecated";
Packit 022b05
	break;
Packit 022b05
    case SMI_STATUS_OBSOLETE:
Packit 022b05
	statStr = "obsolete";
Packit 022b05
	break;
Packit 022b05
    case SMI_STATUS_MANDATORY:
Packit 022b05
	statStr = "mandatory";
Packit 022b05
	break;
Packit 022b05
    case SMI_STATUS_OPTIONAL:
Packit 022b05
	statStr = "optional";
Packit 022b05
	break;
Packit 022b05
    case SMI_STATUS_UNKNOWN:
Packit 022b05
    default:
Packit 022b05
	statStr = "unknown";
Packit 022b05
	break;
Packit 022b05
    }
Packit 022b05
    return statStr;
Packit 022b05
}
Packit 022b05
Packit 022b05
static char* getStringAccess( SmiAccess smiAccess )
Packit 022b05
{
Packit 022b05
    switch( smiAccess ) {
Packit 022b05
    case SMI_ACCESS_NOT_IMPLEMENTED: return "not-implemented";
Packit 022b05
    case SMI_ACCESS_NOT_ACCESSIBLE : return "not-accessible";
Packit 022b05
    case SMI_ACCESS_NOTIFY         : return "notify";
Packit 022b05
    case SMI_ACCESS_READ_ONLY      : return "read-only";
Packit 022b05
    case SMI_ACCESS_READ_WRITE     : return "read-write";
Packit 022b05
    case SMI_ACCESS_UNKNOWN:
Packit 022b05
    default: return "unknown";
Packit 022b05
    }
Packit 022b05
}
Packit 022b05
#if 0
Packit 022b05
static char
Packit 022b05
*getStringValue(SmiValue *valuePtr, SmiType *typePtr)
Packit 022b05
{
Packit 022b05
    static char    s[1024];
Packit 022b05
    char           ss[9];
Packit 022b05
    int		   n;
Packit 022b05
    unsigned int   i;
Packit 022b05
    SmiNamedNumber *nn;
Packit 022b05
    SmiNode        *nodePtr;
Packit 022b05
    
Packit 022b05
    s[0] = 0;
Packit 022b05
    
Packit 022b05
    switch (valuePtr->basetype) {
Packit 022b05
    case SMI_BASETYPE_UNSIGNED32:
Packit 022b05
	sprintf(s, "%lu", valuePtr->value.unsigned32);
Packit 022b05
	break;
Packit 022b05
    case SMI_BASETYPE_INTEGER32:
Packit 022b05
	sprintf(s, "%ld", valuePtr->value.integer32);
Packit 022b05
	break;
Packit 022b05
    case SMI_BASETYPE_UNSIGNED64:
Packit 022b05
	sprintf(s, UINT64_FORMAT, valuePtr->value.unsigned64);
Packit 022b05
	break;
Packit 022b05
    case SMI_BASETYPE_INTEGER64:
Packit 022b05
	sprintf(s, INT64_FORMAT, valuePtr->value.integer64);
Packit 022b05
	break;
Packit 022b05
    case SMI_BASETYPE_FLOAT32:
Packit 022b05
    case SMI_BASETYPE_FLOAT64:
Packit 022b05
    case SMI_BASETYPE_FLOAT128:
Packit 022b05
	break;
Packit 022b05
    case SMI_BASETYPE_ENUM:
Packit 022b05
	for (nn = smiGetFirstNamedNumber(typePtr); nn;
Packit 022b05
	     nn = smiGetNextNamedNumber(nn)) {
Packit 022b05
	    if (nn->value.value.unsigned32 == valuePtr->value.unsigned32)
Packit 022b05
		break;
Packit 022b05
	}
Packit 022b05
	if (nn) {
Packit 022b05
	    sprintf(s, "%s", nn->name);
Packit 022b05
	} else {
Packit 022b05
	    sprintf(s, "%ld", valuePtr->value.integer32);
Packit 022b05
	}
Packit 022b05
	break;
Packit 022b05
    case SMI_BASETYPE_OCTETSTRING:
Packit 022b05
	for (i = 0; i < valuePtr->len; i++) {
Packit 022b05
	    if (!isprint((int)valuePtr->value.ptr[i])) break;
Packit 022b05
	}
Packit 022b05
	if (i == valuePtr->len) {
Packit 022b05
	    sprintf(s, "\"%s\"", valuePtr->value.ptr);
Packit 022b05
	} else {
Packit 022b05
            sprintf(s, "0x%*s", 2 * valuePtr->len, "");
Packit 022b05
            for (i=0; i < valuePtr->len; i++) {
Packit 022b05
                sprintf(ss, "%02x", valuePtr->value.ptr[i]);
Packit 022b05
                strncpy(&s[2+2*i], ss, 2);
Packit 022b05
            }
Packit 022b05
	}
Packit 022b05
	break;
Packit 022b05
    case SMI_BASETYPE_BITS:
Packit 022b05
	sprintf(s, "(");
Packit 022b05
	for (i = 0, n = 0; i < valuePtr->len * 8; i++) {
Packit 022b05
	    if (valuePtr->value.ptr[i/8] & (1 << (7-(i%8)))) {
Packit 022b05
		if (n)
Packit 022b05
		    sprintf(&s[strlen(s)], ", ");
Packit 022b05
		n++;
Packit 022b05
		for (nn = smiGetFirstNamedNumber(typePtr); nn;
Packit 022b05
		     nn = smiGetNextNamedNumber(nn)) {
Packit 022b05
		    if (nn->value.value.unsigned32 == i)
Packit 022b05
			break;
Packit 022b05
		}
Packit 022b05
		if (nn) {
Packit 022b05
		    sprintf(&s[strlen(s)], "%s", nn->name);
Packit 022b05
		} else {
Packit 022b05
		    sprintf(s, "%d", i);
Packit 022b05
		}
Packit 022b05
	    }
Packit 022b05
	}
Packit 022b05
	sprintf(&s[strlen(s)], ")");
Packit 022b05
	break;
Packit 022b05
    case SMI_BASETYPE_UNKNOWN:
Packit 022b05
	break;
Packit 022b05
    case SMI_BASETYPE_OBJECTIDENTIFIER:
Packit 022b05
	nodePtr = smiGetNodeByOID(valuePtr->len, valuePtr->value.oid);
Packit 022b05
	if (nodePtr) {
Packit 022b05
	    sprintf(s, "%s", nodePtr->name);
Packit 022b05
	} else {
Packit 022b05
	    strcpy(s, "");
Packit 022b05
	    for (i=0; i < valuePtr->len; i++) {
Packit 022b05
		if (i) strcat(s, ".");
Packit 022b05
		sprintf(&s[strlen(s)], "%u", valuePtr->value.oid[i]);
Packit 022b05
	    }
Packit 022b05
	}
Packit 022b05
	break;
Packit 022b05
    }
Packit 022b05
Packit 022b05
    return s;
Packit 022b05
}
Packit 022b05
#endif /* 0 */
Packit 022b05
Packit 022b05
static int smiPow( int base, unsigned int exponent )
Packit 022b05
{
Packit 022b05
  unsigned int i;
Packit 022b05
  int ret = 1;
Packit 022b05
  
Packit 022b05
  if( exponent == 0 ) {
Packit 022b05
    return 1;
Packit 022b05
  }
Packit 022b05
Packit 022b05
  for( i = 0; i < exponent; i++ ) {
Packit 022b05
    ret *= base;
Packit 022b05
  }
Packit 022b05
  return ret;
Packit 022b05
}
Packit 022b05
Packit 022b05
static void fprintSegment(FILE *f, int relindent, char *fmt, ...)
Packit 022b05
{
Packit 022b05
    va_list ap;
Packit 022b05
Packit 022b05
    va_start(ap, fmt);
Packit 022b05
     
Packit 022b05
    if ((ind == 0) || (ind + relindent == 0)) {
Packit 022b05
	ind += relindent;
Packit 022b05
    } else {
Packit 022b05
	if (relindent < 0) ind += relindent;
Packit 022b05
	fprintf(f, "%*c", ind * INDENT, ' ');
Packit 022b05
	if (relindent > 0) ind += relindent;
Packit 022b05
    }
Packit 022b05
    vfprintf(f, fmt, ap);
Packit 022b05
Packit 022b05
    va_end(ap);
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
Packit 022b05
static void fprintMultilineString(FILE *f, const char *s)
Packit 022b05
{
Packit 022b05
    int i, j, len;
Packit 022b05
Packit 022b05
    fprintSegment(f, 0, "");
Packit 022b05
    if (s) {
Packit 022b05
	len = strlen(s);
Packit 022b05
	for (i=0; i < len; i++) {
Packit 022b05
	    for (j = 0; xmlEscapes[j].character; j++) {
Packit 022b05
		if (xmlEscapes[j].character == s[i]) break;
Packit 022b05
	    }
Packit 022b05
	    if (xmlEscapes[j].character) {
Packit 022b05
		fputs(xmlEscapes[j].escape, f);
Packit 022b05
	    } else {
Packit 022b05
		putc(s[i], f);
Packit 022b05
	    }
Packit 022b05
            if (s[i] == '\n') {
Packit 022b05
		fprintSegment(f, 0, "");
Packit 022b05
	    }
Packit 022b05
	}
Packit 022b05
    }
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
Packit 022b05
static void fprintDocumentation(FILE *f, const char *description)
Packit 022b05
{
Packit 022b05
    if (description) {
Packit 022b05
	fprintSegment(f, 1, "<xsd:documentation>\n");
Packit 022b05
	fprintMultilineString(f, description);
Packit 022b05
	fprintf(f, "\n");
Packit 022b05
	fprintSegment(f, -1, "</xsd:documentation>\n");
Packit 022b05
    }
Packit 022b05
}
Packit 022b05
Packit 022b05
static void fprintNamedNumber( FILE *f, SmiNamedNumber *nn )
Packit 022b05
{
Packit 022b05
    fprintSegment( f, 1, "<xsd:enumeration value=\"%s\">\n", nn->name );
Packit 022b05
    fprintSegment( f, 1, "<xsd:annotation>\n");
Packit 022b05
    fprintSegment( f, 1, "<xsd:appinfo>\n");
Packit 022b05
    fprintSegment( f, 0, "<intVal>%d</intVal>\n",
Packit 022b05
		   (int)nn->value.value.integer32 );
Packit 022b05
    fprintSegment( f, -1, "</xsd:appinfo>\n");
Packit 022b05
    fprintSegment( f, -1, "</xsd:annotation>\n");
Packit 022b05
    fprintSegment( f, -1, "</xsd:enumeration>\n");
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
static void fprintStdRestHead( FILE *f, SmiType *smiType )
Packit 022b05
{
Packit 022b05
    char *baseTypeName = getStringBasetype(smiType->basetype);
Packit 022b05
    char *prefix = getTypePrefix( baseTypeName );
Packit 022b05
    
Packit 022b05
    if( prefix ) {
Packit 022b05
	fprintSegment(f, 1, "<xsd:restriction base=\"%s:%s\">\n",
Packit 022b05
		      prefix, baseTypeName );
Packit 022b05
    }
Packit 022b05
    else {
Packit 022b05
	fprintSegment(f, 1, "<xsd:restriction base=\"%s\">\n", baseTypeName );
Packit 022b05
    }
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
static void fprintHexOrAsciiType( FILE *f, SmiType *parent,
Packit 022b05
				  SmiInteger32 minLength,
Packit 022b05
				  SmiInteger32 maxLength,
Packit 022b05
				  char *name, int hex )
Packit 022b05
{
Packit 022b05
    char *prefix = parent ? getTypePrefix( parent->name ) : NULL;
Packit 022b05
    char *typeFlag = hex ? "Hex" : "Ascii";
Packit 022b05
    
Packit 022b05
    if( name ) {
Packit 022b05
	fprintSegment( f, 1, "<xsd:simpleType name=\"%s%s\">\n",
Packit 022b05
		       name, typeFlag );
Packit 022b05
    } else {
Packit 022b05
	fprintSegment( f, 1, "<xsd:simpleType>\n");
Packit 022b05
    }
Packit 022b05
    if( prefix ) {
Packit 022b05
	fprintSegment( f, 1, "<xsd:restriction base=\"%s:%s%s\">\n",
Packit 022b05
		       prefix, parent->name, typeFlag );
Packit 022b05
    }
Packit 022b05
    else {
Packit 022b05
	fprintSegment( f, 1, "<xsd:restriction base=\"%s%s\">\n",
Packit 022b05
		       parent->name, typeFlag );
Packit 022b05
    }
Packit 022b05
   
Packit 022b05
    if( minLength > 0 ) {
Packit 022b05
	fprintSegment( f, 0, "<xsd:minLength value=\"%d\"/>\n",
Packit 022b05
		       (int)minLength );
Packit 022b05
    }
Packit 022b05
    if( maxLength > -1 ) {
Packit 022b05
	fprintSegment( f, 0, "<xsd:maxLength value=\"%d\"/>\n",
Packit 022b05
		       (int)maxLength );
Packit 022b05
    }
Packit 022b05
Packit 022b05
    fprintSegment( f, -1, "</xsd:restriction>\n");
Packit 022b05
    fprintSegment( f, -1, "</xsd:simpleType>\n");
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
static int dhInParent( SmiType *smiType )
Packit 022b05
{
Packit 022b05
    SmiType *parent = smiGetParentType( smiType );
Packit 022b05
Packit 022b05
    if( smiType->format && parent->format ) {
Packit 022b05
	return ! strcmp( smiType->format, parent->format );
Packit 022b05
    }
Packit 022b05
    return 0;
Packit 022b05
}
Packit 022b05
Packit 022b05
#define MD_DH_INT_NORMAL   1
Packit 022b05
#define MD_DH_INT_DECIMAL  2
Packit 022b05
#define MD_DH_INT_BIN      3
Packit 022b05
#define MD_DH_INT_OCT      4
Packit 022b05
#define MD_DH_INT_HEX      5
Packit 022b05
Packit 022b05
/* parse a (integer) display hint and specify the offset, if used */
Packit 022b05
static int getIntDHType( char *hint, int *offset )
Packit 022b05
{
Packit 022b05
    switch( hint[ 0 ] ) {
Packit 022b05
Packit 022b05
    case 'd':
Packit 022b05
	if( hint[1] ) {
Packit 022b05
	    *offset = 0;
Packit 022b05
	    *offset = atoi( &hint[2] );
Packit 022b05
	    return MD_DH_INT_DECIMAL;
Packit 022b05
	}
Packit 022b05
	return MD_DH_INT_NORMAL;
Packit 022b05
Packit 022b05
    case 'b':
Packit 022b05
	/* binary value */
Packit 022b05
	return MD_DH_INT_BIN;
Packit 022b05
    case 'o':
Packit 022b05
	/* octet value */
Packit 022b05
	return MD_DH_INT_OCT;
Packit 022b05
    case 'x':
Packit 022b05
	/* hex value */
Packit 022b05
	return MD_DH_INT_HEX;
Packit 022b05
    default:
Packit 022b05
	/* should not occur */
Packit 022b05
	return 0;
Packit 022b05
    }
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
static void fprintRestriction(FILE *f, SmiType *smiType)
Packit 022b05
{
Packit 022b05
    SmiRange *smiRange;
Packit 022b05
    
Packit 022b05
    /* print ranges etc. */
Packit 022b05
    switch( smiType->basetype ) {
Packit 022b05
Packit 022b05
    case SMI_BASETYPE_INTEGER32:
Packit 022b05
    {
Packit 022b05
	SmiInteger32 min = SMI_BASETYPE_INTEGER32_MIN;
Packit 022b05
	SmiInteger32 max = SMI_BASETYPE_INTEGER32_MAX;
Packit 022b05
	int offset = 0, useDecPoint = 0;
Packit 022b05
Packit 022b05
	if( smiType->format ) {
Packit 022b05
	  /* we have a display hint here, so check if we have to use
Packit 022b05
	     a decimal point */
Packit 022b05
	  useDecPoint =  
Packit 022b05
	    getIntDHType( smiType->format, &offset ) == MD_DH_INT_DECIMAL; 
Packit 022b05
	  /* xxx: other display hint types (binary, oct, hex) */
Packit 022b05
	}
Packit 022b05
Packit 022b05
	if( useDecPoint ) {
Packit 022b05
	  fprintSegment( f, 1, "<xsd:restriction base=\"xsd:decimal\">\n");
Packit 022b05
	  fprintSegment( f, 0, "<xsd:fractionDigits value=\"%d\"/>\n", offset );
Packit 022b05
	}
Packit 022b05
	else {
Packit 022b05
	  fprintStdRestHead( f, smiType );
Packit 022b05
	}
Packit 022b05
Packit 022b05
	smiRange = smiGetFirstRange( smiType );
Packit 022b05
	while( smiRange ) {
Packit 022b05
	    if( min == SMI_BASETYPE_INTEGER32_MIN ||
Packit 022b05
		smiRange->minValue.value.integer32 < min ) {
Packit 022b05
		min = smiRange->minValue.value.integer32;
Packit 022b05
	    }
Packit 022b05
	    if( max == SMI_BASETYPE_INTEGER32_MAX ||
Packit 022b05
		smiRange->maxValue.value.integer32 > max ) {
Packit 022b05
		max = smiRange->maxValue.value.integer32;
Packit 022b05
	    }
Packit 022b05
	    smiRange = smiGetNextRange( smiRange );
Packit 022b05
	}
Packit 022b05
	
Packit 022b05
	/* print minimu value */
Packit 022b05
	if( useDecPoint ) {
Packit 022b05
	    fprintSegment( f, 0, "<xsd:minInclusive value=\"%d.%d\"/>\n", 
Packit 022b05
			   (int)min / smiPow( 10, offset ), 
Packit 022b05
			   abs( (int)min % smiPow( 10, offset ) ) );
Packit 022b05
	} else {
Packit 022b05
	    fprintSegment( f, 0, "<xsd:minInclusive value=\"%d\"/>\n",
Packit 022b05
			   (int)min );
Packit 022b05
	}
Packit 022b05
Packit 022b05
	/* print maximum value */
Packit 022b05
	if( useDecPoint ) {
Packit 022b05
	    fprintSegment( f, 0, "<xsd:maxInclusive value=\"%d.%d\"/>\n", 
Packit 022b05
			   (int)max / smiPow( 10, offset ), 
Packit 022b05
			   abs( (int)max % smiPow( 10, offset ) ) );
Packit 022b05
	} else {
Packit 022b05
	    fprintSegment( f, 0, "<xsd:maxInclusive value=\"%d\"/>\n",
Packit 022b05
			   (int)max );
Packit 022b05
	}
Packit 022b05
	
Packit 022b05
	fprintSegment(f, -1, "</xsd:restriction>\n");
Packit 022b05
	break;
Packit 022b05
    }
Packit 022b05
    
Packit 022b05
    case SMI_BASETYPE_OCTETSTRING:
Packit 022b05
    {
Packit 022b05
	SmiInteger32  minLength, maxLength;
Packit 022b05
	unsigned int numSubRanges = 0;
Packit 022b05
	
Packit 022b05
	minLength = 0;
Packit 022b05
	maxLength = -1;
Packit 022b05
Packit 022b05
	/* get range details */
Packit 022b05
	for( smiRange = smiGetFirstRange( smiType );
Packit 022b05
	     smiRange;
Packit 022b05
	     smiRange = smiGetNextRange( smiRange ) ) {
Packit 022b05
	    if( minLength == 0 ||
Packit 022b05
		smiRange->minValue.value.integer32 < minLength ) {
Packit 022b05
		minLength = smiRange->minValue.value.integer32;	     
Packit 022b05
	    }
Packit 022b05
	    if( smiRange->maxValue.value.integer32 > maxLength ) {
Packit 022b05
		maxLength = smiRange->maxValue.value.integer32;
Packit 022b05
	    }
Packit 022b05
	    numSubRanges++;
Packit 022b05
	}
Packit 022b05
Packit 022b05
	
Packit 022b05
Packit 022b05
	if( smiType->format &&
Packit 022b05
	    ( smiType->decl == SMI_DECL_IMPLICIT_TYPE ||
Packit 022b05
	      smiType->decl == SMI_DECL_TEXTUALCONVENTION ) &&
Packit 022b05
	    ! dhInParent( smiType ) ) {
Packit 022b05
	    /*
Packit 022b05
	    fprintStringUnion( f, indent, smiType,
Packit 022b05
			       minLength, maxLength, 0, NULL );
Packit 022b05
	    */
Packit 022b05
	    char *pattern;
Packit 022b05
	    
Packit 022b05
	    fprintSegment( f, 1, "<xsd:restriction base=\"xsd:string\">\n" );
Packit 022b05
Packit 022b05
	    /* create regexp */
Packit 022b05
	    pattern = smiFormatToPattern(smiType->format,
Packit 022b05
					 smiGetFirstRange(smiType));
Packit 022b05
	    if (pattern) {
Packit 022b05
		fprintSegment( f, 0, "<xsd:pattern value=\"%s\"/>\n", pattern);
Packit 022b05
		xfree(pattern);
Packit 022b05
	    }
Packit 022b05
	    else {
Packit 022b05
		fprintf( f, "
Packit 022b05
			 "This feature is not supported. -->\n" );
Packit 022b05
	    }
Packit 022b05
	    fprintSegment( f, -1, "</xsd:restriction>\n");
Packit 022b05
	}
Packit 022b05
	else {
Packit 022b05
	    SmiType *parent = smiGetParentType( smiType );
Packit 022b05
	    /*
Packit 022b05
	    fprintStringUnion( f, indent, smiType,
Packit 022b05
			       minLength, maxLength, secondTime,
Packit 022b05
			       smiType->name );
Packit 022b05
	    */
Packit 022b05
	    if( parent ) {
Packit 022b05
		if(  parent->format ) {
Packit 022b05
		    char *pattern;
Packit 022b05
Packit 022b05
		    pattern = smiFormatToPattern(parent->format,
Packit 022b05
						 smiGetFirstRange(smiType));
Packit 022b05
		    if (pattern) {
Packit 022b05
			fprintSegment( f, 1, "<xsd:restriction base=\"xsd:string\">\n" );
Packit 022b05
			fprintSegment(f, 0, "<xsd:pattern value=\"%s\"/>\n",
Packit 022b05
				      pattern);
Packit 022b05
			fprintSegment( f, -1, "</xsd:restriction>\n");
Packit 022b05
			xfree(pattern);
Packit 022b05
		    }
Packit 022b05
		}
Packit 022b05
		
Packit 022b05
		
Packit 022b05
		else if( smiType->name &&
Packit 022b05
			 ! strcmp( smiType->name, "IpAddress" ) ) {
Packit 022b05
		    SmiUnsigned32 lengths[] = {4, 4};
Packit 022b05
		    lengths[0] = 4; lengths[1] = 4;
Packit 022b05
		    fprintSegment( f, 1, "<xsd:restriction base=\"xsd:string\">\n" );
Packit 022b05
		    fprintSegment( f, 0, "
Packit 022b05
				   "value=\"(0|[1-9](([0-9]){0,2}))."
Packit 022b05
				   "(0|[1-9](([0-9]){0,2}))."
Packit 022b05
				   "(0|[1-9](([0-9]){0,2}))."
Packit 022b05
				   "(0|[1-9](([0-9]){0,2}))\"/>\n" );
Packit 022b05
		    fprintSegment( f, -1, "</xsd:restriction>\n");
Packit 022b05
		}
Packit 022b05
		
Packit 022b05
		else {
Packit 022b05
		    
Packit 022b05
		    
Packit 022b05
		    char *prefix = getTypePrefix( parent->name );
Packit 022b05
Packit 022b05
		    if( prefix ) {
Packit 022b05
			fprintSegment( f, 1, "<xsd:restriction base=\"%s:%s\">\n",
Packit 022b05
				       prefix, parent->name );
Packit 022b05
		    } else {
Packit 022b05
			fprintSegment( f, 1, "<xsd:restriction base=\"%s\">\n",
Packit 022b05
				       parent->name );
Packit 022b05
		    }
Packit 022b05
Packit 022b05
		    /* print length restriction */
Packit 022b05
		    if( minLength > 0 )
Packit 022b05
			fprintSegment( f, 0, "<xsd:minLength value=\"%d\"/>\n",
Packit 022b05
				       (int)minLength );
Packit 022b05
		    if( maxLength > -1 )
Packit 022b05
			fprintSegment( f, 0, "<xsd:maxLength value=\"%d\"/>\n",
Packit 022b05
				       (int)maxLength );		    
Packit 022b05
		    fprintSegment( f, -1, "</xsd:restriction>\n");
Packit 022b05
		}
Packit 022b05
		    
Packit 022b05
Packit 022b05
	    }
Packit 022b05
	}
Packit 022b05
	break;
Packit 022b05
    }
Packit 022b05
Packit 022b05
    case SMI_BASETYPE_FLOAT128:
Packit 022b05
    {
Packit 022b05
/*	SmiFloat128 min, max; */
Packit 022b05
	fprintStdRestHead( f, smiType );
Packit 022b05
	
Packit 022b05
	/* xxx, only SMIng */
Packit 022b05
	break;
Packit 022b05
    }
Packit 022b05
Packit 022b05
    case SMI_BASETYPE_FLOAT64:
Packit 022b05
    {
Packit 022b05
/*	SmiFloat64 min,max;*/
Packit 022b05
	fprintStdRestHead( f, smiType );
Packit 022b05
Packit 022b05
	/* xxx, only SMIng */
Packit 022b05
	break;
Packit 022b05
    }
Packit 022b05
    
Packit 022b05
    case SMI_BASETYPE_FLOAT32:
Packit 022b05
    {
Packit 022b05
/*	SmiFloat32 min,max;*/
Packit 022b05
	fprintStdRestHead( f, smiType );
Packit 022b05
	
Packit 022b05
	/* xxx, only SMIng */
Packit 022b05
	break;
Packit 022b05
    }
Packit 022b05
    
Packit 022b05
    case SMI_BASETYPE_INTEGER64:
Packit 022b05
    {
Packit 022b05
/*	SmiInteger64 min,max;*/
Packit 022b05
	fprintStdRestHead( f, smiType );
Packit 022b05
	
Packit 022b05
	/* xxx, only SMIng */
Packit 022b05
	break;
Packit 022b05
    }
Packit 022b05
Packit 022b05
    case SMI_BASETYPE_UNSIGNED64:
Packit 022b05
    {
Packit 022b05
	SmiUnsigned64 min, max;
Packit 022b05
Packit 022b05
	min = SMI_BASETYPE_UNSIGNED64_MIN;
Packit 022b05
	max = SMI_BASETYPE_UNSIGNED64_MAX;
Packit 022b05
Packit 022b05
	fprintStdRestHead( f, smiType );
Packit 022b05
	
Packit 022b05
	smiRange = smiGetFirstRange( smiType );
Packit 022b05
	while( smiRange ) {
Packit 022b05
	    if( smiRange->minValue.value.unsigned64 < min ) {
Packit 022b05
		min = smiRange->minValue.value.unsigned64;
Packit 022b05
	    }
Packit 022b05
	    if( smiRange->maxValue.value.unsigned64 > max ) {
Packit 022b05
		max = smiRange->maxValue.value.unsigned64;
Packit 022b05
	    }
Packit 022b05
	    smiRange = smiGetNextRange( smiRange );
Packit 022b05
	}
Packit 022b05
	fprintSegment( f, 0, "<xsd:minInclusive value=\"%lu\"/>\n",
Packit 022b05
		       (unsigned long)min );
Packit 022b05
Packit 022b05
	fprintSegment( f, 0, "<xsd:maxInclusive value=\"%lu\"/>\n",
Packit 022b05
		       (unsigned long)max );
Packit 022b05
	
Packit 022b05
	fprintSegment(f, -1, "</xsd:restriction>\n");
Packit 022b05
	
Packit 022b05
	break;
Packit 022b05
    }
Packit 022b05
Packit 022b05
    case SMI_BASETYPE_UNSIGNED32:
Packit 022b05
    {
Packit 022b05
	SmiUnsigned32 min, max;
Packit 022b05
Packit 022b05
	min = 0;
Packit 022b05
	max = 4294967295UL;
Packit 022b05
Packit 022b05
	fprintStdRestHead( f, smiType );
Packit 022b05
	
Packit 022b05
	smiRange = smiGetFirstRange( smiType );
Packit 022b05
	while( smiRange ) {
Packit 022b05
	    if( smiRange->minValue.value.unsigned32 < min ) {
Packit 022b05
		min = smiRange->minValue.value.unsigned32;
Packit 022b05
	    }
Packit 022b05
	    if( smiRange->maxValue.value.unsigned32 > max ) {
Packit 022b05
		max = smiRange->maxValue.value.unsigned32;
Packit 022b05
	    }
Packit 022b05
	    smiRange = smiGetNextRange( smiRange );
Packit 022b05
	}
Packit 022b05
	fprintSegment( f, 0, "<xsd:minInclusive value=\"%u\"/>\n",
Packit 022b05
		       (unsigned int)min );
Packit 022b05
Packit 022b05
	fprintSegment( f, 0, "<xsd:maxInclusive value=\"%u\"/>\n",
Packit 022b05
		       (unsigned int)max );
Packit 022b05
	
Packit 022b05
	fprintSegment(f, -1, "</xsd:restriction>\n");
Packit 022b05
	break;
Packit 022b05
    }
Packit 022b05
Packit 022b05
    case SMI_BASETYPE_ENUM:
Packit 022b05
    case SMI_BASETYPE_BITS:
Packit 022b05
    {
Packit 022b05
	SmiNamedNumber *nn;
Packit 022b05
	
Packit 022b05
	fprintSegment(f, 1, "<xsd:restriction base=\"xsd:NMTOKEN\">\n");
Packit 022b05
Packit 022b05
	/* iterate named numbers */
Packit 022b05
	for( nn = smiGetFirstNamedNumber( smiType );
Packit 022b05
	     nn;
Packit 022b05
	     nn = smiGetNextNamedNumber( nn ) ) {
Packit 022b05
	    fprintNamedNumber( f, nn );
Packit 022b05
	}
Packit 022b05
	fprintSegment(f, -1, "</xsd:restriction>\n");
Packit 022b05
	break;
Packit 022b05
    }
Packit 022b05
Packit 022b05
    case SMI_BASETYPE_OBJECTIDENTIFIER:
Packit 022b05
	fprintSegment( f, 0,
Packit 022b05
		       "<xsd:restriction base=\"smi:ObjectIdentifier\"/>\n");
Packit 022b05
	break;
Packit 022b05
    case SMI_BASETYPE_UNKNOWN:
Packit 022b05
	/* should not occur */
Packit 022b05
	break;
Packit 022b05
    case SMI_BASETYPE_POINTER:
Packit 022b05
	/* TODO */
Packit 022b05
	break;
Packit 022b05
    }
Packit 022b05
}
Packit 022b05
    
Packit 022b05
Packit 022b05
static unsigned int getNamedNumberCount( SmiType *smiType )
Packit 022b05
{
Packit 022b05
    SmiNamedNumber *nn;
Packit 022b05
    unsigned int ret = 0;
Packit 022b05
Packit 022b05
    for( nn = smiGetFirstNamedNumber( smiType );
Packit 022b05
	 nn;
Packit 022b05
	 nn = smiGetNextNamedNumber( nn ) ) {
Packit 022b05
	ret++;
Packit 022b05
    }
Packit 022b05
Packit 022b05
    return ret;
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
static void fprintBitList( FILE *f, SmiType *smiType )
Packit 022b05
{
Packit 022b05
    fprintSegment( f, 1, "<xsd:restriction>\n" );
Packit 022b05
    fprintSegment( f, 1, "<xsd:simpleType>\n" );
Packit 022b05
    fprintSegment( f, 1, "<xsd:list>\n" );  
Packit 022b05
    fprintSegment( f, 1, "<xsd:simpleType>\n" );
Packit 022b05
    fprintRestriction( f, smiType );
Packit 022b05
    fprintSegment( f, -1, "</xsd:simpleType>\n" );
Packit 022b05
    fprintSegment( f, -1, "</xsd:list>\n" );
Packit 022b05
    fprintSegment( f, -1, "</xsd:simpleType>\n");
Packit 022b05
    fprintSegment( f, 0, "<xsd:maxLength value=\"%d\"/>\n",
Packit 022b05
		   getNamedNumberCount( smiType ) );
Packit 022b05
    fprintSegment( f, -1, "</xsd:restriction>\n");
Packit 022b05
}
Packit 022b05
static int getNumSubRanges( SmiType *smiType )
Packit 022b05
{
Packit 022b05
    SmiRange *smiRange;
Packit 022b05
    int num = 0;
Packit 022b05
Packit 022b05
    for( smiRange = smiGetFirstRange( smiType );
Packit 022b05
	 smiRange;
Packit 022b05
	 smiRange = smiGetNextRange( smiRange ) ) {
Packit 022b05
	num++;
Packit 022b05
    }
Packit 022b05
    
Packit 022b05
    return num;
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
static void fprintSubRangeType( FILE *f,
Packit 022b05
				SmiRange *smiRange, SmiType *smiType )
Packit 022b05
{
Packit 022b05
    
Packit 022b05
    switch( smiType->basetype ) {
Packit 022b05
Packit 022b05
    case SMI_BASETYPE_UNSIGNED32: {
Packit 022b05
	SmiUnsigned32 min, max;
Packit 022b05
Packit 022b05
	min = 0;
Packit 022b05
	max = 4294967295UL;
Packit 022b05
Packit 022b05
	if( smiRange->minValue.value.unsigned32 < min ) {
Packit 022b05
	    min = smiRange->minValue.value.unsigned32;
Packit 022b05
	}
Packit 022b05
	if( smiRange->maxValue.value.unsigned32 > max ) {
Packit 022b05
	    max = smiRange->maxValue.value.unsigned32;
Packit 022b05
	}
Packit 022b05
	
Packit 022b05
	fprintSegment( f, 1, "<xsd:simpleType>\n");
Packit 022b05
	fprintStdRestHead( f, smiType );
Packit 022b05
Packit 022b05
	fprintSegment( f, 0, "<xsd:minInclusive value=\"%u\"/>\n",
Packit 022b05
		       (unsigned int)min );
Packit 022b05
	
Packit 022b05
	fprintSegment( f, 0, "<xsd:maxInclusive value=\"%u\"/>\n",
Packit 022b05
		       (unsigned int)max );
Packit 022b05
Packit 022b05
	fprintSegment(f, -1, "</xsd:restriction>\n");
Packit 022b05
	fprintSegment(f, -1, "</xsd:simpleType>\n");
Packit 022b05
	break;
Packit 022b05
    }
Packit 022b05
Packit 022b05
    case SMI_BASETYPE_INTEGER32: {
Packit 022b05
	SmiInteger32 min, max;
Packit 022b05
Packit 022b05
	min = SMI_BASETYPE_INTEGER32_MIN;
Packit 022b05
	max = SMI_BASETYPE_INTEGER32_MAX;
Packit 022b05
Packit 022b05
	if( min == SMI_BASETYPE_INTEGER32_MIN ||
Packit 022b05
	    smiRange->minValue.value.integer32 < min ) {
Packit 022b05
	    min = smiRange->minValue.value.integer32;
Packit 022b05
	}
Packit 022b05
	if( max == SMI_BASETYPE_INTEGER32_MAX ||
Packit 022b05
	    smiRange->maxValue.value.integer32 > max ) {
Packit 022b05
	    max = smiRange->maxValue.value.integer32;
Packit 022b05
	}
Packit 022b05
Packit 022b05
	fprintSegment( f, 1, "<xsd:simpleType>\n");
Packit 022b05
    	fprintStdRestHead( f, smiType );
Packit 022b05
	
Packit 022b05
	fprintSegment( f, 0, "<xsd:minInclusive value=\"%d\"/>\n", (int)min );
Packit 022b05
Packit 022b05
	fprintSegment( f, 0, "<xsd:maxInclusive value=\"%d\"/>\n", (int)max );
Packit 022b05
Packit 022b05
	fprintSegment(f, -1, "</xsd:restriction>\n");	
Packit 022b05
	fprintSegment(f, -1, "</xsd:simpleType>\n");
Packit 022b05
	break;
Packit 022b05
	
Packit 022b05
    }
Packit 022b05
Packit 022b05
    case SMI_BASETYPE_OCTETSTRING: {
Packit 022b05
	SmiInteger32  minLength, maxLength;
Packit 022b05
	
Packit 022b05
	minLength = 0;
Packit 022b05
	maxLength = -1;
Packit 022b05
	
Packit 022b05
	if( smiRange->minValue.value.integer32 < minLength ) {
Packit 022b05
	    minLength = smiRange->minValue.value.integer32;	     
Packit 022b05
	}
Packit 022b05
	if( smiRange->maxValue.value.integer32 > maxLength ) {
Packit 022b05
	    maxLength = smiRange->maxValue.value.integer32;
Packit 022b05
	}
Packit 022b05
	fprintHexOrAsciiType( f, smiType,
Packit 022b05
			      minLength, maxLength, NULL, 1 );
Packit 022b05
	break;
Packit 022b05
    }
Packit 022b05
Packit 022b05
    case SMI_BASETYPE_FLOAT128:
Packit 022b05
    {
Packit 022b05
/*	SmiFloat128 min, max; 
Packit 022b05
	xxx, only SMIng */
Packit 022b05
	break;
Packit 022b05
    }
Packit 022b05
Packit 022b05
    case SMI_BASETYPE_FLOAT64:
Packit 022b05
    {
Packit 022b05
/*	SmiFloat64 min,max;
Packit 022b05
	xxx, only SMIng */
Packit 022b05
	break;
Packit 022b05
    }
Packit 022b05
    
Packit 022b05
    case SMI_BASETYPE_FLOAT32:
Packit 022b05
    {
Packit 022b05
/*	SmiFloat32 min,max;
Packit 022b05
	xxx, only SMIng */
Packit 022b05
	break;
Packit 022b05
    }
Packit 022b05
Packit 022b05
    case SMI_BASETYPE_INTEGER64:
Packit 022b05
    {
Packit 022b05
/*	SmiInteger64 min,max;
Packit 022b05
	 xxx, only SMIng */
Packit 022b05
	break;
Packit 022b05
    }
Packit 022b05
Packit 022b05
    case SMI_BASETYPE_UNSIGNED64:
Packit 022b05
    {
Packit 022b05
	SmiUnsigned64 min, max;
Packit 022b05
Packit 022b05
	min = SMI_BASETYPE_UNSIGNED64_MIN;
Packit 022b05
	max = SMI_BASETYPE_UNSIGNED64_MAX;
Packit 022b05
Packit 022b05
	if( smiRange->minValue.value.unsigned64 < min ) {
Packit 022b05
	    min = smiRange->minValue.value.unsigned64;
Packit 022b05
	}
Packit 022b05
	if( smiRange->maxValue.value.unsigned32 > max ) {
Packit 022b05
	    max = smiRange->maxValue.value.unsigned64;
Packit 022b05
	}
Packit 022b05
	
Packit 022b05
	fprintSegment( f, 1, "<xsd:simpleType>\n");
Packit 022b05
	fprintStdRestHead( f, smiType );
Packit 022b05
Packit 022b05
	fprintSegment( f, 0, "<xsd:minInclusive value=\"%lu\"/>\n",
Packit 022b05
		       (unsigned long)min );
Packit 022b05
Packit 022b05
	fprintSegment( f, 0, "<xsd:maxInclusive value=\"%lu\"/>\n",
Packit 022b05
		       (unsigned long)max );
Packit 022b05
Packit 022b05
	fprintSegment(f, -1, "</xsd:restriction>\n");
Packit 022b05
	fprintSegment(f, -1, "</xsd:simpleType>\n");
Packit 022b05
	break;
Packit 022b05
    }
Packit 022b05
Packit 022b05
    case SMI_BASETYPE_ENUM:
Packit 022b05
    case SMI_BASETYPE_BITS:
Packit 022b05
    case SMI_BASETYPE_OBJECTIDENTIFIER:
Packit 022b05
    case SMI_BASETYPE_UNKNOWN:
Packit 022b05
    case SMI_BASETYPE_POINTER:
Packit 022b05
	/* should not occur */
Packit 022b05
	break;
Packit 022b05
	
Packit 022b05
    }
Packit 022b05
}
Packit 022b05
Packit 022b05
static void fprintDisplayHint( FILE *f, char *format )
Packit 022b05
{
Packit 022b05
    fprintSegment( f, 0, "<displayHint>%s</displayHint>\n", format );
Packit 022b05
}
Packit 022b05
Packit 022b05
static void fprintLengths(FILE *f, SmiType *smiType)
Packit 022b05
{
Packit 022b05
    SmiRange *smiRange = smiGetFirstRange(smiType);
Packit 022b05
Packit 022b05
    if (! smiRange) {
Packit 022b05
	return;
Packit 022b05
    }
Packit 022b05
    
Packit 022b05
    fprintSegment(f, 1, "<lengths>\n");
Packit 022b05
    for (smiRange = smiGetFirstRange(smiType);
Packit 022b05
	 smiRange; smiRange = smiGetNextRange(smiRange)) {
Packit 022b05
	fprintSegment(f, 0, "<length min=\"%u\" max=\"%u\"/>\n",
Packit 022b05
		      smiRange->minValue.value.unsigned32,
Packit 022b05
		      smiRange->maxValue.value.unsigned32);
Packit 022b05
    }
Packit 022b05
    fprintSegment( f, -1, "</lengths>\n");
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
static void fprintTypedef(FILE *f, SmiType *smiType, const char *name)
Packit 022b05
{
Packit 022b05
    SmiRange *smiRange;
Packit 022b05
    unsigned int numSubRanges = getNumSubRanges( smiType );
Packit 022b05
    
Packit 022b05
    if ( name ) {
Packit 022b05
	fprintSegment(f, 1, "<xsd:simpleType name=\"%s\">\n", name);
Packit 022b05
    }
Packit 022b05
Packit 022b05
    else {
Packit 022b05
	/* unnamed simple type */
Packit 022b05
	fprintSegment(f, 1, "<xsd:simpleType>\n");
Packit 022b05
    }
Packit 022b05
Packit 022b05
    if( smiType->description ) {
Packit 022b05
	fprintSegment( f, 1, "<xsd:annotation>\n");
Packit 022b05
	fprintDocumentation(f, smiType->description);
Packit 022b05
	if( smiType->format ) {
Packit 022b05
	    fprintSegment( f, 1, "<xsd:appinfo>\n");
Packit 022b05
	    fprintDisplayHint( f, smiType->format );
Packit 022b05
	    if( smiType->basetype == SMI_BASETYPE_OCTETSTRING ) {
Packit 022b05
	      fprintLengths( f, smiType );
Packit 022b05
	    }
Packit 022b05
	    fprintSegment( f, -1, "</xsd:appinfo>\n");
Packit 022b05
	}
Packit 022b05
	fprintSegment( f, -1, "</xsd:annotation>\n");
Packit 022b05
    }
Packit 022b05
        
Packit 022b05
    if( ( numSubRanges > 1 ) &&
Packit 022b05
	     ( smiType->basetype != SMI_BASETYPE_OCTETSTRING ) ) {
Packit 022b05
	
Packit 022b05
	fprintSegment( f, 1, "<xsd:union>\n");
Packit 022b05
	
Packit 022b05
	for( smiRange = smiGetFirstRange( smiType );
Packit 022b05
	     smiRange;
Packit 022b05
	     smiRange = smiGetNextRange( smiRange ) ) {
Packit 022b05
	    fprintSubRangeType( f, smiRange, smiType );
Packit 022b05
	}
Packit 022b05
	
Packit 022b05
	fprintSegment( f, -1, "</xsd:union>\n");
Packit 022b05
    }
Packit 022b05
    else if( smiType->basetype == SMI_BASETYPE_BITS ) {
Packit 022b05
	fprintBitList( f, smiType );
Packit 022b05
    }
Packit 022b05
    else {
Packit 022b05
	fprintRestriction(f, smiType );
Packit 022b05
    }
Packit 022b05
    fprintSegment(f, -1, "</xsd:simpleType>\n");
Packit 022b05
Packit 022b05
    /* print an empty line after global types */
Packit 022b05
    if( smiType->decl != SMI_DECL_IMPLICIT_TYPE && name ) {
Packit 022b05
	fprintf( f, "\n" );
Packit 022b05
    } 
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
static char* getTypePrefix( char *typeName )
Packit 022b05
{
Packit 022b05
    TypePrefix *iterTPr;
Packit 022b05
Packit 022b05
    if( !typeName ) {
Packit 022b05
	return NULL;
Packit 022b05
    }
Packit 022b05
Packit 022b05
    for( iterTPr = typePrefixes; iterTPr; iterTPr = iterTPr->next ) {
Packit 022b05
	if( ! strcmp( iterTPr->type, typeName ) ) {
Packit 022b05
	    return iterTPr->prefix;
Packit 022b05
	}
Packit 022b05
    }
Packit 022b05
Packit 022b05
    return NULL;
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
static void fprintAnnotationElem( FILE *f, SmiNode *smiNode ) {
Packit 022b05
    int i;
Packit 022b05
    
Packit 022b05
    fprintSegment( f, 1, "<xsd:annotation>\n");
Packit 022b05
    fprintSegment( f, 1, "<xsd:appinfo>\n");
Packit 022b05
Packit 022b05
    if( smiNode->nodekind == SMI_NODEKIND_ROW &&
Packit 022b05
	( smiNode->implied || smiNode->create ) ) {
Packit 022b05
	fprintSegment( f, 0, "
Packit 022b05
	if( smiNode->implied ) {
Packit 022b05
	    fprintf( f, " implied=\"yes\"" );
Packit 022b05
	}
Packit 022b05
	if( smiNode->create ) {
Packit 022b05
	    fprintf( f, " create=\"yes\"" );
Packit 022b05
	}
Packit 022b05
	fprintf( f, "/>\n" );
Packit 022b05
    }
Packit 022b05
    
Packit 022b05
    fprintSegment( f, 0, "<maxAccess>%s</maxAccess>\n",
Packit 022b05
		   getStringAccess( smiNode->access ) );
Packit 022b05
    fprintSegment( f, 0, "<oid>");
Packit 022b05
    for (i = 0; i < smiNode->oidlen; i++) {
Packit 022b05
	fprintf(f, i ? ".%u" : "%u", smiNode->oid[i]);
Packit 022b05
    }
Packit 022b05
    fprintf( f, "</oid>\n" );
Packit 022b05
Packit 022b05
    fprintSegment( f, 0, "<status>%s</status>\n",
Packit 022b05
		   getStringStatus( smiNode->status ) );
Packit 022b05
    if( smiNode->value.basetype != SMI_BASETYPE_UNKNOWN ) {
Packit 022b05
	char *defval = smiRenderValue( &smiNode->value,
Packit 022b05
				       smiGetNodeType( smiNode ),
Packit 022b05
				       SMI_RENDER_FORMAT | SMI_RENDER_NAME );
Packit 022b05
	fprintSegment( f, 0, "<default>%s</default>\n", defval );
Packit 022b05
Packit 022b05
    }
Packit 022b05
Packit 022b05
Packit 022b05
    if( smiNode->format ) {
Packit 022b05
	fprintDisplayHint( f, smiNode->format );
Packit 022b05
    }
Packit 022b05
Packit 022b05
    if( smiNode->units ) {
Packit 022b05
	fprintSegment( f, 0, "<units>%s</units>\n", smiNode->units );
Packit 022b05
    }
Packit 022b05
  
Packit 022b05
    fprintSegment( f, -1, "</xsd:appinfo>\n");
Packit 022b05
    fprintDocumentation( f, smiNode->description );
Packit 022b05
    fprintSegment( f, -1, "</xsd:annotation>\n");
Packit 022b05
    
Packit 022b05
}
Packit 022b05
Packit 022b05
static int hasChildren( SmiNode *smiNode, SmiNodekind nodekind )
Packit 022b05
{
Packit 022b05
    SmiNode *iterNode;
Packit 022b05
    int childNodeCount = 0; 
Packit 022b05
Packit 022b05
    for( iterNode = smiGetFirstChildNode( smiNode );
Packit 022b05
	 iterNode;
Packit 022b05
	 iterNode = smiGetNextChildNode( iterNode ) ){
Packit 022b05
	if( nodekind & iterNode->nodekind ) {
Packit 022b05
	    childNodeCount++;
Packit 022b05
	}
Packit 022b05
    }
Packit 022b05
    return childNodeCount;
Packit 022b05
}
Packit 022b05
Packit 022b05
static void
Packit 022b05
fprintTypeWithHint( FILE *f, SmiNode *smiNode, SmiType *smiType, char *hint )
Packit 022b05
{
Packit 022b05
    char *pattern;
Packit 022b05
    
Packit 022b05
    fprintSegment( f, 1, "<xsd:simpleType>\n");
Packit 022b05
    fprintSegment( f, 1, "<xsd:annotation>\n");
Packit 022b05
    fprintSegment( f, 1, "<xsd:appinfo>\n");
Packit 022b05
    fprintDisplayHint( f, hint );
Packit 022b05
    fprintSegment( f, -1, "</xsd:appinfo>\n");
Packit 022b05
    fprintSegment( f, -1, "</xsd:annotation>\n");
Packit 022b05
    fprintSegment( f, 1, "<xsd:restriction base=\"xsd:string\">\n");
Packit 022b05
Packit 022b05
    pattern = smiFormatToPattern(hint, smiGetFirstRange(smiType));
Packit 022b05
    if (pattern) {
Packit 022b05
        fprintSegment( f, 0, "<xsd:pattern value=\"%s\"/>\n", pattern);
Packit 022b05
	xfree(pattern);
Packit 022b05
    }
Packit 022b05
    fprintSegment( f, -1, "</xsd:restriction>\n");
Packit 022b05
    fprintSegment( f, -1, "</xsd:simpleType>\n");
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
static char *getParentDisplayHint( SmiType *smiType )
Packit 022b05
{
Packit 022b05
    SmiType *iterType;
Packit 022b05
Packit 022b05
    for( iterType = smiGetParentType( smiType );
Packit 022b05
	 iterType;
Packit 022b05
	 iterType = smiGetParentType( iterType ) ) {
Packit 022b05
	if( iterType->format ) {
Packit 022b05
	    return iterType->format;
Packit 022b05
	}	
Packit 022b05
    }
Packit 022b05
    return NULL;
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
static void fprintIndexAttr( FILE *f, SmiNode *smiNode, SmiNode *augments )
Packit 022b05
{
Packit 022b05
    char *typeName, *prefix;
Packit 022b05
    SmiType *smiType;
Packit 022b05
Packit 022b05
    smiType = smiGetNodeType( smiNode );
Packit 022b05
    if( !smiType ) {
Packit 022b05
/*	fprint( f, "\n", smiNode->name );*/
Packit 022b05
	return;
Packit 022b05
    }
Packit 022b05
Packit 022b05
    typeName = smiType->name ?
Packit 022b05
	smiType->name :
Packit 022b05
	getStringBasetype( smiType->basetype );
Packit 022b05
    prefix = getTypePrefix( typeName );
Packit 022b05
    
Packit 022b05
Packit 022b05
    if( smiType->basetype == SMI_BASETYPE_BITS ) {
Packit 022b05
	    fprintSegment( f, 1, "
Packit 022b05
			   "use=\"required\">\n",
Packit 022b05
			   smiNode->name,
Packit 022b05
			   smiNode->name,
Packit 022b05
			   getStringBasetype( smiType->basetype ) );
Packit 022b05
	    fprintAnnotationElem( f, smiNode );
Packit 022b05
    }
Packit 022b05
Packit 022b05
    else if( smiType->basetype == SMI_BASETYPE_OCTETSTRING ) {	    
Packit 022b05
	
Packit 022b05
	if( smiType->decl == SMI_DECL_IMPLICIT_TYPE ) {
Packit 022b05
	    char *hint = getParentDisplayHint( smiType );
Packit 022b05
	    
Packit 022b05
	    fprintSegment( f, 1, "
Packit 022b05
			   "use=\"required\">\n", smiNode->name );
Packit 022b05
	    fprintAnnotationElem( f, smiNode );
Packit 022b05
	    if( ! hint ) {
Packit 022b05
		fprintTypedef( f, smiType, NULL );
Packit 022b05
	    }
Packit 022b05
	    else {
Packit 022b05
		fprintTypeWithHint( f, smiNode, smiType, hint );
Packit 022b05
	    }
Packit 022b05
	}
Packit 022b05
	
Packit 022b05
	else {
Packit 022b05
	    if( prefix ) {
Packit 022b05
		fprintSegment( f, 1, "
Packit 022b05
			       "type=\"%s:%s\" use=\"required\">\n",
Packit 022b05
			       smiNode->name, prefix, typeName );
Packit 022b05
	    }
Packit 022b05
	    else {		    
Packit 022b05
		fprintSegment( f, 1, "
Packit 022b05
			       "type=\"%s\" use=\"required\">\n",
Packit 022b05
			       smiNode->name, typeName );
Packit 022b05
	    }
Packit 022b05
	    fprintAnnotationElem( f, smiNode );
Packit 022b05
	}
Packit 022b05
    }
Packit 022b05
    
Packit 022b05
    /* check for other (implicit) types */
Packit 022b05
    else if( smiType->decl == SMI_DECL_IMPLICIT_TYPE ) {
Packit 022b05
	fprintSegment( f, 1, "
Packit 022b05
		       "use=\"required\">\n",
Packit 022b05
		       smiNode->name );
Packit 022b05
	fprintAnnotationElem( f, smiNode );
Packit 022b05
	fprintTypedef( f, smiType, NULL );
Packit 022b05
    }
Packit 022b05
    
Packit 022b05
    else {	
Packit 022b05
	if( prefix ) {
Packit 022b05
	    fprintSegment( f, 1,"
Packit 022b05
			   smiNode->name, prefix, typeName );
Packit 022b05
	    fprintf( f, "use=\"required\">\n" );
Packit 022b05
	}
Packit 022b05
	else {
Packit 022b05
	    fprintSegment( f, 1, "
Packit 022b05
			   smiNode->name, typeName );
Packit 022b05
	    fprintf( f, "use=\"required\">\n" );
Packit 022b05
	}
Packit 022b05
	
Packit 022b05
	if( augments ) {
Packit 022b05
	    fprintSegment( f, 1, "<xsd:annotation>\n");
Packit 022b05
	    fprintSegment( f, 1, "<xsd:appinfo>\n");
Packit 022b05
	    fprintSegment( f, 0, "<augments>%s</augments>\n", augments->name );
Packit 022b05
	    fprintSegment( f, -1, "</xsd:appinfo>\n");
Packit 022b05
	    fprintSegment( f, -1, "</xsd:annotation>\n");
Packit 022b05
	}
Packit 022b05
	else {
Packit 022b05
	    fprintAnnotationElem( f, smiNode );
Packit 022b05
	    }
Packit 022b05
    }
Packit 022b05
    fprintSegment( f, -1, "</xsd:attribute>\n"); 
Packit 022b05
}
Packit 022b05
Packit 022b05
static int containsIndex( SmiNode *parentNode, SmiNode *idxNode )
Packit 022b05
{
Packit 022b05
    SmiElement *iterElement;
Packit 022b05
Packit 022b05
Packit 022b05
    for( iterElement = smiGetFirstElement( parentNode );
Packit 022b05
	 iterElement;
Packit 022b05
	 iterElement = smiGetNextElement( iterElement ) ) {
Packit 022b05
	SmiNode *iterNode = smiGetElementNode( iterElement );	
Packit 022b05
	if( iterNode == idxNode )
Packit 022b05
	    return 1;
Packit 022b05
    }
Packit 022b05
    return 0;
Packit 022b05
}
Packit 022b05
Packit 022b05
static void fprintIndex( FILE *f,
Packit 022b05
			 SmiNode *smiNode, SmiNode *augments, SmiNode *parent )
Packit 022b05
{
Packit 022b05
    SmiNode *iterNode;
Packit 022b05
    SmiElement *iterElem;
Packit 022b05
  
Packit 022b05
    /* iterate INDEX columns */
Packit 022b05
    for( iterElem = smiGetFirstElement( smiNode );
Packit 022b05
	 iterElem;
Packit 022b05
	 iterElem = smiGetNextElement( iterElem ) ) {
Packit 022b05
	iterNode = smiGetElementNode( iterElem );
Packit 022b05
	if( ! parent || (parent && !containsIndex( parent, iterNode ) ) ) {
Packit 022b05
	    fprintIndexAttr( f, iterNode, augments );
Packit 022b05
	}
Packit 022b05
    }
Packit 022b05
Packit 022b05
    /* print AUGMENTS-clause */
Packit 022b05
    iterNode = smiGetRelatedNode( smiNode );
Packit 022b05
    if( iterNode ) {
Packit 022b05
	fprintIndex( f, iterNode, iterNode, NULL );
Packit 022b05
    }
Packit 022b05
}
Packit 022b05
Packit 022b05
/* counts index elements of a table row node */
Packit 022b05
static int numIndex( SmiNode *smiNode )
Packit 022b05
{
Packit 022b05
    SmiElement *iterElem;
Packit 022b05
    int ret = 0;
Packit 022b05
Packit 022b05
    for( iterElem = smiGetFirstElement( smiNode );
Packit 022b05
	 iterElem;
Packit 022b05
	 iterElem = smiGetNextElement( iterElem ) ) {
Packit 022b05
	ret++;
Packit 022b05
    }
Packit 022b05
    return ret;
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
/* checks if the second node is a subtable of the first node */
Packit 022b05
static int
Packit 022b05
isSubTable( SmiNode *smiNode, SmiNode *subNode )
Packit 022b05
{
Packit 022b05
    SmiElement *iterElement;
Packit 022b05
    unsigned int numIdx = numIndex( smiNode ), numSubIdx = numIndex( subNode );
Packit 022b05
Packit 022b05
    /* compare number of index elements */
Packit 022b05
    if( numSubIdx <= numIdx ) {
Packit 022b05
	/* does not have more index elements --> no subtable */
Packit 022b05
	return 0;
Packit 022b05
    }
Packit 022b05
Packit 022b05
    /* compare all index elements */
Packit 022b05
    for( iterElement = smiGetFirstElement( smiNode );
Packit 022b05
	 iterElement;
Packit 022b05
	 iterElement = smiGetNextElement( iterElement ) ) {
Packit 022b05
	SmiElement *iterSubElement = smiGetFirstElement( subNode );
Packit 022b05
	SmiNode *iterSubNode;
Packit 022b05
	SmiNode *idxNode = smiGetElementNode( iterElement );
Packit 022b05
	
Packit 022b05
	for( iterSubElement = smiGetFirstElement( subNode );
Packit 022b05
	     iterSubElement;
Packit 022b05
	     iterSubElement = smiGetNextElement( iterSubElement ) ) {
Packit 022b05
	    
Packit 022b05
	    iterSubNode = smiGetElementNode( iterSubElement );
Packit 022b05
	    if( idxNode == iterSubNode ){
Packit 022b05
		return 1;
Packit 022b05
	    }
Packit 022b05
	}
Packit 022b05
    }
Packit 022b05
    return 0;
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
static void fprintComplexType( FILE *f, SmiNode *smiNode, const char *name,
Packit 022b05
			       SmiNode *parent )
Packit 022b05
{
Packit 022b05
    SmiNode *iterNode;
Packit 022b05
    int numChildren;
Packit 022b05
    
Packit 022b05
    if( name ) {
Packit 022b05
	fprintSegment( f, 1, "<xsd:complexType name=\"%sType\">\n",
Packit 022b05
		       smiNode->name );
Packit 022b05
    } else {
Packit 022b05
	fprintSegment( f, 1, "<xsd:complexType>\n" );
Packit 022b05
    }
Packit 022b05
Packit 022b05
/*    fprintAnnotationElem( f, smiNode ); */
Packit 022b05
Packit 022b05
    numChildren = hasChildren( smiNode, SMI_NODEKIND_ANY );
Packit 022b05
Packit 022b05
    fprintSegment( f, 1, "<xsd:sequence>\n");
Packit 022b05
Packit 022b05
    /* print child elements */
Packit 022b05
    for( iterNode = smiGetFirstChildNode( smiNode );
Packit 022b05
	 iterNode;
Packit 022b05
	 iterNode = smiGetNextChildNode( iterNode ) ) {
Packit 022b05
	
Packit 022b05
	fprintElement( f, iterNode, NULL );
Packit 022b05
	
Packit 022b05
    }
Packit 022b05
Packit 022b05
    /* print augmentations */
Packit 022b05
    if( nestAugmentedTables ) {
Packit 022b05
	for( iterNode = smiGetFirstNode( smiGetNodeModule( smiNode ),
Packit 022b05
					 SMI_NODEKIND_ROW );
Packit 022b05
	     iterNode;
Packit 022b05
	     iterNode = smiGetNextNode( iterNode, SMI_NODEKIND_ROW ) ) {
Packit 022b05
	    SmiNode *augmNode = smiGetRelatedNode( iterNode );
Packit 022b05
	    if( augmNode == smiNode ) {
Packit 022b05
		SmiNode *augIterNode;
Packit 022b05
		for( augIterNode = smiGetFirstChildNode( iterNode );
Packit 022b05
		     augIterNode;
Packit 022b05
		     augIterNode = smiGetNextChildNode( augIterNode ) ) {
Packit 022b05
		    
Packit 022b05
		    fprintElement( f, augIterNode, NULL );
Packit 022b05
		}
Packit 022b05
	    }
Packit 022b05
	}
Packit 022b05
    }
Packit 022b05
    
Packit 022b05
    /* print subtables */
Packit 022b05
    if( nestSubtables ) {
Packit 022b05
	for( iterNode = smiGetFirstNode( smiGetNodeModule( smiNode ),
Packit 022b05
					 SMI_NODEKIND_ROW );
Packit 022b05
	     iterNode;
Packit 022b05
	     iterNode = smiGetNextNode( iterNode, SMI_NODEKIND_ROW ) ) {
Packit 022b05
	    if( isSubTable( smiNode, iterNode ) ) {
Packit 022b05
/*	    fputs( "\n", f );*/
Packit 022b05
		fprintElement( f, iterNode, smiNode );
Packit 022b05
/*	    fputs( "\n", f );*/
Packit 022b05
	    }
Packit 022b05
	}
Packit 022b05
    }
Packit 022b05
    
Packit 022b05
    fprintSegment( f, -1, "</xsd:sequence>\n");
Packit 022b05
    fprintIndex( f, smiNode, NULL, parent );
Packit 022b05
    
Packit 022b05
    fprintSegment( f, -1, "</xsd:complexType>\n");
Packit 022b05
    if( name ) {
Packit 022b05
	/* we are printing out a global type,
Packit 022b05
	   so let's leave a blank line after it. */
Packit 022b05
	fprintf( f, "\n" );
Packit 022b05
    }
Packit 022b05
Packit 022b05
    for( iterNode = smiGetFirstChildNode( smiNode );
Packit 022b05
	 iterNode;
Packit 022b05
	 iterNode = smiGetNextChildNode( iterNode ) ) {
Packit 022b05
	if( iterNode->nodekind == SMI_NODEKIND_NODE ) {
Packit 022b05
	    fprintComplexType( f, iterNode, iterNode->name, NULL );
Packit 022b05
	}
Packit 022b05
    }
Packit 022b05
Packit 022b05
}    
Packit 022b05
Packit 022b05
Packit 022b05
static void fprintElement( FILE *f, SmiNode *smiNode, SmiNode *parentNode )
Packit 022b05
{
Packit 022b05
    switch( smiNode->nodekind ) {
Packit 022b05
	SmiType *smiType;
Packit 022b05
Packit 022b05
    case SMI_NODEKIND_NODE :
Packit 022b05
	{
Packit 022b05
	    SmiNode *iterNode;
Packit 022b05
Packit 022b05
	    fprintSegment( f, 1, "<xsd:element name=\"%s\">\n", smiNode->name);
Packit 022b05
	    fprintSegment( f, 1, "<xsd:complexType>\n");
Packit 022b05
	    fprintSegment( f, 1, "<xsd:sequence>\n");
Packit 022b05
	    for( iterNode = smiGetFirstChildNode( smiNode );
Packit 022b05
		 iterNode;
Packit 022b05
		 iterNode = smiGetNextChildNode( iterNode ) ) {
Packit 022b05
		if( iterNode->nodekind == SMI_NODEKIND_SCALAR ) {
Packit 022b05
		    fprintElement( f, iterNode, NULL );
Packit 022b05
		}
Packit 022b05
	    }
Packit 022b05
	    fprintSegment( f, -1, "</xsd:sequence>\n");
Packit 022b05
	    fprintSegment( f, -1, "</xsd:complexType>\n");
Packit 022b05
	    fprintSegment( f, -1, "</xsd:element>\n");
Packit 022b05
	}
Packit 022b05
	break;
Packit 022b05
	
Packit 022b05
    case SMI_NODEKIND_TABLE :
Packit 022b05
    {
Packit 022b05
	SmiNode *iterNode;
Packit 022b05
	
Packit 022b05
	/* ignore tables and just include their entries */
Packit 022b05
	for( iterNode = smiGetFirstChildNode( smiNode );
Packit 022b05
	     iterNode;
Packit 022b05
	     iterNode = smiGetNextChildNode( iterNode ) ) {
Packit 022b05
	    fprintElement( f, iterNode, NULL );
Packit 022b05
	}
Packit 022b05
	break;
Packit 022b05
    }
Packit 022b05
Packit 022b05
    case SMI_NODEKIND_ROW:
Packit 022b05
       
Packit 022b05
	fprintSegment( f, 1, "
Packit 022b05
		       "minOccurs=\"0\" maxOccurs=\"unbounded\">\n",
Packit 022b05
		       smiNode->name );
Packit 022b05
	
Packit 022b05
	fprintAnnotationElem( f, smiNode );
Packit 022b05
	
Packit 022b05
	fprintComplexType( f, smiNode, NULL, parentNode );
Packit 022b05
	fprintSegment( f, -1, "</xsd:element>\n");	
Packit 022b05
	break;
Packit 022b05
    
Packit 022b05
    case SMI_NODEKIND_SCALAR:
Packit 022b05
    case SMI_NODEKIND_COLUMN:
Packit 022b05
    {
Packit 022b05
	SmiElement *iterElem;
Packit 022b05
	char *prefix;
Packit 022b05
	char *typeName;
Packit 022b05
	
Packit 022b05
	/* check if we are index column */
Packit 022b05
	for( iterElem = smiGetFirstElement( smiGetParentNode( smiNode ) ) ;
Packit 022b05
	     iterElem;
Packit 022b05
	     iterElem = smiGetNextElement( iterElem ) ) {
Packit 022b05
	    if( smiNode == smiGetElementNode( iterElem ) ) {
Packit 022b05
		/* we are index coulumn ==> do not print element */
Packit 022b05
		return;
Packit 022b05
	    }
Packit 022b05
	}
Packit 022b05
	
Packit 022b05
	if( smiNode->access < SMI_ACCESS_READ_ONLY ) {
Packit 022b05
	    /* only print accessible nodes */
Packit 022b05
	    return;
Packit 022b05
	}
Packit 022b05
	
Packit 022b05
	smiType = smiGetNodeType( smiNode );
Packit 022b05
Packit 022b05
	if( smiType->name ) {
Packit 022b05
	    typeName = smiType->name;
Packit 022b05
	}
Packit 022b05
	else {
Packit 022b05
	    typeName = getStringBasetype( smiType->basetype );
Packit 022b05
	}
Packit 022b05
	prefix = getTypePrefix( typeName );
Packit 022b05
Packit 022b05
#if 0
Packit 022b05
	if( smiType->basetype == SMI_BASETYPE_BITS ) {
Packit 022b05
	    fprintSegment( f, 1, "
Packit 022b05
			   "minOccurs=\"0\">\n",
Packit 022b05
			   smiNode->name,
Packit 022b05
			   smiNode->name,
Packit 022b05
			   getStringBasetype( smiType->basetype ) );
Packit 022b05
	    fprintAnnotationElem( f, smiNode );
Packit 022b05
	}
Packit 022b05
	
Packit 022b05
//	else if( smiType->basetype == SMI_BASETYPE_OCTETSTRING ) {
Packit 022b05
#endif /* 0 */
Packit 022b05
Packit 022b05
	if( smiType->basetype == SMI_BASETYPE_OCTETSTRING ) {
Packit 022b05
	    if( smiType->decl == SMI_DECL_IMPLICIT_TYPE ) {
Packit 022b05
Packit 022b05
		char *hint = getParentDisplayHint( smiType );
Packit 022b05
Packit 022b05
		fprintSegment( f, 1, "
Packit 022b05
			       "minOccurs=\"0\">\n", smiNode->name );
Packit 022b05
		fprintAnnotationElem( f, smiNode );
Packit 022b05
		if( ! hint ) {
Packit 022b05
		    fprintTypedef( f, smiType, NULL );
Packit 022b05
		}
Packit 022b05
		else {
Packit 022b05
		    fprintTypeWithHint( f, smiNode, smiType, hint );
Packit 022b05
		}
Packit 022b05
	    }
Packit 022b05
Packit 022b05
	    else {
Packit 022b05
		if( prefix ) {
Packit 022b05
		    fprintSegment( f, 1, "
Packit 022b05
				   "type=\"%s:%s\" minOccurs=\"0\">\n",
Packit 022b05
				   smiNode->name, prefix, typeName );
Packit 022b05
		}
Packit 022b05
		else {		    
Packit 022b05
		    fprintSegment( f, 1, "
Packit 022b05
				   "type=\"%s\" minOccurs=\"0\">\n",
Packit 022b05
				   smiNode->name, typeName );
Packit 022b05
		}
Packit 022b05
		fprintAnnotationElem( f, smiNode );
Packit 022b05
	    }	   	   
Packit 022b05
	}
Packit 022b05
Packit 022b05
	else if( smiType->decl == SMI_DECL_IMPLICIT_TYPE ) {
Packit 022b05
	    fprintSegment( f, 1, "<xsd:element name=\"%s\" minOccurs=\"0\">\n",
Packit 022b05
			   smiNode->name );
Packit 022b05
	    fprintAnnotationElem( f, smiNode );
Packit 022b05
	    fprintTypedef( f, smiType, NULL );
Packit 022b05
	}
Packit 022b05
	
Packit 022b05
	else {
Packit 022b05
	    if( prefix ) {
Packit 022b05
		fprintSegment( f, 1, "
Packit 022b05
			       "minOccurs=\"0\">\n",
Packit 022b05
			       smiNode->name, prefix, typeName );
Packit 022b05
	    }
Packit 022b05
	    else {
Packit 022b05
		fprintSegment( f, 1, "
Packit 022b05
			       "minOccurs=\"0\">\n",
Packit 022b05
			       smiNode->name, typeName );
Packit 022b05
	    }
Packit 022b05
	    fprintAnnotationElem( f, smiNode );
Packit 022b05
	}
Packit 022b05
	fprintSegment( f, -1, "</xsd:element>\n"); 
Packit 022b05
	break;
Packit 022b05
    }
Packit 022b05
Packit 022b05
    case SMI_NODEKIND_NOTIFICATION:
Packit 022b05
	fprintSegment( f, 0, "<xsd:element name=\"%s\"/>\n", smiNode->name );
Packit 022b05
	break;
Packit 022b05
Packit 022b05
    default:
Packit 022b05
	fprintf( f, "
Packit 022b05
	fprintf( f, "      Nodekind: %#4x -->\n\n", smiNode->nodekind );
Packit 022b05
	
Packit 022b05
    }
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
static void fprintImplicitTypes( FILE *f, SmiModule *smiModule )
Packit 022b05
{
Packit 022b05
    SmiNode *iterNode;
Packit 022b05
    SmiType *smiType;
Packit 022b05
Packit 022b05
    for(iterNode = smiGetFirstNode(smiModule,
Packit 022b05
				   SMI_NODEKIND_SCALAR | SMI_NODEKIND_COLUMN);
Packit 022b05
	iterNode;
Packit 022b05
	iterNode = smiGetNextNode(iterNode,
Packit 022b05
				  SMI_NODEKIND_SCALAR | SMI_NODEKIND_COLUMN)) {
Packit 022b05
	smiType = smiGetNodeType( iterNode );
Packit 022b05
	if( smiType ) {
Packit 022b05
		switch( smiType->basetype ) {
Packit 022b05
		    
Packit 022b05
		case SMI_BASETYPE_BITS:
Packit 022b05
		    if( ! getTypePrefix( smiType->name ) ) {
Packit 022b05
			fprintTypedef( f, smiType, iterNode->name );
Packit 022b05
			break;
Packit 022b05
		    }
Packit 022b05
Packit 022b05
		case SMI_BASETYPE_OCTETSTRING:
Packit 022b05
#if 0
Packit 022b05
		    if( smiType->decl == SMI_DECL_IMPLICIT_TYPE ) {
Packit 022b05
			fprintTypedef( f, INDENT, smiType, iterNode->name );
Packit 022b05
		    }
Packit 022b05
#endif /* 0 */
Packit 022b05
		    break;
Packit 022b05
		default:
Packit 022b05
		    break;
Packit 022b05
		}
Packit 022b05
	}
Packit 022b05
    }
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
#if 0
Packit 022b05
static void fprintRows( FILE *f, SmiModule *smiModule )
Packit 022b05
{
Packit 022b05
    SmiNode *iterNode;
Packit 022b05
Packit 022b05
    for( iterNode = smiGetFirstNode( smiModule, SMI_NODEKIND_ROW );
Packit 022b05
	 iterNode;
Packit 022b05
	 iterNode = smiGetNextNode( iterNode,  SMI_NODEKIND_ROW ) ) {
Packit 022b05
	if( hasChildren( iterNode, SMI_NODEKIND_COLUMN | SMI_NODEKIND_TABLE ) ){
Packit 022b05
	    fprintElement( f, iterNode, NULL );
Packit 022b05
	}
Packit 022b05
    }
Packit 022b05
}
Packit 022b05
#endif
Packit 022b05
Packit 022b05
static void fprintImports( FILE *f, SmiModule *smiModule )
Packit 022b05
{
Packit 022b05
    SmiImport *iterImp;
Packit 022b05
    char *lastModName = "";
Packit 022b05
    
Packit 022b05
    fprintSegment( f, 0, "<xsd:import namespace=\"%ssmi\" schemaLocation=\"%ssmi.xsd\"/>\n", schemaLocation, schemaLocation );
Packit 022b05
    for( iterImp = smiGetFirstImport( smiModule );
Packit 022b05
	 iterImp;
Packit 022b05
	 iterImp = smiGetNextImport( iterImp ) ) {
Packit 022b05
	/* assume imports to be ordered by module names */
Packit 022b05
	if( strcmp( iterImp->module, lastModName ) ) {
Packit 022b05
	    fprintSegment( f, 0, "
Packit 022b05
	    fprintf( f, "namespace=\"%s%s\" schemaLocation=\"%s%s.xsd\"/>\n",
Packit 022b05
		    schemaLocation, iterImp->module,
Packit 022b05
		    schemaLocation, iterImp->module );
Packit 022b05
	}
Packit 022b05
	lastModName = iterImp->module;
Packit 022b05
    }
Packit 022b05
    fprintf( f, "\n");
Packit 022b05
   
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
/*
Packit 022b05
 * Check if given table io a sub table of another table.
Packit 022b05
 * If so, its parent table is returned (NULL otherwise).
Packit 022b05
 */
Packit 022b05
static SmiNode *isASubTable( SmiNode *smiNode, SmiModule *smiModule )
Packit 022b05
{
Packit 022b05
    SmiNode *iterNode;
Packit 022b05
    int numIdxDiff = -1;
Packit 022b05
    SmiNode *retNode = NULL;
Packit 022b05
    
Packit 022b05
    for( iterNode = smiGetFirstNode( smiModule,
Packit 022b05
				     SMI_NODEKIND_ROW );
Packit 022b05
	 iterNode;
Packit 022b05
	 iterNode = smiGetNextNode( iterNode,
Packit 022b05
				    SMI_NODEKIND_ROW ) ) {
Packit 022b05
	
Packit 022b05
	if( isSubTable( iterNode, smiNode ) ) {
Packit 022b05
Packit 022b05
	    if( (numIdxDiff == -1) ||
Packit 022b05
		((numIndex( smiNode ) - numIndex( iterNode )) < numIdxDiff) ) {
Packit 022b05
		retNode = iterNode;
Packit 022b05
		numIdxDiff = numIndex( smiNode ) - numIndex( iterNode );
Packit 022b05
	    }
Packit 022b05
	    
Packit 022b05
	}
Packit 022b05
    }
Packit 022b05
    return retNode;
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
static void fprintGroupTypes( FILE *f, SmiModule *smiModule )
Packit 022b05
{
Packit 022b05
    SmiNode *iterNode, *iterNode2;
Packit 022b05
Packit 022b05
    /* scalar groups */
Packit 022b05
    for( iterNode = smiGetFirstNode( smiModule, SMI_NODEKIND_NODE );
Packit 022b05
	 iterNode;
Packit 022b05
	 iterNode = smiGetNextNode( iterNode, SMI_NODEKIND_NODE ) ) {
Packit 022b05
	if( hasChildren( iterNode, SMI_NODEKIND_SCALAR ) ) {
Packit 022b05
	    fprintSegment(f, 1, "<xsd:complexType name=\"%sType\">\n",
Packit 022b05
			  iterNode->name);
Packit 022b05
	    fprintSegment( f, 1, "<xsd:sequence>\n");
Packit 022b05
	    for( iterNode2 = smiGetFirstChildNode( iterNode );
Packit 022b05
		 iterNode2;
Packit 022b05
		 iterNode2 = smiGetNextChildNode( iterNode2 ) ) {
Packit 022b05
		if( iterNode2->nodekind == SMI_NODEKIND_SCALAR ) {
Packit 022b05
		    fprintElement( f, iterNode2, NULL );
Packit 022b05
		}
Packit 022b05
	    }
Packit 022b05
	    fprintSegment( f, -1, "</xsd:sequence>\n");
Packit 022b05
	    fprintSegment(f, -1, "</xsd:complexType>\n");
Packit 022b05
	}
Packit 022b05
    }   
Packit 022b05
Packit 022b05
    /* rows */
Packit 022b05
    for( iterNode = smiGetFirstNode( smiModule, SMI_NODEKIND_ROW );
Packit 022b05
	 iterNode;
Packit 022b05
	 iterNode = smiGetNextNode( iterNode,  SMI_NODEKIND_ROW ) ) {
Packit 022b05
	if( hasChildren( iterNode,
Packit 022b05
			 SMI_NODEKIND_COLUMN | SMI_NODEKIND_TABLE ) ){	   
Packit 022b05
Packit 022b05
	    /* skip nested subtables here */
Packit 022b05
	    if( nestSubtables ){
Packit 022b05
		if( isASubTable( iterNode, smiModule ) != NULL ) {
Packit 022b05
		    continue;
Packit 022b05
		}
Packit 022b05
	    }
Packit 022b05
Packit 022b05
	    /* skip table augmentations here */
Packit 022b05
	    if( nestAugmentedTables ) {
Packit 022b05
		if( iterNode->indexkind == SMI_INDEX_AUGMENT ) {
Packit 022b05
		    continue;
Packit 022b05
		}
Packit 022b05
	    }
Packit 022b05
	    
Packit 022b05
	    fprintComplexType( f, iterNode, iterNode->name, NULL );
Packit 022b05
	    
Packit 022b05
	}
Packit 022b05
    }   
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
#if 0
Packit 022b05
static void fprintNotifications( FILE *f, SmiModule *smiModule )
Packit 022b05
{
Packit 022b05
    SmiNode *iterNode;
Packit 022b05
    
Packit 022b05
    for( iterNode = smiGetFirstNode( smiModule, SMI_NODEKIND_NOTIFICATION );
Packit 022b05
	 iterNode;
Packit 022b05
	 iterNode = smiGetNextNode( iterNode, SMI_NODEKIND_NOTIFICATION ) ) {
Packit 022b05
	fprintElement( f, iterNode, NULL );
Packit 022b05
    }
Packit 022b05
}
Packit 022b05
#endif
Packit 022b05
Packit 022b05
Packit 022b05
static void fprintModuleHead(FILE *f, SmiModule *smiModule)
Packit 022b05
{
Packit 022b05
    if( smiModule->description ) {
Packit 022b05
	fprintSegment(f, 1, "<xsd:annotation>\n");
Packit 022b05
	fprintDocumentation(f, smiModule->description);
Packit 022b05
	fprintSegment(f, -1, "</xsd:annotation>\n\n");
Packit 022b05
    }
Packit 022b05
    
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
static void fprintKey( FILE *f, SmiNode *smiNode )
Packit 022b05
{
Packit 022b05
    SmiNode *relNode;
Packit 022b05
    SmiElement *iterElem;
Packit 022b05
    
Packit 022b05
    switch( smiNode->indexkind ) {
Packit 022b05
	
Packit 022b05
    case SMI_INDEX_INDEX:
Packit 022b05
	
Packit 022b05
	/* print key */
Packit 022b05
/*	fprintSegment( f, 1, "
Packit 022b05
	fprintf( f, "name=\"%sKey\">\n", smiNode->name );
Packit 022b05
	fprintSegment( f, 0, "
Packit 022b05
	fprintf( f, "xpath=\"%s\"/>\n", smiNode->name );
Packit 022b05
	for( iterElem = smiGetFirstElement( smiNode );
Packit 022b05
	     iterElem;
Packit 022b05
	     iterElem = smiGetNextElement( iterElem ) ) {
Packit 022b05
	    SmiNode *indexNode = smiGetElementNode( iterElem );
Packit 022b05
	    fprintSegment( f, 0, "
Packit 022b05
	    fprintf( f, "xpath=\"@%s\"/>\n", indexNode->name );
Packit 022b05
	}
Packit 022b05
	fprintSegment( f, -1, "</xsd:key>\n\n");*/
Packit 022b05
	break;
Packit 022b05
	
Packit 022b05
    case SMI_INDEX_AUGMENT:
Packit 022b05
	
Packit 022b05
	/* print keyref */
Packit 022b05
	fprintSegment( f, 1, "
Packit 022b05
	relNode = smiGetRelatedNode( smiNode );
Packit 022b05
	fprintf( f, "name=\"%sKeyRef\" ", smiNode->name );
Packit 022b05
	fprintf( f, "refer=\"%sKey\">\n", relNode->name );
Packit 022b05
	fprintSegment( f, 0, "
Packit 022b05
	fprintf( f, "xpath=\"%s\"/>\n", smiNode->name );
Packit 022b05
	for( iterElem = smiGetFirstElement( relNode );
Packit 022b05
	     iterElem;
Packit 022b05
	     iterElem = smiGetNextElement( iterElem ) ) {
Packit 022b05
	    SmiNode *indexNode = smiGetElementNode( iterElem );
Packit 022b05
	    fprintSegment( f, 0, "
Packit 022b05
	    fprintf( f, "xpath=\"@%s\"/>\n", indexNode->name );
Packit 022b05
	}
Packit 022b05
	fprintSegment( f, -1, "</xsd:keyref>\n");
Packit 022b05
	
Packit 022b05
	/* print unique clause */
Packit 022b05
	fprintSegment( f, 1, "
Packit 022b05
	fprintf( f, "name=\"%sKeyRefUnique\">\n", smiNode->name );
Packit 022b05
	fprintSegment( f, 0, "
Packit 022b05
	fprintf( f, "xpath=\"%s\"/>\n", smiNode->name );
Packit 022b05
	for( iterElem = smiGetFirstElement( relNode );
Packit 022b05
	     iterElem;
Packit 022b05
	     iterElem = smiGetNextElement( iterElem ) ) {
Packit 022b05
	    SmiNode *indexNode = smiGetElementNode( iterElem );
Packit 022b05
	    fprintSegment( f, 0, "
Packit 022b05
	    fprintf( f, "xpath=\"@%s\"/>\n", indexNode->name );
Packit 022b05
	}
Packit 022b05
	fprintSegment( f, -1, "</xsd:unique>\n\n");
Packit 022b05
	break;
Packit 022b05
Packit 022b05
    case SMI_INDEX_REORDER:
Packit 022b05
    case SMI_INDEX_SPARSE:
Packit 022b05
    case SMI_INDEX_EXPAND:
Packit 022b05
	/* SMIng, not implemented yet */
Packit 022b05
	break;
Packit 022b05
	
Packit 022b05
    default:
Packit 022b05
	fprintf( f, "\n" );
Packit 022b05
	break;
Packit 022b05
    }   
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
static void fprintGroupElements(FILE *f, SmiModule *smiModule)
Packit 022b05
{
Packit 022b05
    SmiNode *iterNode;
Packit 022b05
Packit 022b05
    /* scalar groups */
Packit 022b05
    for( iterNode = smiGetFirstNode( smiModule, SMI_NODEKIND_NODE );
Packit 022b05
	 iterNode;
Packit 022b05
	 iterNode = smiGetNextNode( iterNode, SMI_NODEKIND_NODE ) ) {
Packit 022b05
	if( hasChildren( iterNode, SMI_NODEKIND_SCALAR ) ) {
Packit 022b05
	    
Packit 022b05
	    if (container) {
Packit 022b05
		fprintSegment(f, 1, "
Packit 022b05
			      "type=\"%s:%sType\" minOccurs=\"0\">\n",
Packit 022b05
			      iterNode->name,
Packit 022b05
			      smiModule->name, iterNode->name);
Packit 022b05
	    } else {
Packit 022b05
		fprintSegment(f, 1, "
Packit 022b05
			      "type=\"%sType\" minOccurs=\"0\">\n",
Packit 022b05
			      iterNode->name, iterNode->name);
Packit 022b05
	    }
Packit 022b05
	    fprintAnnotationElem( f, iterNode );
Packit 022b05
	    fprintSegment( f, -1, "</xsd:element>\n" );
Packit 022b05
	}
Packit 022b05
    }   
Packit 022b05
Packit 022b05
    /* rows */
Packit 022b05
    for( iterNode = smiGetFirstNode( smiModule, SMI_NODEKIND_ROW );
Packit 022b05
	 iterNode;
Packit 022b05
	 iterNode = smiGetNextNode( iterNode,  SMI_NODEKIND_ROW ) ) {
Packit 022b05
	if( hasChildren( iterNode, SMI_NODEKIND_COLUMN | SMI_NODEKIND_TABLE ) ){
Packit 022b05
	    /* skip nested subtables here */
Packit 022b05
	    if( nestSubtables ){
Packit 022b05
		if( isASubTable( iterNode, smiModule ) != NULL ) {
Packit 022b05
		    continue;
Packit 022b05
		}
Packit 022b05
	    }
Packit 022b05
Packit 022b05
	    /* skip table augmentations here */
Packit 022b05
	    if( nestAugmentedTables ) {
Packit 022b05
		if( iterNode->indexkind == SMI_INDEX_AUGMENT ) {
Packit 022b05
		    continue;
Packit 022b05
		}
Packit 022b05
	    }
Packit 022b05
Packit 022b05
	    if (container) {
Packit 022b05
		fprintSegment(f, 1, "
Packit 022b05
			      "type=\"%s:%sType\" minOccurs=\"0\" "
Packit 022b05
			      "maxOccurs=\"unbounded\">\n",
Packit 022b05
			      iterNode->name,
Packit 022b05
			      smiModule->name, iterNode->name);
Packit 022b05
		fprintKey( f, iterNode );
Packit 022b05
	    } else {
Packit 022b05
		fprintSegment(f, 1, "
Packit 022b05
			      "type=\"%sType\" minOccurs=\"0\" "
Packit 022b05
			      "maxOccurs=\"unbounded\">\n",
Packit 022b05
			      iterNode->name, iterNode->name);
Packit 022b05
	    }
Packit 022b05
	    fprintAnnotationElem( f, iterNode );
Packit 022b05
	    fprintSegment( f, -1, "</xsd:element>\n" );
Packit 022b05
	}
Packit 022b05
    }   
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
static char *getSubTableXPath( SmiNode *smiNode, SmiModule *smiModule )
Packit 022b05
{
Packit 022b05
    char *ret;
Packit 022b05
    SmiNode *parentTable = isASubTable( smiNode, smiModule );
Packit 022b05
Packit 022b05
    if( parentTable ) {
Packit 022b05
	smiAsprintf( &ret, "%s/%s",
Packit 022b05
		     getSubTableXPath( parentTable, smiModule ),
Packit 022b05
		     smiNode->name );
Packit 022b05
    }
Packit 022b05
    else {
Packit 022b05
	smiAsprintf( &ret, "%s", smiNode->name );
Packit 022b05
    }
Packit 022b05
    return ret;   
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
static void fprintKeys( FILE *f, SmiModule *smiModule )
Packit 022b05
{
Packit 022b05
Packit 022b05
    SmiNode *iterNode;
Packit 022b05
Packit 022b05
    for( iterNode = smiGetFirstNode( smiModule, SMI_NODEKIND_ROW );
Packit 022b05
	 iterNode;
Packit 022b05
	 iterNode = smiGetNextNode( iterNode, SMI_NODEKIND_ROW ) ) {
Packit 022b05
Packit 022b05
	SmiElement *iterElem;
Packit 022b05
Packit 022b05
	/* print only keys for base tables */
Packit 022b05
	if( iterNode->indexkind != SMI_INDEX_INDEX ) {
Packit 022b05
	    continue;
Packit 022b05
	}
Packit 022b05
	
Packit 022b05
	/* print key */
Packit 022b05
	fprintSegment( f, 1, "<xsd:key name=\"%sKey\">\n", iterNode->name );
Packit 022b05
	fprintSegment( f, 0, "
Packit 022b05
	fprintf( f, "xpath=\"%s\"/>\n",
Packit 022b05
		 nestSubtables ?
Packit 022b05
		 getSubTableXPath( iterNode, smiModule ) : iterNode->name );
Packit 022b05
	    
Packit 022b05
	for( iterElem = smiGetFirstElement( iterNode );
Packit 022b05
	     iterElem;
Packit 022b05
	     iterElem = smiGetNextElement( iterElem ) ) {
Packit 022b05
	    SmiNode *indexNode = smiGetElementNode( iterElem );
Packit 022b05
	    fprintSegment( f, 0, "
Packit 022b05
	    fprintf( f, "xpath=\"@%s\"/>\n", indexNode->name );
Packit 022b05
	}
Packit 022b05
	fprintSegment( f, -1, "</xsd:key>\n\n");
Packit 022b05
    }
Packit 022b05
    
Packit 022b05
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
static void fprintContextHead(FILE *f)
Packit 022b05
{
Packit 022b05
    fprintSegment( f, 1, "<xsd:element name=\"snmp-data\">\n");
Packit 022b05
    fprintSegment( f, 1, "<xsd:complexType>\n");
Packit 022b05
    fprintSegment( f, 1, "<xsd:sequence>\n");
Packit 022b05
    fprintSegment( f, 1, "
Packit 022b05
		   "minOccurs=\"0\" maxOccurs=\"unbounded\">\n");
Packit 022b05
    fprintSegment( f, 1, "<xsd:complexType>\n");
Packit 022b05
    fprintSegment( f, 1, "<xsd:sequence>\n");
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
static void fprintContextFoot(FILE *f, SmiModule **modv, int modc)
Packit 022b05
{
Packit 022b05
    int i;
Packit 022b05
    
Packit 022b05
    fprintSegment( f, -1, "</xsd:sequence>\n");
Packit 022b05
    fprintSegment( f, 0, "<xsd:attribute name=\"ipaddr\" type=\"xsd:NMTOKEN\" use=\"required\"/>\n");
Packit 022b05
    fprintSegment( f, 0, "<xsd:attribute name=\"hostname\" type=\"xsd:NMTOKEN\"/>\n");
Packit 022b05
    fprintSegment( f, 0, "<xsd:attribute name=\"port\" type=\"xsd:unsignedInt\" use=\"required\"/>\n");
Packit 022b05
    fprintSegment( f, 0, "<xsd:attribute name=\"community\" type=\"xsd:NMTOKEN\" use=\"required\"/>\n");
Packit 022b05
    fprintSegment( f, 0, "<xsd:attribute name=\"caching\" type=\"xsd:NMTOKEN\"/>\n");
Packit 022b05
    fprintSegment( f, 0, "<xsd:attribute name=\"time\" type=\"xsd:dateTime\" use=\"required\"/>\n");
Packit 022b05
    fprintSegment( f, -1, "</xsd:complexType>\n");
Packit 022b05
    fprintSegment( f, -1, "</xsd:element>\n");
Packit 022b05
    fprintSegment( f, -1, "</xsd:sequence>\n");
Packit 022b05
    fprintSegment( f, -1, "</xsd:complexType>\n");
Packit 022b05
Packit 022b05
    for( i=0; i < modc; i++ ) {
Packit 022b05
	fprintKeys( f, modv[ i ] );
Packit 022b05
    }
Packit 022b05
    fprintSegment( f, -1, "</xsd:element>\n\n");
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
static void fprintTypedefs(FILE *f, SmiModule *smiModule)
Packit 022b05
{
Packit 022b05
    int		 i;
Packit 022b05
    SmiType	 *smiType;
Packit 022b05
    
Packit 022b05
    for(i = 0, smiType = smiGetFirstType(smiModule);
Packit 022b05
	smiType;
Packit 022b05
	i++, smiType = smiGetNextType(smiType)) {
Packit 022b05
	fprintf(f, "\n");
Packit 022b05
	fprintTypedef(f, smiType, smiType->name);
Packit 022b05
    }
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
static void registerType( char *type, char *module )
Packit 022b05
{
Packit 022b05
    TypePrefix *oldTPr = NULL, *iterTPr = NULL;
Packit 022b05
Packit 022b05
    for( iterTPr = typePrefixes; iterTPr; iterTPr = iterTPr->next ) {
Packit 022b05
	oldTPr = iterTPr;
Packit 022b05
    }
Packit 022b05
    if( ! oldTPr ) {
Packit 022b05
	/* type prefixes do not exist yet */
Packit 022b05
	typePrefixes = xmalloc( sizeof( TypePrefix ) );
Packit 022b05
	typePrefixes->type = type;
Packit 022b05
	typePrefixes->prefix = module;
Packit 022b05
	typePrefixes->next = NULL;
Packit 022b05
    }
Packit 022b05
    else {
Packit 022b05
	/* create new TypePrefix */
Packit 022b05
	oldTPr->next = xmalloc( sizeof( TypePrefix ) );
Packit 022b05
	oldTPr->next->type = type;
Packit 022b05
	oldTPr->next->prefix = module;
Packit 022b05
	oldTPr->next->next = NULL;
Packit 022b05
    }
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
static void dumpXsdModules(int modc, SmiModule **modv, int flags, char *output)
Packit 022b05
{
Packit 022b05
    int  i;
Packit 022b05
    FILE *f = stdout;
Packit 022b05
    SmiImport *iterImp;
Packit 022b05
    char *lastModName = "";
Packit 022b05
Packit 022b05
    if (output) {
Packit 022b05
	f = fopen(output, "w");
Packit 022b05
	if (!f) {
Packit 022b05
	    fprintf(stderr, "smidump: cannot open %s for writing: ", output);
Packit 022b05
	    perror(NULL);
Packit 022b05
	    exit(1);
Packit 022b05
	}
Packit 022b05
    }
Packit 022b05
Packit 022b05
    for (i = 0; i < modc; i++) {
Packit 022b05
Packit 022b05
	fprintf(f, "\n"); 
Packit 022b05
	fprintf(f, "
Packit 022b05
	       SMI_VERSION_STRING ". Do not edit. -->\n");
Packit 022b05
	
Packit 022b05
	fputs( "
Packit 022b05
	fprintf(f, "%s ", schemaLocation);
Packit 022b05
	fputs( "are subject to changes. -->\n\n", f );
Packit 022b05
Packit 022b05
	fprintSegment(f, 1, "
Packit 022b05
	fprintf(f, "targetNamespace=\"%s%s\"\n",
Packit 022b05
		schemaLocation, modv[i]->name);
Packit 022b05
    
Packit 022b05
	fprintf(f, "            xmlns=\"%s%s\"\n",
Packit 022b05
		schemaLocation, modv[i]->name);
Packit 022b05
/*      fprintf(f, "            xmlns:xmn=\"http://www.w3.org/XML/1998/namespace\"\n"); */
Packit 022b05
	fprintf(f, "            xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n");
Packit 022b05
	fprintf(f, "            xmlns:smi=\"%ssmi\"\n", schemaLocation);
Packit 022b05
    
Packit 022b05
	for( iterImp = smiGetFirstImport( modv[i] );
Packit 022b05
	     iterImp;
Packit 022b05
	     iterImp = smiGetNextImport( iterImp ) ) {
Packit 022b05
	    registerType( iterImp->name, iterImp->module );
Packit 022b05
	    /* assume imports to be ordered by module names */
Packit 022b05
	    if( strcmp( iterImp->module, lastModName ) ) {
Packit 022b05
		fprintf( f, "            xmlns:%s=\"%s%s\"\n",
Packit 022b05
			 iterImp->module, schemaLocation, iterImp->module );
Packit 022b05
	    }
Packit 022b05
	    lastModName = iterImp->module;
Packit 022b05
	}
Packit 022b05
  
Packit 022b05
	fprintf(f, "            xml:lang=\"en\"\n");
Packit 022b05
	fprintf(f, "            elementFormDefault=\"qualified\"\n");
Packit 022b05
	fprintf(f, "            attributeFormDefault=\"unqualified\">\n\n");
Packit 022b05
Packit 022b05
	fprintModuleHead(f, modv[i]);
Packit 022b05
	fprintImports(f, modv[i]);
Packit 022b05
	fprintContextHead(f);
Packit 022b05
	fprintGroupElements(f, modv[i]);
Packit 022b05
	fprintContextFoot(f, modv, 0);
Packit 022b05
	fprintGroupTypes(f, modv[i]);
Packit 022b05
	fprintImplicitTypes(f, modv[i]);
Packit 022b05
	fprintTypedefs(f, modv[i]);
Packit 022b05
Packit 022b05
	fprintSegment(f, -1, "</xsd:schema>\n");
Packit 022b05
    }
Packit 022b05
Packit 022b05
    if (fflush(f) || ferror(f)) {
Packit 022b05
	perror("smidump: write error");
Packit 022b05
	exit(1);
Packit 022b05
    }
Packit 022b05
Packit 022b05
    if (output) {
Packit 022b05
	fclose(f);
Packit 022b05
    }
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
static void dumpXsdContainer(int modc, SmiModule **modv, int flags,
Packit 022b05
			     char *output)
Packit 022b05
{
Packit 022b05
    int  i;
Packit 022b05
    FILE *f = stdout;
Packit 022b05
Packit 022b05
    if (output) {
Packit 022b05
	f = fopen(output, "w");
Packit 022b05
	if (!f) {
Packit 022b05
	    fprintf(stderr, "smidump: cannot open %s for writing: ", output);
Packit 022b05
	    perror(NULL);
Packit 022b05
	    exit(1);
Packit 022b05
	}
Packit 022b05
    }
Packit 022b05
Packit 022b05
    fprintf(f, "\n"); 
Packit 022b05
    fprintf(f, "
Packit 022b05
	    SMI_VERSION_STRING ". Do not edit. -->\n");
Packit 022b05
	
Packit 022b05
    fputs( "
Packit 022b05
    fprintf(f, "%s ", schemaLocation);
Packit 022b05
    fputs( "are subject to changes. -->\n\n", f );
Packit 022b05
    
Packit 022b05
    fprintSegment(f, 1, "
Packit 022b05
    fprintf(f, "targetNamespace=\"%s%s\"\n", schemaLocation, containerBasename);
Packit 022b05
    fprintf(f, "            xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n");
Packit 022b05
    fprintf(f, "            xmlns:smi=\"%ssmi\"\n", schemaLocation);
Packit 022b05
    for (i = 0; i < modc; i++) {
Packit 022b05
	fprintf(f, "            xmlns:%s=\"%s%s\"\n",
Packit 022b05
		modv[i]->name, schemaLocation, modv[i]->name);
Packit 022b05
    }
Packit 022b05
    
Packit 022b05
    fprintf(f, "            xml:lang=\"en\"\n");
Packit 022b05
    fprintf(f, "            elementFormDefault=\"qualified\"\n");
Packit 022b05
    fprintf(f, "            attributeFormDefault=\"unqualified\">\n\n");
Packit 022b05
Packit 022b05
    /* imports */
Packit 022b05
    for (i = 0; i < modc; i++) {
Packit 022b05
	fprintSegment( f, 0, "
Packit 022b05
	fprintf( f, "namespace=\"%s%s\" schemaLocation=\"%s%s.xsd\"/>\n",
Packit 022b05
		 schemaLocation, modv[i]->name,
Packit 022b05
		 schemaLocation, modv[i]->name);
Packit 022b05
    }
Packit 022b05
    fprintf( f, "\n");
Packit 022b05
    
Packit 022b05
    /* context */
Packit 022b05
    fprintContextHead(f);
Packit 022b05
    for (i = 0; i < modc; i++) {
Packit 022b05
	/* per module elements */
Packit 022b05
	fprintGroupElements(f, modv[i]);
Packit 022b05
    }
Packit 022b05
    fprintContextFoot(f, modv, modc);
Packit 022b05
Packit 022b05
    fprintSegment(f, -1, "</xsd:schema>\n");
Packit 022b05
Packit 022b05
    if (fflush(f) || ferror(f)) {
Packit 022b05
	perror("smidump: write error");
Packit 022b05
	exit(1);
Packit 022b05
    }
Packit 022b05
Packit 022b05
    if (output) {
Packit 022b05
	fclose(f);
Packit 022b05
    }
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
static void dumpXsd(int modc, SmiModule **modv, int flags, char *output)
Packit 022b05
{
Packit 022b05
    /* register smi basetypes */
Packit 022b05
    registerType( "Integer32", "smi" );
Packit 022b05
    registerType( "ObjectIdentifier", "smi" );
Packit 022b05
    registerType( "OctetString", "smi" );
Packit 022b05
    registerType( "Unsigned32", "smi" );
Packit 022b05
    registerType( "Unsigned64", "smi" );
Packit 022b05
Packit 022b05
    /* make sure url ends with '/' */
Packit 022b05
    if( schemaLocation[ strlen( schemaLocation ) - 1 ] != '/' ) {
Packit 022b05
	smiAsprintf( &schemaLocation, "%s%c", schemaLocation, '/');
Packit 022b05
    }
Packit 022b05
	
Packit 022b05
    if (container) {
Packit 022b05
	dumpXsdContainer(modc, modv, flags, output);
Packit 022b05
    } else {
Packit 022b05
	dumpXsdModules(modc, modv, flags, output);
Packit 022b05
    }
Packit 022b05
Packit 022b05
    /* delete type-prefix-mapping */
Packit 022b05
    free( typePrefixes ); /* XXX: TODO: free all malloced types in a loop */
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
void initXsd()
Packit 022b05
{
Packit 022b05
Packit 022b05
    static SmidumpDriverOption opt[] = {
Packit 022b05
	{ "schema-url", OPT_STRING, &schemaLocation, 0,
Packit 022b05
	  "URI prefix for schema definitions and namespaces" },
Packit 022b05
	{ "container", OPT_FLAG, &container, 0,
Packit 022b05
	  "generate a container schema" },
Packit 022b05
	{ "nest-augments", OPT_FLAG, &nestAugmentedTables, 0,
Packit 022b05
	  "Nest rows of augmented tables in the base tables" },
Packit 022b05
	{ "nest-subtables", OPT_FLAG, &nestSubtables, 0,
Packit 022b05
	  "Nest subtables in the base tables" },
Packit 022b05
	{ 0, OPT_END, 0, 0 }
Packit 022b05
    };
Packit 022b05
    
Packit 022b05
    static SmidumpDriver driver = {
Packit 022b05
	"xsd",
Packit 022b05
	dumpXsd,
Packit 022b05
	0,
Packit 022b05
	SMIDUMP_DRIVER_CANT_UNITE,
Packit 022b05
	"XML schema definitions",
Packit 022b05
	opt,
Packit 022b05
	NULL
Packit 022b05
    };
Packit 022b05
    
Packit 022b05
    smidumpRegisterDriver(&driver);
Packit 022b05
}