Ilya Zakharevich on Fri, 3 May 2002 22:06:18 -0400 |
[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]
Re: [PATCH] OS/2 dynalinking |
[Continuing an old discussion] On Tue, Mar 13, 2001 at 08:25:49PM +0100, Karim.Belabas wrote: > but it's annoying to rename things once they have been taught to cvs. So I'd > like to discuss a few things first. So far, for system specific stuff, PARI has > > 1) #define in the middle of general code [NOT a good thing, to be eliminated] > > 2) generic trivial wrappers: os_read, os_signal, os_getenv, ... in > src/language/es.c, which fail automatically on some architectures (e.g > WinCE). [Better, but not uniform] > > 3) Odos/pariCE.c which is only linked in the CE binary and contains a number > of needed standard routines, trivially implemented, or in terms of the > Windows API. > > Would a directory src/systems, containing e.g. > > os2.c unix.c winCE.c > os2.h unix.h winCE.h > > each system being represented by only 2 files, be acceptable ? I do not think this is practical if done exactly like this. E.g., the patch in question contains dlfcn.h. Merging it in pari_os2.h would not solve anything: one would need to surround existing `#include <dlfcn.h>' by *additional* check for #ifndef DLFCN_ALREADY_INCLUDED or somesuch. And anyway, os2.h would need to duplicate (or include) unix.h. However, the idea with os2.c is viable, so I redid the patch. Since I did not update build tools: to use this patch *now* one needs to manually define USE_DLOPEN, add ../src/systems/os2 to the include path, and add os2$(_O) to the list of dependencies. Moreover, the install() from the PARI itself works only if PARI library is in a DLL. Enjoy, Ilya --- ./src/systems/os2.c.orig Fri May 3 17:22:26 2002 +++ ./src/systems/os2.c Fri May 3 17:59:36 2002 @@ -0,0 +1,150 @@ +#include "dlfcn.h" + +#define INCL_BASE +#include <os2.h> +#include <float.h> + +static ULONG retcode; +static char fail[300]; + +static ULONG dllHandle; +static char dllname[80]; +static int handle_found; +static int handle_loaded; + +#ifdef DLOPEN_INITTERM +unsigned long _DLL_InitTerm(unsigned long modHandle, unsigned long flag) +{ + switch (flag) { + case 0: /* INIT */ + /* Save handle */ + dllHandle = modHandle; + handle_found = 1; + return TRUE; + + case 1: /* TERM */ + handle_found = 0; + dllHandle = (unsigned long)NULLHANDLE; + return TRUE; + } + + return FALSE; +} + +#endif + +void * +dlopen(char *path, int mode) +{ + HMODULE handle; + char tmp[260], *beg, *dot; + ULONG rc; + unsigned fpflag = _control87(0,0); + + fail[0] = 0; + if (!path) { /* Our own handle. */ + if (handle_found) { + if (handle_loaded) + return (void*)dllHandle; + rc = DosQueryModuleName(dllHandle, sizeof(dllname), dllname); + if (rc) { + strcpy(fail, "can't find my DLL name by the handle"); + return 0; + } + rc = DosLoadModule(fail, sizeof fail, dllname, &handle); + if (rc) { + strcpy(fail, "can't load my own DLL"); + return 0; + } + handle_loaded = 1; + goto ret; + } + strcpy(fail, "can't load from myself: compiled without -DDLOPEN_INITTERM"); + return 0; + } + if ((rc = DosLoadModule(fail, sizeof fail, path, &handle)) == 0) + goto ret; + + retcode = rc; + + /* Not found. Check for non-FAT name and try truncated name. */ + /* Don't know if this helps though... */ + for (beg = dot = path + strlen(path); + beg > path && !strchr(":/\\", *(beg-1)); + beg--) + if (*beg == '.') + dot = beg; + if (dot - beg > 8) { + int n = beg+8-path; + memmove(tmp, path, n); + memmove(tmp+n, dot, strlen(dot)+1); + if (DosLoadModule(fail, sizeof fail, tmp, &handle) == 0) + goto ret; + } + handle = 0; + + ret: + _control87(fpflag, MCW_EM); /* Some modules reset FP flags on load */ + return (void *)handle; +} + +void * +dlsym(void *handle, char *symbol) +{ + ULONG rc, type; + PFN addr; + + fail[0] = 0; + rc = DosQueryProcAddr((HMODULE)handle, 0, symbol, &addr); + if (rc == 0) { + rc = DosQueryProcType((HMODULE)handle, 0, symbol, &type); + if (rc == 0 && type == PT_32BIT) + return (void *)addr; + rc = ERROR_CALL_NOT_IMPLEMENTED; + } + retcode = rc; + return NULL; +} + +char * +dlerror(void) +{ + static char buf[700]; + ULONG len; + + if (retcode == 0) + return NULL; + if (DosGetMessage(NULL, 0, buf, sizeof buf - 1, retcode, + "OSO001.MSG", &len)) { + if (fail[0]) + sprintf(buf, +"OS/2 system error code %d, possible problematic module: '%s'", + (int)retcode, fail); + else + sprintf(buf, "OS/2 system error code %d", (int)retcode); + } else { + buf[len] = '\0'; + if (len && buf[len - 1] == '\n') + buf[--len] = 0; + if (len && buf[len - 1] == '\r') + buf[--len] = 0; + if (len && buf[len - 1] == '.') + buf[--len] = 0; + if (fail[0] && len < 300) + sprintf(buf + len, ", possible problematic module: '%s'", + fail); + } + retcode = 0; + return buf; +} + +int +dlclose(void *handle) +{ + ULONG rc; + + if ((rc = DosFreeModule((HMODULE)handle)) == 0) return 0; + + retcode = rc; + return 2; +} --- ./src/systems/os2/dlfcn.h.orig Fri May 3 17:22:42 2002 +++ ./src/systems/os2/dlfcn.h Fri May 3 17:22:42 2002 @@ -0,0 +1,5 @@ +#define RTLD_LAZY 1 +#define RTLD_GLOBAL 1 +void *dlopen(char *path, int mode); +void *dlsym(void *handle, char *symbol); +char *dlerror(void); --- ./src/systems/os2/pari.def.base.orig Fri May 3 17:22:42 2002 +++ ./src/systems/os2/pari.def.base Fri May 3 17:22:42 2002 @@ -0,0 +1,6 @@ +LIBRARY 'pari' INITINSTANCE TERMINSTANCE +; Can't put http://www.parigp-home.de/, since it is split on : +DESCRIPTION '@#www.parigp-home.de/:@VERSION@#@GP/PARI compiled with @CFLAGS@ +CODE LOADONCALL +DATA LOADONCALL NONSHARED MULTIPLE +EXPORTS