Merge branch 'master' of github.com:gnustep/libs-base into add_nsorderedset_classcluster

This commit is contained in:
Gregory John Casamento 2019-06-07 04:55:25 -04:00
commit b3e457cd1f
16 changed files with 786 additions and 110 deletions

View file

@ -1,3 +1,59 @@
2019-05-23 Frederik Seiffert <frederik@algoriddim.com>
* configure:
* configure.ac:
Link against libandroid on Android.
* Headers/Foundation/NSBundle.h:
* Source/NSBundle.m:
Added methods for passing Android asset manager from Java to GNUstep
and for getting AAsset/AAssetDir for given path in main bundle.
Skip app bundle suffix check on Android. Extended bundle resource
paths backbone to check for known paths directly on Android as we
can't enumerate directories.
Extended -localizations method to check for known localizations
directly (requires setting userLanguages in NSUserDefaults).
Extracted path cache cleaning into separate method.
* Source/GSFileHandle.h:
* Source/GSFileHandle.m:
Added file handle support for reading Android assets from main bundle.
* Source/NSData.m:
Added support for reading Android assets from main bundle in
readContentsOfFile(). This is also used by all other
-initWithContentsOfFile: and related methods from other classes.
* Source/NSFileManager.m:
Added support for Android assets from main bundle in
fileExistsAtPath:isDirectory:, isReadableFileAtPath:,
NSDirectoryEnumerator, and copying from assets. Extended
GSAttrDictionary with basic support for Android assets.
* Source/NSProcessInfo.m:
Added +initialize method to auto-initialize NSProcessInfo on Android
using fake executable path "/data/data/<app identifier>/exe" (Android
apps don't have a real executable path).
2019-05-20 Frederik Seiffert <frederik@algoriddim.com>
* Source/NSLog.m: Have all logs go to syslog on android.
* Source/NSThread.m: Spinlock implementation using builtins as
implemented by David in libobjc2
* Source/NSRunLoop.m
* Headers/GNUstepBase/config.h.in:
* configure.ac:
This updates the libdispatch runloop integration to be compatible with
the Swift corelibs libdispatch release at
(https://github.com/apple/swift-corelibs-libdispatch).
In that release, the main queue handle and drain functions have been
renamed with a "_4CF" (for CoreFoundation) suffix and have moved to
private.h, so we now check for the existance of this header and
function names.
Note that libdispatch must be compiled with
INSTALL_PRIVATE_HEADERS=YES.
Also fixes the checks for the HAVE_LIBDISPATCH_RUNLOOP define (was
inverted) and ensures that both the handle and drain functions are
available.
2019-02-16 Richard Frith-Macdonald <rfm@gnu.org>
* Source/NSString.m: Removed public functions which could conflict

View file

@ -36,6 +36,10 @@ extern "C" {
#import <Foundation/NSObject.h>
#import <Foundation/NSString.h>
#ifdef __ANDROID__
#include <android/asset_manager_jni.h>
#endif
@class NSString;
@class NSArray;
@class NSDictionary;
@ -540,6 +544,47 @@ GS_EXPORT NSString* const NSLoadedClasses;
ofType: (NSString*)extension
inDirectory: (NSString*)bundlePath;
/** Cleans up the path cache for the bundle. */
- (void) cleanPathCache;
#ifdef __ANDROID__
/**
* Sets the Java Android asset manager.
* The developer can call this method to enable asset loading via NSBundle.
*/
+ (void) setJavaAssetManager: (jobject)jassetManager withJNIEnv: (JNIEnv *)env;
/**
* Returns the native Android asset manager.
*/
+ (AAssetManager *) assetManager;
/**
* Returns the Android asset for the given path if path is in main bundle
* resources and asset exists.
* Uses `AASSET_MODE_UNKNOWN` to open the asset if it exists.
* The returned object must be released using AAsset_close().
*/
+ (AAsset *) assetForPath: (NSString *)path;
/**
* Returns the Android asset for the given path if path is in main bundle
* resources and asset exists.
* Uses the given mode to open the AAsset if it exists.
* The returned object must be released using AAsset_close().
*/
+ (AAsset *) assetForPath: (NSString *)path withMode: (int)mode;
/**
* Returns the Android asset dir for the given path if path is in main bundle
* resources and the asset directory exists.
* The returned object must be released using AAssetDir_close().
*/
+ (AAssetDir *) assetDirForPath: (NSString *)path;
#endif /* __ANDROID__ */
@end
#endif /* GNUSTEP */
@ -603,7 +648,7 @@ GS_EXPORT NSString* const NSLoadedClasses;
* </p>
*/
#define NSLocalizedString(key, comment) \
[[NSBundle mainBundle] localizedStringForKey:(key) value:@"" table:nil]
[[NSBundle mainBundle] localizedStringForKey: (key) value: @"" table: nil]
/**
* This function (macro) does the same as
@ -621,7 +666,7 @@ GS_EXPORT NSString* const NSLoadedClasses;
* different table.
*/
#define NSLocalizedStringFromTable(key, tbl, comment) \
[[NSBundle mainBundle] localizedStringForKey:(key) value:@"" table:(tbl)]
[[NSBundle mainBundle] localizedStringForKey: (key) value: @"" table: (tbl)]
/**
* This function is the full-blown localization function (it
@ -637,7 +682,7 @@ GS_EXPORT NSString* const NSLoadedClasses;
* use when translating the string.
*/
#define NSLocalizedStringFromTableInBundle(key, tbl, bundle, comment) \
[bundle localizedStringForKey:(key) value:@"" table:(tbl)]
[bundle localizedStringForKey: (key) value: @"" table: (tbl)]
#if defined(__cplusplus)

View file

@ -216,6 +216,9 @@
/* Define to 1 if you have the `dispatch_main_queue_drain_np' function. */
#undef HAVE_DISPATCH_MAIN_QUEUE_DRAIN_NP
/* Define to 1 if you have the <dispatch/private.h> header file. */
#undef HAVE_DISPATCH_PRIVATE_H
/* Define to 1 if you have the `dladdr' function. */
#undef HAVE_DLADDR
@ -767,6 +770,14 @@
/* Define to 1 if you have the `_Block_copy' function. */
#undef HAVE__BLOCK_COPY
/* Define to 1 if you have the `_dispatch_get_main_queue_handle_4CF' function.
*/
#undef HAVE__DISPATCH_GET_MAIN_QUEUE_HANDLE_4CF
/* Define to 1 if you have the `_dispatch_main_queue_callback_4CF' function.
*/
#undef HAVE__DISPATCH_MAIN_QUEUE_CALLBACK_4CF
/* Define to 1 if you have the `__builtin_extract_return_address' function. */
#undef HAVE___BUILTIN_EXTRACT_RETURN_ADDRESS

View file

@ -35,6 +35,10 @@
#include <zlib.h>
#endif
#ifdef __ANDROID__
#include <android/asset_manager_jni.h>
#endif
struct sockaddr_in;
/**
@ -69,6 +73,9 @@ struct sockaddr_in;
#if defined(_WIN32)
WSAEVENT event;
#endif
#ifdef __ANDROID__
AAsset *asset;
#endif
#endif
}

View file

@ -285,6 +285,13 @@ static GSTcpTune *tune = nil;
do
{
#ifdef __ANDROID__
if (asset)
{
result = AAsset_read(asset, buf, len);
}
else
#endif
#if USE_ZLIB
if (gzDescriptor != 0)
{
@ -379,6 +386,14 @@ static GSTcpTune *tune = nil;
[self ignoreReadDescriptor];
[self ignoreWriteDescriptor];
#ifdef __ANDROID__
if (asset)
{
AAsset_close(asset);
asset = NULL;
}
else
#endif
if (closeOnDealloc == YES && descriptor != -1)
{
[self closeFile];
@ -1075,6 +1090,15 @@ NSString * const GSSOCKSRecvAddr = @"GSSOCKSRecvAddr";
if (d < 0)
{
#ifdef __ANDROID__
asset = [NSBundle assetForPath:path withMode:AASSET_MODE_RANDOM];
if (asset)
{
readOK = YES;
return self;
}
#endif
DESTROY(self);
return nil;
}
@ -1645,6 +1669,13 @@ NSString * const GSSOCKSRecvAddr = @"GSSOCKSRecvAddr";
{
off_t result = -1;
#ifdef __ANDROID__
if (asset)
{
result = AAsset_seek(asset, 0, SEEK_CUR);
}
else
#endif
if (isStandardFile && descriptor >= 0)
{
#if USE_ZLIB
@ -1669,6 +1700,13 @@ NSString * const GSSOCKSRecvAddr = @"GSSOCKSRecvAddr";
{
off_t result = -1;
#ifdef __ANDROID__
if (asset)
{
result = AAsset_seek(asset, 0, SEEK_END);
}
else
#endif
if (isStandardFile && descriptor >= 0)
{
#if USE_ZLIB
@ -1693,6 +1731,13 @@ NSString * const GSSOCKSRecvAddr = @"GSSOCKSRecvAddr";
{
off_t result = -1;
#ifdef __ANDROID__
if (asset)
{
result = AAsset_seek(asset, (off_t)pos, SEEK_SET);
}
else
#endif
if (isStandardFile && descriptor >= 0)
{
#if USE_ZLIB
@ -1726,6 +1771,15 @@ NSString * const GSSOCKSRecvAddr = @"GSSOCKSRecvAddr";
[self ignoreWriteDescriptor];
[self setNonBlocking: NO];
#ifdef __ANDROID__
if (asset)
{
AAsset_close(asset);
asset = NULL;
}
else
#endif
#if USE_ZLIB
if (gzDescriptor != 0)
{

View file

@ -627,15 +627,11 @@ descriptorOrComparator: (id)descriptorOrComparator
while (stackSize > 1)
{
NSInteger n = stackSize -2;
if ( (n >= 1
&& runStack[n-1].length <= (runStack[n].length
+ runStack[n+1].length)
)
|| (n >= 2
&& runStack[n-2].length <= (runStack[n].length
+ runStack[n-1].length)
)
)
if ((n >= 1 && runStack[n-1].length
<= (runStack[n].length + runStack[n+1].length))
|| (n >= 2 && runStack[n-2].length
<= (runStack[n].length + runStack[n-1].length)))
{
if (runStack[n-1].length < runStack[n+1].length)
{

View file

@ -241,6 +241,11 @@ static NSString *library_combo =
nil;
#endif
#ifdef __ANDROID__
static jobject _jassetManager = NULL;
static AAssetManager *_assetManager = NULL;
#endif
/*
* Try to find the absolute path of an executable.
@ -264,17 +269,17 @@ AbsolutePathOfExecutable(NSString *path, BOOL atLaunch)
NSString *result = nil;
env = [[NSProcessInfo processInfo] environment];
pathlist = [env objectForKey:@"PATH"];
pathlist = [env objectForKey: @"PATH"];
/* Windows 2000 and perhaps others have "Path" not "PATH" */
if (pathlist == nil)
{
pathlist = [env objectForKey:@"Path"];
pathlist = [env objectForKey: @"Path"];
}
#if defined(_WIN32)
patharr = [pathlist componentsSeparatedByString:@";"];
patharr = [pathlist componentsSeparatedByString: @";"];
#else
patharr = [pathlist componentsSeparatedByString:@":"];
patharr = [pathlist componentsSeparatedByString: @":"];
#endif
/* Add . if not already in path */
if ([patharr indexOfObject: @"."] == NSNotFound)
@ -285,7 +290,7 @@ AbsolutePathOfExecutable(NSString *path, BOOL atLaunch)
patharr = [patharr objectEnumerator];
while (nil != (prefix = [patharr nextObject]))
{
if ([prefix isEqual:@"."])
if ([prefix isEqual: @"."])
{
if (atLaunch == YES)
{
@ -543,13 +548,14 @@ _find_framework(NSString *name)
{
NSArray *paths;
NSFileManager *file_mgr = manager();
NSString *file_name = [name stringByAppendingPathExtension:@"framework"];
NSString *file_name;
NSString *file_path;
NSString *path;
NSEnumerator *enumerator;
NSCParameterAssert(name != nil);
file_name = [name stringByAppendingPathExtension: @"framework"];
paths = NSSearchPathForDirectoriesInDomains(GSFrameworksDirectory,
NSAllDomainsMask,YES);
@ -922,9 +928,9 @@ _find_main_bundle_for_tool(NSString *toolName)
for (j = 0; j < [l count]; j++)
{
if ([[l objectAtIndex: j] pointerValue]
== [[b objectAtIndex:i] pointerValue])
== [[b objectAtIndex: i] pointerValue])
{
[l removeObjectAtIndex:j];
[l removeObjectAtIndex: j];
}
}
}
@ -1382,6 +1388,7 @@ _bundle_load_callback(Class theClass, struct objc_category *theCategory)
isNonInstalledTool = YES;
}
#ifndef __ANDROID__ /* don't check suffix on Android's fake executable path */
if (isApplication == YES)
{
s = [path lastPathComponent];
@ -1422,6 +1429,7 @@ _bundle_load_callback(Class theClass, struct objc_category *theCategory)
}
}
}
#endif /* !__ANDROID__ */
if (isApplication == NO)
{
@ -1805,9 +1813,6 @@ IF_NO_GC(
{
NSString *identifier = [self bundleIdentifier];
NSUInteger count;
NSUInteger plen = [_path length];
NSEnumerator *enumerator;
NSString *path;
[load_lock lock];
if (_bundles != nil)
@ -1835,38 +1840,7 @@ IF_NO_GC(
/* Clean up path cache for this bundle.
*/
[pathCacheLock lock];
enumerator = [pathCache keyEnumerator];
while (nil != (path = [enumerator nextObject]))
{
if (YES == [path hasPrefix: _path])
{
if ([path length] == plen)
{
/* Remove the bundle directory path from the cache.
*/
[pathCache removeObjectForKey: path];
}
else
{
unichar c = [path characterAtIndex: plen];
/* if the directory is inside the bundle, remove from cache.
*/
if ('/' == c)
{
[pathCache removeObjectForKey: path];
}
#if defined(_WIN32)
else if ('\\' == c)
{
[pathCache removeObjectForKey: path];
}
#endif
}
}
}
[pathCacheLock unlock];
[self cleanPathCache];
RELEASE(_path);
}
TEST_RELEASE(_frameworkVersion);
@ -2144,6 +2118,59 @@ IF_NO_GC(
addBundlePath(array, contents, primary, subPath, language);
}
}
#ifdef __ANDROID__
/* Android: check subdir and localization directly, as AAssetDir and thereby
* NSDirectoryEnumerator doesn't list directories
*/
NSString *originalPrimary = primary;
if (subPath)
{
primary = [originalPrimary stringByAppendingPathComponent: subPath];
contents = bundle_directory_readable(primary);
addBundlePath(array, contents, primary, nil, nil);
if (localization)
{
primary = [primary stringByAppendingPathComponent:
[localization stringByAppendingPathExtension: @"lproj"]];
contents = bundle_directory_readable(primary);
addBundlePath(array, contents, primary, nil, nil);
}
else
{
NSString *subPathPrimary = primary;
enumerate = [languages objectEnumerator];
while ((language = [enumerate nextObject]))
{
primary = [subPathPrimary stringByAppendingPathComponent:
[language stringByAppendingPathExtension: @"lproj"]];
contents = bundle_directory_readable(primary);
addBundlePath(array, contents, primary, nil, nil);
}
}
}
if (localization)
{
primary = [originalPrimary stringByAppendingPathComponent:
[localization stringByAppendingPathExtension: @"lproj"]];
contents = bundle_directory_readable(primary);
addBundlePath(array, contents, primary, nil, nil);
}
else
{
enumerate = [languages objectEnumerator];
while ((language = [enumerate nextObject]))
{
primary = [originalPrimary stringByAppendingPathComponent:
[language stringByAppendingPathExtension: @"lproj"]];
contents = bundle_directory_readable(primary);
addBundlePath(array, contents, primary, nil, nil);
}
}
#endif /* __ANDROID__ */
primary = rootPath;
contents = bundle_directory_readable(primary);
addBundlePath(array, contents, primary, subPath, nil);
@ -2254,7 +2281,7 @@ IF_NO_GC(
#if !defined(_WIN32)
if (_frameworkVersion)
rootPath = [NSString stringWithFormat:@"%@/Versions/%@", [self bundlePath],
rootPath = [NSString stringWithFormat: @"%@/Versions/%@", [self bundlePath],
_frameworkVersion];
else
#endif
@ -2525,6 +2552,27 @@ IF_NO_GC(
locale = [[locale lastPathComponent] stringByDeletingPathExtension];
[array addObject: locale];
}
#ifdef __ANDROID__
// Android: Check known languages for localizations directly, as AAssetDir
// and thereby NSDirectoryEnumerator doesn't list directories and the above
// call to list lproj resources will therefore come up empty.
NSArray *languages = [[NSUserDefaults standardUserDefaults]
stringArrayForKey: @"NSLanguages"];
for (locale in languages)
{
NSString *path = [self pathForResource: @"Localizable"
ofType: @"strings"
inDirectory: nil
forLocalization: locale];
if (path)
{
[array addObject: locale];
}
}
#endif /* __ANDROID__ */
return GS_IMMUTABLE(array);
}
@ -2732,7 +2780,7 @@ IF_NO_GC(
withString: @"_1"];
#if !defined(_WIN32)
path = [_path stringByAppendingPathComponent:@"Versions/Current"];
path = [_path stringByAppendingPathComponent: @"Versions/Current"];
#else
path = _path;
#endif
@ -2766,7 +2814,7 @@ IF_NO_GC(
{
#if !defined(_WIN32)
return [_path stringByAppendingPathComponent:
[NSString stringWithFormat:@"Versions/%@/%@",
[NSString stringWithFormat: @"Versions/%@/%@",
version, executableName]];
#else
return [_path stringByAppendingPathComponent: executableName];
@ -2795,7 +2843,7 @@ IF_NO_GC(
{
#if !defined(_WIN32)
return [_path stringByAppendingPathComponent:
[NSString stringWithFormat:@"Versions/%@/Resources",
[NSString stringWithFormat: @"Versions/%@/Resources",
version]];
#else
/* No Versions (that require symlinks) on mswindows */
@ -2852,7 +2900,7 @@ IF_NO_GC(
{
#if !defined(_WIN32)
return [_path stringByAppendingPathComponent:
[NSString stringWithFormat:@"Versions/%@/PlugIns",
[NSString stringWithFormat: @"Versions/%@/PlugIns",
version]];
#else
return [_path stringByAppendingPathComponent: @"PlugIns"];
@ -2880,8 +2928,8 @@ IF_NO_GC(
{
#if !defined(_WIN32)
return [_path stringByAppendingPathComponent:
[NSString stringWithFormat:@"Versions/%@/PrivateFrameworks",
version]];
[NSString stringWithFormat: @"Versions/%@/PrivateFrameworks",
version]];
#else
return [_path stringByAppendingPathComponent: @"PrivateFrameworks"];
#endif
@ -3202,5 +3250,142 @@ IF_NO_GC(
return path;
}
- (void)cleanPathCache
{
NSUInteger plen = [_path length];
NSEnumerator *enumerator;
NSString *path;
[pathCacheLock lock];
enumerator = [pathCache keyEnumerator];
while (nil != (path = [enumerator nextObject]))
{
if (YES == [path hasPrefix: _path])
{
if ([path length] == plen)
{
/* Remove the bundle directory path from the cache.
*/
[pathCache removeObjectForKey: path];
}
else
{
unichar c = [path characterAtIndex: plen];
/* if the directory is inside the bundle, remove from cache.
*/
if ('/' == c)
{
[pathCache removeObjectForKey: path];
}
#if defined(_WIN32)
else if ('\\' == c)
{
[pathCache removeObjectForKey: path];
}
#endif
}
}
}
[pathCacheLock unlock];
/* also destroy cached variables depending on bundle paths */
DESTROY(_infoDict);
DESTROY(_localizations);
}
#ifdef __ANDROID__
+ (AAssetManager *)assetManager
{
return _assetManager;
}
+ (void) setJavaAssetManager: (jobject)jassetManager withJNIEnv: (JNIEnv *)env
{
/* create global reference to Java asset manager to prevent garbage
* collection
*/
_jassetManager = (*env)->NewGlobalRef(env, jassetManager);
// get native asset manager (may be shared across multiple threads)
_assetManager = AAssetManager_fromJava(env, _jassetManager);
// clean main bundle path cache in case it was accessed before
[_mainBundle cleanPathCache];
}
+ (AAsset *) assetForPath: (NSString *)path
{
return [self assetForPath: path withMode: AASSET_MODE_UNKNOWN];
}
+ (AAsset *) assetForPath: (NSString *)path withMode: (int)mode
{
AAsset *asset = NULL;
if (_assetManager && _mainBundle)
{
NSString *resourcePath = [_mainBundle resourcePath];
if ([path hasPrefix: resourcePath]
&& [path length] > [resourcePath length])
{
NSString *assetPath;
assetPath = [path substringFromIndex: [resourcePath length] + 1];
asset = AAssetManager_open(_assetManager,
[assetPath fileSystemRepresentation], mode);
}
}
return asset;
}
+ (AAssetDir *) assetDirForPath: (NSString *)path
{
AAssetDir *assetDir = NULL;
if (_assetManager && _mainBundle)
{
NSString *resourcePath = [_mainBundle resourcePath];
if ([path hasPrefix: resourcePath])
{
NSString *assetPath = @"";
if ([path length] > [resourcePath length])
{
assetPath = [path substringFromIndex: [resourcePath length] + 1];
}
assetDir = AAssetManager_openDir(_assetManager,
[assetPath fileSystemRepresentation]);
if (assetDir)
{
/* AAssetManager_openDir() always returns an object,
* so we check if the directory exists by ensuring
* it contains a file
*/
BOOL exists = AAssetDir_getNextFileName(assetDir) != NULL;
if (exists)
{
AAssetDir_rewind(assetDir);
}
else
{
AAssetDir_close(assetDir);
assetDir = NULL;
}
}
}
}
return assetDir;
}
#endif /* __ANDROID__ */
@end

View file

@ -242,6 +242,40 @@ readContentsOfFile(NSString *path, void **buf, off_t *len, NSZone *zone)
void *tmp = 0;
int c;
off_t fileLength;
#ifdef __ANDROID__
// Android: try using asset manager if path is in main bundle resources
AAsset *asset = [NSBundle assetForPath: path withMode: AASSET_MODE_BUFFER];
if (asset)
{
fileLength = AAsset_getLength(asset);
tmp = NSZoneMalloc(zone, fileLength);
if (tmp == 0)
{
NSLog(@"Malloc failed for file (%@) of length %jd - %@", path,
(intmax_t)fileLength, [NSError _last]);
AAsset_close(asset);
goto failure;
}
int result = AAsset_read(asset, tmp, fileLength);
AAsset_close(asset);
if (result < 0)
{
NSWarnFLog(@"read of file (%@) contents failed - %@", path,
[NSError errorWithDomain: NSPOSIXErrorDomain
code: result
userInfo: nil]);
goto failure;
}
*buf = tmp;
*len = fileLength;
return YES;
}
#endif /* __ANDROID__ */
#if defined(_WIN32)
thePath = (const unichar*)[path fileSystemRepresentation];

View file

@ -241,7 +241,7 @@
struct _STATB statbuf;
_CHAR _path[0];
}
+ (NSDictionary*) attributesAt: (const _CHAR*)lpath
+ (NSDictionary*) attributesAt: (NSString *)path
traverseLink: (BOOL)traverse;
@end
@ -738,7 +738,7 @@ static NSStringEncoding defaultEncoding;
nxtImp = [direnum methodForSelector: @selector(nextObject)];
urlArray = [NSMutableArray arrayWithCapacity:128];
urlArray = [NSMutableArray arrayWithCapacity: 128];
while ((tempPath = (*nxtImp)(direnum, @selector(nextObject))) != nil)
{
NSURL *tempURL;
@ -749,7 +749,7 @@ static NSStringEncoding defaultEncoding;
/* we purge files beginning with . */
if (!((mask & NSDirectoryEnumerationSkipsHiddenFiles)
&& [lastComponent hasPrefix:@"."]))
&& [lastComponent hasPrefix: @"."]))
{
[urlArray addObject: tempURL];
}
@ -1652,6 +1652,29 @@ static NSStringEncoding defaultEncoding;
if (_STAT(lpath, &statbuf) != 0)
{
#ifdef __ANDROID__
/* Android: try using asset manager if path is in
* main bundle resources
*/
AAsset *asset = [NSBundle assetForPath: path];
if (asset)
{
AAsset_close(asset);
return YES;
}
AAssetDir *assetDir = [NSBundle assetDirForPath: path];
if (assetDir)
{
AAssetDir_close(assetDir);
if (isDirectory)
{
*isDirectory = YES;
}
return YES;
}
#endif
return NO;
}
@ -1700,6 +1723,17 @@ static NSStringEncoding defaultEncoding;
{
return YES;
}
#ifdef __ANDROID__
// Android: try using asset manager if path is in main bundle resources
AAsset *asset = [NSBundle assetForPath: path];
if (asset)
{
AAsset_close(asset);
return YES;
}
#endif
return NO;
}
#endif
@ -1929,8 +1963,7 @@ static NSStringEncoding defaultEncoding;
{
NSDictionary *d;
d = [GSAttrDictionaryClass attributesAt:
[self fileSystemRepresentationWithPath: path] traverseLink: flag];
d = [GSAttrDictionaryClass attributesAt: path traverseLink: flag];
return d;
}
@ -2012,8 +2045,7 @@ static NSStringEncoding defaultEncoding;
NSDictionary *d;
DESTROY(_lastError);
d = [GSAttrDictionaryClass attributesAt:
[self fileSystemRepresentationWithPath: path] traverseLink: NO];
d = [GSAttrDictionaryClass attributesAt: path traverseLink: NO];
if (error != NULL)
{
@ -2177,8 +2209,8 @@ static NSStringEncoding defaultEncoding;
*/
- (NSDictionary*) fileSystemAttributesAtPath: (NSString*)path
{
return [self attributesOfFileSystemForPath:path
error:NULL];
return [self attributesOfFileSystemForPath: path
error: NULL];
}
/**
@ -2379,6 +2411,9 @@ static NSStringEncoding defaultEncoding;
typedef struct _GSEnumeratedDirectory {
NSString *path;
_DIR *pointer;
#ifdef __ANDROID__
AAssetDir *assetDir;
#endif
} GSEnumeratedDirectory;
@ -2386,6 +2421,12 @@ static inline void gsedRelease(GSEnumeratedDirectory X)
{
DESTROY(X.path);
_CLOSEDIR(X.pointer);
#ifdef __ANDROID__
if (X.assetDir)
{
AAssetDir_close(X.assetDir);
}
#endif
}
#define GSI_ARRAY_TYPES 0
@ -2443,12 +2484,29 @@ static inline void gsedRelease(GSEnumeratedDirectory X)
localPath = [_mgr fileSystemRepresentationWithPath: path];
dir_pointer = _OPENDIR(localPath);
#ifdef __ANDROID__
AAssetDir *assetDir = NULL;
if (!dir_pointer)
{
/* Android: try using asset manager if path is in
* main bundle resources
*/
assetDir = [NSBundle assetDirForPath: path];
}
if (dir_pointer || assetDir)
#else
if (dir_pointer)
#endif
{
GSIArrayItem item;
item.ext.path = @"";
item.ext.pointer = dir_pointer;
#ifdef __ANDROID__
item.ext.assetDir = assetDir;
#endif
GSIArrayAddItem(_stack, item);
}
@ -2535,35 +2593,56 @@ static inline void gsedRelease(GSEnumeratedDirectory X)
while (GSIArrayCount(_stack) > 0)
{
GSEnumeratedDirectory dir = GSIArrayLastItem(_stack).ext;
struct _DIRENT *dirbuf;
struct _STATB statbuf;
#if defined(_WIN32)
const wchar_t *dirname = NULL;
#else
const char *dirname = NULL;
#endif
dirbuf = _READDIR(dir.pointer);
#ifdef __ANDROID__
if (dir.assetDir)
{
/* This will only return files and not directories, which means that
* recursion is not supported.
* See https://issuetracker.google.com/issues/37002833
*/
dirname = AAssetDir_getNextFileName(dir.assetDir);
}
else if (dir.pointer)
#endif
{
struct _DIRENT *dirbuf = _READDIR(dir.pointer);
if (dirbuf)
{
dirname = dirbuf->d_name;
}
}
if (dirbuf)
if (dirname)
{
#if defined(_WIN32)
/* Skip "." and ".." directory entries */
if (wcscmp(dirbuf->d_name, L".") == 0
|| wcscmp(dirbuf->d_name, L"..") == 0)
if (wcscmp(dirname, L".") == 0
|| wcscmp(dirname, L"..") == 0)
{
continue;
}
/* Name of file to return */
returnFileName = [_mgr
stringWithFileSystemRepresentation: dirbuf->d_name
length: wcslen(dirbuf->d_name)];
stringWithFileSystemRepresentation: dirname
length: wcslen(dirname)];
#else
/* Skip "." and ".." directory entries */
if (strcmp(dirbuf->d_name, ".") == 0
|| strcmp(dirbuf->d_name, "..") == 0)
if (strcmp(dirname, ".") == 0
|| strcmp(dirname, "..") == 0)
{
continue;
}
/* Name of file to return */
returnFileName = [_mgr
stringWithFileSystemRepresentation: dirbuf->d_name
length: strlen(dirbuf->d_name)];
stringWithFileSystemRepresentation: dirname
length: strlen(dirname)];
#endif
/* if we have a null FileName something went wrong (charset?) and we skip it */
if (returnFileName == nil)
@ -2841,6 +2920,9 @@ static inline void gsedRelease(GSEnumeratedDirectory X)
int rbytes;
int wbytes;
char buffer[bufsize];
#ifdef __ANDROID__
AAsset *asset = NULL;
#endif
attributes = [self fileAttributesAtPath: source traverseLink: NO];
if (nil == attributes)
@ -2859,7 +2941,16 @@ static inline void gsedRelease(GSEnumeratedDirectory X)
/* Open the source file. In case of error call the handler. */
sourceFd = open([self fileSystemRepresentationWithPath: source],
GSBINIO|O_RDONLY);
#ifdef __ANDROID__
if (sourceFd < 0)
{
// Android: try using asset manager if path is in main bundle resources
asset = [NSBundle assetForPath: source withMode: AASSET_MODE_STREAMING];
}
if (sourceFd < 0 && asset == NULL)
#else
if (sourceFd < 0)
#endif
{
return [self _proceedAccordingToHandler: handler
forError: @"cannot open file for reading"
@ -2873,6 +2964,13 @@ static inline void gsedRelease(GSEnumeratedDirectory X)
GSBINIO|O_WRONLY|O_CREAT|O_TRUNC, fileMode);
if (destFd < 0)
{
#ifdef __ANDROID__
if (asset)
{
AAsset_close(asset);
}
else
#endif
close (sourceFd);
return [self _proceedAccordingToHandler: handler
@ -2886,6 +2984,13 @@ static inline void gsedRelease(GSEnumeratedDirectory X)
file. In case of errors call the handler and abort the operation. */
for (i = 0; i < fileSize; i += rbytes)
{
#ifdef __ANDROID__
if (asset)
{
rbytes = AAsset_read(asset, buffer, bufsize);
}
else
#endif
rbytes = read (sourceFd, buffer, bufsize);
if (rbytes <= 0)
{
@ -2893,6 +2998,13 @@ static inline void gsedRelease(GSEnumeratedDirectory X)
{
break; // End of input file
}
#ifdef __ANDROID__
if (asset)
{
AAsset_close(asset);
}
else
#endif
close (sourceFd);
close (destFd);
@ -2906,6 +3018,13 @@ static inline void gsedRelease(GSEnumeratedDirectory X)
wbytes = write (destFd, buffer, rbytes);
if (wbytes != rbytes)
{
#ifdef __ANDROID__
if (asset)
{
AAsset_close(asset);
}
else
#endif
close (sourceFd);
close (destFd);
@ -2916,6 +3035,13 @@ static inline void gsedRelease(GSEnumeratedDirectory X)
toPath: destination];
}
}
#ifdef __ANDROID__
if (asset)
{
AAsset_close(asset);
}
else
#endif
close (sourceFd);
close (destFd);
@ -3252,12 +3378,16 @@ static inline void gsedRelease(GSEnumeratedDirectory X)
static NSSet *fileKeys = nil;
+ (NSDictionary*) attributesAt: (const _CHAR*)lpath
+ (NSDictionary*) attributesAt: (NSString *)path
traverseLink: (BOOL)traverse
{
GSAttrDictionary *d;
unsigned l = 0;
unsigned i;
const _CHAR *lpath = [defaultManager fileSystemRepresentationWithPath: path];
#ifdef __ANDROID__
AAsset *asset = NULL;
#endif
if (lpath == 0 || *lpath == 0)
{
@ -3275,6 +3405,13 @@ static NSSet *fileKeys = nil;
{
if (lstat(lpath, &d->statbuf) != 0)
{
#ifdef __ANDROID__
/* Android: try using asset manager if path is in
* main bundle resources
*/
asset = [NSBundle assetForPath: path];
if (asset == NULL)
#endif
DESTROY(d);
}
}
@ -3282,6 +3419,11 @@ static NSSet *fileKeys = nil;
#endif
if (_STAT(lpath, &d->statbuf) != 0)
{
#ifdef __ANDROID__
// Android: try using asset manager if path is in main bundle resources
asset = [NSBundle assetForPath: path];
if (asset == NULL)
#endif
DESTROY(d);
}
if (d != nil)
@ -3290,6 +3432,16 @@ static NSSet *fileKeys = nil;
{
d->_path[i] = lpath[i];
}
#ifdef __ANDROID__
if (asset)
{
// set some basic stat values for Android assets
memset(&d->statbuf, 0, sizeof(d->statbuf));
d->statbuf.st_mode = S_IRUSR;
d->statbuf.st_size = AAsset_getLength(asset);
AAsset_close(asset);
}
#endif
}
return AUTORELEASE(d);
}

View file

@ -181,8 +181,10 @@ _NSLog_standard_printf_handler(NSString* message)
#else
#if defined(HAVE_SYSLOG)
#ifndef __ANDROID__ // always use syslog on Android (no stdout/stderr)
if (GSPrivateDefaultsFlag(GSLogSyslog) == YES
|| write(_NSLogDescriptor, buf, len) != (int)len)
#endif
{
null_terminated_buf = malloc(sizeof (char) * (len + 1));
strncpy (null_terminated_buf, buf, len);

View file

@ -2580,12 +2580,56 @@ GSPrivateMemorySize(NSObject *self, NSHashTable *exclude)
}
@implementation NSObject (MemoryFootprint)
+ (NSUInteger) contentSizeInBytesOf: (NSObject*)instance
excluding: (NSHashTable*)exclude
{
unsigned count;
Ivar *vars;
NSUInteger size = 0;
if (0 != (vars = class_copyIvarList(self, &count)))
{
while (count-- > 0)
{
const char *type = ivar_getTypeEncoding(vars[count]);
type = GSSkipTypeQualifierAndLayoutInfo(type);
if ('@' == *type)
{
NSObject *obj = object_getIvar(instance, vars[count]);
if (obj != nil)
{
size += [obj sizeInBytesExcluding: exclude];
}
}
}
free(vars);
}
return size;
}
+ (NSUInteger) sizeInBytesExcluding: (NSHashTable*)exclude
{
return 0;
}
- (NSUInteger) sizeInBytesExcluding: (NSHashTable*)exclude
{
return GSPrivateMemorySize(self, exclude);
if (0 == NSHashGet(exclude, self))
{
Class c = object_getClass(self);
NSUInteger size = class_getInstanceSize(c);
NSHashInsert(exclude, self);
if (size > 0)
{
while (c != Nil)
{
size += [c contentSizeInBytesOf: self excluding: exclude];
}
c = class_getSuperclass(c);
}
return size;
}
return 0;
}
@end

View file

@ -943,6 +943,35 @@ extern char **__libc_argv;
}
}
#elif defined(__ANDROID__)
+ (void) initialize
{
if (nil == procLock) procLock = [NSRecursiveLock new];
if (self == [NSProcessInfo class]
&& !_gnu_processName && !_gnu_arguments && !_gnu_environment)
{
FILE *f = fopen("/proc/self/cmdline", "r");
if (f)
{
char identifier[BUFSIZ];
fgets(identifier, sizeof(identifier), f);
fclose(f);
// construct fake executable path
char *arg0;
asprintf(&arg0, "/data/data/%s/exe", identifier);
char *argv[] = { arg0 };
_gnu_process_args(sizeof(argv)/sizeof(char *), argv, NULL);
}
else
{
fprintf(stderr, "Failed to read cmdline\n");
}
}
}
#else
+ (void) initialize

View file

@ -62,10 +62,12 @@
#include <math.h>
#include <time.h>
#if HAVE_DISPATCH_GET_MAIN_QUEUE_HANDLE_NP && HAVE_DISPATCH_MAIN_QUEUE_DRAIN_NP
#if HAVE_LIBDISPATCH_RUNLOOP
# define RL_INTEGRATE_DISPATCH 1
# ifdef HAVE_DISPATCH_H
# include <dispatch.h>
# elif HAVE_DISPATCH_PRIVATE_H
# include <dispatch/private.h>
# elif HAVE_DISPATCH_DISPATCH_H
# include <dispatch/dispatch.h>
# endif
@ -398,7 +400,13 @@ static inline BOOL timerInvalidated(NSTimer *t)
@implementation GSMainQueueDrainer
+ (void*) mainQueueFileDescriptor
{
#if HAVE_DISPATCH_GET_MAIN_QUEUE_HANDLE_NP
return (void*)(uintptr_t)dispatch_get_main_queue_handle_np();
#elif HAVE__DISPATCH_GET_MAIN_QUEUE_HANDLE_4CF
return (void*)_dispatch_get_main_queue_handle_4CF();
#else
#error libdispatch missing main queue handle function
#endif
}
- (void) receivedEvent: (void*)data
@ -406,7 +414,13 @@ static inline BOOL timerInvalidated(NSTimer *t)
extra: (void*)extra
forMode: (NSString*)mode
{
#if HAVE_DISPATCH_MAIN_QUEUE_DRAIN_NP
dispatch_main_queue_drain_np();
#elif HAVE__DISPATCH_MAIN_QUEUE_CALLBACK_4CF
_dispatch_main_queue_callback_4CF(NULL)
#else
#error libdispatch missing main queue callback function
#endif
}
@end
#endif

View file

@ -38,21 +38,40 @@
// Dummy implementatation
// cleaner than IFDEF'ing the code everywhere
#if !(HAVE_PTHREAD_SPIN_LOCK)
#warning no spin_locks, using dummy versions
typedef int pthread_spinlock_t;
typedef volatile int pthread_spinlock_t;
int pthread_spin_init(pthread_spinlock_t *lock, int pshared)
{
#if DEBUG
#if DEBUG && !__has_builtin(__sync_bool_compare_and_swap)
fprintf(stderr,"NSThread.m: Warning this platform does not support spin locks - init.\n");
#endif
return 0;
}
int pthread_spin_lock(pthread_spinlock_t *lock)
{
#if __has_builtin(__sync_bool_compare_and_swap)
int count = 0;
// Set the spin lock value to 1 if it is 0.
while(!__sync_bool_compare_and_swap(lock, 0, 1))
{
count++;
if (0 == count % 10)
{
// If it is already 1, let another thread play with the CPU for a
// bit then try again.
sleep(0);
}
}
#else
#warning no spin_locks, using dummy versions
#endif
return 0;
}
int pthread_spin_unlock(pthread_spinlock_t *lock)
{
#if __has_builtin(__sync_bool_compare_and_swap)
__sync_synchronize();
*lock = 0;
#endif
return 0;
}
int pthread_spin_destroy(pthread_spinlock_t *lock)

59
configure vendored
View file

@ -764,7 +764,6 @@ infodir
docdir
oldincludedir
includedir
runstatedir
localstatedir
sharedstatedir
sysconfdir
@ -879,7 +878,6 @@ datadir='${datarootdir}'
sysconfdir='${prefix}/etc'
sharedstatedir='${prefix}/com'
localstatedir='${prefix}/var'
runstatedir='${localstatedir}/run'
includedir='${prefix}/include'
oldincludedir='/usr/include'
docdir='${datarootdir}/doc/${PACKAGE}'
@ -1132,15 +1130,6 @@ do
| -silent | --silent | --silen | --sile | --sil)
silent=yes ;;
-runstatedir | --runstatedir | --runstatedi | --runstated \
| --runstate | --runstat | --runsta | --runst | --runs \
| --run | --ru | --r)
ac_prev=runstatedir ;;
-runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
| --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
| --run=* | --ru=* | --r=*)
runstatedir=$ac_optarg ;;
-sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
ac_prev=sbindir ;;
-sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
@ -1278,7 +1267,7 @@ fi
for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
datadir sysconfdir sharedstatedir localstatedir includedir \
oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
libdir localedir mandir runstatedir
libdir localedir mandir
do
eval ac_val=\$$ac_var
# Remove trailing slashes.
@ -1431,7 +1420,6 @@ Fine tuning of the installation directories:
--sysconfdir=DIR read-only single-machine data [PREFIX/etc]
--sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
--localstatedir=DIR modifiable single-machine data [PREFIX/var]
--runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run]
--libdir=DIR object code libraries [EPREFIX/lib]
--includedir=DIR C header files [PREFIX/include]
--oldincludedir=DIR C header files for non-gcc [/usr/include]
@ -5464,7 +5452,7 @@ else
We can't simply define LARGE_OFF_T to be 9223372036854775807,
since some C++ compilers masquerading as C compilers
incorrectly reject 9223372036854775807. */
#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
&& LARGE_OFF_T % 2147483647 == 1)
? 1 : -1];
@ -5510,7 +5498,7 @@ else
We can't simply define LARGE_OFF_T to be 9223372036854775807,
since some C++ compilers masquerading as C compilers
incorrectly reject 9223372036854775807. */
#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
&& LARGE_OFF_T % 2147483647 == 1)
? 1 : -1];
@ -5534,7 +5522,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
We can't simply define LARGE_OFF_T to be 9223372036854775807,
since some C++ compilers masquerading as C compilers
incorrectly reject 9223372036854775807. */
#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
&& LARGE_OFF_T % 2147483647 == 1)
? 1 : -1];
@ -5579,7 +5567,7 @@ else
We can't simply define LARGE_OFF_T to be 9223372036854775807,
since some C++ compilers masquerading as C compilers
incorrectly reject 9223372036854775807. */
#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
&& LARGE_OFF_T % 2147483647 == 1)
? 1 : -1];
@ -5603,7 +5591,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
We can't simply define LARGE_OFF_T to be 9223372036854775807,
since some C++ compilers masquerading as C compilers
incorrectly reject 9223372036854775807. */
#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
&& LARGE_OFF_T % 2147483647 == 1)
? 1 : -1];
@ -6008,6 +5996,9 @@ case "$target_os" in
LDFLAGS="$LDFLAGS -L/usr/local/lib";;
netbsd*) CPPFLAGS="$CPPFLAGS -I/usr/pkg/include"
LDFLAGS="$LDFLAGS -Wl,-R/usr/pkg/lib -L/usr/pkg/lib";;
linux-android* )
# link against libandroid for native application APIs
LIBS="$LIBS -landroid";;
esac
#--------------------------------------------------------------------
@ -12410,6 +12401,20 @@ else
have_dispatch=no
fi
done
# check for private header which includes runloop integration functions in
# the Swift corelibs libdispatch release
for ac_header in dispatch/private.h
do :
ac_fn_c_check_header_mongrel "$LINENO" "dispatch/private.h" "ac_cv_header_dispatch_private_h" "$ac_includes_default"
if test "x$ac_cv_header_dispatch_private_h" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_DISPATCH_PRIVATE_H 1
_ACEOF
fi
done
fi
@ -12515,10 +12520,24 @@ _ACEOF
fi
done
if test "$ac_cv_func_dispatch_main_queue_drain_np" = "no"; then
if test "$ac_cv_func_dispatch_main_queue_drain_np" = "yes" && test "$ac_cv_func_dispatch_get_main_queue_handle_np" = "yes"; then
HAVE_LIBDISPATCH_RUNLOOP=1
fi
if test "$ac_cv_func_dispatch_get_main_queue_handle_np" = "no"; then
# Check for "_4CF" variants of runloop integration functions provided by the
# Swift corelibs libdispatch release
for ac_func in _dispatch_main_queue_callback_4CF _dispatch_get_main_queue_handle_4CF
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
cat >>confdefs.h <<_ACEOF
#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
_ACEOF
fi
done
if test "$ac_cv_func__dispatch_main_queue_callback_4CF" = "yes" && test "$ac_cv_func__dispatch_get_main_queue_handle_4CF" = "yes"; then
HAVE_LIBDISPATCH_RUNLOOP=1
fi
fi

