[pygccxml-commit] SF.net SVN: pygccxml:[1538] pygccxml_dev
Brought to you by:
mbaas,
roman_yakovenko
|
From: <rom...@us...> - 2009-01-06 08:38:34
|
Revision: 1538
http://pygccxml.svn.sourceforge.net/pygccxml/?rev=1538&view=rev
Author: roman_yakovenko
Date: 2009-01-06 08:38:32 +0000 (Tue, 06 Jan 2009)
Log Message:
-----------
small refactoring, which allows to merge information from binary files to the declarations tree
Modified Paths:
--------------
pygccxml_dev/pygccxml/binary_parsers/__init__.py
pygccxml_dev/pygccxml/declarations/decl_printer.py
pygccxml_dev/pygccxml/declarations/declaration.py
pygccxml_dev/unittests/data/core_cache.hpp
pygccxml_dev/unittests/undname_creator_tester.py
Added Paths:
-----------
pygccxml_dev/pygccxml/binary_parsers/parsers.py
pygccxml_dev/pygccxml/binary_parsers/undname.py
Removed Paths:
-------------
pygccxml_dev/pygccxml/binary_parsers/common_utils.py
Modified: pygccxml_dev/pygccxml/binary_parsers/__init__.py
===================================================================
--- pygccxml_dev/pygccxml/binary_parsers/__init__.py 2009-01-05 22:58:43 UTC (rev 1537)
+++ pygccxml_dev/pygccxml/binary_parsers/__init__.py 2009-01-06 08:38:32 UTC (rev 1538)
@@ -3,7 +3,9 @@
# accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
-from common_utils import undecorate_blob
-from common_utils import undecorate_decl
-from common_utils import exported_symbols
-from common_utils import UNDECORATE_NAME_OPTIONS
+import sys
+import undname
+from parsers import merge_information
+
+def undecorate_blob( blob ):
+ return undname.undname_creator_t().undecorate_blob( blob )
Deleted: pygccxml_dev/pygccxml/binary_parsers/common_utils.py
===================================================================
--- pygccxml_dev/pygccxml/binary_parsers/common_utils.py 2009-01-05 22:58:43 UTC (rev 1537)
+++ pygccxml_dev/pygccxml/binary_parsers/common_utils.py 2009-01-06 08:38:32 UTC (rev 1538)
@@ -1,285 +0,0 @@
-# Copyright 2004-2008 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 re
-import sys
-import ctypes
-from .. import declarations
-
-class UNDECORATE_NAME_OPTIONS:
- UNDNAME_COMPLETE = 0x0000 #Enables full undecoration.
- UNDNAME_NO_LEADING_UNDERSCORES = 0x0001 #Removes leading underscores from Microsoft extended keywords.
- UNDNAME_NO_MS_KEYWORDS = 0x0002 #Disables expansion of Microsoft extended keywords.
- UNDNAME_NO_FUNCTION_RETURNS = 0x0004 #Disables expansion of return type for primary declaration.
- UNDNAME_NO_ALLOCATION_MODEL = 0x0008 #Disables expansion of the declaration model.
- UNDNAME_NO_ALLOCATION_LANGUAGE = 0x0010 #Disables expansion of the declaration language specifier.
- UNDNAME_RESERVED1 = 0x0020 #RESERVED.
- UNDNAME_RESERVED2 = 0x0040 #RESERVED.
- UNDNAME_NO_THISTYPE = 0x0060 #Disables all modifiers on the this type.
- UNDNAME_NO_ACCESS_SPECIFIERS = 0x0080 #Disables expansion of access specifiers for members.
- UNDNAME_NO_THROW_SIGNATURES = 0x0100 #Disables expansion of "throw-signatures" for functions and pointers to functions.
- UNDNAME_NO_MEMBER_TYPE = 0x0200 #Disables expansion of static or virtual members.
- UNDNAME_NO_RETURN_UDT_MODEL = 0x0400 #Disables expansion of the Microsoft model for UDT returns.
- UNDNAME_32_BIT_DECODE = 0x0800 #Undecorates 32-bit decorated names.
- UNDNAME_NAME_ONLY = 0x1000 #Gets only the name for primary declaration; returns just [scope::]name. Expands template params.
- UNDNAME_TYPE_ONLY = 0x2000 #Input is just a type encoding; composes an abstract declarator.
- UNDNAME_HAVE_PARAMETERS = 0x4000 #The real template parameters are available.
- UNDNAME_NO_ECSU = 0x8000 #Suppresses enum/class/struct/union.
- UNDNAME_NO_IDENT_CHAR_CHECK = 0x10000 #Suppresses check for valid identifier characters.
- UNDNAME_NO_PTR64 = 0x20000 #Does not include ptr64 in output.
-
- UNDNAME_SCOPES_ONLY = UNDNAME_NO_LEADING_UNDERSCORES \
- | UNDNAME_NO_MS_KEYWORDS \
- | UNDNAME_NO_FUNCTION_RETURNS \
- | UNDNAME_NO_ALLOCATION_MODEL \
- | UNDNAME_NO_ALLOCATION_LANGUAGE \
- | UNDNAME_NO_ACCESS_SPECIFIERS \
- | UNDNAME_NO_THROW_SIGNATURES \
- | UNDNAME_NO_MEMBER_TYPE \
- | UNDNAME_NO_ECSU \
- | UNDNAME_NO_IDENT_CHAR_CHECK
-
- SHORT_UNIQUE_NAME = UNDNAME_NO_MS_KEYWORDS | UNDNAME_NO_ACCESS_SPECIFIERS | UNDNAME_NO_ECSU
-
-#~ The following code doesn't work - access violation
-
-#~__unDName definition was taken from:
-#~http://www.tech-archive.net/Archive/VC/microsoft.public.vc.language/2006-02/msg00754.html
-
-#~ msvcrxx = ctypes.windll.msvcr90
-#~ free_type = ctypes.CFUNCTYPE( None, ctypes.c_void_p ) #free type
-#~ malloc_type = ctypes.CFUNCTYPE( ctypes.c_void_p, ctypes.c_uint ) #malloc type
-#~ __unDName = msvcrxx.__unDName
-#~ __unDName.argtypes = [ ctypes.c_char_p #undecorated name
- #~ , ctypes.c_char_p #decorated name
- #~ , ctypes.c_int #sizeof undecorated name
- #~ , malloc_type
- #~ , free_type
- #~ , ctypes.c_ushort #flags
- #~ ]
-#~ __unDName.restype = ctypes.c_char_p
-#~ def undecorate_name( name, options=None ):
- #~ if not name:
- #~ return ''
- #~ if options is None:
- #~ options = UNDECORATE_NAME_OPTIONS.SHORT_UNIQUE_NAME
- #~ buffer_size = 1024 * 32
- #~ undecorated_name = ctypes.create_string_buffer('\0' * buffer_size) #should be enouph for any symbol
- #~ __unDName( undecorated_name
- #~ , str(name)
- #~ , buffer_size
- #~ , malloc_type( msvcrxx.malloc )
- #~ , free_type( msvcrxx.free )
- #~ , options )
- #~ return undecorated_name.value
-
-class undname_creator:
- def __init__( self ):
- import ctypes.wintypes
- self.__undname = ctypes.windll.dbghelp.UnDecorateSymbolName
- self.__undname.argtypes = [ctypes.c_char_p, ctypes.c_char_p, ctypes.c_uint, ctypes.c_uint]
- self.__clean_ecsu = re.compile( r'(?:(^|\W))(?:(class|enum|struct|union))' )
- self.__fundamental_types = (
- ( 'short unsigned int', 'unsigned short')
- , ( 'short int', 'short' )
- , ( 'long int', 'long' )
- , ( 'long unsigned int', 'unsigned long' )
- )
- self.__calling_conventions = re.compile( r'(?:(^|\s))(?:__(cdecl|clrcall|stdcall|fastcall|thiscall)\s)' )
-
- def normalize_undecorated( self, undname, options=None ):
- if options is None:
- options = UNDECORATE_NAME_OPTIONS.SHORT_UNIQUE_NAME
- if UNDECORATE_NAME_OPTIONS.UNDNAME_NO_ECSU & options:
- undname = self.__clean_ecsu.sub( '', undname )
- if UNDECORATE_NAME_OPTIONS.UNDNAME_NO_ACCESS_SPECIFIERS & options:
- for prefix in ( 'public: ', 'private: ', 'protected: ' ):
- if undname.startswith( prefix ):
- undname = undname[ len(prefix): ]
- break
- if UNDECORATE_NAME_OPTIONS.UNDNAME_NO_MS_KEYWORDS & options:
- undname = self.__calling_conventions.sub( ' ', undname)
- return undname.strip()
-
- def undecorate_blob( self, name, options=None ):
- if options is None:
- options = UNDECORATE_NAME_OPTIONS.SHORT_UNIQUE_NAME
- buffer = ctypes.create_string_buffer(1024*16)
- res = self.__undname( str(name), buffer, ctypes.sizeof(buffer), options)
- if res:
- return self.normalize_undecorated( str(buffer[:res]) )
- else:
- return name
-
- def __remove_leading_scope( self, s ):
- if s and s.startswith( '::' ):
- return s[2:]
- else:
- return s
-
- def __format_type_as_undecorated( self, type_, is_argument ):
- result = []
- type_ = declarations.remove_alias( type_ )
- if declarations.is_array( type_ ):
- result.append( declarations.array_item_type( type_ ).decl_string )
- result.append( '*' )
- if is_argument:
- result.append( 'const' )
- else:
- result.append( self.__remove_leading_scope( type_.decl_string ) )
- return ' '.join( result )
-
- def __normalize( self, name ):
- for what, with_ in self.__fundamental_types:
- name = name.replace( what, with_ )
- name = name.replace( ', ', ',' )
- return name
-
- def undecorate_argtypes( self, argtypes ):
- if not argtypes:
- return 'void'
- else:
- formater = lambda type_: self.__format_type_as_undecorated( type_, True )
- return ','.join( map( formater, argtypes ) )
-
- def __undecorated_calldef( self, calldef ):
- calldef_type = calldef.function_type()
-
- result = []
- is_mem_fun = isinstance( calldef, declarations.member_calldef_t )
- if is_mem_fun and calldef.virtuality != declarations.VIRTUALITY_TYPES.NOT_VIRTUAL:
- result.append( 'virtual ' )
- if is_mem_fun and calldef.has_static:
- result.append( 'static ' )
- if calldef_type.return_type:
- result.append( self.__format_type_as_undecorated( calldef.return_type, False ) )
- result.append( ' ' )
- if is_mem_fun:
- result.append( self.__remove_leading_scope( calldef.parent.decl_string ) + '::')
-
- result.append( calldef.name )
- if isinstance( calldef, ( declarations.constructor_t, declarations.destructor_t) ) \
- and declarations.templates.is_instantiation( calldef.parent.name ):
- result.append( '<%s>' % ','.join( declarations.templates.args( calldef.parent.name ) ) )
-
- result.append( '(%s)' % self.undecorate_argtypes( calldef_type.arguments_types ) )
- if is_mem_fun and calldef.has_const:
- result.append( 'const' )
- return ''.join( result )
-
- def __undecorated_variable( self, decl ):
- result = []
- is_mem_var = isinstance( decl.parent, declarations.class_t )
- if is_mem_var and decl.type_qualifiers.has_static:
- result.append( 'static ' )
- result.append( self.__format_type_as_undecorated( decl.type, False ) )
- result.append( ' ' )
- if is_mem_var:
- result.append( self.__remove_leading_scope( decl.parent.decl_string ) + '::' )
- result.append( decl.name )
- return ''.join( result )
-
- def undecorated_decl(self, decl):
- """returns string, which contains full function name formatted exactly as
- result of dbghelp.UnDecorateSymbolName, with UNDNAME_NO_MS_KEYWORDS | UNDNAME_NO_ACCESS_SPECIFIERS | UNDNAME_NO_ECSU
- options.
- """
- name = None
- if isinstance( decl, declarations.calldef_t ):
- name = self.__undecorated_calldef( decl )
- elif isinstance( decl, declarations.variable_t ):
- name = self.__undecorated_variable( decl )
- else:
- raise NotImplementedError()
- return self.__normalize( name )
-
-if 'win' in sys.platform:
- undecorate_blob = undname_creator().undecorate_blob
- undecorate_decl = undname_creator().undecorated_decl
- undecorate_argtypes = undname_creator().undecorate_argtypes
- normalize_undecorated = undname_creator().normalize_undecorated
-else:
- def undecorate_blob( x ):
- raise NotImplementedError()
- def undecorate_decl( x ):
- raise NotImplementedError()
- def undecorate_argtypes( x ):
- raise NotImplementedError()
- def normalize_undecorated( *args ):
- raise NotImplementedError()
-
-import exceptions
-class LicenseWarning( exceptions.UserWarning ):
- def __init__( self, *args, **keywd ):
- exceptions.UserWarning.__init__( self, *args, **keywd )
-
-class exported_symbols:
- map_file_re_c = re.compile( r' +\d+ (?P<internall>.+?)(?:\s+exported name\:\s(?P<name>.*)$)')
- map_file_re_cpp = re.compile( r' +\d+ (?P<decorated>.+?) \((?P<undecorated>.+)\)$' )
-
- @staticmethod
- def load_from_map_file( fname ):
- """returns dictionary { decorated symbol : orignal declaration name }"""
- result = {}
- f = open( fname )
- lines = []
- was_exports = False
- for line in f:
- if was_exports:
- lines.append( line )
- elif 'Exports' == line.strip():
- was_exports = True
- else:
- pass
- index = 0
-
- while index < len( lines ):
- line = lines[index].rstrip()
- found = exported_symbols.map_file_re_cpp.match( line )
- if found:
- result[ found.group( 'decorated' ) ] = normalize_undecorated( found.group( 'undecorated' ) )
- elif index + 1 < len( lines ):
- two_lines = line + lines[index+1].rstrip()
- found = exported_symbols.map_file_re_c.match( two_lines )
- if found:
- result[ found.group( 'name' ) ] = found.group( 'name' )
- index += 1
- else:
- pass
- index += 1
- return result
-
- @staticmethod
- def load_from_dll_file( fname ):
- import warnings
- warnings.warn( '\n'*2 + '-' * 30 + '>>LICENSE WARNING<<' + '-'*30
- + '\n"load_from_dll_file" functionality uses code licensed under MIT license.'
- + '\npygccxml project uses Boost Software License, Version 1.0. '
- + '\nFor more information about this functionality take a look on get_dll_exported_symbols.py file.'
- + '\n' + '='*79
- + '\n' * 2
- , LicenseWarning )
- import get_dll_exported_symbols
- result = {}
- blobs = get_dll_exported_symbols.read_export_table( fname )
- for blob in blobs:
- result[ blob ] = undecorate_blob( blob )
- return result
-
- @staticmethod
- def load_from_file( fname ):
- ext = os.path.splitext( fname )[1]
- if '.dll' == ext:
- return exported_symbols.load_from_dll_file( fname )
- elif '.map' == ext:
- return exported_symbols.load_from_map_file( fname )
- else:
- raise RuntimeError( "Don't know how to read exported symbols from file '%s'"
- % fname )
-
- @staticmethod
- def is_c_function( decl, blob ):
- return decl.name == blob
Copied: pygccxml_dev/pygccxml/binary_parsers/parsers.py (from rev 1537, pygccxml_dev/pygccxml/binary_parsers/common_utils.py)
===================================================================
--- pygccxml_dev/pygccxml/binary_parsers/parsers.py (rev 0)
+++ pygccxml_dev/pygccxml/binary_parsers/parsers.py 2009-01-06 08:38:32 UTC (rev 1538)
@@ -0,0 +1,193 @@
+# Copyright 2004-2008 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 re
+import sys
+import ctypes
+import undname
+import warnings
+import exceptions
+from .. import declarations
+
+class LicenseWarning( exceptions.UserWarning ):
+ def __init__( self, *args, **keywd ):
+ exceptions.UserWarning.__init__( self, *args, **keywd )
+
+
+dll_file_parser_warning = \
+"""
+
+----------------------------->> LICENSE WARNING <<-----------------------------
+"dll_file_parser_t" functionality uses code licensed under MIT license.
+pygccxml project uses Boost Software License, Version 1.0.
+For more information about this functionality take a look on
+get_dll_exported_symbols.py file.
+================================================================================
+
+
+"""
+
+class libparser_t( object ):
+ def __init__( self, global_ns, binary_file ):
+ self.__global_ns = global_ns
+ self.__binary_file = binary_file
+ self.__loaded_symbols = None
+
+ @property
+ def global_ns( self ):
+ """reference to global namespace"""
+ return self.__global_ns
+
+ @property
+ def binary_file( self ):
+ """binary file path"""
+ return self.__binary_file
+
+ @property
+ def loaded_symbols( self ):
+ """list of symbols, which were loaded from the binary file"""
+ return self.__loaded_symbols
+
+ def load_symbols( self ):
+ raise NotImplementedError()
+
+ def merge( self ):
+ raise NotImplementedError()
+
+ def parse( self ):
+ self.__loaded_symbols = self.load_symbols()
+ result = {}
+ for smbl in self.__loaded_symbols:
+ decorated, decl = self.merge( smbl )
+ if decl:
+ decl.decorated_name = decorated
+ result[ decorated ] = decl
+ return result
+
+CCTS = declarations.CALLING_CONVENTION_TYPES
+
+
+CCTS = declarations.CALLING_CONVENTION_TYPES
+
+class msvc_libparser_t( libparser_t ):
+ def __init__( self, global_ns, binary_file ):
+ libparser_t.__init__( self, global_ns, binary_file )
+ self.__formated_decls = {}
+ self.undname_creator = undname.undname_creator_t()
+
+ for f in self.global_ns.calldefs( allow_empty=True, recursive=True ):
+ self.__formated_decls[ self.undname_creator.undecorated_decl( f ) ] = f
+
+ for v in self.global_ns.variables( allow_empty=True, recursive=True ):
+ self.__formated_decls[ self.undname_creator.undecorated_decl( v ) ] = v
+
+ @property
+ def formated_decls( self ):
+ return self.__formated_decls
+
+class map_file_parser_t( msvc_libparser_t ):
+ c_entry = re.compile( r' +\d+ (?P<internall>.+?)(?:\s+exported name\:\s(?P<name>.*)$)')
+ cpp_entry = re.compile( r' +\d+ (?P<decorated>.+?) \((?P<undecorated>.+)\)$' )
+
+ def __init__( self, global_ns, map_file_path ):
+ msvc_libparser_t.__init__( self, global_ns, map_file_path )
+
+ def load_symbols( self ):
+ """returns dictionary { decorated symbol : orignal declaration name }"""
+ f = file( self.binary_file )
+ lines = []
+ was_exports = False
+ for line in f:
+ if was_exports:
+ lines.append( line )
+ elif 'Exports' == line.strip():
+ was_exports = True
+ else:
+ pass
+
+ index = 0
+ result = []
+ while index < len( lines ):
+ line = lines[index].rstrip()
+ found = self.cpp_entry.match( line )
+ if found:
+ result.append( ( found.group( 'decorated' ), found.group( 'undecorated' ) ) )
+ elif index + 1 < len( lines ):
+ two_lines = line + lines[index+1].rstrip()
+ found = self.c_entry.match( two_lines )
+ if found:
+ result.append( ( found.group( 'name' ), found.group( 'name' ) ) )
+ index += 1
+ else:
+ pass
+ index += 1
+ return result
+
+ def merge( self, smbl ):
+ decorated, undecorated = smbl
+ if decorated == undecorated:
+ #we deal with C function ( or may be we deal with variable?, I have to check the latest
+ f = self.global_ns.free_fun( decorated )
+ #TODO create usecase, where C function uses different calling convention
+ f.calling_convention = CCTS.CDECL
+ return decorated, f
+ else:
+ undecorated_normalized = self.undname_creator.normalize_undecorated( undecorated )
+ if undecorated_normalized not in self.formated_decls:
+ return None, None
+ decl = self.formated_decls[ undecorated_normalized ]
+ if isinstance( decl, declarations.calldef_t ):
+ decl.calling_convention = CCTS.extract( undecorated, CCTS.CDECL )
+ return decorated, decl
+
+
+class dll_file_parser_t( msvc_libparser_t ):
+ def __init__( self, global_ns, map_file_path ):
+ global dll_file_parser_warning
+ warnings.warn( dll_file_parser_warning, LicenseWarning )
+ msvc_libparser_t.__init__( self, global_ns, map_file_path )
+
+ def load_symbols( self ):
+ import get_dll_exported_symbols
+ return get_dll_exported_symbols.read_export_table( self.binary_file )
+
+ def merge( self, smbl ):
+ blob = smbl
+ blob_undecorated = self.undname_creator.undecorate_blob( blob, undname.UNDECORATE_NAME_OPTIONS.UNDNAME_COMPLETE )
+ blob_undecorated_normalized = self.undname_creator.undecorate_blob( blob )
+ if blob == blob_undecorated == blob_undecorated_normalized:
+ #we deal with C function ( or may be we deal with variable?, I have to check the latest
+ f = self.global_ns.free_fun( blob )
+ #TODO create usecase, where C function uses different calling convention
+ f.calling_convention = CCTS.CDECL
+ return blob, f
+ else:
+ if blob_undecorated_normalized not in self.formated_decls:
+ return None, None
+ decl = self.formated_decls[ blob_undecorated_normalized ]
+ if isinstance( decl, declarations.calldef_t ):
+ decl.calling_convention = CCTS.extract( blob_undecorated, CCTS.CDECL )
+ return blob, decl
+
+
+def merge_information( global_ns, fname, runs_under_unittest=False ):
+ ext = os.path.splitext( fname )[1]
+ parser = None
+ if '.dll' == ext:
+ parser = dll_file_parser_t( global_ns, fname )
+ elif '.map' == ext:
+ parser = map_file_parser_t( global_ns, fname )
+ else:
+ raise RuntimeError( "Don't know how to read exported symbols from file '%s'"
+ % fname )
+ symbols = parser.parse()
+ if runs_under_unittest:
+ return symbols, parser
+ else:
+ return symbols
+
+
+
Added: pygccxml_dev/pygccxml/binary_parsers/undname.py
===================================================================
--- pygccxml_dev/pygccxml/binary_parsers/undname.py (rev 0)
+++ pygccxml_dev/pygccxml/binary_parsers/undname.py 2009-01-06 08:38:32 UTC (rev 1538)
@@ -0,0 +1,201 @@
+# Copyright 2004-2008 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 re
+import sys
+import ctypes
+from pygccxml import declarations
+
+class UNDECORATE_NAME_OPTIONS:
+ UNDNAME_COMPLETE = 0x0000 #Enables full undecoration.
+ UNDNAME_NO_LEADING_UNDERSCORES = 0x0001 #Removes leading underscores from Microsoft extended keywords.
+ UNDNAME_NO_MS_KEYWORDS = 0x0002 #Disables expansion of Microsoft extended keywords.
+ UNDNAME_NO_FUNCTION_RETURNS = 0x0004 #Disables expansion of return type for primary declaration.
+ UNDNAME_NO_ALLOCATION_MODEL = 0x0008 #Disables expansion of the declaration model.
+ UNDNAME_NO_ALLOCATION_LANGUAGE = 0x0010 #Disables expansion of the declaration language specifier.
+ UNDNAME_RESERVED1 = 0x0020 #RESERVED.
+ UNDNAME_RESERVED2 = 0x0040 #RESERVED.
+ UNDNAME_NO_THISTYPE = 0x0060 #Disables all modifiers on the this type.
+ UNDNAME_NO_ACCESS_SPECIFIERS = 0x0080 #Disables expansion of access specifiers for members.
+ UNDNAME_NO_THROW_SIGNATURES = 0x0100 #Disables expansion of "throw-signatures" for functions and pointers to functions.
+ UNDNAME_NO_MEMBER_TYPE = 0x0200 #Disables expansion of static or virtual members.
+ UNDNAME_NO_RETURN_UDT_MODEL = 0x0400 #Disables expansion of the Microsoft model for UDT returns.
+ UNDNAME_32_BIT_DECODE = 0x0800 #Undecorates 32-bit decorated names.
+ UNDNAME_NAME_ONLY = 0x1000 #Gets only the name for primary declaration; returns just [scope::]name. Expands template params.
+ UNDNAME_TYPE_ONLY = 0x2000 #Input is just a type encoding; composes an abstract declarator.
+ UNDNAME_HAVE_PARAMETERS = 0x4000 #The real template parameters are available.
+ UNDNAME_NO_ECSU = 0x8000 #Suppresses enum/class/struct/union.
+ UNDNAME_NO_IDENT_CHAR_CHECK = 0x10000 #Suppresses check for valid identifier characters.
+ UNDNAME_NO_PTR64 = 0x20000 #Does not include ptr64 in output.
+
+ UNDNAME_SCOPES_ONLY = UNDNAME_NO_LEADING_UNDERSCORES \
+ | UNDNAME_NO_MS_KEYWORDS \
+ | UNDNAME_NO_FUNCTION_RETURNS \
+ | UNDNAME_NO_ALLOCATION_MODEL \
+ | UNDNAME_NO_ALLOCATION_LANGUAGE \
+ | UNDNAME_NO_ACCESS_SPECIFIERS \
+ | UNDNAME_NO_THROW_SIGNATURES \
+ | UNDNAME_NO_MEMBER_TYPE \
+ | UNDNAME_NO_ECSU \
+ | UNDNAME_NO_IDENT_CHAR_CHECK
+
+ SHORT_UNIQUE_NAME = UNDNAME_NO_MS_KEYWORDS | UNDNAME_NO_ACCESS_SPECIFIERS | UNDNAME_NO_ECSU
+
+#~ The following code doesn't work - access violation
+
+#~__unDName definition was taken from:
+#~http://www.tech-archive.net/Archive/VC/microsoft.public.vc.language/2006-02/msg00754.html
+
+#~ msvcrxx = ctypes.windll.msvcr90
+#~ free_type = ctypes.CFUNCTYPE( None, ctypes.c_void_p ) #free type
+#~ malloc_type = ctypes.CFUNCTYPE( ctypes.c_void_p, ctypes.c_uint ) #malloc type
+#~ __unDName = msvcrxx.__unDName
+#~ __unDName.argtypes = [ ctypes.c_char_p #undecorated name
+ #~ , ctypes.c_char_p #decorated name
+ #~ , ctypes.c_int #sizeof undecorated name
+ #~ , malloc_type
+ #~ , free_type
+ #~ , ctypes.c_ushort #flags
+ #~ ]
+#~ __unDName.restype = ctypes.c_char_p
+#~ def undecorate_name( name, options=None ):
+ #~ if not name:
+ #~ return ''
+ #~ if options is None:
+ #~ options = UNDECORATE_NAME_OPTIONS.SHORT_UNIQUE_NAME
+ #~ buffer_size = 1024 * 32
+ #~ undecorated_name = ctypes.create_string_buffer('\0' * buffer_size) #should be enouph for any symbol
+ #~ __unDName( undecorated_name
+ #~ , str(name)
+ #~ , buffer_size
+ #~ , malloc_type( msvcrxx.malloc )
+ #~ , free_type( msvcrxx.free )
+ #~ , options )
+ #~ return undecorated_name.value
+
+class undname_creator_t:
+ def __init__( self ):
+ import ctypes.wintypes
+ self.__undname = ctypes.windll.dbghelp.UnDecorateSymbolName
+ self.__undname.argtypes = [ctypes.c_char_p, ctypes.c_char_p, ctypes.c_uint, ctypes.c_uint]
+ self.__clean_ecsu = ( re.compile( r'(?P<startswith>^|\W)(?:(class|enum|struct|union)\s)' )
+ , '%(startswith)s' )
+ self.__fundamental_types = (
+ ( 'short unsigned int', 'unsigned short')
+ , ( 'short int', 'short' )
+ , ( 'long int', 'long' )
+ , ( 'long unsigned int', 'unsigned long' )
+ )
+ self.__calling_conventions = ( re.compile( r'(?P<startswith>^|\s)(?:__(cdecl|clrcall|stdcall|fastcall|thiscall)\s)' )
+ , '%(startswith)s' )
+
+ def normalize_undecorated( self, undname, options=None ):
+ if options is None:
+ options = UNDECORATE_NAME_OPTIONS.SHORT_UNIQUE_NAME
+ if UNDECORATE_NAME_OPTIONS.UNDNAME_NO_ECSU & options:
+ expr, substitute = self.__clean_ecsu
+ undname = expr.sub( lambda m: substitute % m.groupdict(), undname )
+ if UNDECORATE_NAME_OPTIONS.UNDNAME_NO_ACCESS_SPECIFIERS & options:
+ for prefix in ( 'public: ', 'private: ', 'protected: ' ):
+ if undname.startswith( prefix ):
+ undname = undname[ len(prefix): ]
+ break
+ if UNDECORATE_NAME_OPTIONS.UNDNAME_NO_MS_KEYWORDS & options:
+ expr, substitute = self.__calling_conventions
+ undname = expr.sub( lambda m: substitute % m.groupdict(), undname )
+ return undname.strip()
+
+ def undecorate_blob( self, name, options=None ):
+ if options is None:
+ options = UNDECORATE_NAME_OPTIONS.SHORT_UNIQUE_NAME
+ buffer = ctypes.create_string_buffer(1024*16)
+ res = self.__undname( str(name), buffer, ctypes.sizeof(buffer), options)
+ if res:
+ return self.normalize_undecorated( str(buffer[:res]) )
+ else:
+ return name
+
+ def __remove_leading_scope( self, s ):
+ if s and s.startswith( '::' ):
+ return s[2:]
+ else:
+ return s
+
+ def __format_type_as_undecorated( self, type_, is_argument ):
+ result = []
+ type_ = declarations.remove_alias( type_ )
+ if declarations.is_array( type_ ):
+ result.append( declarations.array_item_type( type_ ).decl_string )
+ result.append( '*' )
+ if is_argument:
+ result.append( 'const' )
+ else:
+ result.append( self.__remove_leading_scope( type_.decl_string ) )
+ return ' '.join( result )
+
+ def __normalize( self, name ):
+ for what, with_ in self.__fundamental_types:
+ name = name.replace( what, with_ )
+ name = name.replace( ', ', ',' )
+ return name
+
+ def undecorate_argtypes( self, argtypes ):
+ if not argtypes:
+ return 'void'
+ else:
+ formater = lambda type_: self.__format_type_as_undecorated( type_, True )
+ return ','.join( map( formater, argtypes ) )
+
+ def __undecorated_calldef( self, calldef ):
+ calldef_type = calldef.function_type()
+
+ result = []
+ is_mem_fun = isinstance( calldef, declarations.member_calldef_t )
+ if is_mem_fun and calldef.virtuality != declarations.VIRTUALITY_TYPES.NOT_VIRTUAL:
+ result.append( 'virtual ' )
+ if is_mem_fun and calldef.has_static:
+ result.append( 'static ' )
+ if calldef_type.return_type:
+ result.append( self.__format_type_as_undecorated( calldef.return_type, False ) )
+ result.append( ' ' )
+ if is_mem_fun:
+ result.append( self.__remove_leading_scope( calldef.parent.decl_string ) + '::')
+
+ result.append( calldef.name )
+ if isinstance( calldef, ( declarations.constructor_t, declarations.destructor_t) ) \
+ and declarations.templates.is_instantiation( calldef.parent.name ):
+ result.append( '<%s>' % ','.join( declarations.templates.args( calldef.parent.name ) ) )
+
+ result.append( '(%s)' % self.undecorate_argtypes( calldef_type.arguments_types ) )
+ if is_mem_fun and calldef.has_const:
+ result.append( 'const' )
+ return ''.join( result )
+
+ def __undecorated_variable( self, decl ):
+ result = []
+ is_mem_var = isinstance( decl.parent, declarations.class_t )
+ if is_mem_var and decl.type_qualifiers.has_static:
+ result.append( 'static ' )
+ result.append( self.__format_type_as_undecorated( decl.type, False ) )
+ result.append( ' ' )
+ if is_mem_var:
+ result.append( self.__remove_leading_scope( decl.parent.decl_string ) + '::' )
+ result.append( decl.name )
+ return ''.join( result )
+
+ def undecorated_decl(self, decl):
+ """returns string, which contains full function name formatted exactly as
+ result of dbghelp.UnDecorateSymbolName, with UNDNAME_NO_MS_KEYWORDS | UNDNAME_NO_ACCESS_SPECIFIERS | UNDNAME_NO_ECSU
+ options.
+ """
+ name = None
+ if isinstance( decl, declarations.calldef_t ):
+ name = self.__undecorated_calldef( decl )
+ elif isinstance( decl, declarations.variable_t ):
+ name = self.__undecorated_variable( decl )
+ else:
+ raise NotImplementedError()
+ return self.__normalize( name )
Modified: pygccxml_dev/pygccxml/declarations/decl_printer.py
===================================================================
--- pygccxml_dev/pygccxml/declarations/decl_printer.py 2009-01-05 22:58:43 UTC (rev 1537)
+++ pygccxml_dev/pygccxml/declarations/decl_printer.py 2009-01-06 08:38:32 UTC (rev 1538)
@@ -123,9 +123,6 @@
if self.verbose and self.__inst.decorated_name:
decorated_name = 'decorated name: %s'%(self.__inst.decorated_name)
self.writer( ' ' * curr_level * self.INDENT_SIZE + decorated_name + os.linesep)
- if self.verbose and self.__inst.undecorated_name:
- undecorated_name = 'undecorated name: %s' % (self.__inst.undecorated_name)
- self.writer( ' ' * curr_level * self.INDENT_SIZE + undecorated_name + os.linesep)
def print_calldef_info(self, decl=None):
""" Returns function signature: [retval, [arg1, ..., argN]]. """
Modified: pygccxml_dev/pygccxml/declarations/declaration.py
===================================================================
--- pygccxml_dev/pygccxml/declarations/declaration.py 2009-01-05 22:58:43 UTC (rev 1537)
+++ pygccxml_dev/pygccxml/declarations/declaration.py 2009-01-06 08:38:32 UTC (rev 1538)
@@ -69,7 +69,6 @@
self._compiler = None
self._partial_name = None
self._decorated_name = None
- self._undecorated_name = None
def __str__(self):
"""Default __str__ method.
@@ -244,15 +243,6 @@
@type: str
""" )
- def _get_undecorated_name( self ):
- return self._undecorated_name
- def _set_undecorated_name( self, undecorated_name ):
- self._undecorated_name = undecorated_name
- undecorated_name = property( _get_undecorated_name, _set_undecorated_name
- , doc="""declaration name, which was created by pygccxml, for matching ( source code <==> binary ) purpose
- @type: str
- """ )
-
def _get_attributes( self ):
return self._attributes
def _set_attributes( self, attributes ):
Modified: pygccxml_dev/unittests/data/core_cache.hpp
===================================================================
--- pygccxml_dev/unittests/data/core_cache.hpp 2009-01-05 22:58:43 UTC (rev 1537)
+++ pygccxml_dev/unittests/data/core_cache.hpp 2009-01-06 08:38:32 UTC (rev 1538)
@@ -22,4 +22,4 @@
#endif//__core_cache_hpp__
-//touch//touch//touch//touch//touch
\ No newline at end of file
+//touch//touch//touch//touch//touch//touch//touch//touch
\ No newline at end of file
Modified: pygccxml_dev/unittests/undname_creator_tester.py
===================================================================
--- pygccxml_dev/unittests/undname_creator_tester.py 2009-01-05 22:58:43 UTC (rev 1537)
+++ pygccxml_dev/unittests/undname_creator_tester.py 2009-01-06 08:38:32 UTC (rev 1538)
@@ -20,19 +20,24 @@
global_ns = None
known_issues = set([
- #pointer to functions
- 'void (** myclass_t::get_do_smth(void))(std::auto_ptr<number_t> &)'
- , 'void myclass_t::set_do_smth(void (**)(std::auto_ptr<number_t> &))'
- # array as function argument
- , 'int FA10_i_i(int * const)'
+ # array as function argument: 'int FA10_i_i(int * const)'
+ '?FA10_i_i@@YAHQAH@Z'
+ #pointer to function: 'void myclass_t::set_do_smth(void (**)(std::auto_ptr<number_t> &))'
+ , '?set_do_smth@myclass_t@@QAEXPAP6AXAAV?$auto_ptr@Vnumber_t@@@std@@@Z@Z'
+ #pointer to functions: 'void (** myclass_t::get_do_smth(void))(std::auto_ptr<number_t> &)'
+ , '?get_do_smth@myclass_t@@QAEPAP6AXAAV?$auto_ptr@Vnumber_t@@@std@@@ZXZ'
])
if 'msvc71' == utils.native_compiler.get_gccxml_compiler():
- known_issues.add( 'std::auto_ptr<number_t> & std::auto_ptr<number_t>::operator=(std::auto_ptr_ref<number_t>)' )
+ #missing reference in argument - compiler issue 'std::auto_ptr<number_t> & std::auto_ptr<number_t>::operator=(std::auto_ptr_ref<number_t>)'
+ known_issues.add( '??4?$auto_ptr@Vnumber_t@@@std@@QAEAAV01@U?$auto_ptr_ref@Vnumber_t@@@1@@Z' )
def __init__(self, *args ):
parser_test_case.parser_test_case_t.__init__( self, *args )
self.header = r'msvc\mydll.h'
+ self.map_file = os.path.join( autoconfig.data_directory, 'msvc', 'release', 'mydll.map' )
+ self.dll_file = os.path.join( autoconfig.data_directory, 'msvc', 'release', 'mydll.dll' )
+
def setUp(self):
if not tester_t.global_ns:
decls = parser.parse( [self.header], self.config )
@@ -49,46 +54,61 @@
return False
def __tester_impl( self, fname ):
- symbols = binary_parsers.exported_symbols.load_from_file( fname )
+ symbols, parser = binary_parsers.merge_information( self.global_ns, fname, runs_under_unittest=True )
self.failUnless( 'identity' in symbols )
- undecorated_blob_names = set()
- for blob in symbols.iterkeys():
+ blob_names = set()
+ for blob in parser.loaded_symbols:
+ if isinstance( blob, tuple ):
+ blob = blob[0]
undname = binary_parsers.undecorate_blob( blob )
if "`" in undname:
continue
- undecorated_blob_names.add( undname )
+ blob_names.add( blob )
- undecorated_decl_names = set()
- for f in self.global_ns.decls(self.is_included):
- undecorated_decl_names.add( binary_parsers.undecorate_decl( f ) )
+ decl_blob_names = set( symbols.keys() )
- issuperset = undecorated_decl_names.issuperset( undecorated_blob_names )
+ issuperset = decl_blob_names.issuperset( blob_names )
if not issuperset:
- common = undecorated_decl_names.intersection( undecorated_blob_names )
+ common = decl_blob_names.intersection( blob_names )
- undecorated_decl_names.difference_update(common)
- undecorated_blob_names.difference_update(common)
- if not self.known_issues.issubset( undecorated_blob_names ):
- undecorated_blob_names.difference_update( self.known_issues )
+ decl_blob_names.difference_update(common)
+ blob_names.difference_update(common)
+ if not self.known_issues.issubset( blob_names ):
+ blob_names.difference_update( self.known_issues )
msg = [ "undecorate_decl - failed" ]
- msg.append( "undecorated_decl_names :" )
- for i in undecorated_decl_names:
+ msg.append( "decl_blob_names :" )
+ for i in decl_blob_names:
msg.append( '\t==>%s<==' % i )
- msg.append( "undecorated_blob_names :" )
- for i in undecorated_blob_names:
+ msg.append( "blob_names :" )
+ for i in blob_names:
msg.append( '\t==>%s<==' % i )
self.fail( os.linesep.join(msg) )
def test_map_file( self ):
- map_file = os.path.join( autoconfig.data_directory, 'msvc', 'release', 'mydll.map' )
- self.__tester_impl( map_file )
+ self.__tester_impl( self.map_file )
def test_dll_file( self ):
- dll_file = os.path.join( autoconfig.data_directory, 'msvc', 'release', 'mydll.dll' )
- self.__tester_impl( dll_file )
+ self.__tester_impl( self.dll_file )
+ def test_compare_parsers( self ):
+ dsymbols, dparser = binary_parsers.merge_information( self.global_ns, self.dll_file, runs_under_unittest=True )
+ msymbols, mparser = binary_parsers.merge_information( self.global_ns, self.map_file, runs_under_unittest=True )
+
+ self.failUnless( len( dparser.loaded_symbols ) == len( mparser.loaded_symbols ) )
+
+ was_error = False
+ for blob, decl in dsymbols.iteritems():
+ if blob not in msymbols:
+ was_error = True
+ print '\n%s could not be found in map file loaded symbols' % binary_parsers.undecorate_blob( blob )
+ #~ self.failUnless( blob in msymbols, binary_parsers.undecorate_blob( blob ) )
+ else:
+ mdecl = msymbols[ blob ]
+ self.failUnless( mdecl is decl )
+ self.failUnless( was_error == False )
+
def create_suite():
suite = unittest.TestSuite()
if 'win' in sys.platform:
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|