#!/usr/bin/python
#
# Pybble
#
# 	Parse a mibble output file into something more parseable.
#
#       Usage: MibblePrinter.sh [mib file] | pybble.py -a [aux file]  -o [output file]
#	This will produce a [output].java and [output].dat files containing
#	the constant declarations and data files respectively.
#
#
# Tom Coppeto
# OnTapSolutions
# 11 September 2005
#
# CVS $Id: pybble.py,v 1.2 2005/09/28 19:19:42 tom Exp $
#

import getopt
import sys
import time


def gettime():
	return time.ctime()


def nameFrotz(name, append):
	sz = len(name)
	i = 0
	while i < sz:
		c = name[i]
		if c.isupper():
			break
		i = i + 1

	prefix = name[:i]
	suffix = name[i:]
	ret = prefix.upper() + "_" + suffix.upper() + "_" + append
	return ret


def nameToVar(name):
	return nameFrotz(name, "PROPERTY")


def nameToValue(name):
	return nameFrotz(name, "VALUE")


def parseDesc(line):
	ret = ""
	words = line.split()
	for word in words:
		if word == "Description:":
			continue
		if word == ")":
			continue
		if ret != "":
			ret = ret + " " 
		ret = ret + word
	return ret


def parseMibObject(name, input):

	descFlag = 0
	units  = ""

	for line in input:
		tokens = line.split()

		if tokens[0] == "Access:":
			if tokens[1] == "not-accessible":
				return
			access = tokens[1]
			continue

		if tokens[0] == "Units:":
			units = tokens[1]
			continue

		if tokens[0] == "Syntax:":
			if tokens[2] == "1]":
				type = "Boolean"
			if tokens[2] == "2]":
				type = "Integer"
			if tokens[2] == "4]":
				type = "String"
			if tokens[2] == "6]":
				type = "OID"
			continue
		
		if tokens[0] == "Description:":
			desc     = parseDesc(line)
			descFlag = 1
			continue

		if tokens[0] == "::=":
			oid = tokens[1]
			break

		if tokens[0] == ")":
			descFlag = 0
			continue

		if descFlag == 1:
			token = tokens[0]
			if token[len(token)-1] == ":":
				print token
				descFlag = 0
				continue
			desc = desc + " " + parseDesc(line)

	object = [oid, name, type, access, units, desc]
	return object


def parseMibIdentObject(name, input):

	descFlag = 0

	for line in input:
		tokens = line.split()

		if tokens[0] == "Description:":
			desc     = parseDesc(line)
			descFlag = 1
			continue

		if tokens[0] == "::=":
			oid = tokens[1]
			break

		if tokens[0] == ")":
			descFlag = 0
			continue

		if descFlag == 1:
			token = tokens[0]
			if token[len(token)-1] == ":":
				print token
				descFlag = 0
				continue
			desc = desc + " " + parseDesc(line)

	object = [oid, name, desc]
	return object


def parseAuxObject(line):

	tokens = line.split(":")
	if len(tokens) != 4:
		return

	return tokens
	

def read_mib():
	mibReg = []
	mibIdentReg = []

	for line in sys.stdin:
		decl = line.split()
		if len(decl) != 4:
			continue
	
		if decl[0] == "VALUE" and decl[2] == "OBJECT-TYPE":
			object = parseMibObject(decl[1], sys.stdin)
			if object is not None:
				mibReg.append(object)

		if decl[0] == "VALUE" and decl[2] == "OBJECT-IDENTITY":
			object = parseMibIdentObject(decl[1], sys.stdin)
			if object is not None:
				mibIdentReg.append(object)
	
	return mibReg, mibIdentReg


