Esempio n. 1
0
def parse_include(indent, include, path):
    if 'pack' in include:
        return

    include, comment = parse_comment(include)

    module_name = include.replace('#include', '').replace('# include', '')
    module_name = module_name.replace('<', '').replace('>', '').strip()
    if module_name.endswith('.h'):
        module_name = module_name[:-2]

    module_name = module_name.replace('.', '_').replace('"', '').lower()

    if module_name.isdigit():
        module_name = '_' + module_name

    print(module_name)
    res = locate_module(include, module_name, '.', path)

    if res is not None:
        print('{0}from .{1} import *{2}'.format(indent, res, comment))
Esempio n. 2
0
def parse_struct_union(indent,
                       data,
                       importer,
                       struct_count,
                       union_count,
                       declarations,
                       declare=False):
    import sys

    lines = data.split('\n')

    saved_lines = lines[:]

    for i, line in enumerate(lines):
        line = line.replace('__WRAPPED__', '')
        if '_Struct_size_bytes_' in line:
            l1, l2 = line.split('_Struct_size_bytes_(', 1)
            l2 = l2.split(')', 1)[1]
            line = l1 + l2

        if '_Union_size_bytes_' in line:
            l1, l2 = line.split('_Union_size_bytes_(', 1)
            l2 = l2.split(')', 1)[1]
            line = l1 + l2
        lines[i] = line

    lines[0] = parse_comment(lines[0])[0]

    if len(lines) == 1:
        line = lines[0]
        line, comment = parse_comment(line)

        lines = line.split(' ')
        attr_name = lines[-1].replace(';', '').strip()
        value = lines[-2].strip()

        attr_name, value = process_param(attr_name, value)
        try:
            line = indent + attr_name + ' = ' + value + '\n'
            if comment:
                comment = equalize_width(indent, comment)
                print('\n' + comment)

            print(line)

        except TypeError:
            print(indent + '# STRUCT ERROR 1:', lines)
            return struct_count, union_count
        return struct_count, union_count

    if 'struct' not in lines[0] or 'union' not in lines[0]:
        lines[0] += ' ' + lines.pop(1).lstrip()

    start_data = ''

    comments = ''

    while '{' not in start_data:
        try:
            line, comment = parse_comment(lines.pop(0))
            if comment:
                comment = equalize_width(indent, comment)
                comments += comment
            start_data += ' ' + line.strip()
        except IndexError:
            break
    if comments:
        print('\n' + comments)

    try:
        start_data, extra = start_data.split('{', 1)
    except ValueError:
        start_data = start_data.replace('{', '').strip()
        extra = ''

    if extra.strip():
        lines.insert(0, extra)

    if 'public' in start_data:
        brace_count = 0
        start = None
        for i, line in enumerate(lines):
            if line.strip().startswith('typedef '):
                start = i
            if start is not None:
                brace_count += line.count('{')
                brace_count -= line.count('}')

                if ';' in line and brace_count == 0:
                    stop = i
                    break
        else:
            return struct_count, union_count

        res = parse_struct_union(indent, '\n'.join(lines[start:stop]),
                                 importer, struct_count, union_count,
                                 declarations, declare)

        return res + (stop, )
    try:
        parent_cls, cls_name = start_data.rstrip().rsplit(' ', 1)
    except ValueError:
        brace_count = 1
        cls_names = ''
        end_index = 0

        for i, line in enumerate(lines):
            brace_count += line.count('{')
            brace_count -= line.count('}')
            if brace_count == 0:
                cls_names += line
                end_index = i

            if ';' in line and brace_count == 0:
                break
        else:
            print(indent + '# STRUCT ERROR 2:', lines)
            return struct_count, union_count

        cls_names = cls_names.replace(';', '').replace('}', '').strip()
        if not cls_names:
            print(indent + '# STRUCT ERROR 3:', lines)
            return struct_count, union_count

        cls_names = cls_names.split(' ')
        cls_name = cls_names[0]
        parent_cls = start_data.strip()
        lines = lines[:end_index]
        lines[end_index] = '} ' + ' '.join(cls_names[1:]) + ';'

    parent_cls = parent_cls.replace('typedef', '')
    cls_name = cls_name.replace('typedef', '')

    if 'struct' in parent_cls or 'struct' in cls_name:
        parent_cls = parent_cls.replace('struct', '').strip()
        cls_name = cls_name.replace('struct', '').strip()
        data_type = 'ctypes.Structure'
    else:
        parent_cls = parent_cls.replace('union', '').strip()
        cls_name = cls_name.replace('union', '').strip()
        data_type = 'ctypes.Union'

    if not parent_cls or 'DECLSPEC_ALIGN' in parent_cls:
        parent_cls = data_type

    cls_name = cls_name.replace('{', '').strip()
    if ';' in cls_name:
        cls_name = cls_name.replace(';', '').strip()
        if parent_cls in ('ctypes.Structure', 'ctypes.Union'):
            if declare:
                u_s_declarations.append(
                    TEMPLATE_DECLARATION.format(indent='',
                                                cls_name=cls_name,
                                                parent_cls=parent_cls))
            else:
                print(
                    TEMPLATE_DECLARATION.format(indent=indent,
                                                cls_name=cls_name,
                                                parent_cls=parent_cls))
                print('\n')
            return struct_count, union_count
        else:
            if parent_cls == cls_name:
                print(indent + '# STRUCT ERROR 4:', lines)
                return struct_count, union_count

            if '*' in cls_name or '*' in parent_cls:
                cls_name, parent_cls = process_param(cls_name, parent_cls)
                print(indent + cls_name + ' = ' + parent_cls)
            else:
                declarations += [cls_name]
                if declare:
                    u_s_declarations.append(
                        TEMPLATE_DECLARATION.format(indent='',
                                                    cls_name=cls_name,
                                                    parent_cls=parent_cls))
                else:
                    print(
                        TEMPLATE_DECLARATION.format(indent=indent,
                                                    cls_name=cls_name.strip(),
                                                    parent_cls=parent_cls))
                    print('\n')

            return struct_count, union_count
    try:
        var_names = data.rsplit('}', 1)[1].replace(';', '')
    except:
        var_names = data.replace(';', '')

    var_names = list(n.strip() for n in var_names.split(','))

    if not cls_name and var_names:
        cls_name = var_names.pop(0)

    elif not cls_name:
        print(indent + 'STRUCT ERROR 5:', lines)
        return struct_count, union_count

    if cls_name in var_names:
        var_names.remove(cls_name)

    if cls_name not in declarations:
        declarations += [cls_name.strip()]

        if declare:
            for item in u_s_declarations:
                if item.startswith('class ' + cls_name + '('):
                    print(indent + '# STRUCT ERROR 6:', cls_name, lines)
                    break
            else:
                u_s_declarations.append(
                    TEMPLATE_DECLARATION.format(indent='',
                                                cls_name=cls_name.strip(),
                                                parent_cls=parent_cls))
        else:
            print(
                TEMPLATE_DECLARATION.format(indent=indent,
                                            cls_name=cls_name.strip(),
                                            parent_cls=parent_cls))
            print('\n')
    # else:
    # sys.stderr.write('STRUCT ERROR: ' + str(lines) + '\n')
    # return struct_count, union_count

    anonymous = []
    fields = []
    sub_structure_type = None
    field = ''
    chained_comment = False
    field_comment = ''
    field_macro = ''
    macro_output = None
    skip_until = None

    data_fields = '~~~~'.join(lines)
    data_fields = data_fields[:data_fields.rfind('}')].split('~~~~')

    found_defines = []

    sys.stderr.write('STRUCTURE DATAFIELDS: ' + str(data_fields) + '\n')

    if '                        struct' in data_fields:
        sys.stderr.write('SUBTYPE: ' + cls_name + '\n')

    for line_num, line in enumerate(data_fields):

        if skip_until is not None:
            if line_num <= skip_until:
                continue

            skip_until = None

        if (line.strip().startswith('# define')
                or line.strip().startswith('#define')):
            var_name, var_value = line.strip()[1:].replace('define', '',
                                                           1).strip().split(
                                                               ' ', 1)
            var_name = var_name.strip()
            var_value = var_value.strip()

            if var_value.startswith('('):
                var_value = var_value[1:].strip()

            def_template = '{0}{1} = {2}'.format(indent, var_name, var_value)

            if len(def_template) > 76:
                def_template = '{0}{1} = (\n{0}    {2}\n{0})'.format(
                    indent, var_name, var_value)
            print(def_template)
            continue

        if (line.strip().startswith('#endif')
                or line.strip().startswith('# endif')):
            field_macro = ''
            fields += [[line, '']]
            indent = indent[:-4]
            macro_output = None
            continue

        for item in ('ifdef', 'ifndef', 'if', 'elif', 'else'):
            if (line.strip().startswith('#' + item)
                    or line.strip().startswith('# ' + item)):
                define = True
                break
        else:
            define = False

        if define:
            macro_output = []
            import sys

            stdout = sys.stdout

            class STDOut(object):
                def write(self, data):
                    sys.stderr.write(data + '\n')
                    macro_output.append(data)

                def __getattr__(self, item):
                    if item in self.__dict__:
                        return self.__dict__[item]
                    return getattr(STDOut.stdout, item)

            sys.stdout = STDOut()
            _, indent = parse_macro(indent, line.strip(), struct=True)
            sys.stdout = stdout
            field_macro = line
            continue

        if ' ' not in line.strip(
        ) and 'struct' not in line and 'union' not in line:
            continue

        if chained_comment and '*/' not in line:
            continue

        chained_comment = False

        if sub_structure_type is None:
            line, comment = parse_comment(line)
        else:
            comment = ''

        if line is None and comment is None:
            comment = ''
            chained_comment = True
            for comnt in data_fields[line_num:]:
                comnt = comnt.strip()

                if (not comnt.startswith('**/') and not comnt.startswith('*/')
                        and comnt.startswith('*')):
                    comnt = comnt[1:].strip()

                comment += ' ' + comnt
                if '*/' in comnt:
                    break

            line, comment = parse_comment(comment)
            field_comment = equalize_width(indent + '    ', comment)

            if not line:
                continue

        elif comment:
            field_comment = equalize_width(indent + '    ', comment)

        if not line:
            continue

        if line.startswith('#'):
            continue

        if '_Field_' in line:
            chunk_1, chunk_2 = line.split('_Field_', 1)
            chunk_2 = chunk_2.split('(', 1)[1]
            bad_chunk = ''
            b_count = 1
            for char in list(chunk_2):
                b_count += char.count('(')
                b_count -= char.count(')')
                bad_chunk += char
                if not b_count:
                    break
            else:
                continue

            chunk_2 = chunk_2.replace(bad_chunk, '', 1)
            line = chunk_1 + chunk_2

            if not line.strip():
                continue

        if 'OPTIONAL' in line:
            line = line[:line.find('OPTIONAL') - 1].rstrip()

        if sub_structure_type is None:
            if ((line.strip().startswith('union')
                 or line.strip().startswith('struct'))
                    and line.strip().endswith(';')):
                line = line.replace('struct', '').replace('union', '')
            if line.strip().startswith('union'):
                sub_structure_type = 'union'

            elif line.strip().startswith('struct'):
                sub_structure_type = 'struct'

        if sub_structure_type is not None:
            if line.strip().endswith(';'):
                mult = None
                line = line.replace(sub_structure_type, '').strip()[:-1]
                try:
                    p_cls, c_name = line.split(' ')
                except ValueError:
                    c_name = line
                    if sub_structure_type == 'union':
                        p_cls = 'ctypes.Union'
                    else:
                        p_cls = 'ctypes.Structure'

                if '*' in c_name:
                    f_name, f_data_type = process_param(
                        c_name, c_name.replace('*', ''))

                else:
                    f_name = c_name
                    f_data_type = cls_name + '.' + f_name
                    if macro_output is not None:
                        print(''.join(macro_output))
                        macro_output = None

                    print(
                        TEMPLATE_DECLARATION.format(indent=indent,
                                                    cls_name=f_name,
                                                    parent_cls=p_cls))
                    print('\n')
                    print(
                        TEMPLATE_DECLARATION_SUBSTRUCTURE.format(
                            indent=indent, cls_name=cls_name,
                            child_cls=f_name))
                sub_structure_type = None
            else:
                sub_structure = []
                brace_count = 0

                skip_until = line_num
                for j, sub_line in enumerate(data_fields[line_num:]):
                    skip_until = line_num + j
                    sub_structure += [sub_line]
                    brace_count += sub_line.count('{')
                    brace_count -= sub_line.count('}')
                    if ';' in sub_line and brace_count == 0:
                        break

                sys.stderr.write('SUBSTRUCTURE: ' + str(sub_structure) + '\n')

                f_name = sub_structure[-1]

                f_name = (f_name.replace(';', '').replace('}', '').strip())
                if not f_name:
                    if sub_structure_type == 'union':
                        sub_count = union_count = union_count + 1
                    else:
                        sub_count = struct_count = struct_count + 1

                    f_name = '_{0}_{1}'.format(sub_structure_type.title(),
                                               sub_count)
                    sub_structure[len(sub_structure) -
                                  1] = (sub_structure[len(sub_structure) -
                                                      1].replace(
                                                          ';', f_name + ';'))

                    anonymous += [f_name]

                if '[' in f_name:
                    tmp_field_name, mult = f_name.split('[', 1)
                    mult = mult.replace(']', '').strip()

                    for i, ln in enumerate(sub_structure):
                        sub_structure[i] = ln.replace(f_name, tmp_field_name)
                    f_name = tmp_field_name

                else:
                    mult = None

                sub_structure[0] = (sub_structure[0].replace(
                    sub_structure_type,
                    '{0}typedef {1} '.format(indent, sub_structure_type)))

                if macro_output is not None:
                    print(''.join(macro_output))
                    macro_output = None

                parse_struct_union(indent, '\n'.join(sub_structure), importer,
                                   struct_count, union_count, [])

                f_data_type = cls_name + '.' + f_name
                sub_structure_type = None

                print(
                    TEMPLATE_DECLARATION_SUBSTRUCTURE.format(indent=indent,
                                                             cls_name=cls_name,
                                                             child_cls=f_name))

            if '\n' in field_comment:
                fields += [[field_macro, '\n' + field_comment]]
                field_comment = ''

            elif field_comment:
                field_comment = ' ' + field_comment[field_comment.find('#'):]

            if mult:
                if ':' in f_name:
                    f_name, f_bit = f_name.split(':')
                    f_name = f_name.strip()
                    f_bit = f_bit.strip()
                    template = TEMPLATE_DECLARATION_FIELD_BIT.format(
                        indent=indent,
                        field_name=f_name,
                        field_data_type=f_data_type + ' * ' + mult,
                        field_bit=f_bit,
                        comment='')

                else:
                    template = TEMPLATE_DECLARATION_FIELD.format(
                        indent=indent,
                        field_name=f_name,
                        field_data_type=f_data_type + ' * ' + mult,
                        comment='')

                if field_comment is not None and field_comment.strip():
                    field_comment = equalize_width(indent + '    ',
                                                   field_comment)
                    template = '\n\n' + field_comment + '\n' + template

                fields += [[field_macro, template]]
            else:
                if ':' in f_name:
                    f_name, f_bit = f_name.split(':')
                    f_name = f_name.strip()
                    f_bit = f_bit.strip()
                    template = TEMPLATE_DECLARATION_FIELD_BIT.format(
                        indent=indent,
                        field_name=f_name,
                        field_data_type=f_data_type,
                        field_bit=f_bit,
                        comment='')

                else:
                    template = TEMPLATE_DECLARATION_FIELD.format(
                        indent=indent,
                        field_name=f_name,
                        field_data_type=f_data_type,
                        comment='')

                if field_comment is not None and field_comment.strip():
                    field_comment = equalize_width(indent + '    ',
                                                   field_comment)
                    template = '\n\n' + field_comment + '\n' + template

                fields += [[field_macro, template]]

            field_comment = ''
            continue

        elif field:
            line = line.strip()
            if line.endswith('\\'):
                line = line[:-1].strip()
            field += ' ' + line
            if not line.endswith(';'):
                continue

        elif line.rstrip().endswith(';'):
            field = line
        else:
            line = line.strip()
            if line.endswith('\\'):
                line = line[:-1].strip()

            field = line
            continue

        try:
            field_data_type, field_name = (field[:-1].replace(
                ';', '').strip().split(' ', 1))
        except ValueError:
            if '}' in field:
                continue

            import sys

            parent_cls = line.replace(';', '').strip()
            for i, item in enumerate(u_s_declarations):
                if item.startswith('class ' + cls_name + '('):
                    u_s_declarations[i] = TEMPLATE_DECLARATION.format(
                        indent='', cls_name=cls_name, parent_cls=parent_cls)
                    break
            else:
                sys.stderr.write('******* ' + str(field) + '\n')
                raise

            continue

        if ',' in field_name:
            field_names = list(fn.strip() for fn in field_name.split(','))
            count = []
        elif '[' in field_name:
            count = []
            while '[' in field_name:
                field_name, c = field_name.rsplit('[', 1)
                count.insert(0, c.replace(']', '').strip())
            field_names = [field_name]
        else:
            count = []
            field_names = [field_name.strip()]

        for i, field_name in enumerate(field_names):
            while ' ' in field_name:
                try:
                    field_data_type, field_name = (field_data_type.split(
                        ' ', 1))
                except ValueError:
                    break
            field_names[i] = field_name.strip()

        field_data_type = field_data_type.strip()
        field_data_type = field_data_type.replace('IUnknown',
                                                  'comtypes.IUnknown')

        field_data_types = []
        for i, field_name in enumerate(field_names):

            field_name, fd_type = process_param(field_name, field_data_type)

            field_data_types += [fd_type]
            field_names[i] = field_name

        for i, field_data_type in enumerate(field_data_types):
            fd_type = field_data_type
            for j, cnt in enumerate(count):
                if j == 1:
                    fd_type = '(' + fd_type + ')'
                if j:
                    fd_type += '({0} * {1})'.format(field_data_type, cnt)
                else:
                    fd_type += ' * ' + cnt

            field_data_types[i] = fd_type

        for i, field_name in enumerate(field_names):

            if '\n' in field_comment:
                fields += [[field_macro, '\n' + field_comment]]
                field_comment = ''

            elif field_comment:
                field_comment = ' ' + field_comment[field_comment.find('#'):]

            if field_name is None:
                continue

            if field_data_types[i] in ('_In_', '_Out_', 'IN', 'OUT',
                                       '_Inout_'):
                try:
                    field_data_types[i], field_name = field_name.split(' ', 1)
                except ValueError:
                    sys.stderr.write(str(saved_lines) + '\n')
                    raise
                field_data_types[i] = field_data_types[i].strip()
                field_name = field_name.strip()

                field_name, field_data_types[i] = process_param(
                    field_name, field_data_types[i])

            if ':' in field_name and '>::' not in field_name:
                field_name, field_bit = field_name.split(':')
                field_name = field_name.strip()
                field_bit = field_bit.strip()
                template = TEMPLATE_DECLARATION_FIELD_BIT.format(
                    indent=indent,
                    field_name=field_name,
                    field_data_type=field_data_types[i],
                    field_bit=field_bit,
                    comment='')

            else:
                template = TEMPLATE_DECLARATION_FIELD.format(
                    indent=indent,
                    field_name=field_name,
                    field_data_type=field_data_types[i],
                    comment='')

            if field_comment is not None and field_comment.strip():
                field_comment = equalize_width(indent + '    ', field_comment)
                template = '\n\n' + field_comment + '\n' + template

            fields += [[field_macro, template]]

        field_comment = ''
        field = ''

    if not cls_name:
        return struct_count, union_count

    if anonymous:
        print(
            TEMPLATE_DECLARATION_ANONYMOUS_START.format(indent=indent,
                                                        cls_name=cls_name))

        for anon in anonymous:
            print(
                TEMPLATE_DECLARATION_ANONYMOUS.format(indent=indent,
                                                      anonymous=anon))
        print(TEMPLATE_DECLARATION_ANONYMOUS_END.format(indent=indent, ))

    print(('\n'.join(found_defines)))
    if found_defines:
        print()

    if fields:
        for items in fields:
            if items[0]:
                has_macro = True
                break
        else:
            has_macro = False

        last_field = ''
        if has_macro:
            print(
                TEMPLATE_DECLARATION_FIELDS_MACRO_START.format(
                    indent=indent, cls_name=cls_name))

            last_macro = ''
            closed_macro = False
            for macro, field in fields:
                if macro and macro != last_macro:
                    last_macro = macro
                    closed_macro = True
                    print(
                        TEMPLATE_DECLARATION_FIELDS_MACRO_END.format(
                            indent=indent))
                    if '#else' in macro:
                        _, indent = parse_macro(indent,
                                                macro.strip(),
                                                struct=True)
                    else:
                        _, indent = parse_macro(indent + '    ',
                                                macro.strip(),
                                                struct=True)
                        indent = indent[:-4]

                    if 'endif' in macro:
                        print()

                if not field:
                    continue

                if closed_macro:
                    closed_macro = False
                    print(
                        TEMPLATE_DECLARATION_FIELDS_MACRO_CONTINUE.format(
                            indent=indent, cls_name=cls_name))
                if field.startswith('\n\n') and last_field.endswith('\n'):
                    field = field[2:]

                last_field = field
                print(field)

            if not closed_macro:
                print(
                    TEMPLATE_DECLARATION_FIELDS_MACRO_END.format(
                        indent=indent))

            print(
                TEMPLATE_DECLARATION_FIELDS_MACRO_ASSIGN.format(
                    indent=indent, cls_name=cls_name))

        else:
            print(
                TEMPLATE_DECLARATION_FIELDS_START.format(indent=indent,
                                                         cls_name=cls_name))

            for _, field in fields:
                if field.startswith('\n\n') and last_field.endswith('\n'):
                    field = field[2:]

                last_field = field
                print(field)

            print(TEMPLATE_DECLARATION_FIELDS_END.format(indent=indent, ))

    variables = []

    for var_name in var_names:
        if not var_name:
            continue

        var_name, value = process_param(var_name, cls_name)

        if var_name is None:
            continue

        if declare:
            variables += [var_name + ' = ' + value]

        else:
            variables += [indent + var_name + ' = ' + value]

    if variables:
        variables = '\n'.join(variables)
        if declare:
            u_s_declarations.append(variables + '\n')
        else:
            print(variables)
    elif declare:
        u_s_declarations.append('\n')

    return struct_count, union_count
