1310903Sngie/* 2159063Sharti * Copyright (C) 2004-2006 3133211Sharti * Hartmut Brandt. 4133211Sharti * All rights reserved. 5310903Sngie * 6128237Sharti * Author: Harti Brandt <harti@freebsd.org> 7310903Sngie * 8133211Sharti * Redistribution and use in source and binary forms, with or without 9133211Sharti * modification, are permitted provided that the following conditions 10133211Sharti * are met: 11133211Sharti * 1. Redistributions of source code must retain the above copyright 12133211Sharti * notice, this list of conditions and the following disclaimer. 13128237Sharti * 2. Redistributions in binary form must reproduce the above copyright 14128237Sharti * notice, this list of conditions and the following disclaimer in the 15128237Sharti * documentation and/or other materials provided with the distribution. 16310903Sngie * 17133211Sharti * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18133211Sharti * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19133211Sharti * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20133211Sharti * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 21133211Sharti * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22133211Sharti * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23133211Sharti * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24133211Sharti * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25133211Sharti * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26133211Sharti * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27133211Sharti * SUCH DAMAGE. 28128237Sharti * 29159063Sharti * $Begemot: gensnmpdef.c 383 2006-05-30 07:40:49Z brandt_h $ 30128237Sharti */ 31159063Sharti#include <sys/queue.h> 32159063Sharti 33128237Sharti#include <stdio.h> 34128237Sharti#include <stdlib.h> 35128237Sharti#include <string.h> 36128237Sharti#include <unistd.h> 37128237Sharti#include <errno.h> 38128237Sharti#include <err.h> 39128237Sharti#include <assert.h> 40128237Sharti#include <smi.h> 41128237Sharti 42128237Shartistatic const char usgtxt[] = 43159063Sharti"Usage: gensnmpdef [-hEe] [-c <cut>] MIB [MIB ...]\n" 44128237Sharti"Options:\n" 45128237Sharti" -c specify the number of initial sub-oids to cut from the oids\n" 46159063Sharti" -E extract named enum types. Print a typedef for all enums defined\n" 47159063Sharti" in syntax clauses of normal objects. Suppress normal output.\n" 48159063Sharti" -e extract unnamed enum types. Print a typedef for all enums defined\n" 49159063Sharti" as textual conventions. Suppress normal output.\n" 50128237Sharti" -h print this help\n" 51128237Sharti"MIBs are searched according to the libsmi(3) search rules and can\n" 52128237Sharti"be specified either by path or module name\n"; 53128237Sharti 54128237Shartistatic SmiNode *last_node; 55128237Shartistatic u_int cut = 3; 56128237Sharti 57159063Shartistruct tdef { 58159063Sharti char *name; 59159063Sharti SLIST_ENTRY(tdef) link; 60159063Sharti}; 61159063Sharti 62205729Santoinestatic SLIST_HEAD(, tdef) tdefs = SLIST_HEAD_INITIALIZER(tdefs); 63159063Shartistatic int do_typedef = 0; 64159063Sharti 65128237Shartistatic void print_node(SmiNode *n, u_int level); 66128237Sharti 67128237Shartistatic void 68128237Shartisave_node(SmiNode *n) 69128237Sharti{ 70128237Sharti if (n != NULL) 71128237Sharti last_node = n; 72128237Sharti} 73128237Sharti 74128237Shartistatic void 75128237Shartipindent(u_int level) 76128237Sharti{ 77128237Sharti if (level >= cut) 78128237Sharti printf("%*s", (level - cut) * 2, ""); 79128237Sharti} 80128237Sharti 81128237Shartistatic void 82128237Shartiprint_name(SmiNode *n) 83128237Sharti{ 84128237Sharti char *p; 85128237Sharti 86128237Sharti for (p = n->name; *p != '\0'; p++) { 87128237Sharti if (*p == '-') 88128237Sharti printf("_"); 89128237Sharti else 90128237Sharti printf("%c", *p); 91128237Sharti } 92128237Sharti} 93128237Sharti 94128237Shartistatic u_int 95128237Sharticlose_node(u_int n, u_int level) 96128237Sharti{ 97128237Sharti while (n--) { 98128237Sharti pindent(level); 99128237Sharti level--; 100128237Sharti if (level >= cut) 101128237Sharti printf(")\n"); 102128237Sharti } 103128237Sharti return (level); 104128237Sharti} 105128237Sharti 106128237Shartistatic u_int 107128237Shartiopen_node(const SmiNode *n, u_int level, SmiNode **last) 108128237Sharti{ 109128237Sharti SmiNode *n1; 110128237Sharti u_int i; 111128237Sharti 112128237Sharti if (*last != NULL) { 113128237Sharti for (i = 0; i < (*last)->oidlen - 1; i++) { 114128237Sharti if (i >= n->oidlen) { 115128237Sharti level = close_node((*last)->oidlen - 116128237Sharti n->oidlen, level); 117128237Sharti break; 118128237Sharti } 119128237Sharti if ((*last)->oid[i] != n->oid[i]) 120128237Sharti break; 121128237Sharti } 122128237Sharti if (i < (*last)->oidlen - 1) 123128237Sharti level = close_node((*last)->oidlen - 1 - i, 124128237Sharti level - 1) + 1; 125128237Sharti } 126128237Sharti 127128237Sharti while (level < n->oidlen - 1) { 128128237Sharti if (level >= cut) { 129312098Sngie n1 = smiGetNodeByOID(level + 1, n->oid); 130312098Sngie if (n1 == NULL) 131312098Sngie continue; 132128237Sharti pindent(level); 133128237Sharti printf("(%u", n->oid[level]); 134128237Sharti printf(" "); 135128237Sharti print_name(n1); 136128237Sharti printf("\n"); 137128237Sharti } 138128237Sharti level++; 139128237Sharti } 140128237Sharti return (level); 141128237Sharti} 142128237Sharti 143128237Shartistatic const char *const type_names[] = { 144128237Sharti [SMI_BASETYPE_UNKNOWN] = "UNKNOWN_TYPE", 145128237Sharti [SMI_BASETYPE_INTEGER32] = "INTEGER", 146128237Sharti [SMI_BASETYPE_OCTETSTRING] = "OCTETSTRING", 147128237Sharti [SMI_BASETYPE_OBJECTIDENTIFIER] = "OID", 148128237Sharti [SMI_BASETYPE_UNSIGNED32] = "UNSIGNED32", 149128237Sharti [SMI_BASETYPE_INTEGER64] = "INTEGER64", 150128237Sharti [SMI_BASETYPE_UNSIGNED64] = "UNSIGNED64", 151128237Sharti [SMI_BASETYPE_FLOAT32] = "FLOAT32", 152128237Sharti [SMI_BASETYPE_FLOAT64] = "FLOAT64", 153128237Sharti [SMI_BASETYPE_FLOAT128] = "FLOAT128", 154159063Sharti [SMI_BASETYPE_ENUM] = "ENUM", 155128237Sharti [SMI_BASETYPE_BITS] = "BITS", 156128237Sharti}; 157128237Sharti 158128237Shartistatic const char *const type_map[] = { 159128237Sharti "Gauge32", "GAUGE", 160128237Sharti "Gauge", "GAUGE", 161128237Sharti "TimeTicks", "TIMETICKS", 162128237Sharti "Counter32", "COUNTER", 163128237Sharti "Counter", "COUNTER", 164128237Sharti "Counter64", "COUNTER64", 165128237Sharti "Integer32", "INTEGER32", 166128237Sharti "IpAddress", "IPADDRESS", 167128237Sharti NULL 168128237Sharti}; 169128237Sharti 170128237Shartistatic void 171159063Shartiprint_enum(SmiType *t) 172159063Sharti{ 173159063Sharti SmiNamedNumber *nnum; 174159063Sharti 175159063Sharti printf(" ("); 176159063Sharti for (nnum = smiGetFirstNamedNumber(t); nnum != NULL; 177159063Sharti nnum = smiGetNextNamedNumber(nnum)) 178159063Sharti printf(" %ld %s", nnum->value.value.integer32, nnum->name); 179159063Sharti printf(" )"); 180159063Sharti} 181159063Sharti 182159063Shartistatic void 183128237Shartiprint_type(SmiNode *n) 184128237Sharti{ 185128237Sharti SmiType *type; 186128237Sharti u_int m; 187128237Sharti 188128237Sharti type = smiGetNodeType(n); 189128237Sharti assert(type != NULL); 190128237Sharti 191128237Sharti if (type->name != NULL) { 192128237Sharti for (m = 0; type_map[m] != NULL; m += 2) 193128237Sharti if (strcmp(type_map[m], type->name) == 0) { 194128237Sharti printf("%s", type_map[m + 1]); 195128237Sharti return; 196128237Sharti } 197128237Sharti } 198128237Sharti printf("%s", type_names[type->basetype]); 199159063Sharti 200159063Sharti if (type->basetype == SMI_BASETYPE_ENUM || 201159063Sharti type->basetype == SMI_BASETYPE_BITS) 202159063Sharti print_enum(type); 203159063Sharti 204159063Sharti else if (type->basetype == SMI_BASETYPE_OCTETSTRING && 205159063Sharti type->name != NULL) 206159063Sharti printf(" | %s", type->name); 207128237Sharti} 208128237Sharti 209128237Shartistatic void 210128237Shartiprint_access(SmiAccess a) 211128237Sharti{ 212128237Sharti if (a == SMI_ACCESS_READ_ONLY) 213128237Sharti printf(" GET"); 214128237Sharti else if (a == SMI_ACCESS_READ_WRITE) 215128237Sharti printf(" GET SET"); 216128237Sharti} 217128237Sharti 218128237Shartistatic void 219128237Shartiprint_scalar(SmiNode *n, u_int level) 220128237Sharti{ 221128237Sharti SmiNode *p; 222128237Sharti 223128237Sharti assert (n->nodekind == SMI_NODEKIND_SCALAR); 224128237Sharti 225128237Sharti save_node(n); 226128237Sharti 227128237Sharti pindent(level); 228128237Sharti printf("(%u ", n->oid[level]); 229128237Sharti print_name(n); 230128237Sharti printf(" "); 231128237Sharti print_type(n); 232128237Sharti 233128237Sharti /* generate the operation from the parent node name */ 234128237Sharti p = smiGetParentNode(n); 235128237Sharti printf(" op_%s", p->name); 236128237Sharti 237128237Sharti print_access(n->access); 238310903Sngie 239128237Sharti printf(")\n"); 240128237Sharti} 241128237Sharti 242128237Shartistatic void 243128237Shartiprint_notification(SmiNode *n, u_int level) 244128237Sharti{ 245128237Sharti 246128237Sharti assert (n->nodekind == SMI_NODEKIND_NOTIFICATION); 247128237Sharti 248128237Sharti save_node(n); 249128237Sharti 250128237Sharti pindent(level); 251128237Sharti printf("(%u ", n->oid[level]); 252128237Sharti print_name(n); 253128237Sharti printf(" OID"); 254128237Sharti 255128237Sharti printf(" op_%s)\n", n->name); 256128237Sharti} 257128237Sharti 258128237Shartistatic void 259128237Shartiprint_col(SmiNode *n, u_int level) 260128237Sharti{ 261128237Sharti assert (n->nodekind == SMI_NODEKIND_COLUMN); 262128237Sharti 263128237Sharti save_node(n); 264128237Sharti 265128237Sharti pindent(level); 266128237Sharti printf("(%u ", n->oid[level]); 267128237Sharti print_name(n); 268128237Sharti printf(" "); 269128237Sharti print_type(n); 270128237Sharti print_access(n->access); 271128237Sharti printf(")\n"); 272128237Sharti} 273128237Sharti 274128237Shartistatic void 275128237Shartiprint_index(SmiNode *row) 276128237Sharti{ 277128237Sharti SmiElement *e; 278128237Sharti 279128237Sharti e = smiGetFirstElement(row); 280128237Sharti while (e != NULL) { 281128237Sharti printf(" "); 282128237Sharti print_type(smiGetElementNode(e)); 283128237Sharti e = smiGetNextElement(e); 284128237Sharti } 285128237Sharti} 286128237Sharti 287128237Shartistatic void 288128237Shartiprint_table(SmiNode *n, u_int level) 289128237Sharti{ 290128237Sharti SmiNode *row, *col, *rel; 291128237Sharti 292128237Sharti assert (n->nodekind == SMI_NODEKIND_TABLE); 293128237Sharti 294128237Sharti save_node(n); 295128237Sharti 296128237Sharti pindent(level); 297128237Sharti printf("(%u ", n->oid[level]); 298128237Sharti print_name(n); 299128237Sharti printf("\n"); 300128237Sharti 301128237Sharti row = smiGetFirstChildNode(n); 302128237Sharti if (row->nodekind != SMI_NODEKIND_ROW) 303128237Sharti errx(1, "%s: kind %u, not row", __func__, row->nodekind); 304128237Sharti 305128237Sharti save_node(n); 306128237Sharti 307128237Sharti pindent(level + 1); 308128237Sharti printf("(%u ", row->oid[level + 1]); 309128237Sharti print_name(row); 310128237Sharti printf(" :"); 311128237Sharti 312128237Sharti /* index */ 313128237Sharti rel = smiGetRelatedNode(row); 314128237Sharti switch (row->indexkind) { 315128237Sharti 316128237Sharti case SMI_INDEX_INDEX: 317128237Sharti print_index(row); 318128237Sharti break; 319128237Sharti 320128237Sharti case SMI_INDEX_AUGMENT: 321128237Sharti if (rel == NULL) 322128237Sharti errx(1, "%s: cannot find augemented table", row->name); 323128237Sharti print_index(rel); 324128237Sharti break; 325128237Sharti 326128237Sharti default: 327128237Sharti errx(1, "%s: cannot handle index kind %u", row->name, 328128237Sharti row->indexkind); 329128237Sharti } 330128237Sharti 331128237Sharti printf(" op_%s", n->name); 332128237Sharti printf("\n"); 333128237Sharti 334128237Sharti col = smiGetFirstChildNode(row); 335128237Sharti while (col != NULL) { 336128237Sharti print_col(col, level + 2); 337128237Sharti col = smiGetNextChildNode(col); 338128237Sharti } 339128237Sharti pindent(level + 1); 340128237Sharti printf(")\n"); 341128237Sharti 342128237Sharti pindent(level); 343128237Sharti printf(")\n"); 344128237Sharti} 345128237Sharti 346128237Shartistatic void 347128237Shartiprint_it(SmiNode *n, u_int level) 348128237Sharti{ 349128237Sharti switch (n->nodekind) { 350128237Sharti 351128237Sharti case SMI_NODEKIND_NODE: 352128237Sharti print_node(n, level); 353128237Sharti break; 354128237Sharti 355128237Sharti case SMI_NODEKIND_SCALAR: 356128237Sharti print_scalar(n, level); 357128237Sharti break; 358128237Sharti 359128237Sharti case SMI_NODEKIND_TABLE: 360128237Sharti print_table(n, level); 361128237Sharti break; 362128237Sharti 363128237Sharti case SMI_NODEKIND_COMPLIANCE: 364128237Sharti case SMI_NODEKIND_GROUP: 365128237Sharti save_node(n); 366128237Sharti break; 367128237Sharti 368128237Sharti case SMI_NODEKIND_NOTIFICATION: 369128237Sharti print_notification(n, level); 370128237Sharti break; 371128237Sharti 372128237Sharti default: 373128237Sharti errx(1, "cannot handle %u nodes", n->nodekind); 374128237Sharti } 375128237Sharti} 376128237Sharti 377128237Shartistatic void 378128237Shartiprint_node(SmiNode *n, u_int level) 379128237Sharti{ 380128237Sharti assert (n->nodekind == SMI_NODEKIND_NODE); 381128237Sharti 382128237Sharti save_node(n); 383128237Sharti 384128237Sharti pindent(level); 385128237Sharti printf("(%u ", n->oid[level]); 386128237Sharti print_name(n); 387128237Sharti printf("\n"); 388128237Sharti 389128237Sharti n = smiGetFirstChildNode(n); 390128237Sharti while (n != NULL) { 391128237Sharti print_it(n, level + 1); 392128237Sharti n = smiGetNextChildNode(n); 393128237Sharti } 394128237Sharti pindent(level); 395128237Sharti printf(")\n"); 396128237Sharti} 397128237Sharti 398159063Shartistatic void 399159063Shartisave_typdef(char *name) 400159063Sharti{ 401159063Sharti struct tdef *t; 402159063Sharti 403312098Sngie t = calloc(1, sizeof(struct tdef)); 404159063Sharti if (t == NULL) 405159063Sharti err(1, NULL); 406159063Sharti 407159063Sharti t->name = name; 408159063Sharti SLIST_INSERT_HEAD(&tdefs, t, link); 409159063Sharti} 410159063Sharti 411159063Shartistatic void 412159063Shartitdefs_cleanup(void) 413159063Sharti{ 414159063Sharti struct tdef *t; 415159063Sharti 416159063Sharti while ((t = SLIST_FIRST(&tdefs)) != NULL) { 417159063Sharti SLIST_REMOVE_HEAD(&tdefs, link); 418159063Sharti free(t); 419159063Sharti } 420159063Sharti} 421159063Sharti 422159063Shartistatic void 423159063Shartiprint_enum_typedef(SmiType *t) 424159063Sharti{ 425159063Sharti SmiNamedNumber *nnum; 426310903Sngie 427159063Sharti for (nnum = smiGetFirstNamedNumber(t); nnum != NULL; 428159063Sharti nnum = smiGetNextNamedNumber(nnum)) { 429159063Sharti printf("\t%ld %s\n" , nnum->value.value.integer32, nnum->name); 430159063Sharti } 431159063Sharti} 432159063Sharti 433159063Shartistatic void 434159063Shartiprint_stype(SmiNode *n) 435159063Sharti{ 436159063Sharti SmiType *type; 437159063Sharti struct tdef *t = NULL; 438310903Sngie 439159063Sharti type = smiGetNodeType(n); 440159063Sharti assert(type != NULL); 441310903Sngie 442159063Sharti if (type->basetype == SMI_BASETYPE_ENUM) { 443159063Sharti if (do_typedef == 'e' && type->name != NULL) { 444159063Sharti SLIST_FOREACH(t, &tdefs, link) { 445159063Sharti if (strcmp(t->name, type->name) == 0) 446159063Sharti return; 447159063Sharti } 448159063Sharti save_typdef(type->name); 449159063Sharti printf("typedef %s ENUM (\n", type->name); 450159063Sharti } else if (do_typedef == 'E' && type->name == NULL) 451159063Sharti printf("typedef %sType ENUM (\n", n->name); 452159063Sharti else 453159063Sharti return; 454310903Sngie 455159063Sharti print_enum_typedef(type); 456159063Sharti printf(")\n\n"); 457159063Sharti 458159063Sharti } else if (type->basetype == SMI_BASETYPE_BITS) { 459159063Sharti if (do_typedef == 'e' && type->name != NULL) { 460159063Sharti SLIST_FOREACH(t, &tdefs, link) { 461159063Sharti if (strcmp(t->name, type->name) == 0) 462159063Sharti return; 463159063Sharti } 464159063Sharti save_typdef(type->name); 465159063Sharti printf("typedef %s BITS (\n", type->name); 466159063Sharti } else if (do_typedef == 'E' && type->name == NULL) 467159063Sharti printf("typedef %sType BITS (\n", n->name); 468159063Sharti else 469159063Sharti return; 470159063Sharti 471159063Sharti print_enum_typedef(type); 472159063Sharti printf(")\n\n"); 473159063Sharti } 474159063Sharti} 475159063Sharti 476159063Shartistatic void 477159063Shartiprint_typdefs(SmiNode *n) 478159063Sharti{ 479159063Sharti SmiNode *p; 480310903Sngie 481159063Sharti p = n; 482159063Sharti n = smiGetFirstChildNode(n); 483159063Sharti while (n != NULL) { 484159063Sharti switch (n->nodekind) { 485159063Sharti case SMI_NODEKIND_SCALAR: 486159063Sharti case SMI_NODEKIND_COLUMN: 487159063Sharti print_stype(n); 488159063Sharti break; 489159063Sharti case SMI_NODEKIND_COMPLIANCE: 490159063Sharti case SMI_NODEKIND_GROUP: 491159063Sharti save_node(n); 492159063Sharti return; 493159063Sharti default: 494159063Sharti break; 495159063Sharti } 496159063Sharti n = smiGetNextChildNode(n); 497159063Sharti } 498159063Sharti 499159063Sharti save_node(p); 500159063Sharti} 501159063Sharti 502128237Shartiint 503128237Shartimain(int argc, char *argv[]) 504128237Sharti{ 505128237Sharti int opt; 506128237Sharti int flags; 507128237Sharti SmiModule **mods; 508128237Sharti char *name; 509128237Sharti SmiNode *n, *last; 510128237Sharti u_int level; 511128237Sharti long u; 512128237Sharti char *end; 513128237Sharti 514128237Sharti smiInit(NULL); 515128237Sharti 516159063Sharti while ((opt = getopt(argc, argv, "c:Eeh")) != -1) 517128237Sharti switch (opt) { 518128237Sharti 519128237Sharti case 'c': 520128237Sharti errno = 0; 521128237Sharti u = strtol(optarg, &end, 10); 522128237Sharti if (errno != 0) 523128237Sharti err(1, "argument to -c"); 524128237Sharti if (*end != '\0') 525128237Sharti err(1, "%s: not a number", optarg); 526128237Sharti if (u < 0 || u > 5) 527128237Sharti err(1, "%s: out of range", optarg); 528128237Sharti cut = (u_int)u; 529128237Sharti break; 530128237Sharti 531159063Sharti case 'E': 532159063Sharti do_typedef = 'E'; 533159063Sharti break; 534159063Sharti 535159063Sharti case 'e': 536159063Sharti do_typedef = 'e'; 537159063Sharti break; 538159063Sharti 539128237Sharti case 'h': 540128237Sharti fprintf(stderr, usgtxt); 541128237Sharti exit(0); 542128237Sharti } 543128237Sharti 544128237Sharti argc -= optind; 545128237Sharti argv += optind; 546128237Sharti 547128237Sharti flags = smiGetFlags(); 548128237Sharti flags |= SMI_FLAG_ERRORS; 549128237Sharti smiSetFlags(flags); 550128237Sharti 551128237Sharti mods = malloc(sizeof(mods[0]) * argc); 552128237Sharti if (mods == NULL) 553128237Sharti err(1, NULL); 554128237Sharti 555128237Sharti for (opt = 0; opt < argc; opt++) { 556128237Sharti if ((name = smiLoadModule(argv[opt])) == NULL) 557128237Sharti err(1, "%s: cannot load", argv[opt]); 558128237Sharti mods[opt] = smiGetModule(name); 559128237Sharti } 560128237Sharti level = 0; 561128237Sharti last = NULL; 562128237Sharti for (opt = 0; opt < argc; opt++) { 563312098Sngie if (mods[opt] == NULL) /* smiGetModule failed above */ 564312098Sngie continue; 565128237Sharti n = smiGetFirstNode(mods[opt], SMI_NODEKIND_ANY); 566312098Sngie if (n == NULL) 567312098Sngie continue; 568128237Sharti for (;;) { 569159063Sharti if (do_typedef == 0) { 570159063Sharti level = open_node(n, level, &last); 571159063Sharti print_it(n, level); 572159063Sharti last = n; 573159063Sharti } else 574159063Sharti print_typdefs(n); 575128237Sharti 576128237Sharti if (last_node == NULL || 577128237Sharti (n = smiGetNextNode(last_node, SMI_NODEKIND_ANY)) 578128237Sharti == NULL) 579128237Sharti break; 580128237Sharti } 581128237Sharti } 582159063Sharti if (last != NULL && do_typedef == 0) 583159063Sharti level = close_node(last->oidlen - 1, level - 1); 584159063Sharti else if (do_typedef != 0) 585159063Sharti tdefs_cleanup(); 586159063Sharti 587128237Sharti return (0); 588128237Sharti} 589