[Python-checkins] CVS: python/dist/src/PC/os2emx Makefile,NONE,1.1 README.os2emx,NONE,1.1 config.c,NONE,1.1 dlfcn.c,NONE,1.1 dlfcn.h,NONE,1.1 dllentry.c,NONE,1.1 getpathp.c,NONE,1.1 pyconfig.h,NONE,1.1 python23.def,NONE,1.1 pythonpm.c,NONE,1.1

Andrew I MacIntyre aimacintyre@users.sourceforge.net
Sat, 16 Feb 2002 21:23:32 -0800


Update of /cvsroot/python/python/dist/src/PC/os2emx
In directory usw-pr-cvs1:/tmp/cvs-serv24301/dist/src/PC/os2emx

Added Files:
	Makefile README.os2emx config.c dlfcn.c dlfcn.h dllentry.c 
	getpathp.c pyconfig.h python23.def pythonpm.c 
Log Message:
Create and populate OS/2 EMX port build directory:
  PC/os2emx/
    Makefile
    README.os2emx
    config.c
    dlfcn.c            // libdl emulation code for loadable extensions
    dlfcn.h
    dllentry.c         // DLL initialisation routine for Python DLL
    getpath.c
    pyconfig.h
    python23.def       // Python DLL symbol export definitions
    pythonpm.c         // console-less PM interpreter wrapper


--- NEW FILE: Makefile ---
#####################==================----------------תתתתתתתתתתתתת
#
# Top-Level Makefile for Building Python 2.3 for OS/2 using GCC/EMX
# Originally written by Andrew Zabolotny, <bit@eltech.ru> for Python 1.5.2
# Modified by Andrew MacIntyre, <andymac@pcug.org.au> for Python 2.3
#
# This makefile was developed for use with [P]GCC/EMX compiler any
# version and GNU Make.
#
# The output of the build is a largish Python23.DLL containing the
# essential modules of Python and a small Python.exe program to start
# the interpreter. When embedding Python within another program, only
# Python23.DLL is needed. We also build python_s.a static library (which
# can be converted into OMF (.lib) format using emxomf tool) and both
# python.a and python.lib import libraries.  Then the optional 
# extension modules, which are OS/2 DLLs renamed with a PYD file extension.
#
# Recommended build order:
#   make depend		(if you have makedep)
#   make all
#   make lx		(if you have lxlite)
#   make test		(optional)
#
#####################==================----------------תתתתתתתתתתתתת

# === Compilation mode: debug or release ===
MODE=		optimize
#MODE=		debug
# === Assert() enabled ===
#ASSERTIONS=no
ASSERTIONS=yes

# === Optional modules ===
# Do you have the InfoZip compression library installed?
ZLIB=		no
# Do you have the Ultra Fast Crypt (UFC) library installed?
UFC=		no
# Do you have the Tcl/Tk library installed?
TCLTK=		no
# Do you have the GNU multiprecision library installed?
GMPZ=		no
# Do you have the GNU readline library installed?
# NOTE: I'm using a modified version of Kai Uwe Rommel's port that 
#       - is compiled with multithreading enabled
#       - is linked statically
#       I have had no success trying to use a DLL version, even with
#       the multithreading switch.
GREADLINE=	no
# Do you have the BSD DB library (v1.85) as included in the EMXBSD package?
# NOTE: this library needs to be recompiled with a structure member
#       renamed to avoid problems with the multithreaded errno support
#       (there is a structure member called errno, used for shadowing the
#       real errno, which conflicts with the errno redefinition of -Zmt)
BSDDB=		no
# Do you have the ncurses library installed? EMX's BSD curses aren't enough! 
CURSES=		no
# Do you have the expat XML parsing library installed?
EXPAT=		no
# Do you have the GDBM library installed?
GDBM=		no

# === The Tools ===
CC=		gcc
CFLAGS=		-Zmt -Wall $(INCLUDE)
CFLAGS.LIB=	$(CFLAGS)
LD=		gcc
LDFLAGS=	-Zmt -Zcrtdll -L. -lgcc
LDFLAGS.EXE=	$(LDFLAGS)
LDFLAGS.DLL=	$(LDFLAGS) -Zdll
LDFLAGS.A=	$(LDFLAGS) $(LIBS)
ARFLAGS=	crs
IMPLIB=		emximp
EXPLIB=		emxexp

# adjust C compiler settings based on build options
ifeq ($(MODE),debug)
  CFLAGS+=	-g -O
  LDFLAGS+=	-g
else
  CFLAGS+=	-s -O2
  LDFLAGS+=	-s
endif
ifeq ($(ASSERTIONS),no)
  CFLAGS+=	-DNDEBUG
endif

# We're using the OMF format since EMX's ld has a obscure bug
# because of which it sometimes fails to build relocations
# in .data segment that point to another .data locations
# (except for the final linking if the .EXEs)
OMF=		yes

# if fork() support is required, the main executable must be linked with ld
EXEOMF=		no

# File extensions
MODULE.EXT=	.pyd
ifeq ($(OMF),yes)
  O=		.obj
  A=		.lib
  AR=		emxomfar
  CFLAGS+=	-Zomf
  LDFLAGS+=	-Zomf
  ifeq ($(MODE),debug)
    ARFLAGS=	-p64 crs
  else
    ARFLAGS=	-p32 crs
  endif
else
  O=		.o
  A=		.a
  AR=		ar
endif

# Source file paths
SRCPATH=.;../../Python;../../Parser;../../Objects;../../Include;../../Modules
# Python contains the central core, containing the builtins and interpreter.
# Parser contains Python's Internal Parser and
#   Standalone Parser Generator Program (Shares Some of Python's Modules)
# Objects contains Python Object Types
# Modules contains extension Modules (Built-In or as Separate DLLs)

# Unix shells tend to use "$" as delimiter for variable names.
# Test for this behaviour and set $(BUCK) variable correspondigly ...
__TMP__:=$(shell echo $$$$)
ifeq ($(__TMP__),$$$$)
  BUCK=		$$
  BRO=		(
  BRC=		)
else
  BUCK=		\$$
  BRO=		\(
  BRC=		\)
endif
# Compute the "double quote" variable
__TMP__:=$(shell echo "")
ifeq ($(__TMP__),"")
  DQUOTE=	"
else
  DQUOTE=	\"
endif

# Include paths
#INCLUDE=	-I$(subst ;, -I, $(SRCPATH))
INCLUDE=	-I. -I../../Include

# Path to search for .c files
vpath %.c .;..;$(SRCPATH)

# Top of the package tree
TOP=		../../

# Directory for output files
OUTBASE=	out/
OUT=		$(OUTBASE)$(MODE)/

# Additional libraries
LIBS=		-lsocket

# Utility macro: replacement for $^
^^=		$(filter-out %$A,$^)
# Use $(L^) to link with all libraries specified as dependencies
L^=		$(addprefix -l,$(basename $(notdir $(filter %$A,$+))))

# Build rules
$(OUT)%$O: %.c
	$(CC) $(CFLAGS.LIB) -c $< -o $@

%.a:
	$(LD) $(LDFLAGS.A) -o $@ $(^^) $(L^)

%.dll:
	$(LD) $(LDFLAGS.DLL) -o $@ $(^^) $(L^) $(LIBS)

%.pyd: $(OUT)%module$O $(OUT)%_m.def
	$(LD) $(LDFLAGS.DLL) -o $@ $(^^) $(PYTHON.IMPLIB) $(LIBS)

%.exe:
	$(LD) $(LDFLAGS.EXE) -o $@ $(^^) $(L^)

%_m.def:
	@echo Creating .DEF file: $@
	@echo LIBRARY $(notdir $*) INITINSTANCE TERMINSTANCE >$@
        ifeq ($(DESCRIPTION.$(notdir $*)$(MODULE.EXT)),)
	  @echo DESCRIPTION $(DQUOTE)Python standard module $(notdir $*)$(DQUOTE) >>$@
        else
	  @echo DESCRIPTION $(DQUOTE)$(DESCRIPTION.$(notdir $*)$(MODULE.EXT))$(DQUOTE) >>$@
        endif
	@echo DATA MULTIPLE NONSHARED >>$@
	@echo EXPORTS >>$@
	@echo 	init$(notdir $*) >>$@

%.def:
	@echo Creating .DEF file: $@
	@echo NAME $(notdir $*) $(EXETYPE.$(notdir $*).exe) >$@
	@echo DESCRIPTION $(DQUOTE)$(DESCRIPTION.$(notdir $*).exe)$(DQUOTE) >>$@
	@echo STACKSIZE 1048576 >>$@

# Output file names
PYTHON_VER=	2.3
PYTHON_LIB=	python23
PYTHON.LIB=	$(PYTHON_LIB)_s$A
PYTHON.IMPLIB=	$(PYTHON_LIB)$A
ifeq ($(EXEOMF),yes)
  PYTHON.EXEIMP=	$(PYTHON.IMPLIB)
  LDMODE.EXE=		-Zomf
else
  PYTHON.EXEIMP=	$(PYTHON_LIB).a
  LDMODE.EXE = 
endif
PYTHON.DLL=	$(PYTHON_LIB).dll
PYTHON.DEF=	$(PYTHON_LIB).def
PYTHON.EXE=	python.exe
PYTHONPM.EXE=	pythonpm.exe
PGEN.EXE=	pgen.exe
LIBRARY=	$(PYTHON.LIB)
LD_LIBRARY=	$(PYTHON.IMPLIB)

# Additional executable parameters
EXETYPE.$(PYTHON.EXE)=		WINDOWCOMPAT
EXETYPE.$(PYTHONPM.EXE)=	WINDOWAPI
EXETYPE.$(PGEN.EXE)=		WINDOWCOMPAT
DESCRIPTION.$(PYTHON.EXE)=	Python object-oriented programming language interpreter for OS/2
DESCRIPTION.$(PYTHONPM.EXE)=	$(DESCRIPTION.$(PYTHON.EXE))
DESCRIPTION.$(PGEN.EXE)=	Python object-oriented programming language parser generator for OS/2

# Module descriptions
DESCRIPTION.zlib$(MODULE.EXT)=		Python Extension DLL for accessing the InfoZip compression library
DESCRIPTION.crypt$(MODULE.EXT)=		Python Extension DLL implementing the crypt$(BRO)$(BRC) function
DESCRIPTION._tkinter$(MODULE.EXT)=	Python Extension DLL for access to Tcl/Tk Environment
DESCRIPTION.mpz$(MODULE.EXT)=		Python Extension DLL for access to GNU multi-precision library
DESCRIPTION.readline$(MODULE.EXT)=	Python Extension DLL for access to GNU ReadLine library
DESCRIPTION.bsddb$(MODULE.EXT)=		Python Extension DLL for access to BSD DB (v1.85) library
DESCRIPTION._curses$(MODULE.EXT)=	Python Extension DLL for access to ncurses library
DESCRIPTION.pyexpat$(MODULE.EXT)=	Python Extension DLL for access to expat library

# Source files
SRC.PGEN=	$(addprefix ../../Parser/, \
		pgenmain.c \
		pgen.c \
		printgrammar.c \
		grammar.c \
		bitset.c \
		firstsets.c)
OBJ.PGEN=	$(addprefix $(OUT),$(notdir $(SRC.PGEN:.c=$O)))

SRC.OS2EMX=	config.c dlfcn.c getpathp.c
SRC.MAIN=	$(addprefix $(TOP), \
		Modules/getbuildinfo.c \
		Modules/main.c)
SRC.MODULES=	$(addprefix $(TOP), \
		Modules/gcmodule.c \
		Modules/signalmodule.c \
		Modules/posixmodule.c \
		Modules/threadmodule.c \
		Modules/_sre.c)
SRC.PARSER=	$(addprefix $(TOP), \
		Parser/acceler.c \
		Parser/grammar1.c \
		Parser/listnode.c \
		Parser/node.c \
		Parser/parser.c \
		Parser/parsetok.c \
		Parser/tokenizer.c \
		Parser/bitset.c \
		Parser/metagrammar.c \
		Parser/myreadline.c)
SRC.PYTHON=	$(addprefix $(TOP), \
		Python/bltinmodule.c \
		Python/exceptions.c \
		Python/ceval.c \
		Python/compile.c \
		Python/codecs.c \
		Python/errors.c \
		Python/frozen.c \
		Python/frozenmain.c \
		Python/future.c \
		Python/getargs.c \
		Python/getcompiler.c \
		Python/getcopyright.c \
		Python/getmtime.c \
		Python/getplatform.c \
		Python/getversion.c \
		Python/graminit.c \
		Python/import.c \
		Python/importdl.c \
		Python/marshal.c \
		Python/modsupport.c \
		Python/mysnprintf.c \
		Python/mystrtoul.c \
		Python/pyfpe.c \
		Python/pystate.c \
		Python/pythonrun.c \
		Python/structmember.c \
		Python/symtable.c \
		Python/sysmodule.c \
		Python/traceback.c \
		Python/getopt.c \
		Python/dynload_shlib.c \
		Python/thread.c)
SRC.OBJECT=	$(addprefix $(TOP), \
		Objects/abstract.c \
		Objects/bufferobject.c \
		Objects/cellobject.c \
		Objects/classobject.c \
		Objects/cobject.c \
		Objects/complexobject.c \
		Objects/descrobject.c \
		Objects/dictobject.c \
		Objects/fileobject.c \
		Objects/floatobject.c \
		Objects/frameobject.c \
		Objects/funcobject.c \
		Objects/intobject.c \
		Objects/iterobject.c \
		Objects/listobject.c \
		Objects/longobject.c \
		Objects/methodobject.c \
		Objects/moduleobject.c \
		Objects/object.c \
		Objects/rangeobject.c \
		Objects/sliceobject.c \
		Objects/stringobject.c \
		Objects/structseq.c \
		Objects/tupleobject.c \
		Objects/typeobject.c \
		Objects/unicodeobject.c \
		Objects/unicodectype.c \
		Objects/weakrefobject.c)

SRC.LIB=	$(SRC.OS2EMX) \
		$(SRC.MAIN) \
		$(SRC.PARSER) \
		$(SRC.OBJECT) \
		$(SRC.PYTHON) \
		$(SRC.MODULES)
OBJ.LIB=	$(addprefix $(OUT),$(notdir $(SRC.LIB:.c=$O)))

SRC.EXE=	$(TOP)Modules/python.c
SRC.PMEXE=	pythonpm.c

# Python modules to be dynamically loaded that:
#   1) have only single source file and require no extra libs
#   2) use the standard module naming convention
#      (the 'module' in ?????module.c is assumed)
# - these can be built with implicit rules
EASYEXTMODULES=	array \
		cmath \
		_codecs \
		dl \
		errno \
		fcntl \
		fpectl \
		fpetest \
		_locale \
		math \
		new \
		parser \
		pwd \
		rgbimg \
		rotor \
		select \
		sha \
		strop \
		struct \
		time \
		timing

