#!./tclnm

set tmpn "/tmp/t.[id process]"
set tmp [dbm open $tmpn wct]
set mib [dbm open "mib" wct]
set tf [open mib.str w+]

proc ARGH args {
    puts stdout "\nARGHHH: <$args>"
    flush stdout
    panic_now
    }

proc write_string str {
    global tf
    set pos "[tell $tf] [string length $str]"
    puts $tf "$str\001" 
    return "{$pos}"
    }

proc read_string {arg} {
    global tf
    if {[llength $arg] == 0} { return "" }
    seek $tf [lindex $arg 0]
    return [read $tf [lindex $arg 1]]
    }

set MOD ""
proc -- {args} { puts stdout "# $args" }
proc y {args} {}
proc o {args} {}
proc 1 {args} {}
proc x {args} { global tmp ; dbm store $tmp "X [lindex $args 0]" "$args" }
proc s {args} {}
proc i {args} {}
proc t {args} {}
proc r {args} {}
proc p {args} {}

proc m {mib args} {
    global MOD
    set MOD $mib
    puts stdout "MODULE::$mib" 
    }

proc b {tag a1 a2 args} { 
    global MOD tmp
    #set pos [write_string "$args"]
    #tmp store "m $MOD::$tag" $pos

    set i 0
    case $a2 in {
	d { set desc [write_string [lindex $args $i]] ; incr i 
	    set ref "{}" }
	b { set desc [write_string [lindex $args $i]] ; incr i 
	    set ref [write_string [lindex $args $i]] ; incr i }
	n { set desc "{}" 
	    set ref "{}" }
	default { ARGHH $a2 $tag }
	}
    dbm store $tmp "m $MOD::$tag" "$a1 $desc $ref [lrange $args $i end]"
    }

proc z {cnt} {
    global f x tmp mib
    set y 0
    while {1} {
	set t1 [lindex $x 0]
	set m1 [lindex $x 1]
	set v  [lindex $x 2]
	set t2 [lindex $x 3]
	set m2 [lindex $x 4]
	if { "$t2::$m2" == "_::_" } {
	    set v ".$v"
	    set o ".$t1"
	    set vt2 _
	} else {
	    dbm fetch $tmp "v $m2::$t2" vt2
	    dbm fetch $tmp "o $m2::$t2" ot2
	    set v "$vt2.$v"
	    set o "$ot2.$t1"
	}
	dbm store $mib "o $vt2 $t1" "$v"
	dbm store $tmp "v $m1::$t1" "$v"
	dbm store $tmp "o $m1::$t1" "$o"
	set stat ""
	set ref ""
	set desc ""
	set access ""
	set defval ""
	set symb ""
	set type ""
	set targ ""
	if {[dbm fetch $tmp "m $m1::$t1" w]} {
	    set stat [lindex $w 0]
	    set desc [lindex $w 1]
	    set ref [lindex $w 2]
	    set access [lindex $w 3]
	    set idx 4
	    while {[lindex $w $idx] == "x"} {
		incr idx
		set sym [lindex $w $idx]
		append symb $sym
		incr idx
		set z [lrange $w $idx end]
		if {[lindex $w $idx] == "n"} {
		    incr idx
		    set z [lrange $w $idx end]
		    set w [lrange [dbm fetch $tmp "X $sym"] 3 end ]
		} else {
		    set z [lrange $w $idx end]
		    set w [lindex [dbm fetch $tmp "X $sym"] 3 ]
		}
		append w " " $z
		set idx 0
	    }
	    case [lindex $w $idx] in {
		e { 
		incr idx
		set n [lindex $w $idx]
		incr idx
		set type "Enum"
		set i [expr $n*2+$idx-1]
		set targ "$n [lrange $w $idx $i]"
		for {set i 0} {$i < $n} {incr i} { incr idx 2 }
		}
		o {
		    set type "OctetString"
		    incr idx
		    case [lindex $w $idx] in {
			n { incr idx }
			f { incr idx
			    set targ "[lindex $w $idx]"
			    append targ " " $targ
			    incr idx }
			v { incr idx
			    set targ "[lindex $w $idx]"
			    incr idx
			    append targ " " "[lindex $w $idx]"
			    incr idx }
			default {ARGH $w}
			}
		}
		i { 
		    set type "Integer"
		    incr idx
		    case [lindex $w $idx] in {
			n { incr idx } 
			p { incr idx
			    set targ "[lindex $w $idx]"
			    incr idx
			    append targ " " "[lindex $w $idx]"
			    incr idx }
			z { incr idx
			    set targ "-[lindex $w $idx]"
			    incr idx
			    append targ " " "[lindex $w $idx]"
			    incr idx }
			default {ARGH $w}
			}
		}
		p { incr idx ; if {[lindex $w $idx] != "n"} { ARGH $w }
		    set type "IpAddress" ; incr idx }
		n { incr idx ; if {[lindex $w $idx] != "n"} { ARGH $w }
		    set type "NetworkAddress" ; incr idx }
		g { incr idx ; if {[lindex $w $idx] != "n"} { ARGH $w }
		    set type "Gauge" ; incr idx }
		d { incr idx ; if {[lindex $w $idx] != "n"} { ARGH $w }
		    set type "OID" ; incr idx }
		t { incr idx ; if {[lindex $w $idx] != "n"} { ARGH $w }
		    set type "TimeTicks" ; incr idx }
		c { incr idx ; if {[lindex $w $idx] != "n"} { ARGH $w }
		    set type "Counter" ; incr idx }
		default { ARGH $w }
	    }
	    if {[lrange $w $idx end] != "u 0"} {
		set i [llength $w]
		incr i -2
		set defval [lrange $w $idx $i]]
	    }


	}
	dbm store $mib "n $v" \
	    "{$o} {$type} {$targ} {$symb} {$stat} {$access} {$desc} {$ref} {$defval} {$m1}"
	incr y
	if {[gets $f x] == -1} { break }
	}
    puts stdout "done $y $cnt" 
    dbm close $mib
    dbm close $tmp
    exit 
    }

#
#
#
set fn ""
set fs 0
foreach i $argv {
	set s [file size $i]
	if {$s > $fs} {
	    set fn $i
	    set fs $s
	}
}
puts stdout "loading $fn ($fs bytes)"
set f [open $fn r]
if {[gets $f x] == -1} { exit }
while { 1 } {
	set t "$x"
	if {[gets $f x] == -1} { exit }
	while { [regexp {^[^"]*("[^"]*)("[^"]*"[^"]*)*$} $t] } {
	    append t "\n" "$x"
	    if {[gets $f x] == -1} { exit }
	} 
	while {[regexp {^[ 	].*$} $x]} {
	    append t "$x"
	    if {[gets $f x] == -1} { exit }
	}
	if {[regsub -all {([^"]*)"([^"]*)"([^"]*)} "$t" {\1{\2}\3} s]} {
		set t "$s"
	}
	eval $t
	}
close $f
dbm close $tmp
dbm close $mib
system "rm -f ${tmpn}*"
