| #! /usr/bin/env python | |
| """nm2def.py | |
| Helpers to extract symbols from Unix libs and auto-generate | |
| Windows definition files from them. Depends on nm(1). Tested | |
| on Linux and Solaris only (-p option to nm is for Solaris only). | |
| By Marc-Andre Lemburg, Aug 1998. | |
| Additional notes: the output of nm is supposed to look like this: | |
| acceler.o: | |
| 000001fd T PyGrammar_AddAccelerators | |
| U PyGrammar_FindDFA | |
| 00000237 T PyGrammar_RemoveAccelerators | |
| U _IO_stderr_ | |
| U exit | |
| U fprintf | |
| U free | |
| U malloc | |
| U printf | |
| grammar1.o: | |
| 00000000 T PyGrammar_FindDFA | |
| 00000034 T PyGrammar_LabelRepr | |
| U _PyParser_TokenNames | |
| U abort | |
| U printf | |
| U sprintf | |
| ... | |
| Even if this isn't the default output of your nm, there is generally an | |
| option to produce this format (since it is the original v7 Unix format). | |
| """ | |
| import os, sys | |
| PYTHONLIB = 'libpython'+sys.version[:3]+'.a' | |
| PC_PYTHONLIB = 'Python'+sys.version[0]+sys.version[2]+'.dll' | |
| NM = 'nm -p -g %s' # For Linux, use "nm -g %s" | |
| def symbols(lib=PYTHONLIB,types=('T','C','D')): | |
| lines = os.popen(NM % lib).readlines() | |
| lines = [s.strip() for s in lines] | |
| symbols = {} | |
| for line in lines: | |
| if len(line) == 0 or ':' in line: | |
| continue | |
| items = line.split() | |
| if len(items) != 3: | |
| continue | |
| address, type, name = items | |
| if type not in types: | |
| continue | |
| symbols[name] = address,type | |
| return symbols | |
| def export_list(symbols): | |
| data = [] | |
| code = [] | |
| for name,(addr,type) in symbols.items(): | |
| if type in ('C','D'): | |
| data.append('\t'+name) | |
| else: | |
| code.append('\t'+name) | |
| data.sort() | |
| data.append('') | |
| code.sort() | |
| return ' DATA\n'.join(data)+'\n'+'\n'.join(code) | |
| # Definition file template | |
| DEF_TEMPLATE = """\ | |
| EXPORTS | |
| %s | |
| """ | |
| # Special symbols that have to be included even though they don't | |
| # pass the filter | |
| SPECIALS = ( | |
| ) | |
| def filter_Python(symbols,specials=SPECIALS): | |
| for name in symbols.keys(): | |
| if name[:2] == 'Py' or name[:3] == '_Py': | |
| pass | |
| elif name not in specials: | |
| del symbols[name] | |
| def main(): | |
| s = symbols(PYTHONLIB) | |
| filter_Python(s) | |
| exports = export_list(s) | |
| f = sys.stdout # open('PC/python_nt.def','w') | |
| f.write(DEF_TEMPLATE % (exports)) | |
| f.close() | |
| if __name__ == '__main__': | |
| main() |