Esempio n. 3
0
def parse_interface(indent, methods, importer, interface_data, dec):

    if isinstance(interface_data, dict):

        if 'declared' in interface_data and dec:
            dec = False

        if dec is True:
            help_string = get_help_string(indent, interface_data)
            interface_data['iid'] = interface_data['iid'].format(indent=indent)
            interface_data['declared'] = True

            if interface_data['co_class']:
                co_class = TEMPLATE_COCLASS.format(indent='',
                                                   helpstring=help_string,
                                                   **interface_data)
                interface_declarations.append(co_class)

            elif interface_data['library']:
                library = TEMPLATE_LIBRARY.format(indent='',
                                                  helpstring=help_string,
                                                  **interface_data)

                interface_declarations.append(library)
            else:
                interface = TEMPLATE_INTERFACE.format(indent='',
                                                      helpstring=help_string,
                                                      **interface_data)

                interface_declarations.append(interface)
            return

        if interface_data['co_class'] or interface_data['library']:
            return

        cls_name = interface_data['cls_name']

    else:
        cls_name = interface_data

    chained_comment = False
    chained_method = False
    found_methods = []

    skip_dict = None
    for line_num, method in enumerate(methods):
        if not isinstance(interface_data, dict):
            if skip_dict is not None:
                if line_num != skip_dict:
                    continue
                skip_dict = None
            import sys

            if method.strip().startswith('virtual'):
                method = method.replace('virtual', '')
                method, method_options = parse_comment(method)
                method_options = method_options.replace('#', '').strip()

                method = method.replace('STDMETHODCALLTYPE ', '').strip()

                skip_dict = line_num + 1
                found_params = []
                if not method.strip().endswith(';'):
                    while method.count('(') - 1 != method.count(')'):
                        method = method.replace('(', '')
                        method = method.replace(')', '')

                method_data_type, method_name = method.split(' ', 1)
                method_name = method_name.split('(', 1)[0]
                method_name = method_name.strip()

                method_options = method_options.replace('[helpstring]', '')
                method_options = method_options.replace('[id]', '')

                if method_options.strip():
                    method_options = method_options.replace('][', ', ')
                    method_options = method_options.replace('] [', ', ')
                    method_options = Options(method_options)
                    method_options = "[helpstring('Method {0}'), {1}]".format(
                        method_name,
                        str(method_options)[1:-1])
                else:
                    method_options = "[helpstring('Method {0}')]".format(
                        method_name)

                sys.stderr.write('METHOD: ' + method_options + '\n')

                if not method.strip().endswith(';'):
                    end = False
                    for j, line in enumerate(methods[line_num + 1:]):
                        if end:
                            break

                        skip_dict += 1
                        param, param_options = parse_comment(line.strip())
                        if param.endswith(';'):
                            end = True
                        param = param.replace(',', '').replace(') = 0;', '')
                        param = param.replace('};', '').strip()
                        param = param.replace(');', '').strip()

                        if not param:
                            continue

                        param_options = param_options.replace('#', '').strip()
                        param_options = param_options.replace(
                            '[helpstring]', '')
                        param_options = param_options.replace('[id]', '')
                        param_options = param_options.replace('[size_is]', '')

                        if param_options.startswith('['):
                            param_options = param_options.replace('][', ', ')
                            param_options = param_options.replace('] [', ', ')
                            param_options = Options(param_options)
                        else:
                            param_options = '[]'
                        try:
                            param_data_type, param = param.strip().rsplit(
                                ' ', 1)
                        except ValueError:
                            sys.stderr.write('PARAM: ' + param + '\n')
                            raise
                        param_data_type = param_data_type.strip().split(' ')
                        if len(param_data_type) == 1:
                            param_additional_options = []
                            param_data_type = param_data_type[0]
                        else:
                            param_additional_options = param_data_type[:-1]
                            param_data_type = param_data_type[-1]

                        param, param_data_type = process_param(
                            param.strip(), param_data_type.strip())

                        try:
                            param_options = eval(str(param_options))
                        except SyntaxError:
                            param_options = eval(
                                str(param_options).replace(', , ', ', '))

                        for addl_option in param_additional_options:
                            if 'Out' in addl_option or 'out' in addl_option:
                                if 'out' not in param_options:
                                    param_options += ['out']
                            if 'In' in addl_option or 'in' in addl_option:
                                if 'in' not in param_options:
                                    param_options += ['in']
                            if '_Reserved_' in addl_option:
                                if 'in' not in param_options:
                                    param_options += ['in']

                        template = TEMPLATE_PARAM1.format(
                            indent=indent,
                            param_direction=param_options,
                            param_data_type=param_data_type,
                            param_name=param,
                            comment='')

                        if len(template) > 79:
                            template = TEMPLATE_PARAM2.format(
                                indent=indent,
                                param_direction=param_options,
                                param_data_type=param_data_type,
                                param_name=param,
                                comment='')

                        sys.stderr.write('PARAMTEMPLATE: ' + template + '\n')
                        found_params += [template]

                found_methods += [
                    TEMPLATE_METHOD.format(
                        indent=indent,
                        method_options=method_options,
                        method_data_type=method_data_type.replace(
                            'virtual', '').replace('STDMETHODCALLTYPE',
                                                   '').strip(),
                        method_name=method_name.replace('(', '').strip(),
                        params=''.join(found_params) if found_params else '',
                        comment='')
                ]
                sys.stderr.write('METHODTEMPLATE: ' + found_methods[-1] + '\n')
            continue

        else:
            if chained_method:
                if ';' in method:
                    chained_method = False
                continue

            if chained_comment:
                if '*/' in method:
                    chained_comment = False

                continue

            method, comment = parse_comment(method)

            if method is None and comment is None:
                comment = ''
                chained_comment = True
                for comnt in methods[line_num:]:
                    comnt = comnt.strip()

                    if (not comnt.startswith('**/')
                            and not comnt.startswith('*/')
                            and comnt.startswith('*')):
                        comnt = comnt[1:].strip()

                    comment += ' ' + comnt
                    if '*/' in comnt:
                        break
                method, new_comment = parse_comment(comment)

            if method and not method.endswith(';'):
                chained_method = True

                method = ''
                comment = ''
                skip_meth = None
                for j, meth in enumerate(methods[line_num:]):
                    if skip_meth is not None:
                        if skip_meth <= j:
                            continue
                        skip_meth = None

                    meth = meth.strip()
                    meth, new_comment = parse_comment(meth)

                    if meth is None and new_comment is None:
                        new_comment = ''
                        skip_meth = j
                        for k, comnt in enumerate(methods[line_num + j:]):
                            skip_meth += 1
                            comnt = comnt.strip()

                            if (not comnt.startswith('**/')
                                    and not comnt.startswith('*/')
                                    and comnt.startswith('*')):
                                comnt = comnt[1:].strip()

                            new_comment += ' ' + comnt
                            if '*/' in comnt:
                                break
                        meth, new_comment = parse_comment(new_comment)

                    comment += ' ' + new_comment
                    method += ' ' + meth

                    if meth.endswith('\\'):
                        method = method[:-1]

                    if ';' in meth:
                        break

            comment = equalize_width(indent + '    ', comment)

            if comment:
                if '\n' in comment:
                    found_methods += ['\n']
                    split_comment = comment.split('\n')
                    for comnt in split_comment[:-1]:
                        found_methods += [comnt + '\n']

                    found_methods += [split_comment[-1]]
                else:
                    try:
                        if found_methods[-1].strip().endswith('\n'):
                            found_methods += [comment.rstrip() + '\n']
                        else:
                            found_methods += ['\n' + comment.rstrip()]
                    except IndexError:
                        found_methods += [comment.rstrip() + '\n']

                comment = ''

            if not method:
                continue

            if method.strip().startswith('['):
                pattern, method_options = parse_options(method.strip())
                method = method.replace(pattern, '')
            else:
                method_options = Options('[]')

            try:
                method_name, temp_params = method.split('(', 1)
            except ValueError:
                continue

            method_name = method_name.strip()
            try:
                method_data_type, method_name = method_name.split(' ')
            except ValueError:
                continue

            method_name = method_name.strip()
            method_data_type = method_data_type.strip()
            temp_params = temp_params.strip()[:-2]

            found_params = []

            while temp_params:
                if temp_params.startswith('['):
                    pattern, param_direction = parse_options(temp_params)
                    temp_params = temp_params.replace(pattern, '')
                else:
                    param_direction = Options('[]')

                if ',' in temp_params:
                    param, temp_params = split_strip(temp_params, ',')
                else:
                    param = temp_params
                    temp_params = ''

                try:
                    param_data_type, param_name = split_strip(param, ' ')
                except ValueError:
                    continue

                param_name, param_data_type = process_param(
                    param_name, param_data_type)
                template = TEMPLATE_PARAM1.format(
                    indent=indent,
                    param_direction=param_direction,
                    param_data_type=param_data_type,
                    param_name=param_name,
                    comment=comment)
                if len(template) > 79:
                    template = TEMPLATE_PARAM2.format(
                        indent=indent,
                        param_direction=param_direction,
                        param_data_type=param_data_type,
                        param_name=param_name,
                        comment=comment)

                found_params += [template]

            found_methods += [
                TEMPLATE_METHOD.format(
                    indent=indent,
                    method_options=str(method_options).replace("['in']", "[]"),
                    method_data_type=method_data_type,
                    method_name=method_name,
                    params=''.join(found_params) if found_params else '',
                    comment=comment)
            ]

    template = TEMPLATE_METHODS.format(
        indent=indent,
        cls_name=cls_name,
        methods=''.join(found_methods),
    )
    if not found_methods:
        template = template.split('[')[0]
        template += '[]\n\n'

    if isinstance(interface_data, dict):
        print(template)
    else:
        print(indent + 'pass')
        return cls_name, template
