diff options
author | William Joye <wjoye@cfa.harvard.edu> | 2018-12-25 17:48:54 (GMT) |
---|---|---|
committer | William Joye <wjoye@cfa.harvard.edu> | 2018-12-25 17:48:54 (GMT) |
commit | 8eb0f61e2e27ef6594eee8bcf68d574fb087fe66 (patch) | |
tree | fc0f3692516c8c3e8090df20223d342a1b64df93 /tcl8.6/macosx/tclMacOSXBundle.c | |
parent | 5f5fd2864a3193a8d5da12fcb92ba7379084c286 (diff) | |
download | blt-8eb0f61e2e27ef6594eee8bcf68d574fb087fe66.zip blt-8eb0f61e2e27ef6594eee8bcf68d574fb087fe66.tar.gz blt-8eb0f61e2e27ef6594eee8bcf68d574fb087fe66.tar.bz2 |
update tcl/tk
Diffstat (limited to 'tcl8.6/macosx/tclMacOSXBundle.c')
-rw-r--r-- | tcl8.6/macosx/tclMacOSXBundle.c | 312 |
1 files changed, 312 insertions, 0 deletions
diff --git a/tcl8.6/macosx/tclMacOSXBundle.c b/tcl8.6/macosx/tclMacOSXBundle.c new file mode 100644 index 0000000..dad3733 --- /dev/null +++ b/tcl8.6/macosx/tclMacOSXBundle.c @@ -0,0 +1,312 @@ +/* + * tclMacOSXBundle.c -- + * + * This file implements functions that inspect CFBundle structures on + * MacOS X. + * + * Copyright 2001-2009, Apple Inc. + * Copyright (c) 2003-2009 Daniel A. Steffen <das@users.sourceforge.net> + * + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ + +#include "tclPort.h" + +#ifdef HAVE_COREFOUNDATION +#include <CoreFoundation/CoreFoundation.h> + +#ifndef TCL_DYLD_USE_DLFCN +/* + * Use preferred dlfcn API on 10.4 and later + */ +# if !defined(NO_DLFCN_H) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1040 +# define TCL_DYLD_USE_DLFCN 1 +# else +# define TCL_DYLD_USE_DLFCN 0 +# endif +#endif /* TCL_DYLD_USE_DLFCN */ + +#ifndef TCL_DYLD_USE_NSMODULE +/* + * Use deprecated NSModule API only to support 10.3 and earlier: + */ +# if MAC_OS_X_VERSION_MIN_REQUIRED < 1040 +# define TCL_DYLD_USE_NSMODULE 1 +# else +# define TCL_DYLD_USE_NSMODULE 0 +# endif +#endif /* TCL_DYLD_USE_NSMODULE */ + +#if TCL_DYLD_USE_DLFCN +#include <dlfcn.h> +#if defined(HAVE_WEAK_IMPORT) && MAC_OS_X_VERSION_MIN_REQUIRED < 1040 +/* + * Support for weakly importing dlfcn API. + */ +extern void * dlsym(void *handle, const char *symbol) + WEAK_IMPORT_ATTRIBUTE; +extern char * dlerror(void) WEAK_IMPORT_ATTRIBUTE; +#endif +#endif /* TCL_DYLD_USE_DLFCN */ + +#if TCL_DYLD_USE_NSMODULE +#include <mach-o/dyld.h> +#endif + +#if (TCL_DYLD_USE_DLFCN && MAC_OS_X_VERSION_MIN_REQUIRED < 1040) || \ + (MAC_OS_X_VERSION_MIN_REQUIRED < 1050) +MODULE_SCOPE long tclMacOSXDarwinRelease; +#endif + +#ifdef TCL_DEBUG_LOAD +#define TclLoadDbgMsg(m, ...) \ + do { \ + fprintf(stderr, "%s:%d: %s(): " m ".\n", \ + strrchr(__FILE__, '/')+1, __LINE__, __func__, \ + ##__VA_ARGS__); \ + } while (0) +#else +#define TclLoadDbgMsg(m, ...) +#endif /* TCL_DEBUG_LOAD */ + +/* + * Forward declaration of functions defined in this file: + */ + +static short OpenResourceMap(CFBundleRef bundleRef); + +#endif /* HAVE_COREFOUNDATION */ + +/* + *---------------------------------------------------------------------- + * + * OpenResourceMap -- + * + * Wrapper that dynamically acquires the address for the function + * CFBundleOpenBundleResourceMap before calling it, since it is only + * present in full CoreFoundation on Mac OS X and not in CFLite on pure + * Darwin. Factored out because it is moderately ugly code. + * + *---------------------------------------------------------------------- + */ + +#ifdef HAVE_COREFOUNDATION + +static short +OpenResourceMap( + CFBundleRef bundleRef) +{ + static int initialized = FALSE; + static short (*openresourcemap)(CFBundleRef) = NULL; + + if (!initialized) { +#if TCL_DYLD_USE_DLFCN +#if MAC_OS_X_VERSION_MIN_REQUIRED < 1040 + if (tclMacOSXDarwinRelease >= 8) +#endif + { + openresourcemap = dlsym(RTLD_NEXT, + "CFBundleOpenBundleResourceMap"); +#ifdef TCL_DEBUG_LOAD + if (!openresourcemap) { + const char *errMsg = dlerror(); + + TclLoadDbgMsg("dlsym() failed: %s", errMsg); + } +#endif /* TCL_DEBUG_LOAD */ + } + if (!openresourcemap) +#endif /* TCL_DYLD_USE_DLFCN */ + { +#if TCL_DYLD_USE_NSMODULE + if (NSIsSymbolNameDefinedWithHint( + "_CFBundleOpenBundleResourceMap", "CoreFoundation")) { + NSSymbol nsSymbol = NSLookupAndBindSymbolWithHint( + "_CFBundleOpenBundleResourceMap", "CoreFoundation"); + + if (nsSymbol) { + openresourcemap = NSAddressOfSymbol(nsSymbol); + } + } +#endif /* TCL_DYLD_USE_NSMODULE */ + } + initialized = TRUE; + } + + if (openresourcemap) { + return openresourcemap(bundleRef); + } + return -1; +} + +#endif /* HAVE_COREFOUNDATION */ + +/* + *---------------------------------------------------------------------- + * + * Tcl_MacOSXOpenBundleResources -- + * + * Given the bundle name for a shared library, this routine sets + * libraryPath to the Resources/Scripts directory in the framework + * package. If hasResourceFile is true, it will also open the main + * resource file for the bundle. + * + * Results: + * TCL_OK if the bundle could be opened, and the Scripts folder found. + * TCL_ERROR otherwise. + * + * Side effects: + * libraryVariableName may be set, and the resource file opened. + * + *---------------------------------------------------------------------- + */ + +int +Tcl_MacOSXOpenBundleResources( + Tcl_Interp *interp, + const char *bundleName, + int hasResourceFile, + int maxPathLen, + char *libraryPath) +{ + return Tcl_MacOSXOpenVersionedBundleResources(interp, bundleName, NULL, + hasResourceFile, maxPathLen, libraryPath); +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_MacOSXOpenVersionedBundleResources -- + * + * Given the bundle and version name for a shared library (version name + * can be NULL to indicate latest version), this routine sets libraryPath + * to the Resources/Scripts directory in the framework package. If + * hasResourceFile is true, it will also open the main resource file for + * the bundle. + * + * Results: + * TCL_OK if the bundle could be opened, and the Scripts folder found. + * TCL_ERROR otherwise. + * + * Side effects: + * libraryVariableName may be set, and the resource file opened. + * + *---------------------------------------------------------------------- + */ + +int +Tcl_MacOSXOpenVersionedBundleResources( + Tcl_Interp *interp, + const char *bundleName, + const char *bundleVersion, + int hasResourceFile, + int maxPathLen, + char *libraryPath) +{ +#ifdef HAVE_COREFOUNDATION + CFBundleRef bundleRef, versionedBundleRef = NULL; + CFStringRef bundleNameRef; + CFURLRef libURL; + + libraryPath[0] = '\0'; + + bundleNameRef = CFStringCreateWithCString(NULL, bundleName, + kCFStringEncodingUTF8); + + bundleRef = CFBundleGetBundleWithIdentifier(bundleNameRef); + CFRelease(bundleNameRef); + + if (bundleVersion && bundleRef) { + /* + * Create bundle from bundleVersion subdirectory of 'Versions'. + */ + + CFURLRef bundleURL = CFBundleCopyBundleURL(bundleRef); + + if (bundleURL) { + CFStringRef bundleVersionRef = CFStringCreateWithCString(NULL, + bundleVersion, kCFStringEncodingUTF8); + + if (bundleVersionRef) { + CFComparisonResult versionComparison = kCFCompareLessThan; + CFStringRef bundleTailRef = CFURLCopyLastPathComponent( + bundleURL); + + if (bundleTailRef) { + versionComparison = CFStringCompare(bundleTailRef, + bundleVersionRef, 0); + CFRelease(bundleTailRef); + } + if (versionComparison != kCFCompareEqualTo) { + CFURLRef versURL = CFURLCreateCopyAppendingPathComponent( + NULL, bundleURL, CFSTR("Versions"), TRUE); + + if (versURL) { + CFURLRef versionedBundleURL = + CFURLCreateCopyAppendingPathComponent( + NULL, versURL, bundleVersionRef, TRUE); + + if (versionedBundleURL) { + versionedBundleRef = CFBundleCreate(NULL, + versionedBundleURL); + if (versionedBundleRef) { + bundleRef = versionedBundleRef; + } + CFRelease(versionedBundleURL); + } + CFRelease(versURL); + } + } + CFRelease(bundleVersionRef); + } + CFRelease(bundleURL); + } + } + + if (bundleRef) { + if (hasResourceFile) { + (void) OpenResourceMap(bundleRef); + } + + libURL = CFBundleCopyResourceURL(bundleRef, CFSTR("Scripts"), + NULL, NULL); + + if (libURL) { + /* + * FIXME: This is a quick fix, it is probably not right for + * internationalization. + */ + + CFURLGetFileSystemRepresentation(libURL, TRUE, + (unsigned char *) libraryPath, maxPathLen); + CFRelease(libURL); + } + if (versionedBundleRef) { +#if MAC_OS_X_VERSION_MIN_REQUIRED < 1050 + /* + * Workaround CFBundle bug in Tiger and earlier. [Bug 2569449] + */ + + if (tclMacOSXDarwinRelease >= 9) +#endif + { + CFRelease(versionedBundleRef); + } + } + } + + if (libraryPath[0]) { + return TCL_OK; + } +#endif /* HAVE_COREFOUNDATION */ + return TCL_ERROR; +} + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ |