mirror of
				https://bitbucket.org/chromiumembedded/cef
				synced 2025-06-05 21:39:12 +02:00 
			
		
		
		
	
		
			
				
	
	
		
			2114 lines
		
	
	
		
			65 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			2114 lines
		
	
	
		
			65 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| # Copyright (c) 2011 The Chromium Embedded Framework Authors. All rights
 | |
| # reserved. Use of this source code is governed by a BSD-style license that
 | |
| # can be found in the LICENSE file.
 | |
| 
 | |
| from __future__ import absolute_import
 | |
| from date_util import *
 | |
| from file_util import *
 | |
| import os
 | |
| import re
 | |
| import shutil
 | |
| import string
 | |
| import sys
 | |
| import textwrap
 | |
| import time
 | |
| 
 | |
| 
 | |
| def notify(msg):
 | |
|   """ Display a message. """
 | |
|   sys.stdout.write('  NOTE: ' + msg + '\n')
 | |
| 
 | |
| 
 | |
| def wrap_text(text, indent='', maxchars=80):
 | |
|   """ Wrap the text to the specified number of characters. If
 | |
|     necessary a line will be broken and wrapped after a word.
 | |
|     """
 | |
|   result = ''
 | |
|   lines = textwrap.wrap(text, maxchars - len(indent))
 | |
|   for line in lines:
 | |
|     result += indent + line + '\n'
 | |
|   return result
 | |
| 
 | |
| 
 | |
| def is_base_class(clsname):
 | |
|   """ Returns true if |clsname| is a known base (root) class in the object
 | |
|         hierarchy.
 | |
|     """
 | |
|   return clsname == 'CefBaseRefCounted' or clsname == 'CefBaseScoped'
 | |
| 
 | |
| 
 | |
| def get_capi_file_name(cppname):
 | |
|   """ Convert a C++ header file name to a C API header file name. """
 | |
|   return cppname[:-2] + '_capi.h'
 | |
| 
 | |
| 
 | |
| def get_capi_name(cppname, isclassname, prefix=None):
 | |
|   """ Convert a C++ CamelCaps name to a C API underscore name. """
 | |
|   result = ''
 | |
|   lastchr = ''
 | |
|   for chr in cppname:
 | |
|     # add an underscore if the current character is an upper case letter
 | |
|     # and the last character was a lower case letter
 | |
|     if len(result) > 0 and not chr.isdigit() \
 | |
|         and chr.upper() == chr \
 | |
|         and not lastchr.upper() == lastchr:
 | |
|       result += '_'
 | |
|     result += chr.lower()
 | |
|     lastchr = chr
 | |
| 
 | |
|   if isclassname:
 | |
|     result += '_t'
 | |
| 
 | |
|   if not prefix is None:
 | |
|     if prefix[0:3] == 'cef':
 | |
|       # if the prefix name is duplicated in the function name
 | |
|       # remove that portion of the function name
 | |
|       subprefix = prefix[3:]
 | |
|       pos = result.find(subprefix)
 | |
|       if pos >= 0:
 | |
|         result = result[0:pos] + result[pos + len(subprefix):]
 | |
|     result = prefix + '_' + result
 | |
| 
 | |
|   return result
 | |
| 
 | |
| 
 | |
| def get_wrapper_type_enum(cppname):
 | |
|   """ Returns the wrapper type enumeration value for the specified C++ class
 | |
|         name. """
 | |
|   return 'WT_' + get_capi_name(cppname, False)[4:].upper()
 | |
| 
 | |
| 
 | |
| def get_prev_line(body, pos):
 | |
|   """ Retrieve the start and end positions and value for the line immediately
 | |
|     before the line containing the specified position.
 | |
|     """
 | |
|   end = body.rfind('\n', 0, pos)
 | |
|   start = body.rfind('\n', 0, end) + 1
 | |
|   line = body[start:end]
 | |
|   return {'start': start, 'end': end, 'line': line}
 | |
| 
 | |
| 
 | |
| def get_comment(body, name):
 | |
|   """ Retrieve the comment for a class or function. """
 | |
|   result = []
 | |
| 
 | |
|   pos = body.find(name)
 | |
|   in_block_comment = False
 | |
|   while pos > 0:
 | |
|     data = get_prev_line(body, pos)
 | |
|     line = data['line'].strip()
 | |
|     pos = data['start']
 | |
|     if len(line) == 0:
 | |
|       # check if the next previous line is a comment
 | |
|       prevdata = get_prev_line(body, pos)
 | |
|       prevline = prevdata['line'].strip()
 | |
|       if prevline[0:2] == '//' and prevline[0:3] != '///':
 | |
|         result.append(None)
 | |
|       else:
 | |
|         break
 | |
|     # single line /*--cef()--*/
 | |
|     elif line[0:2] == '/*' and line[-2:] == '*/':
 | |
|       continue
 | |
|     # start of multi line /*--cef()--*/
 | |
|     elif in_block_comment and line[0:2] == '/*':
 | |
|       in_block_comment = False
 | |
|       continue
 | |
|     # end of multi line /*--cef()--*/
 | |
|     elif not in_block_comment and line[-2:] == '*/':
 | |
|       in_block_comment = True
 | |
|       continue
 | |
|     elif in_block_comment:
 | |
|       continue
 | |
|     elif line[0:2] == '//':
 | |
|       # keep the comment line including any leading spaces
 | |
|       result.append(line[2:])
 | |
|     else:
 | |
|       break
 | |
| 
 | |
|   result.reverse()
 | |
|   return result
 | |
| 
 | |
| 
 | |
| def validate_comment(file, name, comment):
 | |
|   """ Validate the comment array returned by get_comment(). """
 | |
|   # Verify that the comment contains beginning and ending '///' as required by
 | |
|   # CppDoc (the leading '//' from each line will already have been removed by
 | |
|   # the get_comment() logic). There may be additional comments proceeding the
 | |
|   # CppDoc block so we look at the quantity of lines equaling '/' and expect
 | |
|   # the last line to be '/'.
 | |
|   docct = 0
 | |
|   for line in comment:
 | |
|     if not line is None and len(line) > 0 and line == '/':
 | |
|       docct = docct + 1
 | |
|   if docct != 2 or len(comment) < 3 or comment[len(comment) - 1] != '/':
 | |
|     raise Exception('Missing or incorrect comment in %s for: %s' % \
 | |
|         (file, name))
 | |
| 
 | |
| 
 | |
| def format_comment(comment, indent, translate_map=None, maxchars=80):
 | |
|   """ Return the comments array as a formatted string. """
 | |
|   if not translate_map is None:
 | |
|     # Replace longest keys first in translation.
 | |
|     translate_keys = sorted(
 | |
|         translate_map.keys(), key=lambda item: (-len(item), item))
 | |
| 
 | |
|   result = ''
 | |
|   wrapme = ''
 | |
|   hasemptyline = False
 | |
|   for line in comment:
 | |
|     # if the line starts with a leading space, remove that space
 | |
|     if not line is None and len(line) > 0 and line[0:1] == ' ':
 | |
|       line = line[1:]
 | |
|       didremovespace = True
 | |
|     else:
 | |
|       didremovespace = False
 | |
| 
 | |
|     if line is None or len(line) == 0 or line[0:1] == ' ' \
 | |
|         or line[0:1] == '/':
 | |
|       # the previous paragraph, if any, has ended
 | |
|       if len(wrapme) > 0:
 | |
|         if not translate_map is None:
 | |
|           # apply the translation
 | |
|           for key in translate_keys:
 | |
|             wrapme = wrapme.replace(key, translate_map[key])
 | |
|         # output the previous paragraph
 | |
|         result += wrap_text(wrapme, indent + '// ', maxchars)
 | |
|         wrapme = ''
 | |
| 
 | |
|     if not line is None:
 | |
|       if len(line) == 0 or line[0:1] == ' ' or line[0:1] == '/':
 | |
|         # blank lines or anything that's further indented should be
 | |
|         # output as-is
 | |
|         result += indent + '//'
 | |
|         if len(line) > 0:
 | |
|           if didremovespace:
 | |
|             result += ' ' + line
 | |
|           else:
 | |
|             result += line
 | |
|         result += '\n'
 | |
|       else:
 | |
|         # add to the current paragraph
 | |
|         wrapme += line + ' '
 | |
|     else:
 | |
|       # output an empty line
 | |
|       hasemptyline = True
 | |
|       result += '\n'
 | |
| 
 | |
|   if len(wrapme) > 0:
 | |
|     if not translate_map is None:
 | |
|       # apply the translation
 | |
|       for key in translate_map.keys():
 | |
|         wrapme = wrapme.replace(key, translate_map[key])
 | |
|     # output the previous paragraph
 | |
|     result += wrap_text(wrapme, indent + '// ', maxchars)
 | |
| 
 | |
|   if hasemptyline:
 | |
|     # an empty line means a break between comments, so the comment is
 | |
|     # probably a section heading and should have an extra line before it
 | |
|     result = '\n' + result
 | |
|   return result
 | |
| 
 | |
| 
 | |
| def format_translation_changes(old, new):
 | |
|   """ Return a comment stating what is different between the old and new
 | |
|     function prototype parts.
 | |
|     """
 | |
|   changed = False
 | |
|   result = ''
 | |
| 
 | |
|   # normalize C API attributes
 | |
|   oldargs = [x.replace('struct _', '') for x in old['args']]
 | |
|   oldretval = old['retval'].replace('struct _', '')
 | |
|   newargs = [x.replace('struct _', '') for x in new['args']]
 | |
|   newretval = new['retval'].replace('struct _', '')
 | |
| 
 | |
|   # check if the prototype has changed
 | |
|   oldset = set(oldargs)
 | |
|   newset = set(newargs)
 | |
|   if len(oldset.symmetric_difference(newset)) > 0:
 | |
|     changed = True
 | |
|     result += '\n  // WARNING - CHANGED ATTRIBUTES'
 | |
| 
 | |
|     # in the implementation set only
 | |
|     oldonly = oldset.difference(newset)
 | |
|     for arg in oldonly:
 | |
|       result += '\n  //   REMOVED: ' + arg
 | |
| 
 | |
|     # in the current set only
 | |
|     newonly = newset.difference(oldset)
 | |
|     for arg in newonly:
 | |
|       result += '\n  //   ADDED:   ' + arg
 | |
| 
 | |
|   # check if the return value has changed
 | |
|   if oldretval != newretval:
 | |
|     changed = True
 | |
|     result += '\n  // WARNING - CHANGED RETURN VALUE'+ \
 | |
|               '\n  //   WAS: '+old['retval']+ \
 | |
|               '\n  //   NOW: '+new['retval']
 | |
| 
 | |
|   if changed:
 | |
|     result += '\n  #pragma message("Warning: "__FILE__": '+new['name']+ \
 | |
|               ' prototype has changed")\n'
 | |
| 
 | |
|   return result
 | |
| 
 | |
| 
 | |
| def format_translation_includes(header, body):
 | |
|   """ Return the necessary list of includes based on the contents of the
 | |
|     body.
 | |
|     """
 | |
|   result = ''
 | |