Esempio n. 4
0
def parse_macro(indent, lne, macro=False, struct=False):
    global line
    line, comment = parse_comment(lne)
    comment = comment.strip()
    line = line.strip()

    if comment:
        comment = ' ' + comment

    def set_pattern(repl, add):
        global line

        line = line.replace(repl, '').strip()

        if ' or ' in line:
            defines = list(d.strip() for d in line.split(' or '))
        elif ' and ' in line:
            defines = list(d.strip() for d in line.split(' and '))
        else:
            defines = [line]

        for define in defines:
            old_define = define
            open_brackets = ''
            while define.startswith('('):
                open_brackets += define[:1]
                define = define[1:]

            define = open_brackets + add + define
            define += ')'
            line = line.replace(old_define, define)

    try:
        if line.startswith('#ifndef'):
            set_pattern('#ifndef', 'not defined(')
            if (
                line.count('(') == 1 and
                line.count(')') == 1 and
                line.startswith('(') and
                line.endswith(')')
            ):
                line = line[1:-1]

            new_line = 'if ' + line + ':'
            new_line = new_line.replace('( ', '(').replace(' )', ')')

            if macro:
                print(indent + new_line)
            elif struct:
                print(indent[:-4] + new_line)
                return '', indent + '    '
            else:
                print(indent + '    ' + new_line)
                return '', indent + '    '

        if line.startswith('#ifdef'):
            set_pattern('#ifdef', 'defined(')
            if (
                line.count('(') == 1 and
                line.count(')') == 1 and
                line.startswith('(') and
                line.endswith(')')
            ):
                line = line[1:-1]

            line = 'if ' + line + ':' + comment
            line = line.replace('( ', '(').replace(' )', ')')
            if macro:
                print(indent + line)
            elif struct:
                print(indent[:-4] + line)
                return '', indent + '    '
            else:
                print(indent + '    ' + line)
                return '', indent + '    '

        if (
            line.startswith('#elif') or
            line.startswith('#else') or
            line.startswith('#if')
        ):

            for item in ('#elif', '#if'):
                if line.startswith(item):
                    line = line.replace(item, '').strip()

                    if (
                        line.count('(') == 1 and
                        line.count(')') == 1 and
                        line.startswith('(') and
                        line.endswith(')')
                    ):
                        line = line[1:-1]

                    line = item + ' ' + line
                    break

            line = line[1:] + ':' + comment
            line = line.replace('( ', '(').replace(' )', ')')

            if line.startswith('if'):
                if macro:
                    print(indent + line)
                elif struct:
                    print(indent[:-4] + line)
                    return '', indent + '    '
                else:
                    print(indent + '    ' + line)
                    return '', indent + '    '

            else:
                if macro:
                    print(indent + line)
                elif struct:
                    print(indent[:-4] + line)
                    return '', indent
                else:
                    print(indent + line)
                    return '', indent

        if line.startswith('#endif'):
            if struct:
                indent = indent[:-4]
                if comment:
                    print(indent[:-4] + '# END IF ' + comment[2:] + '\n')
                else:
                    print(indent[:-4] + '# END IF' + '\n\n')

                return '', indent

            if comment:
                print(indent + '# END IF ' + comment[2:] + '\n')
            else:
                print(indent + '# END IF' + '\n\n')
            return '', indent[:-4]

        return line, indent

    finally:
        data_type = pyparsing.oneOf("defined")
        decl_data_type = pyparsing.Combine(data_type)
        name = pyparsing.Word(pyparsing.alphas + '_',
            pyparsing.alphanums + '_')

        LPAR, RPAR = map(pyparsing.Suppress, "()")

        c_function = (
            decl_data_type("type")
            + LPAR + name("name") + RPAR
        )
        c_function.ignore(pyparsing.cStyleComment)

        for define in c_function.searchString(line):
            if (
                define['name'] not in new_defines and
                define['name'] not in KNOWN_DEFINES
            ):
                new_defines.append(define['name'])
