Chris@87: from __future__ import division, absolute_import, print_function Chris@87: Chris@87: import re Chris@87: import sys Chris@87: import os Chris@87: import subprocess Chris@87: Chris@87: __doc__ = """This module generates a DEF file from the symbols in Chris@87: an MSVC-compiled DLL import library. It correctly discriminates between Chris@87: data and functions. The data is collected from the output of the program Chris@87: nm(1). Chris@87: Chris@87: Usage: Chris@87: python lib2def.py [libname.lib] [output.def] Chris@87: or Chris@87: python lib2def.py [libname.lib] > output.def Chris@87: Chris@87: libname.lib defaults to python.lib and output.def defaults to stdout Chris@87: Chris@87: Author: Robert Kern Chris@87: Last Update: April 30, 1999 Chris@87: """ Chris@87: Chris@87: __version__ = '0.1a' Chris@87: Chris@87: py_ver = "%d%d" % tuple(sys.version_info[:2]) Chris@87: Chris@87: DEFAULT_NM = 'nm -Cs' Chris@87: Chris@87: DEF_HEADER = """LIBRARY python%s.dll Chris@87: ;CODE PRELOAD MOVEABLE DISCARDABLE Chris@87: ;DATA PRELOAD SINGLE Chris@87: Chris@87: EXPORTS Chris@87: """ % py_ver Chris@87: # the header of the DEF file Chris@87: Chris@87: FUNC_RE = re.compile(r"^(.*) in python%s\.dll" % py_ver, re.MULTILINE) Chris@87: DATA_RE = re.compile(r"^_imp__(.*) in python%s\.dll" % py_ver, re.MULTILINE) Chris@87: Chris@87: def parse_cmd(): Chris@87: """Parses the command-line arguments. Chris@87: Chris@87: libfile, deffile = parse_cmd()""" Chris@87: if len(sys.argv) == 3: Chris@87: if sys.argv[1][-4:] == '.lib' and sys.argv[2][-4:] == '.def': Chris@87: libfile, deffile = sys.argv[1:] Chris@87: elif sys.argv[1][-4:] == '.def' and sys.argv[2][-4:] == '.lib': Chris@87: deffile, libfile = sys.argv[1:] Chris@87: else: Chris@87: print("I'm assuming that your first argument is the library") Chris@87: print("and the second is the DEF file.") Chris@87: elif len(sys.argv) == 2: Chris@87: if sys.argv[1][-4:] == '.def': Chris@87: deffile = sys.argv[1] Chris@87: libfile = 'python%s.lib' % py_ver Chris@87: elif sys.argv[1][-4:] == '.lib': Chris@87: deffile = None Chris@87: libfile = sys.argv[1] Chris@87: else: Chris@87: libfile = 'python%s.lib' % py_ver Chris@87: deffile = None Chris@87: return libfile, deffile Chris@87: Chris@87: def getnm(nm_cmd = ['nm', '-Cs', 'python%s.lib' % py_ver]): Chris@87: """Returns the output of nm_cmd via a pipe. Chris@87: Chris@87: nm_output = getnam(nm_cmd = 'nm -Cs py_lib')""" Chris@87: f = subprocess.Popen(nm_cmd, shell=True, stdout=subprocess.PIPE) Chris@87: nm_output = f.stdout.read() Chris@87: f.stdout.close() Chris@87: return nm_output Chris@87: Chris@87: def parse_nm(nm_output): Chris@87: """Returns a tuple of lists: dlist for the list of data Chris@87: symbols and flist for the list of function symbols. Chris@87: Chris@87: dlist, flist = parse_nm(nm_output)""" Chris@87: data = DATA_RE.findall(nm_output) Chris@87: func = FUNC_RE.findall(nm_output) Chris@87: Chris@87: flist = [] Chris@87: for sym in data: Chris@87: if sym in func and (sym[:2] == 'Py' or sym[:3] == '_Py' or sym[:4] == 'init'): Chris@87: flist.append(sym) Chris@87: Chris@87: dlist = [] Chris@87: for sym in data: Chris@87: if sym not in flist and (sym[:2] == 'Py' or sym[:3] == '_Py'): Chris@87: dlist.append(sym) Chris@87: Chris@87: dlist.sort() Chris@87: flist.sort() Chris@87: return dlist, flist Chris@87: Chris@87: def output_def(dlist, flist, header, file = sys.stdout): Chris@87: """Outputs the final DEF file to a file defaulting to stdout. Chris@87: Chris@87: output_def(dlist, flist, header, file = sys.stdout)""" Chris@87: for data_sym in dlist: Chris@87: header = header + '\t%s DATA\n' % data_sym Chris@87: header = header + '\n' # blank line Chris@87: for func_sym in flist: Chris@87: header = header + '\t%s\n' % func_sym Chris@87: file.write(header) Chris@87: Chris@87: if __name__ == '__main__': Chris@87: libfile, deffile = parse_cmd() Chris@87: if deffile is None: Chris@87: deffile = sys.stdout Chris@87: else: Chris@87: deffile = open(deffile, 'w') Chris@87: nm_cmd = [str(DEFAULT_NM), str(libfile)] Chris@87: nm_output = getnm(nm_cmd) Chris@87: dlist, flist = parse_nm(nm_output) Chris@87: output_def(dlist, flist, DEF_HEADER, deffile)