generateCode.py 8.95 KB
Newer Older
math's avatar
math committed
1 2 3 4
#!/usr/bin/env python

from optparse import OptionParser
import os
5
import sys
math's avatar
math committed
6 7

class RawCode(object):
8 9
    def __init__(self, name, attr, structors):
        self._structors = structors
10
        self._name = "W" + name
math's avatar
math committed
11 12 13
        self._attr = attr
        self._indent = "    "
        self._header = \
14
"""\
math's avatar
math committed
15 16
//---------------------------------------------------------------------------
//
17
// Project: OpenWalnut
math's avatar
math committed
18
//
19 20
// Copyright 2009 SomeCopyrightowner
//
21
// This file is part of OpenWalnut.
22
//
23
// OpenWalnut is free software: you can redistribute it and/or modify
24 25 26 27
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
28
// OpenWalnut is distributed in the hope that it will be useful,
29 30 31 32 33
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
34
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
35
//
math's avatar
math committed
36 37 38 39 40 41 42 43 44
//---------------------------------------------------------------------------

"""
        self._body = ""
        self._footer = ""

        if os.environ['USER']:
            self._author = os.environ['USER']
        elif os.environ['LOGNAME']:
45
            self._author = os.environ['LOGNAME']
math's avatar
math committed
46 47 48 49 50 51 52
        else:
            self._author = "Unkown"
        self._doxy = "/**\n * TODO(" + self._author + "): Document this!\n */\n"

    def indent(self, level, str):
        result = ""
        for line in str.splitlines( True ):
53 54 55 56 57
            if line.strip() == "":
                # don't indent empty lines
                result += line
            else:
                result += (level*self._indent) + line
math's avatar
math committed
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
        return result

    def signatures(self, accessor):
        result = []
        for attribute in self._attr:
            sig = []
            type = attribute[0]
            name = attribute[1]
            if( accessor == "get" ):
                sig.append(type + " ")
                sig.append("get" + name[0].upper() + name[1:] + "() const")
            elif( accessor == "set" ):
                sig.append("void ")
                sig.append("set" + name[0].upper() + name[1:] + "( " + type + " " + name + " )")
            else:
                assert 1==0 and "No getter nor setter methode requested"
            result.append(sig)
        return result

class HeaderCode(RawCode):
78 79
    def __init__(self, name, attr, structors):
        RawCode.__init__(self, name, attr, structors)
math's avatar
math committed
80 81 82 83 84 85 86 87
        guard = self._name.upper() + "_H"
        self._header += "#ifndef " + guard + "\n"
        self._header += "#define " + guard + "\n\n"
        self._footer += "#endif  // " + self._name.upper() + "_H\n"

    def renderSignatures(self):
        result = ""
        for sig in self.signatures("get"):
88 89
            result += self._doxy
            result += ''.join(sig) + ";" + "\n\n"
math's avatar
math committed
90
        for sig in self.signatures("set"):
91 92
            result += self._doxy
            result += ''.join(sig) + ";" + "\n\n"
math's avatar
math committed
93 94 95 96 97
        return result

    def renderMemberVariables(self):
        result = ""
        for attribute in self._attr:
98 99
            result += self._doxy
            result += attribute[0] + " m_" + attribute[1] + ";" + "\n\n";
math's avatar
math committed
100 101
        return result

102 103 104 105 106 107 108 109 110 111 112 113
    def structor(self, type):
        result = ""
        result += self._doxy
        if type == "con":
            result += ""
        elif type == "de":
            result += "~"
        else:
            assert 1 == 0 and "Neither Constructor nor Destructor are requested but: " + type
        result += self._name + "();\n\n"
        return result

math's avatar
math committed
114
    def __str__(self):
115 116
        modifier_level = 0
        member_level = 1
math's avatar
math committed
117 118
        result = self._header
        result += self.indent(0, self._doxy)
119
        result += "class " + self._name + "\n"
math's avatar
math committed
120
        result += "{\n"
121
        result += self.indent(modifier_level, "public:\n")
122 123 124
        if self._structors:
            result += self.indent(member_level, self.structor("con"))
            result += self.indent(member_level, self.structor("de"))
125
        result += self.indent(member_level, self.renderSignatures())
126
        result += self.indent(modifier_level, "protected:\n")
127 128
        result += self.indent(modifier_level, "private:\n")
        result += self.indent(member_level, self.renderMemberVariables())
math's avatar
math committed
129 130 131 132 133
        result += "};\n\n"
        result += self._footer
        return result