# Python modules to be dynamically loaded that need explicit build rules
#  (either multiple source files and/or non-standard module naming)
#  (NOTE: use shortened names for modules affected by 8 char name limit)
HARDEXTMODULES=	binascii \
		cPickle \
		cStringI \
		_hotshot \
		imageop \
		md5 \
		operator \
		pcre \
		regex \
		_socket \
		termios \
		_testcap \
		unicoded \
		_weakref \
		xreadlin

# Python external ($(MODULE.EXT)) modules - can be EASY or HARD
ifeq ($(ZLIB),yes)
  HARDEXTMODULES+=	zlib
endif
ifeq ($(UFC),yes)
  HARDEXTMODULES+=	crypt
endif
ifeq ($(TCLTK),yes)
  HARDEXTMODULES+=	_tkinter
  CFLAGS+=		-DHAS_DIRENT -I/TclTk80/include
  TK_LIBS+=		-L/TclTk80/lib -ltcl80 -ltk80
endif
ifeq ($(GMPZ),yes)
  HARDEXTMODULES+=	mpz
endif
ifeq ($(GREADLINE),yes)
  HARDEXTMODULES+=	readline
endif
ifeq ($(BSDDB),yes)
  HARDEXTMODULES+=	bsddb
endif
ifeq ($(CURSES),yes)
  HARDEXTMODULES+=	_curses _curses_
endif
ifeq ($(EXPAT),yes)
  HARDEXTMODULES+=	pyexpat
endif
ifeq ($(GDBM),yes)
  HARDEXTMODULES+=	gdbm dbm
endif

EXTERNDLLS=	$(addsuffix $(MODULE.EXT),$(patsubst %module,%,$(EASYEXTMODULES)))
EXTERNDLLS+=	$(addsuffix $(MODULE.EXT),$(patsubst %module,%,$(HARDEXTMODULES)))

# Targets
all:  $(OUT) $(PYTHON.LIB) $(PYTHON.DEF) $(PYTHON.IMPLIB) $(PYTHON.DLL) \
  $(PYTHON.EXE) $(PYTHONPM.EXE) $(PGEN.EXE) $(EXTERNDLLS)

clean:
	rm -f $(OUT)*
	rm -f $(PYTHON.LIB) $(PYTHON.IMPLIB) $(PYTHON.EXEIMP) $(PYTHON.DLL) \
	  $(PYTHON.EXE) $(PYTHONPM.EXE) $(PGEN.EXE) *$(MODULE.EXT)

lx:
	@echo Packing everything with lxLite...
	lxlite $(PYTHON.DLL) $(PYTHON.EXE) $(PYTHONPM.EXE) $(PGEN.EXE)

depend: $(OUTBASE)
	makedep -f $(OUTBASE)python.dep -o $(BUCK)O -p $(BUCK)\(OUT\) \
	  -r -c $(INCLUDE) $(SRC.LIB) $(SRC.PGEN)

$(OUT): $(OUTBASE)

$(OUT) $(OUTBASE):
	mkdir.exe $@

$(PYTHON.LIB): $(OBJ.LIB)
	rm.exe -f $@
	$(AR) $(ARFLAGS) $@ $^

$(PYTHON.DEF): $(PYTHON.LIB)
	@echo Creating .DEF file: $@
	@echo LIBRARY $(PYTHON_LIB) INITINSTANCE TERMINSTANCE >$@
	@echo DESCRIPTION $(DQUOTE)Python $(PYTHON_VER) Core DLL$(DQUOTE) >>$@
	@echo PROTMODE >>$@
	@echo DATA MULTIPLE NONSHARED >>$@
	@echo EXPORTS >>$@
	$(EXPLIB) -u $(PYTHON.LIB) >>$@

$(PYTHON.IMPLIB): $(PYTHON.DEF)
	$(IMPLIB) -o $@ $^

$(PYTHON.EXEIMP): $(PYTHON.DEF)
	$(IMPLIB) -o $@ $^

$(PYTHON.DLL): $(OUT)dllentry$O $(PYTHON.LIB) $(PYTHON.DEF)

# Explicit make targets for the .EXEs to be able to use LD to link
# (so that fork() will work if required)

$(PYTHON.EXE): $(SRC.EXE) $(PYTHON.EXEIMP) $(OUT)python.def
	$(CC) -Zmt $(LDMODE.EXE) -Zcrtdll -Wall $(INCLUDE) -L. -lgcc -o $@ $(SRC.EXE) $(PYTHON.EXEIMP) $(LIBS) $(OUT)python.def

$(PYTHONPM.EXE): $(SRC.PMEXE) $(PYTHON.EXEIMP) $(OUT)pythonpm.def
	$(CC) -Zmt $(LDMODE.EXE) -Zcrtdll -Wall $(INCLUDE) -L. -lgcc -o $@ $(SRC.PMEXE) $(PYTHON.EXEIMP) $(LIBS) $(OUT)pythonpm.def

$(PGEN.EXE): $(OBJ.PGEN) $(PYTHON.LIB) $(OUT)pgen.def

# Explicit building instructions for those external modules that require 
# awkward handling (due e.g. to non-std naming, or multiple source files)
# - standard modules
binascii$(MODULE.EXT): $(OUT)binascii$O $(OUT)binascii_m.def $(PYTHON.IMPLIB)
	$(LD) $(LDFLAGS.DLL) -o $@ $(^^) $(L^) $(LIBS)

cPickle$(MODULE.EXT): $(OUT)cPickle$O $(OUT)cPickle_m.def $(PYTHON.IMPLIB)
	$(LD) $(LDFLAGS.DLL) -o $@ $(^^) $(L^) $(LIBS)

# cStringIO needs to be renamed to be useful (8 char DLL name limit)
cStringIO$(MODULE.EXT): $(OUT)cStringIO$O $(OUT)cStringIO_m.def $(PYTHON.IMPLIB)
	$(LD) $(LDFLAGS.DLL) -o $@ $(^^) $(L^) $(LIBS)

cStringI$(MODULE.EXT): cStringIO$(MODULE.EXT)
	cp $^ $@

_hotshot$(MODULE.EXT): $(OUT)_hotshot$O $(OUT)_hotshot_m.def $(PYTHON.IMPLIB)
	$(LD) $(LDFLAGS.DLL) -o $@ $(^^) $(L^) $(LIBS)

imageop$(MODULE.EXT): $(OUT)imageop$O $(OUT)imageop_m.def $(PYTHON.IMPLIB)
	$(LD) $(LDFLAGS.DLL) -o $@ $(^^) $(L^) $(LIBS)

md5$(MODULE.EXT): $(OUT)md5module$O $(OUT)md5c$O $(OUT)md5_m.def $(PYTHON.IMPLIB)
	$(LD) $(LDFLAGS.DLL) -o $@ $(^^) $(L^) $(LIBS)

operator$(MODULE.EXT): $(OUT)operator$O $(OUT)operator_m.def $(PYTHON.IMPLIB)
	$(LD) $(LDFLAGS.DLL) -o $@ $(^^) $(L^) $(LIBS)

pcre$(MODULE.EXT): $(OUT)pcremodule$O $(OUT)pypcre$O $(OUT)pcre_m.def $(PYTHON.IMPLIB)
	$(LD) $(LDFLAGS.DLL) -o $@ $(^^) $(L^) $(LIBS)

regex$(MODULE.EXT): $(OUT)regexmodule$O $(OUT)regexpr$O $(OUT)regex_m.def $(PYTHON.IMPLIB)
	$(LD) $(LDFLAGS.DLL) -o $@ $(^^) $(L^) $(LIBS)

_socket$(MODULE.EXT): $(OUT)socketmodule$O $(OUT)_socket_m.def $(PYTHON.IMPLIB)
	$(LD) $(LDFLAGS.DLL) -o $@ $(^^) $(L^) $(LIBS)

# _symtable needs to be renamed to be useful
_symtable$(MODULE.EXT): $(OUT)symtablemodule$O $(OUT)_symtable_m.def $(PYTHON.IMPLIB)
	$(LD) $(LDFLAGS.DLL) -o $@ $(^^) $(L^) $(LIBS)

_symtabl$(MODULE.EXT): _symtable$(MODULE.EXT)
	cp $^ $@

termios$(MODULE.EXT): $(OUT)termios$O $(OUT)termios_m.def $(PYTHON.IMPLIB)
	$(LD) $(LDFLAGS.DLL) -o $@ $(^^) $(L^) $(LIBS)

# _testcapi needs to be renamed to be useful
_testcapi$(MODULE.EXT): $(OUT)_testcapimodule$O $(OUT)_testcapi_m.def $(PYTHON.IMPLIB)
	$(LD) $(LDFLAGS.DLL) -o $@ $(^^) $(L^) $(LIBS)

_testcap$(MODULE.EXT): _testcapi$(MODULE.EXT)
	cp $^ $@

# unicodedata needs to be renamed to be useful
unicodedata$(MODULE.EXT): $(OUT)unicodedata$O $(OUT)unicodedata_m.def $(PYTHON.IMPLIB)
	$(LD) $(LDFLAGS.DLL) -o $@ $(^^) $(L^) $(LIBS) $(MODULE_LIBS)

unicoded$(MODULE.EXT): unicodedata$(MODULE.EXT)
	cp $^ $@

_weakref$(MODULE.EXT): $(OUT)_weakref$O $(OUT)_weakref_m.def $(PYTHON.IMPLIB)
	$(LD) $(LDFLAGS.DLL) -o $@ $(^^) $(L^) $(LIBS)

# xreadlines needs to be renamed to be useful
xreadlines$(MODULE.EXT): $(OUT)xreadlinesmodule$O $(OUT)xreadlines_m.def $(PYTHON.IMPLIB)
	$(LD) $(LDFLAGS.DLL) -o $@ $(^^) $(L^) $(LIBS)

xreadlin$(MODULE.EXT): xreadlines$(MODULE.EXT)
	cp $^ $@

# - optional modules (requiring other software to be installed)
bsddb$(MODULE.EXT): $(OUT)bsddbmodule$O $(OUT)bsddb_m.def $(PYTHON.IMPLIB)
	$(LD) $(LDFLAGS.DLL) -o $@ $(^^) $(L^) -ldb $(LIBS)

crypt$(MODULE.EXT): $(OUT)cryptmodule$O $(OUT)crypt_m.def $(PYTHON.IMPLIB)
	$(LD) $(LDFLAGS.DLL) -o $@ $(^^) $(L^) -lufc $(LIBS)

# The _curses_panel module requires a couple of ncurses library entry
# points, which are best exposed as exports from the _curses module DLL
$(OUT)_curses_m.def:
	@echo Creating .DEF file: $@
	@echo LIBRARY $(notdir $*) INITINSTANCE TERMINSTANCE >$@
	@echo DESCRIPTION $(DQUOTE)$(DESCRIPTION.$(notdir $*)$(MODULE.EXT))$(DQUOTE) >>$@
	@echo DATA MULTIPLE NONSHARED >>$@
	@echo EXPORTS >>$@
	@echo 	init_curses >>$@
	@echo 	wnoutrefresh >>$@
	@echo 	_nc_panelhook >>$@
	@echo 	is_linetouched >>$@
	@echo 	mvwin >>$@
	@echo 	stdscr >>$@
	@echo 	wtouchln >>$@

$(OUT)_curses_panel_m.def:
	@echo Creating .DEF file: $@
	@echo LIBRARY $(notdir $*) INITINSTANCE TERMINSTANCE >$@
	@echo DESCRIPTION $(DQUOTE)Python standard module $(notdir $*)$(DQUOTE) >>$@
	@echo DATA MULTIPLE NONSHARED >>$@
	@echo IMPORTS >>$@
	@echo 	_curses.wnoutrefresh >>$@
	@echo 	_curses._nc_panelhook >>$@
	@echo 	_curses.is_linetouched >>$@
	@echo 	_curses.mvwin >>$@
	@echo 	_curses.stdscr >>$@
	@echo 	_curses.wtouchln >>$@
	@echo EXPORTS >>$@
	@echo 	init_curses_panel >>$@

_curses$(MODULE.EXT): $(OUT)_cursesmodule$O $(OUT)_curses_m.def $(PYTHON.IMPLIB)
	$(LD) $(LDFLAGS.DLL) -o $@ $(^^) $(L^) $(LIBS) -lncurses

# curses_panel needs to be renamed to be useful
_curses_panel$(MODULE.EXT): $(OUT)_curses_panel$O $(OUT)_curses_panel_m.def $(PYTHON.IMPLIB)
	$(LD) $(LDFLAGS.DLL) -o $@ $(^^) $(L^) $(LIBS) -lpanel

_curses_$(MODULE.EXT): _curses_panel$(MODULE.EXT)
	cp $^ $@

dbm$(MODULE.EXT): $(OUT)dbmmodule$O $(OUT)dbm_m.def $(PYTHON.IMPLIB)
	$(LD) $(LDFLAGS.DLL) -o $@ $(^^) $(L^) $(LIBS) -lgdbm

gdbm$(MODULE.EXT): $(OUT)gdbmmodule$O $(OUT)gdbm_m.def $(PYTHON.IMPLIB)
	$(LD) $(LDFLAGS.DLL) -o $@ $(^^) $(L^) $(LIBS) -lgdbm

mpz$(MODULE.EXT): $(OUT)mpzmodule$O $(OUT)mpz_m.def $(PYTHON.IMPLIB)
	$(LD) $(LDFLAGS.DLL) -o $@ $(^^) $(L^) $(LIBS) -lgmp

pyexpat$(MODULE.EXT): $(OUT)pyexpat$O $(OUT)pyexpat_m.def $(PYTHON.IMPLIB)
	$(LD) $(LDFLAGS.DLL) -o $@ $(^^) $(L^) $(LIBS) -lexpat

readline$(MODULE.EXT): $(OUT)readline$O $(OUT)readline_m.def $(PYTHON.IMPLIB)
	$(LD) $(LDFLAGS.DLL) -o $@ $(^^) $(L^) $(LIBS) -lreadline -lncurses

#_tkinter$(MODULE.EXT): $(OUT)_tkinter$O $(OUT)tclNotify$O $(OUT)tkappinit$O
_tkinter$(MODULE.EXT): $(OUT)_tkinter$O $(OUT)tclNotify$O \
    $(OUT)_tkinter_m.def $(PYTHON.IMPLIB)
	$(LD) $(LDFLAGS.DLL) -o $@ $(^^) $(L^) $(LIBS) $(TK_LIBS)

zlib$(MODULE.EXT): $(OUT)zlibmodule$O $(OUT)zlib_m.def $(PYTHON.IMPLIB)
	$(LD) $(LDFLAGS.DLL) -o $@ $(^^) $(L^) $(LIBS) -lz

# the test target
test:
	./python -tt ../../lib/test/regrtest.py -l -u "network"