| 
 | |
|   # <algorithm> required for VS2013.
 | |
|   if body.find('std::min') > 0 or body.find('std::max') > 0:
 | |
|     result += '#include <algorithm>\n'
 | |
| 
 | |
|   if body.find('cef_api_hash(') > 0:
 | |
|     result += '#include "include/cef_api_hash.h"\n'
 | |
| 
 | |
|   # identify what CppToC classes are being used
 | |
|   p = re.compile('([A-Za-z0-9_]{1,})CppToC')
 | |
|   list = sorted(set(p.findall(body)))
 | |
|   for item in list:
 | |
|     directory = ''
 | |
|     if not is_base_class(item):
 | |
|       cls = header.get_class(item)
 | |
|       dir = cls.get_file_directory()
 | |
|       if not dir is None:
 | |
|         directory = dir + '/'
 | |
|     result += '#include "libcef_dll/cpptoc/'+directory+ \
 | |
|               get_capi_name(item[3:], False)+'_cpptoc.h"\n'
 | |
| 
 | |
|   # identify what CToCpp classes are being used
 | |
|   p = re.compile('([A-Za-z0-9_]{1,})CToCpp')
 | |
|   list = sorted(set(p.findall(body)))
 | |
|   for item in list:
 | |
|     directory = ''
 | |
|     if not is_base_class(item):
 | |
|       cls = header.get_class(item)
 | |
|       dir = cls.get_file_directory()
 | |
|       if not dir is None:
 | |
|         directory = dir + '/'
 | |
|     result += '#include "libcef_dll/ctocpp/'+directory+ \
 | |
|               get_capi_name(item[3:], False)+'_ctocpp.h"\n'
 | |
| 
 | |
|   if body.find('shutdown_checker') > 0:
 | |
|     result += '#include "libcef_dll/shutdown_checker.h"\n'
 | |
| 
 | |
|   if body.find('transfer_') > 0:
 | |
|     result += '#include "libcef_dll/transfer_util.h"\n'
 | |
| 
 | |
|   return result
 | |
| 
 | |
| 
 | |
| def str_to_dict(str):
 | |
|   """ Convert a string to a dictionary. If the same key has multiple values
 | |
|         the values will be stored in a list. """
 | |
|   dict = {}
 | |
|   parts = str.split(',')
 | |
|   for part in parts:
 | |
|     part = part.strip()
 | |
|     if len(part) == 0:
 | |
|       continue
 | |
|     sparts = part.split('=')
 | |
|     if len(sparts) > 2:
 | |
|       raise Exception('Invalid dictionary pair format: ' + part)
 | |
|     name = sparts[0].strip()
 | |
|     if len(sparts) == 2:
 | |
|       val = sparts[1].strip()
 | |
|     else:
 | |
|       val = True
 | |
|     if name in dict:
 | |
|       # a value with this name already exists
 | |
|       curval = dict[name]
 | |
|       if not isinstance(curval, list):
 | |
|         # convert the string value to a list
 | |
|         dict[name] = [curval]
 | |
|       dict[name].append(val)
 | |
|     else:
 | |
|       dict[name] = val
 | |
|   return dict
 | |
| 
 | |
| 
 | |
| def dict_to_str(dict):
 | |
|   """ Convert a dictionary to a string. """
 | |
|   str = []
 | |
|   for name in dict.keys():
 | |
|     if not isinstance(dict[name], list):
 | |
|       if dict[name] is True:
 | |
|         # currently a bool value
 | |
|         str.append(name)
 | |
|       else:
 | |
|         # currently a string value
 | |
|         str.append(name + '=' + dict[name])
 | |
|     else:
 | |
|       # currently a list value
 | |
|       for val in dict[name]:
 | |
|         str.append(name + '=' + val)
 | |
|   return ','.join(str)
 | |
| 
 | |
| 
 | |
| # regex for matching comment-formatted attributes
 | |
| _cre_attrib = '/\*--cef\(([A-Za-z0-9_ ,=:\n]{0,})\)--\*/'
 | |
| # regex for matching class and function names
 | |
| _cre_cfname = '([A-Za-z0-9_]{1,})'
 | |
| # regex for matching class and function names including path separators
 | |
| _cre_cfnameorpath = '([A-Za-z0-9_\/]{1,})'
 | |
| # regex for matching function return values
 | |
| _cre_retval = '([A-Za-z0-9_<>:,\*\&]{1,})'
 | |
| # regex for matching typedef value and name combination
 | |
| _cre_typedef = '([A-Za-z0-9_<>:,\*\&\s]{1,})'
 | |
| # regex for matching function return value and name combination
 | |
| _cre_func = '([A-Za-z][A-Za-z0-9_<>:,\*\&\s]{1,})'
 | |
| # regex for matching virtual function modifiers + arbitrary whitespace
 | |
| _cre_vfmod = '([\sA-Za-z0-9_]{0,})'
 | |
| # regex for matching arbitrary whitespace
 | |
| _cre_space = '[\s]{1,}'
 | |
| # regex for matching optional virtual keyword
 | |
| _cre_virtual = '(?:[\s]{1,}virtual){0,1}'
 | |
| 
 | |
| # Simple translation types. Format is:
 | |
| #   'cpp_type' : ['capi_type', 'capi_default_value']
 | |
| _simpletypes = {
 | |
|     'void': ['void', ''],
 | |
|     'void*': ['void*', 'NULL'],
 | |
|     'int': ['int', '0'],
 | |
|     'int16': ['int16', '0'],
 | |
|     'uint16': ['uint16', '0'],
 | |
|     'int32': ['int32', '0'],
 | |
|     'uint32': ['uint32', '0'],
 | |
|     'int64': ['int64', '0'],
 | |
|     'uint64': ['uint64', '0'],
 | |
|     'double': ['double', '0'],
 | |
|     'float': ['float', '0'],
 | |
|     'long': ['long', '0'],
 | |
|     'unsigned long': ['unsigned long', '0'],
 | |
|     'long long': ['long long', '0'],
 | |
|     'size_t': ['size_t', '0'],
 | |
|     'bool': ['int', '0'],
 | |
|     'char': ['char', '0'],
 | |
|     'char* const': ['char* const', 'NULL'],
 | |
|     'cef_color_t': ['cef_color_t', '0'],
 | |
|     'cef_json_parser_error_t': ['cef_json_parser_error_t', 'JSON_NO_ERROR'],
 | |
|     'cef_plugin_policy_t': ['cef_plugin_policy_t', 'PLUGIN_POLICY_ALLOW'],
 | |
|     'CefCursorHandle': ['cef_cursor_handle_t', 'kNullCursorHandle'],
 | |
|     'CefCompositionUnderline': [
 | |
|         'cef_composition_underline_t', 'CefCompositionUnderline()'
 | |
|     ],
 | |
|     'CefEventHandle': ['cef_event_handle_t', 'kNullEventHandle'],
 | |
|     'CefWindowHandle': ['cef_window_handle_t', 'kNullWindowHandle'],
 | |
|     'CefPoint': ['cef_point_t', 'CefPoint()'],
 | |
|     'CefRect': ['cef_rect_t', 'CefRect()'],
 | |
|     'CefSize': ['cef_size_t', 'CefSize()'],
 | |
|     'CefRange': ['cef_range_t', 'CefRange()'],
 | |
|     'CefDraggableRegion': ['cef_draggable_region_t', 'CefDraggableRegion()'],
 | |
|     'CefThreadId': ['cef_thread_id_t', 'TID_UI'],
 | |
|     'CefTime': ['cef_time_t', 'CefTime()'],
 | |
| }
 | |
| 
 | |
| 
 | |
| def get_function_impls(content, ident, has_impl=True):
 | |
|   """ Retrieve the function parts from the specified contents as a set of
 | |
|     return value, name, arguments and body. Ident must occur somewhere in
 | |
|     the value.
 | |
|     """
 | |
|   # extract the functions
 | |
|   find_regex = '\n' + _cre_func + '\((.*?)\)([A-Za-z0-9_\s]{0,})'
 | |
|   if has_impl:
 | |
|     find_regex += '\{(.*?)\n\}'
 | |
|   else:
 | |
|     find_regex += '(;)'
 | |
|   p = re.compile(find_regex, re.MULTILINE | re.DOTALL)
 | |
|   list = p.findall(content)
 | |
| 
 | |
|   # build the function map with the function name as the key
 | |
|   result = []
 | |
|   for retval, argval, vfmod, body in list:
 | |
|     if retval.find(ident) < 0:
 | |
|       # the identifier was not found
 | |
|       continue
 | |
| 
 | |
|     # remove the identifier
 | |
|     retval = retval.replace(ident, '')
 | |
|     retval = retval.strip()
 | |
| 
 | |
|     # Normalize the delimiter.
 | |
|     retval = retval.replace('\n', ' ')
 | |
| 
 | |
|     # retrieve the function name
 | |
|     parts = retval.split(' ')
 | |
|     name = parts[-1]
 | |
|     del parts[-1]
 | |
|     retval = ' '.join(parts)
 | |
| 
 | |
|     # parse the arguments
 | |
|     args = []
 | |
|     for v in argval.split(','):
 | |
|       v = v.strip()
 | |
|       if len(v) > 0:
 | |
|         args.append(v)
 | |
| 
 | |
|     result.append({
 | |
|         'retval': retval.strip(),
 | |
|         'name': name,
 | |
|         'args': args,
 | |
|         'vfmod': vfmod.strip(),
 | |
|         'body': body if has_impl else '',
 | |
|     })
 | |
| 
 | |
|   return result
 | |
| 
 | |
| 
 | |
| def get_next_function_impl(existing, name):
 | |
|   result = None
 | |
|   for item in existing:
 | |
|     if item['name'] == name:
 | |
|       result = item
 | |
|       existing.remove(item)
 | |
|       break
 | |
|   return result
 | |
| 
 | |
| 
 | |
| def get_copyright(full=False):
 | |
|   if full:
 | |
|     result = \
 | |
| """// Copyright (c) $YEAR$ Marshall A. Greenblatt. All rights reserved.
 | |
| //
 | |
| // Redistribution and use in source and binary forms, with or without
 | |
| // modification, are permitted provided that the following conditions are
 | |
| // met:
 | |
| //
 | |
| //    * Redistributions of source code must retain the above copyright
 | |
| // notice, this list of conditions and the following disclaimer.
 | |
| //    * Redistributions in binary form must reproduce the above
 | |
| // copyright notice, this list of conditions and the following disclaimer
 | |
| // in the documentation and/or other materials provided with the
 | |
| // distribution.
 | |
| //    * Neither the name of Google Inc. nor the name Chromium Embedded
 | |
| // Framework nor the names of its contributors may be used to endorse
 | |
| // or promote products derived from this software without specific prior
 | |
| // written permission.
 | |
| //
 | |
| // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | |
| // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | |
| // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | |
| // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | |
| // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | |
| // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | |
| // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | |
| // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | |
| // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | |
| // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | |
| // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | |
| """
 | |
|   else:
 | |
|     result = \
 | |
