#!/usr/bin/awk -f # # MIB to HTML file converter # Copyright (C) 1996 by Equivalance # # # # This script will convert most MIB definition files into a tree of # HTML files that can be used by MibMaster. It requires the "awk" # program, and is invoked as follows: # # awk -f mib_to_html mib.txt # # where: mib.txt is the input ASN file # # While running, it will print the names of all files it creates. The # last file generated will contain hyperlinks to all of the top level # files for the MIBs. It will have the same name as the MIB definition. # # This script will correctly interpret tables, and will automatically # detect and fill in enumerated types. It extracts the MIB descriptions # and inserts them as online help automatically. In fact, it's pretty damn # good, and will take every MIB file I can throw at it!! # # # Parse error codes # 100 expected IDENTIFIER # 101 expected IDENTIFIER # 102 type does not exist # 104 expected { or OF # 105 expected ACCESS type # 106 expected object attribute # 107 symbol used but not defined # 108 expected object identifer # 109 Attempt to define with empty name # 110 Attempt to redefine symbol # 111 Expected LITERAL ################################################################### ## ## general functions ## # # parse_error # display a parse error # function parse_error(num, str) { print "parse error " num " near line " NR " : " str; } # # generate_error # display a code generation error # function gen_error(num, str) { print "codegen error " num " : " str; } # # generate_warning # display a code generation warning # function gen_warning(num, str) { print "codegen warning " num " : " str; } # # sort # sort an array of strings and return the sorted indexes in _sort # function sort(array, f, i, len, t) { len = 0 for (i in array) { _sort[len] = i; len++; } f = 1; while (f != 0) { f = 0; for (i = 0; i < len-1; i++) { if (array[_sort[i]] > array[_sort[i+1]]) { t = _sort[i]; _sort[i] = _sort[i+1] _sort[i+1] = t; f = 1; } } } return len; } function sortobj(array, len) { len = 0 for (i in array) { _sort[len] = i; len++; } quicksort_obj(array, 0, len-1); return len; } function quicksort_obj(array, l, r, v, t, i, j, c) { if (r > l) { v = array[_sort[r]]; i = l - 1; j = r; do { do { i = i + 1; c = compare_oid(array[_sort[i]], v) } while (c < 0) do { j = j - 1; c = compare_oid(array[_sort[j]], v) } while (c > 0) t = _sort[i]; _sort[i] = _sort[j]; _sort[j] = t } while (j > i); _sort[j] = _sort[i]; _sort[i] = _sort[r]; _sort[r] = t quicksort_obj(array, l, i-1) quicksort_obj(array, i+1, r) } } # # make_filename # given a basename, make a legal filename. Also check it # for uniqueness against all other filenames created so far, # and also hack it for 8.3 compliance if required # function make_filename(fn, nfn, i) { if (_force8dot3) nfn = substr(tolower(fn), 1, 8) else nfn = tolower(fn) fn = nfn nfn = fn _fileext if (_force8dot3) nfn = substr(tolower(fn), 1, 6) else nfn = tolower(fn) fn = nfn; i = 0; nfn = fn _fileext while (nfn in _filenames) { i++; nfn = fn i _fileext } _filenames[nfn] = 1; return nfn; } # # compare_oid # compare two oids in terms of their numeric order # function compare_oid(oid1, oid2, l1, l2, c, j) { l1 = split(oid1, a1, ".") l2 = split(oid2, a2, ".") c = 0; j = 1; while ((c == 0) && (j <= l1) && (j <= l2)) { c = (a1[j] + 0) - (a2[j] + 0) j++ } if (c == 0) c = l1 - l2; return c; } # # relate_oid # compare the relationship between two oids. # if oid1 is a child of oid2, return -1 # if oid1 is identical to oid1, return 0 # if oid1 is a parent of oid2, return 1 # if the Lowest Common Parent of oid1 and oid2 isn't oid1 or oid, return 2 # # function relate_oid(oid1, oid2, l1, l2, c, j) { l1 = split(oid1, a1, ".") l2 = split(oid2, a2, ".") c = 0; j = 1; while ((c == 0) && (j <= l1) && (j <= l2)) { c = a1[j] - a2[j] j++ } if (c == 0) { if (l1 == l2) return 0; else if (l1 < l2) return 1; else return -1; } return 2; } # # return the parent of an oid by removing the last integer # function get_parent_oid(oid, n, array, i, poid) { # calculate the parent oid n = split(oid, array, ".") for (i = 1; i < n; i++) { if (i == 1) poid = array[i] else poid = poid "." array[i] } return poid; } function print_indent(indent) { for (i = 0; i < indent; i++) printf " "; } ################################################################### ## ## lexical analyser functions ## function get_new_line( stat, line) { do { stat = getline line; if (stat <= 0) return EOF; gsub(/^[ \t]*/, "", line); gsub(/[ \t]$/, "", line); } while (line == "") return line; } function get_raw_token( n, s, t, u, z) { gsub(/^[ \t]*/, "", _text); gsub(/[ \t]$/, "", line); while (1) { if (_text == "") _text = get_new_line() if (_text == EOF) return EOF; if (_text !~ /^\-\-/) break; _text = get_new_line(); if (_text == EOF) return EOF; } if (_text ~ /^\"[^\"]*/) { gsub(/^\"/, "", _text); sval = ""; while (1) { gsub(/^[ \t]*/, "", _text); gsub(/[ \t]*$/, "", _text); if (_text ~ /\"[ \t]*$/) break; if (sval == "") sval = _text "\n" else sval = sval " " _text "\n" stat = getline _text; if (stat <= 0) break; if (_text ~ /^[ \t]*$/) _text = "

