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 30import os.path 31import sys 32 33import in_generator 34import license 35import name_utilities 36import template_expander 37 38 39HEADER_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 50def 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 59class 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 154if __name__ == "__main__": 155 in_generator.Maker(EventFactoryWriter).main(sys.argv) 156