- Auto-generate all C/C++ translation code (issue #33).

- Change index parameter types from int to size_t to make 0-based range implicit.
- Make CefPrintOptions and CefMenuInfo proper wrapper classes.
- Normalize the naming of menu-related types.
- Remove unused command_line variable from test_suite.cc.

git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@408 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
This commit is contained in:
Marshall Greenblatt
2011-12-08 01:38:30 +00:00
parent b4653ce1da
commit 64e08c2918
238 changed files with 14703 additions and 4322 deletions

View File

@ -2,6 +2,7 @@
# reserved. Use of this source code is governed by a BSD-style license that
# can be found in the LICENSE file.
from date_util import *
from file_util import *
import os
import re
@ -147,7 +148,7 @@ def get_comment(body, name):
result.append(None)
else:
break
elif line[0:2] == '/*':
elif line[0:2] == '/*' or line[-2:] == '*/':
continue
elif line[0:2] == '//':
# keep the comment line including any leading spaces
@ -288,7 +289,8 @@ def format_translation_includes(body):
return result
def str_to_dict(str):
""" Convert a string to a dictionary. """
""" Convert a string to a dictionary. If the same key has multiple values
the values will be stored in a list. """
dict = {}
parts = string.split(str, ',')
for part in parts:
@ -296,21 +298,40 @@ def str_to_dict(str):
if len(part) == 0:
continue
sparts = string.split(part, '=')
if len(sparts) != 2:
if len(sparts) > 2:
raise Exception('Invalid dictionary pair format: '+part)
dict[string.strip(sparts[0])] = string.strip(sparts[1])
name = string.strip(sparts[0])
if len(sparts) == 2:
val = string.strip(sparts[1])
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():
str.append(name+'='+dict[name])
if not isinstance(dict[name], list):
# currently a string value
str.append(name+'='+dict[name])
else:
# currently a list value
for val in dict[name]:
str.append(name+'='+val)
return string.join(str, ',')
# regex for matching comment-formatted attributes
_cre_attrib = '/\*--cef\(([A-Za-z0-9_ ,=]{0,})\)--\*/'
_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 typedef values and function return values
@ -377,6 +398,25 @@ def get_next_function_impl(existing, name):
break
return result
def get_copyright():
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.
//
// ---------------------------------------------------------------------------
//
// 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.
//
"""
# add the copyright year
return result.replace('$YEAR$', get_year())
class obj_header:
""" Class representing a C++ header file. """
@ -632,8 +672,34 @@ class obj_class:
return self.comment
def get_attribs(self):
""" Return the class attributes as a dictionary. """
return self.attribs;
""" 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. """
@ -727,7 +793,18 @@ class obj_function:
for arg in arglist:
arg = string.strip(arg)
if len(arg) > 0:
self.arguments.append(obj_argument(self, arg))
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)
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()
@ -736,6 +813,15 @@ class obj_function:
""" 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:
@ -747,9 +833,35 @@ class obj_function:
return self.comment
def get_attribs(self):
""" Return the function attributes as a dictionary. """
""" 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
@ -789,19 +901,14 @@ class obj_function:
args.append(dict['value'])
elif dict['format'] == 'multi-arg':
# add an additional argument for the size of the array
type = type.get_name()
if type[-1] == 's':
type = type[:-1]
args.append('size_t '+type+'Count')
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'])
elif dict['format'] == 'multi-func':
# change the function to return one value of the
# required type based on an index parameter
type = type.get_name()
if type[-1] == 's':
type = type[:-1]
args.append('int '+type+'Index')
retval = dict['value']
return { 'retval' : retval, 'name' : name, 'args' : args }
@ -825,8 +932,7 @@ class obj_function:
if isimpl and isinstance(self, obj_function_virtual):
# enumeration return values must be qualified with the class name
type = self.get_retval().get_type()
if type.is_result_struct() and not type.is_byref() \
and not type.is_byaddr():
if type.is_result_struct() and type.is_result_struct_enum():
retval = self.parent.get_name()+'::'+retval
return { 'retval' : retval, 'name' : name, 'args' : args }
@ -841,6 +947,28 @@ class obj_function:
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 other_class_name == 'CefBase':
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):
@ -904,6 +1032,10 @@ class obj_argument:
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()
@ -921,7 +1053,210 @@ class obj_argument:
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 = string.split(val, ':')
if len(parts) != 2:
raise Exception("Invalid 'count_func' attribute value for "+ \
this.parent.get_qualified_name()+': '+val)
if string.strip(parts[0]) == name:
return string.strip(parts[1])
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'
# refptr type
if self.type.is_result_refptr():
same_side = self.parent.is_same_side(self.type.get_refptr_type())
if self.type.is_byref():
if same_side:
return 'refptr_same_byref'
return 'refptr_diff_byref'
if same_side:
return 'refptr_same'
return 'refptr_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_refptr():
# refptr vector types
same_side = self.parent.is_same_side(self.type.get_refptr_type())
if self.type.is_const():
if same_side:
return 'refptr_vec_same_byref_const'
return 'refptr_vec_diff_byref_const'
if same_side:
return 'refptr_vec_same_byref'
return 'refptr_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_refptr():
if self.parent.is_same_side(self.type.get_refptr_type()):
return 'refptr_same'
else:
return 'refptr_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':
return 'NULL'
return ''
class obj_analysis:
""" Class representing an analysis of a data type value. """
@ -930,6 +1265,8 @@ class obj_analysis:
self.value = value
self.result_type = 'unknown'
self.result_value = None
self.result_default = None
self.refptr_type = None
# parse the argument string
partlist = string.split(string.strip(value))
@ -996,10 +1333,11 @@ class obj_analysis:
# check for vectors
if value.find('std::vector') == 0:
self.result_type = 'vector'
val = value[12:-1]
val = string.strip(value[12:-1])
self.result_value = [
self._get_basic(val)
]
self.result_value[0]['vector_type'] = val
return True
# check for maps
@ -1029,6 +1367,10 @@ class obj_analysis:
if not basic is None:
self.result_type = basic['result_type']
self.result_value = basic['result_value']
if 'refptr_type' in basic:
self.refptr_type = basic['refptr_type']
if 'result_default' in basic:
self.result_default = basic['result_default']
return True
return False
@ -1043,27 +1385,28 @@ class obj_analysis:
# check for simple direct translations
simpletypes = {
'void' : 'void',
'int' : 'int',
'int64' : 'int64',
'uint64' : 'uint64',
'double' : 'double',
'long' : 'long',
'unsigned long' : 'unsigned long',
'size_t' : 'size_t',
'time_t' : 'time_t',
'bool' : 'int',
'char* const': 'char* const',
'CefCursorHandle' : 'cef_cursor_handle_t',
'CefWindowHandle' : 'cef_window_handle_t',
'CefRect' : 'cef_rect_t',
'CefThreadId' : 'cef_thread_id_t',
'CefTime' : 'cef_time_t',
'void' : ['void', ''],
'int' : ['int', '0'],
'int64' : ['int64', '0'],
'uint64' : ['uint64', '0'],
'double' : ['double', '0'],
'long' : ['long', '0'],
'unsigned long' : ['unsigned long', '0'],
'size_t' : ['size_t', '0'],
'time_t' : ['time_t', '0'],
'bool' : ['int', '0'],
'char* const': ['char* const', 'NULL'],
'CefCursorHandle' : ['cef_cursor_handle_t', 'NULL'],
'CefWindowHandle' : ['cef_window_handle_t', 'NULL'],
'CefRect' : ['cef_rect_t', 'CefRect()'],
'CefThreadId' : ['cef_thread_id_t', 'TID_UI'],
'CefTime' : ['cef_time_t', 'CefTime()'],
}
if value in simpletypes.keys():
return {
'result_type' : 'simple',
'result_value' : simpletypes[value]
'result_value' : simpletypes[value][0],
'result_default' : simpletypes[value][1],
}
# check if already a C API structure
@ -1079,7 +1422,8 @@ class obj_analysis:
if len(list) == 1:
return {
'result_type' : 'refptr',
'result_value' : get_capi_name(list[0], True)+'*'
'result_value' : get_capi_name(list[0], True)+'*',
'refptr_type' : list[0]
}
# check for CEF structure types
@ -1103,13 +1447,27 @@ class obj_analysis:
return self.name
def get_value(self):
""" Return the name. """
""" Return the C++ value (type + name). """
return self.value
def get_type(self):
""" Return the type. """
""" Return the C++ type. """
return self.type
def get_refptr_type(self):
""" Return the C++ class type referenced by a CefRefPtr. """
if self.is_result_vector() and self.is_result_vector_refptr():
# return the vector RefPtr type
return self.result_value[0]['refptr_type']
# return the basic RefPtr type
return self.refptr_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
@ -1126,6 +1484,10 @@ class obj_analysis:
""" 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 = ''
@ -1136,10 +1498,18 @@ class obj_analysis:
result += '*'
return result
def get_result_simple_default(self):
""" Return the default value fo the basic type. """
return self.result_default
def is_result_refptr(self):
""" Returns true if this is a reference pointer type. """
return (self.result_type == 'refptr')
def get_result_refptr_type_root(self):
""" Return the refptr type structure name. """
return self.result_value[:-1]
def get_result_refptr_type(self, defined_structs = []):
""" Return the refptr type. """
result = ''
@ -1154,12 +1524,19 @@ class obj_analysis:
""" 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 = ''
# structure values that are passed by reference or address must be
# structures and not enumerations
if self.is_byref() or self.is_byaddr():
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:
@ -1167,7 +1544,7 @@ class obj_analysis:
else:
result += 'enum '
result += self.result_value
if self.is_byref() or self.is_byaddr():
if not is_enum:
result += '*'
return result
@ -1192,6 +1569,22 @@ class obj_analysis:
""" 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_refptr(self):
""" Returns true if this is a string vector. """
return self.result_value[0]['result_type'] == 'refptr'
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():
@ -1209,7 +1602,8 @@ class obj_analysis:
if type == 'simple':
str = value
if self.is_const():
str += ' const*'
str += ' const'
str += '*'
result['value'] = str
elif type == 'refptr':
str = ''
@ -1217,25 +1611,29 @@ class obj_analysis:
str += 'struct _'
str += value
if self.is_const():
str += ' const*'
str += ' const'
str += '*'
result['value'] = str
else:
raise Exception('Unsupported vector type: '+type)
if self.is_const():
# const vector values must be passed as the value array parameter
# and a size parameter
result['format'] = 'multi-arg'
else:
# non-const vector values must be passed as one function to get the
# size and another function to get the element at a specified index
result['format'] = 'multi-func'
# 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():
@ -1278,7 +1676,7 @@ class obj_analysis:
format = resdict['format']
result += resdict['value']
if self.has_name() and format != 'multi-func':
if self.has_name():
result += ' '+self.get_name();
return {'format' : format, 'value' : result}