\n" } gsub(/\"$/, "\n", _text); sval = sval _text _text = ""; return LITERAL; } if (match(_text, /^[a-zA-Z][a-zA-Z0-9\-_]+/) == 1) { sval = substr(_text, 1, RLENGTH); u = substr(_text, RLENGTH+1); _text = u; return IDENTIFIER; } if (match(_text, /[0-9]+/) == 1) { sval = substr(_text, 1, RLENGTH); u = substr(_text, RLENGTH+1); _text = u; return INTEGER; } if (match(_text, /^\:\:\=/) == 1) { sval = substr(_text, 1, RLENGTH); u = substr(_text, RLENGTH+1); _text = u; return ASSIGNMENT; } t = substr(_text, 1, 1); sval = t; _text = substr(_text, 2); return t; } function ignore_line() { _text = ""; } function get_token( t) { if (_unget_sp > 0) { t = _unget_token_stack [_unget_sp]; sval = _unget_lexeme_stack[_unget_sp]; _unget_sp--; return t; } t = get_raw_token(); if (t == EOF) return t; if (t != IDENTIFIER) return t; if (sval in _token) return _token[sval]; return t; } function unget_token(t, s) { _unget_sp++; _unget_token_stack [_unget_sp] = t; _unget_lexeme_stack[_unget_sp] = s; } function expect_identifier(id, t) { t = get_token(); if (t != IDENTIFIER || sval != id) { print "error 1 (" NR ") : expected " id ", found " s; exit; } } function expect_token(t, u) { u = get_token(); if (t != u) { print "error 2 (" NR ") : expected token " t " found " u; exit; } } function expect_literal() { if (get_token() != LITERAL) parse_error(111, "Expected LITERAL, found \"" sval "\""); } function get_integer( t) { t = get_token(); if (t != INTEGER) { print "error 3 (" NR ") : expected integer, found " sval; exit; } return sval; } function get_identifier( t) { t = get_token(); if (t != IDENTIFIER) { print "error 4 (" NR ") : expected identifier " s ", found " t; exit; } return sval; } ################################################################### ## ## ASN type functions ## function make_type(name, typeinfo, outputType) { if (!(name in _type)) { _type[name] = typeinfo _typeOutput[name] = outputType } ## else ## parse_error(103, "type " name " already exists"); } function resolve_type(name, t) { while (1) { t = _type[name] if (t == "") return name if (t !~ /^__/) return t name = t } } function dump_types( i) { print "types:" for (i in _type) print i } function dump_objects( i, len, oid) { print "objects:" len = sortobj(_symbolToOid) for (i = 0; i < len; i++) { oid = _symbolToOid[_sort[i]]; if (_oidToAccess[oid] != "na") { print oid " : " _sort[i] " " _oidToAccess[oid] } } } function make_object(oid, name, desc, access, syntax, size, type, idx) { if (oid in _oidToSymbol && _oidToSymbol[oid] != name) { _symbolToOid[name] = oid; return; } if (name == "") { parse_error(109, "Attempt to define " oid " with empty name") return; } if (name in _symbolToOid && oid != _symbolToOid[name]) { parse_error(110, "Attempt to redefine symbol " name); return; } _symbolToOid[name] = oid _oidToSymbol[oid] = name _oidToDesc[oid] = desc _oidToAccess[oid] = access _oidToSyntax[oid] = syntax _oidToType[oid] = type _oidToParent[oid] = get_parent_oid(oid) _oidToIndex[oid] = idx _oidToSize[oid] = size } ################################################################### ## ## parser functions ## function parse_enumeratedtype( text, t, pos, num, s) { text = ""; pos = 1; while (1) { t = get_token(); if (t == "}") return text else if (t == ",") ; else if (t == IDENTIFIER) { s = sval; expect_token("(") num = get_integer() expect_token(")") while (pos < num) { text = text "ILLEGAL " pos++; } text = text s " " pos++; } } } function parse_textual_convention( t, syntax, size) { while (syntax == "") { t = get_token(); if (t == STATUS) { if (get_token() != IDENTIFIER) ; } else if (t == DISPLAY_HINT) expect_literal(); else if (t == DESCRIPTION) expect_literal() else if (t == REFERENCE) expect_literal() else if (t == SYNTAX) { syntax = parse_type() size = _size } else parse_error(112, "expected TEXTUAL CONVENTION attribute, found \"" sval "\"") } return syntax; } function parse_type( s1, t2, t, size) { # get the first token of the type t = get_token(); def = ""; _size = 0 # INTEGER type if (t == INTEGERt) { t = get_token(); # check to see if it is an enumerated integer # if it is, create an internal type and return that as the type if (t == "{") { t = "__enum" _internalType; _internalType++; make_type(t, "E " parse_enumeratedtype(), ""); return t; } # check to see if it is has a min/max value if (t == "(") ignore_line(); # otherwise end of type else unget_token(t, sval); return "INTEGER"; } # SEQUENCE type if (t == SEQUENCE) { t = get_token(); # check if sequence of another type if (sval == "OF") { t = "__sequence" _internalType; _internalType++; make_type(t, "O " get_identifier(), ""); return t; } else if (t == "{") { s = ""; while (1) { t = get_token(); while (t == ",") t = get_token() if (t == "}" || t == EOF) break; if (s == "") s = sval else s = s " " sval parse_type() } t = "__sequence" _internalType; _internalType++; make_type(t, "S " s, ""); return t; } parse_error(104, "expected { or OF, found " _lexeme[t]); return ""; } if (t == OBJECT_TYPE) { return "OBJECT TYPE"; } if (t == TRAP_TYPE) { return "TRAP TYPE"; } if (t == OBJECT) { s1 = sval; t2 = get_token(); if (t2 == IDENTIFIERt) return "OBJECT ID"; unget_token(t2, sval); unget_token(t, s1); } if (t == OCTET) { s1 = sval; t2 = get_token(); if (t2 == STRING) { t = get_token(); if (t == "(") { expect_identifier("SIZE") expect_token("(") t = get_token() ##% while ((t != ")") && (t != EOF)) { if (t == INTEGER) _size = sval+0; t = get_token() ##% } expect_token(")") } else unget_token(t, sval) return "OCTET_STRING" } unget_token(t2, sval); unget_token(t, s1); } if (t == IDENTIFIER && (sval in _type)) { s1 = sval t = get_token(); if (t == "(") ignore_line(); else unget_token(t, sval); return s1; } if (t == TEXTUAL_CONVENTION) return parse_textual_convention(); return sval; } function parse_imports( t) { while (t != ";") t = get_token(); } function parse_block( t) { expect_token("{") t = get_token(); while (t != "}") { # print sval t = get_token(); } } function parse_index( t, str) { expect_token("{") while (1) { t = get_token(); if (t == EOF || t == "}") break; if (t != ",") str = str sval " " } return str } function parse_variables( s) { s = "" expect_token("{") while (1) { t = get_token() while (t == ",") t = get_token(); if (t == "}") break; if (s == "") s = sval else s = s " " sval } return s } # # parse_object_def # parse an object definition. This will result in the creation of an # entry in the OID tree # function parse_object_def(name, oid, type, access, syntax, desc, t, t2, s, i, y, z, str, fn, array, idx, size) { type = parse_type() access = "na" syntax = ""; desc = ""; while (1) { t = get_token(); if (t == ASSIGNMENT) break; if (t == SYNTAX) { syntax = parse_type() size = _size } else if (t == ACCESS) { t = get_token(); if (tolower(sval) == "read-only") access = "ro" else if (tolower(sval) == "read-write") access = "rw" else if (tolower(sval) == "not-accessible") access = "na" else parse_error(105, "expected ACCESS type, found \"" sval "\"") } else if (t == ENTERPRISE) { ignore_line(); } else if (t == STATUS) { if (get_token() != IDENTIFIER) ; } else if (t == DEFVAL) { ignore_line(); } else if (t == INDEX) { idx = parse_index(); } else if (t == REFERENCE) { expect_literal() } else if (t == VARIABLES) { variables[n] = parse_variables() } else if (t == DESCRIPTION) { expect_literal() desc = sval } else parse_error(106, "expected object attribute, found \"" sval "\"") } t = get_token() if (t == INTEGER) oid = sval+0; else if (t == "{") { oid = ""; while (1) { t = get_token() if (t == "}") break; if (t == INTEGER) { if (oid == "") oid = sval + 0; else oid = oid "." sval+0; } else if (t == IDENTIFIER) { s1 = sval t2 = get_token() if (t2 == "(") { z = get_integer(); expect_token(")") if (oid == "") oid = z else oid = oid "." z make_object(oid, s1, "", "na", "", 0, "", "") } else { unget_token(t2, sval) if (s1 in _symbolToOid) z = _symbolToOid[s1] else { parse_error(107, "symbol " s1 " used but not defined") z = 0; } if (oid == "") oid = z else oid = oid "." z } } else break; } } else { parse_error(108, "expected object identifer, found \"" sval "\"") return; } make_object(oid, name, desc, access, syntax, size, type, idx) return; } # # parse a type assignment of the form # newtype ::= oldtype # function parse_type_assign(newtype, oldtype) { oldtype = parse_type() # make sure the "old" type actually exists if (!(oldtype in _type)) { parse_error(102, "type " oldtype " does not exist") return; } # assign the information from the old type to the new type make_type(newtype, _type[oldtype], _typeOutput[oldtype]); } # # parse a DEFINITION block # function parse_definition( t, t2, t3, s) { t = get_token(); if (t == EOF) return EOF; if (t != IDENTIFIER) { parse_error(100, "expected IDENTIFIER, found " _lexeme[t] " \"" sval "\"") return EOF; } _defname = sval; expect_token(DEFINITIONS); expect_token(ASSIGNMENT); expect_token(BEGINt); fileList = FILELIST; print "Parsing " _defname "..."; t = get_token(); while (t != ENDt) { if (t == IMPORTS) parse_imports(); else if (t == IDENTIFIER) { s = sval; t2 = get_token(); if (t2 == ASSIGNMENT) parse_type_assign(s); else { unget_token(t2, sval); parse_object_def(s); } } else { parse_error(101, "expected IDENTIFIER, found \"" sval "\"") ignore_line(); } t = get_token(); } return 1; } ################################################################### ## ## initialisation functions ## function init_globals( i, symbol, t) { # globals _force8dot3 = 0; _text = ""; _unget_sp = 0; _internalType = 1; if (_force8dot3) _fileext = ".htm" else _fileext = ".html"; # token definitions EOF = -1; i = 256; IDENTIFIER = i++; LITERAL = i++; ASSIGNMENT = i++; INTEGER = i++; IMPORTS = i++; _token["IMPORTS"] = IMPORTS; ENDt = i++; _token["END"] = ENDt; BEGINt = i++; _token["BEGIN"] = BEGINt; OBJECT = i++; _token["OBJECT"] = OBJECT; IDENTIFIERt = i++; _token["IDENTIFIER"] = IDENTIFIERt; OBJECT_TYPE = i++; _token["OBJECT-TYPE"] = OBJECT_TYPE SEQUENCE = i++; _token["SEQUENCE"] = SEQUENCE; SYNTAX = i++; _token["SYNTAX"] = SYNTAX; ACCESS = i++; _token["ACCESS"] = ACCESS; _token["MAX-ACCESS"] = ACCESS; STATUS = i++; _token["STATUS"] = STATUS; DEFVAL = i++; _token["DEFVAL"] = DEFVAL DESCRIPTION = i++; _token["DESCRIPTION"] = DESCRIPTION; VARIABLES = i++; _token["VARIABLES"] = VARIABLES; INDEX = i++; _token["INDEX"] = INDEX; INTEGERt = i++; _token["INTEGER"] = INTEGERt; OCTET = i++; _token["OCTET"] = OCTET; STRING = i++; _token["STRING"] = STRING; REFERENCE = i++; _token["REFERENCE"] = REFERENCE; TRAP_TYPE = i++; _token["TRAP-TYPE"] = TRAP_TYPE; ENTERPRISE = i++; _token["ENTERPRISE"] = ENTERPRISE; DEFINITIONS = i++; _token["DEFINITIONS"] = DEFINITIONS; TEXTUAL_CONVENTION = i++; _token["TEXTUAL-CONVENTION"] = TEXTUAL_CONVENTION; DISPLAY_HINT = i++; _token["DISPLAY_HINT"] = DISPLAY_HINT; OCTECTSTRING = i++; OBJECTID = i++; # lexeme lookup table for (i in _token) _lexeme[_token[i]] = i; _lexeme[IDENTIFIER] = "IDENTIFIER"; _lexeme[LITERAL] = "LITERAL"; _lexeme[ASSIGNMENT] = "ASSIGNMENT"; _lexeme[INTEGER] = "INTEGER"; # RFC 1155 symbols _symbolToOid["iso"] = "1"; _symbolToOid["org"] = "1.3"; _symbolToOid["dod"] = "1.3.6"; _symbolToOid["internet"] = "1.3.6.1"; _symbolToOid["directory"] = _symbolToOid["internet"] ".1"; _symbolToOid["mgmt"] = _symbolToOid["internet"] ".2"; _symbolToOid["experimental"] = _symbolToOid["internet"] ".3"; _symbolToOid["private"] = _symbolToOid["internet"] ".4"; _symbolToOid["mib"] = _symbolToOid["mgmt"] ".1" _symbolToOid["mib-2"] = _symbolToOid["mgmt"] ".1" _symbolToOid["system"] = _symbolToOid["mib-2"] ".1" _symbolToOid["interfaces"] = _symbolToOid["mib-2"] ".2" _symbolToOid["at"] = _symbolToOid["mib-2"] ".3" _symbolToOid["ip"] = _symbolToOid["mib-2"] ".4" _symbolToOid["icmp"] = _symbolToOid["mib-2"] ".5" _symbolToOid["tcp"] = _symbolToOid["mib-2"] ".6" _symbolToOid["udp"] = _symbolToOid["mib-2"] ".7" _symbolToOid["egp"] = _symbolToOid["mib-2"] ".8" _symbolToOid["cmot"] = _symbolToOid["mib-2"] ".9" _symbolToOid["transmission"] = _symbolToOid["mib-2"] ".10" _symbolToOid["snmp"] = _symbolToOid["mib-2"] ".11" _symbolToOid["enterprises"] = _symbolToOid["private"] ".1" for (symbol in _symbolToOid) { _oidToSymbol[_symbolToOid[symbol]] = symbol _oidToAccess[_symbolToOid[symbol]] = "na"; } # types make_type("TRAP TYPE", "", ""); make_type("INTEGER", "", ""); make_type("OCTET_STRING", "", ""); make_type("DisplayString", "", ""); make_type("Counter", "", ""); make_type("TimeTicks", "", ""); make_type("Gauge", "", ""); make_type("PhysAddress", "", "hex"); make_type("IpAddress", "", ""); make_type("NetworkAddress", "", ""); make_type("DateAndTime", "", "dateandtime"); make_type("OBJECT ID", "", ""); # index lengths _typeToIndexLen["INTEGER"] = 1; _typeToIndexLen["IpAddress"] = 4; _typeToIndexLen["NetworkAddress"] = 4; } ################################################################### ## ## Code generation routines ## function get_change_page(oid, value, len, array, ofile, type, fn, i, text, typecode) { type = _oidToSyntax[oid] if (type in _typeToChangePage) return _typeToChangePage[type] if ((type !~ /^__enum/) && (type !~ /DateAndTime/)) return "/change.html" if (type ~ /^__enum/) { text = "" len = split(value, array) if (len < 2 || array[1] !~ "array") return "/change.html" for (i = 2; i <= len; i++) { if (((i-1) % 6) == 1) text = text "" text = text "
" array[i] "" } typecode = "" } else { text = "\">" typecode = "date" } ofile = _dir "change" type ".html" _typeToChangePage[type] = "../" ofile print "Change MIB Entry <!--#snmp oid-->" > ofile print "" > ofile print "