def write_vars (outputPrefix, mibReg, mibIdentReg):
	file = open(outputPrefix + ".java", "w")
	file.write("\n    /*\n     * MIB constants\n     * generated at " + gettime() + " by pybble\n     */\n\n")

	file.write("    // identity (value) objects\n")
	index = 0
	while index < len(mibIdentReg):
		mib = mibIdentReg[index]
		index = index + 1
		file.write("    public static final String %-55s" % nameToValue(mib[1]) + " = getQualifiedId(\"" + mib[0] + "\");\n")
	
	file.write("\n    // attribute objects\n")
	index = 0
	while index < len(mibReg):
		mib = mibReg[index]
		index = index + 1
		file.write("    public static final String %-55s" % nameToVar(mib[1]) + " = getQualifiedId(\"" + mib[0] + "\";)\n")
		
	file.close()	
	return


def read_aux (filename):
	file = open(filename, "r")

	auxReg = {}

	while True:
		line = file.readline()
		if not line:
			break

		auxObjects = parseAuxObject(line)
		if auxObjects is not None:
			auxReg[auxObjects[0]] = auxObjects

	return auxReg


def write_aux(outputPrefix, mibReg, mibIdentReg, auxReg):
	file = open(outputPrefix + ".dat", "w")
	file.write("#\n# MIB Auxiliary Data File\n#\n#     generated at " + gettime() + " by pybble\n#\n#\n# CVS $Id: pybble.py,v 1.2 2005/09/28 19:19:42 tom Exp $\n#")

	file.write("\n\n#\n# MIB identity (value) objects\n#\n\n")
	index = 0
	while index < len(mibIdentReg):
		mibObjects = mibIdentReg[index]
		index = index + 1
		if auxReg.has_key(mibObjects[1]):
			auxObjects = auxReg[mibObjects[1]]
			file.write(mibObjects[0] + ":" + mibObjects[1] + ":" + auxObjects[2] + ":" + auxObjects[1] + ":::" + mibObjects[2] + "\n")
		else:
			file.write(mibObjects[0] + ":" + mibObjects[1] + ":::::" + mibObjects[2] + "\n")

	file.write("\n\n#\n# MIB attribute objects\n#\n\n")
	index = 0
	while index < len(mibReg):
		mibObjects = mibReg[index]
		index = index + 1
		if auxReg.has_key(mibObjects[1]):
			auxObjects = auxReg[mibObjects[1]]
			file.write(mibObjects[0] + ":" + mibObjects[1] + ":" + auxObjects[2] + ":" + auxObjects[1] + ":" + mibObjects[2] + ":" + mibObjects[3] + ":" + mibObjects[4] + ":" + mibObjects[5] + "\n")
		else:
			file.write(mibObjects[0] + ":" + mibObjects[1] + ":::" + mibObjects[2] + ":" + mibObjects[3] + ":" + mibObjects[4] + ":" + mibObjects[5] + "\n")

	file.close()
	return


def usage(prog):
	print prog + " -a <aux filename> -o <output filename prefix> [-h]"
	return


def main(argv=None):
	if argv is None:
		argv = sys.argv

	try:
		opts,args = getopt.getopt(argv[1:], "a:o:h")
	except getopt.GetoptError:
		print >> sys.stderr, "unknown option"
		usage(argv[0])
		sys.exit(2)

	auxFilename  = None
	mibFilename  = None
	outputPrefix = None

	for o, a in opts:
		if o == "-a":
			auxFilename = a
			continue
		if o == "-o":
			outputPrefix = a
			continue
		if o == "-h":
			usage(argv[0])
			sys.exit()

		print >> sys.stderr, "unknown option " + o
		usage(argv[0])
		sys.exit(2)

	if auxFilename is None:
		print >> sys.stderr, "missing aux file"
		sys.exit(2)

	if outputPrefix is None:
		print >> sys.stderr, "missing output file"
		sys.exit(2)

	mibReg, mibIdentReg = read_mib()
	auxReg = read_aux(auxFilename)

	write_vars(outputPrefix, mibReg, mibIdentReg)
	write_aux(outputPrefix, mibReg, mibIdentReg, auxReg)

		

if __name__ == "__main__":
	sys.exit(main())
