diff --git a/Python/dynload_shlib.c b/Python/dynload_shlib.c index e8a04ce500a..61674ba555a 100644 --- a/Python/dynload_shlib.c +++ b/Python/dynload_shlib.c @@ -18,6 +18,10 @@ #ifdef HAVE_DLFCN_H #include +#else +#if defined(PYOS_OS2) && defined(PYCC_GCC) +#include "dlfcn.h" +#endif #endif #if (defined(__OpenBSD__) || defined(__NetBSD__)) && !defined(__ELF__) @@ -31,9 +35,14 @@ const struct filedescr _PyImport_DynLoadFiletab[] = { #ifdef __CYGWIN__ {".dll", "rb", C_EXTENSION}, {"module.dll", "rb", C_EXTENSION}, +#else +#if defined(PYOS_OS2) && defined(PYCC_GCC) + {".pyd", "rb", C_EXTENSION}, + {".dll", "rb", C_EXTENSION}, #else {".so", "rb", C_EXTENSION}, {"module.so", "rb", C_EXTENSION}, +#endif #endif {0, 0} }; @@ -82,7 +91,9 @@ dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname, } } +#if !(defined(PYOS_OS2) && defined(PYCC_GCC)) dlopenflags = PyThreadState_Get()->interp->dlopenflags; +#endif if (Py_VerboseFlag) printf("dlopen(\"%s\", %x);\n", pathname, dlopenflags); diff --git a/Python/import.c b/Python/import.c index e657b70b8ef..e106aad6806 100644 --- a/Python/import.c +++ b/Python/import.c @@ -900,6 +900,11 @@ find_module(char *realname, PyObject *path, char *buf, size_t buflen, static struct filedescr fd_builtin = {"", "", C_BUILTIN}; static struct filedescr fd_package = {"", "", PKG_DIRECTORY}; char name[MAXPATHLEN+1]; +#if defined(PYOS_OS2) + size_t saved_len; + size_t saved_namelen; + char *saved_buf = NULL; +#endif if (strlen(realname) > MAXPATHLEN) { PyErr_SetString(PyExc_OverflowError, @@ -1026,7 +1031,38 @@ find_module(char *realname, PyObject *path, char *buf, size_t buflen, fdp = PyMac_FindModuleExtension(buf, &len, name); if (fdp) { #else +#if defined(PYOS_OS2) + /* take a snapshot of the module spec for restoration + * after the 8 character DLL hackery + */ + saved_buf = strdup(buf); + saved_len = len; + saved_namelen = namelen; +#endif /* PYOS_OS2 */ for (fdp = _PyImport_Filetab; fdp->suffix != NULL; fdp++) { +#if defined(PYOS_OS2) + /* OS/2 limits DLLs to 8 character names (w/o extension) + * so if the name is longer than that and its a + * dynamically loaded module we're going to try, + * truncate the name before trying + */ + if (strlen(realname) > 8) { + /* is this an attempt to load a C extension? */ + const struct filedescr *scan = _PyImport_DynLoadFiletab; + while (scan->suffix != NULL) { + if (strcmp(scan->suffix, fdp->suffix) == 0) + break; + else + scan++; + } + if (scan->suffix != NULL) { + /* yes, so truncate the name */ + namelen = 8; + len -= strlen(realname) - namelen; + buf[len] = '\0'; + } + } +#endif /* PYOS_OS2 */ strcpy(buf+len, fdp->suffix); if (Py_VerboseFlag > 1) PySys_WriteStderr("# trying %s\n", buf); @@ -1040,7 +1076,21 @@ find_module(char *realname, PyObject *path, char *buf, size_t buflen, fp = NULL; } } +#if defined(PYOS_OS2) + /* restore the saved snapshot */ + strcpy(buf, saved_buf); + len = saved_len; + namelen = saved_namelen; +#endif } +#if defined(PYOS_OS2) + /* don't need/want the module name snapshot anymore */ + if (saved_buf) + { + free(saved_buf); + saved_buf = NULL; + } +#endif if (fp != NULL) break; } @@ -1099,6 +1149,12 @@ find_module(char *realname, PyObject *path, char *buf, size_t buflen, #include #include +#elif defined(PYOS_OS2) +#define INCL_DOS +#define INCL_DOSERRORS +#define INCL_NOPMAPI +#include + #elif defined(RISCOS) #include "oslib/osfscontrol.h" #endif @@ -1255,6 +1311,26 @@ case_ok(char *buf, int len, int namelen, char *name) return 0; +/* OS/2 */ +#elif defined(PYOS_OS2) + HDIR hdir = 1; + ULONG srchcnt = 1; + FILEFINDBUF3 ffbuf; + APIRET rc; + + if (getenv("PYTHONCASEOK") != NULL) + return 1; + + rc = DosFindFirst(buf, + &hdir, + FILE_READONLY | FILE_HIDDEN | FILE_SYSTEM | FILE_DIRECTORY, + &ffbuf, sizeof(ffbuf), + &srchcnt, + FIL_STANDARD); + if (rc != NO_ERROR) + return 0; + return strncmp(ffbuf.achName, name, namelen) == 0; + /* assuming it's a case-sensitive filesystem, so there's nothing to do! */ #else return 1; diff --git a/Python/importdl.h b/Python/importdl.h index 76fd05d2933..8e04f286e0d 100644 --- a/Python/importdl.h +++ b/Python/importdl.h @@ -37,7 +37,7 @@ extern PyObject *_PyImport_LoadDynamicModule(char *name, char *pathname, #include typedef FARPROC dl_funcptr; #else -#ifdef PYOS_OS2 +#if defined(PYOS_OS2) && !defined(PYCC_GCC) #include typedef int (* APIENTRY dl_funcptr)(); #else diff --git a/Python/thread_os2.h b/Python/thread_os2.h index a35f3e9922d..69bcd2ce504 100644 --- a/Python/thread_os2.h +++ b/Python/thread_os2.h @@ -7,8 +7,12 @@ #include "process.h" +#if defined(PYCC_GCC) +#include +#include +#else long PyThread_get_thread_ident(void); - +#endif /* * Initialization of the C package, should not be needed. @@ -41,14 +45,20 @@ PyThread_start_new_thread(void (*func)(void *), void *arg) long PyThread_get_thread_ident(void) { +#if !defined(PYCC_GCC) PPIB pib; PTIB tib; +#endif if (!initialized) PyThread_init_thread(); +#if defined(PYCC_GCC) + return _gettid(); +#else DosGetInfoBlocks(&tib,&pib); return tib->tib_ptib2->tib2_ultid; +#endif } static void @@ -103,7 +113,7 @@ PyThread__exit_prog(int status) /* * Lock support. This is implemented with an event semaphore and critical * sections to make it behave more like a posix mutex than its OS/2 - # counterparts. + * counterparts. */ typedef struct os2_lock_t { @@ -114,6 +124,19 @@ typedef struct os2_lock_t { PyThread_type_lock PyThread_allocate_lock(void) { +#if defined(PYCC_GCC) + _fmutex *sem = malloc(sizeof(_fmutex)); + if (!initialized) + PyThread_init_thread(); + dprintf(("%ld: PyThread_allocate_lock() -> %lx\n", + PyThread_get_thread_ident(), + (long)sem)); + if (_fmutex_create(sem, 0)) { + free(sem); + sem = NULL; + } + return (PyThread_type_lock) sem; +#else APIRET rc; type_os2_lock lock = (type_os2_lock)malloc(sizeof(struct os2_lock_t)); @@ -130,16 +153,27 @@ PyThread_allocate_lock(void) lock->changed)); return (PyThread_type_lock) lock; +#endif } void PyThread_free_lock(PyThread_type_lock aLock) { +#if !defined(PYCC_GCC) type_os2_lock lock = (type_os2_lock)aLock; +#endif + dprintf(("%ld: PyThread_free_lock(%p) called\n", PyThread_get_thread_ident(),aLock)); +#if defined(PYCC_GCC) + if (aLock) { + _fmutex_close((_fmutex *)aLock); + free((_fmutex *)aLock); + } +#else DosCloseEventSem(lock->changed); free(aLock); +#endif } /* @@ -150,15 +184,22 @@ PyThread_free_lock(PyThread_type_lock aLock) int PyThread_acquire_lock(PyThread_type_lock aLock, int waitflag) { +#if !defined(PYCC_GCC) int done = 0; ULONG count; PID pid = 0; TID tid = 0; type_os2_lock lock = (type_os2_lock)aLock; +#endif dprintf(("%ld: PyThread_acquire_lock(%p, %d) called\n", PyThread_get_thread_ident(), aLock, waitflag)); +#if defined(PYCC_GCC) + /* always successful if the lock doesn't exist */ + if (aLock && _fmutex_request((_fmutex *)aLock, waitflag ? 0 : _FMR_NOWAIT)) + return 0; +#else while (!done) { /* if the lock is currently set, we have to wait for the state to change */ if (lock->is_set) { @@ -182,15 +223,23 @@ PyThread_acquire_lock(PyThread_type_lock aLock, int waitflag) DosExitCritSec(); } +#endif return 1; } void PyThread_release_lock(PyThread_type_lock aLock) { +#if defined(PYCC_GCC) type_os2_lock lock = (type_os2_lock)aLock; +#endif + dprintf(("%ld: PyThread_release_lock(%p) called\n", PyThread_get_thread_ident(),aLock)); +#if defined(PYCC_GCC) + if (aLock) + _fmutex_release((_fmutex *)aLock); +#else if (!lock->is_set) { dprintf(("%ld: Could not PyThread_release_lock(%p) error: %l\n", PyThread_get_thread_ident(), aLock, GetLastError())); @@ -208,4 +257,5 @@ void PyThread_release_lock(PyThread_type_lock aLock) DosPostEventSem(lock->changed); DosExitCritSec(); +#endif }