diff options
Diffstat (limited to 'qpid/cpp/managementgen/generate.py')
-rwxr-xr-x | qpid/cpp/managementgen/generate.py | 229 |
1 files changed, 229 insertions, 0 deletions
diff --git a/qpid/cpp/managementgen/generate.py b/qpid/cpp/managementgen/generate.py new file mode 100755 index 0000000000..1d0987e685 --- /dev/null +++ b/qpid/cpp/managementgen/generate.py @@ -0,0 +1,229 @@ +#!/usr/bin/env python + +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http:#www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +from xml.dom.minidom import parse, parseString, Node +from cStringIO import StringIO +from stat import * +from errno import * +import os +import os.path +import filecmp + +#===================================================================================== +# +#===================================================================================== +class Template: + def __init__ (self, filename, handler): + self.filename = filename + self.handler = handler + + def expandLine (self, line, stream, object): + cursor = 0 + while 1: + sub = line.find ("/*MGEN:", cursor) + if sub == -1: + stream.write (line[cursor:len (line)]) + return + + subend = line.find("*/", sub) + stream.write (line[cursor:sub]) + cursor = subend + 2 + + tag = line[sub:subend] + dotPos = tag.find (".") + if dotPos == -1: + raise ValueError ("Invalid tag: %s" % tag) + tagObject = tag[7:dotPos] + tagName = tag[dotPos + 1:len (tag)] + + self.handler (object, stream, tagObject, tagName) + + def expand (self, object): + fd = open (self.filename) + stream = StringIO () + + for line in fd: + self.expandLine (line, stream, object) + fd.close () + + return stream + +#===================================================================================== +# +#===================================================================================== +class Generator: + def createPath (self, path): + exists = True + try: + mode = os.stat (path)[ST_MODE] + except OSError, (err,text): + if err == ENOENT: + exists = False + else: + raise + if exists and not S_ISDIR (mode): + raise ValueError ("path is not directory: %s" % path) + if not exists: + pair = os.path.split (path) + self.createPath (pair[0]) + os.mkdir (path) + + def normalize (self, path): + newpath = os.path.normcase (os.path.normpath (path)) + self.createPath (newpath) + return newpath + "/" + + def __init__ (self, destDir, templateDir): + self.dest = self.normalize (destDir) + self.input = self.normalize (templateDir) + self.filelists = {} + self.filelists["h"] = [] + self.filelists["cpp"] = [] + self.filelists["mk"] = [] + self.templateFiles = [] + + def genDisclaimer (self, stream): + stream.write ("// This source file was created by a code generator.\n") + stream.write ("// Please do not edit.") + + def fileExt (self, path): + dot = path.rfind (".") + if dot == -1: + return "" + return path[dot + 1:] + + def writeIfChanged (self, stream, target, force=False): + ext = self.fileExt (target) + self.filelists[ext].append (target) + tempFile = self.dest + "gen.tmp" + fd = open (tempFile, "w") + fd.write (stream.getvalue ()) + fd.close () + + try: + if not force and filecmp.cmp (target, tempFile): + os.remove (tempFile) + return + except: + pass + + try: + os.remove (target) + except: + pass + + os.rename (tempFile, target) + print "Generated:", target + + def targetClassFile (self, _class, templateFile): + dot = templateFile.find(".") + if dot == -1: + raise ValueError ("Invalid template file name %s" % templateFile) + extension = templateFile[dot:len (templateFile)] + path = self.dest + _class.getName ().capitalize () + extension + return path + + def targetMethodFile (self, method, templateFile): + """ Return the file name for a method file """ + dot = templateFile.rfind(".") + if dot == -1: + raise ValueError ("Invalid template file name %s" % templateFile) + extension = templateFile[dot:] + path = self.dest + "Args" + method.getFullName () + extension + return path + + def substHandler (self, object, stream, tagObject, tag): + if tagObject == "Root": + obj = "self" + else: + obj = "object" # MUST be the same as the 2nd formal parameter + + call = obj + ".gen" + tag + "(stream)" + eval (call) + + def makeClassFiles (self, templateFile, schema): + """ Generate an expanded template per schema class """ + classes = schema.getClasses () + template = Template (self.input + templateFile, self.substHandler) + self.templateFiles.append (templateFile) + for _class in classes: + target = self.targetClassFile (_class, templateFile) + stream = template.expand (_class) + self.writeIfChanged (stream, target) + + def makeMethodFiles (self, templateFile, schema): + """ Generate an expanded template per method-with-arguments """ + classes = schema.getClasses () + template = Template (self.input + templateFile, self.substHandler) + self.templateFiles.append (templateFile) + for _class in classes: + methods = _class.getMethods () + for method in methods: + if method.getArgCount () > 0: + target = self.targetMethodFile (method, templateFile) + stream = template.expand (method) + self.writeIfChanged (stream, target) + + def makeMakeFile (self, target): + stream = StringIO () + stream.write ("# Generated makefile fragment.\n\n") + stream.write ("mgen_generator=$(mgen_dir)/main.py \\\n") + stream.write (" $(mgen_dir)/generate.py \\\n") + stream.write (" $(mgen_dir)/schema.py \\\n") + stream.write (" $(top_srcdir)/../specs/management-types.xml \\\n") + stream.write (" $(top_srcdir)/../specs/management-schema.xml \\\n ") + first = 1 + for template in self.templateFiles: + if first == 1: + first = 0 + else: + stream.write (" \\\n ") + stream.write ("$(mgen_dir)/templates/" + template) + + stream.write ("\n\nmgen_broker_cpp=") + first = 1 + for file in self.filelists["cpp"]: + if first == 1: + first = 0 + else: + stream.write (" \\\n ") + stream.write (file.replace ("../src", ".")) + stream.write ("\n\n") + + stream.write ("# Header file install rules.\n") + stream.write ("qpid_managementdir = $(includedir)/qpid/management\n") + stream.write ("dist_qpid_management_HEADERS = ") + first = 1 + for file in self.filelists["h"]: + if first == 1: + first = 0 + else: + stream.write (" \\\n ") + stream.write (file.replace ("../src", ".")) + stream.write ("\n\n") + + stream.write ("if GENERATE\n") + stream.write ("$(srcdir)/managementgen.mk: $(mgen_generator)\n") + stream.write ("\t$(mgen_cmd)\n") + stream.write ("\n$(mgen_generator):\n") + stream.write ("endif\n") + + self.writeIfChanged (stream, target, force=True) |