diff --git a/ChangeLog b/ChangeLog
index 9f9f2e3bc..f04641796 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,59 @@
+2019-05-23 Frederik Seiffert
+
+ * 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//exe" (Android
+ apps don't have a real executable path).
+
+2019-05-20 Frederik Seiffert
+
+ * 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
* Source/NSString.m: Removed public functions which could conflict
diff --git a/Headers/Foundation/NSBundle.h b/Headers/Foundation/NSBundle.h
index ef97f923e..76b8bbb4f 100644
--- a/Headers/Foundation/NSBundle.h
+++ b/Headers/Foundation/NSBundle.h
@@ -36,6 +36,10 @@ extern "C" {
#import
#import
+#ifdef __ANDROID__
+#include
+#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;
*
*/
#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)
diff --git a/Headers/GNUstepBase/config.h.in b/Headers/GNUstepBase/config.h.in
index 390b53603..79896e758 100644
--- a/Headers/GNUstepBase/config.h.in
+++ b/Headers/GNUstepBase/config.h.in
@@ -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 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
diff --git a/Source/GSFileHandle.h b/Source/GSFileHandle.h
index 0db80e679..e4e507180 100644
--- a/Source/GSFileHandle.h
+++ b/Source/GSFileHandle.h
@@ -35,6 +35,10 @@
#include
#endif
+#ifdef __ANDROID__
+#include
+#endif
+
struct sockaddr_in;
/**
@@ -69,6 +73,9 @@ struct sockaddr_in;
#if defined(_WIN32)
WSAEVENT event;
#endif
+#ifdef __ANDROID__
+ AAsset *asset;
+#endif
#endif
}
diff --git a/Source/GSFileHandle.m b/Source/GSFileHandle.m
index 5b91f04ae..cb814ac4a 100644
--- a/Source/GSFileHandle.m
+++ b/Source/GSFileHandle.m
@@ -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)
{
diff --git a/Source/GSTimSort.m b/Source/GSTimSort.m
index fe37f636d..2a9b369e1 100644
--- a/Source/GSTimSort.m
+++ b/Source/GSTimSort.m
@@ -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)
{
diff --git a/Source/NSBundle.m b/Source/NSBundle.m
index 75528649e..309b7e25a 100644
--- a/Source/NSBundle.m
+++ b/Source/NSBundle.m
@@ -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
diff --git a/Source/NSData.m b/Source/NSData.m
index 1a3f507a0..d60c37f88 100644
--- a/Source/NSData.m
+++ b/Source/NSData.m
@@ -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];
diff --git a/Source/NSFileManager.m b/Source/NSFileManager.m
index c741184ca..2770c661c 100644
--- a/Source/NSFileManager.m
+++ b/Source/NSFileManager.m
@@ -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);
}
diff --git a/Source/NSLog.m b/Source/NSLog.m
index 35e6fc4f3..f2bc50718 100644
--- a/Source/NSLog.m
+++ b/Source/NSLog.m
@@ -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);
diff --git a/Source/NSObject.m b/Source/NSObject.m
index eea533cd4..3c0f5569c 100644
--- a/Source/NSObject.m
+++ b/Source/NSObject.m
@@ -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
diff --git a/Source/NSProcessInfo.m b/Source/NSProcessInfo.m
index da94da15c..6f395ee3e 100644
--- a/Source/NSProcessInfo.m
+++ b/Source/NSProcessInfo.m
@@ -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
diff --git a/Source/NSRunLoop.m b/Source/NSRunLoop.m
index 1746fa3d0..962f04c55 100644
--- a/Source/NSRunLoop.m
+++ b/Source/NSRunLoop.m
@@ -62,10 +62,12 @@
#include
#include
-#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
+# elif HAVE_DISPATCH_PRIVATE_H
+# include
# elif HAVE_DISPATCH_DISPATCH_H
# include
# 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
diff --git a/Source/NSThread.m b/Source/NSThread.m
index 9419e28b3..c7b35c7ff 100644
--- a/Source/NSThread.m
+++ b/Source/NSThread.m
@@ -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)
diff --git a/configure b/configure
index dc38115d8..431d93732 100755
--- a/configure
+++ b/configure
@@ -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
diff --git a/configure.ac b/configure.ac
index 2b555fc1d..0636c0350 100644
--- a/configure.ac
+++ b/configure.ac
@@ -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