1 # Copyright (C) 2013 Google Inc. All rights reserved.
3 # Redistribution and use in source and binary forms, with or without
4 # modification, are permitted provided that the following conditions are
7 # * Redistributions of source code must retain the above copyright
8 # notice, this list of conditions and the following disclaimer.
9 # * Redistributions in binary form must reproduce the above
10 # copyright notice, this list of conditions and the following disclaimer
11 # in the documentation and/or other materials provided with the
13 # * Neither the name of Google Inc. nor the names of its
14 # contributors may be used to endorse or promote products derived from
15 # this software without specific prior written permission.
17 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 from in_generator import Maker
38 HEADER_TEMPLATE = """%(license)s
40 #ifndef %(namespace)s%(suffix)sHeaders_h
41 #define %(namespace)s%(suffix)sHeaders_h
42 %(base_header_for_suffix)s
45 #endif // %(namespace)s%(suffix)sHeaders_h
49 INTERFACES_HEADER_TEMPLATE = """%(license)s
51 #ifndef %(namespace)s%(suffix)sInterfaces_h
52 #define %(namespace)s%(suffix)sInterfaces_h
53 %(base_header_for_suffix)s
54 %(declare_conditional_macros)s
56 #define %(macro_style_name)s_INTERFACES_FOR_EACH(macro) \\
58 %(unconditional_macros)s
60 %(conditional_macros)s
62 #endif // %(namespace)s%(suffix)sInterfaces_h
66 class Writer(in_generator.Writer):
67 def __init__(self, in_file_path):
68 super(Writer, self).__init__(in_file_path)
69 self.namespace = self.in_file.parameters['namespace'].strip('"')
70 self.suffix = self.in_file.parameters['suffix'].strip('"')
71 self._entries_by_conditional = {}
72 self._unconditional_entries = []
73 self._validate_entries()
74 self._sort_entries_by_conditional()
75 self._outputs = {(self.namespace + self.suffix + "Headers.h"): self.generate_headers_header,
76 (self.namespace + self.suffix + "Interfaces.h"): self.generate_interfaces_header,
79 def _validate_entries(self):
80 # If there is more than one entry with the same script name, only the first one will ever
81 # be hit in practice, and so we'll silently ignore any properties requested for the second
82 # (like RuntimeEnabled - see crbug.com/332588).
83 entries_by_script_name = dict()
84 for entry in self.in_file.name_dictionaries:
85 script_name = name_utilities.script_name(entry)
86 if script_name in entries_by_script_name:
87 self._fatal('Multiple entries with script_name=%(script_name)s: %(name1)s %(name2)s' % {
88 'script_name': script_name,
89 'name1': entry['name'],
90 'name2': entries_by_script_name[script_name]['name']})
91 entries_by_script_name[script_name] = entry
93 def _fatal(self, message):
94 print 'FATAL ERROR: ' + message
97 def _sort_entries_by_conditional(self):
98 unconditional_names = set()
99 for entry in self.in_file.name_dictionaries:
100 conditional = entry['Conditional']
102 cpp_name = name_utilities.cpp_name(entry)
103 if cpp_name in unconditional_names:
105 unconditional_names.add(cpp_name)
106 self._unconditional_entries.append(entry)
108 for entry in self.in_file.name_dictionaries:
109 cpp_name = name_utilities.cpp_name(entry)
110 if cpp_name in unconditional_names:
112 conditional = entry['Conditional']
113 if not conditional in self._entries_by_conditional:
114 self._entries_by_conditional[conditional] = []
115 self._entries_by_conditional[conditional].append(entry)
117 def _headers_header_include_path(self, entry):
118 if entry['ImplementedAs']:
119 path = os.path.dirname(entry['name'])
122 path += entry['ImplementedAs']
127 def _headers_header_includes(self, entries):
129 for entry in entries:
130 cpp_name = name_utilities.cpp_name(entry)
131 # Avoid duplicate includes.
132 if cpp_name in includes:
134 if self.suffix == 'Modules':
135 subdir_name = 'modules'
138 include = '#include "%(path)s"\n#include "bindings/%(subdir_name)s/v8/V8%(script_name)s.h"' % {
139 'path': self._headers_header_include_path(entry),
140 'script_name': name_utilities.script_name(entry),
141 'subdir_name': subdir_name,
143 includes[cpp_name] = self.wrap_with_condition(include, entry['Conditional'])
144 return includes.values()
146 def generate_headers_header(self):
147 base_header_for_suffix = ''
149 base_header_for_suffix = '\n#include "core/%(namespace)sHeaders.h"\n' % {'namespace': self.namespace}
150 return HEADER_TEMPLATE % {
151 'license': license.license_for_generated_cpp(),
152 'namespace': self.namespace,
153 'suffix': self.suffix,
154 'base_header_for_suffix': base_header_for_suffix,
155 'includes': '\n'.join(self._headers_header_includes(self.in_file.name_dictionaries)),
158 def _declare_one_conditional_macro(self, conditional, entries):
159 macro_name = '%(macro_style_name)s_INTERFACES_FOR_EACH_%(conditional)s' % {
160 'macro_style_name': name_utilities.to_macro_style(self.namespace + self.suffix),
161 'conditional': conditional,
163 return self.wrap_with_condition("""#define %(macro_name)s(macro) \\
167 #define %(macro_name)s(macro)""" % {
168 'macro_name': macro_name,
169 'declarations': '\n'.join(sorted(set([
170 ' macro(%(cpp_name)s) \\' % {'cpp_name': name_utilities.cpp_name(entry)}
171 for entry in entries]))),
174 def _declare_conditional_macros(self):
176 self._declare_one_conditional_macro(conditional, entries)
177 for conditional, entries in self._entries_by_conditional.items()])
179 def _unconditional_macro(self, entry):
180 return ' macro(%(cpp_name)s) \\' % {'cpp_name': name_utilities.cpp_name(entry)}
182 def _conditional_macros(self, conditional):
183 return ' %(macro_style_name)s_INTERFACES_FOR_EACH_%(conditional)s(macro) \\' % {
184 'macro_style_name': name_utilities.to_macro_style(self.namespace + self.suffix),
185 'conditional': conditional,
188 def generate_interfaces_header(self):
189 base_header_for_suffix = ''
191 base_header_for_suffix = '\n#include "core/%(namespace)sInterfaces.h"\n' % {'namespace': self.namespace}
192 return INTERFACES_HEADER_TEMPLATE % {
193 'license': license.license_for_generated_cpp(),
194 'namespace': self.namespace,
195 'suffix': self.suffix,
196 'base_header_for_suffix': base_header_for_suffix,
197 'macro_style_name': name_utilities.to_macro_style(self.namespace + self.suffix),
198 'declare_conditional_macros': self._declare_conditional_macros(),
199 'unconditional_macros': '\n'.join(sorted(set(map(self._unconditional_macro, self._unconditional_entries)))),
200 'conditional_macros': '\n'.join(map(self._conditional_macros, self._entries_by_conditional.keys())),