diff options
Diffstat (limited to 'maketables')
-rwxr-xr-x | maketables | 210 |
1 files changed, 210 insertions, 0 deletions
diff --git a/maketables b/maketables new file mode 100755 index 0000000..4e7d6ea --- /dev/null +++ b/maketables @@ -0,0 +1,210 @@ +#!/usr/bin/env python +# +# Copyright (c) 2008-2010 Wind River Systems, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the Lesser GNU General Public License version 2.1 as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the Lesser GNU General Public License for more details. +# +# You should have received a copy of the Lesser GNU General Public License +# version 2.1 along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +"""convert tables.in files to enums, tables, and support code. + +Inputs are a type name, prefix, and a list of columns, followed by a list of +names with optional "= value" suffixes, plus optional additional columns. +The names are used to create enums and a table of strings, as well as +to/from lookups between the ids and names. If additional columns are +defined, each column (separated by ", ") is used to create an additional +table of the given name, and a lookup function from ids. Example: + foo: FFF; bar = GOZINTA + hello, yah + world, nope +produces: + typedef enum { + FFF_UNKNOWN = -1, + FFF_MIN = 0, + FFF_NONE = 0, + FFF_HELLO, + FFF_WORLD, + FFF_MAX + } foo_id_t; + extern const char *foo_name(foo_id_t id); + extern foo_id_t foo_id(const char *name); + extern const char *foo_bar(foo_id_t id); + +such that foo_name(1) => "hello" and foo_bar(1) => "yah". If there +is an assigned value for a column description, missing column values +yield that value, otherwise they yield "unknown". + +Values out of range yield "unknown", and unrecognized names yield the +value -1. Note that the "MAX" value is one more than the highest defined +value. (This is for consistency with C array bounds.) +""" + +import glob +import sys +import re +import datetime +import string +from templatefile import TemplateFile + +class DataType: + """a set of related DataItem objects""" + + def __init__(self, path): + """read the first line of path, then make tuples of the rest""" + source = file(path) + definition = source.readline().rstrip() + self.name, qualifiers = string.split(definition, ': ', 2) + if '; ' in qualifiers: + self.prefix, columns = string.split(qualifiers, '; ') + else: + self.prefix = qualifiers + columns = [] + if len(columns): + self.columns = [] + columns = string.split(columns, ', ') + for col in columns: + if "=" in col: + name, default = string.split(col, ' = ') + else: + name, default = col, "" + self.columns.append({"name":name, "value":default}) + else: + self.columns = [] + self.data = [] + self.comments = [] + for line in source.readlines(): + item = {} + if line.startswith('#'): + self.comments.append(line.rstrip().replace('#', '')) + continue + # first entry on the line is the "real" name/id, following hunks + # are additional columns + cols = string.split(line.rstrip(), ', ') + item["name"] = cols.pop(0) + item["upper"] = item["name"].replace('-', '_').upper() + column_list = [] + for col in self.columns: + if len(cols) > 0: + column_list.append({"name":col["name"], "value":cols.pop(0)}) + else: + column_list.append({"name":col["name"], "value":col["default"]}) + item["cols"] = column_list + self.data.append(item) + + def __getitem__(self, key): + """Make this object look like a dict for Templates to use""" + attr = getattr(self, key) + + if callable(attr): + return attr() + else: + return attr + + def __repr__(self): + str = "" + str += "type: %s_t" % self.name + str += " %s_ENUM\n" % self.prefix + for col in self.columns: + str += "\tcol: %s (%s)\n" % (col["name"], col["value"]) + for item in self.data: + str += "item: %s\n" % item["name"] + for col in item["cols"]: + str += "\t%s(%s)\n" % (col["name"], col["value"]) + return str + + def comment(self): + if len(self.comments): + return '/*' + '\n *'.join(self.comments) + ' */\n' + else: + return '' + + def names(self): + return ',\n\t'.join('"%s"' % x["name"] for x in self.data) + + def enums(self): + return ',\n\t'.join('%s_%s' % (self.prefix, x["upper"]) for x in self.data) + + def column_names(self): + decl_lines = [] + column = 0 + for col in self.columns: + decl_lines.append("static const char *%s_id_to_%s[] = {" % (self.name, col["name"])) + decl_lines.append('\t"%s",' % col["value"]) + for item in self.data: + decl_lines.append('\t"%s",' % item["cols"][column]["value"]) + decl_lines.append('\tNULL') + decl_lines.append("};") + column = column + 1 + return '\n'.join(decl_lines) + + def column_funcs(self): + decl_lines = [] + for col in self.columns: + decl_lines.append('extern const char *') + decl_lines.append('pseudo_%s_%s(pseudo_%s_t id) {' % + (self.name, col["name"], self.name)) + decl_lines.append('\tif (id < 0 || id >= %s_MAX)' % (self.prefix)) + decl_lines.append('\t\treturn "%s";' % col["value"]) + decl_lines.append('\treturn %s_id_to_%s[id];' % + (self.name, col["name"])) + decl_lines.append('}') + return '\n'.join(decl_lines) + + def column_protos(self): + decl_lines = [] + for col in self.columns: + decl_lines.append('extern const char *pseudo_%s_%s(pseudo_%s_t id);' % + (self.name, col["name"], self.name)) + return '\n'.join(decl_lines) + +def main(): + """Read in function defintions, write out files based on templates.""" + datatypes = [] + templates = [] + + # error checking helpfully provided by the exception handler + copyright_file = open('guts/COPYRIGHT') + TemplateFile.copyright = copyright_file.read() + copyright_file.close() + + for path in glob.glob('table_templates/*'): + try: + template_file = TemplateFile(path) + template_file.emit('copyright') + template_file.emit('header') + templates.append(template_file) + except IOError: + print "Invalid or malformed template %s. Aborting." % path + exit(1) + + for filename in sys.argv[1:]: + # read in the datatype + sys.stdout.write("%s: " % filename) + datatype = DataType(filename) + datatypes.append(datatype) + print datatype.__repr__() + print "" + + print "Writing datatypes...", + for datatype in datatypes: + # populate various tables and files with each datatype + for template_file in templates: + template_file.emit('body', datatype) + print "done. Cleaning up." + + for template_file in templates: + # clean up files + template_file.emit('footer') + template_file.close() + +if __name__ == '__main__': + main() |