| Index: ppapi/generators/apiidlc.py
|
| diff --git a/ppapi/generators/apiidlc.py b/ppapi/generators/apiidlc.py
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..19e92b2463eae9452d9a5160ae56cbeb1d5d49ef
|
| --- /dev/null
|
| +++ b/ppapi/generators/apiidlc.py
|
| @@ -0,0 +1,242 @@
|
| +#!/usr/bin/env python
|
| +
|
| +import getopt
|
| +import os
|
| +import sys
|
| +
|
| +from Cheetah.Template import Template
|
| +from datetime import datetime
|
| +from idl_option import ParseOptions
|
| +from idl_parser import IDLParser
|
| +
|
| +class APIArgument:
|
| + def __init__(self, name, type):
|
| + self.name = name
|
| + self.type = type
|
| +
|
| + def __str__(self):
|
| + return "%s: %s" % (self.type, self.name)
|
| +
|
| + def mapped_type(self):
|
| + if self.type == "long":
|
| + return "int"
|
| + if self.type == "DOMString":
|
| + return "std::string"
|
| + if self.type.endswith("Options"):
|
| + return "ListValue"
|
| + return self.type
|
| +
|
| + def mapped_arg_type(self):
|
| + if self.type == "long":
|
| + return "int"
|
| + if self.type == "DOMString":
|
| + return "const std::string&"
|
| + if self.type.endswith("Options"):
|
| + return "const ListValue&"
|
| + return self.type
|
| +
|
| +class APIFunction:
|
| + def __init__(self, name, arguments, return_values, family=None,
|
| + is_experimental=False):
|
| + self.family = family
|
| + self.name = name
|
| + self.arguments = arguments
|
| + self.return_values = return_values
|
| + self.is_experimental = is_experimental
|
| +
|
| + def class_name(self):
|
| + return self.family.name + self.name
|
| +
|
| + def dotted_name(self):
|
| + dotted_name = self.family.name.lower() + '.' + self.name.lower()
|
| + if self.is_experimental:
|
| + return 'experimental.' + dotted_name
|
| + else:
|
| + return dotted_name
|
| +
|
| + def __str__(self):
|
| + s = self.name + ": "
|
| + for argument in self.arguments:
|
| + s += str(argument) + ", "
|
| + s += " <- "
|
| + for return_value in self.return_values:
|
| + s += str(return_value) + ", "
|
| + return s
|
| +
|
| +class APIFamily:
|
| + def __init__(self, name, functions):
|
| + self.name = name
|
| + self.functions = functions
|
| + for f in functions:
|
| + f.family = self
|
| +
|
| + def __str__(self):
|
| + s = self.name + ": "
|
| + for function in self.functions:
|
| + s += str(function) + "; "
|
| + return s
|
| +
|
| + def header_path(self):
|
| + return "chrome/browser/extensions/api/%(ln)s/%(ln)s_api.h" % {
|
| + 'ln': self.name.lower() }
|
| +
|
| +class TemplateHelper:
|
| + def __init__(self, template, families, input_dir,
|
| + output_filename, output_dir):
|
| + self.template = template
|
| + self.families = families
|
| + self.dirname = output_dir
|
| + self.basename = output_filename
|
| + self.pathname = os.path.join(output_dir, output_filename)
|
| +
|
| + self.template.families = self.families
|
| + self.template.basename = self.basename
|
| + self.template.dirname = self.dirname
|
| + self.template.output_file = self.output_file
|
| + self.template.pathname = self.pathname
|
| + self.template.year = datetime.today().year
|
| +
|
| + if self.basename.endswith(".cc"):
|
| + self.template.header_pathname = "chrome/%s" % (
|
| + self.basename.replace(".cc", ".h"))
|
| +
|
| + path_parts = os.path.join(input_dir,
|
| + output_filename).replace('.', '/').split('/')
|
| + path_parts_upper = ['CHROME']
|
| + for part in path_parts:
|
| + if len(part.strip()) != 0:
|
| + path_parts_upper.append(part.upper())
|
| + self.template.guard = '_'.join(path_parts_upper) + '_'
|
| +
|
| + def output_file(self):
|
| + self.make_path(self.dirname)
|
| + f = open(self.pathname, 'w+')
|
| + f.write(str(self.template))
|
| + f.close()
|
| +
|
| + def make_path(self, path):
|
| + try:
|
| + os.makedirs(path)
|
| + except OSError, e:
|
| + if e.errno == 17:
|
| + pass
|
| + else:
|
| + raise e
|
| +
|
| +def generate_file(template_filename, families, input_dir, output_dir):
|
| + output_filename = template_filename.replace(".tmpl", "")
|
| + template_pathname = os.path.join(input_dir, template_filename)
|
| + th = TemplateHelper(Template(file=template_pathname), families,
|
| + input_dir, output_filename, output_dir)
|
| + th.output_file()
|
| +
|
| +def read_idl(idl_filename):
|
| + f = open(idl_filename, 'r')
|
| + contents = f.read()
|
| + f.close()
|
| +
|
| + parser = IDLParser()
|
| + return parser.ParseData(contents, idl_filename)
|
| +
|
| +def member_to_function(member):
|
| + if member.cls != "Member":
|
| + return None
|
| +
|
| + name = member.GetProperty("NAME")
|
| + arguments = []
|
| + for member_part in member.children:
|
| + if member_part.cls != "Callspec":
|
| + continue
|
| + for child in member_part.children:
|
| + if child.cls == "Param":
|
| + # The last param is usually a callback, which is implied.
|
| + if child.GetProperty("NAME") == "callBack":
|
| + continue
|
| + arguments.append(APIArgument(child.GetProperty("NAME"),
|
| + child.GetProperty("TYPEREF")))
|
| + return APIFunction(name.capitalize(), arguments, [])
|
| +
|
| +def nodes_to_families(nodes):
|
| + families = []
|
| + for node in nodes:
|
| + namespace = node.GetProperty("NAME")
|
| + if namespace.startswith("experimental."):
|
| + is_experimental = True
|
| + namespace = namespace.replace("experimental.", "")
|
| + else:
|
| + is_experimental = False
|
| + namespace = namespace.capitalize()
|
| + functions = []
|
| + for child in node.children:
|
| + if child.cls == "Interface":
|
| + if child.GetProperty("NAME") == "Functions":
|
| + for member in child.children:
|
| + function = member_to_function(member)
|
| + if function is not None:
|
| + function.is_experimental = is_experimental
|
| + functions.append(function)
|
| + families.append(APIFamily(namespace, functions))
|
| + return families
|
| +
|
| +def main():
|
| + try:
|
| + opts, args = getopt.getopt(sys.argv[1:], "hi:o:d:",
|
| + ["help", "input=", "output=", "idl="])
|
| + except getopt.GetoptError, err:
|
| + print str(err)
|
| + usage()
|
| + sys.exit(2)
|
| +
|
| + input_dir = None
|
| + output_dir = None
|
| + idl_filename = None
|
| +
|
| + verbose = False
|
| + for o, a in opts:
|
| + if o in ("-h", "--help"):
|
| + usage()
|
| + sys.exit(0)
|
| + elif o in ("-i", "--input"):
|
| + input_dir = a
|
| + elif o in ("-o", "--output"):
|
| + output_dir = a
|
| + elif o in ("-d", "--idl"):
|
| + idl_filename = a
|
| + else:
|
| + assert False, "unhandled option: %s" % o
|
| +
|
| + if (input_dir is None):
|
| + print "ERROR: Must specify input_dir."
|
| + usage()
|
| + sys.exit(2)
|
| +
|
| + if (output_dir is None):
|
| + print "ERROR: Must specify output_dir."
|
| + usage()
|
| + sys.exit(2)
|
| +
|
| + if (idl_filename is None):
|
| + print "ERROR: Must specify idl."
|
| + usage()
|
| + sys.exit(2)
|
| +
|
| + nodes = read_idl(idl_filename)
|
| + families = nodes_to_families(nodes)
|
| +
|
| + for arg in args:
|
| + generate_file(arg, families, input_dir, output_dir)
|
| +
|
| + sys.exit(0)
|
| +
|
| +def usage():
|
| + print """
|
| +Takes an input directory, an output directory, an IDL, and one or more names of
|
| +template files in the input directory, and generates files from those templates
|
| +in the output directory.
|
| +
|
| +Usage: apiidlc -i input_directory -o output_directory -d idl_filename
|
| + [file1.tmpl] [file2.tmpl] ...
|
| +"""
|
| +
|
| +if __name__ == "__main__":
|
| + main()
|
|
|