Thread: [pygccxml-commit] SF.net SVN: pygccxml: [73] pygccxml_dev/pygccxml/parser
Brought to you by:
mbaas,
roman_yakovenko
From: <rom...@us...> - 2006-05-14 07:25:32
|
Revision: 73 Author: roman_yakovenko Date: 2006-05-14 00:25:24 -0700 (Sun, 14 May 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=73&view=rev Log Message: ----------- adding demangled property to declaration_t class, requiered few fixes in parser package Modified Paths: -------------- pygccxml_dev/pygccxml/parser/linker.py pygccxml_dev/pygccxml/parser/patcher.py pygccxml_dev/pygccxml/parser/project_reader.py pygccxml_dev/pygccxml/parser/scanner.py Modified: pygccxml_dev/pygccxml/parser/linker.py =================================================================== --- pygccxml_dev/pygccxml/parser/linker.py 2006-05-14 07:23:52 UTC (rev 72) +++ pygccxml_dev/pygccxml/parser/linker.py 2006-05-14 07:25:24 UTC (rev 73) @@ -84,7 +84,8 @@ def visit_casting_operator( self ): self.__link_calldef() - self.__inst.name = 'operator ' + self.__inst.return_type.decl_string + #will be fixed by patcher. It is needed because of demangled name taken into account + #self.__inst._name = 'operator ' + self.__inst.return_type.decl_string def visit_free_function( self ): self.__link_calldef() @@ -101,15 +102,15 @@ #class name. I think this is because those constructors are compiler #generated. I need to find out more about this and to talk with Brad - new_name = self.__inst.name + new_name = self.__inst._name if templates.is_instantiation( new_name ): new_name = templates.name( new_name ) for decl in self.__inst.declarations: if not isinstance( decl, constructor_t ): continue - if '.' in decl.name or '$' in decl.name: - decl.name = new_name + if '.' in decl._name or '$' in decl._name: + decl._name = new_name bases = self.__inst.bases.split() self.__inst.bases = [] Modified: pygccxml_dev/pygccxml/parser/patcher.py =================================================================== --- pygccxml_dev/pygccxml/parser/patcher.py 2006-05-14 07:23:52 UTC (rev 72) +++ pygccxml_dev/pygccxml/parser/patcher.py 2006-05-14 07:25:24 UTC (rev 73) @@ -172,8 +172,20 @@ return call_invocation.join( f_q_name, args ) +class fix_casting_operator_name_patcher_t( patcher_base_t ): + def __init__( self, decls ): + patcher_base_t.__init__( self, decls ) + + def patch_it(self): + for decl in declarations.make_flatten( self.decls ): + if not isinstance( decl, declarations.casting_operator_t): + continue + decl.name = 'operator ' + decl.return_type.decl_string + def patch_it(decls): patcher = default_argument_patcher_t( decls ) patcher.patch_it() + patcher2 = fix_casting_operator_name_patcher_t( decls ) + patcher2.patch_it() return patcher.decls \ No newline at end of file Modified: pygccxml_dev/pygccxml/parser/project_reader.py =================================================================== --- pygccxml_dev/pygccxml/parser/project_reader.py 2006-05-14 07:23:52 UTC (rev 72) +++ pygccxml_dev/pygccxml/parser/project_reader.py 2006-05-14 07:25:24 UTC (rev 73) @@ -15,6 +15,51 @@ ALL_AT_ONCE = 'all at once' FILE_BY_FILE = 'file by file' + +#TODO: rework next explanation to something useful. +""" +file_configuration_t is rather cool feature. When you create module_builder_t +class instance you should pass list of files. This list can contain string( == file paths ) and/or instances of file_configuration_t class. + +file_configuration_t is class with fat interface. +It has 4 states: + 1. it could contain reference to source file. + Use "create_source_fc" function to create an instance of file_configuration_t + + 2. it could contain reference to source file and xml file. In this case if xml file + exist, source file will not be parsed by gccxml. If xml file does not exists, source + file will be parsed and xml file will be saved for future use. + See create_cached_source_fc function + + 3. it could contain reference to xml file only + See create_gccxml_fc + + 4. it could contain some text. In this case, parser will create temporal file on + disk and will pass it as an argument to gccxml. + See create_text_fc + +In most cases you don't all those features. If I were you, I would create regular +source file and put all template instantiation there. + +Any way the code: + +tmpl_inst = ''' +===================== + #include "TempClass.h" + + namespace details{ + inline void export_templates(){ + sizeof( TempClass<int> ); + } + } +''' + +import module_builder +mb = module_builder.module_builder_t( + [ module_builder.create_text_fc( tmpl_inst ) ] + , .... ) + +""" class file_configuration_t( object ): class CONTENT_TYPE: STANDARD_SOURCE_FILE = 'standard source file' @@ -239,7 +284,7 @@ for other_ns in other_ns_list: main_ns = pygccxml.declarations.find_declaration( answer , type=pygccxml.declarations.namespace_t - , name=other_ns.name + , name=other_ns._name , recursive=False ) if main_ns: main_ns.take_parenting( other_ns ) @@ -253,23 +298,23 @@ decls = [] for decl in nsref.declarations: if not ddhash.has_key( decl.__class__ ): - ddhash[ decl.__class__ ] = { decl.name : [ decl ] } + ddhash[ decl.__class__ ] = { decl._name : [ decl ] } decls.append( decl ) else: joined_decls = ddhash[ decl.__class__ ] - if not joined_decls.has_key( decl.name ): + if not joined_decls.has_key( decl._name ): decls.append( decl ) - joined_decls[decl.name] = [ decl ] + joined_decls[decl._name] = [ decl ] else: if isinstance( decl, pygccxml.declarations.calldef_t ): - if decl not in joined_decls[decl.name]: + if decl not in joined_decls[decl._name]: #functions has overloading decls.append( decl ) - joined_decls[decl.name].append( decl ) + joined_decls[decl._name].append( decl ) else: - assert 1 == len( joined_decls[ decl.name ] ) + assert 1 == len( joined_decls[ decl._name ] ) if isinstance( decl, pygccxml.declarations.namespace_t ): - joined_decls[ decl.name ][0].take_parenting( decl ) + joined_decls[ decl._name ][0].take_parenting( decl ) nsref.declarations = decls def _join_class_hierarchy( self, namespaces ): @@ -347,7 +392,7 @@ decl_wrapper_type.declaration = leaved_classes[ create_key(decl_wrapper_type.declaration) ] else: msg = [] - msg.append( "Unable to find out actual class definition: '%s'." % decl_wrapper_type.declaration.name ) + msg.append( "Unable to find out actual class definition: '%s'." % decl_wrapper_type.declaration._name ) msg.append( "Class definition has been changed from one compilation to an other." ) msg.append( "Why did it happen to me? Here is a short list of reasons: " ) msg.append( " 1. There are different preprocessor definitions applied on same file during compilation" ) Modified: pygccxml_dev/pygccxml/parser/scanner.py =================================================================== --- pygccxml_dev/pygccxml/parser/scanner.py 2006-05-14 07:23:52 UTC (rev 72) +++ pygccxml_dev/pygccxml/parser/scanner.py 2006-05-14 07:25:24 UTC (rev 73) @@ -25,6 +25,7 @@ XML_AN_CONST = "const" XML_AN_CONTEXT = "context" XML_AN_DEFAULT = "default" +XML_AN_DEMANGLED = "demangled" XML_AN_EXTERN = "extern" XML_AN_FILE = "file" XML_AN_ID = "id" @@ -145,11 +146,6 @@ continue members_mapping[ id( decl ) ] = members self.__members = members_mapping - #for id, members in self.__members.iteritems(): - #decl = self.__declarations.get( id, None ) - #if not decl or not isinstance( decl, scopedef_t): - #continue - #self.__declarations[id].declarations = members def declarations(self): return self.__declarations @@ -189,6 +185,7 @@ self.__read_bases( obj, attrs ) self.__read_artificial(obj, attrs) self.__read_mangled( obj, attrs) + self.__read_demangled( obj, attrs) elif isinstance( obj, type_t ): self.__types[ attrs[XML_AN_ID] ] = obj elif isinstance( obj, types.StringTypes ): @@ -229,6 +226,9 @@ def __read_mangled( self, decl, attrs ): decl.mangled = attrs.get( XML_AN_MANGLED, None ) + def __read_demangled( self, decl, attrs ): + decl.demangled = attrs.get( XML_AN_DEMANGLED, None ) + def __read_access( self, attrs ): self.__access[ attrs[XML_AN_ID] ] = attrs.get( XML_AN_ACCESS, ACCESS_TYPES.PUBLIC ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-05-20 20:25:30
|
Revision: 142 Author: roman_yakovenko Date: 2006-05-20 13:25:22 -0700 (Sat, 20 May 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=142&view=rev Log Message: ----------- adding doc strings Modified Paths: -------------- pygccxml_dev/pygccxml/parser/config.py pygccxml_dev/pygccxml/parser/project_reader.py pygccxml_dev/pygccxml/parser/source_reader.py Modified: pygccxml_dev/pygccxml/parser/config.py =================================================================== --- pygccxml_dev/pygccxml/parser/config.py 2006-05-18 15:11:59 UTC (rev 141) +++ pygccxml_dev/pygccxml/parser/config.py 2006-05-20 20:25:22 UTC (rev 142) @@ -10,7 +10,15 @@ """Configuration object to collect parameters for invoking gccxml. This class serves as a container for the parameters that can be used - to customize the call to gccxml. + to customize the call to gccxml. This class also allows users to work with + relative files paths. In this case files are searched in the following order: + + 1. current directory + + 2. working directory + + 3. additional include paths specified by the user + """ def __init__( self , gccxml_path='' Modified: pygccxml_dev/pygccxml/parser/project_reader.py =================================================================== --- pygccxml_dev/pygccxml/parser/project_reader.py 2006-05-18 15:11:59 UTC (rev 141) +++ pygccxml_dev/pygccxml/parser/project_reader.py 2006-05-20 20:25:22 UTC (rev 142) @@ -16,9 +16,10 @@ FILE_BY_FILE = 'file by file' -#TODO: rework next explanation to something useful. -""" -file_configuration_t is rather cool feature. When you create module_builder_t +class file_configuration_t( object ): + """ + file_configuration_t class is cool feature. When you want to parse C++ code + from different sources at once, you should use this class. class instance you should pass list of files. This list can contain string( == file paths ) and/or instances of file_configuration_t class. file_configuration_t is class with fat interface. @@ -60,7 +61,7 @@ , .... ) """ -class file_configuration_t( object ): + class CONTENT_TYPE: STANDARD_SOURCE_FILE = 'standard source file' CACHED_SOURCE_FILE = 'cached source file' Modified: pygccxml_dev/pygccxml/parser/source_reader.py =================================================================== --- pygccxml_dev/pygccxml/parser/source_reader.py 2006-05-18 15:11:59 UTC (rev 141) +++ pygccxml_dev/pygccxml/parser/source_reader.py 2006-05-20 20:25:22 UTC (rev 142) @@ -44,7 +44,35 @@ cls_inst.aliases.append( decl ) class source_reader_t: + """ + This class reads C++ source code and returns declarations tree. + + This class is the only class that have an intime knowledge about GCC-XML. + It has only one responsibility: it calls GCC-XML with a source file specified + by user and creates declarations tree. The implementation of this class is split + to 2 classes: + + 1. L{scanner_t} - this class scans the "XML" file, generated by GCC-XML and + creates `pygccxml`_ declarations and types classes. After the xml file has + been processed declarations and type class instances keeps references to + each other using GCC-XML generated id's. + + 2. L{linker_t} - this class contains logic for replacing GCC-XML generated + ids with references to declarations or type class instances. + """ def __init__( self, config, cache=None, decl_factory=None ): + """ + @param config: instance of L{config_t} class, that contains GCC-XML + configuration + @type config: L{config_t} + + @param cache: reference to cache object, that will be updated after + file has been parsed. + @param cache: instance of class, that derives from {cache_base_t} + + @param decl_factory: declarations factory, if not given default + declarations factory L{decl_factory_t} will be used + """ self.__search_directories = [] self.__config = config self.__search_directories.append( config.working_directory ) @@ -118,6 +146,20 @@ return cmd_line def create_xml_file( self, header, destination=None ): + """ + This function will return the file name of the file, created by GCC-XML + for "header" file. If destination_file_path is not None, then this file + path will be used and returned. + + @param header: path to source file, that should be parsed + @type header: str + + @param destination: if given, will be used as target file/path for + GCC-XML generated file. + @type destination: str + + @return: path to GCC-XML generated file + """ gccxml_file = destination # If file specified, remove it to start else create new file name if gccxml_file: @@ -155,6 +197,17 @@ return gccxml_file def create_xml_file_from_string( self, content, destination=None ): + """ + Creates XML file from text. + + @param content: C++ source code + @type content: str + + @param destination: file name for GCC-XML generated file + @type destination: str + + @return: returns file name of GCC-XML generated file + """ header_file = pygccxml.utils.create_temp_file_name( suffix='.h' ) gccxml_file = None try: @@ -167,6 +220,12 @@ return gccxml_file def read_file(self, source_file): + """ + Reads C++ source file and returns declarations tree + + @param source_file: path to C++ source file + @type source_file: str + """ declarations, types = None, None gccxml_file = '' try: @@ -193,6 +252,14 @@ return declarations def read_xml_file(self, gccxml_created_file): + """ + Reads GCC-XML generated XML file. + + @param gccxml_created_file: path to GCC-XML generated file + @type gccxml_created_file: str + + @return: declarations tree + """ if self.__config.verbose: logger.info( "Reading xml file: [%s]" % gccxml_created_file ) @@ -200,6 +267,10 @@ return declarations def read_string(self, content): + """ + Reads Python string, that contains valid C++ code, and returns + declarations tree. + """ header_file = pygccxml.utils.create_temp_file_name( suffix='.h' ) header_file_obj = file(header_file, 'w+') header_file_obj.write( content ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-05-27 19:48:33
|
Revision: 167 Author: roman_yakovenko Date: 2006-05-27 12:48:20 -0700 (Sat, 27 May 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=167&view=rev Log Message: ----------- excluding unnamed classes from being exported Modified Paths: -------------- pygccxml_dev/pygccxml/declarations/class_declaration.py pygccxml_dev/pygccxml/parser/project_reader.py pygccxml_dev/pygccxml/parser/scanner.py pyplusplus_dev/pyplusplus/decl_wrappers/class_wrapper.py Modified: pygccxml_dev/pygccxml/declarations/class_declaration.py =================================================================== --- pygccxml_dev/pygccxml/declarations/class_declaration.py 2006-05-27 18:46:37 UTC (rev 166) +++ pygccxml_dev/pygccxml/declarations/class_declaration.py 2006-05-27 19:48:20 UTC (rev 167) @@ -101,6 +101,8 @@ self._aliases = [] def _get_name_impl( self ): + if not self._name: #class with empty name + return self._name if class_t.USE_DEMANGLED_AS_NAME and self.demangled: fname = algorithm.full_name( self.parent ) if fname.startswith( '::' ) and not self.demangled.startswith( '::' ): Modified: pygccxml_dev/pygccxml/parser/project_reader.py =================================================================== --- pygccxml_dev/pygccxml/parser/project_reader.py 2006-05-27 18:46:37 UTC (rev 166) +++ pygccxml_dev/pygccxml/parser/project_reader.py 2006-05-27 19:48:20 UTC (rev 167) @@ -346,6 +346,11 @@ if not decl.name and decl not in joined_decls[decl._name]: decls.append( decl ) joined_decls[decl._name].append( decl ) + elif isinstance( decl, pygccxml.declarations.class_t ): + #unnamed classes + if not decl.name and decl not in joined_decls[decl._name]: + decls.append( decl ) + joined_decls[decl._name].append( decl ) else: assert 1 == len( joined_decls[ decl._name ] ) if isinstance( decl, pygccxml.declarations.namespace_t ): Modified: pygccxml_dev/pygccxml/parser/scanner.py =================================================================== --- pygccxml_dev/pygccxml/parser/scanner.py 2006-05-27 18:46:37 UTC (rev 166) +++ pygccxml_dev/pygccxml/parser/scanner.py 2006-05-27 19:48:20 UTC (rev 167) @@ -366,6 +366,8 @@ def __read_class_impl(self, class_type, attrs): decl = None name = attrs.get(XML_AN_NAME, '') + if '$' in name or '.' in name: + name = '' if attrs.has_key( XML_AN_INCOMPLETE ): decl = self.__decl_factory.create_class_declaration(name=name) else: Modified: pyplusplus_dev/pyplusplus/decl_wrappers/class_wrapper.py =================================================================== --- pyplusplus_dev/pyplusplus/decl_wrappers/class_wrapper.py 2006-05-27 18:46:37 UTC (rev 166) +++ pyplusplus_dev/pyplusplus/decl_wrappers/class_wrapper.py 2006-05-27 19:48:20 UTC (rev 167) @@ -103,6 +103,8 @@ self.wrapper_user_code.append( user_text.user_text_t( code ) ) def _exportable_impl( self ): + if not self.name: + return 'pyplusplus can not expose unnamed classes.' if isinstance( self.parent, declarations.namespace_t ): return '' if not self in self.parent.public_members: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-05-31 03:55:51
|
Revision: 189 Author: roman_yakovenko Date: 2006-05-30 20:55:37 -0700 (Tue, 30 May 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=189&view=rev Log Message: ----------- applying Allen patch - gccxml check error Modified Paths: -------------- pygccxml_dev/pygccxml/parser/config.py pygccxml_dev/pygccxml/parser/source_reader.py pyplusplus_dev/pyplusplus/module_builder/builder.py Modified: pygccxml_dev/pygccxml/parser/config.py =================================================================== --- pygccxml_dev/pygccxml/parser/config.py 2006-05-31 03:41:50 UTC (rev 188) +++ pygccxml_dev/pygccxml/parser/config.py 2006-05-31 03:55:37 UTC (rev 189) @@ -27,8 +27,9 @@ , define_symbols=None , undefine_symbols=None , start_with_declarations=None - , verbose=False): - """Constructor. + , verbose=False + , ignore_gccxml_output=False): + """Constructor. """ object.__init__( self ) self.__gccxml_path = gccxml_path @@ -51,6 +52,7 @@ self.__start_with_declarations = start_with_declarations self.__verbose = verbose + self.__ignore_gccxml_output = ignore_gccxml_output def clone(self): return config_t( gccxml_path=self.__gccxml_path @@ -59,7 +61,8 @@ , define_symbols=self.__define_symbols[:] , undefine_symbols=self.__undefine_symbols[:] , start_with_declarations=self.__start_with_declarations[:] - , verbose=self.verbose) + , verbose=self.verbose + , ignore_gccxml_output=self.ignore_gccxml_output) def __get_gccxml_path(self): return self.__gccxml_path @@ -94,3 +97,9 @@ def __set_verbose(self, val=True): self.__verbose = val verbose = property( __get_verbose, __set_verbose ) + + def __get_ignore_gccxml_output(self): + return self.__ignore_gccxml_output + def __set_ignore_gccxml_output(self, val=True): + self.__ignore_gccxml_output = val + ignore_gccxml_output = property( __get_ignore_gccxml_output, __set_ignore_gccxml_output ) Modified: pygccxml_dev/pygccxml/parser/source_reader.py =================================================================== --- pygccxml_dev/pygccxml/parser/source_reader.py 2006-05-31 03:41:50 UTC (rev 188) +++ pygccxml_dev/pygccxml/parser/source_reader.py 2006-05-31 03:55:37 UTC (rev 189) @@ -170,14 +170,11 @@ ffname = header if not os.path.isabs( ffname ): ffname = self.__file_full_name(header) - #input, output = os.popen4( self.__create_command_line( ffname, gccxml_file ) ) - #input.close() command_line = self.__create_command_line( ffname, gccxml_file ) if self.__config.verbose: logger.info( " Command line for GCC-XML: %s" % command_line ) input_, output = os.popen4( command_line ) input_.close() - #output = os.popen(command_line) gccxml_reports = [] while True: data = output.readline() @@ -186,11 +183,12 @@ break exit_status = output.close() gccxml_msg = ''.join(gccxml_reports) - if gccxml_msg or exit_status or not os.path.isfile(gccxml_file): - raise gccxml_runtime_error_t( "Error occured while running GCC-XML: %s" % gccxml_msg ) - - #if not os.path.isfile(gccxml_file): - #raise gccxml_runtime_error_t( "Error occured while running GCC-XML: %s status:%s" % (gccxml_msg, exit_status) ) + if self.__config.ignore_gccxml_output: + if not os.path.isfile(gccxml_file): + raise gccxml_runtime_error_t( "Error occured while running GCC-XML: %s status:%s" % (gccxml_msg, exit_status) ) + else: + if gccxml_msg or exit_status or not os.path.isfile(gccxml_file): + raise gccxml_runtime_error_t( "Error occured while running GCC-XML: %s" % gccxml_msg ) except Exception, error: pygccxml.utils.remove_file_no_raise( gccxml_file ) raise error Modified: pyplusplus_dev/pyplusplus/module_builder/builder.py =================================================================== --- pyplusplus_dev/pyplusplus/module_builder/builder.py 2006-05-31 03:41:50 UTC (rev 188) +++ pyplusplus_dev/pyplusplus/module_builder/builder.py 2006-05-31 03:55:37 UTC (rev 189) @@ -33,7 +33,8 @@ , compilation_verbose=False , compilation_mode=None , cache=None - , optimize_queries=True): + , optimize_queries=True + , ignore_gccxml_output=False): """ @param files: list of files, declarations from them you want to export @type files: list of strings or L{file_configuration_t} instances @@ -60,7 +61,8 @@ , define_symbols=define_symbols , undefine_symbols=undefine_symbols , start_with_declarations=start_with_declarations - , verbose=compilation_verbose) + , verbose=compilation_verbose + , ignore_gccxml_output=ignore_gccxml_output) #may be in future I will add those directories to user_defined_directories #to self.__code_creator. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-06-18 05:23:26
|
Revision: 223 Author: roman_yakovenko Date: 2006-06-17 22:23:18 -0700 (Sat, 17 Jun 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=223&view=rev Log Message: ----------- Committing changes from Janes, Matthias adding treatment for Java native types Modified Paths: -------------- pygccxml_dev/pygccxml/declarations/type_visitor.py pygccxml_dev/pygccxml/parser/linker.py Modified: pygccxml_dev/pygccxml/declarations/type_visitor.py =================================================================== --- pygccxml_dev/pygccxml/declarations/type_visitor.py 2006-06-18 05:22:04 UTC (rev 222) +++ pygccxml_dev/pygccxml/declarations/type_visitor.py 2006-06-18 05:23:18 UTC (rev 223) @@ -72,7 +72,31 @@ def visit_complex_float(self): raise NotImplementedError() + + def visit_jbyte(self): + raise NotImplementedError() + def visit_jshort(self): + raise NotImplementedError() + + def visit_jint(self): + raise NotImplementedError() + + def visit_jlong(self): + raise NotImplementedError() + + def visit_jfloat(self): + raise NotImplementedError() + + def visit_jdouble(self): + raise NotImplementedError() + + def visit_jchar(self): + raise NotImplementedError() + + def visit_jboolean(self): + raise NotImplementedError() + def visit_volatile( self ): raise NotImplementedError() Modified: pygccxml_dev/pygccxml/parser/linker.py =================================================================== --- pygccxml_dev/pygccxml/parser/linker.py 2006-06-18 05:22:04 UTC (rev 222) +++ pygccxml_dev/pygccxml/parser/linker.py 2006-06-18 05:23:18 UTC (rev 223) @@ -193,6 +193,30 @@ def visit_complex_float(self): pass + def visit_jbyte(self): + pass + + def visit_jshort(self): + pass + + def visit_jint(self): + pass + + def visit_jlong(self): + pass + + def visit_jfloat(self): + pass + + def visit_jdouble(self): + pass + + def visit_jchar(self): + pass + + def visit_jboolean(self): + pass + def visit_volatile( self ): self.__link_compound_type() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-07-02 17:25:33
|
Revision: 269 Author: roman_yakovenko Date: 2006-07-02 10:25:19 -0700 (Sun, 02 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=269&view=rev Log Message: ----------- integrating cflags patch from Allen Modified Paths: -------------- pygccxml_dev/pygccxml/parser/config.py pygccxml_dev/pygccxml/parser/declarations_cache.py pygccxml_dev/pygccxml/parser/directory_cache.py pygccxml_dev/pygccxml/parser/source_reader.py Modified: pygccxml_dev/pygccxml/parser/config.py =================================================================== --- pygccxml_dev/pygccxml/parser/config.py 2006-06-29 13:05:12 UTC (rev 268) +++ pygccxml_dev/pygccxml/parser/config.py 2006-07-02 17:25:19 UTC (rev 269) @@ -28,7 +28,8 @@ , undefine_symbols=None , start_with_declarations=None , verbose=False - , ignore_gccxml_output=False): + , ignore_gccxml_output=False + , cflags=""): """Constructor. """ object.__init__( self ) @@ -53,6 +54,7 @@ self.__verbose = verbose self.__ignore_gccxml_output = ignore_gccxml_output + self.__cflags = cflags def clone(self): return config_t( gccxml_path=self.__gccxml_path @@ -62,7 +64,8 @@ , undefine_symbols=self.__undefine_symbols[:] , start_with_declarations=self.__start_with_declarations[:] , verbose=self.verbose - , ignore_gccxml_output=self.ignore_gccxml_output) + , ignore_gccxml_output=self.ignore_gccxml_output + , cflags=self.cflags) def __get_gccxml_path(self): return self.__gccxml_path @@ -103,3 +106,9 @@ def __set_ignore_gccxml_output(self, val=True): self.__ignore_gccxml_output = val ignore_gccxml_output = property( __get_ignore_gccxml_output, __set_ignore_gccxml_output ) + + def __get_cflags(self): + return self.__cflags + def __set_cflags(self, val): + self.__cflags = val + cflags = property( __get_cflags, __set_cflags ) Modified: pygccxml_dev/pygccxml/parser/declarations_cache.py =================================================================== --- pygccxml_dev/pygccxml/parser/declarations_cache.py 2006-06-29 13:05:12 UTC (rev 268) +++ pygccxml_dev/pygccxml/parser/declarations_cache.py 2006-07-02 17:25:19 UTC (rev 269) @@ -25,33 +25,59 @@ f.close() return sig.hexdigest() +def configuration_signature( config ): + """ Return a signature for a configuration (config_t) + object. This can then be used as a key in the cache. + This method must take into account anything about + a configuration that could cause the declarations generated + to be different between runs. + """ + sig = md5.new() + sig.update(str(config.gccxml_path)) + sig.update(str(config.working_directory)) + sig.update(str(config.cflags)) + for p in config.include_paths: + sig.update(str(p)) + for s in config.define_symbols: + sig.update(str(s)) + for u in config.undefine_symbols: + sig.update(str(u)) + return sig.hexdigest() + class cache_base_t( object ): def __init__( self ): object.__init__(self) def flush(self): + """ Flush (write out) the cache to disk if needed. """ raise NotImplementedError() def update(self, source_file, configuration, declarations, included_files): + """ Update cache entry. + @param source_file: path to the C++ source file being parsed + @param configuration: configuration used in parsing (config_t) + @param declarations: declaration tree found when parsing + @param included_files: files included by parsing. + """ raise NotImplementedError() def cached_value(self, source_file, configuration): - #returns declarations, types + """ Return declarations we have cached for the source_file and configuration + given. + @param source_file: path to the C++ source file being parsed. + @param configuration: configuration to use for parsing (config_t) + """ raise NotImplementedError() class record_t( object ): def __init__( self , source_signature - , working_directory - , include_paths - , define_symbols + , config_signature , included_files , included_files_signature , declarations ): self.__source_signature = source_signature - self.__working_directory = working_directory - self.__include_paths = include_paths - self.__define_symbols = define_symbols + self.__config_signature = config_signature self.__included_files = included_files self.__included_files_signature = included_files_signature self.__declarations = declarations @@ -64,16 +90,11 @@ was_hit = property( _get_was_hit, _set_was_hit ) def key(self): - return ( self.__source_signature - , self.__working_directory - , tuple(self.__include_paths) - , tuple(self.__define_symbols ) ) + return ( self.__source_signature, self.__config_signature) def create_key( source_file, configuration ): return ( file_signature(source_file) - , configuration.working_directory - , tuple( configuration.include_paths ) - , tuple( configuration.define_symbols ) ) + , configuration_signature(configuration)) create_key = staticmethod( create_key ) #def value(self): @@ -97,22 +118,10 @@ return self.__source_signature source_signature = property( __source_signature ) - def __source_file(self): - return self.__source_file - source_file = property( __source_file ) - - def __working_directory(self): - return self.__working_directory - working_directory = property( __working_directory ) - - def __include_paths(self): - return self.__include_paths - include_paths = property( __include_paths ) - - def __define_symbols(self): - return self.__define_symbols - define_symbols = property( __define_symbols ) - + def __config_signature(self): + return self.__config_signature + config_signature = property( __config_signature ) + def __included_files(self): return self.__included_files included_files = property( __included_files ) @@ -134,14 +143,18 @@ """ def __init__( self, name ): + """ + @param name: name of the cache file. + """ cache_base_t.__init__( self ) - self.__name = name - self.__cache = self.__load( self.__name ) + self.__name = name # Name of cache file + self.__cache = self.__load( self.__name ) # Map record_key to record_t self.__needs_flushed = not bool( self.__cache ) # If empty then we need to flush for entry in self.__cache.itervalues(): # Clear hit flags entry.was_hit = False - def __load( file_name ): + def __load( file_name ): + " Load pickled cache from file and return the object. " cache = None if os.path.exists( file_name ) and not os.path.isfile( file_name ): raise RuntimeError( 'Cache should be initialized with valid full file name' ) @@ -165,10 +178,12 @@ __load = staticmethod( __load ) def flush(self): - # Remove entries that did not get a cache hit + # If not marked as needing flushed, then return immediately if not self.__needs_flushed: + logger.info("Cache did not change, ignoring flush.") return + # Remove entries that did not get a cache hit num_removed = 0 for key in self.__cache.keys(): if not self.__cache[key].was_hit: @@ -184,9 +199,7 @@ def update(self, source_file, configuration, declarations, included_files): """ Update a cached record with the current key and value contents. """ record = record_t( source_signature=file_signature(source_file) - , working_directory=configuration.working_directory - , include_paths=configuration.include_paths - , define_symbols=configuration.define_symbols + , config_signature=configuration_signature(configuration) , included_files=included_files , included_files_signature=map( file_signature, included_files) , declarations=declarations Modified: pygccxml_dev/pygccxml/parser/directory_cache.py =================================================================== --- pygccxml_dev/pygccxml/parser/directory_cache.py 2006-06-29 13:05:12 UTC (rev 268) +++ pygccxml_dev/pygccxml/parser/directory_cache.py 2006-07-02 17:25:19 UTC (rev 269) @@ -345,6 +345,7 @@ map(lambda p: m.update(p), config.include_paths) map(lambda p: m.update(p), config.define_symbols) map(lambda p: m.update(p), config.undefine_symbols) + map(lambda p: m.update(p), config.cflags) return m.digest() Modified: pygccxml_dev/pygccxml/parser/source_reader.py =================================================================== --- pygccxml_dev/pygccxml/parser/source_reader.py 2006-06-29 13:05:12 UTC (rev 268) +++ pygccxml_dev/pygccxml/parser/source_reader.py 2006-07-02 17:25:19 UTC (rev 269) @@ -127,6 +127,9 @@ cmd.append( '"%s"' % os.path.normpath( self.__config.gccxml_path ) ) else: cmd.append( '%s' % os.path.normpath( self.__config.gccxml_path ) ) + # Add all cflags passed + if self.__config.cflags != "": + cmd.append(" %s "%self.__config.cflags) #second all additional includes directories cmd.append( ''.join( [' -I"%s"' % search_dir for search_dir in self.__search_directories] ) ) #third all additional defined symbols This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mb...@us...> - 2006-07-08 14:07:19
|
Revision: 276 Author: mbaas Date: 2006-07-08 07:07:13 -0700 (Sat, 08 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=276&view=rev Log Message: ----------- Changed the internal storage for enumerations from dict to list so that the original order of the values is maintained. Modified Paths: -------------- pygccxml_dev/pygccxml/declarations/enumeration.py pygccxml_dev/pygccxml/parser/patcher.py pygccxml_dev/pygccxml/parser/scanner.py Modified: pygccxml_dev/pygccxml/declarations/enumeration.py =================================================================== --- pygccxml_dev/pygccxml/declarations/enumeration.py 2006-07-07 18:44:39 UTC (rev 275) +++ pygccxml_dev/pygccxml/declarations/enumeration.py 2006-07-08 14:07:13 UTC (rev 276) @@ -8,17 +8,35 @@ """ import declaration +import copy +import types class enumeration_t( declaration.declaration_t ): """ describes C++ enum """ def __init__( self, name='', parent=None, values=None ): + """Constructor. + + The items of the list 'values' may either be strings containing + the enumeration value name or tuples (name, numvalue). + + @param name: Enum name + @type name: str + @param parent: Parent declaration + @type parent: declaration_t + @param values: Enumeration values + @type values: list + """ declaration.declaration_t.__init__( self, name, parent ) - if not values: - values = {} - self._values = values # dict name(str) -> value(int) + # A list of tuples (valname(str), valnum(int)). The order of the list should + # be the same as the order in the C/C++ source file. + self._values = [] + + # Initialize values via property access + self.values = values + def __eq__(self, other): if not declaration.declaration_t.__eq__( self, other ): return False @@ -28,9 +46,64 @@ return [self.values] def _get_values(self): - return self._values + return copy.copy(self._values) def _set_values(self, values): - self._values = values + self._values = [] + # None is treated like an empty list + if (values==None): + return + # Check that we have indeed a list... + if type(values)!=list: + raise ValueError, "'values' must be a list (got a %s instead)"%type(values).__name__ + # Append the items individually. This has the effect that there's + # some additional type checking and that a copy of 'values' is stored + # and the caller cannot further manipulate the list via his own reference + for item in values: + if isinstance(item, types.StringTypes): + self.append_value(item) + elif type(item)==tuple: + name,num = item + self.append_value(name, num) + else: + raise ValueError, "'values' contains an invalid item: %s"%item values = property( _get_values, _set_values - , doc="dictionary that contains mapping between name and value, { name(str) : value(int) }") + , doc="""A list of tuples (valname(str), valnum(int)) that contain the enumeration values. + @type: list""") + def append_value(self, valuename, valuenum=None): + """Append another enumeration value to the enum. + + The numeric value may be None in which case it is automatically determined by + increasing the value of the last item. + + When the 'values' attribute is accessed the resulting list will be in the same + order as append_value() was called. + + @param valuename: The name of the value. + @type valuename: str + @param valuenum: The numeric value or None. + @type valuenum: int + """ + # No number given? Then use the previous one + 1 + if valuenum==None: + if len(self._values)==0: + valuenum = 0 + else: + valuenum = self._values[-1][1]+1 + + # Store the new value + self._values.append((valuename, int(valuenum))) + + def has_value_name(self, name): + """Check if this enum has a particular name among its values. + + @param name: Enumeration value name + @type name: str + @return: True if there is an enumeration value with the given name + """ + for val,num in self._values: + if val==name: + return True + return False + + Modified: pygccxml_dev/pygccxml/parser/patcher.py =================================================================== --- pygccxml_dev/pygccxml/parser/patcher.py 2006-07-07 18:44:39 UTC (rev 275) +++ pygccxml_dev/pygccxml/parser/patcher.py 2006-07-08 14:07:13 UTC (rev 276) @@ -56,7 +56,7 @@ type_ = declarations.remove_reference( declarations.remove_cv( arg.type ) ) if not declarations.is_enum( type_ ): return False - return type_.declaration.values.has_key( arg.default_value ) + return type_.declaration.has_value_name( arg.default_value ) def __fix_unqualified_enum( self, func, arg): type_ = declarations.remove_reference( declarations.remove_cv( arg.type ) ) @@ -106,9 +106,11 @@ enums = filter( lambda decl: isinstance( decl, declarations.enumeration_t ) , scope.declarations ) for enum_decl in enums: - if default_value in enum_decl.values.keys(): + valnames = map(lambda x: x[0], enum_decl.values) + valnums = map(lambda x: x[1], enum_decl.values) + if default_value in valnames: return enum_decl - if default_value in enum_decl.values.values(): + if default_value in valnums: return enum_decl else: return None @@ -188,4 +190,4 @@ patcher2 = fix_casting_operator_name_patcher_t( decls ) patcher2.patch_it() return patcher.decls - \ No newline at end of file + Modified: pygccxml_dev/pygccxml/parser/scanner.py =================================================================== --- pygccxml_dev/pygccxml/parser/scanner.py 2006-07-07 18:44:39 UTC (rev 275) +++ pygccxml_dev/pygccxml/parser/scanner.py 2006-07-08 14:07:13 UTC (rev 276) @@ -255,7 +255,9 @@ return self.__decl_factory.create_enumeration( name=enum_name ) def __read_enumeration_value( self, attrs ): - self.__inst.values[attrs.get( XML_AN_NAME, '' )] = attrs[XML_AN_INIT] + name = attrs.get( XML_AN_NAME, '' ) + num = int(attrs[XML_AN_INIT]) + self.__inst.append_value(name, num) def __read_array_type( self, attrs ): type_ = attrs[ XML_AN_TYPE ] This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-08-26 17:26:25
|
Revision: 475 Author: roman_yakovenko Date: 2006-08-26 10:26:11 -0700 (Sat, 26 Aug 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=475&view=rev Log Message: ----------- adding declarations and type algorirthms result cache Modified Paths: -------------- pygccxml_dev/pygccxml/declarations/algorithm.py pygccxml_dev/pygccxml/declarations/class_declaration.py pygccxml_dev/pygccxml/declarations/declaration.py pygccxml_dev/pygccxml/declarations/namespace.py pygccxml_dev/pygccxml/declarations/scopedef.py pygccxml_dev/pygccxml/parser/linker.py Added Paths: ----------- pygccxml_dev/pygccxml/declarations/algorithms_cache.py Modified: pygccxml_dev/pygccxml/declarations/algorithm.py =================================================================== --- pygccxml_dev/pygccxml/declarations/algorithm.py 2006-08-26 12:14:17 UTC (rev 474) +++ pygccxml_dev/pygccxml/declarations/algorithm.py 2006-08-26 17:26:11 UTC (rev 475) @@ -19,18 +19,15 @@ """ if not decl: return [] - cached_decl_path = getattr(decl, "cached_decl_path", None) - if cached_decl_path: - return cached_decl_path - else: + if not decl.cache.declaration_path: result = [ decl.name ] parent = decl.parent while parent: result.append( parent.name ) parent = parent.parent result.reverse() - setattr(decl, "cached_decl_path", result) - return result + decl.cache.declaration_path = result + return decl.cache.declaration_path def full_name( decl ): """ @@ -44,11 +41,13 @@ """ if None is decl: raise RuntimeError( "Unable to generate full name for None object!" ) - decl_path = declaration_path( decl ) - ##Here I have lack of knowledge: - ##TODO: "What is the full name of declaration declared in unnamed namespace?" - result = filter( None, decl_path ) - return result[0] + '::'.join( result[1:] ) + if not decl.cache.full_name: + decl_path = declaration_path( decl ) + ##Here I have lack of knowledge: + ##TODO: "What is the full name of declaration declared in unnamed namespace?" + result = filter( None, decl_path ) + decl.cache.full_name = result[0] + '::'.join( result[1:] ) + return decl.cache.full_name def make_flatten( decl_or_decls ): Added: pygccxml_dev/pygccxml/declarations/algorithms_cache.py =================================================================== --- pygccxml_dev/pygccxml/declarations/algorithms_cache.py (rev 0) +++ pygccxml_dev/pygccxml/declarations/algorithms_cache.py 2006-08-26 17:26:11 UTC (rev 475) @@ -0,0 +1,33 @@ +# Copyright 2004 Roman Yakovenko. +# Distributed under the Boost Software License, Version 1.0. (See +# accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +""" +defines class that will keep results of different calculations. +""" + +class algorithms_cache_t( object ): + def __init__( self ): + object.__init__( self ) + self.full_name = None + self.access_type = None + self.declaration_path = None + + def reset( self ): + self.full_name = None + self.access_type = None + self.declaration_path = None + + def reset_name_based( self ): + self.full_name = None + self.declaration_path = None + + def reset_access_type( self ): + self.access_type = None + +class type_traits_cache_t( object ): + def __init__( self ): + object.__init__( self ) + self.remove_alias = None + Modified: pygccxml_dev/pygccxml/declarations/class_declaration.py =================================================================== --- pygccxml_dev/pygccxml/declarations/class_declaration.py 2006-08-26 12:14:17 UTC (rev 474) +++ pygccxml_dev/pygccxml/declarations/class_declaration.py 2006-08-26 17:26:11 UTC (rev 475) @@ -107,9 +107,7 @@ if not self._name: #class with empty name return self._name elif class_t.USE_DEMANGLED_AS_NAME and self.demangled: - if self.__cached_demangled_name: - return self.__cached_demangled_name - else: + if not self.__cached_demangled_name: fname = algorithm.full_name( self.parent ) if fname.startswith( '::' ) and not self.demangled.startswith( '::' ): fname = fname[2:] @@ -120,7 +118,7 @@ self.__cached_demangled_name = tmp else: self.__cached_demangled_name = self._name - return self.__cached_demangled_name + return self.__cached_demangled_name else: return self._name @@ -246,6 +244,8 @@ returns list of members according to access type If access equals to None, then returned list will contain all members. + You should not modify the list content, otherwise different optimization + data will stop work and may to give you wrong results. @param access: describes desired members @type access: L{ACCESS_TYPES} @@ -265,25 +265,24 @@ all_members.extend( self.private_members ) return all_members - def set_members( self, access, new_members ): - """ - set list of members according to access type + def adopt_declaration( self, decl, access ): + """adds new declaration to the class - @param access: describes desired members - @type access: L{ACCESS_TYPES} + @param decl: reference to a L{declaration<declaration_t>} - @param new_members: list of new members - @type new_members: [ L{member<declaration_t>} ] + @param access: member access type + @type access: L{ACCESS_TYPES} """ - assert( access in ACCESS_TYPES.ALL ) if access == ACCESS_TYPES.PUBLIC: - self.public_members = new_members + self.public_members.append( decl ) elif access == ACCESS_TYPES.PROTECTED: - self.protected_members = new_members + self.protected_members.append( decl ) + elif access == ACCESS_TYPES.PRIVATE: + self.private_members.append( decl ) else: - self.private_members = new_members - for member in new_members: - member.parent = self + raise RuntimeError( "Invalid access type: %s." % access ) + decl.parent = self + decl.cache.access_type = access def remove_declaration( self, decl ): """ @@ -293,19 +292,16 @@ @type decl: L{declaration_t} """ container = None - if decl in self.public_members: + access_type = self.find_out_member_access_type( decl ) + if access_type == ACCESS_TYPES.PUBLIC: container = self.public_members - elif decl in self.protected_members: + elif access_type == ACCESS_TYPES.PROTECTED: container = self.protected_members - elif decl in self.private_members: + else: #decl.cache.access_type == ACCESS_TYPES.PRVATE container = self.private_members - else: - raise ValueError() del container[ container.index( decl ) ] - #add more comment about this. - #if not keep_parent: - # decl.parent=None - + decl.cache.reset_access_type() + def find_out_member_access_type( self, member ): """ returns member access type @@ -316,19 +312,15 @@ @return: L{ACCESS_TYPES} """ assert member.parent is self - cached_access_type = getattr(member, "_cached_access_type", None) - if cached_access_type: - return cached_access_type - else: + if not member.cache.access_type: access_type = None if member in self.public_members: - access_type = ACCESS_TYPES.PUBLIC + member.cache.access_type = ACCESS_TYPES.PUBLIC elif member in self.protected_members: - access_type = ACCESS_TYPES.PROTECTED + member.cache.access_type = ACCESS_TYPES.PROTECTED elif member in self.private_members: - access_type = ACCESS_TYPES.PRIVATE + member.cache.access_type = ACCESS_TYPES.PRIVATE else: raise RuntimeError( "Unable to find member within internal members list." ) - setattr(member, "_cached_access_type", access_type) - return access_type + return member.cache.access_type Modified: pygccxml_dev/pygccxml/declarations/declaration.py =================================================================== --- pygccxml_dev/pygccxml/declarations/declaration.py 2006-08-26 12:14:17 UTC (rev 474) +++ pygccxml_dev/pygccxml/declarations/declaration.py 2006-08-26 17:26:11 UTC (rev 475) @@ -12,8 +12,8 @@ import algorithm import templates +import algorithms_cache - class location_t(object): """provides information about the location of the declaration within the source file. @@ -75,8 +75,7 @@ self._mangled = mangled self._demangled = demangled self._parent = None - - #self._cached_name = None + self._cache = algorithms_cache.algorithms_cache_t() def __str__(self): """Default __str__ method. @@ -159,8 +158,15 @@ # return self._cached_name return self._get_name_impl() + def _on_rename( self ): + pass + def _set_name( self, new_name ): + previous_name = self._name self._name = new_name + if previous_name: #the was a rename and not initial "set" + self._on_rename() + name = property( _get_name, _set_name , doc="""Declaration name @type: str @@ -236,3 +242,10 @@ doc="""Full name of the declaration @type: str """ ) + @property + def cache( self ): + """implementation details + + reference to instance of L{algorithms_cache.algorithms_cache_t} class. + """ + return self._cache \ No newline at end of file Modified: pygccxml_dev/pygccxml/declarations/namespace.py =================================================================== --- pygccxml_dev/pygccxml/declarations/namespace.py 2006-08-26 12:14:17 UTC (rev 474) +++ pygccxml_dev/pygccxml/declarations/namespace.py 2006-08-26 17:26:11 UTC (rev 475) @@ -48,6 +48,10 @@ self.declarations.append( decl ) inst.declarations = [] + def adopt_declaration( self, decl ): + self.declarations.append( decl ) + decl.parent = self + def remove_declaration( self, decl ): """ removes decl from members list Modified: pygccxml_dev/pygccxml/declarations/scopedef.py =================================================================== --- pygccxml_dev/pygccxml/declarations/scopedef.py 2006-08-26 12:14:17 UTC (rev 474) +++ pygccxml_dev/pygccxml/declarations/scopedef.py 2006-08-26 17:26:11 UTC (rev 475) @@ -205,6 +205,15 @@ return add_operator( symbol ) return name #both name and symbol are None + def _on_rename( self ): + for decl in self.decls(allow_empty=True): + decl.cache.reset_name_based() + #I am not sure whether to introduce this or not? + #It could be very time consuming operation + it changes optimize query + #data structures. + #if self.parent: + # if self.parent._optimized: + # self.parent.init_optimizer() def __normalize_args( self, **keywds ): """implementation details""" Modified: pygccxml_dev/pygccxml/parser/linker.py =================================================================== --- pygccxml_dev/pygccxml/parser/linker.py 2006-08-26 12:14:17 UTC (rev 474) +++ pygccxml_dev/pygccxml/parser/linker.py 2006-08-26 17:26:11 UTC (rev 475) @@ -54,10 +54,9 @@ continue decl = self.__decls[member] if isinstance( self.__inst, class_t ): - self.__inst.get_members( access ).append( decl ) + self.__inst.adopt_declaration( decl, access ) else: - self.__inst.declarations.append( decl ) - decl.parent = self.__inst + self.__inst.adopt_declaration( decl ) def __link_calldef(self): self.__inst.return_type = self.__link_type( self.__inst.return_type ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2007-04-19 08:51:23
|
Revision: 1002 http://svn.sourceforge.net/pygccxml/?rev=1002&view=rev Author: roman_yakovenko Date: 2007-04-19 01:51:24 -0700 (Thu, 19 Apr 2007) Log Message: ----------- adding cElementTree parser - for big xml file the gain in speed could be more than 5% Modified Paths: -------------- pygccxml_dev/pygccxml/parser/scanner.py pygccxml_dev/pygccxml/parser/source_reader.py Added Paths: ----------- pygccxml_dev/pygccxml/parser/etree_scanner.py Added: pygccxml_dev/pygccxml/parser/etree_scanner.py =================================================================== --- pygccxml_dev/pygccxml/parser/etree_scanner.py (rev 0) +++ pygccxml_dev/pygccxml/parser/etree_scanner.py 2007-04-19 08:51:24 UTC (rev 1002) @@ -0,0 +1,49 @@ +# Copyright 2004 Roman Yakovenko. +# Distributed under the Boost Software License, Version 1.0. (See +# accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +import scanner +import xml.etree.cElementTree as ElementTree + +class etree_saxifier_t(object): + """Produces SAX events for an element and children.""" + def __init__(self, element_or_tree, content_handler): + try: + element = element_or_tree.getroot() + except AttributeError: + element = element_or_tree + self._element = element + self._content_handler = content_handler + + def saxify(self): + self._content_handler.startDocument() + self._recursive_saxify(self._element, {}) + self._content_handler.endDocument() + + def _recursive_saxify(self, element, prefixes): + attrs = {} + for attr in element.items(): + attrs[ attr[0] ] = attr[1] + + content_handler = self._content_handler + content_handler.startElement( element.tag, attrs ) + + if element.text: + content_handler.characters(element.text) + for child in element: + self._recursive_saxify(child, prefixes) + content_handler.endElement( element.tag ) + + if element.tail: + content_handler.characters(element.tail) + +class etree_scanner_t( scanner.scanner_t ): + def __init__(self, gccxml_file, decl_factory, *args ): + scanner.scanner_t.__init__( self, gccxml_file, decl_factory, *args ) + + def read( self ): + tree = ElementTree.parse( self.gccxml_file ) + saxifier = etree_saxifier_t( tree, self ) + saxifier.saxify() + Modified: pygccxml_dev/pygccxml/parser/scanner.py =================================================================== --- pygccxml_dev/pygccxml/parser/scanner.py 2007-04-19 07:19:18 UTC (rev 1001) +++ pygccxml_dev/pygccxml/parser/scanner.py 2007-04-19 08:51:24 UTC (rev 1002) @@ -165,6 +165,12 @@ def members(self): return self.__members + def startElementNS(self, name, qname, attrs): + return self.startElement( name[1], attrs ) + + def endElementNS(self, name, qname): + return self.endElement( name[1] ) + def startElement(self, name, attrs): try: if name not in self.__readers: Modified: pygccxml_dev/pygccxml/parser/source_reader.py =================================================================== --- pygccxml_dev/pygccxml/parser/source_reader.py 2007-04-19 07:19:18 UTC (rev 1001) +++ pygccxml_dev/pygccxml/parser/source_reader.py 2007-04-19 08:51:24 UTC (rev 1002) @@ -8,7 +8,12 @@ import config import pygccxml.utils import linker -import scanner + +try: #select faster xml parser + from etree_scanner import etree_scanner_t as scanner_t +except: + from scanner import scanner_t + import declarations_cache import patcher from pygccxml.declarations import * @@ -308,7 +313,7 @@ return file_path def __parse_gccxml_created_file( self, gccxml_file ): - scanner_ = scanner.scanner_t( gccxml_file, self.__decl_factory ) + scanner_ = scanner_t( gccxml_file, self.__decl_factory ) scanner_.read() decls = scanner_.declarations() types = scanner_.types() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2007-04-19 21:13:17
|
Revision: 1008 http://svn.sourceforge.net/pygccxml/?rev=1008&view=rev Author: roman_yakovenko Date: 2007-04-19 14:13:19 -0700 (Thu, 19 Apr 2007) Log Message: ----------- calculated only once some variables Modified Paths: -------------- pygccxml_dev/pygccxml/parser/linker.py pygccxml_dev/pygccxml/parser/scanner.py Modified: pygccxml_dev/pygccxml/parser/linker.py =================================================================== --- pygccxml_dev/pygccxml/parser/linker.py 2007-04-19 16:28:15 UTC (rev 1007) +++ pygccxml_dev/pygccxml/parser/linker.py 2007-04-19 21:13:19 UTC (rev 1008) @@ -23,9 +23,9 @@ return self.__inst def _set_inst(self, inst): self.__inst = inst - if isinstance( self.__inst, declaration_t ): - if self.__inst.location is not None: - self.__inst.location.file_name = self.__files[self.__inst.location.file_name] + #use inst, to reduce attribute access time + if isinstance( inst, declaration_t ) and inst.location: + inst.location.file_name = self.__files[inst.location.file_name] instance = property( _get_inst, _set_inst ) def __link_type(self, type_id): @@ -248,4 +248,4 @@ def visit_declarated( self ): if isinstance( self.__inst.declaration, types.StringTypes ): - self.__inst.declaration = self.__decls[self.__inst.declaration] \ No newline at end of file + self.__inst.declaration = self.__decls[self.__inst.declaration] Modified: pygccxml_dev/pygccxml/parser/scanner.py =================================================================== --- pygccxml_dev/pygccxml/parser/scanner.py 2007-04-19 16:28:15 UTC (rev 1007) +++ pygccxml_dev/pygccxml/parser/scanner.py 2007-04-19 21:13:19 UTC (rev 1008) @@ -182,23 +182,21 @@ if name in self.deep_declarations: self.__inst = obj self.__read_access( attrs ) + element_id = attrs.get(XML_AN_ID, None) if isinstance( obj, declaration_t ): self.__update_membership( attrs ) - self.__declarations[ attrs[XML_AN_ID] ] = obj + self.__declarations[ element_id ] = obj if not isinstance( obj, namespace_t ): self.__read_location( obj, attrs ) - if isinstance( obj, scopedef_t): - #deprecated - #self.__read_members( obj, attrs ) - if isinstance( obj, class_t ): - self.__read_bases( obj, attrs ) + if isinstance( obj, class_t): + self.__read_bases( obj, attrs ) self.__read_artificial(obj, attrs) self.__read_mangled( obj, attrs) self.__read_demangled( obj, attrs) elif isinstance( obj, type_t ): - self.__types[ attrs[XML_AN_ID] ] = obj + self.__types[ element_id ] = obj elif isinstance( obj, types.StringTypes ): - self.__files[ attrs[XML_AN_ID] ] = obj + self.__files[ element_id ] = obj else: self.logger.warning( 'Unknown object type has been found.' + ' Please report this bug to pygccxml development team.' ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2007-04-19 21:50:47
|
Revision: 1009 http://svn.sourceforge.net/pygccxml/?rev=1009&view=rev Author: roman_yakovenko Date: 2007-04-19 14:50:46 -0700 (Thu, 19 Apr 2007) Log Message: ----------- another performance optimization - on file 31Mb the number of functions calls was reduced from 15815730 to 10073090 and it is not the limit Modified Paths: -------------- pygccxml_dev/pygccxml/parser/patcher.py pygccxml_dev/pygccxml/parser/source_reader.py Modified: pygccxml_dev/pygccxml/parser/patcher.py =================================================================== --- pygccxml_dev/pygccxml/parser/patcher.py 2007-04-19 21:13:19 UTC (rev 1008) +++ pygccxml_dev/pygccxml/parser/patcher.py 2007-04-19 21:50:46 UTC (rev 1009) @@ -6,33 +6,19 @@ from pygccxml import utils from pygccxml import declarations -class patcher_base_t(object): - def __init__( self, decls ): + +class default_argument_patcher_t( object ): + def __init__( self ): object.__init__( self ) - self.__decls = decls + + def __call__(self, decl): + for arg in decl.arguments: + if not arg.default_value: + continue + fixer = self.__find_fixer( decl, arg ) + if fixer: + arg.default_value = fixer( decl, arg ) - def _get_decls(self): - return self.__decls - decls = property( _get_decls ) - - def patch_it(self): - raise NotImplementedError() - -class default_argument_patcher_t( patcher_base_t ): - def __init__( self, decls ): - patcher_base_t.__init__( self, decls ) - - def patch_it(self): - for decl in declarations.make_flatten( self.decls ): - if not isinstance( decl, declarations.calldef_t ): - continue - for arg in decl.arguments: - if not arg.default_value: - continue - fixer = self.__find_fixer( decl, arg ) - if fixer: - arg.default_value = fixer( decl, arg ) - def __find_fixer(self, func, arg): if not arg.default_value: return False @@ -116,11 +102,10 @@ #this algorithm could be improved: it could take into account #1. unnamed namespaced #2. location within files - enums = filter( lambda decl: isinstance( decl, declarations.enumeration_t ) - , scope.declarations ) - for enum_decl in enums: - if enum_decl.has_value_name( default_value ): - return enum_decl + enumeration_t = declarations.enumeration_t + for decl in scope.declarations: + if isinstance( decl, enumeration_t ) and decl.has_value_name( default_value ): + return decl return None def __is_double_call( self, func, arg ): @@ -182,20 +167,21 @@ return call_invocation.join( f_q_name, args ) -class fix_casting_operator_name_patcher_t( patcher_base_t ): - def __init__( self, decls ): - patcher_base_t.__init__( self, decls ) +class casting_operator_patcher_t( object ): + def __init__( self ): + object.__init__( self ) - def patch_it(self): - for decl in declarations.make_flatten( self.decls ): - if not isinstance( decl, declarations.casting_operator_t): - continue - decl.name = 'operator ' + decl.return_type.decl_string + def __call__(self, decl): + decl.name = 'operator ' + decl.return_type.decl_string -def patch_it(decls): - patcher = default_argument_patcher_t( decls ) - patcher.patch_it() - patcher2 = fix_casting_operator_name_patcher_t( decls ) - patcher2.patch_it() - return patcher.decls +_default_arg_patcher_ = default_argument_patcher_t() +_casting_oper_patcher_ = casting_operator_patcher_t() + +def fix_decls(decls): + #decls should be flat list of all declarations, you want to apply patch on + for decl in decls: + if isinstance( decl, declarations.calldef_t ): + _default_arg_patcher_( decl ) + if isinstance( decl, declarations.casting_operator_t): + _casting_oper_patcher_( decl ) Modified: pygccxml_dev/pygccxml/parser/source_reader.py =================================================================== --- pygccxml_dev/pygccxml/parser/source_reader.py 2007-04-19 21:13:19 UTC (rev 1008) +++ pygccxml_dev/pygccxml/parser/source_reader.py 2007-04-19 21:50:46 UTC (rev 1009) @@ -318,14 +318,14 @@ decls = scanner_.declarations() types = scanner_.types() files = {} - for file_id, file_path in scanner_.files().items(): + for file_id, file_path in scanner_.files().iteritems(): files[file_id] = self.__produce_full_file(file_path) linker_ = linker.linker_t( decls=decls , types=types , access=scanner_.access() , membership=scanner_.members() , files=files ) - for type_ in list( types.itervalues() ): + for type_ in types.values(): #I need this copy because internaly linker change types collection linker_.instance = type_ apply_visitor( linker_, type_ ) @@ -333,16 +333,13 @@ linker_.instance = decl apply_visitor( linker_, decl ) bind_aliases( decls.itervalues() ) - decls = filter( lambda inst: isinstance(inst, declaration_t) and not inst.parent, decls.itervalues() ) #some times gccxml report typedefs defined in no namespace #it happens for example in next situation #template< typename X> - #void ddd(){ typedef typename X::Y YY;} + #void ddd(){ typedef typename X::Y YY;} + decls = filter( lambda inst: isinstance(inst, declaration_t) and not inst.parent + , decls.itervalues() ) + patcher.fix_decls( make_flatten( decls ) ) decls = filter( lambda inst: isinstance( inst, namespace_t ), decls ) - decls = patcher.patch_it( decls ) - decls_all = make_flatten( decls ) - for decl in decls_all: - if decl.location: - decl.location.file_name = self.__produce_full_file( decl.location.file_name ) return ( decls, files.values() ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2007-04-21 17:21:42
|
Revision: 1012 http://svn.sourceforge.net/pygccxml/?rev=1012&view=rev Author: roman_yakovenko Date: 2007-04-21 10:21:44 -0700 (Sat, 21 Apr 2007) Log Message: ----------- adding another set of performance optimizations, basically to reduce the number of "isinstance" calls Modified Paths: -------------- pygccxml_dev/pygccxml/parser/patcher.py pygccxml_dev/pygccxml/parser/scanner.py pygccxml_dev/pygccxml/parser/source_reader.py Modified: pygccxml_dev/pygccxml/parser/patcher.py =================================================================== --- pygccxml_dev/pygccxml/parser/patcher.py 2007-04-20 20:22:23 UTC (rev 1011) +++ pygccxml_dev/pygccxml/parser/patcher.py 2007-04-21 17:21:44 UTC (rev 1012) @@ -177,12 +177,11 @@ _casting_oper_patcher_ = casting_operator_patcher_t() -def fix_decls(decls, enums): +def fix_calldef_decls(decls, enums): default_arg_patcher = default_argument_patcher_t(enums) #decls should be flat list of all declarations, you want to apply patch on for decl in decls: - if isinstance( decl, declarations.calldef_t ): - default_arg_patcher( decl ) + default_arg_patcher( decl ) if isinstance( decl, declarations.casting_operator_t): _casting_oper_patcher_( decl ) Modified: pygccxml_dev/pygccxml/parser/scanner.py =================================================================== --- pygccxml_dev/pygccxml/parser/scanner.py 2007-04-20 20:22:23 UTC (rev 1011) +++ pygccxml_dev/pygccxml/parser/scanner.py 2007-04-21 17:21:44 UTC (rev 1012) @@ -127,7 +127,7 @@ #mapping from id -> decl self.__declarations = {} #list of all read declarations - self.__all_declarations = [] + self.__calldefs = [] #list of enums I need later self.__enums = [] #mapping from id -> type @@ -157,8 +157,8 @@ def declarations(self): return self.__declarations - def all_declarations( self ): - return self.__all_declarations + def calldefs( self ): + return self.__calldefs def enums(self): return self.__enums @@ -194,7 +194,6 @@ self.__read_access( attrs ) element_id = attrs.get(XML_AN_ID, None) if isinstance( obj, declaration_t ): - self.__all_declarations.append( obj ) self.__update_membership( attrs ) self.__declarations[ element_id ] = obj if not isinstance( obj, namespace_t ): @@ -335,10 +334,11 @@ argument.default_value = None self.__inst.arguments.append( argument ) - def __read_calldef( self, calldef, attrs ): + def __read_calldef( self, calldef, attrs, is_declaration ): #destructor for example doesn't have return type calldef.return_type = attrs.get( XML_AN_RETURNS, None ) - if isinstance( calldef, declaration_t ): + if is_declaration: + self.__calldefs.append( calldef ) calldef.name = attrs.get(XML_AN_NAME, '') calldef.has_extern = attrs.get( XML_AN_EXTERN, False ) throw_stmt = attrs.get( XML_AN_THROW, None ) @@ -352,10 +352,10 @@ calldef.does_throw = True calldef.exceptions = throw_stmt.split() - def __read_member_function( self, calldef, attrs ): - self.__read_calldef( calldef, attrs ) + def __read_member_function( self, calldef, attrs, is_declaration ): + self.__read_calldef( calldef, attrs, is_declaration ) calldef.has_const = attrs.get( XML_AN_CONST, False ) - if isinstance( calldef, declaration_t ): + if is_declaration: calldef.has_static = attrs.get( XML_AN_STATIC, False ) if attrs.has_key( XML_AN_PURE_VIRTUAL ): calldef.virtuality = VIRTUALITY_TYPES.PURE_VIRTUAL @@ -368,12 +368,12 @@ def __read_function_type(self, attrs): answer = free_function_type_t() - self.__read_calldef( answer, attrs ) + self.__read_calldef( answer, attrs, False ) return answer def __read_method_type(self, attrs): answer = member_function_type_t() - self.__read_member_function( answer, attrs ) + self.__read_member_function( answer, attrs, False ) return answer def __read_typedef(self, attrs ): @@ -420,33 +420,33 @@ def __read_casting_operator(self, attrs ): operator = self.__decl_factory.create_casting_operator() - self.__read_member_function( operator, attrs ) + self.__read_member_function( operator, attrs, True ) return operator def __read_constructor( self, attrs ): constructor = self.__decl_factory.create_constructor() - self.__read_member_function( constructor, attrs ) + self.__read_member_function( constructor, attrs, True ) return constructor def __read_function(self, attrs): gfunction = self.__decl_factory.create_free_function() - self.__read_calldef( gfunction, attrs ) + self.__read_calldef( gfunction, attrs, True ) return gfunction def __read_method(self, attrs): mfunction = self.__decl_factory.create_member_function() - self.__read_member_function( mfunction, attrs ) + self.__read_member_function( mfunction, attrs, True ) return mfunction def __read_destructor(self, attrs): destructor = self.__decl_factory.create_destructor() - self.__read_member_function( destructor, attrs ) + self.__read_member_function( destructor, attrs, True ) destructor.name = '~' + destructor.name return destructor def __read_free_operator(self, attrs ): operator = self.__decl_factory.create_free_operator() - self.__read_member_function( operator, attrs ) + self.__read_member_function( operator, attrs, True ) if 'new' in operator.name or 'delete' in operator.name: operator.name = 'operator ' + operator.name else: @@ -455,7 +455,7 @@ def __read_member_operator(self, attrs): operator = self.__decl_factory.create_member_operator() - self.__read_member_function( operator, attrs ) + self.__read_member_function( operator, attrs, True ) if 'new' in operator.name or 'delete' in operator.name: operator.name = 'operator ' + operator.name else: Modified: pygccxml_dev/pygccxml/parser/source_reader.py =================================================================== --- pygccxml_dev/pygccxml/parser/source_reader.py 2007-04-20 20:22:23 UTC (rev 1011) +++ pygccxml_dev/pygccxml/parser/source_reader.py 2007-04-21 17:21:44 UTC (rev 1012) @@ -338,7 +338,7 @@ #template< typename X> #void ddd(){ typedef typename X::Y YY;} #if I will fail on this bug next time, the right way to fix it may be different - patcher.fix_decls( scanner_.all_declarations(), scanner_.enums() ) + patcher.fix_calldef_decls( scanner_.calldefs(), scanner_.enums() ) decls = filter( lambda inst: isinstance( inst, namespace_t ) and not inst.parent , decls.itervalues() ) return ( decls, files.values() ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2007-05-27 20:21:21
|
Revision: 1046 http://svn.sourceforge.net/pygccxml/?rev=1046&view=rev Author: roman_yakovenko Date: 2007-05-27 13:21:17 -0700 (Sun, 27 May 2007) Log Message: ----------- adding sceleton of synopsis parser Modified Paths: -------------- pygccxml_dev/pygccxml/parser/__init__.py pygccxml_dev/pygccxml/parser/source_reader.py Added Paths: ----------- pygccxml_dev/pygccxml/parser/synopsis_reader.py pygccxml_dev/pygccxml/parser/synopsis_scanner.py Modified: pygccxml_dev/pygccxml/parser/__init__.py =================================================================== --- pygccxml_dev/pygccxml/parser/__init__.py 2007-05-27 19:16:22 UTC (rev 1045) +++ pygccxml_dev/pygccxml/parser/__init__.py 2007-05-27 20:21:17 UTC (rev 1046) @@ -7,6 +7,10 @@ """ from config import config_t +from config import gccxml_configuration_t +from config import synopsis_configuration_t + + from project_reader import COMPILATION_MODE from project_reader import project_reader_t from project_reader import file_configuration_t @@ -56,4 +60,4 @@ def parse_xml_file( content, config=None ): parser = source_reader_t( config ) - return parser.read_xml_file( content ) \ No newline at end of file + return parser.read_xml_file( content ) Modified: pygccxml_dev/pygccxml/parser/source_reader.py =================================================================== --- pygccxml_dev/pygccxml/parser/source_reader.py 2007-05-27 19:16:22 UTC (rev 1045) +++ pygccxml_dev/pygccxml/parser/source_reader.py 2007-05-27 20:21:17 UTC (rev 1046) @@ -5,9 +5,10 @@ import os import sys +import linker import config +import patcher import pygccxml.utils -import linker try: #select faster xml parser from etree_scanner import etree_scanner_t as scanner_t @@ -15,9 +16,8 @@ from scanner import scanner_t import declarations_cache -import patcher -from pygccxml.declarations import * from pygccxml import utils +from pygccxml.declarations import * class gccxml_runtime_error_t( RuntimeError ): def __init__( self, msg ): @@ -77,7 +77,7 @@ @param decl_factory: declarations factory, if not given default declarations factory L{decl_factory_t} will be used """ - self.logger = utils.loggers.gccxml + self.logger = utils.loggers.cxx_parser self.__search_directories = [] self.__config = config self.__search_directories.append( config.working_directory ) @@ -85,44 +85,11 @@ if not cache: cache = declarations_cache.dummy_cache_t() self.__dcache = cache - self.__raise_on_wrong_settings() + self.__config.raise_on_wrong_settings() self.__decl_factory = decl_factory if not decl_factory: self.__decl_factory = decl_factory_t() - def __raise_on_wrong_settings(self): - if not os.path.isfile( self.__config.gccxml_path ): - if sys.platform == 'win32': - gccxml_name = 'gccxml' + '.exe' - environment_var_delimiter = ';' - elif sys.platform == 'linux2' or sys.platform == 'darwin': - gccxml_name = 'gccxml' - environment_var_delimiter = ':' - else: - raise RuntimeError( 'unable to find out location of gccxml' ) - may_be_gccxml = os.path.join( self.__config.gccxml_path, gccxml_name ) - if os.path.isfile( may_be_gccxml ): - self.__config.gccxml_path = may_be_gccxml - else: - for path in os.environ['PATH'].split( environment_var_delimiter ): - gccxml_path = os.path.join( path, gccxml_name ) - if os.path.isfile( gccxml_path ): - self.__config.gccxml_path = gccxml_path - break - else: - msg = 'gccxml_path("%s") should exists or to be a valid file name.' \ - % self.__config.gccxml_path - raise RuntimeError( msg ) - if not os.path.isdir( self.__config.working_directory ): - msg = 'working_directory("%s") should exists or to be a valid directory name.' \ - % self.__config.working_directory - raise RuntimeError( msg ) - for include_path in self.__config.include_paths: - if not os.path.isdir( include_path ): - msg = 'include path "%s" should exists or to be a valid directory name.' \ - % include_path - raise RuntimeError( msg ) - def __create_command_line(self, file, xmlfile): assert isinstance( self.__config, config.config_t ) #returns @@ -222,8 +189,14 @@ finally: pygccxml.utils.remove_file_no_raise( header_file ) return gccxml_file - - def read_file(self, source_file): + + def read_file( self, source_file ): + if isinstance( self.__config, config.gccxml_configuration_t ): + return self.read_gccxml_file( source_file ) + else: + return self.read_synopsis_file( source_file ) + + def read_gccxml_file(self, source_file): """ Reads C++ source file and returns declarations tree @@ -342,4 +315,28 @@ decls = filter( lambda inst: isinstance( inst, namespace_t ) and not inst.parent , decls.itervalues() ) return ( decls, files.values() ) + + def read_synopsis_file( self, source_file ): + import synopsis_scanner + from Synopsis import AST + from Synopsis.Parsers import Cxx + ffname = self.__file_full_name(source_file) + + cppflags = [] + map( lambda dpath: cppflags.append( '-I %s' % dpath ) + , self.__config.include_paths ) + map( lambda define: cppflags.append( '-D %s' % define ) + , self.__config.define_symbols ) + map( lambda define: cppflags.append( '-U %s' % define ) + , self.__config.undefine_symbols ) + + cxx = Cxx.Parser( preprocess=True, cppflags=cppflags ) + ast = AST.AST() + cxx.process( ast, input=[source_file] ) + scanner = synopsis_scanner.scanner_t( ast, self.__decl_factory ) + scanner.visitAST( ast ) + declarations = [scanner.global_ns] + self.__dcache.update( ffname, self.__config, declarations, [] ) + return declarations + Added: pygccxml_dev/pygccxml/parser/synopsis_reader.py =================================================================== --- pygccxml_dev/pygccxml/parser/synopsis_reader.py (rev 0) +++ pygccxml_dev/pygccxml/parser/synopsis_reader.py 2007-05-27 20:21:17 UTC (rev 1046) @@ -0,0 +1,36 @@ +import os +import sys + +from Synopsis import AST +from Synopsis.Parsers import Cxx + +headers_dir = '/home/roman/language-binding/sources/pygccxml_dev/unittests/data' + +offset = 0 +def print_decls( d ): + global offset + print offset * ' ', d.name(), d.__class__.__name__ + if hasattr( d, 'declarations' ): + offset += 1 + for d1 in d.declarations(): + print_decls( d1 ) + offset -= 1 + +def parse( f ): + global offset, headers_dir + print 'file ', f + cxx = Cxx.Parser( + preprocess=True + , cppflags=['-I %s' % headers_dir ] ) + + ast = AST.AST() + cxx.process( ast, input=[os.path.join(headers_dir, f )] ) + + offset = 0 + for d in ast.declarations(): + print_decls( d ) + +parse( 'declarations_enums.hpp' ) +#for x in os.listdir( headers_dir ): + #if x.endswith( 'hpp' ): + #parse( x ) Added: pygccxml_dev/pygccxml/parser/synopsis_scanner.py =================================================================== --- pygccxml_dev/pygccxml/parser/synopsis_scanner.py (rev 0) +++ pygccxml_dev/pygccxml/parser/synopsis_scanner.py 2007-05-27 20:21:17 UTC (rev 1046) @@ -0,0 +1,46 @@ +# Copyright 2004 Roman Yakovenko. +# Distributed under the Boost Software License, Version 1.0. (See +# accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +import os +import types +import pprint +import warnings +from Synopsis import AST +from pygccxml import utils +from pygccxml.declarations import * + +class scanner_t( AST.Visitor, object ): + def __init__(self, ast, decl_factory ): + self.logger = utils.loggers.cxx_parser + self.ast = ast + + assert isinstance( decl_factory, decl_factory_t ) + self.__decl_factory = decl_factory + + #mapping from id -> decl + self.__decl = self.__decl_factory.create_namespace( name='::' ) + self.global_ns = self.__decl + + + def read_deaclaration( self, node, decl ): + #this function should not be called for namespace + decl.name = node.name() + decl.location = location_t( file_name=node.file(), line=node.line() ) + + def visitModule( self, node ): + ns = self.__decl_factory.create_namespace( name=node.name() ) + self.__decl.adopt_declaration( ns ) + self.__decl = ns + super( scanner_t, self ).visitModule( node ) + + def visitEnum( self, node ): + values = [] + for enumerator in node.enumerators(): + print enumerator.name(), ':', enumerator.value() + values.append( ( enumerator.name(), enumerator.value() ) ) + enum = self.__decl_factory.create_enumeration( values=values ) + self.read_deaclaration( node, enum ) + self.__decl.adopt_declaration( enum ) + super( scanner_t, self ).visitEnum( node ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2007-11-07 21:24:10
|
Revision: 1128 http://pygccxml.svn.sourceforge.net/pygccxml/?rev=1128&view=rev Author: roman_yakovenko Date: 2007-11-07 13:24:10 -0800 (Wed, 07 Nov 2007) Log Message: ----------- adding support for GCCXML 0.9 Modified Paths: -------------- pygccxml_dev/pygccxml/parser/linker.py pygccxml_dev/pygccxml/parser/patcher.py pygccxml_dev/pygccxml/parser/scanner.py Modified: pygccxml_dev/pygccxml/parser/linker.py =================================================================== --- pygccxml_dev/pygccxml/parser/linker.py 2007-11-07 18:33:13 UTC (rev 1127) +++ pygccxml_dev/pygccxml/parser/linker.py 2007-11-07 21:24:10 UTC (rev 1128) @@ -19,6 +19,12 @@ self.__files = files self.__inst = None + self.__compiler = None + if self.__decls: + for d in self.__decls.itervalues(): + self.__compiler = d.compiler + break + def _get_inst(self): return self.__inst def _set_inst(self, inst): @@ -40,7 +46,7 @@ else: return unknown_t() - def __link_compound_type(self): + def __link_compound_type(self): self.__inst.base = self.__link_type( self.__inst.base ) def __link_members(self): @@ -229,7 +235,13 @@ self.__link_compound_type() def visit_pointer( self ): - self.__link_compound_type() + if '0.9' in self.__compiler and isinstance( self.__inst.base, member_variable_type_t ): + original_inst = self.__inst + self.__inst = self.__inst.base + self.visit_member_variable_type() + self.__inst = original_inst + else: + self.__link_compound_type() def visit_reference( self ): self.__link_compound_type() Modified: pygccxml_dev/pygccxml/parser/patcher.py =================================================================== --- pygccxml_dev/pygccxml/parser/patcher.py 2007-11-07 18:33:13 UTC (rev 1127) +++ pygccxml_dev/pygccxml/parser/patcher.py 2007-11-07 21:24:10 UTC (rev 1128) @@ -132,6 +132,8 @@ return call_invocation.join( dv[:found1[0]], args2 ) def __is_constructor_call( self, func, arg ): + #if '0.9' in func.compiler: + # return False call_invocation = declarations.call_invocation dv = arg.default_value if not call_invocation.is_call_invocation( dv ): @@ -184,4 +186,4 @@ default_arg_patcher( decl ) if isinstance( decl, declarations.casting_operator_t): _casting_oper_patcher_( decl ) - + \ No newline at end of file Modified: pygccxml_dev/pygccxml/parser/scanner.py =================================================================== --- pygccxml_dev/pygccxml/parser/scanner.py 2007-11-07 18:33:13 UTC (rev 1127) +++ pygccxml_dev/pygccxml/parser/scanner.py 2007-11-07 21:24:10 UTC (rev 1128) @@ -308,7 +308,8 @@ size = self.__guess_int_value( attrs.get(XML_AN_MAX, '' ) ) if size is None: size = array_t.SIZE_UNKNOWN - warnings.warn( 'unable to find out array size from expression "%s"' % attrs[ XML_AN_MAX ] ) + msg = 'unable to find out array size from expression "%s"' % attrs[ XML_AN_MAX ] + warnings.warn( msg ) return array_t( type_, size + 1 ) def __read_cv_qualified_type( self, attrs ): @@ -339,7 +340,10 @@ def __read_offset_type( self,attrs ): base = attrs[ XML_AN_BASE_TYPE ] type_ = attrs[ XML_AN_TYPE ] - return member_variable_type_t( class_inst=base, variable_type=type_ ) + if '0.9' in self.__compiler: + return pointer_t( member_variable_type_t( class_inst=base, variable_type=type_ ) ) + else: + return member_variable_type_t( class_inst=base, variable_type=type_ ) def __read_argument( self, attrs ): if isinstance( self.__inst, calldef_type_t ): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2007-11-12 20:19:43
|
Revision: 1144 http://pygccxml.svn.sourceforge.net/pygccxml/?rev=1144&view=rev Author: roman_yakovenko Date: 2007-11-12 12:19:48 -0800 (Mon, 12 Nov 2007) Log Message: ----------- adding restricted type Modified Paths: -------------- pygccxml_dev/pygccxml/parser/linker.py pygccxml_dev/pygccxml/parser/scanner.py Modified: pygccxml_dev/pygccxml/parser/linker.py =================================================================== --- pygccxml_dev/pygccxml/parser/linker.py 2007-11-12 20:19:25 UTC (rev 1143) +++ pygccxml_dev/pygccxml/parser/linker.py 2007-11-12 20:19:48 UTC (rev 1144) @@ -264,3 +264,7 @@ def visit_declarated( self ): if isinstance( self.__inst.declaration, types.StringTypes ): self.__inst.declaration = self.__decls[self.__inst.declaration] + + def visit_restrict( self ): + self.__link_compound_type() + Modified: pygccxml_dev/pygccxml/parser/scanner.py =================================================================== --- pygccxml_dev/pygccxml/parser/scanner.py 2007-11-12 20:19:25 UTC (rev 1143) +++ pygccxml_dev/pygccxml/parser/scanner.py 2007-11-12 20:19:48 UTC (rev 1144) @@ -318,9 +318,7 @@ elif attrs.has_key( XML_AN_VOLATILE ): return volatile_t( attrs[XML_AN_TYPE] ) elif attrs.has_key( XML_AN_RESTRICT ): - #TODO: find out what is restrict type - #and I really don't know what I should return - return volatile_t( attrs[XML_AN_TYPE] ) + return restrict_t( attrs[XML_AN_TYPE] ) else: assert 0 This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2008-02-19 22:48:40
|
Revision: 1246 http://pygccxml.svn.sourceforge.net/pygccxml/?rev=1246&view=rev Author: roman_yakovenko Date: 2008-02-19 14:48:47 -0800 (Tue, 19 Feb 2008) Log Message: ----------- updating pdb parser Modified Paths: -------------- pygccxml_dev/pygccxml/parser/pdb_reader.py Added Paths: ----------- pygccxml_dev/pygccxml/parser/msdia_details.py Added: pygccxml_dev/pygccxml/parser/msdia_details.py =================================================================== --- pygccxml_dev/pygccxml/parser/msdia_details.py (rev 0) +++ pygccxml_dev/pygccxml/parser/msdia_details.py 2008-02-19 22:48:47 UTC (rev 1246) @@ -0,0 +1,49 @@ +import getpass +import comtypes +import comtypes.client + +msdia_path = None +if 'root' == getpass.getuser(): + msdia_path = r'C:\Program Files\Microsoft Visual Studio 9.0\Common7\Packages\Debugger\msdia90.dll' + +msdia = comtypes.client.GetModule( msdia_path ) + +class UdtKind: + UdtStruct, UdtClass, UdtUnion = ( 0, 1, 2 ) + +msdia.UdtKind = UdtKind + +class NameSearchOptions: + nsNone = 0 + nsfCaseSensitive = 0x1 + nsfCaseInsensitive = 0x2 + nsfFNameExt = 0x4 + nsfRegularExpression = 0x8 + nsfUndecoratedName = 0x10 + + # For backward compabibility: + nsCaseSensitive = nsfCaseSensitive + nsCaseInsensitive = nsfCaseInsensitive + nsFNameExt = nsfFNameExt + nsRegularExpression = nsfRegularExpression | nsfCaseSensitive + nsCaseInRegularExpression = nsfRegularExpression | nsfCaseInsensitive + +msdia.NameSearchOptions = NameSearchOptions + + +# +#from distutils import ccompiler +#from distutils import msvccompiler +# +#if 'msvc' == ccompiler.get_default_compiler(): +# cc = msvccompiler.MSVCCompiler() +# cc.initialize() +# generator = 'NMake Makefiles' +# native_build = '"%s" /A all' % cc.find_exe( 'nmake.exe' ) +# configure_environment_script = cc.find_exe( 'vsvars32.bat' ) +# if not configure_environment_script: +# configure_environment_script = cc.find_exe( 'vcvars32.bat' ) +# cl_mapping = { 6.0 : "msvc6", 7.0 : "msvc7", 7.1 : "msvc71", 8.0 : "msvc8" } +# compiler = cl_mapping[ msvccompiler.get_build_version() ] +#else: +# raise RuntimeError( "Unable to find out MSDIA dll location") Modified: pygccxml_dev/pygccxml/parser/pdb_reader.py =================================================================== --- pygccxml_dev/pygccxml/parser/pdb_reader.py 2008-02-19 22:48:10 UTC (rev 1245) +++ pygccxml_dev/pygccxml/parser/pdb_reader.py 2008-02-19 22:48:47 UTC (rev 1246) @@ -3,26 +3,15 @@ import ctypes import comtypes import comtypes.client -from sets import Set as set +from msdia_details import msdia -msdia_dll = r'C:\Program Files\Microsoft Visual Studio .NET 2003\Visual Studio SDKs\DIA SDK\bin\msdia71.dll' -msdia_dll = r'D:\Program Files\Microsoft Visual Studio .NET 2003\Visual Studio SDKs\DIA SDK\bin\msdia71.dll' +sys.path.append( r'C:\dev\language-binding\pygccxml_dev' ) -msdia_dll = 'msdia80.dll' +from pygccxml import utils +from pygccxml import declarations -msdia = comtypes.client.GetModule( msdia_dll ) -control_pdb = r'C:\dev\produce_pdb\Debug\produce_pdb.pdb' -control_pdb = r'xxx.pdb' -ds = comtypes.client.CreateObject( msdia.DiaSource ) -ds.loadDataFromPdb(control_pdb) -session = ds.openSession() - -root_symbol = session.globalScope - -print root_symbol - SymTagEnum = 12 def AsDiaSymbol( x ): @@ -31,23 +20,17 @@ def print_enums( smb ): enums = smb.findChildren( SymTagEnum, None, 0 ) for enum in iter( enums ): - enum = AsDiaSymbol( enum ) - if 'shared_consts' not in enum.name: - continue + enum = AsDiaSymbol( enum ) print 'name: ', enum.name if enum.container: print 'container: ', enum.container.name - if enum.classParent: + if enum.classParent: print 'parent: ', enum.classParent.name if enum.lexicalParent: print 'lexical parent: ', enum.lexicalParent.Name - #~ print 'enum: ', enum.symIndexId - #~ f = session.findFile( internal_smb, internal_smb.name, 0 ) - #~ print 'name: ', internal_smb.name - #~ print f - - values = enum.findChildren( msdia.SymTagData, None, 0 ) - for v in iter(values): + + values = enum.findChildren( msdia.SymTagData, None, 0 ) + for v in iter(values): v = AsDiaSymbol(v) if v.classParent.symIndexId != enum.symIndexId: continue @@ -68,4 +51,95 @@ print 'File: ', f.fileName #~ print_files( session ) -print_enums( root_symbol ) +#print_enums( root_symbol ) + +class pdb_reader_t(object): + def __init__(self, pdb_file_path ): + self.logger = utils.loggers.gccxml + self.logger.debug( 'creating DiaSource object' ) + self.__dia_source = comtypes.client.CreateObject( msdia.DiaSource ) + self.logger.debug( 'loading pdb file: %s' % pdb_file_path ) + self.__dia_source.loadDataFromPdb(pdb_file_path) + self.logger.debug( 'opening session' ) + self.__dia_session = self.__dia_source.openSession() + self.__global_ns = declarations.namespace_t( '::' ) + + def read(self): + self.__populate_scopes() + + @property + def dia_global_scope(self): + return self.__dia_session.globalScope + + @property + def global_ns(self): + return self.__global_ns + + def __split_scope_identifiers( self, name ): + result = [] + tmp = name.split( '::' ) + tmp.reverse() + while tmp: + token = tmp.pop() + less_count = token.count( '<' ) + greater_count = token.count( '>' ) + if less_count != greater_count: + while less_count != greater_count: + next_token = tmp.pop() + token = token + '::' + next_token + less_count += next_token.count( '<' ) + greater_count += next_token.count( '>' ) + result.append( token ) + return result + + def __is_udt( self, name ): + self.logger.debug( 'testing whether name( "%s" ) is UDT symbol' % name ) + flags = msdia.NameSearchOptions.nsfCaseSensitive + found = self.dia_global_scope.findChildren( msdia.SymTagUDT, name, flags ) + if found.Count: + self.logger.debug( 'name( "%s" ) is UDT symbol' % name ) + else: + self.logger.debug( 'name( "%s" ) is **NOT** UDT symbol' % name ) + return found.Count + + def __populate_scopes(self): + classes = [] + dia_classes = self.dia_global_scope.findChildren( msdia.SymTagUDT, None, 0 ) + for dia_class in iter( dia_classes ): + dia_class = AsDiaSymbol( dia_class ) + if '$' in dia_class.name: + continue + klass = declarations.class_t(dia_class.name) + if msdia.UdtKind.UdtStruct == dia_class.udtKind: + klass.class_type = declarations.CLASS_TYPES.STRUCT + elif msdia.UdtKind.UdtClass == dia_class.udtKind: + klass.class_type = declarations.CLASS_TYPES.CLASS + else: + klass.class_type = declarations.CLASS_TYPES.UNION + scope_identifiers = self.__split_scope_identifiers( dia_class.name ) + if 1 == len(scope_identifiers): + classes.append( klass ) + #self.global_ns.adopt_declaration( klass ) + else: + ns_ref = self.global_ns + for i in range( len(scope_identifiers) - 1): + full_identifier = '::'.join( scope_identifiers[0:i+1] ) + if not self.__is_udt( full_identifier ): + #we have namespace + try: + ns_ref = ns_ref.namespace( scope_identifiers[i], recursive=False) + except ns_ref.declaration_not_found_t: + new_ns = declarations.namespace_t( scope_identifiers[i] ) + ns_ref.adopt_declaration( new_ns ) + ns_ref = new_ns + else: + classes.append( klass ) + classes.sort( lambda klass1, klass2: cmp( klass1.name, klass2.name ) ) + for i in classes: + print str(i) + declarations.print_declarations( self.global_ns ) + +if __name__ == '__main__': + control_pdb = r'C:\dev\produce_pdb\Debug\produce_pdb.pdb' + reader = pdb_reader_t( control_pdb ) + reader.read() \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2008-02-20 12:57:43
|
Revision: 1249 http://pygccxml.svn.sourceforge.net/pygccxml/?rev=1249&view=rev Author: roman_yakovenko Date: 2008-02-20 04:57:47 -0800 (Wed, 20 Feb 2008) Log Message: ----------- auto detect of msdiaxx.dll location Modified Paths: -------------- pygccxml_dev/pygccxml/parser/msdia_details.py pygccxml_dev/pygccxml/parser/pdb_reader.py Modified: pygccxml_dev/pygccxml/parser/msdia_details.py =================================================================== --- pygccxml_dev/pygccxml/parser/msdia_details.py 2008-02-20 08:03:33 UTC (rev 1248) +++ pygccxml_dev/pygccxml/parser/msdia_details.py 2008-02-20 12:57:47 UTC (rev 1249) @@ -1,13 +1,73 @@ -import getpass +import os import comtypes import comtypes.client +import _winreg as win_registry +from distutils import msvccompiler -msdia_path = None -if 'root' == getpass.getuser(): - msdia_path = r'C:\Program Files\Microsoft Visual Studio 9.0\Common7\Packages\Debugger\msdia90.dll' +class msdia_searcher_t: + def __init__( self ): + self.root_reg_key = win_registry.HKEY_LOCAL_MACHINE + + def find_path( self ): + vss_installed = self.__get_installed_vs_dirs() + msdia_dlls = self.__get_msdia_dll_paths( vss_installed ) + #D:\Program Files\Microsoft Visual Studio .NET 2003\Common7\IDE\ + #D:\Program Files\Microsoft Visual Studio .NET 2003\Common7\Packages\Debugger\msdia71.dll + #C:\Program Files\Microsoft Visual Studio 9.0\Common7\Packages\Debugger\msdia90.dll + if 1 == len(msdia_dlls): + return msdia_dlls[0] + else: + #TODO find the highest version and use it. + pass + + def __get_msdia_dll_paths( self, vss_installed ): + msdia_dlls = [] + for vs in vss_installed: + vs = os.path.split( vs )[0] + debug_dir = os.path.join( vs, 'Packages', 'Debugger' ) + files = filter( lambda f: f.startswith( 'msdia' ) and f.endswith( '.dll' ) + , os.listdir( debug_dir ) ) + if not files: + continue + msdia_dlls.extend([ os.path.join( debug_dir, f ) for f in files ]) + if not msdia_dlls: + raise RuntimeError( 'pygccxml unable to find out msdiaXX.dll location' ) + return msdia_dlls + + def __get_installed_vs_dirs( self ): + vs_reg_path = 'Software\Microsoft\VisualStudio' + vss = self.read_keys( self.root_reg_key, vs_reg_path ) + vs_installed_and_exist = [] + + for vs_installed in vss: + values = self.read_values( self.root_reg_key, vs_reg_path + '\\' + vs_installed ) + try: + vs_installed_and_exist.append( os.path.realpath( values['installdir'] ) ) + except KeyError: + pass + + if not vs_installed_and_exist: + raise RuntimeError( 'pygccxml unable to find out a Visual Studio installation directory' ) + return vs_installed_and_exist -msdia = comtypes.client.GetModule( msdia_path ) + + def read_keys(self, base, key): + return msvccompiler.read_keys(base, key) + def read_values(self, base, key): + return msvccompiler.read_values(base, key) + +msdia_path = msdia_searcher_t().find_path() + +comtypes_client_gen_dir = comtypes.client.gen_dir +try: + comtypes.client.gen_dir = None + msdia = comtypes.client.GetModule( msdia_path ) +finally: + comtypes.client.gen_dir = comtypes_client_gen_dir + +#Adding code, that was not generated for some reason. + class UdtKind: UdtStruct, UdtClass, UdtUnion = ( 0, 1, 2 ) @@ -29,21 +89,3 @@ nsCaseInRegularExpression = nsfRegularExpression | nsfCaseInsensitive msdia.NameSearchOptions = NameSearchOptions - - -# -#from distutils import ccompiler -#from distutils import msvccompiler -# -#if 'msvc' == ccompiler.get_default_compiler(): -# cc = msvccompiler.MSVCCompiler() -# cc.initialize() -# generator = 'NMake Makefiles' -# native_build = '"%s" /A all' % cc.find_exe( 'nmake.exe' ) -# configure_environment_script = cc.find_exe( 'vsvars32.bat' ) -# if not configure_environment_script: -# configure_environment_script = cc.find_exe( 'vcvars32.bat' ) -# cl_mapping = { 6.0 : "msvc6", 7.0 : "msvc7", 7.1 : "msvc71", 8.0 : "msvc8" } -# compiler = cl_mapping[ msvccompiler.get_build_version() ] -#else: -# raise RuntimeError( "Unable to find out MSDIA dll location") Modified: pygccxml_dev/pygccxml/parser/pdb_reader.py =================================================================== --- pygccxml_dev/pygccxml/parser/pdb_reader.py 2008-02-20 08:03:33 UTC (rev 1248) +++ pygccxml_dev/pygccxml/parser/pdb_reader.py 2008-02-20 12:57:47 UTC (rev 1249) @@ -5,7 +5,8 @@ import comtypes.client from msdia_details import msdia -sys.path.append( r'C:\dev\language-binding\pygccxml_dev' ) +sys.path.append( r'../..' ) +#sys.path.append( r'C:\dev\language-binding\pygccxml_dev' ) from pygccxml import utils from pygccxml import declarations @@ -36,14 +37,6 @@ continue print ' value %s(%d): ' % ( v.name, v.value ) -def print_nss( smb, offset ): - symbols = smb.findChildren( msdia.SymTagUDT, None, 0 ) - for internal_smb in iter( symbols ): - internal_smb = ctypes.cast( internal_smb, ctypes.POINTER( msdia.IDiaSymbol ) ) - if internal_smb.classParentId == smb.symIndexId: - print ' ' * offset, internal_smb.name - print_nss( internal_smb, offset + 1 ) - def print_files( session ): files = iter( session.findFile( None, '', 0 ) ) for f in files: @@ -67,6 +60,11 @@ def read(self): self.__populate_scopes() + files = iter( self.__dia_session.findFile( None, '', 0 ) ) + for f in files: + f = ctypes.cast( f, ctypes.POINTER(msdia.IDiaSourceFile) ) + print 'File: ', f.fileName + @property def dia_global_scope(self): return self.__dia_session.globalScope @@ -141,5 +139,6 @@ if __name__ == '__main__': control_pdb = r'C:\dev\produce_pdb\Debug\produce_pdb.pdb' + control_pdb = r'xxx.pdb' reader = pdb_reader_t( control_pdb ) - reader.read() \ No newline at end of file + reader.read() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |