Example #1
0
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
Example #2
0
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
Example #3
0
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
Example #4
0
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
Example #5
0
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