Change MIB Entry

" >> ofile print "
" >> ofile print "" >> ofile print "
Host:" >> ofile print "
Set Community:" >> ofile print "
OID:" >> ofile print "
Type:" >> ofile print "
Value:" >> ofile print "
New value:" >> ofile print text >> ofile print "


" >> ofile print "\">" >> ofile print "\">" >> ofile print "\">" >> ofile print "\">" >> ofile print "\">" >> ofile print "" >> ofile print "" >> ofile print "" >> ofile print "

" _oidToSymbol[oid] "

" >> ofile print _oidToDesc[oid] >> ofile print "" >> ofile return "../" ofile } function output_hdr_only(n) { print "" n " for <!--#snmp host-->" > _outfile print "" >> _outfile print "

" n n2 "

" >> _outfile } function output_hdr(n, s) { output_hdr_only(n) print "" >> _outfile } function output_trailer(desc) { print "
OIDNameType" s >> _outfile } function output_page_table_hdr(n, root) { output_hdr(n, "") print "" >> _outfile print "Row " >> _outfile print "" >> _outfile print "

" >> _outfile print "


" >> _outfile print desc >> _outfile print "" >> _outfile close(_outfile); } function get_printable_type(oid, type) { type = _oidToSyntax[oid] if (type ~ /__enum/) type = "INTEGER" return type } # # format 0 = normal oids # format 1 = row table oids # format 2 = vertical page table oids # format 3 = horizontal page table oids # function output_entry(format, prefix, oid, idx) { _output_entry(format, prefix, oid, idx, "smartvalue") } function output_enum(format, prefix, oid, idx, enumtext) { _output_entry(format, prefix, oid, idx, "array " enumtext) } function _output_entry(format, prefix, oid, idx, text, name, access, type) { name = _oidToSymbol[oid] access = _oidToAccess[oid] type = get_printable_type(oid) if (format < 2) { if (format == 0) { printf ("%s", "") >> _outfile printf ("%s", "" prefix ".0") >> _outfile } else { printf ("%s", "") >> _outfile printf ("%s", "" prefix ".") >> _outfile } printf ("%s", "" name "") >> _outfile printf ("%s", "" type) >> _outfile } else if (format == 2) { printf ("%s", "" prefix) >> _outfile printf ("%s", "" name "") >> _outfile printf ("%s", "" type) >> _outfile printf ("%s", "") >> _outfile printf ("%s", "") >> _outfile } else if (format == 3) printf ("%s", "") >> _outfile printf ("%s", "") >> _outfile if (access == "rw") printf ("%s","&oid=\">") >> _outfile printf ("%s", "") >> _outfile if (access == "rw") printf ("%s", "") >> _outfile printf ("%s", "") >> _outfile if (format == 2) printf ("%s", "") >> _outfile if (format != 3) printf ("%s", "") >> _outfile print "" >> _outfile } function make_description(name, text, str) { str = "\n" str = str "

" name "

\n" str = str text "\n" str = str "
\n" return str; } function output_row_table_ref(second, root, prefix, name, fn, idx, dir, refdir, indexLen, labelOid, i, label, titleopt) { # find a string in the table definition to use as an index i = 1; label = 0 while (label == 0) { labelOid = root "." i if (!(labelOid in _oidToSymbol)) break; if (_oidToSyntax[labelOid] == "DisplayString") { label = i; } i++; } # now output the ref if (second) print "
" >> _outfile else { print "" >> _outfile print "" prefix >> _outfile print "
" name "" >> _outfile print "Table" >> _outfile print "" >> _outfile } print "" >> _outfile printf "&" >> _outfile printf "root=" root "&" >> _outfile printf "num=" >> _outfile print "\">Row " >> _outfile if (name in _tableOptionsRowTable) titleopt = _tableOptionsTableTitle[name] else titleopt = _tabletitle if (titleopt && (label != 0)) print " - " >> _outfile print "
" >> _outfile } function output_page_table_ref(trailing, root, prefix, name, fn, idx, dir, refdir, indexLen) { # now output the ref print "" >> _outfile print "" prefix >> _outfile print "" name "" >> _outfile print "Table" >> _outfile printf "&" >> _outfile printf "root=" root "&" >> _outfile print "\">All rows" >> _outfile if (!trailing) print "" >> _outfile } function symbol_to_indexlen(t, f, s, l) { l = 0; if (resolve_type(t) ~ /^E /) l = 1; else if (t ~ /^OCTET_STRING/) { l = _oidToSize[_symbolToOid[array[i]]]; if (l == 0) { if (f) { gen_warning(103, "Unbounded OCTET STRING used as row index for " s) l =1; } } else if (!(t in _typeToIndexLen)) { if (f) { gen_warning(103, "Unexpected type " t " used as row index for " s) indexLen = 1 } } else indexLen += (_typeToIndexLen[t]+0) } return l } function output_sequence(prefix, oid, idx, dir, refdir, type, indent, sfn, soutfile, rowOid, array, len, indexLen, l, t, pageopt, rowopt) { name = _oidToSymbol[oid] sfn = make_filename(name) if (name in _tableOptionsRowTable) { rowopt = _tableOptionsRowTable [name] pageopt = _tableOptionsPageTable [name] } else { rowopt = _rowtable pageopt = _pagetable } rowOid = oid ".1" if (!(rowOid in _oidToSymbol)) gen_error(101, "Row oid " rowOid " not found") else { if (_oidToIndex[rowOid] == "") indexLen = 1 else { len = split(_oidToIndex[rowOid], array, " ") indexLen = 0; for (i = 1; i <= len; i++) { l = symbol_to_indexlen(array[i], 0, _oidToSymbol[rowOid]) if (l == 0) l = symbol_to_indexlen(_oidToSyntax[_symbolToOid[array[i]]], 1, _oidToSymbol[rowOid]) indexLen += l } } if (pageopt != "n") { output_page_table_ref(rowopt, oid ".1", prefix, name, "page-" sfn, idx, dir, refdir, indexLen) soutfile = _outfile _outfile = dir "page-" sfn if (pageopt == "h") { output_h_page_table(name, oid ".1", dir, "", indent+2, "") } else { output_v_page_table(name, oid ".1", dir, "", indent+2, "") } _outfile = soutfile } if (rowopt) { output_row_table_ref(pageopt != "n", oid ".1", prefix, name, sfn, idx, dir, refdir, indexLen) soutfile = _outfile _outfile = dir sfn output_row_tree(name, oid ".1", dir, "", indent+2, "") _outfile = soutfile } } } function output_row_tree(prefix, root, dir, refdir, indent, hdr) { output_tree(1, prefix, root, dir, refdir, indent, hdr) } function output_v_page_table(prefix, root, dir, refdir, indent, hdr) { output_tree(2, prefix, root, dir, refdir, indent, hdr) } function output_tree(format, prefix, root, dir, refdir, indent, hdr, i, symbol, suffix, list, len, suffixes, suffix_i, oid, t, s, desc, t2) { symbol = prefix # # collect a list of oids who have the tree root as their parent # i = 0 for (oid in _oidToSymbol) { if (_oidToParent[oid] == root) { suffix = substr(oid, length(root)+2) list[i] = suffix; i++; } } # # sort the list of children into a suffix array # len = sortobj(list) for (i = 0; i < len; i++) suffixes[i] = list[_sort[i]] # # output the header # if (format == 0) output_hdr(prefix " - " root, "Value") else if (format == 1) output_hdr("Table " prefix " - " root ", Row ", "Value") else if (format == 2) output_page_table_hdr("Table " prefix " - " root, root) # # output each child # for (i = 0; i < len; i++) { suffix_i = suffixes[i] oid = root "." suffix_i t = _oidToType[oid] s = _oidToSyntax[oid] desc = desc make_description(_oidToSymbol[oid], _oidToDesc[oid]) prefix = symbol "." suffix_i if (t == "OBJECT ID") { create_file(format, prefix, oid, dir, refdir, indent, oid, "") } else { if (t == "OBJECT TYPE") { t2 = resolve_type(s) if (s ~ /^__sequence/) output_sequence(prefix, oid, suffix_i, dir, refdir, _type[s], indent) else if (t2 ~ /^E /) { gsub(/^E /, "", t2) output_enum(format, prefix, oid, suffix_i, t2) } else { t = _typeOutput[s] if (t == "") _output_entry(format, prefix, oid, suffix_i, "smartvalue") else _output_entry(format, prefix, oid, suffix_i, t) } } } } # # output the trailer # output_trailer(desc) } function create_file(format, prefix, oid, dir, refdir, indent, root, addroot, fn, soutfile) { symbol = _oidToSymbol[oid] fn = make_filename(symbol) print "" >> _outfile print "" prefix >> _outfile printf "> _outfile printf "?" >> _outfile if (root != "") printf "&root=" root >> _outfile else printf "&root=" >> _outfile printf "\">" >> _outfile print symbol "" >> _outfile print "" >> _outfile soutfile = _outfile _outfile = dir fn output_tree(0, symbol, oid, dir, "", indent+2, addroot) _outfile = soutfile } function output_h_page_table(prefix, root, dir, refdir, indent, hdr, i, hasObjectType, oid, suffix, list, t, len, suffixes, t2, desc, array, l, u, sfn, soutfile, s, s2, s3, symbol) { symbol = prefix # # collect a list of oids who have the tree root as their parent # i = 0 for (oid in _oidToSymbol) { if (_oidToParent[oid] == root) { suffix = substr(oid, length(root)+2) list[i] = suffix; i++; } } # # sort the list of children into a suffix array # len = sortobj(list) for (i = 0; i < len; i++) suffixes[i] = list[_sort[i]] # # output the header # output_hdr_only("Table " prefix " - " root) print "" >> _outfile; # # output the column names # print "" >> _outfile # # output the column types # print "" >> _outfile # # output the rows # print "" >> _outfile print "" >> _outfile print "" >> _outfile # # output the trailer # output_trailer(desc) } function output_defns( i, len, oid, defs, poid, roots, nroots, a, j, c, p, dir, symbol, fn, prefix) { # # make a pass through the list of object definitions and extract # all of the accessible objects and sequences. Then sort them by oid # printf ("Extracting definitions..."); c = 0; for (i in _symbolToOid) { oid = _symbolToOid[i]; if (_oidToAccess[oid] != "na" || _oidToSyntax[oid] ~ /^__sequence/) { defs[i] = oid; c++; } } print c " found. done" printf ("Sorting definitions...") len = sortobj(defs) print "done" # # Find the common ancestors of all of the definied oids, and then # sort them by oid. # This relies on the fact that the oids are sorted, i.e. the # parent of an oid will always be added before a child # printf "Finding root oids..." for (i = 0; i < len; i++) { oid = _symbolToOid[_sort[i]]; poid = _oidToParent[oid] if (!(poid in roots)) { a = 1 for (j in roots) { c = relate_oid(j, poid) if (c == 1) a = 0 } if (a) roots[poid] = 1; } } for (i in roots) { oid = i; nroots[_oidToSymbol[i]] = oid; } len = sortobj(nroots) print len " found. done" for (i = 0; i < len; i++) sroots[i] = nroots[_sort[i]] # # output the definitions # fn = tolower(_defname); if (_force8dot3) { p = index(fn, "-"); if (p > 0) fn = substr(fn, 1, p-1); fn = substr(fn, 1, 8); } _outfile = make_filename(fn); dir = tolower(_defname); if (_force8dot3) { p = index(dir, "-"); if (p > 0) dir = substr(dir, 1, p-1); dir = substr(dir, 1, 8); } system("mkdir " dir) dir = dir "/"; refdir = dir; _dir = dir # # if there is only only one root node, only output that file # print "Creating top level HTML file " _outfile if (len == 1) { output_tree(0, _oidToSymbol[oid], oid, dir, refdir, 2, "") } else { output_hdr(_defname, "") for (i = 0; i < len; i++) { print_indent(2) symbol = _oidToSymbol[sroots[i]] print symbol " : " sroots[i] # find the parent oid and it's symbol poid = _oidToParent[sroots[i]] if (poid in _oidToSymbol) { prefix = sroots[i] gsub (poid, "", prefix) prefix = _oidToSymbol[poid] prefix } else prefix = sroots[i] create_file(0, prefix, sroots[i], dir, refdir, 2, sroots[i], "") } output_trailer("") } close(_outfile) } ################################################################### ## ## main ## function read_table_options(fn, line, n, fields, num) { num = 0 while (1) { stat = getline line < fn; if (stat <= 0) break num++; if (line !~ /^[ \t]*#/ && line !~ /^[ \t]*$/) { n = split(line, fields) if (line < 4) print fn "(" num ") : must have four fields" else { if (fields[1] == "DEFAULT") { print "Setting default table options" _tabletitle = fields[2] == "y" _rowtable = fields[3] == "y" _pagetable = fields[4] } else { print "Setting table options for " fields[1] _tableOptionsTableTitle[fields[1]] = fields[2] == "y" _tableOptionsRowTable [fields[1]] = fields[3] == "y" _tableOptionsPageTable [fields[1]] = fields[4] } } } } } function main( t) { _rowtable = "y" _tabletitle = "y" _pagetable = "h" if (tableopts == "") read_table_options("tableopt") else read_table_options(tableopts) init_globals(); parse_definition() ##dump_types(); ##dump_objects(); output_defns(); } BEGIN { main() }
Name" >> _outfile; for (i = 0; i < len; i++) { suffix_i = suffixes[i] oid = root "." suffix_i name = _oidToSymbol[oid] print "" name >> _outfile desc = desc make_description(_oidToSymbol[oid], _oidToDesc[oid]) } print "
Type" >> _outfile; for (i = 0; i < len; i++) { suffix_i = suffixes[i] oid = root "." suffix_i s = get_printable_type(oid) print "" s >> _outfile } print "
Row " >> _outfile for (i = 0; i < len; i++) { suffix_i = suffixes[i] oid = root "." suffix_i t = _oidToType[oid] s = _oidToSyntax[oid] if (t == "OBJECT ID") { gen_error(102, "found nested table whilst expanding table") } else { if (t == "OBJECT TYPE") { t2 = resolve_type(s) if (s ~ /^__sequence/) gen_error(102, "found nested table whilst expanding table") else if (t2 ~ /^E /) { gsub(/^E /, "", t2) output_enum(3, prefix, oid, suffix_i, t2) } else { t = _typeOutput[s] if (t == "") _output_entry(3, prefix, oid, suffix_i, "smartvalue") else _output_entry(3, prefix, oid, suffix_i, t) } } } } print "