-include $(OUTBASE)python.dep

--- NEW FILE: README.os2emx ---
This is a port of Python 2.3 to OS/2 using the EMX development tools
=========================================================================

What's new since the previous release
-------------------------------------

This release of the port incorporates the following changes from the 
December 24, 2001 release of the Python 2.2 port:

- based on the Python v2.3 final release source.
  

Licenses and info about Python and EMX
--------------------------------------

Please read the file README.Python-2.3 included in this package for 
information about Python 2.3.  This file is the README file from the 
Python 2.3 source distribution available via http://www.python.org/ 
and its mirrors.  The file LICENCE.Python-2.3 is the text of the Licence 
from the Python 2.3 source distribution.

Note that the EMX package that this package depends on is released under 
the GNU General Public Licence.  Please refer to the documentation 
accompanying the EMX Runtime libraries for more information about the 
implications of this.  A copy of version 2 of the GPL is included as the 
file COPYING.gpl2.

Readline and GDBM are covered by the GNU General Public Licence.  I think 
Eberhard Mattes' porting changes to BSD DB v1.85 are also GPL'ed (BSD DB 
itself is BSD Licenced).  ncurses and expat appear to be covered by MIT 
style licences - please refer to the source distributions for more detail.  
zlib is distributable under a very free license.  GNU MP and GNU UFC are 
under the GNU LGPL (see file COPYING.lib).

My patches to the Python-2.x source distributions, and any other packages 
used in this port, are placed in the public domain.

This software is provided 'as-is', without any express or implied warranty.
In no event will the author be held liable for any damages arising from the 
use of the software.

I do hope however that it proves useful to someone.


Other ports
-----------

There have been ports of previous versions of Python to OS/2.

The best known would be that by Jeff Rush, most recently of version 
1.5.2.  Jeff used IBM's Visual Age C++ (v3) for his ports, and his 
patches have been included in the Python 2.3 source distribution.

Andrew Zabolotny implemented a port of Python v1.5.2 using the EMX 
development tools.  His patches against the Python v1.5.2 source 
distribution have become the core of this port, and without his efforts 
this port wouldn't exist.  Andrew's port also appears to have been 
compiled with his port of gcc 2.95.2 to EMX, which I have but have 
chosen not to use for the binary distribution of this port (see item 21 
of the "YOU HAVE BEEN WARNED" section below).

Previous Python port releases by me:-
 - v2.0 on March 31, 2001;
 - v2.0 on April 25, 2001 (cleanup release + Stackless variant);
 - v2.1 on June 17, 2001;
 - v2.0 (Stackless re-release) on June 18, 2001.
 - v2.1.1 on August 5, 2001;
 - v2.1.1 on August 12, 2001 (cleanup release);
 - v2.1.1 (updated DLL) on August 14, 2001.
 - v2.2b2 on December 8, 2001 (not uploaded to archive sites)
 - v2.2c1 on December 16, 2001 (not uploaded to archive sites)
 - v2.2 on December 24, 2001

It is possible to have these earlier ports still usable after installing 
this port - see the README.os2emx.multiple_versions file, contributed by
Dr David Mertz, for a suggested approach to achieving this.


Software requirements
---------------------

