OpenFPGA/libs/EXTERNAL/tcl8.6.12/macosx/tclMacOSXBundle.c

314 lines
7.7 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* 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 = (short (*)(CFBundleRef))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.
*
*----------------------------------------------------------------------
*/
#undef Tcl_MacOSXOpenBundleResources
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:
*/