Home | History | Annotate | Download | only in scripts
      1 # Copyright (C) 2013 Google Inc. All rights reserved.
      2 #
      3 # Redistribution and use in source and binary forms, with or without
      4 # modification, are permitted provided that the following conditions are
      5 # met:
      6 #
      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
     12 # distribution.
     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.
     16 #
     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.
     28 
     29 import os.path
     30 import re
     31 
     32 import in_generator
     33 from in_generator import Maker
     34 import license
     35 
     36 
     37 HEADER_TEMPLATE = """%(license)s
     38 
     39 #ifndef %(class_name)sHeaders_h
     40 #define %(class_name)sHeaders_h
     41 
     42 %(includes)s
     43 
     44 #endif // %(class_name)sHeaders_h
     45 """
     46 
     47 
     48 INTERFACES_HEADER_TEMPLATE = """%(license)s
     49 
     50 #ifndef %(class_name)sInterfaces_h
     51 #define %(class_name)sInterfaces_h
     52 
     53 %(declare_conditional_macros)s
     54 
     55 #define %(macro_style_name)s_INTERFACES_FOR_EACH(macro) \\
     56     \\
     57 %(unconditional_macros)s
     58     \\
     59 %(conditional_macros)s
     60 
     61 #endif // %(class_name)sInterfaces_h
     62 """
     63 
     64 
     65 def _to_macro_style(name):
     66     s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name)
     67     return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).upper()
     68 
     69 
     70 class Writer(in_generator.Writer):
     71     def __init__(self, in_file_path, enabled_conditions):
     72         super(Writer, self).__init__(in_file_path, enabled_conditions)
     73         self.class_name = self.in_file.parameters['namespace'].strip('"')
     74         self._entries_by_conditional = {}
     75         self._unconditional_entries = []
     76         self._sort_entries_by_conditional()
     77         self._outputs = {(self.class_name + "Headers.h"): self.generate_headers_header,
     78                          (self.class_name + "Interfaces.h"): self.generate_interfaces_header,
     79                         }
     80 
     81     def _sort_entries_by_conditional(self):
     82         unconditional_names = set()
     83         for entry in self.in_file.name_dictionaries:
     84             conditional = entry['Conditional']
     85             if not conditional:
     86                 name = self._class_name_for_entry(entry)
     87                 if name in unconditional_names:
     88                     continue
     89                 unconditional_names.add(name)
     90                 self._unconditional_entries.append(entry)
     91                 continue
     92         for entry in self.in_file.name_dictionaries:
     93             name = self._class_name_for_entry(entry)
     94             if name in unconditional_names:
     95                 continue
     96             conditional = entry['Conditional']
     97             if not conditional in self._entries_by_conditional:
     98                 self._entries_by_conditional[conditional] = []
     99             self._entries_by_conditional[conditional].append(entry)
    100 
    101     def _class_name_for_entry(self, entry):
    102         if entry['ImplementedAs']:
    103             return entry['ImplementedAs']
    104         return os.path.basename(entry['name'])
    105 
    106     def _headers_header_include_path(self, entry):
    107         if entry['ImplementedAs']:
    108             path = os.path.dirname(entry['name'])
    109             if len(path):
    110                 path += '/'
    111             path += entry['ImplementedAs']
    112         else:
    113             path = entry['name']
    114         return path + '.h'
    115 
    116     def _headers_header_includes(self, entries):
    117         includes = dict()
    118         for entry in entries:
    119             class_name = self._class_name_for_entry(entry)
    120             # Avoid duplicate includes.
    121             if class_name in includes:
    122                 continue
    123             include = '#include "%(path)s"\n#include "V8%(js_name)s.h"' % {
    124                 'path': self._headers_header_include_path(entry),
    125                 'js_name': os.path.basename(entry['name']),
    126             }
    127             includes[class_name] = self.wrap_with_condition(include, entry['Conditional'])
    128         return includes.values()
    129 
    130     def generate_headers_header(self):
    131         return HEADER_TEMPLATE % {
    132             'license': license.license_for_generated_cpp(),
    133             'class_name': self.class_name,
    134             'includes': '\n'.join(self._headers_header_includes(self.in_file.name_dictionaries)),
    135         }
    136 
    137     def _declare_one_conditional_macro(self, conditional, entries):
    138         macro_name = '%(macro_style_name)s_INTERFACES_FOR_EACH_%(conditional)s' % {
    139             'macro_style_name': _to_macro_style(self.class_name),
    140             'conditional': conditional,
    141         }
    142         return self.wrap_with_condition("""#define %(macro_name)s(macro) \\
    143 %(declarations)s
    144 
    145 #else
    146 #define %(macro_name)s(macro)""" % {
    147             'macro_name': macro_name,
    148             'declarations': '\n'.join(sorted(set([
    149                 '    macro(%(name)s) \\' % {'name': self._class_name_for_entry(entry)}
    150                 for entry in entries]))),
    151         }, conditional)
    152 
    153     def _declare_conditional_macros(self):
    154         return '\n'.join([
    155             self._declare_one_conditional_macro(conditional, entries)
    156             for conditional, entries in self._entries_by_conditional.items()])
    157 
    158     def _unconditional_macro(self, entry):
    159         return '    macro(%(name)s) \\' % {'name': self._class_name_for_entry(entry)}
    160 
    161     def _conditional_macros(self, conditional):
    162         return '    %(macro_style_name)s_INTERFACES_FOR_EACH_%(conditional)s(macro) \\' % {
    163             'macro_style_name': _to_macro_style(self.class_name),
    164             'conditional': conditional,
    165         }
    166 
    167     def generate_interfaces_header(self):
    168         return INTERFACES_HEADER_TEMPLATE % {
    169             'license': license.license_for_generated_cpp(),
    170             'class_name': self.class_name,
    171             'macro_style_name': _to_macro_style(self.class_name),
    172             'declare_conditional_macros': self._declare_conditional_macros(),
    173             'unconditional_macros': '\n'.join(sorted(set(map(self._unconditional_macro, self._unconditional_entries)))),
    174             'conditional_macros': '\n'.join(map(self._conditional_macros, self._entries_by_conditional.keys())),
    175         }
    176