X-Git-Url: http://git.chise.org/gitweb/?p=chise%2Fxemacs-chise.git.1;a=blobdiff_plain;f=src%2Fsysdll.c;h=c9e28c04d1dae4c55d10f2ed2831a283a1e1a83f;hp=d5f309c3638e84a142a7abe999796e193841df80;hb=8ba3626da629f1b4ecafae24c85f3d0cb3bf8b8e;hpb=6883ee56ec887c2c48abe5b06b5e66aa74031910 diff --git a/src/sysdll.c b/src/sysdll.c index d5f309c..c9e28c0 100644 --- a/src/sysdll.c +++ b/src/sysdll.c @@ -24,74 +24,76 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #endif #include -#include -#include -#include +#include "lisp.h" #include "sysdll.h" -/* This whole file is conditional upon HAVE_DLL */ +/* This whole file is conditional upon HAVE_SHLIB */ #ifdef HAVE_SHLIB /* Thankfully, most systems follow the ELFish dlopen() method. -** HAVE__DLOPEN is lame, but SCO has their dl* functions as _dl*, and -** unless you include dlfcn.h you don't get the macros to mask them, and -** autoconf fails to find them. -** -** Anybody who wants to use this on SCO needs to have their configure.in -** look for _dlopen() as well as dlopen() */ -#if defined(HAVE_DLOPEN) || defined(HAVE__DLOPEN) + +#if defined(HAVE_DLOPEN) #include #ifndef RTLD_LAZY # define RTLD_LAZY 1 #endif /* RTLD_LAZY isn't defined under FreeBSD - ick */ -#ifndef RTLD_GLOBAL -# define RTLD_GLOBAL 0 +#ifndef RTLD_NOW +# define RTLD_NOW 2 #endif int -dll_init (CONST char *arg) +dll_init (const char *arg) { return 0; } + dll_handle -dll_open (CONST char *fname) +dll_open (const char *fname) { - return (dll_handle)dlopen (fname, RTLD_LAZY | RTLD_GLOBAL); + return (dll_handle) dlopen (fname, RTLD_NOW); } int dll_close (dll_handle h) { - return dlclose((void *)h); + return dlclose ((void *) h); } dll_func -dll_function (dll_handle h, CONST char *n) +dll_function (dll_handle h, const char *n) { #ifdef DLSYM_NEEDS_UNDERSCORE char *buf = alloca_array (char, strlen (n) + 2); *buf = '_'; - (void)strcpy(buf + 1, n); + strcpy (buf + 1, n); n = buf; #endif - return (dll_func)dlsym ((void *)h, n); + return (dll_func) dlsym ((void *) h, n); } dll_var -dll_variable (dll_handle h, CONST char *n) +dll_variable (dll_handle h, const char *n) { +#ifdef DLSYM_NEEDS_UNDERSCORE + char *buf = alloca_array (char, strlen (n) + 2); + *buf = '_'; + strcpy (buf + 1, n); + n = buf; +#endif return (dll_var)dlsym ((void *)h, n); } -CONST char * +const char * dll_error (dll_handle h) { -#ifdef HAVE_DLERROR - return (CONST char *)dlerror (); +#if defined(HAVE_DLERROR) || defined(dlerror) + return (const char *) dlerror (); +#elif defined(HAVE__DLERROR) + return (const char *) _dlerror(); #else return "Shared library error"; #endif @@ -101,59 +103,49 @@ dll_error (dll_handle h) /* This is the HP/UX version */ #include int -dll_init (CONST char *arg) +dll_init (const char *arg) { return 0; } dll_handle -dll_open (CONST char *fname) +dll_open (const char *fname) { - shl_t h = shl_load (fname, BIND_DEFERRED,0L); - shl_t *hp = NULL; + /* shl_load will hang hard if passed a NULL fname. */ + if (fname == NULL) return NULL; - if (h) - { - hp = (shl_t *)malloc (sizeof (shl_t)); - if (!hp) - shl_unload(h); - else - *hp = h; - } - return (dll_handle)hp; + return (dll_handle) shl_load (fname, BIND_DEFERRED,0L); } int dll_close (dll_handle h) { - shl_t hp = *((shl_t *)h); - free (hp); - return shl_unload(h); + return shl_unload ((shl_t) h); } dll_func -dll_function (dll_handle h, CONST char *n) +dll_function (dll_handle h, const char *n) { long handle = 0L; - if (shl_findsym ((shl_t *)h, n, TYPE_PROCEDURE, &handle)) + if (shl_findsym ((shl_t *) &h, n, TYPE_PROCEDURE, &handle)) return NULL; - return (dll_func)handle; + return (dll_func) handle; } dll_var -dll_variable (dll_handle h, CONST char *n) +dll_variable (dll_handle h, const char *n) { long handle = 0L; - if (shl_findsym ((shl_t *)h, n, TYPE_DATA, &handle)) + if (shl_findsym ((shl_t *) &h, n, TYPE_DATA, &handle)) return NULL; - return (dll_var)handle; + return (dll_var) handle; } -CONST char * +const char * dll_error (dll_handle h) { /* #### WTF?! Shouldn't this at least attempt to get strerror or @@ -161,10 +153,10 @@ dll_error (dll_handle h) return "Generic shared library error"; } -#elif defined(HAVE_INIT_DLD) +#elif defined(HAVE_DLD_INIT) #include int -dll_init (CONST char *arg) +dll_init (const char *arg) { char *real_exe = dld_find_executable (arg); int rc; @@ -179,13 +171,13 @@ dll_init (CONST char *arg) } dll_handle -dll_open (CONST char *fname) +dll_open (const char *fname) { rc = dld_link (fname); if (rc) return NULL; - return (dll_handle)1; + return (dll_handle) 1; } int @@ -201,27 +193,32 @@ dll_close (dll_handle h) } DLL_FUNC -dll_function (dll_handle h, CONST char *n) +dll_function (dll_handle h, const char *n) { - return dld_get_func(n); + return dld_get_func (n); } DLL_FUNC -dll_variable (dll_handle h, CONST char *n) +dll_variable (dll_handle h, const char *n) { - return dld_get_symbol(n); + return dld_get_symbol (n); } -#elif defined(_WINDOWS) || defined(WIN32) +#elif defined (WIN32_NATIVE) + +#define WIN32_LEAN_AND_MEAN +#include +#undef WIN32_LEAN_AND_MEAN + int -dll_init (CONST char *arg) +dll_init (const char *arg) { return 0; } dll_handle -dll_open (CONST char *fname) +dll_open (const char *fname) { - return (dll_handle)LoadLibrary (fname); + return (dll_handle) LoadLibrary (fname); } int @@ -231,32 +228,266 @@ dll_close (dll_handle h) } dll_func -dll_function (dll_handle h, CONST char *n) +dll_function (dll_handle h, const char *n) { - return (dll_func)GetProcAddress (h,n); + return (dll_func) GetProcAddress (h, n); } dll_func -dll_variable (dll_handle h, CONST char *n) +dll_variable (dll_handle h, const char *n) { - return (dll_func)GetProcAddress (h,n); + return (dll_func) GetProcAddress (h, n); } -CONST char * +const char * dll_error (dll_handle h) { return "Windows DLL Error"; } +#elif defined(HAVE_DYLD) + +/* + This section supports MacOSX dynamic libraries. Dynamically + loadable libraries must be compiled as bundles, not dynamiclibs. +*/ + +#include + +int +dll_init (const char *arg) +{ + return 0; +} + +dll_handle +dll_open (const char *fname) +{ + NSObjectFileImage file; + NSObjectFileImageReturnCode ret; + + /* + * MacOS X dll support is for bundles, not the current executable, so return + * NULL is this case. However, dll_function() uses a special hack where a + * NULL handle can be used to find executable symbols. This satisfies the + * needs of ui-gtk.c but is not a general solution. + */ + if (fname == NULL) + return NULL; + + ret = NSCreateObjectFileImageFromFile(fname, &file); + + if (ret != NSObjectFileImageSuccess) { + return NULL; + } + + return (dll_handle)NSLinkModule(file, fname, + NSLINKMODULE_OPTION_BINDNOW | + NSLINKMODULE_OPTION_PRIVATE | + NSLINKMODULE_OPTION_RETURN_ON_ERROR); +} + +int +dll_close (dll_handle h) +{ + return NSUnLinkModule((NSModule)h, NSUNLINKMODULE_OPTION_NONE); +} + +/* Given an address, return the mach_header for the image containing it + * or zero if the given address is not contained in any loaded images. + * + * Note: image_for_address(), my_find_image() and search_linked_libs() are + * based on code from the dlcompat library + * (http://www.opendarwin.org/projects/dlcompat). + */ + +static struct mach_header* +image_for_address(void *address) +{ + unsigned long i; + unsigned long count = _dyld_image_count(); + struct mach_header *mh = 0; + + for (i = 0; i < count; i++) + { + unsigned long addr = (unsigned long)address - + _dyld_get_image_vmaddr_slide(i); + mh = _dyld_get_image_header(i); + + if (mh) + { + struct load_command *lc = + (struct load_command *)((char *)mh + sizeof(struct mach_header)); + unsigned long j; + + for (j = 0; j < mh->ncmds; + j++, lc = (struct load_command *)((char *)lc + lc->cmdsize)) + { + if (LC_SEGMENT == lc->cmd && + addr >= ((struct segment_command *)lc)->vmaddr && + addr < + ((struct segment_command *)lc)->vmaddr + + ((struct segment_command *)lc)->vmsize) + { + goto image_found; + } + } + } + + mh = 0; + } + + image_found: + return mh; +} + +static const struct mach_header* +my_find_image(const char *name) +{ + const struct mach_header *mh = (struct mach_header *) + NSAddImage(name, NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED | + NSADDIMAGE_OPTION_RETURN_ON_ERROR); + + if (!mh) + { + int count = _dyld_image_count(); + int j; + + for (j = 0; j < count; j++) + { + const char *id = _dyld_get_image_name(j); + + if (!strcmp(id, name)) + { + mh = _dyld_get_image_header(j); + break; + } + } + } + + return mh; +} + +/* + * dyld adds libraries by first adding the directly dependant libraries in + * link order, and then adding the dependencies for those libraries, so we + * should do the same... but we don't bother adding the extra dependencies, if + * the symbols are neither in the loaded image nor any of it's direct + * dependencies, then it probably isn't there. + */ +static NSSymbol +search_linked_libs(const struct mach_header * mh, const char *symbol) +{ + int n; + NSSymbol nssym = 0; + + struct load_command *lc = + (struct load_command *)((char *)mh + sizeof(struct mach_header)); + + for (n = 0; n < mh->ncmds; + n++, lc = (struct load_command *)((char *)lc + lc->cmdsize)) + { + if ((LC_LOAD_DYLIB == lc->cmd) || (LC_LOAD_WEAK_DYLIB == lc->cmd)) + { + struct mach_header *wh; + + if ((wh = (struct mach_header *) + my_find_image((char *)(((struct dylib_command *)lc)->dylib.name.offset + + (char *)lc)))) + { + if (NSIsSymbolNameDefinedInImage(wh, symbol)) + { + nssym = + NSLookupSymbolInImage(wh, + symbol, + NSLOOKUPSYMBOLINIMAGE_OPTION_BIND | + NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR); + break; + } + } + } + } + + return nssym; +} + +dll_func +dll_function (dll_handle h, const char *n) +{ + NSSymbol sym = 0; +#ifdef DLSYM_NEEDS_UNDERSCORE + char *buf = alloca_array (char, strlen (n) + 2); + *buf = '_'; + strcpy (buf + 1, n); + n = buf; +#endif + + /* NULL means the program image and shared libraries, not bundles. */ + + if (h == NULL) + { + /* NOTE: This assumes that this function is included in the main program + and not in a shared library. */ + const struct mach_header* my_mh = image_for_address(&dll_function); + + if (NSIsSymbolNameDefinedInImage(my_mh, n)) + { + sym = + NSLookupSymbolInImage(my_mh, + n, + NSLOOKUPSYMBOLINIMAGE_OPTION_BIND | + NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR); + } + + if (!sym) + { + sym = search_linked_libs(my_mh, n); + } + } + else + { + sym = NSLookupSymbolInModule((NSModule)h, n); + } + + if (sym == 0) return 0; + return (dll_func)NSAddressOfSymbol(sym); +} + +dll_var +dll_variable (dll_handle h, const char *n) +{ + NSSymbol sym; +#ifdef DLSYM_NEEDS_UNDERSCORE + char *buf = alloca_array (char, strlen (n) + 2); + *buf = '_'; + strcpy (buf + 1, n); + n = buf; +#endif + sym = NSLookupSymbolInModule((NSModule)h, n); + if (sym == 0) return 0; + return (dll_var)NSAddressOfSymbol(sym); +} + +const char * +dll_error (dll_handle h) +{ + NSLinkEditErrors c; + int errorNumber; + const char *fileNameWithError, *errorString; + NSLinkEditError(&c, &errorNumber, &fileNameWithError, &errorString); + return errorString; +} + + #else -/* Catchall if we don't know about this systems method of dynamic loading */ +/* Catchall if we don't know about this system's method of dynamic loading */ int -dll_init (CONST char *arg) +dll_init (const char *arg) { return -1; } dll_handle -dll_open (CONST char *fname) +dll_open (const char *fname) { return NULL; } @@ -268,18 +499,18 @@ dll_close (dll_handle h) } dll_func -dll_function (dll_handle h, CONST char *n) +dll_function (dll_handle h, const char *n) { return NULL; } dll_func -dll_variable (dll_handle h, CONST char *n) +dll_variable (dll_handle h, const char *n) { return NULL; } -CONST char * +const char * dll_error (dll_handle h) { return "Shared libraries not implemented on this system";