| """// Copyright (c) $YEAR$ The Chromium Embedded Framework Authors. All rights
 | |
| // reserved. Use of this source code is governed by a BSD-style license that
 | |
| // can be found in the LICENSE file.
 | |
| """
 | |
| 
 | |
|   result += \
 | |
| """//
 | |
| // ---------------------------------------------------------------------------
 | |
| //
 | |
| // This file was generated by the CEF translator tool. If making changes by
 | |
| // hand only do so within the body of existing method and function
 | |
| // implementations. See the translator.README.txt file in the tools directory
 | |
| // for more information.
 | |
| //
 | |
| // $hash=$$HASH$$$
 | |
| //
 | |
| 
 | |
| """
 | |
|   # add the copyright year
 | |
|   return result.replace('$YEAR$', get_year())
 | |
| 
 | |
| 
 | |
| class obj_header:
 | |
|   """ Class representing a C++ header file. """
 | |
| 
 | |
|   def __init__(self):
 | |
|     self.filenames = []
 | |
|     self.typedefs = []
 | |
|     self.funcs = []
 | |
|     self.classes = []
 | |
|     self.root_directory = None
 | |
| 
 | |
|   def set_root_directory(self, root_directory):
 | |
|     """ Set the root directory. """
 | |
|     self.root_directory = root_directory
 | |
| 
 | |
|   def get_root_directory(self):
 | |
|     """ Get the root directory. """
 | |
|     return self.root_directory
 | |
| 
 | |
|   def add_directory(self, directory, excluded_files=[]):
 | |
|     """ Add all header files from the specified directory. """
 | |
|     files = get_files(os.path.join(directory, '*.h'))
 | |
|     for file in files:
 | |
|       if len(excluded_files) == 0 or \
 | |
|           not os.path.split(file)[1] in excluded_files:
 | |
|         self.add_file(file)
 | |
| 
 | |
|   def add_file(self, filepath):
 | |
|     """ Add a header file. """
 | |
| 
 | |
|     if self.root_directory is None:
 | |
|       filename = os.path.split(filepath)[1]
 | |
|     else:
 | |
|       filename = os.path.relpath(filepath, self.root_directory)
 | |
|       filename = filename.replace('\\', '/')
 | |
| 
 | |
|     # read the input file into memory
 | |
|     self.add_data(filename, read_file(filepath))
 | |
| 
 | |
|   def add_data(self, filename, data):
 | |
|     """ Add header file contents. """
 | |
| 
 | |
|     added = False
 | |
| 
 | |
|     # remove space from between template definition end brackets
 | |
|     data = data.replace("> >", ">>")
 | |
| 
 | |
|     # extract global typedefs
 | |
|     p = re.compile('\ntypedef' + _cre_space + _cre_typedef + ';',
 | |
|                    re.MULTILINE | re.DOTALL)
 | |
|     list = p.findall(data)
 | |
|     if len(list) > 0:
 | |
|       # build the global typedef objects
 | |
|       for value in list:
 | |
|         pos = value.rfind(' ')
 | |
|         if pos < 0:
 | |
|           raise Exception('Invalid typedef: ' + value)
 | |
|         alias = value[pos + 1:].strip()
 | |
|         value = value[:pos].strip()
 | |
|         self.typedefs.append(obj_typedef(self, filename, value, alias))
 | |
| 
 | |
|     # extract global functions
 | |
|     p = re.compile('\n' + _cre_attrib + '\n' + _cre_func + '\((.*?)\)',
 | |
|                    re.MULTILINE | re.DOTALL)
 | |
|     list = p.findall(data)
 | |
|     if len(list) > 0:
 | |
|       added = True
 | |
| 
 | |
|       # build the global function objects
 | |
|       for attrib, retval, argval in list:
 | |
|         comment = get_comment(data, retval + '(' + argval + ');')
 | |
|         validate_comment(filename, retval, comment)
 | |
|         self.funcs.append(
 | |
|             obj_function(self, filename, attrib, retval, argval, comment))
 | |
| 
 | |
|     # extract includes
 | |
|     p = re.compile('\n#include \"include/' + _cre_cfnameorpath + '.h')
 | |
|     includes = p.findall(data)
 | |
| 
 | |
|     # extract forward declarations
 | |
|     p = re.compile('\nclass' + _cre_space + _cre_cfname + ';')
 | |
|     forward_declares = p.findall(data)
 | |
| 
 | |
|     # extract empty classes
 | |
|     p = re.compile('\n' + _cre_attrib + '\nclass' + _cre_space + _cre_cfname +
 | |
|                    _cre_space + ':' + _cre_space + 'public' + _cre_virtual +
 | |
|                    _cre_space + _cre_cfname + _cre_space + '{};',
 | |
|                    re.MULTILINE | re.DOTALL)
 | |
|     list = p.findall(data)
 | |
|     if len(list) > 0:
 | |
|       added = True
 | |
| 
 | |
|       # build the class objects
 | |
|       for attrib, name, parent_name in list:
 | |
|         # Style may place the ':' on the next line.
 | |
|         comment = get_comment(data, name + ' :')
 | |
|         if len(comment) == 0:
 | |
|           comment = get_comment(data, name + "\n")
 | |
|         validate_comment(filename, name, comment)
 | |
|         self.classes.append(
 | |
|             obj_class(self, filename, attrib, name, parent_name, "", comment,
 | |
|                       includes, forward_declares))
 | |
| 
 | |
|       # Remove empty classes from |data| so we don't mess up the non-empty
 | |
|       # class search that follows.
 | |
|       data = p.sub('', data)
 | |
| 
 | |
|     # extract classes
 | |
|     p = re.compile('\n' + _cre_attrib + '\nclass' + _cre_space + _cre_cfname +
 | |
|                    _cre_space + ':' + _cre_space + 'public' + _cre_virtual +
 | |
|                    _cre_space + _cre_cfname + _cre_space + '{(.*?)\n};',
 | |
|                    re.MULTILINE | re.DOTALL)
 | |
|     list = p.findall(data)
 | |
|     if len(list) > 0:
 | |
|       added = True
 | |
| 
 | |
|       # build the class objects
 | |
|       for attrib, name, parent_name, body in list:
 | |
|         # Style may place the ':' on the next line.
 | |
|         comment = get_comment(data, name + ' :')
 | |
|         if len(comment) == 0:
 | |
|           comment = get_comment(data, name + "\n")
 | |
|         validate_comment(filename, name, comment)
 | |
|         self.classes.append(
 | |
|             obj_class(self, filename, attrib, name, parent_name, body, comment,
 | |
|                       includes, forward_declares))
 | |
| 
 | |
|     if added:
 | |
|       # a global function or class was read from the header file
 | |
|       self.filenames.append(filename)
 | |
| 
 | |
|   def __repr__(self):
 | |
|     result = ''
 | |
| 
 | |
|     if len(self.typedefs) > 0:
 | |
|       strlist = []
 | |
|       for cls in self.typedefs:
 | |
|         strlist.append(str(cls))
 | |
|       result += "\n".join(strlist) + "\n\n"
 | |
| 
 | |
|     if len(self.funcs) > 0:
 | |
|       strlist = []
 | |
|       for cls in self.funcs:
 | |
|         strlist.append(str(cls))
 | |
|       result += "\n".join(strlist) + "\n\n"
 | |
| 
 | |
|     if len(self.classes) > 0:
 | |
|       strlist = []
 | |
|       for cls in self.classes:
 | |
|         strlist.append(str(cls))
 | |
|       result += "\n".join(strlist)
 | |
| 
 | |
|     return result
 | |
| 
 | |
|   def get_file_names(self):
 | |
|     """ Return the array of header file names. """
 | |
|     return self.filenames
 | |
| 
 | |
|   def get_typedefs(self):
 | |
|     """ Return the array of typedef objects. """
 | |
|     return self.typedefs
 | |
| 
 | |
|   def get_funcs(self, filename=None):
 | |
|     """ Return the array of function objects. """
 | |
|     if filename is None:
 | |
|       return self.funcs
 | |
|     else:
 | |
|       # only return the functions in the specified file
 | |
|       res = []
 | |
|       for func in self.funcs:
 | |
|         if func.get_file_name() == filename:
 | |
|           res.append(func)
 | |
|       return res
 | |
| 
 | |
|   def get_classes(self, filename=None):
 | |
|     """ Return the array of class objects. """
 | |
|     if filename is None:
 | |
|       return self.classes
 | |
|     else:
 | |
|       # only return the classes in the specified file
 | |
|       res = []
 | |
|       for cls in self.classes:
 | |
|         if cls.get_file_name() == filename:
 | |
|           res.append(cls)
 | |
|       return res
 | |
| 
 | |
|   def get_class(self, classname, defined_structs=None):
 | |
|     """ Return the specified class or None if not found. """
 | |
|     for cls in self.classes:
 | |
|       if cls.get_name() == classname:
 | |
|         return cls
 | |
|       elif not defined_structs is None:
 | |
|         defined_structs.append(cls.get_capi_name())
 | |
|     return None
 | |
| 
 | |
|   def get_class_names(self):
 | |
|     """ Returns the names of all classes in this object. """
 | |
|     result = []
 | |
|     for cls in self.classes:
 | |
|       result.append(cls.get_name())
 | |
|     return result
 | |
| 
 | |
|   def get_base_class_name(self, classname):
 | |
|     """ Returns the base (root) class name for |classname|. """
 | |
|     cur_cls = self.get_class(classname)
 | |
|     while True:
 | |
|       parent_name = cur_cls.get_parent_name()
 | |
|       if is_base_class(parent_name):
 | |
|         return parent_name
 | |
|       else:
 | |
|         parent_cls = self.get_class(parent_name)
 | |
|         if parent_cls is None:
 | |
|           break
 | |
|       cur_cls = self.get_class(parent_name)
 | |
|     return None
 | |
| 
 | |
|   def get_types(self, list):
 | |
|     """ Return a dictionary mapping data types to analyzed values. """
 | |
|     for cls in self.typedefs:
 | |
|       cls.get_types(list)
 | |
| 
 | |
|     for cls in self.classes:
 | |
|       cls.get_types(list)
 | |
| 
 | |
|   def get_alias_translation(self, alias):
 | |
|     """ Return a translation of alias to value based on typedef
 | |
|             statements. """
 | |
|     for cls in self.typedefs:
 | |
|       if cls.alias == alias:
 | |
|         return cls.value
 | |
|     return None
 | |
| 
 | |
|   def get_analysis(self, value, named=True):
 | |
|     """ Return an analysis of the value based the header file context. """
 | |
|     return obj_analysis([self], value, named)
 | |
| 
 | |
|   def get_defined_structs(self):
 | |
|     """ Return a list of already defined structure names. """
 | |
|     return [
 | |
|         'cef_print_info_t', 'cef_window_info_t', 'cef_base_ref_counted_t',
 | |
|         'cef_base_scoped_t'
 | |
|     ]
 | |
| 
 | |
|   def get_capi_translations(self):
 | |
|     """ Return a dictionary that maps C++ terminology to C API terminology.
 | |
|         """
 | |
|     # strings that will be changed in C++ comments
 | |
|     map = {
 | |
|         'class': 'structure',
 | |
|         'Class': 'Structure',
 | |
|         'interface': 'structure',
 | |
|         'Interface': 'Structure',
 | |
|         'true': 'true (1)',
 | |
|         'false': 'false (0)',
 | |
|         'empty': 'NULL',
 | |
|         'method': 'function'
 | |
|     }
 | |
| 
 | |
|     # add mappings for all classes and functions
 | |
|     funcs = self.get_funcs()
 | |
|     for func in funcs:
 | |
|       map[func.get_name() + '()'] = func.get_capi_name() + '()'
 | |
| 
 | |
|     classes = self.get_classes()
 | |
|     for cls in classes:
 | |
|       map[cls.get_name()] = cls.get_capi_name()
 | |
| 
 | |
|       funcs = cls.get_virtual_funcs()
 | |
|       for func in funcs:
 | |
|         map[func.get_name() + '()'] = func.get_capi_name() + '()'
 | |
| 
 | |
|       funcs = cls.get_static_funcs()
 | |
|       for func in funcs:
 | |
|         map[func.get_name() + '()'] = func.get_capi_name() + '()'
 | |
| 
 | |
|     return map
 | |
| 
 | |
| 
 | |
| class obj_class:
 | |
|   """ Class representing a C++ class. """
 | |
| 
 | |
|   def __init__(self, parent, filename, attrib, name, parent_name, body, comment,
 | |
|                includes, forward_declares):
 | |
|     if not isinstance(parent, obj_header):
 | |
|       raise Exception('Invalid parent object type')
 | |
| 
 | |
|     self.parent = parent
 | |
|     self.filename = filename
 | |
|     self.attribs = str_to_dict(attrib)
 | |
|     self.name = name
 | |
|     self.parent_name = parent_name
 | |
|     self.comment = comment
 | |
|     self.includes = includes
 | |
|     self.forward_declares = forward_declares
 | |
| 
 | |
|     # extract typedefs
 | |
|     p = re.compile(
 | |
|         '\n' + _cre_space + 'typedef' + _cre_space + _cre_typedef + ';',
 | |
|         re.MULTILINE | re.DOTALL)
 | |
|     list = p.findall(body)
 | |
| 
 | |
|     # build the typedef objects
 | |
|     self.typedefs = []
 | |
|     for value in list:
 | |
|       pos = value.rfind(' ')
 | |
|       if pos < 0:
 | |
|         raise Exception('Invalid typedef: ' + value)
 | |
|       alias = value[pos + 1:].strip()
 | |
|       value = value[:pos].strip()
 | |
|       self.typedefs.append(obj_typedef(self, filename, value, alias))
 | |
| 
 | |
|     # extract static functions
 | |
|     p = re.compile('\n' + _cre_space + _cre_attrib + '\n' + _cre_space +
 | |
|                    'static' + _cre_space + _cre_func + '\((.*?)\)',
 | |
|                    re.MULTILINE | re.DOTALL)
 | |
|     list = p.findall(body)
 | |
| 
 | |
|     # build the static function objects
 | |
|     self.staticfuncs = []
 | |
|     for attrib, retval, argval in list:
 | |
|       comment = get_comment(body, retval + '(' + argval + ')')
 | |
|       validate_comment(filename, retval, comment)
 | |
|       self.staticfuncs.append(
 | |
|           obj_function_static(self, attrib, retval, argval, comment))
 | |
| 
 | |
|     # extract virtual functions
 | |
|     p = re.compile(
 | |
|         '\n' + _cre_space + _cre_attrib + '\n' + _cre_space + 'virtual' +
 | |
|         _cre_space + _cre_func + '\((.*?)\)' + _cre_vfmod,
 | |
|         re.MULTILINE | re.DOTALL)
 | |
|     list = p.findall(body)
 | |
| 
 | |
|     # build the virtual function objects
 | |
|     self.virtualfuncs = []
 | |
|     for attrib, retval, argval, vfmod in list:
 | |
|       comment = get_comment(body, retval + '(' + argval + ')')
 | |
|       validate_comment(filename, retval, comment)
 | |
|       self.virtualfuncs.append(
 | |
|           obj_function_virtual(self, attrib, retval, argval, comment,
 | |
|                                vfmod.strip()))
 | |
| 
 | |
|   def __repr__(self):
 | |
|     result = '/* ' + dict_to_str(
 | |
|         self.attribs) + ' */ class ' + self.name + "\n{"
 | |
| 
 | |
|     if len(self.typedefs) > 0:
 | |
|       result += "\n\t"
 | |
|       strlist = []
 | |
|       for cls in self.typedefs:
 | |
|         strlist.append(str(cls))
 | |
|       result += "\n\t".join(strlist)
 | |
| 
 | |
|     if len(self.staticfuncs) > 0:
 | |
|       result += "\n\t"
 | |
|       strlist = []
 | |
|       for cls in self.staticfuncs:
 | |
|         strlist.append(str(cls))
 | |
|       result += "\n\t".join(strlist)
 | |
| 
 | |
|     if len(self.virtualfuncs) > 0:
 | |
|       result += "\n\t"
 | |
|       strlist = []
 | |
|       for cls in self.virtualfuncs:
 | |
|         strlist.append(str(cls))
 | |
|       result += "\n\t".join(strlist)
 | |
| 
 | |
|     result += "\n};\n"
 | |
|     return result
 | |
| 
 | |
|   def get_file_name(self):
 | |
|     """ Return the C++ header file name. Includes the directory component,
 | |
|             if any. """
 | |
|     return self.filename
 | |
| 
 | |
|   def get_capi_file_name(self):
 | |
|     """ Return the CAPI header file name. Includes the directory component,
 | |
|             if any. """
 | |
|     return get_capi_file_name(self.filename)
 | |
| 
 | |
|   def get_file_directory(self):
 | |
|     """ Return the file directory component, if any. """
 | |
|     pos = self.filename.rfind('/')
 | |
|     if pos >= 0:
 | |
|       return self.filename[:pos]
 | |
|     return None
 | |
| 
 | |
|   def get_name(self):
 | |
|     """ Return the class name. """
 | |
|     return self.name
 | |
| 
 | |
|   def get_capi_name(self):
 | |
|     """ Return the CAPI structure name for this class. """
 | |
|     return get_capi_name(self.name, True)
 | |
| 
 | |
|   def get_parent_name(self):
 | |
|     """ Return the parent class name. """
 | |
|     return self.parent_name
 | |
| 
 | |
|   def get_parent_capi_name(self):
 | |
|     """ Return the CAPI structure name for the parent class. """
 | |
|     return get_capi_name(self.parent_name, True)
 | |
| 
 | |
|   def has_parent(self, parent_name):
 | |
|     """ Returns true if this class has the specified class anywhere in its
 | |
|             inheritance hierarchy. """
 | |
|     # Every class has a known base class as the top-most parent.
 | |
|     if is_base_class(parent_name) or parent_name == self.parent_name:
 | |
|       return True
 | |
|     if is_base_class(self.parent_name):
 | |
|       return False
 | |
| 
 | |
|     cur_cls = self.parent.get_class(self.parent_name)
 | |
|     while True:
 | |
|       cur_parent_name = cur_cls.get_parent_name()
 | |
|       if is_base_class(cur_parent_name):
 | |
|         break
 | |
|       elif cur_parent_name == parent_name:
 | |
|         return True
 | |
|       cur_cls = self.parent.get_class(cur_parent_name)
 | |
| 
 | |
|     return False
 | |
| 
 | |
|   def get_comment(self):
 | |
|     """ Return the class comment as an array of lines. """
 | |
|     return self.comment
 | |
| 
 | |
|   def get_includes(self):
 | |
|     """ Return the list of classes that are included from this class'
 | |
|             header file. """
 | |
|     return self.includes
 | |
| 
 | |
|   def get_forward_declares(self):
 | |
|     """ Return the list of classes that are forward declared for this
 | |
|             class. """
 | |
|     return self.forward_declares
 | |
| 
 | |
|   def get_attribs(self):
 | |
|     """ Return all attributes as a dictionary. """
 | |
|     return self.attribs
 | |
| 
 | |
|   def has_attrib(self, name):
 | |
|     """ Return true if the specified attribute exists. """
 | |
|     return name in self.attribs
 | |
| 
 | |
|   def get_attrib(self, name):
 | |
|     """ Return the first or only value for specified attribute. """
 | |
|     if name in self.attribs:
 | |
|       if isinstance(self.attribs[name], list):
 | |
|         # the value is a list
 | |
|         return self.attribs[name][0]
 | |
|       else:
 | |
|         # the value is a string
 | |
|         return self.attribs[name]
 | |
|     return None
 | |
| 
 | |
|   def get_attrib_list(self, name):
 | |
|     """ Return all values for specified attribute as a list. """
 | |
|     if name in self.attribs:
 | |
|       if isinstance(self.attribs[name], list):
 | |
|         # the value is already a list
 | |
|         return self.attribs[name]
 | |
|       else:
 | |
|         # convert the value to a list
 | |
|         return [self.attribs[name]]
 | |
|     return None
 | |
| 
 | |
|   def get_typedefs(self):
 | |
|     """ Return the array of typedef objects. """
 | |
|     return self.typedefs
 | |
| 
 | |
|   def has_typedef_alias(self, alias):
 | |
|     """ Returns true if the specified typedef alias is defined in the scope
 | |
|             of this class declaration. """
 | |
|     for typedef in self.typedefs:
 | |
|       if typedef.get_alias() == alias:
 | |
|         return True
 | |
|     return False
 | |
| 
 | |
|   def get_static_funcs(self):
 | |
|     """ Return the array of static function objects. """
 | |
|     return self.staticfuncs
 | |
| 
 | |
|   def get_virtual_funcs(self):
 | |
|     """ Return the array of virtual function objects. """
 | |
|     return self.virtualfuncs
 | |
| 
 | |
|   def get_types(self, list):
 | |
|     """ Return a dictionary mapping data types to analyzed values. """
 | |
|     for cls in self.typedefs:
 | |
|       cls.get_types(list)
 | |
| 
 | |
|     for cls in self.staticfuncs:
 | |
|       cls.get_types(list)
 | |
| 
 | |
|     for cls in self.virtualfuncs:
 | |
|       cls.get_types(list)
 | |
| 
 | |
|   def get_alias_translation(self, alias):
 | |
|     for cls in self.typedefs:
 | |
|       if cls.alias == alias:
 | |
|         return cls.value
 | |
|     return None
 | |
| 
 | |
|   def get_analysis(self, value, named=True):
 | |
|     """ Return an analysis of the value based on the class definition
 | |
|         context.
 | |
|         """
 | |
|     return obj_analysis([self, self.parent], value, named)
 | |
| 
 | |
|   def is_library_side(self):
 | |
|     """ Returns true if the class is implemented by the library. """
 | |
|     return self.attribs['source'] == 'library'
 | |
| 
 | |
|   def is_client_side(self):
 | |
|     """ Returns true if the class is implemented by the client. """
 | |
|     return self.attribs['source'] == 'client'
 | |
| 
 | |
| 
 | |
| class obj_typedef:
 | |
