def getArgs(func_el): # # Returns a list with one dict per argument. # Each dict contains the following keywords: # # 'name', 'type', 'kw', 'id', 'native', 'fundamental', 'enumeration', 'loaded_class', # 'known_class', 'type_namespaces', 'default', 'function_pointer' # args = [] argc = 1 for sub_el in func_el.getchildren(): if sub_el.tag == 'Argument': arg_dict = OrderedDict() if 'name' in sub_el.keys(): arg_dict['name'] = sub_el.get('name') else: arg_dict['name'] = 'arg_' + str(argc) argc += 1 arg_type_dict = utils.findType(sub_el) pointerness = arg_type_dict['pointerness'] is_ref = arg_type_dict['is_reference'] arg_kw = arg_type_dict['cv_qualifiers'] arg_id = arg_type_dict['id'] arg_type_el = arg_type_dict['el'] is_func_ptr = arg_type_dict['is_function_pointer'] arg_type = arg_type_dict['name'] + '*'*pointerness + '&'*is_ref arg_dict['type'] = arg_type arg_dict['kw'] = arg_kw arg_dict['id'] = arg_id arg_dict['function_pointer'] = is_func_ptr arg_dict['native'] = utils.isNative(arg_type_el) arg_dict['fundamental'] = utils.isFundamental(arg_type_el) arg_dict['enumeration'] = utils.isEnumeration(arg_type_el) arg_dict['loaded_class'] = utils.isLoadedClass(arg_type_el) arg_dict['known_class'] = utils.isKnownClass(arg_type_el) arg_dict['type_namespaces'] = utils.getNamespaces(arg_type_el) if 'default' in sub_el.keys(): arg_dict['default'] = True else: arg_dict['default'] = False args.append(arg_dict) return args
def usesLoadedType(func_el): uses_loaded_type = False return_type_dict = utils.findType(func_el) return_is_loaded = utils.isLoadedClass( return_type_dict['el'] ) args = getArgs(func_el) is_arg_loaded = [arg_dict['loaded_class'] for arg_dict in args] if (return_is_loaded) or (True in is_arg_loaded): uses_loaded_type = True return uses_loaded_type
def generateFunctionWrapperClassVersion(func_el, wr_func_name, namespaces, n_overloads): new_code = '' # Check if this function makes use of any loaded types uses_loaded_type = funcutils.usesLoadedType(func_el) # Function name func_name = func_el.get('name') # Determine return type return_type_dict = utils.findType(func_el) return_el = return_type_dict['el'] pointerness = return_type_dict['pointerness'] is_ref = return_type_dict['is_reference'] return_type_kw = return_type_dict['cv_qualifiers'] return_kw_str = ' '.join(return_type_kw) + ' ' * bool(len(return_type_kw)) return_is_loaded = utils.isLoadedClass(return_el) return_type = return_type_dict['name'] + '*' * pointerness + '&' * is_ref # If return type is a known class, add '::' for absolute namespace. if (not return_is_loaded) and utils.isKnownClass(return_el): return_type = '::' + return_type # If return-by-value, then a const qualifier on the return value is meaningless # (will result in a compiler warning) if (pointerness == 0) and (is_ref == False): if 'const' in return_type_kw: return_type_kw.remove('const') # Arguments args = funcutils.getArgs(func_el) # One function for each set of default arguments n_overloads = funcutils.numberOfDefaultArgs(func_el) for remove_n_args in range(n_overloads + 1): # Check that the function is acceptable if funcutils.ignoreFunction(func_el, limit_pointerness=True, remove_n_args=remove_n_args): continue if remove_n_args == 0: use_args = args else: use_args = args[:-remove_n_args] # Argument bracket args_bracket = funcutils.constrArgsBracket(use_args, include_arg_name=True, include_arg_type=True, include_namespace=True, use_wrapper_class=True) # Name of original function to call call_func_name = func_name # Convert return type if loaded class if utils.isLoadedClass(return_el): wrapper_return_type = classutils.toWrapperType( return_type, remove_reference=True) else: wrapper_return_type = return_type # Write declaration line new_code += return_kw_str + wrapper_return_type + ' ' + wr_func_name + args_bracket + '\n' # Write function body indent = ' ' * cfg.indent new_code += '{\n' if return_type == 'void': new_code += indent else: new_code += indent + 'return ' # args_bracket_notypes = funcutils.constrArgsBracket(use_args, include_arg_name=True, include_arg_type=False, wrapper_to_pointer=True) args_bracket_notypes = funcutils.constrArgsBracket( use_args, include_arg_name=True, include_arg_type=False, cast_to_original=True, wrapper_to_pointer=True) if return_is_loaded: abs_return_type_simple = classutils.toAbstractType( return_type, include_namespace=True, remove_reference=True, remove_pointers=True) wrapper_return_type_simple = wrapper_return_type.replace( '*', '').replace('&', '') if is_ref: # Return-by-reference new_code += 'reference_returner< ' + wrapper_return_type_simple + ', ' + abs_return_type_simple + ' >( ' + call_func_name + args_bracket_notypes + ' );\n' elif (not is_ref) and (pointerness > 0): # Return-by-pointer new_code += 'pointer_returner< ' + wrapper_return_type_simple + ', ' + abs_return_type_simple + ' >( ' + call_func_name + args_bracket_notypes + ' );\n' else: # Return-by-value new_code += wrapper_return_type + '( ' + call_func_name + args_bracket_notypes + ' );\n' else: new_code += call_func_name + args_bracket_notypes + ';\n' new_code += '}\n' new_code += '\n' # Add 'extern "C" {...}' block new_code = 'extern "C"\n{\n' + new_code + '}\n' return new_code
def constrArgsBracket(args, include_arg_name=True, include_arg_type=True, include_namespace=False, cast_to_original=False, use_wrapper_class=False, wrapper_to_pointer=False, add_namespace_to_loaded=''): # # Requires a list of dicts as input, as returned by 'getArgs' or 'constrWrapperArgs'. # import modules.classutils as classutils # Construct bracket with input arguments args_seq = '' argc = 1 for i in range(len(args)): # We must create a new copy since we may be altering the content later arg_dict = OrderedDict(args[i]) if arg_dict['loaded_class'] and (add_namespace_to_loaded != ''): add_namespaces = add_namespace_to_loaded.split('::') arg_dict['type_namespaces'] = add_namespaces + arg_dict['type_namespaces'] arg_dict['type'] = add_namespace_to_loaded + '::' + arg_dict['type'] if include_arg_name and cast_to_original: if arg_dict['loaded_class']: # We assume that arg_dict['type'] *is* the original type! cast_to_type = arg_dict['type'] if include_namespace: namespaces = arg_dict['type_namespaces'] if len(namespaces)>0: cast_to_type = '::'.join(namespaces) + '::' + cast_to_type # If argument type is not pointer or reference, add a reference operator '&' check_type = cast_to_type.split('<')[0] if ('*' not in check_type) and ('&' not in check_type): cast_to_type = cast_to_type + '&' # Add qualifiers if len(arg_dict['kw']) > 0: qualifiers = ' '.join(arg_dict['kw']) cast_to_type = qualifiers + ' ' + cast_to_type # Determine what argument name to use (arg_name or *arg_name.get_BEptr() or ...) if wrapper_to_pointer: if arg_dict['type'].count('*') == 0: use_name = '*' + arg_dict['name'] + '.get_BEptr()' elif arg_dict['type'].count('*') == 1: use_name = '(*' + arg_dict['name'] + ')' + '.get_BEptr()' args_seq += 'dynamic_cast< ' + cast_to_type + ' >(' + use_name + ')' else: args_seq += 'dynamic_cast< ' + cast_to_type + ' >(' + arg_dict['name'] + ')' else: args_seq += arg_dict['name'] else: if include_arg_type: args_seq += ''.join([ kw+' ' for kw in arg_dict['kw'] ]) if use_wrapper_class and arg_dict['loaded_class'] == True: args_seq += classutils.toWrapperType(arg_dict['type'], include_namespace=include_namespace) else: if include_namespace: # If known class, add '::' for absolute namespace if arg_dict['known_class']: args_seq += '::' + arg_dict['type'] else: args_seq += arg_dict['type'] else: args_seq += utils.removeNamespace(arg_dict['type']) if include_arg_type and include_arg_name: args_seq += ' ' if include_arg_name: if utils.isLoadedClass(arg_dict['type'], byname=True) and wrapper_to_pointer: if arg_dict['type'].count('*') == 0: args_seq += '*' + arg_dict['name'] + '.get_BEptr()' elif arg_dict['type'].count('*') == 1: args_seq += '(*' + arg_dict['name'] + ')' + '.get_BEptr()' else: raise Exception('funcutils.constrArgsBracket cannot presently deal with arguments of type pointer-to-pointer for wrapper classes.') else: args_seq += arg_dict['name'] args_seq += ', ' args_seq = args_seq.rstrip(', ') args_seq = args_seq.strip() args_bracket = '(' + args_seq + ')' return args_bracket
def ignoreFunction(func_el, limit_pointerness=False, remove_n_args=0, print_warning=True): # TODO: When BOSS starts accepting template functions, add a check for the template arguments import modules.classutils as classutils func_name = getFunctionNameDict(func_el) # Should this function be ditched? if func_name['long_templ_args'] in cfg.ditch: return True # Ignore templated functions (BOSS cannot deal with that yet...) if utils.isTemplateFunction(func_el): if print_warning: reason = "Templated function. BOSS cannot deal with this yet." infomsg.IgnoredFunction(func_name['long_templ_args'], reason).printMessage() return True # Check if this is an operator function is_operator = False if func_el.tag == 'OperatorMethod': is_operator = True # Check function return type if 'returns' in func_el.keys(): return_type_dict = utils.findType(func_el) return_type = return_type_dict['name'] + '*'*return_type_dict['pointerness'] + '&'*return_type_dict['is_reference'] return_el = return_type_dict['el'] if not utils.isAcceptedType(return_el): if print_warning: reason = "Non-accepted return type '%s'." % return_type infomsg.IgnoredFunction(is_operator*'operator'+func_name['long_templ_args'], reason).printMessage() return True # Check argument types arg_types_accepted = True args = getArgs(func_el) use_n_args = len(args) - remove_n_args if remove_n_args > 0: args = args[:-remove_n_args] for arg_dict in args: arg_type_name = arg_dict['type'] arg_el = gb.id_dict[arg_dict['id']] # Find out if argument type is base type of any accepted type is_parent_of_accepted= False if utils.isNative(arg_el): arg_class_name = classutils.getClassNameDict(arg_el) if arg_class_name['long_templ'] in gb.parents_of_loaded_classes: is_parent_of_accepted = True if arg_dict['function_pointer']: if print_warning: reason = "Function pointer type argument, '%s'." % arg_dict['name'] infomsg.IgnoredFunction(is_operator*'operator'+func_name['long_templ_args'], reason).printMessage() arg_types_accepted = False break if (not utils.isAcceptedType(arg_el)): # and (not is_parent_of_accepted): if print_warning: reason = "Non-accepted argument type '%s'." % arg_type_name infomsg.IgnoredFunction(is_operator*'operator'+func_name['long_templ_args'], reason).printMessage() arg_types_accepted = False break if limit_pointerness == True: if utils.isLoadedClass(arg_el): if ('**' in arg_type_name) or ('*&' in arg_type_name): if print_warning: reason = "Argument of type pointer-to-pointer/reference-to-pointer to loaded class, '%s'." % arg_type_name infomsg.IgnoredFunction(is_operator*'operator'+func_name['long_templ_args'], reason).printMessage() arg_types_accepted = False break if (not arg_types_accepted): return True # Function accepted (i.e. should *not* be ignored) return False