1 #!/usr/bin/env python 2 # Copyright (C) 2013 Google Inc. All rights reserved. 3 # 4 # Redistribution and use in source and binary forms, with or without 5 # modification, are permitted provided that the following conditions are 6 # met: 7 # 8 # * Redistributions of source code must retain the above copyright 9 # notice, this list of conditions and the following disclaimer. 10 # * Redistributions in binary form must reproduce the above 11 # copyright notice, this list of conditions and the following disclaimer 12 # in the documentation and/or other materials provided with the 13 # distribution. 14 # * Neither the name of Google Inc. nor the names of its 15 # contributors may be used to endorse or promote products derived from 16 # this software without specific prior written permission. 17 # 18 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 30 import os.path 31 import sys 32 33 import in_generator 34 import license 35 import name_utilities 36 import template_expander 37 38 39 HEADER_TEMPLATE = """%(license)s 40 41 #ifndef %(namespace)s%(suffix)sHeaders_h 42 #define %(namespace)s%(suffix)sHeaders_h 43 %(base_header_for_suffix)s 44 %(includes)s 45 46 #endif // %(namespace)s%(suffix)sHeaders_h 47 """ 48 49 50 def case_insensitive_matching(name): 51 return (name == ('HTMLEvents') 52 or name == 'Event' 53 or name == 'Events' 54 or name.startswith('UIEvent') 55 or name.startswith('CustomEvent') 56 or name.startswith('MouseEvent')) 57 58 59 class EventFactoryWriter(in_generator.Writer): 60 defaults = { 61 'ImplementedAs': None, 62 'Conditional': None, 63 'RuntimeEnabled': None, 64 } 65 default_parameters = { 66 'namespace': '', 67 'suffix': '', 68 } 69 filters = { 70 'cpp_name': name_utilities.cpp_name, 71 'enable_conditional': name_utilities.enable_conditional_if_endif, 72 'lower_first': name_utilities.lower_first, 73 'case_insensitive_matching': case_insensitive_matching, 74 'script_name': name_utilities.script_name, 75 } 76 77 def __init__(self, in_file_path): 78 super(EventFactoryWriter, self).__init__(in_file_path) 79 self.namespace = self.in_file.parameters['namespace'].strip('"') 80 self.suffix = self.in_file.parameters['suffix'].strip('"') 81 self._validate_entries() 82 self._outputs = {(self.namespace + self.suffix + "Headers.h"): self.generate_headers_header, 83 (self.namespace + self.suffix + ".cpp"): self.generate_implementation, 84 } 85 86 def _validate_entries(self): 87 # If there is more than one entry with the same script name, only the first one will ever 88 # be hit in practice, and so we'll silently ignore any properties requested for the second 89 # (like RuntimeEnabled - see crbug.com/332588). 90 entries_by_script_name = dict() 91 for entry in self.in_file.name_dictionaries: 92 script_name = name_utilities.script_name(entry) 93 if script_name in entries_by_script_name: 94 self._fatal('Multiple entries with script_name=%(script_name)s: %(name1)s %(name2)s' % { 95 'script_name': script_name, 96 'name1': entry['name'], 97 'name2': entries_by_script_name[script_name]['name']}) 98 entries_by_script_name[script_name] = entry 99 100 def _fatal(self, message): 101 print 'FATAL ERROR: ' + message 102 exit(1) 103 104 def _headers_header_include_path(self, entry): 105 if entry['ImplementedAs']: 106 path = os.path.dirname(entry['name']) 107 if len(path): 108 path += '/' 109 path += entry['ImplementedAs'] 110 else: 111 path = entry['name'] 112 return path + '.h' 113 114 def _headers_header_includes(self, entries): 115 includes = dict() 116 for entry in entries: 117 cpp_name = name_utilities.cpp_name(entry) 118 # Avoid duplicate includes. 119 if cpp_name in includes: 120 continue 121 if self.suffix == 'Modules': 122 subdir_name = 'modules' 123 else: 124 subdir_name = 'core' 125 include = '#include "%(path)s"\n#include "bindings/%(subdir_name)s/v8/V8%(script_name)s.h"' % { 126 'path': self._headers_header_include_path(entry), 127 'script_name': name_utilities.script_name(entry), 128 'subdir_name': subdir_name, 129 } 130 includes[cpp_name] = self.wrap_with_condition(include, entry['Conditional']) 131 return includes.values() 132 133 def generate_headers_header(self): 134 base_header_for_suffix = '' 135 if self.suffix: 136 base_header_for_suffix = '\n#include "core/%(namespace)sHeaders.h"\n' % {'namespace': self.namespace} 137 return HEADER_TEMPLATE % { 138 'license': license.license_for_generated_cpp(), 139 'namespace': self.namespace, 140 'suffix': self.suffix, 141 'base_header_for_suffix': base_header_for_suffix, 142 'includes': '\n'.join(self._headers_header_includes(self.in_file.name_dictionaries)), 143 } 144 145 @template_expander.use_jinja('EventFactory.cpp.tmpl', filters=filters) 146 def generate_implementation(self): 147 return { 148 'namespace': self.namespace, 149 'suffix': self.suffix, 150 'events': self.in_file.name_dictionaries, 151 } 152 153 154 if __name__ == "__main__": 155 in_generator.Maker(EventFactoryWriter).main(sys.argv) 156