Index: ChangeLog ================================================================== --- ChangeLog +++ ChangeLog @@ -1,8 +1,55 @@ Legend: * Changes of existing features or bugfixes + New features + +This file only contains the most significant changes. + +ObjFW 0.90 -> ObjFW 0.90.1, 20.08.2017 + * OFData: Fix -[description] + * OFFileManager: Set errno to 0 before readdir() + * OFDate: Add -[localMinute] + * OFTarArchiveEntry: Fix prefix handling for ustar + * OFZIPArchive: Fix uncompressed + data descriptor + * OFArray: Fix MessagePack encoding + * of_asprintf: Don't require set up OFLocalization + * OFGZIPStream: Add missing documentation + * Fix a linker warning on OpenBSD/SPARC64 + * Remove the OFFile b modes from MorphOS + (they were already removed for all other OSes) + +ObjFW 0.8.1 -> ObjFW 0.90, 01.08.2017 + + New classes: OFFileManager, OFGZIPStream, OFTarArchive, OFTarArchiveEntry + OFHMAC, OFSandbox, OFHTTPCookie, OFHTTPCookieManager, + OFLocalization + + New platforms: Nintendo 3DS, MorphOS + + New lookup assembly for platforms: SPARC64/ELF, ARM64/ELF + + New forwarding for: ARM64/ELF + + New tools: objfw-new (to create boilerplate code) + + New options: --disable-unicode-tables + * Required GCC version increased to 4.6 + * OFDataArray was split into OFData and OFMutableData + * OFURL was split into OFURL and OFMutableURL + * Most properties are now nonatomic + (this changes from returned retained + autoreleased to +0 retained) + * Correct handling of encoding on Win32 console + (stream is read and written in UTF-8 and translated to UTF-16 on the fly) + * Runtime is now built as a separate library + + More encodings for strings + * Reworked OFOptionsParser API + * Refactored OFKernelEventObserver + * Better randomization of HTTP header order + * Allow overriding all HTTP headers + * Definition of thread priorities changed + + Key Value Coding + + Exceptions in ObjC++ + * OFHash was renamed to OFCryptoHash + + PBKDF2 + + scrypt + + Xcode project to build for iOS + + String decomposition to NFD + * OFFile modes simplified ('b' removed) ObjFW 0.8 -> ObjFW 0.8.1, 04.10.2015 * Adjust to __nullable / __nonnull being changed to _Nullable / _Nonnull in Clang 3.7 (this fixes compilation with Clang 3.7) * Blocks: Proper handling when called from a byref handler Index: configure.ac ================================================================== --- configure.ac +++ configure.ac @@ -1,6 +1,6 @@ -AC_INIT(ObjFW, 0.9-dev, js@heap.zone) +AC_INIT(ObjFW, 0.90.1, js@heap.zone) BUILDSYS_INIT AS_IF([test configure.ac -nt configure], [ AC_MSG_ERROR([configure.ac is newer than configure! Run autoreconf!]) ]) @@ -23,11 +23,10 @@ OBJCFLAGS="$OBJCFLAGS -noixemul" LDFLAGS="$LDFLAGS -noixemul" enable_files="yes" # Required for reading ENV: AC_SUBST(NOIXEMUL, -noixemul) - AC_SUBST(OBJFW_RT_MORPHOS_LIB, objfw-rt.library) ]) enable_shared="no" enable_threads="no" ;; @@ -655,12 +654,10 @@ AC_SUBST(ENCODINGS_A, "encodings.a") AC_SUBST(ENCODINGS_ENCODINGS_A, "encodings/encodings.a") ]) ]) -AC_CHECK_FUNCS(sigaction) - AC_CHECK_FUNCS(arc4random random, break) AC_CHECK_LIB(dl, dlopen, LIBS="$LIBS -ldl") AC_CHECK_HEADERS_ONCE(dlfcn.h) case "$host_os" in @@ -1040,10 +1037,11 @@ "OFKernelEventObserver_epoll.m") break ]) AS_IF([test x"$with_wii" = x"yes"], [ + AC_DEFINE(HAVE_POLL, 1, [Whether we have poll()]) AC_SUBST(OFKERNELEVENTOBSERVER_POLL_M, "OFKernelEventObserver_poll.m") ], [ AC_CHECK_HEADERS(poll.h) AC_CHECK_FUNC(poll, [ Index: extra.mk.in ================================================================== --- extra.mk.in +++ extra.mk.in @@ -1,15 +1,14 @@ OBJFW_SHARED_LIB = @OBJFW_SHARED_LIB@ OBJFW_STATIC_LIB = @OBJFW_STATIC_LIB@ # When changing: Be sure to also change these in the Xcode project! OBJFW_LIB_MAJOR = 8 -OBJFW_LIB_MINOR = 0 +OBJFW_LIB_MINOR = 1 OBJFW_LIB_MAJOR_MINOR = ${OBJFW_LIB_MAJOR}.${OBJFW_LIB_MINOR} OBJFW_RT_SHARED_LIB = @OBJFW_RT_SHARED_LIB@ OBJFW_RT_STATIC_LIB = @OBJFW_RT_STATIC_LIB@ -OBJFW_RT_MORPHOS_LIB = @OBJFW_RT_MORPHOS_LIB@ OBJFW_RT_LIB_MAJOR = 0 OBJFW_RT_LIB_MINOR = 0 OBJFW_RT_LIB_MAJOR_MINOR = ${OBJFW_RT_LIB_MAJOR}.${OBJFW_RT_LIB_MINOR} OBJFW_BRIDGE_SHARED_LIB = @OBJFW_BRIDGE_SHARED_LIB@ Index: src/OFApplication.m ================================================================== --- src/OFApplication.m +++ src/OFApplication.m @@ -69,16 +69,10 @@ # define asm __asm__ # include # undef asm #endif -#ifdef HAVE_SIGACTION -# ifndef SA_RESTART -# define SA_RESTART 0 -# endif -#endif - @interface OFApplication () - (instancetype)of_init OF_METHOD_FAMILY(init); - (void)of_setArgumentCount: (int *)argc andArgumentValues: (char **[])argv; #ifdef OF_WINDOWS @@ -507,37 +501,19 @@ return _delegate; } - (void)setDelegate: (id )delegate { -#ifdef HAVE_SIGACTION - struct sigaction sa = { .sa_flags = SA_RESTART }; - sigemptyset(&sa.sa_mask); - -# define REGISTER_SIGNAL(sig) \ - if ([delegate respondsToSelector: \ - @selector(applicationDidReceive##sig)]) { \ - _##sig##Handler = (void (*)(id, SEL))[(id)delegate \ - methodForSelector: \ - @selector(applicationDidReceive##sig)]; \ - \ - sa.sa_handler = handle##sig; \ - } else \ - sa.sa_handler = SIG_DFL; \ - \ - OF_ENSURE(sigaction(sig, &sa, NULL) == 0); -#else -# define REGISTER_SIGNAL(sig) \ +#define REGISTER_SIGNAL(sig) \ if ([delegate respondsToSelector: \ @selector(applicationDidReceive##sig)]) { \ _##sig##Handler = (void (*)(id, SEL))[(id)delegate \ methodForSelector: \ @selector(applicationDidReceive##sig)]; \ signal(sig, handle##sig); \ } else \ signal(sig, (void (*)(int))SIG_DFL); -#endif _delegate = delegate; REGISTER_SIGNAL(SIGINT) #ifdef SIGHUP Index: src/OFArray.m ================================================================== --- src/OFArray.m +++ src/OFArray.m @@ -674,11 +674,11 @@ [data addItem: &type]; [data addItems: &tmp count: sizeof(tmp)]; } else if (count <= UINT32_MAX) { - uint8_t type = 0xDC; + uint8_t type = 0xDD; uint32_t tmp = OF_BSWAP32_IF_LE((uint32_t)count); [data addItem: &type]; [data addItems: &tmp count: sizeof(tmp)]; Index: src/OFData.h ================================================================== --- src/OFData.h +++ src/OFData.h @@ -32,11 +32,11 @@ * for OFData with item size 1. */ @interface OFData: OFObject { - char *_items; + unsigned char *_items; size_t _count, _itemSize; bool _freeWhenDone; } /*! Index: src/OFData.m ================================================================== --- src/OFData.m +++ src/OFData.m @@ -183,11 +183,11 @@ @try { if (itemSize == 0) @throw [OFInvalidArgumentException exception]; - _items = (char *)items; + _items = (unsigned char *)items; _itemSize = itemSize; _count = count; _freeWhenDone = freeWhenDone; } @catch (id e) { [self release]; Index: src/OFDate.h ================================================================== --- src/OFDate.h +++ src/OFDate.h @@ -186,10 +186,17 @@ * * @return The minute of the date */ - (uint8_t)minute; +/*! + * @brief Returns the minute of the date in local time. + * + * @return The minute of the date in local time + */ +- (uint8_t)localMinute; + /*! * @brief Returns the hour of the date. * * @return The hour of the date */ Index: src/OFDate.m ================================================================== --- src/OFDate.m +++ src/OFDate.m @@ -451,10 +451,15 @@ - (uint8_t)minute { GMTIME_RET(tm_min) } + +- (uint8_t)localMinute +{ + LOCALTIME_RET(tm_min) +} - (uint8_t)hour { GMTIME_RET(tm_hour) } Index: src/OFFile.m ================================================================== --- src/OFFile.m +++ src/OFFile.m @@ -132,44 +132,26 @@ { *append = false; if (strcmp(mode, "r") == 0) return MODE_OLDFILE; + if (strcmp(mode, "r+") == 0) + return MODE_OLDFILE; if (strcmp(mode, "w") == 0) return MODE_NEWFILE; if (strcmp(mode, "wx") == 0) return MODE_NEWFILE; + if (strcmp(mode, "w+") == 0) + return MODE_NEWFILE; + if (strcmp(mode, "w+x") == 0) + return MODE_NEWFILE; if (strcmp(mode, "a") == 0) { *append = true; return MODE_READWRITE; } - if (strcmp(mode, "rb") == 0) - return MODE_OLDFILE; - if (strcmp(mode, "wb") == 0) - return MODE_NEWFILE; - if (strcmp(mode, "wbx") == 0) - return MODE_NEWFILE; - if (strcmp(mode, "ab") == 0) { - *append = true; - return MODE_READWRITE; - } - if (strcmp(mode, "r+") == 0) - return MODE_OLDFILE; - if (strcmp(mode, "w+") == 0) - return MODE_NEWFILE; if (strcmp(mode, "a+") == 0) { *append = true; - return MODE_READWRITE; - } - if (strcmp(mode, "r+b") == 0 || strcmp(mode, "rb+") == 0) - return MODE_OLDFILE; - if (strcmp(mode, "w+b") == 0 || strcmp(mode, "wb+") == 0) - return MODE_NEWFILE; - if (strcmp(mode, "w+bx") == 0 || strcmp(mode, "wb+x") == 0) - return MODE_NEWFILE; - if (strcmp(mode, "ab+") == 0 || strcmp(mode, "a+b") == 0) { - *append = true; return MODE_READWRITE; } return -1; } Index: src/OFFileManager.m ================================================================== --- src/OFFileManager.m +++ src/OFFileManager.m @@ -571,10 +571,11 @@ errNo: errno]; if (dirent == NULL) break; # else + errno = 0; if ((dirent = readdir(dir)) == NULL) { if (errno == 0) break; else @throw [OFReadFailedException Index: src/OFGZIPStream.h ================================================================== --- src/OFGZIPStream.h +++ src/OFGZIPStream.h @@ -19,10 +19,16 @@ @class OFInflateStream; OF_ASSUME_NONNULL_BEGIN +/*! + * @class OFGZIPStream OFGZIPStream.h ObjFW/OFGZIPStream.h + * + * @brief A class that handles GZIP compression and decompression transparently + * for an underlying stream. + */ @interface OFGZIPStream: OFStream { OFStream *_stream; OFInflateStream *_inflateStream; enum of_gzip_stream_state { @@ -72,11 +78,26 @@ OFDate *_modificationDate; uint16_t _extraLength; uint32_t _CRC32, _uncompressedSize; } +/*! + * @brief Creates a new OFGZIPStream with the specified underlying stream. + * + * @param stream The underlying stream for the OFGZIPStream + * @return A new, autoreleased OFGZIPStream + */ + (instancetype)streamWithStream: (OFStream *)stream; + - init OF_UNAVAILABLE; + +/*! + * @brief Initializes an already allocated OFGZIPStream with the specified + * underlying stream. + * + * @param stream The underlying stream for the OFGZIPStream + * @return An initialized OFGZIPStream + */ - initWithStream: (OFStream *)stream OF_DESIGNATED_INITIALIZER; @end OF_ASSUME_NONNULL_END Index: src/OFMutableURL.m ================================================================== --- src/OFMutableURL.m +++ src/OFMutableURL.m @@ -16,10 +16,11 @@ #include "config.h" #import "OFMutableURL.h" #import "OFURL+Private.h" +#import "OFString.h" @implementation OFMutableURL @dynamic scheme, host, port, user, password, path, parameters, query, fragment; + (instancetype)URL Index: src/OFRunLoop.m ================================================================== --- src/OFRunLoop.m +++ src/OFRunLoop.m @@ -15,10 +15,11 @@ */ #include "config.h" #include +#include #import "OFRunLoop.h" #import "OFRunLoop+Private.h" #import "OFDictionary.h" #ifdef OF_HAVE_SOCKETS @@ -31,10 +32,12 @@ #endif #import "OFSortedList.h" #import "OFTimer.h" #import "OFTimer+Private.h" #import "OFDate.h" + +#import "OFObserveFailedException.h" static OFRunLoop *mainRunLoop = nil; #ifdef OF_HAVE_SOCKETS @interface OFRunLoop_QueueItem: OFObject @@ -717,12 +720,17 @@ if (timeout < 0) timeout = 0; #if defined(OF_HAVE_SOCKETS) - [_kernelEventObserver - observeForTimeInterval: timeout]; + @try { + [_kernelEventObserver + observeForTimeInterval: timeout]; + } @catch (OFObserveFailedException *e) { + if ([e errNo] != EINTR) + @throw e; + } #elif defined(OF_HAVE_THREADS) [_condition lock]; [_condition waitForTimeInterval: timeout]; [_condition unlock]; #else @@ -733,11 +741,16 @@ * No more timers and no deadline: Just watch for I/O * until we get an event. If a timer is added by * another thread, it cancels the observe. */ #if defined(OF_HAVE_SOCKETS) - [_kernelEventObserver observe]; + @try { + [_kernelEventObserver observe]; + } @catch (OFObserveFailedException *e) { + if ([e errNo] != EINTR) + @throw e; + } #elif defined(OF_HAVE_THREADS) [_condition lock]; [_condition wait]; [_condition unlock]; #else Index: src/OFStream.m ================================================================== --- src/OFStream.m +++ src/OFStream.m @@ -56,11 +56,11 @@ #define MIN_READ_SIZE 512 @implementation OFStream @synthesize of_waitingForDelimiter = _waitingForDelimiter; -#if !defined(OF_WINDOWS) && !defined(OF_MORPHOS) +#if defined(SIGPIPE) && defined(SIG_IGN) + (void)initialize { if (self == [OFStream class]) signal(SIGPIPE, SIG_IGN); } Index: src/OFString.h ================================================================== --- src/OFString.h +++ src/OFString.h @@ -18,10 +18,16 @@ # define __STDC_LIMIT_MACROS #endif #ifndef __STDC_CONSTANT_MACROS # define __STDC_CONSTANT_MACROS #endif + +#import "objfw-defs.h" + +#ifdef OF_HAVE_SYS_TYPES_H +# include +#endif #include #include #import "OFObject.h" Index: src/OFTarArchiveEntry.m ================================================================== --- src/OFTarArchiveEntry.m +++ src/OFTarArchiveEntry.m @@ -86,24 +86,28 @@ if (_type == '\0') _type = OF_TAR_ARCHIVE_ENTRY_TYPE_FILE; if (memcmp(header + 257, "ustar\0" "00", 8) == 0) { - OFString *fileName; + OFString *prefix; _owner = [stringFromBuffer(header + 265, 32) copy]; _group = [stringFromBuffer(header + 297, 32) copy]; _deviceMajor = (uint32_t)octalValueFromBuffer( header + 329, 8, UINT32_MAX); _deviceMinor = (uint32_t)octalValueFromBuffer( header + 337, 8, UINT32_MAX); - fileName = [OFString stringWithFormat: @"%@/%@", - stringFromBuffer(header + 345, 155), _fileName]; - [_fileName release]; - _fileName = [fileName copy]; + prefix = stringFromBuffer(header + 345, 155); + if ([prefix length] > 0) { + OFString *fileName = [OFString + stringWithFormat: @"%@/%@", + prefix, _fileName]; + [_fileName release]; + _fileName = [fileName copy]; + } } objc_autoreleasePoolPop(pool); } @catch (id e) { [self release]; Index: src/OFZIPArchive.m ================================================================== --- src/OFZIPArchive.m +++ src/OFZIPArchive.m @@ -71,19 +71,18 @@ @end @interface OFZIPArchive_FileStream: OFStream { OFStream *_stream, *_decompressedStream; - OFZIPArchive_LocalFileHeader *_localFileHeader; - bool _hasDataDescriptor; - uint64_t _size; + OFZIPArchiveEntry *_entry; + uint64_t _toRead; uint32_t _CRC32; bool _atEndOfStream; } - initWithStream: (OFStream *)path - localFileHeader: (OFZIPArchive_LocalFileHeader *)localFileHeader; + entry: (OFZIPArchiveEntry *)localFileHeader; @end uint32_t of_zip_archive_read_field32(const uint8_t **data, uint16_t *size) { @@ -358,11 +357,11 @@ exceptionWithVersion: version]; } _lastReturnedStream = [[OFZIPArchive_FileStream alloc] initWithStream: _stream - localFileHeader: localFileHeader]; + entry: entry]; objc_autoreleasePoolPop(pool); return _lastReturnedStream; } @@ -451,18 +450,18 @@ } @end @implementation OFZIPArchive_FileStream - initWithStream: (OFStream *)stream - localFileHeader: (OFZIPArchive_LocalFileHeader *)localFileHeader + entry: (OFZIPArchiveEntry *)entry { self = [super init]; @try { _stream = [stream retain]; - switch (localFileHeader->_compressionMethod) { + switch ([entry compressionMethod]) { case OF_ZIP_ARCHIVE_ENTRY_COMPRESSION_METHOD_NONE: _decompressedStream = [stream retain]; break; case OF_ZIP_ARCHIVE_ENTRY_COMPRESSION_METHOD_DEFLATE: _decompressedStream = [[OFInflateStream alloc] @@ -476,14 +475,12 @@ @throw [OFNotImplementedException exceptionWithSelector: _cmd object: self]; } - _localFileHeader = [localFileHeader retain]; - _hasDataDescriptor = (localFileHeader->_generalPurposeBitFlag & - (1 << 3)); - _size = localFileHeader->_uncompressedSize; + _entry = [entry retain]; + _toRead = [entry uncompressedSize]; _CRC32 = ~0; } @catch (id e) { [self release]; @throw e; } @@ -493,12 +490,13 @@ - (void)dealloc { [self close]; + [_stream release]; [_decompressedStream release]; - [_localFileHeader release]; + [_entry release]; [super dealloc]; } - (bool)lowlevelIsAtEndOfStream @@ -507,58 +505,36 @@ } - (size_t)lowlevelReadIntoBuffer: (void *)buffer length: (size_t)length { - size_t min, ret; + size_t ret; if (_stream == nil) @throw [OFNotOpenException exceptionWithObject: self]; if (_atEndOfStream) return 0; - if (_hasDataDescriptor) { - if ([_decompressedStream isAtEndOfStream]) { - uint32_t CRC32; - - _atEndOfStream = true; - - CRC32 = [_stream readLittleEndianInt32]; - if (CRC32 == 0x08074B50) - CRC32 = [_stream readLittleEndianInt32]; - - if (~_CRC32 != CRC32) - @throw [OFChecksumFailedException exception]; - - /* - * FIXME: Check (un)compressed length! - * (Note: Both are 64 bit if the entry uses ZIP64!) - */ - - return 0; - } - - ret = [_decompressedStream readIntoBuffer: buffer - length: length]; - } else { - if (_size == 0) { - _atEndOfStream = true; - - if (~_CRC32 != _localFileHeader->_CRC32) - @throw [OFChecksumFailedException exception]; - - return 0; - } - - min = (length < _size ? length : (size_t)_size); - ret = [_decompressedStream readIntoBuffer: buffer - length: min]; - _size -= ret; - } - - _CRC32 = of_crc32(_CRC32, buffer, ret); + if (sizeof(length) >= sizeof(uint64_t) && length > UINT64_MAX) + @throw [OFOutOfRangeException exception]; + + if ((uint64_t)length > _toRead) + length = (size_t)_toRead; + + ret = [_decompressedStream readIntoBuffer: buffer + length: length]; + + if (ret == 0) + _atEndOfStream = true; + + _toRead -= ret; + _CRC32 = of_crc32(_CRC32, buffer, ret); + + if (_toRead == 0) + if (~_CRC32 != [_entry CRC32]) + @throw [OFChecksumFailedException exception]; return ret; } - (void)close Index: src/of_asprintf.m ================================================================== --- src/of_asprintf.m +++ src/of_asprintf.m @@ -558,14 +558,16 @@ @try { OFMutableString *tmpStr = [OFMutableString stringWithUTF8String: tmp length: tmpLen]; - OFString *decimalPoint = + OFString *point = [OFLocalization decimalPoint]; - [tmpStr replaceOccurrencesOfString: decimalPoint - withString: @"."]; + if (point != nil) + [tmpStr + replaceOccurrencesOfString: point + withString: @"."]; if ([tmpStr UTF8StringLength] > INT_MAX) return false; tmpLen = (int)[tmpStr UTF8StringLength]; tmp2 = malloc(tmpLen); memcpy(tmp2, [tmpStr UTF8String], tmpLen); Index: src/runtime/Makefile ================================================================== --- src/runtime/Makefile +++ src/runtime/Makefile @@ -2,11 +2,10 @@ SUBDIRS = lookup-asm SHARED_LIB = ${OBJFW_RT_SHARED_LIB} STATIC_LIB = ${OBJFW_RT_STATIC_LIB} -MORPHOS_LIB = ${OBJFW_RT_MORPHOS_LIB} LIB_MAJOR = ${OBJFW_RT_LIB_MAJOR} LIB_MINOR = ${OBJFW_RT_LIB_MINOR} SRCS = arc.m \ category.m \ @@ -29,22 +28,13 @@ INCLUDES = ObjFW-RT.h includesubdir = ObjFW-RT OBJS_EXTRA = ${LOOKUP_ASM_LOOKUP_ASM_A} LIB_OBJS_EXTRA = ${LOOKUP_ASM_LOOKUP_ASM_LIB_A} -MORPHOS_LIB_OBJS_EXTRA = morphos-library.o ${LOOKUP_ASM_LOOKUP_ASM_A} include ../../buildsys.mk -${MORPHOS_LIB}: ppcinline.h -ppcinline.h: ObjFW-RT.fd protos.h - cvinclude.pl \ - --root ObjFW_RT \ - --fd ObjFW-RT.fd \ - --clib protos.h \ - --inline $@ - CPPFLAGS += -I. -I.. -I../.. \ -DOF_COMPILING_OBJFW_RT \ -DOBJFW_RT_LIB_MAJOR=${OBJFW_RT_LIB_MAJOR} \ -DOBJFW_RT_LIB_MINOR=${OBJFW_RT_LIB_MINOR} LD = ${OBJC} Index: src/runtime/ObjFW-RT.h ================================================================== --- src/runtime/ObjFW-RT.h +++ src/runtime/ObjFW-RT.h @@ -197,14 +197,13 @@ struct objc_protocol_list *_Nullable next; long count; Protocol *__unsafe_unretained _Nonnull list[1]; }; -#if 1 /* !defined(__MORPHOS__) || defined(OF_COMPILING_OBJFW_RT) */ -# ifdef __cplusplus +#ifdef __cplusplus extern "C" { -# endif +#endif extern SEL _Nonnull sel_registerName(const char *_Nonnull); extern const char *_Nonnull sel_getName(SEL _Nonnull); extern bool sel_isEqual(SEL _Nonnull, SEL _Nonnull); extern Class _Nonnull objc_allocateClassPair(Class _Nullable, const char *_Nonnull, size_t); @@ -239,30 +238,11 @@ objc_uncaught_exception_handler _Nullable); extern void objc_setForwardHandler(IMP _Nullable, IMP _Nullable); extern void objc_setEnumerationMutationHandler( objc_enumeration_mutation_handler _Nullable); extern void objc_zero_weak_references(id _Nonnull); -# ifdef __cplusplus -} -# endif -#else -# define BOOL EXEC_BOOL -# include -# undef BOOL -# ifdef __cplusplus -extern "C" { -# endif -extern struct Library *ObjFWRTBase; -# ifdef __cplusplus -} -# endif -# include "ppcinline.h" -#endif - -#ifdef __cplusplus -extern "C" { -#endif + /* * Used by the compiler, but can also be called manually. * * They need to be in the glue code for the MorphOS library. * Index: src/runtime/lookup-asm/lookup-asm-sparc64-elf.S ================================================================== --- src/runtime/lookup-asm/lookup-asm-sparc64-elf.S +++ src/runtime/lookup-asm/lookup-asm-sparc64-elf.S @@ -50,15 +50,20 @@ #endif ldx [%o2 + %o4], %o2 ldx [%o2 + %o5], %o2 cmp %o2, 0 - be,pn %xcc, \not_found + be,pn %xcc, 0f nop retl mov %o2, %o0 + +0: + mov %o7, %g1 + call \not_found + mov %g1, %o7 .type \name, %function .size \name, .-\name .endm .macro generate_lookup_super name lookup DELETED src/runtime/morphos-library.m Index: src/runtime/morphos-library.m ================================================================== --- src/runtime/morphos-library.m +++ src/runtime/morphos-library.m @@ -1,221 +0,0 @@ -/* - * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 - * Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#include "config.h" - -#import "ObjFW-RT.h" -#import "macros.h" - -#define BOOL EXEC_BOOL -#include -#include -#include -#include -#include -#include -#include -#undef BOOL - -struct ObjFWRTBase { - struct Library library; - BPTR seg_list; -}; - -/* Forward declarations for all functions in the func_table */ -static struct Library *lib_init(struct ObjFWRTBase *base, BPTR seg_list, - struct ExecBase *exec_base); -static struct Library *lib_open(void); -static BPTR lib_close(void); -static BPTR lib_expunge(void); -static void lib_null(void); -void objc_set_exit(void OF_NO_RETURN_FUNC (*exit_fn_)(int status)); - -static ULONG func_table[] = { - FUNCARRAY_BEGIN, - FUNCARRAY_32BIT_NATIVE, - (ULONG)lib_open, - (ULONG)lib_close, - (ULONG)lib_expunge, - (ULONG)lib_null, - -1, - FUNCARRAY_32BIT_SYSTEMV, - /* Functions for the glue code */ - (ULONG)objc_set_exit, - /* Used by the compiler - these need glue code */ - (ULONG)__objc_exec_class, - (ULONG)objc_msg_lookup, - (ULONG)objc_msg_lookup_stret, - (ULONG)objc_msg_lookup_super, - (ULONG)objc_msg_lookup_super_stret, - (ULONG)objc_lookUpClass, - (ULONG)objc_getClass, - (ULONG)objc_getRequiredClass, - (ULONG)objc_exception_throw, - (ULONG)objc_sync_enter, - (ULONG)objc_sync_exit, - (ULONG)objc_getProperty, - (ULONG)objc_setProperty, - (ULONG)objc_getPropertyStruct, - (ULONG)objc_setPropertyStruct, - (ULONG)objc_enumerationMutation, - /* Functions declared in ObjFW-RT.h */ - (ULONG)sel_registerName, - (ULONG)sel_getName, - (ULONG)sel_isEqual, - (ULONG)objc_allocateClassPair, - (ULONG)objc_registerClassPair, - (ULONG)objc_getClassList, - (ULONG)objc_copyClassList, - (ULONG)class_isMetaClass, - (ULONG)class_getName, - (ULONG)class_getSuperclass, - (ULONG)class_getInstanceSize, - (ULONG)class_respondsToSelector, - (ULONG)class_conformsToProtocol, - (ULONG)class_getMethodImplementation, - (ULONG)class_getMethodImplementation_stret, - (ULONG)class_getMethodTypeEncoding, - (ULONG)class_addMethod, - (ULONG)class_replaceMethod, - (ULONG)object_getClass, - (ULONG)object_setClass, - (ULONG)object_getClassName, - (ULONG)protocol_getName, - (ULONG)protocol_isEqual, - (ULONG)protocol_conformsToProtocol, - (ULONG)objc_exit, - (ULONG)objc_setUncaughtExceptionHandler, - (ULONG)objc_setForwardHandler, - (ULONG)objc_setEnumerationMutationHandler, - (ULONG)objc_zero_weak_references, - -1, - FUNCARRAY_END -}; - -static struct Library *lib_init(struct ObjFWRTBase *base, BPTR seg_list, - struct ExecBase *exec_base); - -static struct { - LONG struct_size; - ULONG *func_table; - void *data_table; - struct Library *(*init_func)(struct ObjFWRTBase *base, BPTR seg_list, - struct ExecBase *exec_base); -} init_table = { - .struct_size = sizeof(struct ObjFWRTBase), - func_table, - NULL, - lib_init -}; - -static struct Resident resident = { - .rt_MatchWord = RTC_MATCHWORD, - .rt_MatchTag = &resident, - .rt_EndSkip = &resident + 1, - .rt_Flags = RTF_AUTOINIT | RTF_PPC, - .rt_Version = OBJFW_RT_LIB_MAJOR * 10 + OBJFW_RT_LIB_MINOR, - .rt_Type = NT_LIBRARY, - .rt_Pri = 0, - .rt_Name = (char *)"objfw-rt.library", - .rt_IdString = (char *)"ObjFW-RT " PACKAGE_VERSION - " \xA9 2008-2017 Jonathan Schleifer", - .rt_Init = &init_table -}; - -/* Magic required to make this a MorphOS binary */ -const ULONG __abox__ = 1; - -/* Global variables needed by libnix */ -int ThisRequiresConstructorHandling; -struct ExecBase *SysBase; -void *libnix_mempool; - -/* Functions passed in from the glue linklib */ -static void OF_NO_RETURN_FUNC (*exit_fn)(int status); - -void OF_NO_RETURN_FUNC -exit(int status) -{ - exit_fn(status); -} - -void -objc_set_exit(void OF_NO_RETURN_FUNC (*exit_fn_)(int status)) -{ - exit_fn = exit_fn_; -} - -/* Standard library functions */ -static struct Library *lib_init(struct ObjFWRTBase *base, BPTR seg_list, - struct ExecBase *exec_base) -{ - SysBase = exec_base; - - base->seg_list = seg_list; - - return &base->library; -} - -static struct Library * -lib_open(void) -{ - struct ObjFWRTBase *base = (struct ObjFWRTBase *)REG_A6; - - base->library.lib_OpenCnt++; - base->library.lib_Flags &= ~LIBF_DELEXP; - - return &base->library; -} - -static BPTR -expunge(struct ObjFWRTBase *base) -{ - /* Still in use - set delayed expunge flag and refuse to expunge */ - if (base->library.lib_OpenCnt > 0) { - base->library.lib_Flags |= LIBF_DELEXP; - return 0; - } - - Remove(&base->library.lib_Node); - FreeMem((char *)base - base->library.lib_NegSize, - base->library.lib_NegSize + base->library.lib_PosSize); - - return base->seg_list; -} - -static BPTR -lib_close(void) -{ - struct ObjFWRTBase *base = (struct ObjFWRTBase *)REG_A6; - - /* Not used anymore and delayed expunge flag set -> expunge */ - if (--base->library.lib_OpenCnt == 0 && - (base->library.lib_Flags & LIBF_DELEXP)) - return expunge(base); - - return 0; -} - -static BPTR -lib_expunge(void) -{ - return expunge((struct ObjFWRTBase *)REG_A6); -} - -static void -lib_null(void) -{ -} Index: tests/OFBlockTests.m ================================================================== --- tests/OFBlockTests.m +++ tests/OFBlockTests.m @@ -69,13 +69,19 @@ TEST(@"Class of stack block", (Class)&_NSConcreteStackBlock == objc_getClass("OFStackBlock") && [s isKindOfClass: [OFBlock class]]) +#if !defined(OF_WINDOWS) || !defined(__clang__) + /* + * Causes a linker error on Windows with Clang when compiling as a + * static library. This is a bug in Clang. + */ TEST(@"Class of global block", (Class)&_NSConcreteGlobalBlock == objc_getClass("OFGlobalBlock") && [g isKindOfClass: [OFBlock class]]) +#endif TEST(@"Class of a malloc block", (Class)&_NSConcreteMallocBlock == objc_getClass("OFMallocBlock")) TEST(@"Copying a stack block", Index: tests/OFKernelEventObserverTests.m ================================================================== --- tests/OFKernelEventObserverTests.m +++ tests/OFKernelEventObserverTests.m @@ -20,21 +20,21 @@ #import "OFString.h" #import "OFDate.h" #import "OFTCPSocket.h" #import "OFAutoreleasePool.h" -#if defined(HAVE_SYS_SELECT_H) || defined(OF_WINDOWS) -# import "OFKernelEventObserver_select.h" -#endif -#if defined(HAVE_POLL_H) || defined(OF_WII) -# import "OFKernelEventObserver_poll.h" +#ifdef HAVE_KQUEUE +# import "OFKernelEventObserver_kqueue.h" #endif #ifdef HAVE_EPOLL # import "OFKernelEventObserver_epoll.h" #endif -#ifdef HAVE_KQUEUE -# import "OFKernelEventObserver_kqueue.h" +#ifdef HAVE_POLL +# import "OFKernelEventObserver_poll.h" +#endif +#ifdef HAVE_SELECT +# import "OFKernelEventObserver_select.h" #endif #import "TestsAppDelegate.h" #define EXPECTED_EVENTS 3 @@ -201,10 +201,11 @@ @end @implementation TestsAppDelegate (OFKernelEventObserverTests) - (void)kernelEventObserverTestsWithClass: (Class)class { + OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; ObserverTest *test; module = [class className]; test = [[[ObserverTest alloc] initWithTestsAppDelegate: self] autorelease]; @@ -216,22 +217,22 @@ TEST(@"-[addObjectForReading:]", R([test->_observer addObjectForReading: test->_server])) [test run]; _fails += test->_fails; + + [pool drain]; } - (void)kernelEventObserverTests { - OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; - -#if defined(HAVE_SYS_SELECT_H) || defined(OF_WINDOWS) +#ifdef HAVE_SELECT [self kernelEventObserverTestsWithClass: [OFKernelEventObserver_select class]]; #endif -#if defined(HAVE_POLL_H) || defined(OF_WII) +#ifdef HAVE_POLL [self kernelEventObserverTestsWithClass: [OFKernelEventObserver_poll class]]; #endif #ifdef HAVE_EPOLL @@ -241,9 +242,7 @@ #ifdef HAVE_KQUEUE [self kernelEventObserverTestsWithClass: [OFKernelEventObserver_kqueue class]]; #endif - - [pool drain]; } @end