|   """ Class representing a typedef statement. """
 | |
| 
 | |
|   def __init__(self, parent, filename, value, alias):
 | |
|     if not isinstance(parent, obj_header) \
 | |
|         and not isinstance(parent, obj_class):
 | |
|       raise Exception('Invalid parent object type')
 | |
| 
 | |
|     self.parent = parent
 | |
|     self.filename = filename
 | |
|     self.alias = alias
 | |
|     self.value = self.parent.get_analysis(value, False)
 | |
| 
 | |
|   def __repr__(self):
 | |
|     return 'typedef ' + self.value.get_type() + ' ' + self.alias + ';'
 | |
| 
 | |
|   def get_file_name(self):
 | |
|     """ Return the C++ header file name. """
 | |
|     return self.filename
 | |
| 
 | |
|   def get_capi_file_name(self):
 | |
|     """ Return the CAPI header file name. """
 | |
|     return get_capi_file_name(self.filename)
 | |
| 
 | |
|   def get_alias(self):
 | |
|     """ Return the alias. """
 | |
|     return self.alias
 | |
| 
 | |
|   def get_value(self):
 | |
|     """ Return an analysis of the value based on the class or header file
 | |
|         definition context.
 | |
|         """
 | |
|     return self.value
 | |
| 
 | |
|   def get_types(self, list):
 | |
|     """ Return a dictionary mapping data types to analyzed values. """
 | |
|     name = self.value.get_type()
 | |
|     if not name in list:
 | |
|       list[name] = self.value
 | |
| 
 | |
| 
 | |
| class obj_function:
 | |
|   """ Class representing a function. """
 | |
| 
 | |
|   def __init__(self, parent, filename, attrib, retval, argval, comment):
 | |
|     self.parent = parent
 | |
|     self.filename = filename
 | |
|     self.attribs = str_to_dict(attrib)
 | |
|     self.retval = obj_argument(self, retval)
 | |
|     self.name = self.retval.remove_name()
 | |
|     self.comment = comment
 | |
| 
 | |
|     # build the argument objects
 | |
|     self.arguments = []
 | |
|     arglist = argval.split(',')
 | |
|     argindex = 0
 | |
|     while argindex < len(arglist):
 | |
|       arg = arglist[argindex]
 | |
|       if arg.find('<') >= 0 and arg.find('>') == -1:
 | |
|         # We've split inside of a template type declaration. Join the
 | |
|         # next argument with this argument.
 | |
|         argindex += 1
 | |
|         arg += ',' + arglist[argindex]
 | |
| 
 | |
|       arg = arg.strip()
 | |
|       if len(arg) > 0:
 | |
|         argument = obj_argument(self, arg)
 | |
|         if argument.needs_attrib_count_func() and \
 | |
|             argument.get_attrib_count_func() is None:
 | |
|           raise Exception("A 'count_func' attribute is required "+ \
 | |
|                           "for the '"+argument.get_name()+ \
 | |
|                           "' parameter to "+self.get_qualified_name())
 | |
|         self.arguments.append(argument)
 | |
| 
 | |
|       argindex += 1
 | |
| 
 | |
|     if self.retval.needs_attrib_default_retval() and \
 | |
|         self.retval.get_attrib_default_retval() is None:
 | |
|       raise Exception("A 'default_retval' attribute is required for "+ \
 | |
|                       self.get_qualified_name())
 | |
| 
 | |
|   def __repr__(self):
 | |
|     return '/* ' + dict_to_str(self.attribs) + ' */ ' + self.get_cpp_proto()
 | |
| 
 | |
|   def get_file_name(self):
 | |
|     """ Return the C++ header file name. """
 | |
|     return self.filename
 | |
| 
 | |
|   def get_capi_file_name(self):
 | |
|     """ Return the CAPI header file name. """
 | |
|     return get_capi_file_name(self.filename)
 | |
| 
 | |
|   def get_name(self):
 | |
|     """ Return the function name. """
 | |
|     return self.name
 | |
| 
 | |
|   def get_qualified_name(self):
 | |
|     """ Return the fully qualified function name. """
 | |
|     if isinstance(self.parent, obj_header):
 | |
|       # global function
 | |
|       return self.name
 | |
|     else:
 | |
|       # member function
 | |
|       return self.parent.get_name() + '::' + self.name
 | |
| 
 | |
|   def get_capi_name(self, prefix=None):
 | |
|     """ Return the CAPI function name. """
 | |
|     if 'capi_name' in self.attribs:
 | |
|       return self.attribs['capi_name']
 | |
|     return get_capi_name(self.name, False, prefix)
 | |
| 
 | |
|   def get_comment(self):
 | |
|     """ Return the function comment as an array of lines. """
 | |
|     return self.comment
 | |
| 
 | |
|   def get_attribs(self):
 | |
|     """ Return all attributes as a dictionary. """
 | |
|     return self.attribs
 | |
| 
 | |
|   def has_attrib(self, name):
 | |
|     """ Return true if the specified attribute exists. """
 | |
|     return name in self.attribs
 | |
| 
 | |
|   def get_attrib(self, name):
 | |
|     """ Return the first or only value for specified attribute. """
 | |
|     if name in self.attribs:
 | |
|       if isinstance(self.attribs[name], list):
 | |
|         # the value is a list
 | |
|         return self.attribs[name][0]
 | |
|       else:
 | |
|         # the value is a string
 | |
|         return self.attribs[name]
 | |
|     return None
 | |
| 
 | |
|   def get_attrib_list(self, name):
 | |
|     """ Return all values for specified attribute as a list. """
 | |
|     if name in self.attribs:
 | |
|       if isinstance(self.attribs[name], list):
 | |
|         # the value is already a list
 | |
|         return self.attribs[name]
 | |
|       else:
 | |
|         # convert the value to a list
 | |
|         return [self.attribs[name]]
 | |
|     return None
 | |
| 
 | |
|   def get_retval(self):
 | |
|     """ Return the return value object. """
 | |
|     return self.retval
 | |
| 
 | |
|   def get_arguments(self):
 | |
|     """ Return the argument array. """
 | |
|     return self.arguments
 | |
| 
 | |
|   def get_types(self, list):
 | |
|     """ Return a dictionary mapping data types to analyzed values. """
 | |
|     for cls in self.arguments:
 | |
|       cls.get_types(list)
 | |
| 
 | |
|   def get_capi_parts(self, defined_structs=[], prefix=None):
 | |
|     """ Return the parts of the C API function definition. """
 | |
|     retval = ''
 | |
|     dict = self.retval.get_type().get_capi(defined_structs)
 | |
|     if dict['format'] == 'single':
 | |
|       retval = dict['value']
 | |
| 
 | |
|     name = self.get_capi_name(prefix)
 | |
|     args = []
 | |
| 
 | |
|     if isinstance(self, obj_function_virtual):
 | |
|       # virtual functions get themselves as the first argument
 | |
|       str = 'struct _' + self.parent.get_capi_name() + '* self'
 | |
|       if isinstance(self, obj_function_virtual) and self.is_const():
 | |
|         # const virtual functions get const self pointers
 | |
|         str = 'const ' + str
 | |
|       args.append(str)
 | |
| 
 | |
|     if len(self.arguments) > 0:
 | |
|       for cls in self.arguments:
 | |
|         type = cls.get_type()
 | |
|         dict = type.get_capi(defined_structs)
 | |
|         if dict['format'] == 'single':
 | |
|           args.append(dict['value'])
 | |
|         elif dict['format'] == 'multi-arg':
 | |
|           # add an additional argument for the size of the array
 | |
|           type_name = type.get_name()
 | |
|           if type.is_const():
 | |
|             # for const arrays pass the size argument by value
 | |
|             args.append('size_t ' + type_name + 'Count')
 | |
|           else:
 | |
|             # for non-const arrays pass the size argument by address
 | |
|             args.append('size_t* ' + type_name + 'Count')
 | |
|           args.append(dict['value'])
 | |
| 
 | |
|     return {'retval': retval, 'name': name, 'args': args}
 | |
| 
 | |
|   def get_capi_proto(self, defined_structs=[], prefix=None):
 | |
|     """ Return the prototype of the C API function. """
 | |
|     parts = self.get_capi_parts(defined_structs, prefix)
 | |
|     result = parts['retval']+' '+parts['name']+ \
 | |
|              '('+', '.join(parts['args'])+')'
 | |
|     return result
 | |
| 
 | |
|   def get_cpp_parts(self, isimpl=False):
 | |
|     """ Return the parts of the C++ function definition. """
 | |
|     retval = str(self.retval)
 | |
|     name = self.name
 | |
| 
 | |
|     args = []
 | |
|     if len(self.arguments) > 0:
 | |
|       for cls in self.arguments:
 | |
|         args.append(str(cls))
 | |
| 
 | |
|     if isimpl and isinstance(self, obj_function_virtual):
 | |
|       # enumeration return values must be qualified with the class name
 | |
|       # if the type is defined in the class declaration scope.
 | |
|       type = self.get_retval().get_type()
 | |
|       if type.is_result_struct() and type.is_result_struct_enum() and \
 | |
|           self.parent.has_typedef_alias(retval):
 | |
|         retval = self.parent.get_name() + '::' + retval
 | |
| 
 | |
|     return {'retval': retval, 'name': name, 'args': args}
 | |
| 
 | |
|   def get_cpp_proto(self, classname=None):
 | |
|     """ Return the prototype of the C++ function. """
 | |
|     parts = self.get_cpp_parts()
 | |
|     result = parts['retval'] + ' '
 | |
|     if not classname is None:
 | |
|       result += classname + '::'
 | |
|     result += parts['name'] + '(' + ', '.join(parts['args']) + ')'
 | |
|     if isinstance(self, obj_function_virtual) and self.is_const():
 | |
|       result += ' const'
 | |
|     return result
 | |
| 
 | |
|   def is_same_side(self, other_class_name):
 | |
|     """ Returns true if this function is on the same side (library or
 | |
|             client) and the specified class. """
 | |
|     if isinstance(self.parent, obj_class):
 | |
|       # this function is part of a class
 | |
|       this_is_library_side = self.parent.is_library_side()
 | |
|       header = self.parent.parent
 | |
|     else:
 | |
|       # this function is global
 | |
|       this_is_library_side = True
 | |
|       header = self.parent
 | |
| 
 | |
|     if is_base_class(other_class_name):
 | |
|       other_is_library_side = False
 | |
|     else:
 | |
|       other_class = header.get_class(other_class_name)
 | |
|       if other_class is None:
 | |
|         raise Exception('Unknown class: ' + other_class_name)
 | |
|       other_is_library_side = other_class.is_library_side()
 | |
| 
 | |
|     return other_is_library_side == this_is_library_side
 | |
| 
 | |
| 
 | |
| class obj_function_static(obj_function):
 | |
|   """ Class representing a static function. """
 | |
| 
 | |
|   def __init__(self, parent, attrib, retval, argval, comment):
 | |
|     if not isinstance(parent, obj_class):
 | |
|       raise Exception('Invalid parent object type')
 | |
|     obj_function.__init__(self, parent, parent.filename, attrib, retval, argval,
 | |
|                           comment)
 | |
| 
 | |
|   def __repr__(self):
 | |
|     return 'static ' + obj_function.__repr__(self) + ';'
 | |
| 
 | |
|   def get_capi_name(self, prefix=None):
 | |
|     """ Return the CAPI function name. """
 | |
|     if prefix is None:
 | |
|       # by default static functions are prefixed with the class name
 | |
|       prefix = get_capi_name(self.parent.get_name(), False)
 | |
|     return obj_function.get_capi_name(self, prefix)
 | |
| 
 | |
| 
 | |
| class obj_function_virtual(obj_function):
 | |
|   """ Class representing a virtual function. """
 | |
| 
 | |
|   def __init__(self, parent, attrib, retval, argval, comment, vfmod):
 | |
|     if not isinstance(parent, obj_class):
 | |
|       raise Exception('Invalid parent object type')
 | |
|     obj_function.__init__(self, parent, parent.filename, attrib, retval, argval,
 | |
|                           comment)
 | |
|     if vfmod == 'const':
 | |
|       self.isconst = True
 | |
|     else:
 | |
|       self.isconst = False
 | |
| 
 | |
|   def __repr__(self):
 | |
|     return 'virtual ' + obj_function.__repr__(self) + ';'
 | |
| 
 | |
|   def is_const(self):
 | |
|     """ Returns true if the method declaration is const. """
 | |
|     return self.isconst
 | |
| 
 | |
| 
 | |
| class obj_argument:
 | |
|   """ Class representing a function argument. """
 | |
| 
 | |
|   def __init__(self, parent, argval):
 | |
|     if not isinstance(parent, obj_function):
 | |
|       raise Exception('Invalid parent object type')
 | |
| 
 | |
|     self.parent = parent
 | |
|     self.type = self.parent.parent.get_analysis(argval)
 | |
| 
 | |
|   def __repr__(self):
 | |
|     result = ''
 | |
|     if self.type.is_const():
 | |
|       result += 'const '
 | |
|     result += self.type.get_type()
 | |
|     if self.type.is_byref():
 | |
|       result += '&'
 | |
|     elif self.type.is_byaddr():
 | |
|       result += '*'
 | |
|     if self.type.has_name():
 | |
|       result += ' ' + self.type.get_name()
 | |
|     return result
 | |
| 
 | |
|   def get_name(self):
 | |
|     """ Return the name for this argument. """
 | |
|     return self.type.get_name()
 | |
| 
 | |
|   def remove_name(self):
 | |
|     """ Remove and return the name value. """
 | |
|     name = self.type.get_name()
 | |
|     self.type.name = None
 | |
|     return name
 | |
| 
 | |
|   def get_type(self):
 | |
|     """ Return an analysis of the argument type based on the class
 | |
|         definition context.
 | |
|         """
 | |
|     return self.type
 | |
| 
 | |
|   def get_types(self, list):
 | |
|     """ Return a dictionary mapping data types to analyzed values. """
 | |
|     name = self.type.get_type()
 | |
|     if not name in list:
 | |
|       list[name] = self.type
 | |
| 
 | |
|   def needs_attrib_count_func(self):
 | |
|     """ Returns true if this argument requires a 'count_func' attribute. """
 | |
|     # A 'count_func' attribute is required for non-const non-string vector
 | |
|     # attribute types
 | |
|     return self.type.has_name() and \
 | |
|         self.type.is_result_vector() and \
 | |
|         not self.type.is_result_vector_string() and \
 | |
|         not self.type.is_const()
 | |
| 
 | |
|   def get_attrib_count_func(self):
 | |
|     """ Returns the count function for this argument. """
 | |
|     # The 'count_func' attribute value format is name:function
 | |
|     if not self.parent.has_attrib('count_func'):
 | |
|       return None
 | |
|     name = self.type.get_name()
 | |
|     vals = self.parent.get_attrib_list('count_func')
 | |
|     for val in vals:
 | |
|       parts = val.split(':')
 | |
|       if len(parts) != 2:
 | |
|         raise Exception("Invalid 'count_func' attribute value for "+ \
 | |
|                         self.parent.get_qualified_name()+': '+val)
 | |
|       if parts[0].strip() == name:
 | |
|         return parts[1].strip()
 | |
|     return None
 | |
| 
 | |
|   def needs_attrib_default_retval(self):
 | |
|     """ Returns true if this argument requires a 'default_retval' attribute.
 | |
|         """
 | |
|     # A 'default_retval' attribute is required for enumeration return value
 | |
|     # types.
 | |
|     return not self.type.has_name() and \
 | |
|         self.type.is_result_struct() and \
 | |
|         self.type.is_result_struct_enum()
 | |
| 
 | |
|   def get_attrib_default_retval(self):
 | |
|     """ Returns the defualt return value for this argument. """
 | |
|     return self.parent.get_attrib('default_retval')
 | |
| 
 | |
|   def get_arg_type(self):
 | |
|     """ Returns the argument type as defined in translator.README.txt. """
 | |
|     if not self.type.has_name():
 | |
|       raise Exception('Cannot be called for retval types')
 | |
| 
 | |
|     # simple or enumeration type
 | |
|     if (self.type.is_result_simple() and \
 | |
|             self.type.get_type() != 'bool') or \
 | |
|        (self.type.is_result_struct() and \
 | |
|             self.type.is_result_struct_enum()):
 | |
|       if self.type.is_byref():
 | |
|         if self.type.is_const():
 | |
|           return 'simple_byref_const'
 | |
|         return 'simple_byref'
 | |
|       elif self.type.is_byaddr():
 | |
|         return 'simple_byaddr'
 | |
|       return 'simple_byval'
 | |
| 
 | |
|     # boolean type
 | |
|     if self.type.get_type() == 'bool':
 | |
|       if self.type.is_byref():
 | |
|         return 'bool_byref'
 | |
|       elif self.type.is_byaddr():
 | |
|         return 'bool_byaddr'
 | |
|       return 'bool_byval'
 | |
| 
 | |
|     # structure type
 | |
|     if self.type.is_result_struct() and self.type.is_byref():
 | |
|       if self.type.is_const():
 | |
|         return 'struct_byref_const'
 | |
|       return 'struct_byref'
 | |
| 
 | |
|     # string type
 | |
|     if self.type.is_result_string() and self.type.is_byref():
 | |
|       if self.type.is_const():
 | |
|         return 'string_byref_const'
 | |
|       return 'string_byref'
 | |
| 
 | |
|     # *ptr type
 | |
|     if self.type.is_result_ptr():
 | |
|       prefix = self.type.get_result_ptr_type_prefix()
 | |
|       same_side = self.parent.is_same_side(self.type.get_ptr_type())
 | |
|       if self.type.is_byref():
 | |
|         if same_side:
 | |
|           return prefix + 'ptr_same_byref'
 | |
|         return prefix + 'ptr_diff_byref'
 | |
|       if same_side:
 | |
|         return prefix + 'ptr_same'
 | |
|       return prefix + 'ptr_diff'
 | |
| 
 | |
|     if self.type.is_result_vector():
 | |
|       # all vector types must be passed by reference
 | |
|       if not self.type.is_byref():
 | |
|         return 'invalid'
 | |
| 
 | |
|       if self.type.is_result_vector_string():
 | |
|         # string vector type
 | |
|         if self.type.is_const():
 | |
|           return 'string_vec_byref_const'
 | |
|         return 'string_vec_byref'
 | |
| 
 | |
|       if self.type.is_result_vector_simple():
 | |
|         if self.type.get_vector_type() != 'bool':
 | |
|           # simple/enumeration vector types
 | |
|           if self.type.is_const():
 | |
|             return 'simple_vec_byref_const'
 | |
|           return 'simple_vec_byref'
 | |
| 
 | |
|         # boolean vector types
 | |
|         if self.type.is_const():
 | |
|           return 'bool_vec_byref_const'
 | |
|         return 'bool_vec_byref'
 | |
| 
 | |
|       if self.type.is_result_vector_ptr():
 | |
|         # *ptr vector types
 | |
|         prefix = self.type.get_result_vector_ptr_type_prefix()
 | |
|         same_side = self.parent.is_same_side(self.type.get_ptr_type())
 | |
|         if self.type.is_const():
 | |
|           if same_side:
 | |
|             return prefix + 'ptr_vec_same_byref_const'
 | |
|           return prefix + 'ptr_vec_diff_byref_const'
 | |
|         if same_side:
 | |
|           return prefix + 'ptr_vec_same_byref'
 | |
|         return prefix + 'ptr_vec_diff_byref'
 | |
| 
 | |
|     # string single map type
 | |
|     if self.type.is_result_map_single():
 | |
|       if not self.type.is_byref():
 | |
|         return 'invalid'
 | |
|       if self.type.is_const():
 | |
|         return 'string_map_single_byref_const'
 | |
|       return 'string_map_single_byref'
 | |
| 
 | |
|     # string multi map type
 | |
|     if self.type.is_result_map_multi():
 | |
|       if not self.type.is_byref():
 | |
|         return 'invalid'
 | |
|       if self.type.is_const():
 | |
|         return 'string_map_multi_byref_const'
 | |
|       return 'string_map_multi_byref'
 | |
| 
 | |
|     return 'invalid'
 | |
| 
 | |
|   def get_retval_type(self):
 | |
|     """ Returns the retval type as defined in translator.README.txt. """
 | |
|     if self.type.has_name():
 | |
|       raise Exception('Cannot be called for argument types')
 | |
| 
 | |
|     # unsupported modifiers
 | |
|     if self.type.is_const() or self.type.is_byref() or \
 | |
|         self.type.is_byaddr():
 | |
|       return 'invalid'
 | |
| 
 | |
|     # void types don't have a return value
 | |
|     if self.type.get_type() == 'void':
 | |
|       return 'none'
 | |
| 
 | |
|     if (self.type.is_result_simple() and \
 | |
|             self.type.get_type() != 'bool') or \
 | |
|        (self.type.is_result_struct() and self.type.is_result_struct_enum()):
 | |
|       return 'simple'
 | |
| 
 | |
|     if self.type.get_type() == 'bool':
 | |
|       return 'bool'
 | |
| 
 | |
|     if self.type.is_result_string():
 | |
|       return 'string'
 | |
| 
 | |
|     if self.type.is_result_ptr():
 | |
|       prefix = self.type.get_result_ptr_type_prefix()
 | |
|       if self.parent.is_same_side(self.type.get_ptr_type()):
 | |
|         return prefix + 'ptr_same'
 | |
|       else:
 | |
|         return prefix + 'ptr_diff'
 | |
| 
 | |
|     return 'invalid'
 | |
| 
 | |
|   def get_retval_default(self, for_capi):
 | |
|     """ Returns the default return value based on the retval type. """
 | |
|     # start with the default retval attribute, if any.
 | |
|     retval = self.get_attrib_default_retval()
 | |
|     if not retval is None:
 | |
|       if for_capi:
 | |
|         # apply any appropriate C API translations.
 | |
|         if retval == 'true':
 | |
|           return '1'
 | |
|         if retval == 'false':
 | |
