summaryrefslogtreecommitdiff
path: root/w32
diff options
context:
space:
mode:
authorEli Zaretskii <eliz@gnu.org>2013-04-29 19:26:06 +0300
committerEli Zaretskii <eliz@gnu.org>2013-04-29 19:26:06 +0300
commit19a69bafc0913f13e334b5f56d95c693fab29023 (patch)
treeb3f1d061b1a72d5f7e74a60831d85362f41fafe1 /w32
parent9a7fe22b197770271a2235062fe52cb1c71a3d9e (diff)
downloadgunmake-19a69bafc0913f13e334b5f56d95c693fab29023.tar.gz
Support dynamic object loading on MS-Windows.
w32/include/dlfcn.h: New file. w32/compat/posixfcn.c: Include dlfcn.h. (dlopen, dlerror, dlsym) [MAKE_LOAD]: New functions, in support of dynamic loading. config.h.W32.template (MAKE_LOAD): Define. load.c (load_object) [HAVE_DOS_PATHS]: Support backslashes and drive letters in file names of dynamic objects.
Diffstat (limited to 'w32')
-rw-r--r--w32/compat/posixfcn.c85
-rw-r--r--w32/include/dlfcn.h13
2 files changed, 98 insertions, 0 deletions
diff --git a/w32/compat/posixfcn.c b/w32/compat/posixfcn.c
index 90534d0..cafc864 100644
--- a/w32/compat/posixfcn.c
+++ b/w32/compat/posixfcn.c
@@ -21,6 +21,8 @@ this program. If not, see <http://www.gnu.org/licenses/>. */
#include <errno.h>
#include <windows.h>
+#include "dlfcn.h"
+
#include "makeint.h"
#include "job.h"
@@ -256,3 +258,86 @@ same_stream (FILE *f1, FILE *f2)
}
#endif /* OUTPUT_SYNC */
+
+#if MAKE_LOAD
+
+/* Support for dynamic loading of objects. */
+
+
+static DWORD last_err;
+
+void *
+dlopen (const char *file, int mode)
+{
+ char dllfn[MAX_PATH], *p;
+ HANDLE dllhandle;
+
+ if ((mode & ~(RTLD_LAZY | RTLD_NOW | RTLD_GLOBAL)) != 0)
+ {
+ errno = EINVAL;
+ last_err = ERROR_INVALID_PARAMETER;
+ return NULL;
+ }
+
+ if (!file)
+ dllhandle = GetModuleHandle (NULL);
+ else
+ {
+ /* MSDN says to be sure to use backslashes in the DLL file name. */
+ strcpy (dllfn, file);
+ for (p = dllfn; *p; p++)
+ if (*p == '/')
+ *p = '\\';
+
+ dllhandle = LoadLibrary (dllfn);
+ }
+ if (!dllhandle)
+ last_err = GetLastError ();
+
+ return dllhandle;
+}
+
+char *
+dlerror (void)
+{
+ static char errbuf[1024];
+ DWORD ret;
+
+ if (!last_err)
+ return NULL;
+
+ ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM
+ | FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL, last_err, 0, errbuf, sizeof (errbuf), NULL);
+ while (ret > 0 && (errbuf[ret - 1] == '\n' || errbuf[ret - 1] == '\r'))
+ --ret;
+
+ errbuf[ret] = '\0';
+ if (!ret)
+ sprintf (errbuf, "Error code %lu", last_err);
+
+ last_err = 0;
+ return errbuf;
+}
+
+void *
+dlsym (void *handle, const char *name)
+{
+ FARPROC addr = NULL;
+
+ if (!handle || handle == INVALID_HANDLE_VALUE)
+ {
+ last_err = ERROR_INVALID_PARAMETER;
+ return NULL;
+ }
+
+ addr = GetProcAddress (handle, name);
+ if (!addr)
+ last_err = GetLastError ();
+
+ return (void *)addr;
+}
+
+
+#endif /* MAKE_LOAD */
+
diff --git a/w32/include/dlfcn.h b/w32/include/dlfcn.h
new file mode 100644
index 0000000..c95fee2
--- /dev/null
+++ b/w32/include/dlfcn.h
@@ -0,0 +1,13 @@
+/* dlfcn.h replacement for MS-Windows build. */
+#ifndef DLFCN_H
+#define DLFCN_H
+
+#define RTLD_LAZY 1
+#define RTLD_NOW 2
+#define RTLD_GLOBAL 4
+
+extern void *dlopen (const char *, int);
+extern void *dlsym (void *, const char *);
+extern char *dlerror (void);
+
+#endif /* DLFCN_H */