Blame tools/dump-yang.c

Packit 022b05
/*
Packit 022b05
 * dump-yang.c --
Packit 022b05
 *
Packit 022b05
 *      Operations to dump MIB modules in the YANG output format.
Packit 022b05
 *
Packit 022b05
 * Copyright (c) 2007 J. Schoenwaelder, Jacobs University Bremen.
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-yang.c 8090 2008-04-18 12:56:29Z strauss $
Packit 022b05
 */
Packit 022b05
Packit 022b05
#include <config.h>
Packit 022b05
Packit 022b05
#include <ctype.h>
Packit 022b05
#include <stdio.h>
Packit 022b05
#include <string.h>
Packit 022b05
Packit 022b05
#include "smi.h"
Packit 022b05
#include "smidump.h"
Packit 022b05
#include "fprint.h"
Packit 022b05
#include "fortopat.h"
Packit 022b05
Packit 022b05
/*
Packit 022b05
 * TODO:
Packit 022b05
 * - reproduce the table comment text as a yang comment
Packit 022b05
 * - fix the format strings to xsd pattern algorithm so that it
Packit 022b05
 *   produces more accurate results
Packit 022b05
 * - compute proper boundaries for binary/string length restrictions
Packit 022b05
 * - translate notifications properly (whatever that means ;-)
Packit 022b05
 * - handle opaque in a reasonable way (test case AGGREGATE-MIB)
Packit 022b05
 */
Packit 022b05
Packit 022b05
static int sflag = 0;		/* generate smi: extensions */
Packit 022b05
static int nflag = 0;		/* generate notifications */
Packit 022b05
static int INDENT = 2;		/* indent factor */
Packit 022b05
Packit 022b05
#define  INDENTVALUE	20   /* column to start values, except multiline */
Packit 022b05
#define	 URNBASE	"urn:ietf:params:xml:ns:yang:smiv2:"
Packit 022b05
Packit 022b05
Packit 022b05
#define FLAG_CONFIG_FALSE 0x01
Packit 022b05
Packit 022b05
Packit 022b05
static const char *convertType[] = {
Packit 022b05
Packit 022b05
    /*
Packit 022b05
     * Translation of the SMIng built-in types to the YANG
Packit 022b05
     * equivalents.
Packit 022b05
     */
Packit 022b05
    
Packit 022b05
    "",		  "Integer32",   NULL,	     "int32",
Packit 022b05
    "",		  "Integer64",   NULL,	     "int64",
Packit 022b05
    "",		  "Unsigned32",  NULL,	     "uint32",
Packit 022b05
    "",		  "Unsigned64",  NULL,	     "uint64",
Packit 022b05
    "",		  "OctetString", NULL,	     "binary",
Packit 022b05
    "",		  "Enumeration", NULL,	     "enumeration",
Packit 022b05
    "",		  "Bits",	 NULL,	     "bits",
Packit 022b05
    "",		  "ObjectIdentifier", "yang-types", "object-identifier",
Packit 022b05
Packit 022b05
    /*
Packit 022b05
     * We want to do these translations as well in order to retire the
Packit 022b05
     * SNMPv2-SMI module which is not really an SMIv2 module but part
Packit 022b05
     * of the definition of SNMPv2-SMI itself.
Packit 022b05
     */
Packit 022b05
Packit 022b05
    "SNMPv2-SMI", "Integer32",  NULL,        "int32",
Packit 022b05
    "SNMPv2-SMI", "Integer64",  NULL,        "int64",
Packit 022b05
    "SNMPv2-SMI", "Unsigned32", NULL,        "uint32",
Packit 022b05
    "SNMPv2-SMI", "Opaque",    NULL,	     "binary",
Packit 022b05
    "SNMPv2-SMI", "Counter32", "yang-types", "counter32",
Packit 022b05
    "SNMPv2-SMI", "Counter64", "yang-types", "counter64",
Packit 022b05
    "SNMPv2-SMI", "Gauge32",   "yang-types", "gauge32",
Packit 022b05
    "SNMPv2-SMI", "TimeTicks", "yang-types", "timeticks",
Packit 022b05
    "SNMPv2-SMI", "IpAddress", "inet-types", "ipv4-address",
Packit 022b05
Packit 022b05
    /*
Packit 022b05
     * And we like to do the same for RFC1155-SMI definitions...
Packit 022b05
     */
Packit 022b05
Packit 022b05
    "RFC1155-SMI", "Opaque",    NULL,	     "binary",
Packit 022b05
    "RFC1155-SMI", "Counter",   "yang-types", "counter32",
Packit 022b05
    "RFC1155-SMI", "Gauge",     "yang-types", "gauge32",
Packit 022b05
    "RFC1155-SMI", "TimeTicks", "yang-types", "timeticks",
Packit 022b05
    "RFC1155-SMI", "IpAddress", "inet-types", "ipv4-address",
Packit 022b05
    
Packit 022b05
    /*
Packit 022b05
     * We also translate frequently used SNMPv2-TCs that have a YANG
Packit 022b05
     * equivalent. Note that DateAndTime is slightly different from
Packit 022b05
     * the ISO profile used by date-and-time.
Packit 022b05
     */
Packit 022b05
Packit 022b05
    "SNMPv2-TC",  "PhysAddress", "yang-types", "phys-address",
Packit 022b05
    "SNMPv2-TC",  "MacAddress",  "ieee-types", "mac-address",
Packit 022b05
    "SNMPv2-TC",  "TimeStamp",   "yang-types", "timestamp",
Packit 022b05
Packit 022b05
    NULL, NULL, NULL, NULL
Packit 022b05
};
Packit 022b05
Packit 022b05
Packit 022b05
static const char *convertImport[] = {
Packit 022b05
Packit 022b05
    /*
Packit 022b05
     * Things that are not types but removed from imports...
Packit 022b05
     */
Packit 022b05
Packit 022b05
    "SNMPv2-SMI",  "MODULE-IDENTITY",    NULL, NULL,
Packit 022b05
    "SNMPv2-SMI",  "OBJECT-IDENTITY",    NULL, NULL,
Packit 022b05
    "SNMPv2-SMI",  "OBJECT-TYPE",        NULL, NULL,
Packit 022b05
    "SNMPv2-SMI",  "NOTIFICATION-TYPE",  NULL, NULL,
Packit 022b05
    "SNMPv2-SMI",  "mib-2",              NULL, NULL,
Packit 022b05
    "SNMPv2-TC",   "TEXTUAL-CONVENTION", NULL, NULL,
Packit 022b05
    "SNMPv2-CONF", "OBJECT-GROUP",       NULL, NULL,
Packit 022b05
    "SNMPv2-CONF", "NOTIFICATION-GROUP", NULL, NULL,
Packit 022b05
    "SNMPv2-CONF", "MODULE-COMPLIANCE",  NULL, NULL,
Packit 022b05
    "SNMPv2-CONF", "AGENT-CAPABILITIES", NULL, NULL,
Packit 022b05
    "SNMPv2-MIB",  "snmpTraps",	         NULL, NULL,
Packit 022b05
Packit 022b05
    NULL, NULL, NULL, NULL
Packit 022b05
};
Packit 022b05
Packit 022b05
/*
Packit 022b05
 * SMIv2 modules we never like to import from...
Packit 022b05
 */
Packit 022b05
Packit 022b05
static const char *ignoreImports[] = {
Packit 022b05
    "RFC1155-SMI", "SNMPv2-SMI", "SNMPv2-CONF", NULL
Packit 022b05
};
Packit 022b05
Packit 022b05
Packit 022b05
/*
Packit 022b05
 * Structure used to build a list of imported types.
Packit 022b05
 */
