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