#!/usr/bin/perl -P
#
# MibMerge [file]...
#
# This program reads in lists of MIB variables in various formats, and
# produces a summary of what is found.  The output format is:
#   oid varName -- comments
# where the oid may be omitted.  The comments are expected to be a date
# (yymmdd) followed by one or more words; the earliest and latest dates
# are noted and the words for those dates are saved.
#
# The order of output is the order in which the variables are first seen.
# Thus, if the input starts off with a MIB in some order (e.g., that in
# the "mibtbl" file", that will determine the order of output.

#include "dbg.pl"

$oid = '[\d.]+';
$var = '[a-z][a-z][a-zA-Z0-9_-]+';

line:
for $l (<>) {
	chop $l;
	++$Line;
	if ($l =~ /^($oid)\s+($var)\s*$/) {
		D "Matched oid $1 var $2 " D2;
		$o = $1;
		$v = $2;
		&varline($v);
		if ($o =~ /^\d/) {	# Is it really an oid?
			$O{$v} = $o;	# Maps var to oid.
			$V{$o} = $v;	# Maps oid to var.
		}
		next line;
	}
	if ($l =~ /^($oid)\s+($var)\s+--(.*)$/) {
		D "Matched oid $1 var $2 " D2;
		$o = $1;
		$v = $2;
		$c = $3;
		&varline($v);
		if ($o =~ /^\d/) {	# Is it really an oid?
			$O{$v} = $o;	# Maps var to oid.
			$V{$o} = $v;	# Maps oid to var.
		}
		&comment($v,$c);
		next line;
	}
	if ($l =~ /^([-+| ])\s+($var)\s*--\s*(.*)/) {	# Variable -- comment.
		$o = $1;
		$v = $2;
		$c = $3;
		D "Matched var $v com $c" D2;
		$O{$v} = $o if !$O{$v};
		&varline($v);
		&comment($v,$c);
		next line;
	}
	if ($l =~ /^\s*($var)\s*/) {	# Variable at start of line.
		D "Matched var $1" D2;
		&varline($1);
		next line;
	}
	D "Comment: $l" D3;
	push(@L,$l);
}

# Run thru the list of lines, producing a line of output for each.  For
# variables, we generate a summary line; for non-variables, we just put
# out the line as is.
for $v (@L) {
	next if $done{$v};
	if ($vars{$v}) {	# Is the list item a variable name?
		$o = $O{$v} || "-";
		print "$o $v\t--";
		$dl = $dlo{$v}; $cl = &scrunch($clo{$v});
		$dh = $dhi{$v}; $ch = &scrunch($chi{$v});
		print " $dl $cl" if ($dl || $cl);
		print " $dh $ch" if ($dh || $ch) && ($dh != $dl);
		$done{$v} = 1;
	} else {
		print $v;
	}
		print "\n";
}
exit 0;

# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
# Parse a comment field.  We look for dates, and when one is  found  that  is #
# outside  the  current range [$lo,$hi], we note it and add its comment words #
# to the appropriate %clo or %chi string.                                     #
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
sub comment {
	local($v,$c) = @_;
	local(@c,$d,$lo,$mi,$hi,$w);

	@c = split(/\s/,$c);
	for $w (@c) {		# Run thru the comment word at a time.
		if ($w =~ /^9/) {	# Initial date?
			D "Date: \"$w\"" D2;
			$lo = $mi = $hi = 0;	# Is it low, middle or high?
			if (!($d = $dlo{$v}) || ($w <= $d)) {
				$lo = 1;	# It's the lowest date seen so far.
				$dlo{$v} = $w;
				$clo{$v} = '';
				D "lo $v $dlo{$v} $clo{$v}" D2;
			} elsif (!($d = $dhi{$v}) || ($w >= $d)) {
				$hi = 1;	# It's the highest data seen so far.
				$dhi{$v} = $w;
				$chi{$v} = '';
				D "hi $v $dhi{$v} $chi{$v}" D2;
			} else {
				$mi = 1;	# It's between the hi and lo dates.
				D "Ignoring date $w" D2;
			}
		} else {
			D "Word: \"$w\"" D2;
			if ($lo) {
				$clo{$v} .= " $w";
				D "lo $v $dlo{$v} $clo{$v}" D2;
			} elsif ($hi) {
				$chi{$v} .= " $w";
				D "hi $v $dhi{$v} $chi{$v}" D2;
			} elsif ($mi) {
				D "mi $v $dhi{$v} $chi{$v}" D2;
			} else {
				$clo{$v} .= " $w";
				D "LO $v $dlo{$v} $clo{$v}" D2;
			}
		}
	}
}

# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
# Strip away initial and trailing white  space,  and  reduce  internal  white #
# stuff to a single space.                                                    #
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
sub scrunch {
	local($s) = @_;
	$s =~ s/^\s+//;
	$s =~ s/\s+$//;
	$s =~ s/\s+/ /g;
	$s;
}

# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
# Add a variable to the %vars table, and if this is the first instance,  note #
# in @L where it was first seen.                                              #
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
sub varline {
	local($v) = @_;
	push(@L,$v)	# Add to list of variables.
		if (!$vars{$v}++);	# Count the times the variable is seen.
}