class ImplementationCode(RawCode):
134 135 136 137 138 139 140 141 142 143 144 145 146 147
    def __init__(self, name, attr, structors):
        RawCode.__init__(self, name, attr, structors)
        self._header += "#include \"" + self._name + ".h\"\n\n"

    def structor(self, type):
        result = self._name + "::"
        if type == "con":
            result += ""
        elif type == "de":
            result += "~"
        else:
            assert 1 == 0 and "Neither Constructor nor Destructor are requested but: " + type
        result += self._name + "()\n{\n}\n"
        return result + "\n"
math's avatar
math committed
148 149 150 151

    def renderSignatures(self):
        result = ""
        for sig in self.signatures("get"):
152
            result += sig[0] + self._name + "::" + sig[1] + "\n"
math's avatar
math committed
153 154
            result += "{\n"
            result += self.indent(1, "return m_" + sig[1][3].lower() + sig[1][4:-8]) + ";\n"
155
            result += "}\n\n"
math's avatar
math committed
156
        for sig in self.signatures("set"):
157
            result += sig[0] + self._name + "::" + sig[1] + "\n"
math's avatar
math committed
158 159
            result += "{\n"
            result += self.indent(1, "m_" + sig[1].split()[-2] + " = " + sig[1].split()[-2] + ";\n")
160
            result += "}\n\n"
math's avatar
math committed
161 162 163
        return result

    def __str__(self):
164
        member_level = 0
math's avatar
math committed
165 166
        result = self._header
        result += self.renderSignatures()
167 168 169
        if self._structors:
            result += self.indent(member_level, self.structor("con"))
            result += self.indent(member_level, self.structor("de"))
math's avatar
math committed
170 171
        return result

172 173
class TestCode(RawCode):
    def __init__(self, name):
174
        RawCode.__init__(self, name, [], False)
175 176 177 178 179

    def __str__(self):
        result = "TestCode"
        return result

180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195
def exists( fname ):
    return os.path.exists( fname )

def writeToFile( fname, payload ):
    file = open(fname, 'w')
    file.write( payload )
    file.close()

def writeIfNotExists( code, extension ):
    fname  = code._name + extension
    if exists( fname ):
        sys.stderr.write("Error: file " + fname + " already exists.\n")
        sys.exit(1)
    else:
        writeToFile( fname, str(code) )

196
def main():
197 198
    synopsis  = "\n\t%prog [options] Classname"
    synopsis += "\n\t%prog --help\n"
199
    synopsis += "Example:"
200
    synopsis += "\n\t%prog --class --header --member=int,plistId --member=WSomeOtherClass,myMemeberVar WSomeClass"
201 202
    synopsis += "\n\n%prog automatically writes the code to the corresponding files"
    synopsis += "\n(cpp, h) and exists if it already exists."
203
    parser = OptionParser(usage=synopsis, version="%prog 0.0_pre_alpha (USE AT YOUR OWN RISK)")
204 205 206 207 208 209 210 211 212
    parser.set_defaults(testsuite=False)
    parser.set_defaults(cls=False)
    parser.set_defaults(header=False)
    parser.set_defaults(structors=False)
    parser.add_option("-T","--test", action="store_true", help="Generates test stub", dest="testsuite")
    parser.add_option("-C","--class", action="store_true", help="Generates class stub", dest="cls")
    parser.add_option("-H","--header", action="store_true", help="Generates header stub", dest="header")
    parser.add_option("-m","--member", action="append", help="Adds member to class with public getter and setter methods", dest="members", type="string", metavar="TYPE,NAME")
    parser.add_option("-s","--structors", action="store_true", help="Adds default construtor and destructor.", dest="structors")
213 214 215
    (options, args) = parser.parse_args()
    attributes = []
    classname = ""
216 217 218 219 220 221 222 223
    if options.members:
        for m in options.members:
            if len(m.split(',')) != 2:
                parser.error("parsing option: '" + m + "'\nStrings defining type and name of the member are required and separated by a comma, e.g.: 'int,counter'")
            elif (len(m.split(',')[0]) < 1) or (len(m.split(',')[1]) < 1):
                parser.error("parsing option: '" + m + "'\nEmpty type or name string. Member definitions must have the form: type_string,name_string, e.g. 'int,counter'")
            else:
                attributes.append(m.split(','))
224 225 226 227 228 229 230 231 232
    if len(args) != 1:
        parser.error("Invalid number of arguments, Classname required")
    else:
        classname = args[0]

    if not options.cls and not options.header and not options.testsuite:
        parser.error("No code should be generated?, use at least one option: --class, --header or --test")

    if options.cls:
233
        writeIfNotExists( ImplementationCode(classname, attributes, options.structors), ".cpp" )
234
    if options.header:
235
        writeIfNotExists( HeaderCode(classname, attributes, options.structors), ".h" )
236 237 238 239 240
    if options.testsuite:
        print TestCode(classname)

if __name__ == '__main__':
    main()