Index: tools/nixysa/nixysa/codegen.py |
=================================================================== |
--- tools/nixysa/nixysa/codegen.py (revision 0) |
+++ tools/nixysa/nixysa/codegen.py (revision 0) |
@@ -0,0 +1,238 @@ |
+#!/usr/bin/python2.4 |
+# |
+# Copyright 2008 Google Inc. |
+# |
+# Licensed 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. |
+ |
+"""Code generator |
+ |
+This file is the main entry point for the code generator. |
+To use: |
+ codegen.py --output-dir=output-path --generate=npapi file1.idl file2.idl ... |
+""" |
+ |
+import glob |
+import imp |
+# Use hashlib if present (Python 2.5 and up), otherwise fall back to md5. |
+try: |
+ import hashlib |
+except ImportError: |
+ import md5 |
+import os |
+import sys |
+ |
+import gflags |
+ |
+# local imports |
+import idl_parser |
+import locking |
+import log |
+import syntax_tree |
+ |
+# default supported generators |
+import header_generator |
+import cpp_header_generator |
+import js_header_generator |
+import npapi_generator |
+ |
+# default supported binding models |
+import pod_binding |
+import enum_binding |
+import callback_binding |
+import by_value_binding |
+import by_pointer_binding |
+import unsized_array_binding |
+import nullable_binding |
+ |
+generators = {'header': header_generator, |
+ 'cppheader': cpp_header_generator, |
+ 'jsheader': js_header_generator, |
+ 'npapi': npapi_generator} |
+ |
+binding_models = {'pod': pod_binding, |
+ 'callback': callback_binding, |
+ 'enum': enum_binding, |
+ 'by_value': by_value_binding, |
+ 'by_pointer': by_pointer_binding, |
+ 'unsized_array': unsized_array_binding, |
+ 'nullable': nullable_binding} |
+ |
+ |
+FLAGS = gflags.FLAGS |
+gflags.DEFINE_multistring('binding-module', [], 'include a binding model' |
+ ' module. Value is name:path where \'name\' is the' |
+ ' binding model name, and \'path\' is the binding' |
+ ' model module path.') |
+ |
+gflags.DEFINE_multistring('generator-module', [], 'include a generator module.' |
+ ' Value is name:path where \'name\' is the generator' |
+ ' name, and \'path\' is the generator module path.') |
+ |
+gflags.DEFINE_multistring('generate', [], 'the generator to use') |
+gflags.DEFINE_string('output-dir', '.', 'the output directory') |
+ |
+gflags.DEFINE_boolean('exclusive-lock', False, 'Use file locking to make sure' |
+ ' there is only one instance running at a time.') |
+gflags.DEFINE_boolean('force', False, 'force generation even if the source' |
+ ' files have not changed') |
+gflags.DEFINE_boolean('force-docs', False, 'force all members to have' |
+ ' documentation blocks or else raise an exception.') |
+gflags.DEFINE_boolean('no-return-docs', False, 'remove docs marked as' |
+ ' noreturndocs.') |
+gflags.DEFINE_boolean('overloaded-function-docs', False, |
+ 'generate special overloaded function docs.') |
+gflags.DEFINE_boolean('properties-equal-undefined', False, |
+ 'Emit class.prototype.property = undefined;') |
+ |
+class NativeType(syntax_tree.Definition): |
+ defn_type = 'Native' |
+ |
+ def __init__(self, source, attributes, name, podtype): |
+ syntax_tree.Definition.__init__(self, source, attributes, name) |
+ self.podtype = podtype |
+ self.is_type = True |
+ |
+ def LookUpBindingModel(self): |
+ """Implementation of LookUpBindingModel for NativeType.""" |
+ return 'pod' |
+ |
+ |
+def GetStdNamespace(): |
+ pod_attributes = {'binding_model': 'pod'} |
+ source_file = idl_parser.File('<internal>') |
+ source_file.header = "common.h" |
+ source_file.npapi_cpp = None |
+ source_file.npapi_header = None |
+ source = idl_parser.SourceLocation(source_file, 0) |
+ defn_list = [NativeType(source, pod_attributes, 'string', 'string'), |
+ NativeType(source, pod_attributes, 'wstring', 'wstring')] |
+ return syntax_tree.Namespace(source, [], 'std', defn_list) |
+ |
+ |
+def GetNativeTypes(): |
+ pod_attributes = {'binding_model': 'pod'} |
+ source_file = idl_parser.File('<internal>') |
+ source_file.header = None |
+ source_file.npapi_cpp = None |
+ source_file.npapi_header = None |
+ source = idl_parser.SourceLocation(source_file, 0) |
+ return [NativeType(source, pod_attributes, 'void', 'void'), |
+ NativeType(source, pod_attributes, 'int', 'int'), |
+ NativeType(source, pod_attributes, 'unsigned int', 'int'), |
+ NativeType(source, pod_attributes, 'size_t', 'int'), |
+ NativeType(source, pod_attributes, 'bool', 'bool'), |
+ NativeType(source, pod_attributes, 'float', 'float'), |
+ NativeType(source, pod_attributes, 'double', 'float'), |
+ NativeType(source, pod_attributes, 'Variant', 'variant'), |
+ GetStdNamespace()] |
+ |
+ |
+def AddModulesFromFlags(table, flag_values, md5_hash): |
+ for entry in flag_values: |
+ string_list = entry.split(':') |
+ name = string_list[0] |
+ path = ':'.join(string_list[1:]) |
+ try: |
+ # hash the extra modules that we load |
+ md5_hash.update(open(path).read()) |
+ table[name] = imp.load_source(name, path) |
+ except IOError: |
+ print 'Could not load module %s.' % path |
+ raise |
+ |
+ |
+def main(argv): |
+ files = argv[1:] |
+ # generate a hash of all the inputs to figure out if we need to re-generate |
+ # the outputs. |
+ # Use hashlib if present (Python 2.5 and up), otherwise fall back to md5. |
+ if globals().has_key('hashlib'): |
+ md5_hash = hashlib.md5() |
+ else: |
+ md5_hash = md5.new(); |
+ # hash the input files and the source python files (globbing *.py in the |
+ # directory of this file) |
+ for source_file in files + glob.glob(os.path.join(os.path.dirname(__file__), |
+ '*.py')): |
+ md5_hash.update(open(source_file).read()) |
+ # hash the options since they may affect the output |
+ for s in (FLAGS['generator-module'].value + FLAGS['binding-module'].value + |
+ FLAGS.generate + [FLAGS['output-dir'].value]): |
+ md5_hash.update(s) |
+ |
+ # import generator and binding model modules, and hash them |
+ AddModulesFromFlags(generators, FLAGS['generator-module'].value, md5_hash) |
+ AddModulesFromFlags(binding_models, FLAGS['binding-module'].value, md5_hash) |
+ |
+ output_dir = FLAGS['output-dir'].value |
+ if not os.path.isdir(output_dir): |
+ os.makedirs(output_dir) |
+ |
+ hash_filename = os.path.join(output_dir, 'hash') |
+ hash_value = md5_hash.hexdigest() |
+ if not FLAGS.force: |
+ try: |
+ hash_file = open(hash_filename, 'r') |
+ # Don't read while others are writing... |
+ if FLAGS['exclusive-lock'].value: |
+ locking.lockf(hash_file, locking.LOCK_SH) |
+ |
+ old_hash = hash_file.read() |
+ |
+ if FLAGS['exclusive-lock'].value: |
+ locking.lockf(hash_file, locking.LOCK_UN) |
+ hash_file.close() |
+ |
+ if hash_value == old_hash: |
+ print "Source files haven't changed: nothing to generate." |
+ return |
+ except IOError: |
+ # Could not load the hash file, so there must be stuff to |
+ # generate. |
+ pass |
+ |
+ hash_file = open(hash_filename, 'w') |
+ if FLAGS['exclusive-lock'].value: |
+ locking.lockf(hash_file, locking.LOCK_EX) |
+ |
+ my_parser = idl_parser.Parser(output_dir) |
+ pairs = [] |
+ for f in files: |
+ idl_file = idl_parser.File(f) |
+ defn = my_parser.Parse(idl_file) |
+ pairs.append((idl_file, defn)) |
+ definitions = sum([defn for (f, defn) in pairs], []) + GetNativeTypes() |
+ global_namespace = syntax_tree.Namespace(None, [], '', definitions) |
+ syntax_tree.FinalizeObjects(global_namespace, binding_models) |
+ |
+ writer_list = [] |
+ for generator_name in FLAGS.generate: |
+ try: |
+ generator = generators[generator_name] |
+ writer_list += generator.ProcessFiles(output_dir, pairs, global_namespace) |
+ except KeyError: |
+ print 'Unknown generator %s.' % generator_name |
+ raise |
+ for writer in writer_list: |
+ writer.Write() |
+ |
+ # Save hash for next time |
+ hash_file.write(hash_value) |
+ if FLAGS['exclusive-lock'].value: |
+ locking.lockf(hash_file, locking.LOCK_UN) |
+ hash_file.close() |
+ log.FailIfHaveErrors() |
+ |
+ |
+if __name__ == '__main__': |
+ main(FLAGS(sys.argv)) |
Property changes on: tools/nixysa/nixysa/codegen.py |
___________________________________________________________________ |
Added: svn:eol-style |
+ LF |