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))
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
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
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'])
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