1# author: Andreas Vox, May 2012
2
3import os
4import sys
5
6from xml.etree.ElementTree import ElementTree
7from Cheetah.Template import Template
8
9from impldescription import *
10from parserng import*
11
12class Generator(object):
13
14    def __init__(self, templdir, odir):
15        self._templatedir = templdir
16        self.outdir = odir
17        self._headerfiles = []
18        self._sourcefiles = []
19        self._templateSets = {}
20
21    def getfilename(self, fname):
22        if fname[-2:] == ".h" or fname[-2:] == ".H" or fname[-3:] == ".hh" or fname[-4:] == ".hxx":
23            self._headerfiles.append(fname)
24        elif fname[-2:] == ".c" or fname[-2:] == ".C" or fname[-4:] == ".cpp" or fname[-4:] == ".cxx":
25            self._sourcefiles.append(fname)
26        return os.path.join(self.outdir, fname)
27
28    def writefilelist(self, prefix, outfile):
29        fname = os.path.join(self.outdir, outfile);
30
31        oldlist = []
32        if os.path.exists(fname):
33            of = open(fname, "r")
34            oldlist = of.readlines();
35            of.close()
36
37        newlist = ["# Generated file, do not edit!\n"]
38        newlist.append("SET(%s_HEADERS\n" % prefix)
39        for h in self._headerfiles:
40            newlist.append("\t%s\n" % h)
41        newlist.append(")\n");
42        newlist.append("SET(%s_SOURCES\n" % prefix)
43        for s in self._sourcefiles:
44            newlist.append("\t%s\n" % s)
45        newlist.append(")\n")
46
47        if (oldlist != newlist):
48            nf = open(fname, "w")
49            nf.writelines(newlist)
50            nf.close()
51
52    def generate(self, classDesc):
53        print classDesc.xmlName, ":", classDesc.datatype, classDesc.name, "=", classDesc.template
54        name = classDesc.template
55        if name not in self._templateSets:
56            self._templateSets[name] = TemplateSet(self._templatedir, name)
57
58        self._templateSets[name].generate(classDesc, self)
59
60
61class TemplateSet(object):
62    def __init__(self, dir, name):
63        self.name = name
64        self.templates = []
65        for f in os.listdir(dir):
66            if f[:len(name)] == name and f[-5:] == ".tmpl":
67                fpath = os.path.join(dir, f)
68                pair = (Template(file=fpath), f[len(name):-5])
69                self.templates.append(pair)
70
71    def generate(self, classDesc, generator):
72        if len(self.templates) == 0:
73            raise AssertionError("No '%s' templates found" % self.name)
74        if (self.name != classDesc.template):
75            raise NameError("Template names don't match: %s vs. %s" % (self.name, classDesc.template))
76        for (t,n) in self.templates:
77            t.c = classDesc
78            fname = generator.getfilename(classDesc.name + n)
79            oldcontent = "";
80            if os.path.exists(fname):
81                oldf = open(fname, "r")
82                oldcontent = oldf.read();
83                oldf.close()
84            newcontent = str(t)
85            if oldcontent != newcontent:
86                print "\t>>", fname
87                s = open(fname, "w")
88                s.write(newcontent)
89                s.close()
90            else:
91                print "\tskipping:", fname
92
93
94def Main(file, templdir, outdir):
95    spec = ElementTree();
96    spec.parse(file);
97
98    parser = RNG_Parser(os.path.dirname(file))
99    parser.parsePattern(spec.getroot(), False, False)
100
101    generator = Generator(templdir, outdir)
102
103    for c in parser.classes:
104        parser.imports[c.name] = c.name + ".h"
105    for c in parser.classes:
106        c.addIncludes(parser.imports, parser.refnames)
107        generator.generate(c)
108
109    generator.writefilelist("SCRIBUS_RELAXNG", "generatedfiles.cmake")
110
111rngfile = sys.argv[1]
112if rngfile[-4:] == ".rnc":
113    rncfile = rngfile
114    rngfile = rngfile[:-4] + ".rng"
115    cwd = os.path.dirname(sys.argv[0])
116    err = os.system("java -jar %s/../trang/trang.jar %s %s" % (cwd, rncfile, rngfile))
117    if err != 0:
118        print "aborting"
119        exit(err)
120
121templatedir = os.path.dirname(rngfile)
122outdir = templatedir
123if len(sys.argv) > 2:
124    templatedir = sys.argv[2]
125if len(sys.argv) > 3:
126    outdir = sys.argv[3]
127Main(rngfile, templatedir, outdir);
128
129