Esempio n. 5
0
def parse_define(indent, define, importer):
    old_define = define
    global value
    if 'This' in define:
        return

    if 'GUID_BUILDER' in define:
        return

    if define.startswith('#define INTERFACE'):
        return

    define, comment = parse_comment(define)
    comment = equalize_width(indent, comment.strip())

    if comment:
        print('\n' + comment)

    if define is None and comment is None:
        print(indent + '# DEFINE ERROR 1:', old_define)
        return False

    comment = ''

    define = define.replace('0X', '0x').replace('\t', '    ').replace('->', '.')

    try:
        var_name, value = define[1:].replace('define', '').strip().split(' ', 1)
    except ValueError:
        var_name = define[1:].replace('define', '').strip()
        value = '1'
        # print(indent + '#~#~#~', old_define)
        # return False

    var_name = var_name.strip()
    value = value.strip()

    if var_name == '#':
        try:
            var_name, value = value.split(' ', 1)
        except ValueError:
            print(indent + value + ' = VOID')
            return True

    if '(' in var_name:
        brace_count = var_name.count('(')
        brace_count -= var_name.count(')')
        while brace_count > 0:
            var_name += value[:value.find(')') + 1]
            value = value[value.find(')') + 1:]
            new_brace_count = var_name.count('(')
            new_brace_count -= var_name.count(')')
            if brace_count == new_brace_count:
                break

            brace_count = new_brace_count

        var_name = var_name.replace('=', '')

    var_name = var_name.strip()
    value = value.strip()

    if var_name == value:
        print(indent + '# DEFINE ERROR 3:', old_define)
        return False

    if '0x' in var_name:
        var_name, new_value = var_name.split('0x', 1)
        value = '0x' + new_value + value
        var_name = var_name.strip()
        value = value.strip()

    value = process_hex(value)

    if value.count('"') == 1:
        if not value.endswith('"') or value == '"':
            value += '\\n"'

    def get_ret():
        global value
        if not value.strip():
            value = '1'

        if value.startswith('L"'):
            value = value[1:]

        if var_name.startswith('def '):
            ret = '\n\n' + indent + var_name

            if value == '1':
                ret += (
                    indent + '# DEFINE ERROR 4: ' +
                    str(old_define) +
                    '\n' +
                    indent + '    pass'
                )

            elif '?' in value and ':' in value:
                def split_question_answer(start, v):
                    question, answer = v.split('?', 1)
                    yes, no = answer.split(':', 1)
                    if '?' in no:
                        no = split_question_answer('    elif ', no)
                    else:
                        if no.count('(') != no.count(')') and no.strip().endswith(')'):
                            no = no[:-1]
                        no = [indent + '    else:', indent + '        return ' + no]

                    if question.count('(') != question.count(')') and question.strip().startswith('('):
                        question = question[1:]

                    return [indent + start + question + ':', indent + '        return ' + yes] + no

                ret += '\n'.join(
                    split_question_answer('    if ', value)
                )

            elif value.startswith('{') and value.endswith('}'):
                import re

                temp_value = value[1:-1].strip()
                temp_value = re.sub(r"(?! )=(?! )", ' = ', temp_value)
                temp_value = list(indent + '    ' + v.strip() for v in temp_value.split(';'))
                ret += '\n'.join(temp_value)
            else:
                for char in list('()+-<>/*%!&~,[]";:'):
                    if char in value:
                        break
                else:
                    if ' ' in value:
                        values = list(v.strip() for v in value.split(' '))
                        value = ''
                        while len(values) > 1:
                            value = '(' + values.pop(len(values) - 1) + value + ')'

                        value = values[0] + value

                temp_value = indent + '    return ' + value

                if len(temp_value) > 79:
                    for item in (
                        ' | ',
                        ' or ',
                        ' and ',
                        ','
                    ):

                        if item in value:
                            ret_indent = indent + '        '
                            temp_value = indent + '    return (\n'

                            split_value = list(
                                v.strip() for v in value.split(item)
                            )
                            for i, r_val in enumerate(split_value):
                                brace_count = r_val.count('(') - r_val.count(')')
                                if i == len(split_value) - 1:
                                    item = ''

                                if brace_count > 0:
                                    temp_value += (
                                        ret_indent +
                                        r_val[:r_val.find('(') + 1] +
                                        item +
                                        '\n'
                                    )
                                    r_val = r_val[r_val.find('('):]
                                    ret_indent += '    '
                                elif brace_count < 0:
                                    temp_value += (
                                        ret_indent +
                                        r_val[:r_val.find(')') + 1] +
                                        item +
                                        '\n'
                                    )

                                    r_val = r_val[r_val.find(')'):]
                                    ret_indent = ret_indent[:-4]

                                temp_value += ret_indent + r_val + item + '\n'
                            temp_value += indent + '    )'
                            break
                elif (
                    value.count('(') == 1 and
                    value.count(')') == 1 and
                    value.startswith('(') and
                    value.endswith(')')
                ):
                    temp_value = indent + '    return ' + value[1:-1]

                ret += temp_value

        elif 'CTL_CODE' in value:
            value = value.replace('CTL_CODE', '')[:-1]
            value = (
                'CTL_CODE(\n' +
                '\n'.join(
                    indent + '    ' + val.strip() + ','
                    for val in value[1:].split(',')
                ) +
                '\n' + indent + ')'
            )
            ret = var_name + ' = ' + value

        elif value and var_name != value:
            value = value.replace('{', '[').replace('}', ']')
            ret = var_name + ' = ' + value

            if len(indent + ret) > 76:
                if (
                    ',' in ret and
                    (
                        ('(' in ret and ret.endswith(')')) or
                        ('[' in ret and ret.endswith(']'))
                    )
                ):

                    new_ret, ret = ret.split(' = ', 1)
                    new_ret += ' = '
                    ret_len = len(ret)
                    while ret:
                        try:
                            test_ret, ret = ret.split(',', 1)
                            if ret_len == len(ret):
                                raise ValueError
                            ret_len = len(ret)
                            test_ret = test_ret.strip()
                            if test_ret.startswith('[') or test_ret.startswith('('):
                                new_ret += test_ret[0] + '\n'
                                test_ret = test_ret[1:].strip()

                            new_ret += indent + '    ' + test_ret + ',\n'

                            if ret.strip().startswith('['):
                                test_ret = ret[:ret.find(']') + 1]
                                ret = ret.replace(test_ret, '', 1)

                                test_ret = ', '.join(
                                    itm.strip()
                                    for itm in test_ret.strip()[1:-1].split(',')
                                )
                                test_ret = '[' + test_ret + ']'
                                if ret.startswith(','):
                                    ret = ret[1:]
                                new_ret += indent + '    ' + test_ret + ',\n'
                        except:
                            new_ret += indent + '    ' + ret[:-1] + '\n'
                            new_ret += indent + ret[-1]
                            break
                    ret = new_ret

                    # if ret.endswith(']'):
                    #     start_marker = '['
                    #     end_marker = ']'
                    # else:
                    #     start_marker = '('
                    #     end_marker = ')'
                    # beg, end = ret.split(start_marker, 1)
                    # end = end[:-1].split(',')
                    # end = list(indent + '    ' + itm.strip() + ',' for itm in end)
                    # beg += start_marker + '\n' + '\n'.join(
                    #     end) + '\n' + indent + end_marker
                    # ret = beg
        else:
            ret = ''

        return ret

    for item in (
        'HANDLE',
        'ULONG',
        'LONG',
        'LONGLONG',
        'ULONGLONG',
        'DOUBLE',
        'LONG_PTR',
        'WORD',
        'USHORT',
        'SHORT'
    ):
        value = value.replace('(' + item + ')', '')

    for item in (
        'DWORD',
        'INT',
        'UINT',
    ):
        for bit in ('128', '64', '32', '16', '8', ''):
            value = value.replace('(' + item + bit + ')', '')

    value = value.replace('()', '')

    if '(' in var_name and var_name.endswith(')'):
        tmp_var_name = var_name.replace(' ', '').replace(',', ', ')
        var_name = 'def ' + tmp_var_name + ':\n'

        brace_count = value.count('(')
        brace_count -= value.count(')')

        if brace_count < 0:
            new_value = ''
            brace_count = 0
            for char in list(value.strip()):
                if char == '(':
                    brace_count += 1
                elif char == ')':
                    brace_count -= 1
                if brace_count != -1:
                    new_value += char
                else:
                    brace_count = 0
            value = new_value
        elif brace_count > 0:
            new_value = ''
            brace_count = 0
            for char in list(value.strip()):
                if char == '(':
                    brace_count -= 1
                elif char == ')':
                    brace_count += 1
                if brace_count != -1:
                    value += char
                else:
                    brace_count = 0
            value = new_value

        for key in importer.allowed:
            value = value.replace('(' + key + ')', '')

        if value.startswith('('):
            value = '(' + value[1:].strip()

        if value.endswith(')'):
            value = value[:-1].strip() + ')'

        if '((' in value:
            double_start = value.find('((')
            double_end = value.find('))')
            double_search = value[double_start + 2:double_end - 1]
            count = double_search.count('(') - double_search.count(')')
            if count == 0:
                value = value.replace('((', '(', 1)
                value = value.replace('))', ')', 1)

        list_value = []
        found_open = False
        markers = ('+', '-', '&', '|', '<', '>', '=')
        for char in list(value):
            if char == '(':
                found_open = True
            elif char in markers:
                found_open = False
            elif char == ')' and found_open:
                list_value.reverse()
                list_value.remove('(')
                list_value.reverse()
                found_open = False
                continue

            list_value += [char]

        value = ''.join(list_value)

        for i in range(10, 1, -1):
            value = value.replace(' ' * i, ' ')
        print(DEFINE_TEMPLATE.format(indent, get_ret()))
        return True

    if (
        value.startswith('(') and
        value.endswith(')') and
        ',' not in value and
        '|' not in value and
        'and' not in value and
        'or' not in value
    ):
        value = value[1:-1].strip()

    if value.startswith('((DWORD   )'):
        value = value.replace('((DWORD   )', '')[:-1]
        if '0x' not in value and not value.isdigit():
            print(indent + get_ret())
            return

    if value.startswith('(') and value.endswith(')'):
        if value[1:-1].strip().isdigit():
            value = process_hex(value[1:-1].strip())

    if not value.startswith('0x') and value.isdigit():
        value = process_hex(value)

    if '|' in value or ' or ' in value or ',' in value:
        if '|' in value:
            splitter = '|'
            marker = ' | '

        elif ',' in value:
            splitter = ','
            marker = ','
        else:
            splitter = ' or '
            marker = ' or '

        if value.startswith('(') and value.endswith(')'):
            value = value[1:-1]

        value = value.split(splitter)
        value = marker.join(d.strip() for d in value)

        if len(indent + get_ret()) > 79:
            value = (
                '(\n' + indent + '    ' +
                (marker + '\n' + indent + '    ').join(
                    v.strip()
                    for v in value.split(splitter)
                ) +
                '\n' + indent + ')'
            )

    res = get_ret()

    if 'FIELD_OFFSET' in res:

        beg, end = res.split('FIELD_OFFSET', 1)

        end = end.replace('(', '', 1).strip()
        brace_count = 1
        mid = ''
        for char in list(end):
            if char == '(':
                brace_count += 1
            if char == ')':
                brace_count -= 1
            if brace_count == 0:
                break
            mid += char

        end = end.replace(mid, '', 1)
        mid, param = mid.strip().rsplit(',', 1)
        param = ", '{0}'".format(param.strip())
        mid += param
        beg += 'FIELD_OFFSET(' + mid + end
        res = beg

    if res:
        if ' = ' in res and not res.startswith('#'):
            nm = res.split(' = ')[0]
            if nm in importer.allowed:
                importer.add(nm)
                return False

            if len(indent + res) > 79 and '\n' not in res.strip():
                beg, end = res.split(' = ', 1)
                beg += ' = (\n'
                end = indent + '    ' + end.strip() + '\n' + indent + ')'
                res = beg + end

        if '+' in res and 'FIELD_OFFSET' in res:
            res = res.replace('+ ', '+\n    ' + indent, 1)

        print(DEFINE_TEMPLATE.format(indent, res))
        return True