|           return '0'
 | |
|       return retval
 | |
| 
 | |
|     # next look at the retval type value.
 | |
|     type = self.get_retval_type()
 | |
|     if type == 'simple':
 | |
|       return self.get_type().get_result_simple_default()
 | |
|     elif type == 'bool':
 | |
|       if for_capi:
 | |
|         return '0'
 | |
|       return 'false'
 | |
|     elif type == 'string':
 | |
|       if for_capi:
 | |
|         return 'NULL'
 | |
|       return 'CefString()'
 | |
|     elif type == 'refptr_same' or type == 'refptr_diff' or \
 | |
|          type == 'rawptr_same' or type == 'rawptr_diff':
 | |
|       return 'NULL'
 | |
|     elif type == 'ownptr_same' or type == 'ownptr_diff':
 | |
|       if for_capi:
 | |
|         return 'NULL'
 | |
|       else:
 | |
|         return 'CefOwnPtr<' + self.type.get_ptr_type() + '>()'
 | |
| 
 | |
|     return ''
 | |
| 
 | |
| 
 | |
| class obj_analysis:
 | |
|   """ Class representing an analysis of a data type value. """
 | |
| 
 | |
|   def __init__(self, scopelist, value, named):
 | |
|     self.value = value
 | |
|     self.result_type = 'unknown'
 | |
|     self.result_value = None
 | |
|     self.result_default = None
 | |
|     self.ptr_type = None
 | |
| 
 | |
|     # parse the argument string
 | |
|     partlist = value.strip().split()
 | |
| 
 | |
|     if named == True:
 | |
|       # extract the name value
 | |
|       self.name = partlist[-1]
 | |
|       del partlist[-1]
 | |
|     else:
 | |
|       self.name = None
 | |
| 
 | |
|     if len(partlist) == 0:
 | |
|       raise Exception('Invalid argument value: ' + value)
 | |
| 
 | |
|     # check const status
 | |
|     if partlist[0] == 'const':
 | |
|       self.isconst = True
 | |
|       del partlist[0]
 | |
|     else:
 | |
|       self.isconst = False
 | |
| 
 | |
|     if len(partlist) == 0:
 | |
|       raise Exception('Invalid argument value: ' + value)
 | |
| 
 | |
|     # combine the data type
 | |
|     self.type = ' '.join(partlist)
 | |
| 
 | |
|     # extract the last character of the data type
 | |
|     endchar = self.type[-1]
 | |
| 
 | |
|     # check if the value is passed by reference
 | |
|     if endchar == '&':
 | |
|       self.isbyref = True
 | |
|       self.type = self.type[:-1]
 | |
|     else:
 | |
|       self.isbyref = False
 | |
| 
 | |
|     # check if the value is passed by address
 | |
|     if endchar == '*':
 | |
|       self.isbyaddr = True
 | |
|       self.type = self.type[:-1]
 | |
|     else:
 | |
|       self.isbyaddr = False
 | |
| 
 | |
|     # see if the value is directly identifiable
 | |
|     if self._check_advanced(self.type) == True:
 | |
|       return
 | |
| 
 | |
|     # not identifiable, so look it up
 | |
|     translation = None
 | |
|     for scope in scopelist:
 | |
|       if not isinstance(scope, obj_header) \
 | |
|           and not isinstance(scope, obj_class):
 | |
|         raise Exception('Invalid scope object type')
 | |
|       translation = scope.get_alias_translation(self.type)
 | |
|       if not translation is None:
 | |
|         break
 | |
| 
 | |
|     if translation is None:
 | |
|       raise Exception('Failed to translate type: ' + self.type)
 | |
| 
 | |
|     # the translation succeeded so keep the result
 | |
|     self.result_type = translation.result_type
 | |
|     self.result_value = translation.result_value
 | |
| 
 | |
|   def _check_advanced(self, value):
 | |
|     # check for vectors
 | |
|     if value.find('std::vector') == 0:
 | |
|       self.result_type = 'vector'
 | |
|       val = value[12:-1].strip()
 | |
|       self.result_value = [self._get_basic(val)]
 | |
|       self.result_value[0]['vector_type'] = val
 | |
|       return True
 | |
| 
 | |
|     # check for maps
 | |
|     if value.find('std::map') == 0:
 | |
|       self.result_type = 'map'
 | |
|       vals = value[9:-1].split(',')
 | |
|       if len(vals) == 2:
 | |
|         self.result_value = [
 | |
|             self._get_basic(vals[0].strip()),
 | |
|             self._get_basic(vals[1].strip())
 | |
|         ]
 | |
|         return True
 | |
| 
 | |
|     # check for multimaps
 | |
|     if value.find('std::multimap') == 0:
 | |
|       self.result_type = 'multimap'
 | |
|       vals = value[14:-1].split(',')
 | |
|       if len(vals) == 2:
 | |
|         self.result_value = [
 | |
|             self._get_basic(vals[0].strip()),
 | |
|             self._get_basic(vals[1].strip())
 | |
|         ]
 | |
|         return True
 | |
| 
 | |
|     # check for basic types
 | |
|     basic = self._get_basic(value)
 | |
|     if not basic is None:
 | |
|       self.result_type = basic['result_type']
 | |
|       self.result_value = basic['result_value']
 | |
|       if 'ptr_type' in basic:
 | |
|         self.ptr_type = basic['ptr_type']
 | |
|       if 'result_default' in basic:
 | |
|         self.result_default = basic['result_default']
 | |
|       return True
 | |
| 
 | |
|     return False
 | |
| 
 | |
|   def _get_basic(self, value):
 | |
|     # check for string values
 | |
|     if value == "CefString":
 | |
|       return {'result_type': 'string', 'result_value': None}
 | |
| 
 | |
|     # check for simple direct translations
 | |
|     if value in _simpletypes.keys():
 | |
|       return {
 | |
|           'result_type': 'simple',
 | |
|           'result_value': _simpletypes[value][0],
 | |
|           'result_default': _simpletypes[value][1],
 | |
|       }
 | |
| 
 | |
|     # check if already a C API structure
 | |
|     if value[-2:] == '_t':
 | |
|       return {'result_type': 'structure', 'result_value': value}
 | |
| 
 | |
|     # check for CEF reference pointers
 | |
|     p = re.compile('^CefRefPtr<(.*?)>$', re.DOTALL)
 | |
|     list = p.findall(value)
 | |
|     if len(list) == 1:
 | |
|       return {
 | |
|           'result_type': 'refptr',
 | |
|           'result_value': get_capi_name(list[0], True) + '*',
 | |
|           'ptr_type': list[0]
 | |
|       }
 | |
| 
 | |
|     # check for CEF owned pointers
 | |
|     p = re.compile('^CefOwnPtr<(.*?)>$', re.DOTALL)
 | |
|     list = p.findall(value)
 | |
|     if len(list) == 1:
 | |
|       return {
 | |
|           'result_type': 'ownptr',
 | |
|           'result_value': get_capi_name(list[0], True) + '*',
 | |
|           'ptr_type': list[0]
 | |
|       }
 | |
| 
 | |
|     # check for CEF raw pointers
 | |
|     p = re.compile('^CefRawPtr<(.*?)>$', re.DOTALL)
 | |
|     list = p.findall(value)
 | |
|     if len(list) == 1:
 | |
|       return {
 | |
|           'result_type': 'rawptr',
 | |
|           'result_value': get_capi_name(list[0], True) + '*',
 | |
|           'ptr_type': list[0]
 | |
|       }
 | |
| 
 | |
|     # check for CEF structure types
 | |
|     if value[0:3] == 'Cef' and value[-4:] != 'List':
 | |
|       return {
 | |
|           'result_type': 'structure',
 | |
|           'result_value': get_capi_name(value, True)
 | |
|       }
 | |
| 
 | |
|     return None
 | |
| 
 | |
|   def __repr__(self):
 | |
|     return '(' + self.result_type + ') ' + str(self.result_value)
 | |
| 
 | |
|   def has_name(self):
 | |
|     """ Returns true if a name value exists. """
 | |
|     return (not self.name is None)
 | |
| 
 | |
|   def get_name(self):
 | |
|     """ Return the name. """
 | |
|     return self.name
 | |
| 
 | |
|   def get_value(self):
 | |
|     """ Return the C++ value (type + name). """
 | |
|     return self.value
 | |
| 
 | |
|   def get_type(self):
 | |
|     """ Return the C++ type. """
 | |
|     return self.type
 | |
| 
 | |
|   def get_ptr_type(self):
 | |
|     """ Return the C++ class type referenced by a CefRefPtr. """
 | |
|     if self.is_result_vector() and self.is_result_vector_ptr():
 | |
|       # return the vector RefPtr type
 | |
|       return self.result_value[0]['ptr_type']
 | |
|     # return the basic RefPtr type
 | |
|     return self.ptr_type
 | |
| 
 | |
|   def get_vector_type(self):
 | |
|     """ Return the C++ class type referenced by a std::vector. """
 | |
|     if self.is_result_vector():
 | |
|       return self.result_value[0]['vector_type']
 | |
|     return None
 | |
| 
 | |
|   def is_const(self):
 | |
|     """ Returns true if the argument value is constant. """
 | |
|     return self.isconst
 | |
| 
 | |
|   def is_byref(self):
 | |
|     """ Returns true if the argument is passed by reference. """
 | |
|     return self.isbyref
 | |
| 
 | |
|   def is_byaddr(self):
 | |
|     """ Returns true if the argument is passed by address. """
 | |
|     return self.isbyaddr
 | |
| 
 | |
|   def is_result_simple(self):
 | |
|     """ Returns true if this is a simple argument type. """
 | |
|     return (self.result_type == 'simple')
 | |
| 
 | |
|   def get_result_simple_type_root(self):
 | |
|     """ Return the simple structure or basic type name. """
 | |
|     return self.result_value
 | |
| 
 | |
|   def get_result_simple_type(self):
 | |
|     """ Return the simple type. """
 | |
|     result = ''
 | |
|     if self.is_const():
 | |
|       result += 'const '
 | |
|     result += self.result_value
 | |
|     if self.is_byaddr() or self.is_byref():
 | |
|       result += '*'
 | |
|     return result
 | |
| 
 | |
|   def get_result_simple_default(self):
 | |
|     """ Return the default value fo the basic type. """
 | |
|     return self.result_default
 | |
| 
 | |
|   def is_result_ptr(self):
 | |
|     """ Returns true if this is a *Ptr type. """
 | |
|     return self.is_result_refptr() or self.is_result_ownptr() or \
 | |
|            self.is_result_rawptr()
 | |
| 
 | |
|   def get_result_ptr_type_root(self):
 | |
|     """ Return the *Ptr type structure name. """
 | |
|     return self.result_value[:-1]
 | |
| 
 | |
|   def get_result_ptr_type(self, defined_structs=[]):
 | |
|     """ Return the *Ptr type. """
 | |
|     result = ''
 | |
|     if not self.result_value[:-1] in defined_structs:
 | |
|       result += 'struct _'
 | |
|     result += self.result_value
 | |
|     if self.is_byref() or self.is_byaddr():
 | |
