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