--- ./os2/dl_os2.c-as-sent	Sun Mar 30 15:06:32 2003
+++ ./os2/dl_os2.c	Mon May 26 01:01:12 2003
@@ -4,10 +4,16 @@
 
 #define INCL_BASE
 #include <os2.h>
+#include <float.h>
+#include <stdlib.h>
 
 static ULONG retcode;
 static char fail[300];
 
+static ULONG dllHandle;
+static char dllname[80];
+static int handle_found;
+static int handle_loaded;
 #ifdef PERL_CORE
 
 #include "EXTERN.h"
@@ -19,6 +25,57 @@ char *os2error(int rc);
 
 #endif
 
+#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
+
+HMODULE
+find_myself(void)
+{
+
+  static APIRET APIENTRY (*pDosQueryModFromEIP) (HMODULE * hmod, ULONG * obj, ULONG BufLen, PCHAR Buf,
+		    ULONG * Offset, ULONG Address);
+  HMODULE doscalls_h, mod;
+  static int failed;
+  ULONG obj, offset, rc;
+  char buf[260];
+
+  if (failed)
+	return 0;
+  failed = 1;
+  doscalls_h = (HMODULE)dlopen("DOSCALLS",0);
+  if (!doscalls_h)
+	return 0;
+/*  {&doscalls_handle, NULL, 360}, */	/* DosQueryModFromEIP */
+  rc = DosQueryProcAddr(doscalls_h, 360, 0, (PFN*)&pDosQueryModFromEIP);
+  if (rc)
+	return 0;
+  rc = pDosQueryModFromEIP(&mod, &obj, sizeof(buf), buf, &offset, (ULONG)dlopen);
+  if (rc)
+	return 0;
+  failed = 0;
+  handle_found = 1;
+  dllHandle = mod;
+  return mod;
+}
+
 void *
 dlopen(const char *path, int mode)
 {
@@ -26,10 +83,34 @@ dlopen(const char *path, int mode)
 	char tmp[260];
 	const char *beg, *dot;
 	ULONG rc;
+	unsigned fpflag = _control87(0,0);
 
 	fail[0] = 0;
+	if (!path) {			/* Our own handle. */
+	    if (handle_found || find_myself()) {
+		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");
+		    retcode = rc;
+		    return 0;
+		}
+		rc = DosLoadModule(fail, sizeof fail, dllname, &handle);
+		if (rc) {
+	            strcpy(fail, "can't load my own DLL");
+		    retcode = rc;
+		    return 0;
+		}
+		handle_loaded = 1;
+		goto ret;
+	    }
+	    retcode = ERROR_MOD_NOT_FOUND;
+            strcpy(fail, "can't load from myself: compiled without -DDLOPEN_INITTERM");
+	    return 0;
+	}
 	if ((rc = DosLoadModule(fail, sizeof fail, (char*)path, &handle)) == 0)
-		return (void *)handle;
+		goto ret;
 
 	retcode = rc;
 
@@ -49,12 +130,17 @@ dlopen(const char *path, int mode)
 		memmove(tmp, path, n);
 		memmove(tmp+n, dot, strlen(dot)+1);
 		if (DosLoadModule(fail, sizeof fail, tmp, &handle) == 0)
-			return (void *)handle;
+		    goto ret;
 	}
+	handle = 0;
 
-	return NULL;
+      ret:
+	_control87(fpflag, MCW_EM); /* Some modules reset FP flags on load */
+	return (void *)handle;
 }
 
+#define ERROR_WRONG_PROCTYPE 0xffffffff
+
 void *
 dlsym(void *handle, const char *symbol)
 {
@@ -67,7 +153,7 @@ dlsym(void *handle, const char *symbol)
 		rc = DosQueryProcType((HMODULE)handle, 0, symbol, &type);
 		if (rc == 0 && type == PT_32BIT)
 			return (void *)addr;
-		rc = ERROR_CALL_NOT_IMPLEMENTED;
+		rc = ERROR_WRONG_PROCTYPE;
 	}
 	retcode = rc;
 	return NULL;
@@ -82,12 +168,15 @@ dlerror(void)
 
 	if (retcode == 0)
 		return NULL;
-	err = os2error(retcode);
+	if (retcode == ERROR_WRONG_PROCTYPE)
+	    err = "Wrong procedure type";
+	else
+	    err = os2error(retcode);
 	len = strlen(err);
 	if (len > sizeof(buf) - 1)
 	    len = sizeof(buf) - 1;
 	strncpy(buf, err, len+1);
-	if (fail[0] && len < 300)
+	if (fail[0] && len + strlen(fail) < sizeof(buf) - 100)
 	    sprintf(buf + len, ", possible problematic module: '%s'", fail);
 	retcode = 0;
 	return buf;
