[Stackless-checkins] CVS: slpdev/src/2.2/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

Christian Tismer tismer at centera.de
Sat May 1 02:54:47 CEST 2004


Update of /home/cvs/slpdev/src/2.2/src/PC/os2emx
In directory centera.de:/home/tismer/slpdev/src/2.2/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:
added files

--- NEW FILE: Makefile ---
#####################==================----------------
#
# Top-Level Makefile for Building Python 2.3 for OS/2 using GCC/EMX
# Originally written by Andrew Zabolotny, <bit at eltech.ru> for Python 1.5.2
# Modified by Andrew MacIntyre, <andymac at 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
# === Hard-wire installation location ===
FIXED_PYHOME=no
#FIXED_PYHOME=yes

# === Optional modules ===
# Do you have the InfoZip compression library installed?
HAVE_ZLIB=	no
# Do you have the Ultra Fast Crypt (UFC) library installed?
HAVE_UFC=	no
# Do you have the Tcl/Tk library installed?
HAVE_TCLTK=	no
# Do you have the GNU multiprecision library installed?
HAVE_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 when
#       compiled with multithreading enabled.
HAVE_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)
HAVE_BSDDB=	no
# Do you have the ncurses library installed? EMX's BSD curses aren't enough! 
HAVE_NCURSES=	no
# Do you have the GDBM library installed?
HAVE_GDBM=	no
# Do you have the BZ2 compression library installed?
HAVE_BZ2=	no

# === install locations ===
# default value of PYTHONHOME
LIB_DIR=C:/Python23
# default is to have everything in or under PYTHONHOME
EXE_DIR=$(LIB_DIR)
DLL_DIR=$(EXE_DIR)


# === 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
EXEOPT=		emxbind
PY_DEF=		-DPy_BUILD_CORE


# adjust C compiler settings based on build options
ifeq ($(MODE),debug)
  CFLAGS+=	-g -O
  LDFLAGS+=	-g
else
  CFLAGS+=	-s -O3 -fomit-frame-pointer -mprobe
  LDFLAGS+=	-s
endif
CFLAGS+=	$(PY_DEF)
ifeq ($(ASSERTIONS),no)
  CFLAGS+=	-DNDEBUG
endif
ifeq ($(FIXED_PYHOME),yes)
  CFLAGS+=	-DPREFIX=$(DQUOTE)$(LIB_DIR)$(DQUOTE)
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
MODLIB.EXT=	.dll
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

# EMX's default number of file handles is 40, which is sometimes insufficient
# (the tempfile regression test tries to create 100 temporary files)
NFILES=250

# 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 1572864 >>$@

# 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.bsddb185$(MODULE.EXT)=	Python Extension DLL for access to BSD DB (v1.85) library
DESCRIPTION._curses$(MODLIB.EXT)=	Python Extension DLL for access to ncurses library
DESCRIPTION.pyexpat$(MODULE.EXT)=	Python Extension DLL for access to expat library
DESCRIPTION.bz2$(MODULE.EXT)=		Python Extension DLL for accessing the bz2 compression library

# Source files
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/arraymodule.c \
		Modules/binascii.c \
		Modules/cmathmodule.c \
		Modules/_codecsmodule.c \
		Modules/cPickle.c \
		Modules/cStringIO.c \
		Modules/_csv.c \
		Modules/datetimemodule.c \
		Modules/dlmodule.c \
		Modules/errnomodule.c \
		Modules/fcntlmodule.c \
		Modules/imageop.c \
		Modules/itertoolsmodule.c \
		Modules/_localemodule.c \
		Modules/mathmodule.c \
		Modules/md5c.c \
		Modules/md5module.c \
		Modules/operator.c \
		Modules/pcremodule.c \
		Modules/pypcre.c \
		Modules/_randommodule.c \
		Modules/regexmodule.c \
		Modules/regexpr.c \
		Modules/rgbimgmodule.c \
		Modules/shamodule.c \
		Modules/_sre.c \
		Modules/stropmodule.c \
		Modules/structmodule.c \
		Modules/symtablemodule.c \
		Modules/termios.c \
		Modules/timemodule.c \
		Modules/timingmodule.c \
		Modules/_weakref.c \
		Modules/xreadlinesmodule.c \
		Modules/xxsubtype.c \
		Modules/zipimport.c)