|       result += '*'
 | |
|     return result
 | |
| 
 | |
|   def get_result_ptr_type_prefix(self):
 | |
|     """ Returns the *Ptr type prefix. """
 | |
|     if self.is_result_refptr():
 | |
|       return 'ref'
 | |
|     if self.is_result_ownptr():
 | |
|       return 'own'
 | |
|     if self.is_result_rawptr():
 | |
|       return 'raw'
 | |
|     raise Exception('Not a pointer type')
 | |
| 
 | |
|   def is_result_refptr(self):
 | |
|     """ Returns true if this is a RefPtr type. """
 | |
|     return (self.result_type == 'refptr')
 | |
| 
 | |
|   def is_result_ownptr(self):
 | |
|     """ Returns true if this is a OwnPtr type. """
 | |
|     return (self.result_type == 'ownptr')
 | |
| 
 | |
|   def is_result_rawptr(self):
 | |
|     """ Returns true if this is a RawPtr type. """
 | |
|     return (self.result_type == 'rawptr')
 | |
| 
 | |
|   def is_result_struct(self):
 | |
|     """ Returns true if this is a structure type. """
 | |
|     return (self.result_type == 'structure')
 | |
| 
 | |
|   def is_result_struct_enum(self):
 | |
|     """ Returns true if this struct type is likely an enumeration. """
 | |
|     # structure values that are passed by reference or address must be
 | |
|     # structures and not enumerations
 | |
|     if not self.is_byref() and not self.is_byaddr():
 | |
|       return True
 | |
|     return False
 | |
| 
 | |
|   def get_result_struct_type(self, defined_structs=[]):
 | |
|     """ Return the structure or enumeration type. """
 | |
|     result = ''
 | |
|     is_enum = self.is_result_struct_enum()
 | |
|     if not is_enum:
 | |
|       if self.is_const():
 | |
|         result += 'const '
 | |
|       if not self.result_value in defined_structs:
 | |
|         result += 'struct _'
 | |
|     result += self.result_value
 | |
|     if not is_enum:
 | |
|       result += '*'
 | |
|     return result
 | |
| 
 | |
|   def is_result_string(self):
 | |
|     """ Returns true if this is a string type. """
 | |
|     return (self.result_type == 'string')
 | |
| 
 | |
|   def get_result_string_type(self):
 | |
|     """ Return the string type. """
 | |
|     if not self.has_name():
 | |
|       # Return values are string structs that the user must free. Use
 | |
|       # the name of the structure as a hint.
 | |
|       return 'cef_string_userfree_t'
 | |
|     elif not self.is_const() and (self.is_byref() or self.is_byaddr()):
 | |
|       # Parameters passed by reference or address. Use the normal
 | |
|       # non-const string struct.
 | |
|       return 'cef_string_t*'
 | |
|     # Const parameters use the const string struct.
 | |
|     return 'const cef_string_t*'
 | |
| 
 | |
|   def is_result_vector(self):
 | |
|     """ Returns true if this is a vector type. """
 | |
|     return (self.result_type == 'vector')
 | |
| 
 | |
|   def is_result_vector_string(self):
 | |
|     """ Returns true if this is a string vector. """
 | |
|     return self.result_value[0]['result_type'] == 'string'
 | |
| 
 | |
|   def is_result_vector_simple(self):
 | |
|     """ Returns true if this is a string vector. """
 | |
|     return self.result_value[0]['result_type'] == 'simple'
 | |
| 
 | |
|   def is_result_vector_ptr(self):
 | |
|     """ Returns true if this is a *Ptr vector. """
 | |
|     return self.is_result_vector_refptr() or \
 | |
|            self.is_result_vector_ownptr() or \
 | |
|            self.is_result_vector_rawptr()
 | |
| 
 | |
|   def get_result_vector_ptr_type_prefix(self):
 | |
|     """ Returns the *Ptr type prefix. """
 | |
|     if self.is_result_vector_refptr():
 | |
|       return 'ref'
 | |
|     if self.is_result_vector_ownptr():
 | |
|       return 'own'
 | |
|     if self.is_result_vector_rawptr():
 | |
|       return 'raw'
 | |
|     raise Exception('Not a pointer type')
 | |
| 
 | |
|   def is_result_vector_refptr(self):
 | |
|     """ Returns true if this is a RefPtr vector. """
 | |
|     return self.result_value[0]['result_type'] == 'refptr'
 | |
| 
 | |
|   def is_result_vector_ownptr(self):
 | |
|     """ Returns true if this is a OwnPtr vector. """
 | |
|     return self.result_value[0]['result_type'] == 'ownptr'
 | |
| 
 | |
|   def is_result_vector_rawptr(self):
 | |
|     """ Returns true if this is a RawPtr vector. """
 | |
|     return self.result_value[0]['result_type'] == 'rawptr'
 | |
| 
 | |
|   def get_result_vector_type_root(self):
 | |
|     """ Return the vector structure or basic type name. """
 | |
|     return self.result_value[0]['result_value']
 | |
| 
 | |
|   def get_result_vector_type(self, defined_structs=[]):
 | |
|     """ Return the vector type. """
 | |
|     if not self.has_name():
 | |
|       raise Exception('Cannot use vector as a return type')
 | |
| 
 | |
|     type = self.result_value[0]['result_type']
 | |
|     value = self.result_value[0]['result_value']
 | |
| 
 | |
|     result = {}
 | |
|     if type == 'string':
 | |
|       result['value'] = 'cef_string_list_t'
 | |
|       result['format'] = 'single'
 | |
|       return result
 | |
| 
 | |
|     if type == 'simple':
 | |
|       str = value
 | |
|       if self.is_const():
 | |
|         str += ' const'
 | |
|       str += '*'
 | |
|       result['value'] = str
 | |
|     elif type == 'refptr' or type == 'ownptr' or type == 'rawptr':
 | |
|       str = ''
 | |
|       if not value[:-1] in defined_structs:
 | |
|         str += 'struct _'
 | |
|       str += value
 | |
|       if self.is_const():
 | |
|         str += ' const'
 | |
|       str += '*'
 | |
|       result['value'] = str
 | |
|     else:
 | |
|       raise Exception('Unsupported vector type: ' + type)
 | |
| 
 | |
|     # vector values must be passed as a value array parameter
 | |
|     # and a size parameter
 | |
|     result['format'] = 'multi-arg'
 | |
|     return result
 | |
| 
 | |
|   def is_result_map(self):
 | |
|     """ Returns true if this is a map type. """
 | |
|     return (self.result_type == 'map' or self.result_type == 'multimap')
 | |
| 
 | |
|   def is_result_map_single(self):
 | |
|     """ Returns true if this is a single map type. """
 | |
|     return (self.result_type == 'map')
 | |
| 
 | |
|   def is_result_map_multi(self):
 | |
|     """ Returns true if this is a multi map type. """
 | |
|     return (self.result_type == 'multimap')
 | |
| 
 | |
|   def get_result_map_type(self, defined_structs=[]):
 | |
|     """ Return the map type. """
 | |
|     if not self.has_name():
 | |
|       raise Exception('Cannot use map as a return type')
 | |
|     if self.result_value[0]['result_type'] == 'string' \
 | |
|         and self.result_value[1]['result_type'] == 'string':
 | |
|       if self.result_type == 'map':
 | |
|         return {'value': 'cef_string_map_t', 'format': 'single'}
 | |
|       elif self.result_type == 'multimap':
 | |
|         return {'value': 'cef_string_multimap_t', 'format': 'multi'}
 | |
|     raise Exception('Only mappings of strings to strings are supported')
 | |
| 
 | |
|   def get_capi(self, defined_structs=[]):
 | |
|     """ Format the value for the C API. """
 | |
|     result = ''
 | |
|     format = 'single'
 | |
|     if self.is_result_simple():
 | |
|       result += self.get_result_simple_type()
 | |
|     elif self.is_result_ptr():
 | |
|       result += self.get_result_ptr_type(defined_structs)
 | |
|     elif self.is_result_struct():
 | |
|       result += self.get_result_struct_type(defined_structs)
 | |
|     elif self.is_result_string():
 | |
|       result += self.get_result_string_type()
 | |
|     elif self.is_result_map():
 | |
|       resdict = self.get_result_map_type(defined_structs)
 | |
|       if resdict['format'] == 'single' or resdict['format'] == 'multi':
 | |
|         result += resdict['value']
 | |
|       else:
 | |
|         raise Exception('Unsupported map type')
 | |
|     elif self.is_result_vector():
 | |
|       resdict = self.get_result_vector_type(defined_structs)
 | |
|       if resdict['format'] != 'single':
 | |
|         format = resdict['format']
 | |
|       result += resdict['value']
 | |
| 
 | |
|     if self.has_name():
 | |
|       result += ' ' + self.get_name()
 | |
| 
 | |
|     return {'format': format, 'value': result}
 | |
| 
 | |
| 
 | |
| # test the module
 | |
| if __name__ == "__main__":
 | |
|   import pprint
 | |
|   import sys
 | |
| 
 | |
|   # verify that the correct number of command-line arguments are provided
 | |
|   if len(sys.argv) != 2:
 | |
|     sys.stderr.write('Usage: ' + sys.argv[0] + ' <directory>')
 | |
|     sys.exit()
 | |
| 
 | |
|   pp = pprint.PrettyPrinter(indent=4)
 | |
| 
 | |
|   # create the header object
 | |
|   header = obj_header()
 | |
|   header.add_directory(sys.argv[1])
 | |
| 
 | |
|   # output the type mapping
 | |
|   types = {}
 | |
|   header.get_types(types)
 | |
|   pp.pprint(types)
 | |
|   sys.stdout.write('\n')
 | |
| 
 | |
|   # output the parsed C++ data
 | |
|   sys.stdout.write(str(header))
 | |
| 
 | |
|   # output the C API formatted data
 | |
|   defined_names = header.get_defined_structs()
 | |
|   result = ''
 | |
| 
 | |
|   # global functions
 | |
|   funcs = header.get_funcs()
 | |
|   if len(funcs) > 0:
 | |
|     for func in funcs:
 | |
|       result += func.get_capi_proto(defined_names) + ';\n'
 | |
|     result += '\n'
 | |
| 
 | |
|   classes = header.get_classes()
 | |
|   for cls in classes:
 | |
|     # virtual functions are inside a structure
 | |
|     result += 'struct ' + cls.get_capi_name() + '\n{\n'
 | |
|     funcs = cls.get_virtual_funcs()
 | |
|     if len(funcs) > 0:
 | |
|       for func in funcs:
 | |
|         result += '\t' + func.get_capi_proto(defined_names) + ';\n'
 | |
|     result += '}\n\n'
 | |
| 
 | |
|     defined_names.append(cls.get_capi_name())
 | |
| 
 | |
|     # static functions become global
 | |
|     funcs = cls.get_static_funcs()
 | |
|     if len(funcs) > 0:
 | |
|       for func in funcs:
 | |
|         result += func.get_capi_proto(defined_names) + ';\n'
 | |
|       result += '\n'
 | |
|   sys.stdout.write(result)
 |