diff options
author | Eli Zaretskii <eliz@gnu.org> | 2013-04-29 19:26:06 +0300 |
---|---|---|
committer | Eli Zaretskii <eliz@gnu.org> | 2013-04-29 19:26:06 +0300 |
commit | 19a69bafc0913f13e334b5f56d95c693fab29023 (patch) | |
tree | b3f1d061b1a72d5f7e74a60831d85362f41fafe1 | |
parent | 9a7fe22b197770271a2235062fe52cb1c71a3d9e (diff) | |
download | gunmake-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.
-rw-r--r-- | ChangeLog | 11 | ||||
-rw-r--r-- | config.h.W32.template | 3 | ||||
-rw-r--r-- | load.c | 20 | ||||
-rw-r--r-- | w32/compat/posixfcn.c | 85 | ||||
-rw-r--r-- | w32/include/dlfcn.h | 13 |
5 files changed, 131 insertions, 1 deletions
@@ -1,5 +1,16 @@ 2013-04-29 Eli Zaretskii <eliz@gnu.org> + * 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. + * job.c (construct_command_argv_internal) [WINDOWS32]: Return right after generating new_argv for one_shell case. This fixes the Windows build for both Unixy shell and stock Windows shells. diff --git a/config.h.W32.template b/config.h.W32.template index 8818a76..8d59a13 100644 --- a/config.h.W32.template +++ b/config.h.W32.template @@ -366,6 +366,9 @@ this program. If not, see <http://www.gnu.org/licenses/>. */ /* Define to 1 to enable job server support in GNU make. */ #define MAKE_JOBSERVER 1 +/* Define to 1 to enable 'load' support in GNU make. */ +#define MAKE_LOAD 1 + /* Define to 1 to enable symbolic link timestamp checking. */ /* #undef MAKE_SYMLINKS */ @@ -49,7 +49,11 @@ load_object (const gmk_floc *flocp, int noerror, void *dlp = NULL; /* If the path has no "/", try the current directory first. */ - if (! strchr (ldname, '/')) + if (! strchr (ldname, '/') +#ifdef HAVE_DOS_PATHS + && ! strchr (ldname, '\\') +#endif + ) dlp = dlopen (concat (2, "./", ldname), RTLD_LAZY|RTLD_GLOBAL); /* If we haven't opened it yet, try the default search path. */ @@ -134,6 +138,20 @@ load_file (const gmk_floc *flocp, const char **ldname, int noerror) char *p = new; fp = strrchr (*ldname, '/'); +#ifdef HAVE_DOS_PATHS + if (fp) + { + const char *fp2 = strchr (fp, '\\'); + + if (fp2 > fp) + fp = fp2; + } + else + fp = strrchr (*ldname, '\\'); + /* The (improbable) case of d:foo. */ + if (fp && *fp && fp[1] == ':') + fp++; +#endif if (!fp) fp = *ldname; else 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 */ |