SRC.PARSE1=	$(addprefix $(TOP), \
		Parser/acceler.c \
		Parser/grammar1.c \
		Parser/listnode.c \
		Parser/node.c \
		Parser/parser.c \
		Parser/parsetok.c \
		Parser/bitset.c \
		Parser/metagrammar.c)
SRC.PARSE2=	$(addprefix $(TOP), \
		Parser/tokenizer.c \
		Parser/myreadline.c)
SRC.PARSER=	$(SRC.PARSE1) \
		$(SRC.PARSE2)
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/boolobject.c \
		Objects/bufferobject.c \
		Objects/cellobject.c \
		Objects/classobject.c \
		Objects/cobject.c \
		Objects/complexobject.c \
		Objects/descrobject.c \
		Objects/dictobject.c \
		Objects/enumobject.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/obmalloc.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.PGEN=	$(SRC.PARSE1) \
		$(addprefix $(TOP), \
		Objects/obmalloc.c) \
		$(addprefix $(TOP), \
		Python/mysnprintf.c) \
		$(addprefix $(TOP), \
		Parser/tokenizer_pgen.c \
		Parser/pgenmain.c \
		Parser/pgen.c \
		Parser/printgrammar.c \
		Parser/grammar.c \
		Parser/firstsets.c) \
		
