Files
2014-03-17 15:13:14 +00:00

199 lines
4.9 KiB
Python

# This Python Script takes the cfg_msg.h file, parses it and generates the corresponding Java
# MsgType class.
#
# Version 0.1 - Vincent van Beveren
import re, sys, time, os
groups = {}
className = "MsgTypes"
package = "org.km3net.clbv2.remote"
packdir = package.replace(".", "/")
# what we do not want to parse
filterPattrns = [
"MSG_[A-Z]+_COMMANDS",
"\(",
"MSG_TYPE",
"MSG_GROUP_SHIFT",
"MSG_COMMANDS",
"MSG_EVENTS",
"[A-Z_]+_H_"
]
classTemplate = """\
package %(package)s;
/**
* Contains all identifiers, and is generated from %(srcfile)s
*
* This file is automatically generated! Do not modify!
*
* @data %(filedate)s
*
* @author msg2java.py
*/
public abstract class %(className)s
{
static final int GROUP_SHIFT = 6;
private static int MSG_TYPE(int group, int id)
{
return ( group << GROUP_SHIFT ) | id;
};
private MsgTypes() {};
%(groups)s
}
"""
groupTemplate = """\
public static final int %(groupName)s = %(groupId)s;
%(msgDefs)s
"""
msgTemplate = """\
public static final int %(msgDef)s = MSG_TYPE(%(groupName)s, %(msgId)s);
"""
mTypePattern = re.compile("MSG_TYPE\\(([A-Z_]+),([0-9x]+)\\)")
def filter(macro):
for pattern in filterPattrns:
if re.match(pattern, macro) != None:
return True
return False
def interpret(line):
tokens = line.split()
# it needs to be a #define statement, else we're not interested
if tokens[0].lower() != "#define": return
macro= tokens[1]
if filter(macro): return
if macro.startswith("GROUP_"):
groups[tokens[1]] = (tokens[2], {})
elif macro.startswith("MSG_"):
cmd = "".join(tokens[2:])
result = mTypePattern.match(cmd)
if result == None:
print "Could not parse MSG_TYPE for '#define", macro, cmd,"'"
else:
group = result.group(1)
id = result.group(2)
if group not in groups:
print "Group", group, " for message ", macro, " not found"
else:
groups[group][1][macro] = id
else:
print "Unexpected macro '", macro, "', please modify filter"
def dumpInfo():
for name, data in groups.iteritems():
if len(data[1]) == 0:
print "group ", name, " has id ", data[0], " and no messages"
continue
print "group ", name, " has id ", data[0], " and the following messages:"
for msg, msgId in data[1].iteritems():
print " - ", msg, " = ", msgId
def writeJavaClass(javasrcdir, srcfile):
groupTemplates = []
for groupName, data in groups.iteritems():
msgTemplates = []
for msgName, msgId in data[1].iteritems():
msgTplParams = {
'msgDef' : msgName,
'groupName' : groupName,
'msgId' : msgId
}
msgTemplates += [ msgTemplate % msgTplParams ]
grpTplParams = {
'groupName' : groupName,
'groupId' : data[0],
'msgDefs' : "".join(msgTemplates)
}
groupTemplates += [ groupTemplate % grpTplParams ]
f = file(javasrcdir + "/" + packdir + "/" + className + ".java", "w")
f.write(classTemplate % {
'groups' : "".join(groupTemplates),
'filedate' : time.asctime(),
'className' : className,
'package' : package,
'srcfile' : srcfile
})
f.close()
def processFile(filename):
pLine = None
mlC = False
# poor man's C filter
# filters out all the comments and concats escaped lines
for line in file(filename):
l = str(line)
if mlC:
if l.find("*/") >= 0:
l = l[l.find("*/") + 2:-1]
mlC = False
else:
continue
while l.find("/*") >= 0:
if l.find("*/") >= 0:
l = l[0:l.find("/*")] + l[l.find("*/") + 2:-1]
else:
l = l[0:l.find("/*")]
mlC = True
if l.find("//") >=0:
l = l[0:l.find("//")]
l = l.strip()
if len(l) == 0:
continue
if pLine:
l = pLine + l
if l.endswith("\\"):
pLine = l[0:-1]
else:
# We have a complete cleaned up line
pLine = None
interpret(l)
if __name__ == "__main__":
if len(sys.argv) != 3:
print "usage: msg2java.py <input-header-file> <output java src root>"
sys.exit(1)
processFile(sys.argv[1])
# dumpInfo()
writeJavaClass(sys.argv[2], os.path.basename(sys.argv[1]))