Packit 022b05
Packit 022b05
typedef struct Import {
Packit 022b05
    char          *module;
Packit 022b05
    char	  *prefix;
Packit 022b05
    struct Import *nextPtr;
Packit 022b05
} Import;
Packit 022b05
Packit 022b05
static Import *importList = NULL;
Packit 022b05
Packit 022b05
static int silent = 0;
Packit 022b05
Packit 022b05
Packit 022b05
static char*
Packit 022b05
getStringStatus(SmiStatus status)
Packit 022b05
{
Packit 022b05
    return
Packit 022b05
	(status == SMI_STATUS_CURRENT)     ? "current" :
Packit 022b05
	(status == SMI_STATUS_DEPRECATED)  ? "deprecated" :
Packit 022b05
	(status == SMI_STATUS_OBSOLETE)    ? "obsolete" :
Packit 022b05
	(status == SMI_STATUS_MANDATORY)   ? "current" :
Packit 022b05
	(status == SMI_STATUS_OPTIONAL)    ? "current" :
Packit 022b05
					     "<unknown>";
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
static char*
Packit 022b05
getStringDate(time_t t)
Packit 022b05
{
Packit 022b05
    static char   s[27];
Packit 022b05
    struct tm	  *tm;
Packit 022b05
Packit 022b05
    tm = gmtime(&t);
Packit 022b05
    sprintf(s, "%04d-%02d-%02d",
Packit 022b05
	    tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday);
Packit 022b05
    return s;
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
Packit 022b05
static char*
Packit 022b05
getValueString(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 << 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_POINTER:
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
Packit 022b05
Packit 022b05
static int
Packit 022b05
isPrefixUnique(const char *prefix)
Packit 022b05
{
Packit 022b05
    Import *import;
Packit 022b05
Packit 022b05
    for (import = importList; import; import = import->nextPtr) {
Packit 022b05
         if (strcmp(prefix, import->prefix) == 0) {
Packit 022b05
             return 0;
Packit 022b05
	 }
Packit 022b05
    }
Packit 022b05
Packit 022b05
    return 1;
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
static char*
Packit 022b05
guessNicePrefix(const char *moduleName)
Packit 022b05
{
Packit 022b05
    char *prefix;
Packit 022b05
    int i, d;
Packit 022b05
Packit 022b05
    char *specials[] = {
Packit 022b05
	"yang-smi", "smi",
Packit 022b05
	"yang-types", "yang",
Packit 022b05
	"inet-types", "inet",
Packit 022b05
	"ieee-types", "ieee",
Packit 022b05
	"SNMPv2-TC", "smiv2",
Packit 022b05
	NULL, NULL
Packit 022b05
    };
Packit 022b05
Packit 022b05
    for (i = 0; specials[i]; i +=2) {
Packit 022b05
	if (strcmp(moduleName, specials[i]) == 0) {
Packit 022b05
            if (isPrefixUnique(specials[i+1])) {
Packit 022b05
                return xstrdup(specials[i+1]);
Packit 022b05
	    }
Packit 022b05
	}
Packit 022b05
    }
Packit 022b05
Packit 022b05
    prefix = xstrdup(moduleName);
Packit 022b05
    for (i = 0; prefix[i]; i++) {
Packit 022b05
        prefix[i] = tolower(prefix[i]);
Packit 022b05
    }
Packit 022b05
Packit 022b05
    for (i = 0, d = 0; prefix[i]; i++) {
Packit 022b05
        if (prefix[i] == '-') {
Packit 022b05
	    d++;
Packit 022b05
	    if (d > 1) {
Packit 022b05
		prefix[i] = 0;
Packit 022b05
		if (isPrefixUnique(prefix)) {
Packit 022b05
		    return prefix;
Packit 022b05
		}
Packit 022b05
		prefix[i] = '-';
Packit 022b05
	    }
Packit 022b05
	}
Packit 022b05
    }
Packit 022b05
Packit 022b05
    return prefix;
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
static const char*
Packit 022b05
getModulePrefix(const char *moduleName)
Packit 022b05
{
Packit 022b05
    Import *import;
Packit 022b05
    static char *prefix = NULL;
Packit 022b05
Packit 022b05
    for (import = importList; import; import = import->nextPtr) {
Packit 022b05
        if (strcmp(moduleName, import->module) == 0) {
Packit 022b05
            return import->prefix;
Packit 022b05
	}
Packit 022b05
    }
Packit 022b05
 
Packit 022b05
    if (prefix) xfree(prefix);
Packit 022b05
    prefix = guessNicePrefix(moduleName);
Packit 022b05
    return prefix;
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
Packit 022b05
static Import*
Packit 022b05
addImport(char *module, char *name)
Packit 022b05
{
Packit 022b05
    Import **import, *newImport;
Packit 022b05
    
Packit 022b05
    if (!module || !name) {
Packit 022b05
	return NULL;
Packit 022b05
    }
Packit 022b05
	    
Packit 022b05
    for (import = &importList; *import; import = &(*import)->nextPtr) {
Packit 022b05
	int c = strcmp((*import)->module, module);
Packit 022b05
	if (c == 0) return *import;
Packit 022b05
	if (c > 0) break;
Packit 022b05
    }
Packit 022b05
Packit 022b05
    newImport = xmalloc(sizeof(Import));
Packit 022b05
    newImport->module = module;
Packit 022b05
    newImport->prefix = guessNicePrefix(module);
Packit 022b05
Packit 022b05
    newImport->nextPtr = *import;
Packit 022b05
    *import = newImport;
Packit 022b05
	
Packit 022b05
    return *import;
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
Packit 022b05
static void
Packit 022b05
createImportList(SmiModule *smiModule)
Packit 022b05
{
Packit 022b05
    SmiImport   *smiImport;
Packit 022b05
    SmiIdentifier impModule, impName;
Packit 022b05
    SmiType	*smiType;
Packit 022b05
    SmiNode	*smiNode;
Packit 022b05
    int i;
Packit 022b05
Packit 022b05
    for (smiImport = smiGetFirstImport(smiModule); smiImport;
Packit 022b05
	 smiImport = smiGetNextImport(smiImport)) {
Packit 022b05
Packit 022b05
	impModule = smiImport->module;
Packit 022b05
	impName = smiImport->name;
Packit 022b05
Packit 022b05
	for (i = 0; convertType[i]; i += 4) {
Packit 022b05
	    if (strcmp(smiImport->module, convertType[i]) == 0
Packit 022b05
		&& strcmp(smiImport->name, convertType[i+1]) == 0) {
Packit 022b05
		impModule = (SmiIdentifier) convertType[i+2];
Packit 022b05
		impName = (SmiIdentifier) convertType[i+3];
Packit 022b05
		break;
Packit 022b05
	    }
Packit 022b05
	}
Packit 022b05
Packit 022b05
	if (! impModule || ! impName) continue;
Packit 022b05
Packit 022b05
	for (i = 0; convertImport[i]; i += 4) {
Packit 022b05
	    if (strcmp(smiImport->module, convertImport[i]) == 0
Packit 022b05
		&& strcmp(smiImport->name, convertImport[i+1]) == 0) {
Packit 022b05
		impModule = (SmiIdentifier) convertImport[i+2];
Packit 022b05
		impName = (SmiIdentifier) convertImport[i+3];
Packit 022b05
		break;
Packit 022b05
	    }
Packit 022b05
	}
Packit 022b05
Packit 022b05
	if (! impModule || ! impName) continue;
Packit 022b05
#if 0	
Packit 022b05
	fprintf(stderr, "%s\t%s\n", impModule, impName);
Packit 022b05
#endif
Packit 022b05
	addImport(impModule, impName);
Packit 022b05
    }
Packit 022b05
Packit 022b05
    /*
Packit 022b05
     * Add import for the smi:oid extension and friends.
Packit 022b05
     */
Packit 022b05
Packit 022b05
    if (sflag) {
Packit 022b05
	addImport("yang-smi", "oid");
Packit 022b05
    }
Packit 022b05
    
Packit 022b05
    /*
Packit 022b05
     * Add import for yang-types that were originally ASN.1
Packit 022b05
     * builtins...
Packit 022b05
     */
Packit 022b05
Packit 022b05
    for (smiType = smiGetFirstType(smiModule);
Packit 022b05
	 smiType; smiType = smiGetNextType(smiType)) {
Packit 022b05
	SmiType *parentType = smiGetParentType(smiType);
Packit 022b05
	if (parentType && strcmp(parentType->name, "ObjectIdentifier") == 0) {
Packit 022b05
	    addImport("yang-types", "object-identifier");
Packit 022b05
	}
Packit 022b05
    }
Packit 022b05
Packit 022b05
    for (smiNode = smiGetFirstNode(smiModule,
Packit 022b05
				   SMI_NODEKIND_SCALAR | SMI_NODEKIND_COLUMN);
Packit 022b05
	 smiNode;
Packit 022b05
	 smiNode = smiGetNextNode(smiNode,
Packit 022b05
				  SMI_NODEKIND_SCALAR | SMI_NODEKIND_COLUMN)) {
Packit 022b05
	smiType = smiGetNodeType(smiNode);
Packit 022b05
	if (! smiType->name) {
Packit 022b05
	    smiType = smiGetParentType(smiType);
Packit 022b05
	}
Packit 022b05
	if (smiType && strcmp(smiType->name, "ObjectIdentifier") == 0) {
Packit 022b05
	    addImport("yang-types", "object-identifier");
Packit 022b05
	}
Packit 022b05
    }
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
Packit 022b05
static void
Packit 022b05
freeImportList(void)
Packit 022b05
{
Packit 022b05
    Import *import, *freeme;
Packit 022b05
Packit 022b05
    for (import = importList; import; ) {
Packit 022b05
        xfree(import->prefix);
Packit 022b05
	freeme = import;
Packit 022b05
	import = import->nextPtr;
Packit 022b05
	xfree(freeme);
Packit 022b05
    }
Packit 022b05
    importList = NULL;
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
Packit 022b05
static int
Packit 022b05
isGroup(SmiNode *smiNode)
Packit 022b05
{
Packit 022b05
    SmiNode *childNode;
Packit 022b05
    
Packit 022b05
    for(childNode = smiGetFirstChildNode(smiNode);
Packit 022b05
	childNode;
Packit 022b05
	childNode = smiGetNextChildNode(childNode)) {
Packit 022b05
	if ((childNode->nodekind == SMI_NODEKIND_SCALAR
Packit 022b05
	     || childNode->nodekind == SMI_NODEKIND_TABLE)
Packit 022b05
	    && childNode->status == SMI_STATUS_CURRENT) {
Packit 022b05
	    return 1;
Packit 022b05
	}
Packit 022b05
    }
Packit 022b05
Packit 022b05
    return 0;
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
static int
Packit 022b05
isIndex(SmiNode *groupNode, SmiNode *smiNode)
Packit 022b05
{
Packit 022b05
    SmiElement *smiElement;
Packit 022b05
    int cnt = 0;
Packit 022b05
    
Packit 022b05
    /*
Packit 022b05
     * We return an indication whether smiNode is part of an index. In
Packit 022b05
     * fact, we return number of times smiNode is part of an index
Packit 022b05
     * since we sometimes have to disambiguate names...
Packit 022b05
     */
Packit 022b05
Packit 022b05
    for (smiElement = smiGetFirstElement(groupNode);
Packit 022b05
	 smiElement; smiElement = smiGetNextElement(smiElement)) {
Packit 022b05
	if (smiNode == smiGetElementNode(smiElement)) {
Packit 022b05
	    cnt++;
Packit 022b05
	}
Packit 022b05
    }
Packit 022b05
Packit 022b05
    return cnt;
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
static void
Packit 022b05
fprintRevisions(FILE *f, int indent, SmiModule *smiModule)
Packit 022b05
{
Packit 022b05
    int i;
Packit 022b05
    SmiRevision *smiRevision;
Packit 022b05
    
Packit 022b05
    for(i = 0, smiRevision = smiGetFirstRevision(smiModule);
Packit 022b05
	smiRevision; smiRevision = smiGetNextRevision(smiRevision)) {
Packit 022b05
	fprintSegment(f, indent, "revision ", 0);
Packit 022b05
	fprint(f, "\"%s\" {\n", getStringDate(smiRevision->date));
Packit 022b05
	fprintSegment(f, 2 * indent, "description", INDENTVALUE);
Packit 022b05
	fprint(f, "\n");
Packit 022b05
	fprintMultilineString(f, 2 * indent, smiRevision->description);
Packit 022b05
	fprint(f, ";\n");
Packit 022b05
        fprintSegment(f, indent, "}\n", 0);
Packit 022b05
	i++;
Packit 022b05
    }
Packit 022b05
    if (i) {
Packit 022b05
	fprint(f, "\n");
Packit 022b05
    }
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
static void
Packit 022b05
fprintImports(FILE *f, SmiModule *smiModule)
Packit 022b05
{
Packit 022b05
    Import *import;
Packit 022b05
    int i, len = 4;
Packit 022b05
    
Packit 022b05
    for (import = importList; import; import = import->nextPtr) {
Packit 022b05
	for (i = 0; ignoreImports[i]; i++) {
Packit 022b05
	    if (strcmp(ignoreImports[i], import->module) == 0) {
Packit 022b05
		break;
Packit 022b05
	    }
Packit 022b05
	}
Packit 022b05
	if (ignoreImports[i] == NULL) {
Packit 022b05
	    if (strlen(import->module) > len) len = strlen(import->module);
Packit 022b05
	}
Packit 022b05
    }
Packit 022b05
    
Packit 022b05
    for (import = importList; import; import = import->nextPtr) {
Packit 022b05
	for (i = 0; ignoreImports[i]; i++) {
Packit 022b05
	    if (strcmp(ignoreImports[i], import->module) == 0) {
Packit 022b05
		break;
Packit 022b05
	    }
Packit 022b05
	}
Packit 022b05
	if (ignoreImports[i] == NULL) {
Packit 022b05
	    fprintSegment(f, INDENT, "import", 0);
Packit 022b05
	    fprint(f, " %-*s { prefix \"%s\"; }\n", len,
Packit 022b05
		   import->module, import->prefix);
Packit 022b05
	}
Packit 022b05
    }
Packit 022b05
    fprint(f, "\n");
Packit 022b05
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
Packit 022b05
Packit 022b05
static void
Packit 022b05
fprintSubtype(FILE *f, int indent, SmiType *smiType)
Packit 022b05
{
Packit 022b05
    SmiRange       *range;
Packit 022b05
    SmiNamedNumber *nn;
Packit 022b05
    char	   s[1024];
Packit 022b05
    char	   *tkw, *lkw, *vkw;
Packit 022b05
    int		   i = 0;
Packit 022b05
    int		   len = 4;
Packit 022b05
Packit 022b05
    if ((smiType->basetype == SMI_BASETYPE_ENUM) ||
Packit 022b05
	(smiType->basetype == SMI_BASETYPE_BITS)) {
Packit 022b05
	for (nn = smiGetFirstNamedNumber(smiType);
Packit 022b05
	     nn ; nn = smiGetNextNamedNumber(nn)) {
Packit 022b05
	    if (strlen(nn->name) > len) len = strlen(nn->name);
Packit 022b05
	}
Packit 022b05
	
Packit 022b05
	for(i = 0, nn = smiGetFirstNamedNumber(smiType);
Packit 022b05
	    nn ; i++, nn = smiGetNextNamedNumber(nn)) {
Packit 022b05
	    if (! i) {
Packit 022b05
		fprint(f, " {\n");
Packit 022b05
	    }
Packit 022b05
	    tkw = (smiType->basetype == SMI_BASETYPE_BITS) ? "bits" : "enumeration";
Packit 022b05
	    lkw = (smiType->basetype == SMI_BASETYPE_BITS) ? "bit" : "enum";
Packit 022b05
	    vkw = (smiType->basetype == SMI_BASETYPE_BITS) ? "position" : "value";
Packit 022b05
	    sprintf(s, "%s %-*s { %s %s; }\n",
Packit 022b05
		    lkw, len, nn->name,
Packit 022b05
		    vkw, getValueString(&nn->value, smiType));
Packit 022b05
	    fprintSegment(f, indent + INDENT, s, 0);
Packit 022b05
	}
Packit 022b05
    } else {
Packit 022b05
	for(i = 0, range = smiGetFirstRange(smiType);
Packit 022b05
	    range ; i++, range = smiGetNextRange(range)) {
Packit 022b05
	    if (i) {
Packit 022b05
		fprint(f, " | ");
Packit 022b05
	    } else {
Packit 022b05
		fprint(f, " {\n");
Packit 022b05
		if (smiType->basetype == SMI_BASETYPE_OCTETSTRING) {
Packit 022b05
		    fprintSegment(f, indent + INDENT, "length \"", 0);
Packit 022b05
		} else {
Packit 022b05
		    fprintSegment(f, indent + INDENT, "range \"", 0);
Packit 022b05
		}
Packit 022b05
	    }	    
Packit 022b05
	    if (memcmp(&range->minValue, &range->maxValue,
Packit 022b05
		       sizeof(SmiValue))) {
Packit 022b05
		sprintf(s, "%s", getValueString(&range->minValue, smiType));
Packit 022b05
		sprintf(&s[strlen(s)], "..%s", 
Packit 022b05
			getValueString(&range->maxValue, smiType));
Packit 022b05
	    } else {
Packit 022b05
		sprintf(s, "%s", getValueString(&range->minValue, smiType));
Packit 022b05
	    }
Packit 022b05
	    fprint(f, s);
Packit 022b05
	}
Packit 022b05
	if (i) {
Packit 022b05
	    fprint(f, "\";\n");
Packit 022b05
	}
Packit 022b05
    }
Packit 022b05
Packit 022b05
    if (smiType->format
Packit 022b05
	&& smiType->basetype == SMI_BASETYPE_OCTETSTRING) {
Packit 022b05
Packit 022b05
	char *pattern;
Packit 022b05
	pattern = smiFormatToPattern(smiType->format,
Packit 022b05
				     smiGetFirstRange(smiType));
Packit 022b05
	if (pattern) {
Packit 022b05
	    if (! i) {
Packit 022b05
		fprint(f, "{\n");
Packit 022b05
	    }
Packit 022b05
	    fprintSegment(f, indent + INDENT, "pattern \"", 0);
Packit 022b05
	    fprint(f, "%s\";\n", pattern);
Packit 022b05
	    xfree(pattern);
Packit 022b05
	    i++;
Packit 022b05
	}
Packit 022b05
    }
Packit 022b05
    
Packit 022b05
    if (! i) {
Packit 022b05
	fprint(f, ";\n");
Packit 022b05
    } else {
Packit 022b05
	fprintSegment(f, indent, "}\n", 0);
Packit 022b05
    }
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
static void
Packit 022b05
fprintStatus(FILE *f, int indent, SmiStatus status)
Packit 022b05
{
Packit 022b05
    if ((status != SMI_STATUS_CURRENT) &&
Packit 022b05
	(status != SMI_STATUS_UNKNOWN) &&
Packit 022b05
	(status != SMI_STATUS_MANDATORY) &&
Packit 022b05
	(status != SMI_STATUS_OPTIONAL)) {
Packit 022b05
	fprintSegment(f, indent, "status", 0);
Packit 022b05
	fprint(f, " %s;\n", getStringStatus(status));
Packit 022b05
    }
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
static void
Packit 022b05
fprintUnits(FILE *f, int indent, const char *units)
Packit 022b05
{
Packit 022b05
    if (units) {
Packit 022b05
	fprintSegment(f, indent, "units", 0);
Packit 022b05
	fprint(f, " \"%s\";\n", units);
Packit 022b05
    }
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
static void
Packit 022b05
fprintFormat(FILE *f, int indent, const char *format)
Packit 022b05
{
Packit 022b05
    if (sflag && format) {
Packit 022b05
	fprintSegment(f, 2 * INDENT, "smi:display-hint", 0);
Packit 022b05
	fprint(f, " \"%s\";\n", format);
Packit 022b05
    }
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
static void
Packit 022b05
fprintObjectIdentifier(FILE *f, int indent, SmiSubid *oid, int oidlen)
Packit 022b05
{
Packit 022b05
    int i;
Packit 022b05
Packit 022b05
    if (sflag && oid && oidlen) {
Packit 022b05
	fprintSegment(f, indent, "smi:oid", 0);
Packit 022b05
	fprint(f, " \"");
Packit 022b05
	for (i=0; i < oidlen; i++) {
Packit 022b05
	    fprint(f, "%s%d", i ? "." : "", oid[i]);
Packit 022b05
	}
Packit 022b05
	fprint(f, "\";\n");
Packit 022b05
    }
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
static void
Packit 022b05
fprintDescription(FILE *f, int indent, const char *description)
Packit 022b05
{
Packit 022b05
    if (description) {
Packit 022b05
	fprintSegment(f, indent, "description", INDENTVALUE);
Packit 022b05
	fprint(f, "\n");
Packit 022b05
	fprintMultilineString(f, indent, description);
Packit 022b05
	fprint(f, ";\n");
Packit 022b05
    }
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
static void
Packit 022b05
fprintReference(FILE *f, int indent, const char *reference)
Packit 022b05
{
Packit 022b05
    if (reference) {
Packit 022b05
	fprintSegment(f, indent, "reference", INDENTVALUE);
Packit 022b05
	fprint(f, "\n");
Packit 022b05
	fprintMultilineString(f, indent, reference);
Packit 022b05
	fprint(f, ";\n");
Packit 022b05
    }
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
static void
Packit 022b05
fprintConfig(FILE *f, int indent, SmiAccess access)
Packit 022b05
{
Packit 022b05
    if (access == SMI_ACCESS_READ_WRITE) {
Packit 022b05
	fprintSegment(f, indent, "config true;\n", 0);
Packit 022b05
    } else {
Packit 022b05
	fprintSegment(f, indent, "config false;\n", 0);
Packit 022b05
    }
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
static void
Packit 022b05
fprintDefault(FILE *f, int indent, SmiValue *value, SmiType *smiType)
Packit 022b05
{
Packit 022b05
    if (sflag && value->basetype != SMI_BASETYPE_UNKNOWN) {
Packit 022b05
	fprintSegment(f, indent, "smi:default", 0);
Packit 022b05
	fprint(f, " \"%s\";\n", getValueString(value, smiType));
Packit 022b05
    }
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
static int
Packit 022b05
fprintTypename(FILE *f, SmiType *smiType, int format)
Packit 022b05
{
Packit 022b05
    const char *typeModule = NULL, *typeName = NULL;
Packit 022b05
    SmiModule *smiModule;
Packit 022b05
    int i;
Packit 022b05
Packit 022b05
    if (! smiType) return 0;
Packit 022b05
Packit 022b05
    smiModule = smiGetTypeModule(smiType);
Packit 022b05
Packit 022b05
    if (smiType && ! smiType->name) {
Packit 022b05
	return fprintTypename(f, smiGetParentType(smiType), format);
Packit 022b05
    }
Packit 022b05
Packit 022b05
    for (i = 0; convertType[i]; i += 4) {
Packit 022b05
	if (strcmp(smiModule->name, convertType[i]) == 0
Packit 022b05
	    && strcmp(smiType->name, convertType[i+1]) == 0) {
Packit 022b05
	    typeModule = convertType[i+2];
Packit 022b05
	    typeName = convertType[i+3];
Packit 022b05
	    break;
Packit 022b05
	}
Packit 022b05
    }
Packit 022b05
Packit 022b05
    if (! typeName) {
Packit 022b05
	typeModule = smiModule->name;
Packit 022b05
	typeName = smiType->name;
Packit 022b05
    }
Packit 022b05
Packit 022b05
    if (typeModule) {
Packit 022b05
	typeModule = getModulePrefix(typeModule);
Packit 022b05
    }
Packit 022b05
Packit 022b05
    /*
Packit 022b05
     * We handle a special case here. If we have a format string and
Packit 022b05
     * the type is binary, we turn it into string.
Packit 022b05
     */
Packit 022b05
    
Packit 022b05
    if (! typeModule && typeName && strcmp(typeName, "binary") == 0) {
Packit 022b05
	if (format) {
Packit 022b05
	    typeName = "string";
Packit 022b05
	}
Packit 022b05
    }
Packit 022b05
	
Packit 022b05
    if (typeModule && typeName) {
Packit 022b05
	fprint(f, "%s:%s", typeModule, typeName);
Packit 022b05
    } else {
Packit 022b05
	fprint(f, "%s", typeName);
Packit 022b05
    }
Packit 022b05
Packit 022b05
    return 1;
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
static void
Packit 022b05
fprintTypedefs(FILE *f, SmiModule *smiModule)
Packit 022b05
{
Packit 022b05
    int		 i;
Packit 022b05
    SmiType	 *smiType, *baseType;
Packit 022b05
    
Packit 022b05
    for (i = 0, smiType = smiGetFirstType(smiModule);
Packit 022b05
	 smiType; smiType = smiGetNextType(smiType)) {
Packit 022b05
Packit 022b05
	baseType = smiGetParentType(smiType);
Packit 022b05
Packit 022b05
	if (!i && !silent) {
Packit 022b05
	    fprintSegment(f, INDENT, "/*** TYPE DEFINITIONS ***/\n\n", 0);
Packit 022b05
	}
Packit 022b05
	fprintSegment(f, INDENT, "", 0);
Packit 022b05
	fprint(f, "typedef %s {\n", smiType->name);
Packit 022b05
Packit 022b05
	fprintSegment(f, 2 * INDENT, "type ", 0);
Packit 022b05
	fprintTypename(f, baseType, smiType->format != NULL);
Packit 022b05
	fprintSubtype(f, 2 * INDENT, smiType);
Packit 022b05
	
Packit 022b05
	fprintUnits(f, 2 * INDENT, smiType->units);
Packit 022b05
	fprintStatus(f, 2 * INDENT, smiType->status);
Packit 022b05
	fprintDescription(f, 2 * INDENT, smiType->description);
Packit 022b05
	fprintReference(f, 2 * INDENT, smiType->reference);
Packit 022b05
	fprintFormat(f, 2 * INDENT, smiType->format);
Packit 022b05
	fprintDefault(f, 2 * INDENT, &smiType->value, smiType);
Packit 022b05
Packit 022b05
	fprintSegment(f, INDENT, "}\n\n", 0);
Packit 022b05
	i++;
Packit 022b05
    }
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
static void
Packit 022b05
fprintPath(FILE *f, SmiNode *smiNode)
Packit 022b05
{
Packit 022b05
     SmiNode *entryNode = NULL;
Packit 022b05
     SmiNode *tableNode = NULL;
Packit 022b05
     SmiNode *contNode = NULL;
Packit 022b05
     SmiModule *smiModule = NULL;
Packit 022b05
Packit 022b05
     switch (smiNode->nodekind) {
Packit 022b05
     case SMI_NODEKIND_SCALAR:
Packit 022b05
	     contNode = smiGetParentNode(smiNode);
Packit 022b05
	     break;
Packit 022b05
     case SMI_NODEKIND_COLUMN:
Packit 022b05
	     entryNode = smiGetParentNode(smiNode);
Packit 022b05
	     tableNode = smiGetParentNode(entryNode);
Packit 022b05
	     contNode = smiGetParentNode(tableNode);
Packit 022b05
	     break;
Packit 022b05
     case SMI_NODEKIND_ROW:
Packit 022b05
	     entryNode = smiNode;
Packit 022b05
	     tableNode = smiGetParentNode(entryNode);
Packit 022b05
	     contNode = smiGetParentNode(tableNode);
Packit 022b05
	     break;
Packit 022b05
     case SMI_NODEKIND_TABLE:
Packit 022b05
	     contNode = smiGetParentNode(tableNode);
Packit 022b05
	     break;
Packit 022b05
     default:
Packit 022b05
	     break;
Packit 022b05
     }
Packit 022b05
Packit 022b05
     smiModule = smiGetNodeModule(contNode);
Packit 022b05
     if (smiModule) {
Packit 022b05
         fprint(f, "/%s:%s", getModulePrefix(smiModule->name), contNode->name);
Packit 022b05
     }
Packit 022b05
     if (contNode == smiNode) return;
Packit 022b05
Packit 022b05
     if (entryNode) {
Packit 022b05
	 smiModule = smiGetNodeModule(entryNode);
Packit 022b05
	 if (smiModule) {
Packit 022b05
	     fprint(f, "/%s:%s", getModulePrefix(smiModule->name), entryNode->name);
Packit 022b05
	 }
Packit 022b05
	 if (entryNode == smiNode) return;
Packit 022b05
     }
Packit 022b05
Packit 022b05
     smiModule = smiGetNodeModule(smiNode);
Packit 022b05
     if (smiModule) {
Packit 022b05
         fprint(f, "/%s:%s", getModulePrefix(smiModule->name), smiNode->name);
Packit 022b05
     }
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
static void
Packit 022b05
fprintLeaf(FILE *f, int indent, SmiNode *smiNode, int flags)
Packit 022b05
{
Packit 022b05
    SmiType *smiType;
Packit 022b05
    SmiAccess config;
Packit 022b05
    
Packit 022b05
    smiType = smiGetNodeType(smiNode);
Packit 022b05
Packit 022b05
    fprintSegment(f, indent, "leaf ", 0);
Packit 022b05
    fprint(f, "%s {\n", smiNode->name);
Packit 022b05
Packit 022b05
    fprintSegment(f, indent + INDENT, "type ", 0);
Packit 022b05
    fprintTypename(f, smiType, smiNode->format != NULL);
Packit 022b05
    if (! smiType->name) {
Packit 022b05
	fprintSubtype(f, indent + INDENT, smiType);
Packit 022b05
    } else {
Packit 022b05
	fprint(f, ";\n");
Packit 022b05
    }
Packit 022b05
    
Packit 022b05
    fprintUnits(f, indent + INDENT, smiNode->units);
Packit 022b05
    if (flags & FLAG_CONFIG_FALSE) {
Packit 022b05
	config = SMI_ACCESS_READ_ONLY;
Packit 022b05
    } else {
Packit 022b05
	config = smiNode->access;
Packit 022b05
    }
Packit 022b05
    fprintConfig(f, indent + INDENT, config);
Packit 022b05
    fprintStatus(f, indent + INDENT, smiNode->status);
Packit 022b05
    fprintDescription(f, indent + INDENT, smiNode->description);
Packit 022b05
    fprintReference(f, indent + INDENT, smiNode->reference);
Packit 022b05
    fprintFormat(f, indent + INDENT, smiNode->format);
Packit 022b05
    fprintDefault(f, indent + INDENT, &smiNode->value, smiType);
Packit 022b05
    fprintObjectIdentifier(f, indent + INDENT, smiNode->oid, smiNode->oidlen);
Packit 022b05
    fprintSegment(f, indent, "}\n", 0);
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
static void
Packit 022b05
fprintKeyrefLeaf(FILE *f, int indent, SmiNode *smiNode, int flags)
Packit 022b05
{
Packit 022b05
    SmiNode *entryNode;
Packit 022b05
    SmiAccess config;
Packit 022b05
Packit 022b05
    entryNode = smiGetParentNode(smiNode);
Packit 022b05
    fprintSegment(f, indent, "leaf ", 0);
Packit 022b05
    fprint(f, "%s {\n", smiNode->name);
Packit 022b05
    fprintSegment(f, indent + INDENT, "type keyref {\n", 0);
Packit 022b05
    fprintSegment(f, indent + 2 * INDENT, "path \"", 0);
Packit 022b05
    fprintPath(f, smiNode);
Packit 022b05
    fprint(f, "\";\n");
Packit 022b05
    fprintSegment(f, indent + INDENT, "}\n", 0);
Packit 022b05
    if (flags & FLAG_CONFIG_FALSE) {
Packit 022b05
	config = SMI_ACCESS_READ_ONLY;
Packit 022b05
    } else {
Packit 022b05
	config = entryNode->create
Packit 022b05
	    ? SMI_ACCESS_READ_WRITE : SMI_ACCESS_READ_ONLY;
Packit 022b05
    }
Packit 022b05
    fprintConfig(f, indent + INDENT, config);
Packit 022b05
    fprintStatus(f, indent + INDENT, smiNode->status);
Packit 022b05
    fprintDescription(f, indent + INDENT,
Packit 022b05
		      "Automagically generated keyref leaf.");
Packit 022b05
    fprintSegment(f, indent, "}\n", 0);
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
static void
Packit 022b05
fprintKey(FILE *f, int indent, SmiNode *smiNode)
Packit 022b05
{
Packit 022b05
    SmiElement *smiElement;
Packit 022b05
    int j;
Packit 022b05
Packit 022b05
    fprintSegment(f, indent, "key \"", 0);
Packit 022b05
Packit 022b05
    for (j = 0, smiElement = smiGetFirstElement(smiNode); smiElement;
Packit 022b05
	 j++, smiElement = smiGetNextElement(smiElement)) {
Packit 022b05
        if (j) {
Packit 022b05
            fprint(f, " ");
Packit 022b05
	}
Packit 022b05
	fprintWrapped(f, indent + 5,
Packit 022b05
		      smiGetElementNode(smiElement)->name);
Packit 022b05
    }
Packit 022b05
    fprint(f, "\";\n");
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
static void
Packit 022b05
fprintLeafs(FILE *f, int indent, SmiNode *smiNode)
Packit 022b05
{
Packit 022b05
    SmiNode *childNode;
Packit 022b05
    int c;
Packit 022b05
    
Packit 022b05
    for (c = 0, childNode = smiGetFirstChildNode(smiNode);
Packit 022b05
	 childNode;
Packit 022b05
	 childNode = smiGetNextChildNode(childNode)) {
Packit 022b05
	if (childNode->nodekind == SMI_NODEKIND_COLUMN) {
Packit 022b05
	    fprint(f, "\n");
Packit 022b05
	    fprintLeaf(f, indent, childNode, 0);
Packit 022b05
	    c++;
Packit 022b05
	}
Packit 022b05
    }
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
static void
Packit 022b05
fprintList(FILE *f, int indent, SmiNode *smiNode)
Packit 022b05
{
Packit 022b05
    SmiNode *entryNode;
Packit 022b05
    SmiNode *childNode;
Packit 022b05
    SmiNode *parentNode;
Packit 022b05
    SmiElement *smiElement;
Packit 022b05
Packit 022b05
    entryNode = smiGetFirstChildNode(smiNode);
Packit 022b05
Packit 022b05
    fprint(f, "\n");
Packit 022b05
    fprintSegment(f, indent, "/* XXX table comments here XXX */\n", 0);
Packit 022b05
    fprint(f, "\n");
Packit 022b05
Packit 022b05
    fprintSegment(f, indent, "list", 0);
Packit 022b05
    fprint(f, " %s {\n\n", entryNode->name);
Packit 022b05
Packit 022b05
    fprintKey(f, indent + INDENT, entryNode);
Packit 022b05
    fprintStatus(f, indent + INDENT, entryNode->status);
Packit 022b05
    fprintDescription(f, indent + INDENT, entryNode->description);
Packit 022b05
    fprintReference(f, indent + INDENT, entryNode->reference);
Packit 022b05
    fprintObjectIdentifier(f, indent + INDENT,
Packit 022b05
			   entryNode->oid, entryNode->oidlen);
Packit 022b05
    fprint(f, "\n");
Packit 022b05
Packit 022b05
    for (smiElement = smiGetFirstElement(entryNode); smiElement;
Packit 022b05
	 smiElement = smiGetNextElement(smiElement)) {
Packit 022b05
	childNode = smiGetElementNode(smiElement);
Packit 022b05
	parentNode = smiGetParentNode(childNode);
Packit 022b05
        if (childNode->nodekind == SMI_NODEKIND_COLUMN
Packit 022b05
            && parentNode != entryNode) {
Packit 022b05
	    fprintKeyrefLeaf(f, indent + INDENT, childNode, 0);
Packit 022b05
	}
Packit 022b05
    }
Packit 022b05
Packit 022b05
    fprintLeafs(f, indent + INDENT, entryNode);
Packit 022b05
Packit 022b05
    fprintSegment(f, indent, "}\n", 0);
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
static void
Packit 022b05
fprintAugment(FILE *f, int indent, SmiNode *smiNode)
Packit 022b05
{
Packit 022b05
    SmiNode *baseEntryNode = NULL;
Packit 022b05
Packit 022b05
    if (smiNode) {
Packit 022b05
        baseEntryNode = smiGetRelatedNode(smiNode);
Packit 022b05
    }
Packit 022b05
    if (! smiNode || ! baseEntryNode) {
Packit 022b05
        return;
Packit 022b05
    }
Packit 022b05
Packit 022b05
    fprint(f, "\n");
Packit 022b05
    fprintSegment(f, indent, "/* XXX table comments here XXX */\n", 0);
Packit 022b05
    fprint(f, "\n");
Packit 022b05
Packit 022b05
    fprintSegment(f, indent, "augment", 0);
Packit 022b05
    fprint(f, " \"");
Packit 022b05
    fprintPath(f, baseEntryNode);
Packit 022b05
    fprint(f, "\" {\n");
Packit 022b05
    fprintStatus(f, indent + INDENT, smiNode->status);
Packit 022b05
    fprintDescription(f, indent + INDENT, smiNode->description);
Packit 022b05
    fprintReference(f, indent + INDENT, smiNode->reference);
Packit 022b05
Packit 022b05
    fprintLeafs(f, indent + INDENT, smiNode);
Packit 022b05
    fprintObjectIdentifier(f, indent + INDENT,
Packit 022b05
			   smiNode->oid, smiNode->oidlen);
Packit 022b05
    fprintSegment(f, indent, "}\n\n", 0);
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
static void
Packit 022b05
fprintAugments(FILE *f, SmiModule *smiModule)
Packit 022b05
{
Packit 022b05
    SmiNode *smiNode;
Packit 022b05
    
Packit 022b05
    for (smiNode = smiGetFirstNode(smiModule, SMI_NODEKIND_ANY);
Packit 022b05
	smiNode;
Packit 022b05
	smiNode = smiGetNextNode(smiNode, SMI_NODEKIND_ANY)) {
Packit 022b05
	if (smiNode->nodekind == SMI_NODEKIND_ROW
Packit 022b05
	    && smiNode->indexkind == SMI_INDEX_AUGMENT) {
Packit 022b05
	    fprintAugment(f, INDENT, smiNode);
Packit 022b05
	}
Packit 022b05
    }
Packit 022b05
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
static void
Packit 022b05
fprintContainer(FILE *f, int indent, SmiNode *smiNode)
Packit 022b05
{
Packit 022b05
    SmiNode *childNode;
Packit 022b05
    int c;
Packit 022b05
Packit 022b05
    fprintSegment(f, indent, "container", 0);
Packit 022b05
    fprint(f, " %s {\n\n", smiNode->name);
Packit 022b05
Packit 022b05
    for (c = 0, childNode = smiGetFirstChildNode(smiNode);
Packit 022b05
	 childNode;
Packit 022b05
	 childNode = smiGetNextChildNode(childNode)) {
Packit 022b05
	if (c) {
Packit 022b05
	    fprint(f, "\n");
Packit 022b05
	}
Packit 022b05
	if (childNode->nodekind == SMI_NODEKIND_SCALAR) {
Packit 022b05
	    fprintLeaf(f, indent + INDENT, childNode, 0);
Packit 022b05
	    c++;
Packit 022b05
	}
Packit 022b05
	if (childNode->nodekind == SMI_NODEKIND_TABLE) {
Packit 022b05
	    SmiNode *entryNode = smiGetFirstChildNode(childNode);
Packit 022b05
	    if (entryNode) {
Packit 022b05
	        switch (entryNode->indexkind) {
Packit 022b05
		case SMI_INDEX_INDEX:
Packit 022b05
		case SMI_INDEX_REORDER:
Packit 022b05
		case SMI_INDEX_SPARSE:
Packit 022b05
		case SMI_INDEX_EXPAND:
Packit 022b05
			fprintList(f, indent + INDENT, childNode);
Packit 022b05
			c++;
Packit 022b05
			break;
Packit 022b05
#if 0
Packit 022b05
		case SMI_INDEX_AUGMENT:
Packit 022b05
			fprintAugment(f, indent + INDENT, childNode);
Packit 022b05
			c++;
Packit 022b05
			break;
Packit 022b05
#endif
Packit 022b05
		default:
Packit 022b05
			break;
Packit 022b05
		}
Packit 022b05
	    }
Packit 022b05
	} 
Packit 022b05
    }
Packit 022b05
Packit 022b05
    fprintObjectIdentifier(f, indent + INDENT,
Packit 022b05
			   smiNode->oid, smiNode->oidlen);
Packit 022b05
    
Packit 022b05
    fprintSegment(f, indent, "}\n\n", 0);
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
static void
Packit 022b05
fprintContainers(FILE *f, SmiModule *smiModule)
Packit 022b05
{
Packit 022b05
    SmiNode *smiNode;
Packit 022b05
    
Packit 022b05
    for (smiNode = smiGetFirstNode(smiModule, SMI_NODEKIND_ANY);
Packit 022b05
	smiNode;
Packit 022b05
	smiNode = smiGetNextNode(smiNode, SMI_NODEKIND_ANY)) {
Packit 022b05
	if (isGroup(smiNode)) {
Packit 022b05
	    fprintContainer(f, INDENT, smiNode);
Packit 022b05
	}
Packit 022b05
    }
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
static void
Packit 022b05
fprintNamespace(FILE *f, int indent, SmiModule *smiModule)
Packit 022b05
{
Packit 022b05
     if (! silent) {
Packit 022b05
	  fprintSegment(f, indent, "/*** NAMESPACE / PREFIX DEFINITION ***/\n\n", 0);
Packit 022b05
     }
Packit 022b05
Packit 022b05
     fprintSegment(f, indent, "namespace ", 0);
Packit 022b05
     fprint(f, "\"%s%s\";\n", URNBASE, smiModule->name);
Packit 022b05
     fprintSegment(f, indent, "prefix ", 0);
Packit 022b05
     fprint(f, "\"%s\";\n\n", getModulePrefix(smiModule->name));
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
static void
Packit 022b05
fprintLinkage(FILE *f, int indent, SmiModule *smiModule)
Packit 022b05
{
Packit 022b05
     if (! silent) {
Packit 022b05
	  fprintSegment(f, indent, "/*** LINKAGE (IMPORTS / INCLUDES) ***/\n\n", 0);
Packit 022b05
     }
Packit 022b05
     fprintImports(f, smiModule);
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
static void
Packit 022b05
fprintMeta(FILE *f, int indent, SmiModule *smiModule)
Packit 022b05
{
Packit 022b05
     if (! silent) {
Packit 022b05
	  fprintSegment(f, indent, "/*** META INFORMATION ***/\n\n", 0);
Packit 022b05
     }
Packit 022b05
     fprintSegment(f, indent, "organization", INDENTVALUE);
Packit 022b05
     fprint(f, "\n");
Packit 022b05
     fprintMultilineString(f, indent, smiModule->organization);
Packit 022b05
     fprint(f, ";\n\n");
Packit 022b05
     fprintSegment(f, indent, "contact", INDENTVALUE);
Packit 022b05
     fprint(f, "\n");
Packit 022b05
     fprintMultilineString(f, indent, smiModule->contactinfo);
Packit 022b05
     fprint(f, ";\n\n");
Packit 022b05
     fprintSegment(f, indent, "description", INDENTVALUE);
Packit 022b05
     fprint(f, "\n");
Packit 022b05
     fprintMultilineString(f, indent, smiModule->description);
Packit 022b05
     fprint(f, ";\n\n");
Packit 022b05
     if (smiModule->reference) {
Packit 022b05
	  fprintSegment(f, indent, "reference", INDENTVALUE);
Packit 022b05
	  fprint(f, "\n");
Packit 022b05
	  fprintMultilineString(f, indent, smiModule->reference);
Packit 022b05
	  fprint(f, ";\n\n");
Packit 022b05
     }
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
static void
Packit 022b05
fprintNotificationIndex(FILE *f, int indent,
Packit 022b05
			SmiNode *entryNode, SmiNode *ignoreNode)
Packit 022b05
{
Packit 022b05
    SmiElement *smiElement;
Packit 022b05
    SmiNode *childNode;
Packit 022b05
    SmiNode *parentNode;
Packit 022b05
Packit 022b05
    for (smiElement = smiGetFirstElement(entryNode); smiElement;
Packit 022b05
	 smiElement = smiGetNextElement(smiElement)) {
Packit 022b05
	childNode = smiGetElementNode(smiElement);
Packit 022b05
	parentNode = smiGetParentNode(childNode);
Packit 022b05
	if (childNode != ignoreNode) {
Packit 022b05
	    fprintKeyrefLeaf(f, indent, childNode, FLAG_CONFIG_FALSE);
Packit 022b05
	}
Packit 022b05
    }
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
static int
Packit 022b05
GetPosition(SmiElement *startElement, SmiElement *thisElement)
Packit 022b05
{
Packit 022b05
    SmiElement *smiElement;
Packit 022b05
    SmiNode *smiNode;
Packit 022b05
    SmiNode *thisNode = smiGetElementNode(thisElement);
Packit 022b05
    int cnt = 0;
Packit 022b05
    
Packit 022b05
    for (smiElement = startElement, cnt = 0;
Packit 022b05
	 smiElement; smiElement = smiGetNextElement(smiElement)) {
Packit 022b05
	smiNode = smiGetElementNode(smiElement);
Packit 022b05
	if (smiNode == thisNode) cnt++;
Packit 022b05
    }
Packit 022b05
Packit 022b05
    if (cnt <= 1) {
Packit 022b05
	return 0;
Packit 022b05
    }
Packit 022b05
Packit 022b05
    for (smiElement = startElement, cnt = 0;
Packit 022b05
	 smiElement; smiElement = smiGetNextElement(smiElement)) {
Packit 022b05
	smiNode = smiGetElementNode(smiElement);
Packit 022b05
	if (smiNode == thisNode) cnt++;
Packit 022b05
	if (smiElement == thisElement) {
Packit 022b05
	    break;
Packit 022b05
	}
Packit 022b05
    }
Packit 022b05
    return cnt;
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
static void
Packit 022b05
fprintNotification(FILE *f, SmiNode *smiNode)
Packit 022b05
{
Packit 022b05
    SmiElement *smiElement;
Packit 022b05
    SmiNode *vbNode, *entryNode;
Packit 022b05
    int c, cnt;
Packit 022b05
    
Packit 022b05
    fprintSegment(f, INDENT, "notification", 0);
Packit 022b05
    fprint(f, " %s {\n", smiNode->name);
Packit 022b05
    fprintStatus(f, INDENT + INDENT, smiNode->status);
Packit 022b05
    fprintDescription(f, INDENT + INDENT, smiNode->description);
Packit 022b05
    fprintReference(f, INDENT + INDENT, smiNode->reference);
Packit 022b05
    fprintObjectIdentifier(f, INDENT + INDENT, smiNode->oid, smiNode->oidlen);
Packit 022b05
    fprint(f, "\n");
Packit 022b05
Packit 022b05
    for (c = 0, smiElement = smiGetFirstElement(smiNode); smiElement;
Packit 022b05
	 c++, smiElement = smiGetNextElement(smiElement)) {
Packit 022b05
	vbNode = smiGetElementNode(smiElement);
Packit 022b05
	if (! vbNode) continue;
Packit 022b05
Packit 022b05
	cnt = GetPosition(smiGetFirstElement(smiNode), smiElement);
Packit 022b05
Packit 022b05
	entryNode = (vbNode->nodekind == SMI_NODEKIND_COLUMN)
Packit 022b05
	    ? smiGetParentNode(vbNode) : NULL;
Packit 022b05
Packit 022b05
	fprintSegment(f, INDENT + INDENT, "container ", 0);
Packit 022b05
	if (cnt) {
Packit 022b05
	    fprintf(f, "%s-%s-%d {\n", smiNode->name, vbNode->name, cnt);
Packit 022b05
	} else {
Packit 022b05
	    fprintf(f, "%s-%s {\n", smiNode->name, vbNode->name);
Packit 022b05
	}
Packit 022b05
Packit 022b05
	if (entryNode) {
Packit 022b05
	    switch (entryNode->indexkind) {
Packit 022b05
	    case SMI_INDEX_INDEX:
Packit 022b05
		fprintNotificationIndex(f, INDENT + INDENT + INDENT,
Packit 022b05
					entryNode, vbNode);
Packit 022b05
		break;
Packit 022b05
	    case SMI_INDEX_AUGMENT:
Packit 022b05
		fprintNotificationIndex(f, INDENT + INDENT + INDENT,
Packit 022b05
					smiGetRelatedNode(entryNode), vbNode);
Packit 022b05
		break;
Packit 022b05
	    default:
Packit 022b05
		break;
Packit 022b05
	    }
Packit 022b05
	}
Packit 022b05
	
Packit 022b05
	if (entryNode && isIndex(entryNode, vbNode)) {
Packit 022b05
	    fprintKeyrefLeaf(f, INDENT + INDENT + INDENT,
Packit 022b05
			     vbNode, FLAG_CONFIG_FALSE);
Packit 022b05
	} else {
Packit 022b05
	    fprintLeaf(f, INDENT + INDENT + INDENT,
Packit 022b05
		       vbNode, FLAG_CONFIG_FALSE);
Packit 022b05
	}
Packit 022b05
	fprintSegment(f, INDENT + INDENT, "}\n\n", 0);
Packit 022b05
    }
Packit 022b05
Packit 022b05
    fprintSegment(f, INDENT, "}\n", 0);
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
static void
Packit 022b05
fprintNotifications(FILE *f, SmiModule *smiModule)
Packit 022b05
{
Packit 022b05
    SmiNode *smiNode;
Packit 022b05
    int c;
Packit 022b05
Packit 022b05
    for (c = 0, smiNode = smiGetFirstNode(smiModule,
Packit 022b05
					  SMI_NODEKIND_NOTIFICATION);
Packit 022b05
	 smiNode;
Packit 022b05
	 c++, smiNode = smiGetNextNode(smiNode,
Packit 022b05
				       SMI_NODEKIND_NOTIFICATION)) {
Packit 022b05
	if (c) {
Packit 022b05
	    fprint(f, "\n");
Packit 022b05
	}
Packit 022b05
	fprintNotification(f, smiNode);
Packit 022b05
    }
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
static void
Packit 022b05
dumpYang(int modc, SmiModule **modv, int flags, char *output)
Packit 022b05
{
Packit 022b05
    SmiModule   *smiModule;
Packit 022b05
    int		i;
Packit 022b05
    FILE	*f = stdout;
Packit 022b05
Packit 022b05
    silent = (flags & SMIDUMP_FLAG_SILENT);
Packit 022b05
Packit 022b05
    fprint_indent_texts = INDENT;
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
	smiModule = modv[i];
Packit 022b05
Packit 022b05
        createImportList(smiModule);
Packit 022b05
Packit 022b05
	fprint(f, "/*\n");
Packit 022b05
	fprint(f, " * This module has been generated by smidump "
Packit 022b05
	       SMI_VERSION_STRING ":\n");
Packit 022b05
	fprint(f, " *\n");
Packit 022b05
	fprint(f, " *      smidump -f yang");
Packit 022b05
	if (silent) {
Packit 022b05
	    fprint(f, " -q");
Packit 022b05
	}
Packit 022b05
	if (sflag) {
Packit 022b05
	    fprint(f, " --yang-smi-extensions");
Packit 022b05
	}
Packit 022b05
	if (nflag) {
Packit 022b05
	    fprint(f, " --yang-no-notifications");
Packit 022b05
	}
Packit 022b05
	fprint(f, " %s\n", smiModule->name);
Packit 022b05
	fprint(f, " *\n");
Packit 022b05
	fprint(f, " * Do not edit. Edit the source file instead!\n");
Packit 022b05
	fprint(f, " */\n\n");
Packit 022b05
	fprint(f, "module %s {\n", smiModule->name);
Packit 022b05
	fprint(f, "\n");
Packit 022b05
Packit 022b05
	fprintNamespace(f, INDENT, smiModule);
Packit 022b05
	fprintLinkage(f, INDENT, smiModule);
Packit 022b05
	fprintMeta(f, INDENT, smiModule);
Packit 022b05
	fprintRevisions(f, INDENT, smiModule);
Packit 022b05
Packit 022b05
	fprintTypedefs(f, modv[i]);
Packit 022b05
	fprintContainers(f, modv[i]);
Packit 022b05
	fprintAugments(f, modv[i]);
Packit 022b05
Packit 022b05
	if (! nflag) {
Packit 022b05
	    fprintNotifications(f, modv[i]);
Packit 022b05
	}
Packit 022b05
Packit 022b05
    	fprint(f, "} /* end of module %s */\n", smiModule->name);
Packit 022b05
Packit 022b05
        freeImportList();
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
Packit 022b05
void initYang()
Packit 022b05
{
Packit 022b05
    static SmidumpDriverOption opt[] = {
Packit 022b05
	{ "smi-extensions", OPT_FLAG, &sflag, 0,
Packit 022b05
	  "generate smi extensions" },
Packit 022b05
	{ "no-notifications", OPT_FLAG, &nflag, 0,
Packit 022b05
	  "do not generate notifications" },
Packit 022b05
	{ "indent", OPT_INT, &INDENT, 0,
Packit 022b05
	  "indentation (default 2)" },
Packit 022b05
        { 0, OPT_END, 0, 0 }
Packit 022b05
    };
Packit 022b05
Packit 022b05
    static SmidumpDriver driver = {
Packit 022b05
	"yang",
Packit 022b05
	dumpYang,
Packit 022b05
	0,
Packit 022b05
	SMIDUMP_DRIVER_CANT_UNITE,
Packit 022b05
	"YANG format",
Packit 022b05
	opt,
Packit 022b05
	NULL
Packit 022b05
    };
Packit 022b05
    
Packit 022b05
    smidumpRegisterDriver(&driver);
Packit 022b05
}