OBJ.PGEN=	$(addprefix $(OUT),$(notdir $(SRC.PGEN:.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=	fpectl \
		fpetest \
		parser \
		pwd \
		rotor \
		select 

# 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=	_hotshot \
		_socket \
		_testcap \
		unicoded

# Python modules that are used as libraries and therefore must use
# a .DLL extension
LIBEXTMODULES=

# Python external ($(MODULE.EXT)) modules - can be EASY or HARD
ifeq ($(HAVE_ZLIB),yes)
  HARDEXTMODULES+=	zlib
endif
ifeq ($(HAVE_UFC),yes)
  HARDEXTMODULES+=	crypt
endif
ifeq ($(HAVE_TCLTK),yes)
  HARDEXTMODULES+=	_tkinter
  CFLAGS+=		-DHAS_DIRENT -I/TclTk80/include
  TK_LIBS+=		-L/TclTk80/lib -ltcl80 -ltk80
endif
ifeq ($(HAVE_GMPZ),yes)
  HARDEXTMODULES+=	mpz
endif
ifeq ($(HAVE_GREADLINE),yes)
  HARDEXTMODULES+=	readline
endif
ifeq ($(HAVE_BSDDB),yes)
  HARDEXTMODULES+=	bsddb185
endif
ifeq ($(HAVE_NCURSES),yes)
  LIBEXTMODULES+=	_curses
  HARDEXTMODULES+=	_curses_
endif
ifeq ($(HAVE_GDBM),yes)
  HARDEXTMODULES+=	gdbm dbm
endif
ifeq ($(HAVE_BZ2),yes)
  HARDEXTMODULES+=	bz2
endif

# Expat is now distributed with the Python source
HARDEXTMODULES+=	pyexpat
EXPAT.INC=	-I../../Modules/expat
EXPAT.DEF=	-DHAVE_EXPAT_H -DXML_NS=1 -DXML_DTD=1 -DXML_BYTE_ORDER=12 \
		-DXML_CONTENT_BYTES=1024 -DHAVE_MEMMOVE=1 -DHAVE_BCOPY=1
EXPAT.SRC=	$(addprefix ../../Modules/expat/, \
		xmlparse.c \
		xmlrole.c \
		xmltok.c)

# all the external modules
EXTERNDLLS=	$(addsuffix $(MODULE.EXT),$(patsubst %module,%,$(EASYEXTMODULES)))
EXTERNDLLS+=	$(addsuffix $(MODULE.EXT),$(patsubst %module,%,$(HARDEXTMODULES)))
EXTERNDLLS+=	$(addsuffix $(MODLIB.EXT),$(patsubst %module,%,$(LIBEXTMODULES)))

# Targets
all:  $(OUT) $(PYTHON.LIB) $(PYTHON.DEF) $(PYTHON.IMPLIB) $(PYTHON.DLL) \
	python_noncore

python_noncore:
	make PY_DEF= $(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)
	find ../../Lib -name "*.py[co]" -exec rm {} ";"

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) $@ $^

# the Python core DLL .def file needs to have a number of non-static
# symbols that aren't part of the Python C API removed (commented out)
# from the DLL export list.
$(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) |\
	 sed -e "/^  .init.*/s/^ /; /" \
		-e "/^  .pcre_.*/s/^ /; /" \
		-e "/^  .array_methods/s/^ /; /" \
		-e "/^  .fast_save_leave/s/^ /; /" \
		-e "/^  .dlopen/s/^ /; /" \
		-e "/^  .dlsym/s/^ /; /" \
		-e "/^  .dlclose/s/^ /; /" \
		-e "/^  .dlerror/s/^ /; /" \
		-e "/^  ._Py_re_.*/s/^ /; /" \
		-e "/^  ._Py_MD5.*/s/^ /; /" >>$@

$(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
	$(EXEOPT) -aq $(PYTHON.EXE) -h$(NFILES)

$(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
	$(EXEOPT) -aq $(PYTHONPM.EXE) -h$(NFILES)

$(PGEN.EXE): $(OBJ.PGEN) $(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

_hotshot$(MODULE.EXT): $(OUT)_hotshot$O $(OUT)_hotshot_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)

# _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 $^ $@

# - optional modules (requiring other software to be installed)
bsddb185$(MODULE.EXT): $(OUT)bsddbmodule$O $(OUT)bsddb185_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 $*)$(MODLIB.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$(MODLIB.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

# Expat is now distributed with Python, so use the included version
$(OUT)pyexpat$O:	../../Modules/pyexpat.c
	$(CC) $(CFLAGS) $(EXPAT.INC) -c -o $@ $^
$(OUT)xmlparse$O:	../../Modules/expat/xmlparse.c
	$(CC) $(CFLAGS) $(EXPAT.INC) $(EXPAT.DEF) -c -o $@ $^
$(OUT)xmlrole$O:	../../Modules/expat/xmlrole.c
	$(CC) $(CFLAGS) $(EXPAT.INC) $(EXPAT.DEF) -c -o $@ $^
$(OUT)xmltok$O:	../../Modules/expat/xmltok.c
	$(CC) $(CFLAGS) $(EXPAT.INC) $(EXPAT.DEF) -c -o $@ $^
pyexpat$(MODULE.EXT): $(OUT)pyexpat$O $(OUT)xmlparse$O $(OUT)xmlrole$O \
		$(OUT)xmltok$O $(OUT)pyexpat_m.def $(PYTHON.IMPLIB)
	$(LD) $(LDFLAGS.DLL) -o $@ $(^^) $(L^) $(LIBS)

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

bz2$(MODULE.EXT): $(OUT)bz2module$O $(OUT)bz2_m.def $(PYTHON.IMPLIB)
	$(LD) $(LDFLAGS.DLL) -o $@ $(^^) $(L^) $(LIBS) -lbz2

# the test target
test:
	-find ../../Lib -name "*.py[co]" -exec rm {} ";"
	-./python -E -tt ../../lib/test/regrtest.py -l -u "network"
	./python -E -tt ../../lib/test/regrtest.py -l -u "network"

-include $(OUTBASE)python.dep

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

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

Another day, another version...


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

Please read the file README.Python-2.4 included in this package for 
information about Python 2.4.  This file is the README file from the 
Python 2.4 source distribution available via http://www.python.org/ 
and its mirrors.  The file LICENCE.Python-2.4 is the text of the Licence 
from the Python 2.4 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.4 source distribution.

Andy 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.  Andy'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 16 
of the "YOU HAVE BEEN WARNED" section below).

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         (derived from Hung-Chi Chu's port of v1.1.3, v1.1.4)
- expat        (distributed with Python, v1.95.6)
- 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)


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 1).

Python24.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.  The DLL 
requires the EMX runtime DLLs.

This port has been built with complete support for multithreading.

Modules:

With the exception of modules that have a significant code size, or are 
not recommended or desired for normal use, the standard modules are now 
built into the core DLL rather than configured as dynamically loadable 
modules.  This is for both reasons of performance (startup time) and 
memory use (lots of small DLLs fragment the address space).

I haven't yet changed the building of Python's dynamically loadable 
modules over to using the DistUtils.

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

This port supports case sensitive module import semantics, matching 
the Windows release.  This can be deactivated by setting the PYTHONCASEOK 
environment variable (the value doesn't matter) - see "YOU HAVE BEEN WARNED" 
item 12.

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 (bsddb185), 
GNU GDBM (gdbm, dbm), zlib (zlib), GNU Readline (readline), GNU MP (mpz) 
and GNU UFC (crypt).

Expat is now included in the Python release sourceball, and the pyexpat 
module is always built.

I have built these modules statically linked against the 3rd party 
libraries.  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) 
needs 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 13.

Upstream source patches:

No updates to the Python 2.4 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.4 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, except for the plat-os2emx 
subdirectory.

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.4 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 as follows:
- python-2.4-os2emx-bin-03????.zip  (binaries, library modules)
- python-2.4-os2emx-src-03????      (patches+makefiles for non-Python code)

As all the Python specific patches for the port are now part of the 
Python release tarball, only the patches and makefiles involved in 
building external libraries for optional extensions are included in 
the source archive.

Documentation for the Python language, as well as the Python 2.4 
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.

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:\Python24) 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:/Python24
  SET PYTHONPATH=F:/Python24/Lib;F:/Python24/Lib/plat-os2emx;
                 F:/Python24/Lib/lib-dynload;F:/Python24/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:/Python24/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.4 source 
distribution by changing to the Python 2.4 home directory and executing the 
REGRTEST.CMD batch file.  The following tests are known to fail at this 
time:
- test_mhlib (I don't know of any port of MH to OS/2);
- test_strptime (see "YOU HAVE BEEN WARNED" item 22);
- test_time (see "YOU HAVE BEEN WARNED" item 22);
- test_posixpath (see "YOU HAVE BEEN WARNED" item 23).

Note that some of the network related tests expect the loopback interface
(interface "lo", with IP address 127.0.0.1) to be enabled, which from my
experience is not the default configuration.  Additionally, test_popen2
expects the "cat" utility (such as found in ports of the GNU tools) to
be installed.


Building from source
--------------------

With the EMX port now checked into Python's CVS repository, the build 
infrastructure is part of the Python release sourceball.

Prerequisites

First and foremost, you need an operational EMX development installation - 
EMX v0.9d with fix04 (the latest at time of writing) & the gcc 2.8.1 
compiler released by Eberhard Mattes is the recommended setup.

If you have a different version of gcc installed, see "YOU HAVE BEEN 
WARNED" item 16.

Other items of software required:-

- GNU make (I'm using v3.76.1)
- rm, cp, mkdir from the GNU file utilities package
- GNU find
- GNU sed

Procedure

0. all changes mentioned apply to files in the PC/os2emx subdirectory 
   of the Python release source tree.  make is also executed from this 
   directory, so change into this directory before proceeding.

1. decide if you need to change the location of the Python installation.
   If you wish to do this, set the value of the Makefile variable LIB_DIR 
   to the directory you wish to use for PYTHONHOME 
   (eg /usr/local/lib/python2.4).

   If you want Python to find its library without the PYTHONHOME 
   environment variable set, set the value of the Makefile variable 
   FIXED_PYHOME to "yes" (uncomment the appropriate line).

2. If you wish the Python executables (python.exe, pythonpm.exe & pgen.exe) 
   to be installed in a directory other than the PYTHONHOME directory, set 
   the value of the Makefile variable EXE_DIR to the appropriate directory.

3. If you wish the Python core DLL (python24.dll) to be installed in a 
   directory other than the directory in which the Python executables are 
   installed (by default, the PYTHONHOME directory), set the value of the 
   Makefile variable DLL_DIR to the appropriate directory.  This DLL must 
   be placed in a directory on the system's LIBPATH, or that gets set 
   with BEGINLIBPATH or ENDLIBPATH.

4. If you have installed any of the libraries that can be used to build 
   optional Python modules, set the value of the relevant HAVE_<package> 
   Makefile variable to "yes".  The Makefile currently supports:

   library               Makefile variable
   ........................................
   zlib (1.1.4)          HAVE_ZLIB
   GNU UltraFast Crypt   HAVE_UFC
   Tcl/Tk                HAVE_TCLTK (not known to work)
   GNU MP                HAVE_GMPZ
   GNU Readline          HAVE_GREADLINE
   BSD DB (v1.85)        HAVE_BSDDB
   ncurses               HAVE_NCURSES
   GNU gdbm              HAVE_GDBM
   libbz2                HAVE_BZ2

   Please note that you need to check that what you have installed 
   is compatible with Python's build options.  In particular, the 
   BSD DB v1.85 library needs to be rebuilt with a source patch for 
   multithread support (doesn't change the library's reentrant status 
   but allows it to be linked to Python which is multithreaded).  
   Widely available binary packages of other librarys & DLLs are 
   not built/linked with multithread support.  Beware!

   Also note that the Makefile currently expects any libraries to be 
   found with the default library search path.  You may need to add 
   -L switches to the LDFLAGS Makefile variable if you have installed 
   libraries in directories not in the default search path (which can 
   be controlled by the LIBRARY_PATH environment variable used by EMX).

5. make

   It is usually a good idea to redirect the stdout and stderr streams 
   of the make process to log files, so that you can review any messages. 

6. make test

   This runs the Python regression tests, and completion is a sign of 
   a usable build.  You should check the list of skipped modules to 
   ensure that any optional modules you selected have been built; 
   checking the list of failures against the list of known failures 
   elsewhere in this document is also prudent.

7. make install
   >>>>>> NOT YET COMPLETE <<<<<< 

8. change to a directory outside the Python source tree and start Python. 
   Check the version and build date to confirm satisfactory installation.


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

I know about a number of nasties in this port.

1.  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.

2.  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.

3.  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.

4.  the PyBSDDB3 module has been imported into the Python standard
library, with the intent of superceding the BSDDB 1.85 module (bsddb).
As I don't yet have a satisfactory port of Sleepcat's more recent DB
library (3.3.x/4.0.x/4.1.x), I haven't included a binary of this
module.  I have left the Python part of the PyBSDDB package in this
distribution for completeness.

5.  As a consequence of the PyBSDDB3 module being imported, the former 
BSD DB (bsddb) module, linked against the DB v1.85 library from EMX, 
has been renamed bsddb185.  The bsddb185 module will not be built by 
default on most platforms, but in the absence of a PyBSDDB3 module I 
have retained it in the EMX port.

Version 1.85 of the DB library is widely known to have bugs, although 
some patches have become available (and are incorporated into the 
included bsddb185 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.

Any code you have which uses the v1.85 bsddb module can be modified to 
use the renamed module by changing

  import bsddb

to

  import bsddb185 as bsddb

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

7.  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.

8.  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.

9.  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.

10. 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 pure Python substitutes for pwd and grp, 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)

The ETC_PASSWD and ETC_GROUP environment variables are intended to allow 
support for multiple passwd/grp files, where other applications may not 
support as wide a variety of input variations (drive remappings, 
separators etc).

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.  The 
regression tests (test_pwd and test_grp) will fail if valid password and 
group files cannot be found, but should pass otherwise.

Be aware that Python's pwd & group modules are for reading password and 
group information only.

11. 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.

12. 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.  This can be an issue with some 
file management utilities that do not preserve the case of file and
directory names.

13. 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.dll 
(which is the curses module, but with a .dll extension rather than .pyd 
so that the dynamic loader can actually import the symbols from it as a 
DLL).

The site module (Lib/site.py) has code added to tweak BEGINLIBPATH so
that _curses.dll is found when _curses_panel is imported.  If you have
problems attempting to use the _curses_panel support please let me know,
and I'll have another look at this.

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

15. 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.

16. I have successfully built this port with Andy Zabolotny's ports of 
pgcc 2.95 and gcc 3.2.1, in addition to EM's gcc 2.8.1.  To use the 
bsddb185 module with the gcc 3.2.1 build, I had to recompile the DB library 
with gcc 3.2.1 - I don't know why, but trying to import the module built 
against a DB library compiled with gcc 2.8.1 would result in a SYS3175 
error.

I have not attempted to compile Python with any version of gcc prior to 
v2.8.1.

This release sees the default optimisation change to 
"-O3 -fomit-frame-pointer -mprobe".  This works fine too for pgcc 2.95 
but not for gcc 3.2.1.

With gcc 3.2.1, -O3 causes 2 unexpected test failures: test_format and 
test_unicode.  Both these tests pass if -O2 is instead of -O3 with this 
compiler, and the performance difference is negligible (in contrast to 
gcc 2.8.1 and pgcc 2.95, where the performance difference between the 
2 optimisation settings approaches 10%).

17.  os.spawnv() and os.spawnve() 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.

18.  pythonpm.exe used to be 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.

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

20.  pyconfig.h is installed in the Include subdirectory with all 
other include files.

21.  the default build explicitly sets the number of file handles 
available to a Python process to 250.  EMX default is 40, which is 
insufficient for the tempfile regression test (test_tempfile) which 
tries to create 100 temporary files.

This setting can be overridden via the EMXOPT environment variable:
  set EMXOPT=-h250
is equivalent to the setting currently used.  The emxbind utility (if you 
have it installed) can also be used to permanently change the setting in 
python.exe - please refer to the EMX documentation for more information.

22.  a pure python strptime module is now part of the Python standard
library, superceding a platform specific extension module. This module
leverages the strftime module, and as a result test_strptime fails
due to the EMX strftime bug in item 20 above.

23.  test_posixpath attempts to exercise various Posix path related
functionality.  Most of the sub-tests pass, but the "ismount" and
"samestat" subtests fail:
- EMX provides not satisfactory mount point emulation, so "ismount"
  cannot succeed;
- EMX documents that successive stat() calls will produce different
  results, so "samestat" cannot succeed.

test_posixpath should skip these tests on EMX.

24.  I have had a report that attempting to use the Bittorrent package
(http://bitconjurer.org/BitTorrent/) with this port causes traps not
long after starting the download; this using the "headless" download
script on eCS v1.1.  I have not been able to duplicate this myself,
but the indications I have suggest a failure in the 32 bit TCP/IP
stack (v4.3.2? on eCS v1.1) - on my v4.0 FP12 system with MPTS fixpack
WR8425 applied (16 bit TCP/IP stack v4.02), BitTorrent appears to work
normally in testing on a 100Mbit LAN.  With the curses.panel fix (see
item 13 above), the BitTorrent curses downloader works too.  I'd
appreciate any success or failure reports with BitTorrent, though
I've regretfully recommended that the person who reported the failure
take this up with eCS support.  Since this report, I have received a 
followup which suggests that the problem may have been a buggy network 
card driver.  I think it suffices to say that BitTorrent is a fair stress 
test of a system's networking capability.

25.  In the absence of an EMX implementation of the link() function, I've 
implemented a crude Python emulation, in the file 
Lib/plat-os2emx/_emx_link.py.  This is imported into the os module, and 
becomes available as os.link() in the normal way.

The emulation copies the source file in binary mode, and will fail if 
disk space is exhausted. The call fails if the target already exists. 
There are no guarantees to thread safety with this emulation - beware!

The emulation was written to support a link() based file locking system 
used in GNU Mailman.

26.  AF_UNIX sockets, otherwise known as Unix domain sockets, are now
supported.  Unfortunately, there are some traps arising from the
implementation in IBM's TCP/IP stack:-
- the path name must start with '\\socket\\' ('/socket/' won't work!),
  with the length of the full path name less than 108 characters;
- unlike Unix, the socket endpoints don't exist in the filesystem;
- by default, sockets are in binary mode.

... 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 have 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 at bullseye.apana.org.au, or andymac at pcug.org.au
Web:    http://www.andymac.org/

11 April, 2004.

--- 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 initos2();
extern void initsignal();
#ifdef WITH_THREAD
extern void initthread();
#endif
extern void init_codecs();
extern void init_csv();
extern void init_locale();
extern void init_random();
extern void init_sre();
extern void init_symtable();
extern void init_weakref();
extern void initarray();
extern void initbinascii();
extern void initcPickle();
extern void initcStringIO();
extern void initcmath();
extern void initdatetime();
extern void initdl();
extern void initerrno();
extern void initfcntl();
extern void initimageop();
extern void inititertools();
extern void initmath();
extern void initmd5();
extern void initoperator();
extern void initpcre();
extern void initregex();
extern void initrgbimg();
extern void initsha();
extern void initstrop();
extern void initstruct();
extern void inittermios();
extern void inittime();
extern void inittiming();
extern void initxreadlines();
extern void initxxsubtype();
extern void initzipimport();
#if !HAVE_DYNAMIC_LOADING
extern void init_curses();
extern void init_curses_panel();
extern void init_hotshot();
extern void init_testcapi();
extern void initbsddb185();
extern void initbz2();
extern void initfpectl();
extern void initfpetest();
extern void initparser();
extern void initpwd();
extern void initrotor();
extern void initunicodedata();
extern void initzlib();
#ifdef USE_SOCKET
extern void init_socket();
extern void initselect();
#endif
#endif
/* -- ADDMODULE MARKER 1 -- */

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

struct _inittab _PyImport_Inittab[] = {

	{"os2", initos2},
	{"signal", initsignal},
#ifdef WITH_THREAD
	{"thread", initthread},
#endif
	{"_codecs", init_codecs},
	{"_csv", init_csv},
	{"_locale", init_locale},
	{"_random", init_random},
	{"_sre", init_sre},
	{"_symtable", init_symtable},
	{"_weakref", init_weakref},
	{"array", initarray},
	{"binascii", initbinascii},
	{"cPickle", initcPickle},
	{"cStringIO", initcStringIO},
	{"cmath", initcmath},
	{"datetime", initdatetime},
	{"dl", initdl},
	{"errno", initerrno},
	{"fcntl", initfcntl},
	{"imageop", initimageop},
	{"itertools", inititertools},
	{"math", initmath},
	{"md5", initmd5},
	{"operator", initoperator},
	{"pcre", initpcre},
	{"regex", initregex},
	{"rgbimg", initrgbimg},
	{"sha", initsha},
	{"strop", initstrop},
	{"struct", initstruct},
	{"termios", inittermios},
	{"time", inittime},
	{"timing", inittiming},
	{"xreadlines", initxreadlines},
	{"xxsubtype", initxxsubtype},
	{"zipimport", initzipimport},
#if !HAVE_DYNAMIC_LOADING
	{"_curses", init_curses},
	{"_curses_panel", init_curses_panel},
	{"_hotshot", init_hotshot},
	{"_testcapi", init_testcapi},
	{"bsddb185", initbsddb185},
	{"bz2", initbz2},
	{"fpectl", initfpectl},
	{"fpetest", initfpetest},
	{"parser", initparser},
	{"pwd", initpwd},
	{"rotor", initrotor},
	{"unicodedata", initunicodedata},
	{"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},

	/* This lives in gcmodule.c */
	{"gc", initgc},

	/* 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() - Unix-like dynamic linking
 * emulation 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>

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() - Unix-like dynamic linking
 * emulation functions for OS/2 using DosLoadModule() and company.
 */

#ifndef _DLFCN_H
#define _DLFCN_H

/* 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 the Python 2.3 core DLL.
 */

#define NULL 0

#define REF(s)	extern void s(); void *____ref_##s = &s;

/* Make references to imported symbols to pull them from static library */
REF(Py_Main);

#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;
	}
}

--- 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;
}

/* Is module  (check for .pyc/.pyo too)
 * Assumes 'filename' MAXPATHLEN+1 bytes long - 
 * may extend 'filename' by one character.
 */
static int
ismodule(char *filename)
{
	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");
	char zip_path[MAXPATHLEN+1];
	size_t len;

	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;

	/* Calculate zip archive path */
	strncpy(zip_path, progpath, MAXPATHLEN);
	zip_path[MAXPATHLEN] = '\0';
	len = strlen(zip_path);
	if (len > 4) {
		zip_path[len-3] = 'z';  /* change ending to "zip" */
		zip_path[len-2] = 'i';
		zip_path[len-1] = 'p';
	}
	else {
		zip_path[0] = 0;
	}

	/* We need to construct a path from the following parts.
	 * (1) the PYTHONPATH environment variable, if set;
	 * (2) the zip archive file path;
	 * (3) the PYTHONPATH config macro, with the leading "."
	 *     of each component replaced with pythonhome, if set;
	 * (4) the directory containing the executable (argv0_path).
	 * The length calculation calculates #3 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;
	bufsz += strlen(zip_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 (zip_path[0]) {
		strcpy(buf, zip_path);
		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/from configure.
 * now maintained manually.
 */

/* build environment */
#define PLATFORM	"os2emx"
#define COMPILER	"[EMX GCC " __VERSION__ "]"
#define PYOS_OS2	1
#define PYCC_GCC	1

/* default location(s) */
#ifndef PREFIX
#define PREFIX		""
#endif
#ifndef PYTHONPATH
#define PYTHONPATH	"./Lib;./Lib/plat-" PLATFORM \
			";./Lib/lib-dynload;./Lib/site-packages"
#endif

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

/* if building an extension or wrapper executable,
 * mark Python API symbols "extern" so that symbols
 * imported from the Python core DLL aren't duplicated.
 */
#ifdef Py_BUILD_CORE
#  define PyAPI_FUNC(RTYPE)	RTYPE
#else
#  define PyAPI_FUNC(RTYPE)	extern RTYPE
#endif
#define PyAPI_DATA(RTYPE)	extern RTYPE
#define PyMODINIT_FUNC	void

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

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

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

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

/* Define if you want documentation strings in extension modules */
#define WITH_DOC_STRINGS 1

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

/* system capabilities */
#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

/* 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 strerror function. */
#define HAVE_STRERROR 1

/* Define if you have the strftime function. */
#define HAVE_STRFTIME 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 tmpfile function.  */
#define HAVE_TMPFILE 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 <ncurses.h> header file. */
#define HAVE_NCURSES_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 1

#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_GetProgramFullPath"
  "Py_GetPrefix"
  "Py_GetExecPrefix"
[...1122 lines suppressed...]
;  "inittermios"

; From python23_s.lib(timemodule)
;  "inittime"
;  "inittimezone"

; From python23_s.lib(timingmodule)
;  "inittiming"

; From python23_s.lib(_weakref)
;  "init_weakref"

; From python23_s.lib(xreadlinesmodule)
;  "initxreadlines"

; From python23_s.lib(xxsubtype)
;  "initxxsubtype"

; From python23_s.lib(zipimport)
;  "initzipimport"

--- 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 at 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();
}


_______________________________________________
Stackless-checkins mailing list
Stackless-checkins at stackless.com
http://www.stackless.com/mailman/listinfo/stackless-checkins



More information about the Stackless-checkins mailing list