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() |