View file

@ -1246,6 +1246,9 @@ case "$target_os" in
LDFLAGS="$LDFLAGS -L/usr/local/lib";;
netbsd*) CPPFLAGS="$CPPFLAGS -I/usr/pkg/include"
LDFLAGS="$LDFLAGS -Wl,-R/usr/pkg/lib -L/usr/pkg/lib";;
linux-android* )
# link against libandroid for native application APIs
LIBS="$LIBS -landroid";;
esac
#--------------------------------------------------------------------
@ -3357,6 +3360,9 @@ if test $enable_libdispatch = yes; then
AC_CHECK_HEADERS(dispatch.h, have_dispatch=yes, have_dispatch=no)
if test "$have_dispatch" = "no"; then
AC_CHECK_HEADERS(dispatch/dispatch.h, have_dispatch=yes, have_dispatch=no)
# check for private header which includes runloop integration functions in
# the Swift corelibs libdispatch release
AC_CHECK_HEADERS(dispatch/private.h)
fi
if test "$have_dispatch" = "yes"; then
AC_CHECK_LIB(dispatch, dispatch_queue_create, have_dispatch=yes, have_dispatch=no)
@ -3388,10 +3394,13 @@ if test $HAVE_LIBDISPATCH = 1; then
# We check whether we have a variant of libdispatch that allows runloop
# integration
AC_CHECK_FUNCS(dispatch_main_queue_drain_np dispatch_get_main_queue_handle_np)
if test "$ac_cv_func_dispatch_main_queue_drain_np" = "no"; then
if test "$ac_cv_func_dispatch_main_queue_drain_np" = "yes" && test "$ac_cv_func_dispatch_get_main_queue_handle_np" = "yes"; then
HAVE_LIBDISPATCH_RUNLOOP=1
fi
if test "$ac_cv_func_dispatch_get_main_queue_handle_np" = "no"; then
# Check for "_4CF" variants of runloop integration functions provided by the
# Swift corelibs libdispatch release
AC_CHECK_FUNCS(_dispatch_main_queue_callback_4CF _dispatch_get_main_queue_handle_4CF)
if test "$ac_cv_func__dispatch_main_queue_callback_4CF" = "yes" && test "$ac_cv_func__dispatch_get_main_queue_handle_4CF" = "yes"; then
HAVE_LIBDISPATCH_RUNLOOP=1
fi
fi