1 |
#!/usr/bin/env python
|
2 |
|
3 |
from optparse import OptionParser
|
4 |
from xml.sax import parseString
|
5 |
from xml.sax.handler import ContentHandler
|
6 |
from sys import exit
|
7 |
|
8 |
def die(msg):
|
9 |
print msg
|
10 |
exit(1)
|
11 |
|
12 |
class ClassesDefContentHandler(ContentHandler):
|
13 |
def __init__(self):
|
14 |
self.classes = []
|
15 |
self.headers = []
|
16 |
|
17 |
def startElement(self, name, attrs):
|
18 |
# <*> is used to indicate "whatever specified in classes.h" which obviously
|
19 |
# in this case does not work anymore, because we want to generate such a
|
20 |
# file. Therefore we exit with an error.
|
21 |
#
|
22 |
# If a class has argument "concrete", classes_def.xml declaration is enough
|
23 |
# to generate the dictionary and we do not need to create an instance in
|
24 |
# classes.h.
|
25 |
if name == "class":
|
26 |
if "pattern" in attrs:
|
27 |
die("Cannot use pattern '%s': please declare actual class names to use automatic classes.h generation." % attrs["pattern"])
|
28 |
if "type" in attrs and attrs["type"] == "concrete":
|
29 |
return
|
30 |
self.classes.append(attrs["name"])
|
31 |
if name == "include":
|
32 |
if "file" in attrs:
|
33 |
self.headers.append("\"" + attrs["file"] + "\"")
|
34 |
elif "system" in attrs:
|
35 |
self.headers.append("<"+attrs["system"] + ">")
|
36 |
else:
|
37 |
die("Malformed classes_def.xml")
|
38 |
|
39 |
def endDocument(self):
|
40 |
print "\n".join("#include %s" % x for x in self.headers)
|
41 |
if self.headers: print ""
|
42 |
print "namespace {\n struct dictionary {"
|
43 |
print "\n".join(" %s a%s;" % (n, i) for (i,n) in enumerate(self.classes))
|
44 |
print "};\n}"
|
45 |
|
46 |
if __name__ == "__main__":
|
47 |
parser = OptionParser(usage="%{progname}s <classes_def.xml>")
|
48 |
opts, args = parser.parse_args()
|
49 |
if not args:
|
50 |
parser.error("Please specify the input <classes_def.xml>")
|
51 |
if len(args) > 1:
|
52 |
parser.error("Too many input files specified")
|
53 |
|
54 |
# Replace any occurence of <>& in the attribute values by the xml parameter
|
55 |
rxml, nxml = file(args[0]).read(), ''
|
56 |
q1,q2 = 0,0
|
57 |
for c in rxml :
|
58 |
if (q1 or q2) and c == '<' : nxml += '<'
|
59 |
elif (q1 or q2) and c == '>' : nxml += '>'
|
60 |
# elif (q1 or q2) and c == '&' : nxml += '&'
|
61 |
else : nxml += c
|
62 |
if c == '"' : q1 = not q1
|
63 |
if c == "'" : q2 = not q2
|
64 |
|
65 |
parseString(nxml, ClassesDefContentHandler())
|