#! /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() |