This package requires the EMX Runtime package, available from the 
Hobbes (http://hobbes.nmsu.edu/) and LEO (http://archiv.leo.org/) 
archives of OS/2 software.  I have used EMX version 0.9d fix04 in 
developing this port.

My development system is running OS/2 v4 with fixpack 12.

3rd party software which has been linked into dynamically loaded modules:
- ncurses      (see http://dickey.his.com/ for more info, v5.2)
- GNU Readline (Kai Uwe Rommel's port available from Hobbes or LEO, v2.1)
- GNU GDBM     (Kai Uwe Rommel's port available from Hobbes or LEO, v1.7.3)
- zlib         (Hung-Chi Chu's port available from Hobbes or LEO, v1.1.3)
- expat        (from ftp://ftp.jclark.com/pub/xml/, v1.2)
- GNU MP       (Peter Meerwald's port available from LEO, v2.0.2)
- GNU UFC      (Kai Uwe Rommel's port available from LEO, v2.0.4)

The zlib module requires the Z.DLL to be installed - see the Installation 
section and item 12 of the "YOU HAVE BEEN WARNED" section for more 
information.

About this port
---------------

I have attempted to make this port as complete and functional as I can, 
notwithstanding the issues in the "YOU HAVE BEEN WARNED" section below.

Core components:

Python.exe is linked as an a.out executable, ie using EMX method E1 
to compile & link the executable.  This is so that fork() works (see 
"YOU HAVE BEEN WARNED" item 2).

Python23.dll is created as a normal OMF DLL, with an OMF import 
library and module definition file.  There is also an a.out (.a) import 
library to support linking the DLL to a.out executables.

This port has been built with complete support for multithreading.

Modules:

As far as possible, extension modules have been made dynamically loadable 
when the module is intended to be built this way.  I haven't yet changed 
the building of Python's standard modules over to using the DistUtils.

See "YOU HAVE BEEN WARNED" item 5 for notes about the fcntl module, and 
"YOU HAVE BEEN WARNED" item 14 for notes about the pwd and grp modules.

Support for case sensitive module import semantics has been added to match 
the Windows release.  This can be deactivated by setting the PYTHONCASEOK 
environment variable (the value doesn't matter) - see "YOU HAVE BEEN WARNED" 
item 16.

Optional modules:

Where I've been able to locate the required 3rd party packages already 
ported to OS/2, I've built and included them.

These include ncurses (_curses, _curses_panel), BSD DB (bsddb), 
GNU GDBM (gdbm, dbm), zlib (zlib), GNU Readline (readline), expat 
(pyexpat), GNU MP (mpz) and GNU UFC (crypt).

I have built these modules statically linked against the 3rd party 
libraries, with the exception of zlib.  Unfortunately my attempts to use 
the dll version of GNU readline have been a dismal failure, in that when 
the dynamically linked readline module is active other modules 
immediately provoke a core dump when imported.

Only the BSD DB package (part of the BSD package distributed with EMX) 
needed source modifications to be used for this port, pertaining to use 
of errno with multithreading.

The other packages, except for ncurses and zlib, needed Makefile changes 
for multithreading support but no source changes.

The _curses_panel module is a potential problem - see "YOU HAVE BEEN 
WARNED" item 17.

Upstream source patches:

No updates to the Python 2.3 release have become available.

Eberhard Mattes' EMXFIX04 update to his EMX 0.9d tools suite includes 
bug fixes for the BSD DB library.  The bsddb module included in this 
port incorporates these fixes.

Library and other distributed Python code:

The Python standard library lives in the Lib directory.  All the standard 
library code included with the Python 2.3 source distribution is included 
in the binary archive, with the exception of the dos-8x3 and tkinter 
subdirectories which have been omitted to reduce the size of the binary 
archive - the dos-8x3 components are unnecessary duplicates and Tkinter 
is not supported by this port (yet).  All the plat-* subdirectories in the 
source distribution have also been omitted, and a plat-os2emx directory 
included.

The Tools and Demo directories contain a collection of Python scripts.  
To reduce the size of the binary archive, the Demo/sgi, Demo/Tix, 
Demo/tkinter, Tools/audiopy and Tools/IDLE subdirectories have been 
omitted as not being supported by this port.  The Misc directory has 
also been omitted.

All subdirectories omitted from the binary archive can be reconstituted 
from the Python 2.3 source distribution, if desired.

Support for building Python extensions:

The Config subdirectory contains the files describing the configuration 
of the interpreter and the Makefile, import libraries for the Python DLL, 
and the module definition file used to create the Python DLL.  The 
Include subdirectory contains all the standard Python header files 
needed for building extensions.

As I don't have the Visual Age C++ compiler, I've made no attempt to 
have this port support extensions built with that compiler.


Packaging
---------

This port is packaged into several archives:
- python-2.3-os2emx-bin-02????.zip   (binaries, library modules)
- python-2.3-os2emx-src-03????.zip   (source patches and makefiles)

Documentation for the Python language, as well as the Python 2.3 
source distibution, can be obtained from the Python website 
(http://www.python.org/) or the Python project pages at Sourceforge 
(http://sf.net/projects/python/).


Installation
------------

Obtain and install, as per the included instructions, the EMX runtime 
package.

If you wish to use the zlib module, you will need to obtain and install 
the Z.DLL from Hung-Chi Chu's port of zlib v1.1.3 (zlib113.zip).  See also 
"YOU HAVE BEEN WARNED" item 12 below.

Unpack this archive, preserving the subdirectories, in the root directory 
of the drive where you want Python to live.

Add the Python directory (eg C:\Python23) to the PATH and LIBPATH 
variables in CONFIG.SYS.

You should then set the PYTHONHOME and PYTHONPATH environment variables 
in CONFIG.SYS.

PYTHONHOME should be set to Python's top level directory.  PYTHONPATH 
should be set to the semicolon separated list of principal Python library 
directories.
I use:
  SET PYTHONHOME=F:/Python23
  SET PYTHONPATH=F:/Python23/Lib;F:/Python23/Lib/plat-os2emx;
                 F:/Python23/Lib/lib-dynload;F:/Python23/Lib/site-packages

NOTE!:  the PYTHONPATH setting above is linewrapped for this document - it 
should all be on one line in CONFIG.SYS!

If you wish to use the curses module, you should set the TERM and TERMINFO 
environment variables appropriately.

If you don't already have ncurses installed, I have included a copy of the 
EMX subset of the Terminfo database included with the ncurses-5.2 source 
distribution.  This can be used by setting the TERMINFO environment variable 
to the path of the Terminfo subdirectory below the Python home directory.
On my system this looks like:
  SET TERMINFO=F:/Python23/Terminfo

For the TERM environment variable, I would try one of the following:
  SET TERM=ansi
  SET TERM=os2
  SET TERM=window

You will have to reboot your system for these changes to CONFIG.SYS to take 
effect.

If you wish to compile all the included Python library modules to bytecode, 
you can change into the Python home directory and run the COMPILEALL.CMD 
batch file.

You can execute the regression tests included with the Python 2.3 source 
distribution by changing to the Python 2.3 home directory and executing the 
REGRTEST.CMD batch file.  The following tests are known to fail at this 
time:
- test_longexp (see "YOU HAVE BEEN WARNED" item 1);
- test_mhlib (I don't know of any port of MH to OS/2);
- test_pwd (see "YOU HAVE BEEN WARNED" item 14, probably a bug in my code);
- test_grp (as per test_pwd);
- test_strftime (see "YOU HAVE BEEN WARNED" item 20);
- test_socketserver (fork() related, see "YOU HAVE BEEN WARNED" item 2).


YOU HAVE BEEN WARNED!!
----------------------

I know about a number of nasties in this port.

1.  EMX's malloc() and/or the underlying OS/2 VM system aren't particularly 
comfortable with Python's use of heap memory.  The test_longexp regression 
test exhausts the available swap space on a machine with 64MB of RAM with 
150MB of available swap space.

Using a crudely instrumented wrapper around malloc()/realloc()/free(), the 
heap memory usage of the expression at the core of the test 
(eval('[' + '2,' * NUMREPS + ']')) is as follows (approximately):
  NUMREPS = 1       => 300k
  NUMREPS = 10000   => 22MB
  NUMREPS = 20500   => 59MB

I don't even have enough memory to try for NUMREPS = 25000 :-(, let alone 
the NUMREPS = 65580 in test_longexp!  I do have a report that the test 
succeeds in the presence of sufficient memory (~200MB RAM).

During the course of running the test routine, the Python parser 
allocates lots of 21 byte memory chunks, each of which is actually 
a 64 byte allocation.  There are a smaller number of 3 byte allocations 
which consume 12 bytes each.  Consequently, more than 3 times as much 
memory is allocated than is actually used.

The Python Object Allocator code (PyMalloc) was introduced in Python 2.1 
for Python's core to be able to wrap the malloc() system to deal with 
problems with "unfriendly" malloc() behaviour, such as this.  Unfortunately 
for the OS/2 port, it is only supported for the allocation of memory for 
objects, whereas my research into this problem indicates it is the parser 
which is source of this particular malloc() frenzy.

I have attempted using PyMalloc to manage all of Python's memory 
allocation.  While this works fine (modulo the socket regression test 
failing in the absence of a socket.pyc), it is a significant performance 
hit - the time to run the regression test blows out from ~3.5 minutes to 
~5.75 minutes on my system.

I therefore don't plan to pursue this any further for the time being.

Be aware that certain types of expressions could well bring your system 
to its knees as a result of this issue.  I have modified the longexp test 
to report failure to highlight this.

2.  Eberhard Mattes, author of EMX, writes in his documentation that fork() 
is very inefficient in the OS/2 environment.  It also requires that the 
executable be linked in a.out format rather than OMF.  Use the os.exec 
and/or the os.spawn family of functions where possible.

{3.  Issue resolved...}

4.  In the absence of GNU Readline, terminating the interpreter requires a 
control-Z (^Z) followed by a carriage return.  Jeff Rush documented this 
problem in his Python 1.5.2 port.  With Readline, a control-D (^D) works 
as per the standard Unix environment.

5.  EMX only has a partial implementation of fcntl().  The fcntl module 
in this port supports what EMX supports.  If fcntl is important to you, 
please review the EMX C Library Reference (included in .INF format in the 
EMXVIEW.ZIP archive as part of the complete EMX development tools suite).
Because of other side-effects I have modified the test_fcntl.py test 
script to deactivate the exercising of the missing functionality.

6.  The BSD DB module is linked against DB v1.85.  This version is widely 
known to have bugs, although some patches have become available (and are 
incorporated into the included bsddb module).  Unless you have problems 
with software licenses which would rule out GDBM (and the dbm module 
because it is linked against the GDBM library) or need it for file format 
compatibility, you may be better off deleting it and relying on GDBM.  I 
haven't looked at porting the version of the module supporting the later 
SleepyCat releases of BSD DB, which would also require a port of the 
SleepyCat DB package.

7.  The readline module has been linked against ncurses rather than the 
termcap library supplied with EMX.

{8.  Workaround implemented}

9.  I have configured this port to use "/" as the preferred path separator 
character, rather than "\" ('\\'), in line with the convention supported 
by EMX.  Backslashes are still supported of course, and still appear in 
unexpected places due to outside sources that don't get normalised.

10. While the DistUtils components are now functional, other 
packaging/binary handling tools and utilities such as those included in
the Demo and Tools directories - freeze in particular - are unlikely to 
work.  If you do get them going, I'd like to know about your success.

11. I haven't set out to support the [BEGIN|END]LIBPATH functionality 
supported by one of the earlier ports (Rush's??).  If it works let me know.

12. There appear to be several versions of Z.DLL floating around - the one 
I have is 45061 bytes and dated January 22, 1999.  I have a report that 
another version causes SYS3175s when the zlib module is imported.

14. As a result of the limitations imposed by EMX's library routines, the 
standard extension module pwd only synthesises a simple passwd database, 
and the grp module cannot be supported at all.

I have written substitutes, in Python naturally, which can process real 
passwd and group files for those applications (such as MailMan) that 
require more than EMX emulates.  I have placed pwd.py and grp.py in 
Lib/plat-os2emx, which is usually before Lib/lib-dynload (which contains 
pwd.pyd) in the PYTHONPATH.  If you have become attached to what pwd.pyd 
supports, you can put Lib/lib-dynload before Lib/plat-os2emx in PYTHONPATH 
or delete/rename pwd.py & grp.py.

pwd.py & grp.py support locating their data files by looking in the 
environment for them in the following sequence:
pwd.py:  $ETC_PASSWD             (%ETC_PASSWD%)
         $ETC/passwd             (%ETC%/passwd)
         $PYTHONHOME/Etc/passwd  (%PYTHONHOME%/Etc/passwd)
grp.py:  $ETC_GROUP              (%ETC_GROUP%)
         $ETC/group              (%ETC%/group)
         $PYTHONHOME/Etc/group   (%PYTHONHOME%/Etc/group)

Both modules support using either the ":" character (Unix standard) or 
";" (OS/2, DOS, Windows standard) field separator character, and pwd.py 
implements the following drive letter conversions for the home_directory and 
shell fields (for the ":" separator only):
         $x  ->  x:
         x;  ->  x:

Example versions of passwd and group are in the Etc subdirectory.  Note 
that as of this release, this code fails the regression test.  I'm looking 
into why, and hope to have this fixed.

15. As of Python 2.1, termios support has mutated.  There is no longer a 
platform specific TERMIOS.py containing the symbolic constants - these 
now live in the termios module.  EMX's termios routines don't support all 
of the functionality now exposed by the termios module - refer to the EMX 
documentation to find out what is supported.

16. The case sensitive import semantics introduced in Python 2.1 for other 
case insensitive but case preserving file/operating systems (Windows etc), 
have been incorporated into this port, and are active by default.  Setting 
the PYTHONCASEOK environment variable (to any value) reverts to the 
previous (case insensitive) semantics.

17. Because I am statically linking ncurses, the _curses_panel 
module has potential problems arising from separate library data areas.
To avoid this, I have configured the _curses_.pyd (imported as 
"_curses_panel") to import the ncurses symbols it needs from _curses.pyd. 
As a result the _curses module must be imported before the _curses_panel 
module.  As far as I can tell, the modules in the curses package do this. 
If you have problems attempting to use the _curses_panel support please 
let me know, and I'll look into an alternative solution.

18. I tried enabling the Python Object Allocator (PYMALLOC) code.  While 
the port built this way passes the regression test, the Numpy extension 
(I tested v19.0.0) as built with with the port's DistUtils code doesn't 
work.  Specifically, attempting to "import Numeric" provokes a core dump.  
Supposedly Numpy v20.1.0 contains a fix for this, but for reason outlined 
in item 1 above, PYMALLOC is not enabled in this release.

19. sys.platform now reports "os2emx" instead of "os2".  os.name still 
reports "os2".  This change was to make it easier to distinguish between 
the VAC++ build (being maintained by Michael Muller) and the EMX build 
(this port), principally for DistUtils.

20. it appears that the %W substitution in the EMX strftime() routine has 
an off-by-one bug.  strftime was listed as passing the regression tests 
in previous releases, but this fact appears to have been an oversight in 
the regression test suite.  To fix this really requires a portable 
strftime routine - I'm looking into using one from FreeBSD, but its not 
ready yet.

21. previous releases of my Python ports have used the GCC optimisations 
"-O2 -fomit-frame-pointer".  After experimenting with various optimisation 
settings, including deactivating assert()ions, I have concluded that "-O2" 
appears the best compromise for GCC 2.8.1 on my hardware.  Curiously, 
deactivating assert() (via defining NDEBUG) _negatively_ impacts 
performance, allbeit only slightly, so I've chosen to leave the assert()s 
active.

I did try using Andrew Zabolotny's (p)gcc 2.95.2 compiler, and in 
general concluded that it produced larger objects that ran slower 
than Mattes' gcc 2.8.1 compiler.

Pystone ratings varied from just over 2000/s (no optimisation at all) 
to just under 3300/s (gcc 2.8.1, -O2) on my K6/2-300 system, for 
100,000 iterations per run (rather than the default 10000).

As a result of the optimisation change, the Python DLL is about 10% 
smaller than in the 2.1 release, and many of the dynamically loadable 
modules are smaller too.

[2001/08/12]

22.  As of this release, os.spawnv() and os.spawnve() now expose EMX's 
library routines rather than use the emulation in os.py.

In order to make use of some of the features this makes available in 
the OS/2 environment, you should peruse the relevant EMX documentation 
(EMXLIB.INF in the EMXVIEW.ZIP archive accompanying the EMX archives 
on Hobbes or LEO).  Be aware that I have exposed all the "mode" options 
supported by EMX, but there are combinations that either cannot be 
practically used by/in Python or have the potential to compromise your 
system's stability.

23.  pythonpm.exe in previous releases was just python.exe with the 
WINDOWAPI linker option set in the pythonpm.def file.  In practice, 
this turns out to do nothing useful.

I have written a replacement which wraps the Python DLL in a genuine 
Presentation Manager application.  This version actually runs the 
Python interpreter in a separate thread from the PM shell, in order 
that PythonPM has a functioning message queue as good PM apps should.
In its current state, PythonPM's window is hidden.  It can be displayed, 
although it will have no content as nothing is ever written to the 
window.  Only the "hide" button is available.  Although the code 
has support for shutting PythonPM down when the Python interpreter is 
still busy (via the "control" menu), this is not well tested and given 
comments I've come across in EMX documentation suggesting that the 
thread killing operation has problems I would suggest caution in 
relying on this capability.

PythonPM processes commandline parameters normally.  The standard input, 
output and error streams are only useful if redirected, as PythonPM's 
window is not a console in any form and so cannot accept or display 
anything.  This means that the -i option is ineffective.

Because the Python thread doesn't create its own message queue, creating 
PM Windows and performing most PM operations is not possible from within 
this thread.  How this will affect supporting PM extensions (such as 
Tkinter using a PM port of Tcl/Tk, or wxPython using the PM port of 
WxWindows) is still being researched.

Note that os.fork() _DOES_NOT_WORK_ in PythonPM - SYS3175s are the result 
of trying.  os.spawnv() _does_ work.  PythonPM passes all regression tests 
that the standard Python interpreter (python.exe) passes, with the exception 
of test_fork1 and test_socket which both attempt to use os.fork().

I very much want feedback on the performance, behaviour and utility of 
PythonPM.  I would like to add a PM console capability to it, but that 
will be a non-trivial effort.  I may be able to leverage the code in 
Illya Vaes' Tcl/Tk port, which would make it easier.

[2001/08/14]

24.  os.chdir() now uses EMX's _chdir2(), which supports changing 
both drive and directory at once.  Similarly, os.getcwd() now uses 
EMX's _getcwd() which returns drive as well as path.

[2001/12/08] - 2.2 Beta 2

25.  pyconfig.h (previously known as config.h) is now located in the 
Include subdirectory with all other include files.

[2001/12/16] - 2.2 Release Candidate 1

[2001/12/08] - 2.2 Final

... probably other issues that I've not encountered, or don't remember :-(

If you encounter other difficulties with this port, which can be 
characterised as peculiar to this port rather than to the Python release,
I would like to hear about them.  However I cannot promise to be able to do 
anything to resolve such problems.  See the Contact section below...


To do...
--------

In no particular order of apparent importance or likelihood...

- support Tkinter and/or alternative GUI (wxWindows??)


Credits
-------

In addition to people identified above, I'd like to thank:
- the BDFL, Guido van Rossum, and crew for Python;
- Dr David Mertz, for trying out a pre-release of this port;
- the Python-list/comp.lang.python community;
- John Poltorak, for input about pwd/grp.

Contact
-------

Constructive feedback, negative or positive, about this port is welcome 
and should be addressed to me at the e-mail addresses below.

I intend creating a private mailing list for announcements of fixes & 
updates to this port.  If you wish to receive such e-mail announcments, 
please send me an e-mail requesting that you be added to this list.

Andrew MacIntyre
E-mail: andymac@bullseye.apana.org.au, or andymac@pcug.org.au
Web:    http://www.andymac.org/

24 December, 2001.

--- NEW FILE: config.c ---
/* -*- C -*- ***********************************************
Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
The Netherlands.

                        All Rights Reserved

Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the names of Stichting Mathematisch
Centrum or CWI or Corporation for National Research Initiatives or
CNRI not be used in advertising or publicity pertaining to
distribution of the software without specific, written prior
permission.

While CWI is the initial source for this software, a modified version
is made available by the Corporation for National Research Initiatives
(CNRI) at the Internet address ftp://ftp.python.org.

STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.

******************************************************************/

/* Module configuration */

/* This file contains the table of built-in modules.
   See init_builtin() in import.c. */

#include "Python.h"

extern void init_codecs();
extern void init_curses();
extern void init_curses_panel();
extern void init_hotshot();
extern void init_locale();
extern void init_socket();
extern void init_sre();
extern void init_testcapi();
extern void init_weakref();
extern void initarray();
extern void initbinascii();
extern void initbsddb();
extern void initcPickle();
extern void initcStringIO();
extern void initcmath();
extern void initdl();
extern void initerrno();
extern void initfcntl();
extern void initfpectl();
extern void initfpetest();
extern void initgc();
extern void initimageop();
extern void initmath();
extern void initmd5();
extern void initnew();
extern void initos2();
extern void initoperator();
extern void initparser();
extern void initpcre();
extern void initpwd();
extern void initregex();
extern void initrgbimg();
extern void initrotor();
extern void initselect();
extern void initsha();
extern void initsignal();
extern void initstrop();
extern void initstruct();
extern void inittermios();
extern void initthread();
extern void inittime();
extern void inittiming();
extern void initunicodedata();
extern void initxreadlines();
extern void initzlib();

/* -- ADDMODULE MARKER 1 -- */

extern void PyMarshal_Init();
extern void initimp();

struct _inittab _PyImport_Inittab[] = {

	{"gc", initgc},
        {"os2", initos2},
        {"_sre", init_sre},
        {"signal", initsignal},
#ifdef WITH_THREAD
        {"thread", initthread},
#endif
#if !HAVE_DYNAMIC_LOADING
	{"_codecs", init_codecs},
	{"_curses", init_curses},
	{"_curses_panel", init_curses_panel},
	{"_hotshot", init_hotshot},
	{"_locale", init_locale},
	{"_testcapi", init_testcapi},
	{"_weakref", init_weakref},
	{"array", initarray},
	{"binascii", initbinascii},
	{"bsddb", initbsddb},
	{"cPickle", initcPickle},
	{"cStringIO", initcStringIO},
	{"cmath", initcmath},
	{"dl", initdl},
	{"errno", initerrno},
	{"fcntl", initfcntl},
	{"fpectl", initfpectl},
	{"fpetest", initfpetest},
	{"imageop", initimageop},
	{"math", initmath},
	{"md5", initmd5},
	{"new", initnew},
	{"operator", initoperator},
	{"parser", initparser},
	{"pcre", initpcre},
	{"pwd", initpwd},
	{"regex", initregex},
	{"rgbimg", initrgbimg},
	{"rotor", initrotor},
	{"sha", initsha},
	{"strop", initstrop},
	{"struct", initstruct},
	{"termios", inittermios},
	{"time", inittime},
	{"timing", inittiming},
	{"unicodedata", initunicodedata},
	{"xreadlines", initxreadlines},
	{"zlib", initzlib},
#ifdef USE_SOCKET
        {"_socket", init_socket},
        {"select", initselect},
#endif
#endif

/* -- ADDMODULE MARKER 2 -- */

        /* This module "lives in" with marshal.c */
        {"marshal", PyMarshal_Init},

        /* This lives it with import.c */
        {"imp", initimp},

        /* These entries are here for sys.builtin_module_names */
        {"__main__", NULL},
        {"__builtin__", NULL},
        {"sys", NULL},
        {"exceptions", NULL},

        /* Sentinel */
        {0, 0}
};

--- NEW FILE: dlfcn.c ---
/* -*- C -*- ***********************************************
Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
The Netherlands.

                        All Rights Reserved

Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the names of Stichting Mathematisch
Centrum or CWI or Corporation for National Research Initiatives or
CNRI not be used in advertising or publicity pertaining to
distribution of the software without specific, written prior
permission.

While CWI is the initial source for this software, a modified version
is made available by the Corporation for National Research Initiatives
(CNRI) at the Internet address ftp://ftp.python.org.

STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.

******************************************************************/

/*
    This library implements dlopen() - functions for OS/2 using
    DosLoadModule() and company.
*/

#define INCL_DOS
#define INCL_DOSERRORS
#define INCL_DOSSESMGR
#define INCL_WINPROGRAMLIST
#define INCL_WINFRAMEMGR
#include <os2.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>

/*-------------------------------------- Unix-like dynamic linking emulation -*/

typedef struct _track_rec {
	char *name;
	HMODULE handle;
	void *id;
	struct _track_rec *next;
} tDLLchain, *DLLchain;

static DLLchain dlload = NULL;		/* A simple chained list of DLL names */
static char dlerr [256];			    /* last error text string */
static void *last_id;

static DLLchain find_id(void *id)
{
	DLLchain tmp;

	for (tmp = dlload; tmp; tmp = tmp->next)
		if (id == tmp->id)
			return (tmp);

	return (NULL);
}

/* load a dynamic-link library and return handle */
void *dlopen (char *filename, int flags)
{
	HMODULE hm;
	DLLchain tmp;
	char err[256];
	char *errtxt;
	int rc = 0, set_chain = 0;

	for (tmp = dlload; tmp; tmp = tmp->next)
		if (strnicmp(tmp->name, filename, 999) == 0)
			break;

	if (!tmp)
	{
		tmp = (DLLchain)malloc (sizeof (tDLLchain));
		if (!tmp)
			goto nomem;
		tmp->name = strdup (filename);
		tmp->next = dlload;
		set_chain = 1;
	}

	switch (rc = DosLoadModule((PSZ)&err, sizeof(err), filename, &hm))
	{
		case NO_ERROR:
			tmp->handle = hm;
			if (set_chain) {
				do {
					last_id++;
				} while ((last_id == 0) || (find_id(last_id)));
				tmp->id = last_id;
				dlload = tmp;
			}
			return (tmp->id);
		case ERROR_FILE_NOT_FOUND:
		case ERROR_PATH_NOT_FOUND:
			errtxt = "module `%s' not found";
			break;
		case ERROR_TOO_MANY_OPEN_FILES:
		case ERROR_NOT_ENOUGH_MEMORY:
		case ERROR_SHARING_BUFFER_EXCEEDED:
nomem:
			errtxt = "out of system resources";
			break;
		case ERROR_ACCESS_DENIED:
			errtxt = "access denied";
			break;
		case ERROR_BAD_FORMAT:
		case ERROR_INVALID_SEGMENT_NUMBER:
		case ERROR_INVALID_ORDINAL:
		case ERROR_INVALID_MODULETYPE:
		case ERROR_INVALID_EXE_SIGNATURE:
		case ERROR_EXE_MARKED_INVALID:
		case ERROR_ITERATED_DATA_EXCEEDS_64K:
		case ERROR_INVALID_MINALLOCSIZE:
		case ERROR_INVALID_SEGDPL:
		case ERROR_AUTODATASEG_EXCEEDS_64K:
		case ERROR_RELOCSRC_CHAIN_EXCEEDS_SEGLIMIT:
			errtxt = "invalid module format";
			break;
		case ERROR_INVALID_NAME:
			errtxt = "filename doesn't match module name";
			break;
		case ERROR_SHARING_VIOLATION:
		case ERROR_LOCK_VIOLATION:
			errtxt = "sharing violation";
			break;
		case ERROR_INIT_ROUTINE_FAILED:
			errtxt = "module initialization failed";
			break;
		default:
			errtxt = "cause `%s', error code = %d";
			break;
	}
	snprintf (dlerr, sizeof (dlerr), errtxt, &err, rc);
	if (tmp) {
		if (tmp->name)
			free(tmp->name);
		free (tmp);
	}
	return (0);
}

/* return a pointer to the `symbol' in DLL */
void *dlsym (void *handle, char *symbol)
{
	int rc = 0;
	PFN addr;
	char *errtxt;
	int symord = 0;
	DLLchain tmp = find_id (handle);

	if (!tmp)
		goto inv_handle;

	if (*symbol == '#')
		symord = atoi (symbol + 1);

	switch (rc = DosQueryProcAddr(tmp->handle, symord, symbol, &addr))
	{
		case NO_ERROR:
			return ((void *)addr);
		case ERROR_INVALID_HANDLE:
inv_handle:
			errtxt = "invalid module handle";
			break;
		case ERROR_PROC_NOT_FOUND:
		case ERROR_INVALID_NAME:
			errtxt = "no symbol `%s' in module";
			break;
		default:
			errtxt = "symbol `%s', error code = %d";
			break;
	}
	snprintf (dlerr, sizeof (dlerr), errtxt, symbol, rc);
	return (NULL);
}

/* free dynamicaly-linked library */
int dlclose (void *handle)
{
	int rc;
	DLLchain tmp = find_id (handle);

	if (!tmp)
		goto inv_handle;

	switch (rc = DosFreeModule (tmp->handle))
	{
		case NO_ERROR:
			free (tmp->name);
			dlload = tmp->next;
			free (tmp);
			return (0);
		case ERROR_INVALID_HANDLE:
inv_handle:
			strcpy(dlerr, "invalid module handle");
			return (-1);
		case ERROR_INVALID_ACCESS:
			strcpy (dlerr, "access denied");
			return (-1);
		default:
			return (-1);
	}
}

/* return a string describing last occured dl error */
char *dlerror()
{
	return (dlerr);
}

--- NEW FILE: dlfcn.h ---
/* -*- C -*- ***********************************************
Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
The Netherlands.

                        All Rights Reserved

Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the names of Stichting Mathematisch
Centrum or CWI or Corporation for National Research Initiatives or
CNRI not be used in advertising or publicity pertaining to
distribution of the software without specific, written prior
permission.

While CWI is the initial source for this software, a modified version
is made available by the Corporation for National Research Initiatives
(CNRI) at the Internet address ftp://ftp.python.org.

STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.

******************************************************************/

/*
    This library implements dlopen() - functions for OS/2 using
    DosLoadModule() and company.
*/

#ifndef _DLFCN_H
#define _DLFCN_H

/*-------------------------------------- Unix-like dynamic linking emulation -*/
/* load a dynamic-link library and return handle */
void *dlopen (char *filename, int flags);
/* return a pointer to the `symbol' in DLL */
void *dlsym (void *handle, char *symbol);
/* free dynamicaly-linked library */
int dlclose (void *handle);
/* return a string describing last occured dl error */
char *dlerror(void);

#endif /* !_DLFCN_H */

--- NEW FILE: dllentry.c ---
/*
    This is the entry point for Python DLL(s).
    It also provides an getenv() function that works from within DLLs.
*/

#define NULL 0

/* Make references to imported symbols to pull them from static library */
#define REF(s)	extern void s (); void *____ref_##s = &s;

REF (Py_Main);

#if defined (__EMX__)

#include <signal.h>

extern int _CRT_init (void);
extern void _CRT_term (void);
extern void __ctordtorInit (void);
extern void __ctordtorTerm (void);

unsigned long _DLL_InitTerm (unsigned long mod_handle, unsigned long flag)
{
  switch (flag)
  {
    case 0:
      if (_CRT_init ()) return 0;
      __ctordtorInit ();
      /* Ignore fatal signals */
      signal (SIGSEGV, SIG_IGN);
      signal (SIGFPE, SIG_IGN);
      return 1;
    case 1:
      __ctordtorTerm ();
      _CRT_term ();
      return 1;
    default:
      return 0;
  }
}

#endif

/* A version of getenv() that works from DLLs */
extern int DosScanEnv (const char *pszName, char **ppszValue);

char *getenv (const char *name)
{
  char *value;
  if (DosScanEnv (name, &value))
    return NULL;
  else
    return value;
}

--- NEW FILE: getpathp.c ---

/* Return the initial module search path. */
/* This version used by OS/2+EMX */

/* ----------------------------------------------------------------
   PATH RULES FOR OS/2+EMX:
   This describes how sys.path is formed on OS/2+EMX.  It describes the 
   functionality, not the implementation (ie, the order in which these 
   are actually fetched is different)

   * Python always adds an empty entry at the start, which corresponds
     to the current directory.

   * If the PYTHONPATH env. var. exists, it's entries are added next.

   * We attempt to locate the "Python Home" - if the PYTHONHOME env var
     is set, we believe it.  Otherwise, we use the path of our host .EXE's
     to try and locate our "landmark" (lib\\os.py) and deduce our home.
     - If we DO have a Python Home: The relevant sub-directories (Lib, 
       plat-win, lib-tk, etc) are based on the Python Home
     - If we DO NOT have a Python Home, the core Python Path is
       loaded from the registry.  This is the main PythonPath key, 
       and both HKLM and HKCU are combined to form the path)

   * Iff - we can not locate the Python Home, and have not had a PYTHONPATH
     specified (ie, we have _nothing_ we can assume is a good path), a
     default path with relative entries is used (eg. .\Lib;.\plat-win, etc)


  The end result of all this is:
  * When running python.exe, or any other .exe in the main Python directory
    (either an installed version, or directly from the PCbuild directory),
    the core path is deduced.

  * When Python is hosted in another exe (different directory, embedded via 
    COM, etc), the Python Home will not be deduced, so the core path from
    the registry is used.  Other "application paths "in the registry are 
    always read.

  * If Python can't find its home and there is no registry (eg, frozen
    exe, some very strange installation setup) you get a path with
    some default, but relative, paths.

   ---------------------------------------------------------------- */


#include "Python.h"
#include "osdefs.h"

#ifndef PYOS_OS2
#error This file only compilable on OS/2
#endif

#define INCL_DOS
#include <os2.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>

#if HAVE_UNISTD_H
#include <unistd.h>
#endif /* HAVE_UNISTD_H */

/* Search in some common locations for the associated Python libraries.
 *
 * Py_GetPath() tries to return a sensible Python module search path.
 *
 * The approach is an adaptation for Windows of the strategy used in
 * ../Modules/getpath.c; it uses the Windows Registry as one of its
 * information sources.
 */

#ifndef LANDMARK
#if defined(PYCC_GCC)
#define LANDMARK "lib/os.py"
#else
#define LANDMARK "lib\\os.py"
#endif
#endif

static char prefix[MAXPATHLEN+1];
static char progpath[MAXPATHLEN+1];
static char *module_search_path = NULL;


static int
is_sep(char ch)	/* determine if "ch" is a separator character */
{
#ifdef ALTSEP
	return ch == SEP || ch == ALTSEP;
#else
	return ch == SEP;
#endif
}

/* assumes 'dir' null terminated in bounds.  Never writes
   beyond existing terminator.
*/
static void
reduce(char *dir)
{
	size_t i = strlen(dir);
	while (i > 0 && !is_sep(dir[i]))
		--i;
	dir[i] = '\0';
}
	
static int
exists(char *filename)
{
	struct stat buf;
	return stat(filename, &buf) == 0;
}

/* Assumes 'filename' MAXPATHLEN+1 bytes long - 
   may extend 'filename' by one character.
*/
static int
ismodule(char *filename)	/* Is module -- check for .pyc/.pyo too */
{
	if (exists(filename))
		return 1;

	/* Check for the compiled version of prefix. */
	if (strlen(filename) < MAXPATHLEN) {
		strcat(filename, Py_OptimizeFlag ? "o" : "c");
		if (exists(filename))
			return 1;
	}
	return 0;
}

/* guarantees buffer will never overflow MAXPATHLEN+1 bytes */
static void
join(char *buffer, char *stuff)
{
	size_t n, k;
	if (is_sep(stuff[0]))
		n = 0;
	else {
		n = strlen(buffer);
		if (n > 0 && !is_sep(buffer[n-1]) && n < MAXPATHLEN)
			buffer[n++] = SEP;
	}
	k = strlen(stuff);
	if (n + k > MAXPATHLEN)
		k = MAXPATHLEN - n;
	strncpy(buffer+n, stuff, k);
	buffer[n+k] = '\0';
}

/* gotlandmark only called by search_for_prefix, which ensures
   'prefix' is null terminated in bounds.  join() ensures
   'landmark' can not overflow prefix if too long.
*/
static int
gotlandmark(char *landmark)
{
	int n, ok;

	n = strlen(prefix);
	join(prefix, landmark);
	ok = ismodule(prefix);
	prefix[n] = '\0';
	return ok;
}

/* assumes argv0_path is MAXPATHLEN+1 bytes long, already \0 term'd. 
   assumption provided by only caller, calculate_path() */
static int
search_for_prefix(char *argv0_path, char *landmark)
{
	/* Search from argv0_path, until landmark is found */
	strcpy(prefix, argv0_path);
	do {
		if (gotlandmark(landmark))
			return 1;
		reduce(prefix);
	} while (prefix[0]);
	return 0;
}


static void
get_progpath(void)
{
	extern char *Py_GetProgramName(void);
	char *path = getenv("PATH");
	char *prog = Py_GetProgramName();

	PPIB pib;
	if ((DosGetInfoBlocks(NULL, &pib) == 0) &&
	    (DosQueryModuleName(pib->pib_hmte, sizeof(progpath), progpath) == 0))
		return;

	if (prog == NULL || *prog == '\0')
		prog = "python";

	/* If there is no slash in the argv0 path, then we have to
	 * assume python is on the user's $PATH, since there's no
	 * other way to find a directory to start the search from.  If
	 * $PATH isn't exported, you lose.
	 */
#ifdef ALTSEP
	if (strchr(prog, SEP) || strchr(prog, ALTSEP))
#else
	if (strchr(prog, SEP))
#endif
		strncpy(progpath, prog, MAXPATHLEN);
	else if (path) {
		while (1) {
			char *delim = strchr(path, DELIM);

			if (delim) {
				size_t len = delim - path;
				/* ensure we can't overwrite buffer */
#if !defined(PYCC_GCC)
				len = min(MAXPATHLEN,len);
#else
				len = MAXPATHLEN < len ? MAXPATHLEN : len;
#endif
				strncpy(progpath, path, len);
				*(progpath + len) = '\0';
			}
			else
				strncpy(progpath, path, MAXPATHLEN);

			/* join() is safe for MAXPATHLEN+1 size buffer */
			join(progpath, prog);
			if (exists(progpath))
				break;

			if (!delim) {
				progpath[0] = '\0';
				break;
			}
			path = delim + 1;
		}
	}
	else
		progpath[0] = '\0';
}

static void
calculate_path(void)
{
	char argv0_path[MAXPATHLEN+1];
	char *buf;
	size_t bufsz;
	char *pythonhome = Py_GetPythonHome();
	char *envpath = getenv("PYTHONPATH");

	get_progpath();
	/* progpath guaranteed \0 terminated in MAXPATH+1 bytes. */
	strcpy(argv0_path, progpath);
	reduce(argv0_path);
	if (pythonhome == NULL || *pythonhome == '\0') {
		if (search_for_prefix(argv0_path, LANDMARK))
			pythonhome = prefix;
		else
			pythonhome = NULL;
	}
	else
		strncpy(prefix, pythonhome, MAXPATHLEN);

	if (envpath && *envpath == '\0')
		envpath = NULL;

	/* We need to construct a path from the following parts.
	   (1) the PYTHONPATH environment variable, if set;
	   (2) the PYTHONPATH config macro, with the leading "."
	       of each component replaced with pythonhome, if set;
	   (3) the directory containing the executable (argv0_path).
	   The length calculation calculates #2 first.
	*/

	/* Calculate size of return buffer */
	if (pythonhome != NULL) {
		char *p;
		bufsz = 1;	
		for (p = PYTHONPATH; *p; p++) {
			if (*p == DELIM)
				bufsz++; /* number of DELIM plus one */
		}
		bufsz *= strlen(pythonhome);
	}
	else
		bufsz = 0;
	bufsz += strlen(PYTHONPATH) + 1;
	bufsz += strlen(argv0_path) + 1;
	if (envpath != NULL)
		bufsz += strlen(envpath) + 1;

	module_search_path = buf = malloc(bufsz);
	if (buf == NULL) {
		/* We can't exit, so print a warning and limp along */
		fprintf(stderr, "Can't malloc dynamic PYTHONPATH.\n");
		if (envpath) {
			fprintf(stderr, "Using environment $PYTHONPATH.\n");
			module_search_path = envpath;
		}
		else {
			fprintf(stderr, "Using default static path.\n");
			module_search_path = PYTHONPATH;
		}
		return;
	}

	if (envpath) {
		strcpy(buf, envpath);
		buf = strchr(buf, '\0');
		*buf++ = DELIM;
	}

	if (pythonhome == NULL) {
		strcpy(buf, PYTHONPATH);
		buf = strchr(buf, '\0');
	}
	else {
		char *p = PYTHONPATH;
		char *q;
		size_t n;
		for (;;) {
			q = strchr(p, DELIM);
			if (q == NULL)
				n = strlen(p);
			else
				n = q-p;
			if (p[0] == '.' && is_sep(p[1])) {
				strcpy(buf, pythonhome);
				buf = strchr(buf, '\0');
				p++;
				n--;
			}
			strncpy(buf, p, n);
			buf += n;
			if (q == NULL)
				break;
			*buf++ = DELIM;
			p = q+1;
		}
	}
	if (argv0_path) {
		*buf++ = DELIM;
		strcpy(buf, argv0_path);
		buf = strchr(buf, '\0');
	}
	*buf = '\0';
}


/* External interface */

char *
Py_GetPath(void)
{
	if (!module_search_path)
		calculate_path();
	return module_search_path;
}

char *
Py_GetPrefix(void)
{
	if (!module_search_path)
		calculate_path();
	return prefix;
}

char *
Py_GetExecPrefix(void)
{
	return Py_GetPrefix();
}

char *
Py_GetProgramFullPath(void)
{
	if (!module_search_path)
		calculate_path();
	return progpath;
}

--- NEW FILE: pyconfig.h ---
#ifndef Py_CONFIG_H
#define Py_CONFIG_H

/*
   config.h.
   At some time in the past, generated automatically by configure.
   Maintained manually for better results.
*/

#define PLATFORM	"os2emx"
#define COMPILER	"[EMX GCC " __VERSION__ "]"
#define PYOS_OS2
#define PYCC_GCC
#define PREFIX		"/usr"

/* Debugging */
#ifndef Py_DEBUG
/*#define Py_DEBUG 1*/
#endif

/* so that emx socket headers will define IP V4 socket types */
#define TCPIPV4

/* Use OS/2 flavour of threads */
#define WITH_THREAD
#define OS2_THREADS

/* We want sockets */
#define USE_SOCKET
#define socklen_t int

/* enable the GC module */
#define WITH_CYCLE_GC	1

/* Unicode related */
#define Py_USING_UNICODE
#define PY_UNICODE_TYPE    wchar_t
#define Py_UNICODE_SIZE SIZEOF_SHORT

/* enable the Python object allocator */
/*#define	WITH_PYMALLOC	1*/

#define PYTHONPATH  ".;./Lib;./Lib/plat-" PLATFORM ";./Lib/lib-dynload;./Lib/site-packages"

#define HAVE_TTYNAME	1
#define HAVE_WAIT	1
#define HAVE_GETEGID    1
#define HAVE_GETEUID    1
#define HAVE_GETGID     1
#define HAVE_GETPPID    1
#define HAVE_GETUID     1
#define HAVE_OPENDIR    1
#define HAVE_PIPE       1
#define HAVE_POPEN      1
#define HAVE_SYSTEM	1
#define HAVE_TTYNAME	1
#define HAVE_DYNAMIC_LOADING	1

/* if port of GDBM installed, it includes NDBM emulation */
#define HAVE_NDBM_H	1

/* need this for spawnv code in posixmodule (cloned from WIN32 def'n) */
typedef long intptr_t;

/* we don't have tm_zone but do have the external array
   tzname.  */
#define HAVE_TZNAME 1

/* Define as the return type of signal handlers (int or void).  */
#define RETSIGTYPE void

/* Define if you have the ANSI C header files.  */
#define STDC_HEADERS 1

/* Define if you can safely include both <sys/time.h> and <time.h>.  */
#define TIME_WITH_SYS_TIME 1

/* Used for BeOS configuration */
/* #undef DL_EXPORT_HEADER */
#ifdef DL_EXPORT_HEADER
#include DL_EXPORT_HEADER
#endif

/* Define this if you have the type long long */
#define HAVE_LONG_LONG 1

/* Define if your compiler supports function prototypes */
#define HAVE_PROTOTYPES 1

/* Define if your compiler supports variable length function prototypes
   (e.g. void fprintf(FILE *, char *, ...);) *and* <stdarg.h> */
#define HAVE_STDARG_PROTOTYPES 1

/* Define if malloc(0) returns a NULL pointer */
#define MALLOC_ZERO_RETURNS_NULL 1

/* Define to force use of thread-safe errno, h_errno, and other functions */
#define _REENTRANT 1

/* Define if  you can safely include both <sys/select.h> and <sys/time.h>
   (which you can't on SCO ODT 3.0). */
#define SYS_SELECT_WITH_SYS_TIME 1

/* The number of bytes in an off_t. */
#define SIZEOF_OFF_T 4

/* The number of bytes in an time_t. */
#define SIZEOF_TIME_T 4

/* The number of bytes in a short.  */
#define SIZEOF_SHORT 2

/* The number of bytes in a int.  */
#define SIZEOF_INT 4

/* The number of bytes in a long.  */
#define SIZEOF_LONG 4

/* The number of bytes in a long long.  */
#define SIZEOF_LONG_LONG 8

/* The number of bytes in a void *.  */
#define SIZEOF_VOID_P 4

/* Define if you have the alarm function.  */
#define HAVE_ALARM 1

/* Define if you have the clock function.  */
#define HAVE_CLOCK 1

/* Define if you have the dup2 function.  */
#define HAVE_DUP2 1

/* Define if you have the execv function.  */
#define HAVE_EXECV 1

/* Define if you have the spawnv function.  */
#define HAVE_SPAWNV 1

/* Define if you have the flock function.  */
#define HAVE_FLOCK 1

/* Define if you have the fork function.  */
#define HAVE_FORK 1

/* Define if you have the fsync function.  */
#define HAVE_FSYNC 1

/* Define if you have the ftime function.  */
#define HAVE_FTIME 1

/* Define if you have the ftruncate function.  */
#define HAVE_FTRUNCATE 1

/* Define if you have the getcwd function.  */
#define HAVE_GETCWD 1

/* Define if you have the getpeername function.  */
#define HAVE_GETPEERNAME 1

/* Define if you have the getpgrp function.  */
#define HAVE_GETPGRP 1

/* Define if you have the getpid function.  */
#define HAVE_GETPID 1

/* Define if you have the getpwent function.  */
#define HAVE_GETPWENT 1

/* Define if you have the gettimeofday function.  */
#define HAVE_GETTIMEOFDAY 1

/* Define if you have the getwd function.  */
#define HAVE_GETWD 1

/* Define if you have the hypot function.  */
#define HAVE_HYPOT 1

/* Define if you have the kill function.  */
#define HAVE_KILL 1

/* Define if you have the memmove function.  */
#define HAVE_MEMMOVE 1

/* Define if you have the mktime function.  */
#define HAVE_MKTIME 1

/* Define if you have the pause function.  */
#define HAVE_PAUSE 1

/* Define if you have the putenv function.  */
#define HAVE_PUTENV 1

/* Define if you have the select function.  */
#define HAVE_SELECT 1

/* Define if you have the setgid function.  */
#define HAVE_SETGID 1

/* Define if you have the setlocale function.  */
#define HAVE_SETLOCALE 1

/* Define if you have the setpgid function.  */
#define HAVE_SETPGID 1

/* Define if you have the setuid function.  */
#define HAVE_SETUID 1

/* Define if you have the setvbuf function.  */
#define HAVE_SETVBUF 1

/* Define if you have the sigaction function.  */
#define HAVE_SIGACTION 1

/* Define if you have the strdup function.  */
#define HAVE_STRDUP 1

/* Define if you have the strerror function.  */
#define HAVE_STRERROR 1

/* Define if you have the strftime function.  */
#define HAVE_STRFTIME 1

/* Define if you have the strptime function.  */
#define HAVE_STRPTIME 1

/* Define if you have the tcgetpgrp function.  */
#define HAVE_TCGETPGRP 1

/* Define if you have the tcsetpgrp function.  */
#define HAVE_TCSETPGRP 1

/* Define if you have the times function.  */
#define HAVE_TIMES 1

/* Define if you have the truncate function.  */
#define HAVE_TRUNCATE 1

/* Define if you have the uname function.  */
#define HAVE_UNAME 1

/* Define if you have the waitpid function.  */
#define HAVE_WAITPID 1

/* Define if you have the <dirent.h> header file.  */
#define HAVE_DIRENT_H 1

/* Define if you have the <fcntl.h> header file.  */
#define HAVE_FCNTL_H 1

/* Define if you have the <limits.h> header file.  */
#define HAVE_LIMITS_H 1

/* Define if you have the <locale.h> header file.  */
#define HAVE_LOCALE_H 1

/* Define if you have the <ncurses.h> header file.  */
#define HAVE_NCURSES_H 1

/* Define if you have the <signal.h> header file.  */
#define HAVE_SIGNAL_H 1

/* Define if you have the <stdarg.h> header file.  */
#define HAVE_STDARG_H 1

/* Define if you have the <stddef.h> header file.  */
#define HAVE_STDDEF_H 1

/* Define if you have the <stdlib.h> header file.  */
#define HAVE_STDLIB_H 1

/* Define if you have the <sys/file.h> header file.  */
#define HAVE_SYS_FILE_H 1

/* Define if you have the <sys/param.h> header file.  */
#define HAVE_SYS_PARAM_H 1

/* Define if you have the <sys/select.h> header file.  */
#define HAVE_SYS_SELECT_H 1

/* Define if you have the <sys/time.h> header file.  */
#define HAVE_SYS_TIME_H 1

/* Define if you have the <sys/times.h> header file.  */
#define HAVE_SYS_TIMES_H 1

/* Define if you have the <sys/un.h> header file.  */
#define HAVE_SYS_UN_H 1

/* Define if you have the <sys/utsname.h> header file.  */
#define HAVE_SYS_UTSNAME_H 1

/* Define if you have the <sys/wait.h> header file.  */
#define HAVE_SYS_WAIT_H 1

/* Define if you have the <unistd.h> header file.  */
#define HAVE_UNISTD_H 1

/* Define if you have the <utime.h> header file.  */
#define HAVE_UTIME_H 1

/* EMX has an snprintf() */
#define HAVE_SNPRINTF

#endif /* !Py_CONFIG_H */


--- NEW FILE: python23.def ---
LIBRARY python23 INITINSTANCE TERMINSTANCE 
DESCRIPTION "Python 2.3 Core DLL" 
PROTMODE 
DATA MULTIPLE NONSHARED 
EXPORTS 

; From python23_s.lib(config)
  "_PyImport_Inittab"

; From python23_s.lib(dlfcn)
  "dlopen"
  "dlsym"
  "dlclose"
  "dlerror"

; From python23_s.lib(getpathp)
  "Py_GetPath"
  "Py_GetPrefix"
  "Py_GetExecPrefix"
  "Py_GetProgramFullPath"

; From python23_s.lib(getbuildinfo)
  "Py_GetBuildInfo"

; From python23_s.lib(main)
  "Py_Main"
  "Py_GetArgcArgv"

; From python23_s.lib(acceler)
  "PyGrammar_AddAccelerators"
  "PyGrammar_RemoveAccelerators"

; From python23_s.lib(grammar1)
  "PyGrammar_FindDFA"
  "PyGrammar_LabelRepr"

; From python23_s.lib(listnode)
  "PyNode_ListTree"

; From python23_s.lib(node)
  "PyNode_New"
  "PyNode_AddChild"
  "PyNode_Free"

; From python23_s.lib(parser)
  "PyParser_New"
  "PyParser_Delete"
  "PyParser_AddToken"

; From python23_s.lib(parsetok)
  "Py_TabcheckFlag"
  "PyParser_ParseString"
  "PyParser_ParseStringFlags"
  "PyParser_ParseFile"
  "PyParser_ParseFileFlags"

; From python23_s.lib(tokenizer)
  "PyTokenizer_FromString"
  "PyTokenizer_FromFile"
  "PyTokenizer_Free"
  "PyToken_OneChar"
  "PyToken_TwoChars"
  "PyToken_ThreeChars"
  "PyTokenizer_Get"
  "_PyParser_TokenNames"

; From python23_s.lib(bitset)
  "_Py_newbitset"
  "_Py_delbitset"
  "_Py_addbit"
  "_Py_samebitset"
  "_Py_mergebitset"

; From python23_s.lib(metagrammar)
  "_Py_meta_grammar"

; From python23_s.lib(myreadline)
  "PyOS_ReadlineFunctionPointer"
  "PyOS_StdioReadline"
  "PyOS_Readline"
  "PyOS_InputHook"

; From python23_s.lib(abstract)
  "PyObject_Cmp"
  "PyObject_Type"
  "PyObject_Size"
  "PyMapping_Size"
  "PyObject_Length"
  "PyObject_GetItem"
  "PySequence_GetItem"
  "PyObject_SetItem"
  "PySequence_SetItem"
  "PyObject_DelItem"
  "PySequence_DelItem"
  "PyObject_DelItemString"
  "PyObject_AsCharBuffer"
  "PyObject_CheckReadBuffer"
  "PyObject_AsReadBuffer"
  "PyObject_AsWriteBuffer"
  "PyNumber_Check"
  "PyNumber_Or"
  "PyNumber_Xor"
  "PyNumber_And"
  "PyNumber_Lshift"
  "PyNumber_Rshift"
  "PyNumber_Subtract"
  "PyNumber_Multiply"
  "PyNumber_Divide"
  "PyNumber_Divmod"
  "PyNumber_Add"
  "PyNumber_FloorDivide"
  "PyNumber_TrueDivide"
  "PyNumber_Remainder"
  "PyNumber_Power"
  "PyNumber_InPlaceOr"
  "PyNumber_InPlaceXor"
  "PyNumber_InPlaceAnd"
  "PyNumber_InPlaceLshift"
  "PyNumber_InPlaceRshift"
  "PyNumber_InPlaceSubtract"
  "PyNumber_InPlaceDivide"
  "PyNumber_InPlaceFloorDivide"
  "PyNumber_InPlaceTrueDivide"
  "PyNumber_InPlaceAdd"
  "PyNumber_InPlaceMultiply"
  "PyNumber_InPlaceRemainder"
  "PyNumber_InPlacePower"
  "PyNumber_Negative"
  "PyNumber_Positive"
  "PyNumber_Invert"
  "PyNumber_Absolute"
  "PyNumber_Int"
  "PyNumber_Long"
  "PyNumber_Float"
  "PySequence_Check"
  "PySequence_Size"
  "PySequence_Length"
  "PySequence_Concat"
  "PySequence_Repeat"
  "PySequence_InPlaceConcat"
  "PySequence_InPlaceRepeat"
  "PySequence_GetSlice"
  "PySequence_SetSlice"
  "PySequence_DelSlice"
  "PySequence_Tuple"
  "PyObject_GetIter"
  "PyIter_Next"
  "PySequence_List"
  "PySequence_Fast"
  "_PySequence_IterSearch"
  "PySequence_Count"
  "PySequence_Contains"
  "PySequence_In"
  "PySequence_Index"
  "PyMapping_Check"
  "PyMapping_Length"
  "PyMapping_GetItemString"
  "PyMapping_SetItemString"
  "PyMapping_HasKeyString"
  "PyMapping_HasKey"
  "PyObject_CallObject"
  "PyObject_Call"
  "PyObject_CallFunction"
  "PyObject_CallMethod"
  "PyObject_CallMethodObjArgs"
  "PyObject_CallFunctionObjArgs"
  "PyObject_IsInstance"
  "PyObject_IsSubclass"

; From python23_s.lib(bufferobject)
  "PyBuffer_FromObject"
  "PyBuffer_FromReadWriteObject"
  "PyBuffer_FromMemory"
  "PyBuffer_FromReadWriteMemory"
  "PyBuffer_New"
  "PyBuffer_Type"

; From python23_s.lib(cellobject)
  "PyCell_New"
  "PyCell_Get"
  "PyCell_Set"
  "PyCell_Type"

; From python23_s.lib(classobject)
  "PyClass_New"
  "PyMethod_Function"
  "PyMethod_Self"
  "PyMethod_Class"
  "PyClass_IsSubclass"
  "PyInstance_New"
  "PyInstance_NewRaw"
  "PyMethod_New"
  "PyMethod_Fini"
  "PyClass_Type"
  "PyMethod_Type"
  "PyInstance_Type"

; From python23_s.lib(cobject)
  "PyCObject_FromVoidPtr"
  "PyCObject_FromVoidPtrAndDesc"
  "PyCObject_AsVoidPtr"
  "PyCObject_GetDesc"
  "PyCObject_Import"
  "PyCObject_Type"

; From python23_s.lib(complexobject)
  "_Py_c_sum"
  "_Py_c_diff"
  "_Py_c_neg"
  "_Py_c_prod"
  "_Py_c_quot"
  "_Py_c_pow"
  "PyComplex_FromCComplex"
  "PyComplex_FromDoubles"
  "PyComplex_RealAsDouble"
  "PyComplex_ImagAsDouble"
  "PyComplex_AsCComplex"
  "PyComplex_Type"

; From python23_s.lib(descrobject)
  "PyWrapper_New"
  "PyDescr_NewMethod"
  "PyDescr_NewMember"
  "PyDescr_NewGetSet"
  "PyDescr_NewWrapper"
  "PyDescr_IsData"
  "PyDictProxy_New"
  "PyWrapperDescr_Type"
  "PyProperty_Type"

; From python23_s.lib(dictobject)
  "PyDict_New"
  "PyDict_GetItem"
  "PyDict_SetItem"
  "PyDict_DelItem"
  "PyDict_Clear"
  "PyDict_Next"
  "PyDict_Update"
  "PyDict_MergeFromSeq2"
  "PyDict_Merge"
  "PyDict_Copy"
  "PyDict_Size"
  "PyDict_Keys"
  "PyDict_Values"
  "PyDict_Items"
  "PyDict_GetItemString"
  "PyDict_SetItemString"
  "PyDict_DelItemString"
  "PyDict_Type"
  "PyDictIter_Type"

; From python23_s.lib(fileobject)
  "PyFile_AsFile"
  "PyFile_Name"
  "PyFile_FromFile"
  "PyFile_FromString"
  "PyFile_SetBufSize"
  "PyFile_GetLine"
  "PyFile_SoftSpace"
  "PyFile_WriteObject"
  "PyFile_WriteString"
  "PyObject_AsFileDescriptor"
  "PyFile_Type"

; From python23_s.lib(floatobject)
  "PyFloat_FromDouble"
  "PyFloat_FromString"
  "PyFloat_AsDouble"
  "PyFloat_AsStringEx"
  "PyFloat_AsString"
  "PyFloat_AsReprString"
  "PyFloat_Fini"
  "PyFloat_Type"

; From python23_s.lib(frameobject)
  "PyFrame_FastToLocals"
  "PyFrame_New"
  "PyFrame_BlockSetup"
  "PyFrame_BlockPop"
  "PyFrame_LocalsToFast"
  "PyFrame_Fini"
  "PyFrame_Type"

; From python23_s.lib(funcobject)
  "PyFunction_New"
  "PyFunction_GetCode"
  "PyFunction_GetGlobals"
  "PyFunction_GetDefaults"
  "PyFunction_SetDefaults"
  "PyFunction_GetClosure"
  "PyFunction_SetClosure"
  "PyClassMethod_New"
  "PyStaticMethod_New"
  "PyFunction_Type"
  "PyClassMethod_Type"
  "PyStaticMethod_Type"

; From python23_s.lib(intobject)
  "PyInt_GetMax"
  "PyInt_FromLong"
  "PyInt_AsLong"
  "PyInt_FromString"
  "PyInt_FromUnicode"
  "PyInt_Fini"
  "_Py_ZeroStruct"
  "PyInt_Type"
  "_Py_TrueStruct"

; From python23_s.lib(iterobject)
  "PySeqIter_New"
  "PyCallIter_New"
  "PySeqIter_Type"
  "PyCallIter_Type"

; From python23_s.lib(listobject)
  "PyList_New"
  "PyList_Size"
  "PyList_GetItem"
  "PyList_SetItem"
  "PyList_Insert"
  "PyList_Append"
  "PyList_GetSlice"
  "PyList_SetSlice"
  "PyList_Sort"
  "PyList_Reverse"
  "PyList_AsTuple"
  "PyList_Type"

; From python23_s.lib(longobject)
  "_PyLong_New"
  "_PyLong_Copy"
  "PyLong_FromLong"
  "PyLong_FromUnsignedLong"
  "PyLong_FromDouble"
  "PyLong_AsLong"
  "PyLong_AsUnsignedLong"
  "_PyLong_FromByteArray"
  "_PyLong_AsByteArray"
  "_PyLong_AsScaledDouble"
  "PyLong_AsDouble"
  "PyLong_FromVoidPtr"
  "PyLong_AsVoidPtr"
  "PyLong_FromLongLong"
  "PyLong_FromUnsignedLongLong"
  "PyLong_AsLongLong"
  "PyLong_AsUnsignedLongLong"
  "PyLong_FromString"
  "PyLong_FromUnicode"
  "PyLong_Type"

; From python23_s.lib(methodobject)
  "PyCFunction_New"
  "PyCFunction_GetFunction"
  "PyCFunction_GetSelf"
  "PyCFunction_GetFlags"
  "PyCFunction_Call"
  "Py_FindMethodInChain"
  "Py_FindMethod"
  "PyCFunction_Fini"
  "PyCFunction_Type"

; From python23_s.lib(moduleobject)
  "PyModule_New"
  "PyModule_GetDict"
  "PyModule_GetName"
  "PyModule_GetFilename"
  "_PyModule_Clear"
  "PyModule_Type"

; From python23_s.lib(object)
  "Py_DivisionWarningFlag"
  "PyObject_Init"
  "PyObject_InitVar"
  "_PyObject_New"
  "_PyObject_NewVar"
  "_PyObject_Del"
  "PyObject_Print"
  "PyObject_Str"
  "PyObject_Repr"
  "_PyObject_Dump"
  "PyObject_Unicode"
  "PyObject_GetAttr"
  "PyObject_IsTrue"
  "PyNumber_CoerceEx"
  "PyObject_Compare"
  "PyObject_RichCompare"
  "PyObject_RichCompareBool"
  "_Py_HashDouble"
  "PyObject_Hash"
  "_Py_HashPointer"
  "PyObject_GetAttrString"
  "PyObject_HasAttrString"
  "PyObject_SetAttrString"
  "PyObject_SetAttr"
  "PyObject_HasAttr"
  "_PyObject_GetDictPtr"
  "PyObject_GenericGetAttr"
  "PyObject_GenericSetAttr"
  "PyObject_Not"
  "PyNumber_Coerce"
  "PyCallable_Check"
  "PyObject_Dir"
  "_Py_ReadyTypes"
  "PyMem_Malloc"
  "PyMem_Realloc"
  "PyMem_Free"
  "PyObject_Malloc"
  "PyObject_Realloc"
  "PyObject_Free"
  "Py_ReprEnter"
  "Py_ReprLeave"
  "_PyTrash_deposit_object"
  "_PyTrash_destroy_chain"
  "_Py_NotImplementedStruct"
  "_Py_NoneStruct"
  "_Py_cobject_hack"
  "_Py_abstract_hack"
  "_PyTrash_delete_nesting"
  "_PyTrash_delete_later"

; From python23_s.lib(rangeobject)
  "PyRange_New"
  "PyRange_Type"

; From python23_s.lib(sliceobject)
  "PySlice_New"
  "PySlice_GetIndices"
  "_Py_EllipsisObject"
  "PySlice_Type"

; From python23_s.lib(stringobject)
  "PyString_FromStringAndSize"
  "PyString_InternInPlace"
  "PyString_FromString"
  "PyString_FromFormatV"
  "PyString_AsString"
  "_PyString_Resize"
  "PyString_FromFormat"
  "PyString_Decode"
  "PyString_AsDecodedString"
  "PyString_AsDecodedObject"
  "PyString_Encode"
  "PyString_AsEncodedString"
  "PyString_AsEncodedObject"
  "PyString_AsStringAndSize"
  "PyString_Size"
  "_PyString_Eq"
  "_PyString_Join"
  "PyString_Concat"
  "PyString_ConcatAndDel"
  "_PyString_FormatLong"
  "PyString_Format"
  "PyString_InternFromString"
  "PyString_Fini"
  "_Py_ReleaseInternedStrings"
  "PyString_Type"

; From python23_s.lib(structseq)
  "PyStructSequence_New"
  "PyStructSequence_InitType"

; From python23_s.lib(tupleobject)
  "PyTuple_New"
  "PyTuple_Size"
  "PyTuple_GetItem"
  "PyTuple_SetItem"
  "PyTuple_GetSlice"
  "_PyTuple_Resize"
  "PyTuple_Fini"
  "PyTuple_Type"

; From python23_s.lib(typeobject)
  "PyType_IsSubtype"
  "PyType_GenericAlloc"
  "PyType_GenericNew"
  "_PyType_Lookup"
  "PyType_Ready"
  "_PyObject_SlotCompare"
  "PyType_Type"
  "PyBaseObject_Type"
  "PySuper_Type"

; From python23_s.lib(unicodeobject)
  "PyUnicodeUCS2_GetMax"
  "PyUnicodeUCS2_Resize"
  "PyUnicodeUCS2_FromUnicode"
  "PyUnicodeUCS2_FromObject"
  "PyUnicodeUCS2_FromEncodedObject"
  "PyUnicodeUCS2_Decode"
  "PyUnicodeUCS2_GetDefaultEncoding"
  "PyUnicodeUCS2_DecodeUTF8"
  "PyUnicodeUCS2_DecodeLatin1"
  "PyUnicodeUCS2_DecodeASCII"
  "PyUnicodeUCS2_Encode"
  "PyUnicodeUCS2_AsEncodedString"
  "PyUnicodeUCS2_AsUTF8String"
  "PyUnicodeUCS2_AsLatin1String"
  "PyUnicodeUCS2_AsASCIIString"
  "_PyUnicodeUCS2_AsDefaultEncodedString"
  "PyUnicodeUCS2_AsUnicode"
  "PyUnicodeUCS2_GetSize"
  "PyUnicodeUCS2_SetDefaultEncoding"
  "PyUnicode_DecodeUTF7"
  "PyUnicode_EncodeUTF7"
  "PyUnicodeUCS2_EncodeUTF8"
  "PyUnicodeUCS2_DecodeUTF16"
  "PyUnicodeUCS2_EncodeUTF16"
  "PyUnicodeUCS2_AsUTF16String"
  "PyUnicodeUCS2_DecodeUnicodeEscape"
  "PyUnicodeUCS2_EncodeUnicodeEscape"
  "PyUnicodeUCS2_AsUnicodeEscapeString"
  "PyUnicodeUCS2_DecodeRawUnicodeEscape"
  "PyUnicodeUCS2_EncodeRawUnicodeEscape"
  "PyUnicodeUCS2_AsRawUnicodeEscapeString"
  "PyUnicodeUCS2_EncodeLatin1"
  "PyUnicodeUCS2_EncodeASCII"
  "PyUnicodeUCS2_DecodeCharmap"
  "PyUnicodeUCS2_EncodeCharmap"
  "PyUnicodeUCS2_AsCharmapString"
  "PyUnicodeUCS2_TranslateCharmap"
  "PyUnicodeUCS2_Translate"
  "PyUnicodeUCS2_EncodeDecimal"
  "PyUnicodeUCS2_Count"
  "PyUnicodeUCS2_Find"
  "PyUnicodeUCS2_Tailmatch"
  "PyUnicodeUCS2_Join"
  "PyUnicodeUCS2_Splitlines"
  "PyUnicodeUCS2_Compare"
  "PyUnicodeUCS2_Contains"
  "PyUnicodeUCS2_Concat"
  "PyUnicodeUCS2_Replace"
  "PyUnicodeUCS2_Split"
  "PyUnicodeUCS2_Format"
  "_PyUnicodeUCS2_Init"
  "_PyUnicodeUCS2_Fini"
  "PyUnicode_Type"

; From python23_s.lib(unicodectype)
  "_PyUnicode_TypeRecords"
  "_PyUnicodeUCS2_IsLinebreak"
  "_PyUnicodeUCS2_ToTitlecase"
  "_PyUnicodeUCS2_IsTitlecase"
  "_PyUnicodeUCS2_ToDecimalDigit"
  "_PyUnicodeUCS2_IsDecimalDigit"
  "_PyUnicodeUCS2_ToDigit"
  "_PyUnicodeUCS2_IsDigit"
  "_PyUnicodeUCS2_ToNumeric"
  "_PyUnicodeUCS2_IsNumeric"
  "_PyUnicodeUCS2_IsWhitespace"
  "_PyUnicodeUCS2_IsLowercase"
  "_PyUnicodeUCS2_IsUppercase"
  "_PyUnicodeUCS2_ToUppercase"
  "_PyUnicodeUCS2_ToLowercase"
  "_PyUnicodeUCS2_IsAlpha"

; From python23_s.lib(weakrefobject)
  "_PyWeakref_GetWeakrefCount"
  "PyWeakref_NewRef"
  "PyWeakref_NewProxy"
  "PyWeakref_GetObject"
  "PyObject_ClearWeakRefs"
  "_PyWeakref_RefType"
  "_PyWeakref_ProxyType"
  "_PyWeakref_CallableProxyType"

; From python23_s.lib(bltinmodule)
  "_PyBuiltin_Init"
  "Py_FileSystemDefaultEncoding"

; From python23_s.lib(exceptions)
  "PyExc_TypeError"
  "PyExc_Exception"
  "PyExc_StopIteration"
  "PyExc_StandardError"
  "PyExc_SystemExit"
  "PyExc_KeyboardInterrupt"
  "PyExc_ImportError"
  "PyExc_EnvironmentError"
  "PyExc_IOError"
  "PyExc_OSError"
  "PyExc_EOFError"
  "PyExc_RuntimeError"
  "PyExc_NotImplementedError"
  "PyExc_NameError"
  "PyExc_UnboundLocalError"
  "PyExc_AttributeError"
  "PyExc_SyntaxError"
  "PyExc_IndentationError"
  "PyExc_TabError"
  "PyExc_AssertionError"
  "PyExc_LookupError"
  "PyExc_IndexError"
  "PyExc_KeyError"
  "PyExc_ArithmeticError"
  "PyExc_OverflowError"
  "PyExc_ZeroDivisionError"
  "PyExc_FloatingPointError"
  "PyExc_ValueError"
  "PyExc_UnicodeError"
  "PyExc_ReferenceError"
  "PyExc_SystemError"
  "PyExc_MemoryError"
  "PyExc_Warning"
  "PyExc_UserWarning"
  "PyExc_DeprecationWarning"
  "PyExc_SyntaxWarning"
  "PyExc_OverflowWarning"
  "PyExc_RuntimeWarning"
  "PyExc_MemoryErrorInst"
  "_PyExc_Init"
  "_PyExc_Fini"

; From python23_s.lib(ceval)
  "PyEval_InitThreads"
  "PyEval_AcquireLock"
  "PyEval_ReleaseLock"
  "PyEval_AcquireThread"
  "PyEval_ReleaseThread"
  "PyEval_ReInitThreads"
  "PyEval_SaveThread"
  "PyEval_RestoreThread"
  "Py_AddPendingCall"
  "Py_MakePendingCalls"
  "Py_GetRecursionLimit"
  "Py_SetRecursionLimit"
  "PyEval_EvalCode"
  "PyEval_EvalCodeEx"
  "PyEval_CallObjectWithKeywords"
  "PyEval_SetProfile"
  "PyEval_SetTrace"
  "PyEval_GetBuiltins"
  "PyEval_GetLocals"
  "PyEval_GetGlobals"
  "PyEval_GetFrame"
  "PyEval_GetRestricted"
  "PyEval_MergeCompilerFlags"
  "Py_FlushLine"
  "PyEval_CallObject"
  "PyEval_GetFuncName"
  "PyEval_GetFuncDesc"
  "_PyEval_SliceIndex"

; From python23_s.lib(compile)
  "PyCode_New"
  "PyNode_Compile"
  "PyNode_CompileFlags"
  "PyNode_CompileSymtable"
  "PySymtable_Free"
  "PyCode_Addr2Line"
  "Py_OptimizeFlag"
  "PyCode_Type"

; From python23_s.lib(codecs)
  "PyCodec_Register"
  "_PyCodec_Lookup"
  "PyCodec_Encoder"
  "PyCodec_Decoder"
  "PyCodec_StreamReader"
  "PyCodec_StreamWriter"
  "PyCodec_Encode"
  "PyCodec_Decode"
  "_PyCodecRegistry_Init"
  "_PyCodecRegistry_Fini"

; From python23_s.lib(errors)
  "PyErr_Restore"
  "PyErr_SetObject"
  "PyErr_SetNone"
  "PyErr_SetString"
  "PyErr_Occurred"
  "PyErr_GivenExceptionMatches"
  "PyErr_ExceptionMatches"
  "PyErr_NormalizeException"
  "PyErr_Fetch"
  "PyErr_Clear"
  "PyErr_BadArgument"
  "PyErr_NoMemory"
  "PyErr_SetFromErrnoWithFilename"
  "PyErr_SetFromErrno"
  "_PyErr_BadInternalCall"
  "PyErr_Format"
  "PyErr_BadInternalCall"
  "PyErr_NewException"
  "PyErr_WriteUnraisable"
  "PyErr_Warn"
  "PyErr_WarnExplicit"
  "PyErr_SyntaxLocation"
  "PyErr_ProgramText"

; From python23_s.lib(frozen)
  "PyImport_FrozenModules"

; From python23_s.lib(frozenmain)
  "Py_FrozenMain"

; From python23_s.lib(future)
  "PyNode_Future"

; From python23_s.lib(getargs)
  "PyArg_Parse"
  "PyArg_ParseTuple"
  "PyArg_VaParse"
  "PyArg_ParseTupleAndKeywords"
  "PyArg_UnpackTuple"

; From python23_s.lib(getcompiler)
  "Py_GetCompiler"

; From python23_s.lib(getcopyright)
  "Py_GetCopyright"

; From python23_s.lib(getmtime)
  "PyOS_GetLastModificationTime"

; From python23_s.lib(getplatform)
  "Py_GetPlatform"

; From python23_s.lib(getversion)
  "Py_GetVersion"

; From python23_s.lib(graminit)
  "_PyParser_Grammar"

; From python23_s.lib(import)
  "_PyImport_Init"
  "_PyImport_Fini"
  "PyImport_GetModuleDict"
  "PyImport_Cleanup"
  "PyImport_GetMagicNumber"
  "_PyImport_FixupExtension"
  "_PyImport_FindExtension"
  "PyImport_AddModule"
  "PyImport_ExecCodeModule"
  "PyImport_ExecCodeModuleEx"
  "PyImport_ImportFrozenModule"
  "PyImport_ImportModule"
  "PyImport_Import"
  "PyImport_ImportModuleEx"
  "PyImport_ReloadModule"
;  "initimp"
  "PyImport_ExtendInittab"
  "PyImport_AppendInittab"
  "PyImport_Inittab"
  "_PyImport_Filetab"

; From python23_s.lib(importdl)
  "_PyImport_LoadDynamicModule"

; From python23_s.lib(marshal)
  "PyMarshal_WriteLongToFile"
  "PyMarshal_WriteObjectToFile"
  "PyMarshal_ReadShortFromFile"
  "PyMarshal_ReadLongFromFile"
  "PyMarshal_ReadLastObjectFromFile"
  "PyMarshal_ReadObjectFromString"
  "PyMarshal_ReadObjectFromFile"
  "PyMarshal_WriteObjectToString"
  "PyMarshal_Init"

; From python23_s.lib(modsupport)
  "Py_InitModule4"
  "Py_BuildValue"
  "Py_VaBuildValue"
  "PyEval_CallFunction"
  "PyEval_CallMethod"
  "PyModule_AddObject"
  "PyModule_AddIntConstant"
  "PyModule_AddStringConstant"
  "_Py_PackageContext"

; From python23_s.lib(mysnprintf)
  "PyOS_snprintf"
  "PyOS_vsnprintf"

; From python23_s.lib(mystrtoul)
  "PyOS_strtoul"
  "PyOS_strtol"

; From python23_s.lib(pyfpe)
  "PyFPE_dummy"

; From python23_s.lib(pystate)
  "PyInterpreterState_New"
  "PyInterpreterState_Clear"
  "PyThreadState_Clear"
  "PyThreadState_Delete"
  "PyInterpreterState_Delete"
  "PyThreadState_New"
  "PyThreadState_DeleteCurrent"
  "PyThreadState_Get"
  "PyThreadState_Swap"
  "PyThreadState_GetDict"
  "PyInterpreterState_Head"
  "PyInterpreterState_Next"
  "PyInterpreterState_ThreadHead"
  "PyThreadState_Next"
  "_PyThreadState_Current"

; From python23_s.lib(pythonrun)
  "Py_IgnoreEnvironmentFlag"
  "Py_DebugFlag"
  "Py_VerboseFlag"
  "Py_NoSiteFlag"
  "Py_InteractiveFlag"
  "Py_FrozenFlag"
  "Py_IsInitialized"
  "Py_Initialize"
  "Py_FatalError"
  "Py_Finalize"
  "Py_NewInterpreter"
  "PyErr_Print"
  "Py_EndInterpreter"
  "Py_SetProgramName"
  "Py_GetProgramName"
  "Py_SetPythonHome"
  "Py_GetPythonHome"
  "PyRun_AnyFile"
  "PyRun_AnyFileExFlags"
  "PyRun_AnyFileFlags"
  "PyRun_AnyFileEx"
  "Py_FdIsInteractive"
  "PyRun_InteractiveLoopFlags"
  "PyRun_SimpleFileExFlags"
  "PyRun_InteractiveLoop"
  "PyRun_InteractiveOneFlags"
  "PyRun_InteractiveOne"
  "PyRun_SimpleFile"
  "PyRun_SimpleFileEx"
  "PyRun_FileExFlags"
  "PyRun_SimpleString"
  "PyRun_SimpleStringFlags"
  "PyRun_StringFlags"
  "PyErr_PrintEx"
  "Py_Exit"
  "PyErr_Display"
  "PyRun_String"
  "PyParser_SimpleParseString"
  "PyRun_File"
  "PyRun_FileEx"
  "PyParser_SimpleParseFile"
  "PyParser_SimpleParseStringFlags"
  "PyRun_FileFlags"
  "PyParser_SimpleParseFileFlags"
  "Py_CompileString"
  "Py_CompileStringFlags"
  "Py_SymtableString"
  "Py_AtExit"
  "PyOS_getsig"
  "PyOS_setsig"
  "Py_UseClassExceptionsFlag"
  "Py_UnicodeFlag"
  "_Py_QnewFlag"
  "_PyThread_Started"

; From python23_s.lib(structmember)
  "PyMember_Get"
  "PyMember_GetOne"
  "PyMember_Set"
  "PyMember_SetOne"

; From python23_s.lib(symtable)
  "PySymtableEntry_New"
  "PySymtableEntry_Type"

; From python23_s.lib(sysmodule)
  "PySys_GetObject"
  "PySys_GetFile"
  "PySys_SetObject"
  "PySys_ResetWarnOptions"
  "PySys_AddWarnOption"
  "_PySys_Init"
  "PySys_SetPath"
  "PySys_SetArgv"
  "PySys_WriteStdout"
  "PySys_WriteStderr"

; From python23_s.lib(traceback)
  "PyTraceBack_Here"
  "PyTraceBack_Print"
  "PyTraceBack_Type"

; From python23_s.lib(getopt)
  "_PyOS_GetOpt"
  "_PyOS_opterr"
  "_PyOS_optind"
  "_PyOS_optarg"

; From python23_s.lib(dynload_shlib)
  "_PyImport_DynLoadFiletab"
  "_PyImport_GetDynLoadFunc"

; From python23_s.lib(thread)
  "PyThread_init_thread"
  "PyThread_start_new_thread"
  "PyThread_get_thread_ident"
  "PyThread_exit_thread"
  "PyThread__exit_thread"
  "PyThread_allocate_lock"
  "PyThread_free_lock"
  "PyThread_acquire_lock"
  "PyThread_release_lock"

; From python23_s.lib(gcmodule)
;  "initgc"
  "_PyGC_Dump"
  "_PyObject_GC_Track"
  "_PyObject_GC_UnTrack"
  "_PyObject_GC_Malloc"
  "_PyObject_GC_New"
  "_PyObject_GC_NewVar"
  "_PyObject_GC_Resize"
  "_PyObject_GC_Del"
  "_PyGC_generation0"

; From python23_s.lib(signalmodule)
  "PyErr_CheckSignals"
;  "initsignal"
  "PyErr_SetInterrupt"
  "PyOS_InitInterrupts"
  "PyOS_FiniInterrupts"
  "PyOS_InterruptOccurred"
  "PyOS_AfterFork"

; From python23_s.lib(posixmodule)
;  "initos2"

; From python23_s.lib(threadmodule)
;  "initthread"

; From python23_s.lib(_sre)
;  "init_sre"

--- NEW FILE: pythonpm.c ---
/* OS/2 PM main program - creates a hidden window, and starts Python
 * interpreter in a separate thread, so that Python scripts can be
 * run in PM process space without a console Window.  The interpreter
 * is incorporated by linking in the Python DLL.
 *
 * As it stands, I don't think this is adequate for supporting Python
 * GUI modules, as the Python thread doesn't have its own message
 * queue - which is required of threads that want to create/use
 * PM windows.
 *
 * This code owes a lot to "OS/2 Presentation Manager Programming", by
 * Charles Petzold.
 *
 * Andrew MacIntyre <andymac@bullseye.apana.org.au>, August 2001.
 * Released under the terms of the Python 2.1.1 licence - see the LICENCE
 * file in the Python v2.1.1 (or later) source distribution.
 * Copyright assigned to the Python Software Foundation, 2001.
 */

#define INCL_DOS
#define INCL_WIN
#include <os2.h>
#include <process.h>

#include "Python.h"

/* use structure to pass command line to Python thread */
typedef struct
{
	int argc;
	char **argv;
	HWND Frame;
	int running;
} arglist;

/* make this a global to simplify access.
 * it should only be set from the Python thread, or by the code that
 * initiates the Python thread when the thread cannot be created.
 */
int PythonRC;

extern DL_EXPORT(int) Py_Main(int, char **);
void PythonThread(void *);

int
main(int argc, char **argv)
{
	ULONG FrameFlags = FCF_TITLEBAR |
			   FCF_SYSMENU |
			   FCF_SIZEBORDER |
			   FCF_HIDEBUTTON |
			   FCF_SHELLPOSITION |
			   FCF_TASKLIST;
	HAB hab;
	HMQ hmq;
	HWND Client;
	QMSG qmsg;
	arglist args;
	int python_tid;

	/* init PM and create message queue */
	hab = WinInitialize(0);
	hmq = WinCreateMsgQueue(hab, 0);

	/* create a (hidden) Window to house the window procedure */
	args.Frame = WinCreateStdWindow(HWND_DESKTOP,
					0,
					&FrameFlags,
					NULL,
					"PythonPM",
					0L,
					0,
					0,
					&Client);

	/* run Python interpreter in a thread */
	args.argc = argc;
	args.argv = argv;
	args.running = 0;
	if (-1 == (python_tid = _beginthread(PythonThread, NULL, 1024 * 1024, &args)))
	{
		/* couldn't start thread */
		WinAlarm(HWND_DESKTOP, WA_ERROR);
		PythonRC = 1;
	}
	else
	{
		/* process PM messages, until Python exits */
		while (WinGetMsg(hab, &qmsg, NULLHANDLE, 0, 0))
			WinDispatchMsg(hab, &qmsg);
		if (args.running > 0)
			DosKillThread(python_tid);
	}
		
	/* destroy window, shutdown message queue and PM */
	WinDestroyWindow(args.Frame);
	WinDestroyMsgQueue(hmq);
	WinTerminate(hab);

	return PythonRC;
}

void PythonThread(void *argl)
{
	HAB hab;
	arglist *args;

	/* PM initialisation */
	hab = WinInitialize(0);

	/* start Python */
	args = (arglist *)argl;
	args->running = 1;
	PythonRC = Py_Main(args->argc, args->argv);

	/* enter a critical section and send the termination message */
	DosEnterCritSec();
	args->running = 0;
	WinPostMsg(args->Frame, WM_QUIT, NULL, NULL);

	/* shutdown PM and terminate thread */
	WinTerminate(hab);
	_endthread();
}