ADDED .cirrus.yml Index: .cirrus.yml ================================================================== --- .cirrus.yml +++ .cirrus.yml @@ -0,0 +1,22 @@ +task: + name: FreeBSD 12.1 + freebsd_instance: + image_family: freebsd-12-1 + install_script: + pkg install -y autoconf automake + shared_script: + - ./autogen.sh + - ./configure + - make -j4 install + static_script: + - ./autogen.sh + - ./configure --disable-shared + - make -j4 install + shared_seluid24_script: + - ./autogen.sh + - ./configure --enable-seluid24 + - make -j4 install + static_seluid24_script: + - ./autogen.sh + - ./configure --disable-shared --enable-seluid24 + - make -j4 install Index: .fossil-settings/clean-glob ================================================================== --- .fossil-settings/clean-glob +++ .fossil-settings/clean-glob @@ -19,19 +19,19 @@ config.h config.h.in config.log config.status configure -DerivedData docs extra.mk generators/gen_tables src/Info.plist src/bridge/Info.plist src/objfw-defs.h src/runtime/amiga-library-functable.inc src/runtime/inline.h +tests/DerivedData tests/EBOOT.PBP tests/Info.plist tests/PARAM.SFO tests/objc_sync/objc_sync tests/plugin/Info.plist Index: .fossil-settings/ignore-glob ================================================================== --- .fossil-settings/ignore-glob +++ .fossil-settings/ignore-glob @@ -21,19 +21,19 @@ config.h config.h.in config.log config.status configure -DerivedData docs extra.mk generators/gen_tables src/Info.plist src/bridge/Info.plist src/objfw-defs.h src/runtime/amiga-library-functable.inc src/runtime/inline.h +tests/DerivedData tests/EBOOT.PBP tests/Info.plist tests/PARAM.SFO tests/iOS.xcodeproj/*.pbxuser tests/iOS.xcodeproj/project.xcworkspace Index: .gitignore ================================================================== --- .gitignore +++ .gitignore @@ -21,19 +21,19 @@ config.h config.h.in config.log config.status configure -DerivedData docs extra.mk generators/gen_tables src/Info.plist src/bridge/Info.plist src/objfw-defs.h src/runtime/amiga-library-functable.inc src/runtime/inline.h +tests/DerivedData tests/EBOOT.PBP tests/Info.plist tests/PARAM.SFO tests/iOS.xcodeproj/*.pbxuser tests/iOS.xcodeproj/project.xcworkspace Index: .travis.yml ================================================================== --- .travis.yml +++ .travis.yml @@ -223,23 +223,23 @@ env: - config=amigaos # Nintendo 3DS - os: linux - dist: trusty + dist: bionic env: - config=nintendo_3ds # Nintendo DS - os: linux - dist: trusty + dist: bionic env: - config=nintendo_ds # Nintendo Wii - os: linux - dist: trusty + dist: bionic env: - config=wii before_install: - if [ "$TRAVIS_OS_NAME" = "linux" -a -z "$config" ]; then @@ -266,12 +266,14 @@ fi; fi - if [ "$config" = "nintendo_3ds" -o "$config" = "nintendo_ds" -o "$config" = "wii" ]; then - wget https://github.com/devkitPro/pacman/releases/download/devkitpro-pacman-1.0.1/devkitpro-pacman.deb; - sudo dpkg -i devkitpro-pacman.deb; + deb=devkitpro-pacman.amd64.deb; + wget https://github.com/devkitPro/pacman/releases/download/v1.0.2/$deb; + sudo apt install gdebi; + sudo gdebi -n $deb; fi - if [ "$config" = "nintendo_3ds" ]; then sudo dkp-pacman --noconfirm -Syu 3ds-dev; fi @@ -288,18 +290,10 @@ wget -q https://franke.ms/download/amiga-gcc.tgz; tar -C / -xzf amiga-gcc.tgz; fi script: - # This needs to use ed on macOS, as it has no GNU sed, and sed on Linux, as - # some Travis hosts have no ed. - - if [ "$TRAVIS_OS_NAME" = "osx" ]; then - echo -e '%s/-DSTDOUT$/&_SIMPLE/\nwq' | ed -s tests/Makefile; - else - sed -i 's/-DSTDOUT$/&_SIMPLE/' tests/Makefile; - fi - - build() { if ! git clean -fxd >/tmp/clean_log 2>&1; then cat /tmp/clean_log; exit 1; fi; Index: Makefile ================================================================== --- Makefile +++ Makefile @@ -10,13 +10,19 @@ config.status \ extra.mk include buildsys.mk +.PHONY: docs tarball + utils tests: src -tarball: +docs: + rm -fr docs + doxygen >/dev/null + +tarball: docs echo "Generating tarball for version ${PACKAGE_VERSION}..." rm -fr objfw-${PACKAGE_VERSION} objfw-${PACKAGE_VERSION}.tar \ objfw-${PACKAGE_VERSION}.tar.gz fossil tarball --name objfw-${PACKAGE_VERSION} current - \ --exclude '.fossil-settings/*,.gitignore,.travis.yml' | \ Index: PLATFORMS.md ================================================================== --- PLATFORMS.md +++ PLATFORMS.md @@ -77,22 +77,23 @@ Linux ----- - * Architectures: Alpha, ARMv6, ARM64, Itanium, m68k, MIPS (O32), RISC-V 64, - PowerPC, S390x, SH4, x86, x86_64 - * Compilers: Clang 3.0-9.0, GCC 4.6-8.2 + * Architectures: Alpha, ARMv6, ARMv7, ARM64, Itanium, m68k, MIPS (O32), + MIPS64 (N64), RISC-V 64, PowerPC, S390x, SuperH-4, x86, + x86_64 + * Compilers: Clang 3.0-10.0, GCC 4.6-10.0 * Runtimes: ObjFW macOS ----- * OS Versions: 10.5, 10.7-10.14, Darling - * Architectures: PowerPC, PowerPC 64, x86, x86_64 - * Compilers: Clang 3.1-7.0, GCC 4.2.1 + * Architectures: PowerPC, PowerPC64, x86, x86_64 + * Compilers: Clang 3.1-10.0, GCC 4.2.1 * Runtimes: Apple, ObjFW MorphOS ------- @@ -105,12 +106,13 @@ NetBSD ------ - * OS Versions: 5.1-7.99 - * Architectures: ARM, ARM (big endian, BE8 mode), SPARC, SPARC64, x86, x86_64 + * OS Versions: 5.1-9.0 + * Architectures: ARM, ARM (big endian, BE8 mode), MIPS (O32), SPARC, SPARC64, + x86, x86_64 * Compilers: Clang 3.0-3.2, GCC 4.1.3 & 4.5.3 * Runtimes: ObjFW Nintendo 3DS @@ -134,11 +136,11 @@ OpenBSD ------- - * OS Versions: 5.2-6.5 + * OS Versions: 5.2-6.7 * Architectures: MIPS64, PA-RISC, PowerPC, SPARC64, x86_64 * Compilers: GCC 6.3.0, Clang 4.0 * Runtimes: ObjFW @@ -181,13 +183,16 @@ Windows ------- - * OS Versions: XP (x86), 7 (x64), 8 (x64), 8.1 (x64), 10, Wine (x86 & x64) + * OS Versions: 98 SE, NT 4.0, XP (x86), 7 (x64), 8 (x64), 8.1 (x64), 10, + Wine (x86 & x64) * Architectures: x86, x86_64 - * Compilers: GCC 6.2.0 from msys2 (x86 and x64), Clang 3.9.0 from msys2 (x86) + * Compilers: GCC 5.3.0 & 6.2.0 from msys2 (x86 & x64), + Clang 3.9.0 from msys2 (x86), + Clang 10.0 from msys2 (x86 & x86_64) * Runtimes: ObjFW Others ------ @@ -211,11 +216,12 @@ * ARM (EABI/ELF, Apple/Mach-O) * ARM64 (ARM64/ELF, Apple/Mach-O) * MIPS (O32/ELF, EABI/ELF) * PowerPC (SysV/ELF, EABI/ELF, Apple/Mach-O) + * SPARC (SysV/ELF) * SPARC64 (SysV/ELF) * x86 (SysV/ELF, Apple/Mach-O, Win32/PE) * x86_64 (SysV/ELF, Apple/Mach-O, Mach-O, Win64/PE) Apple/Mach-O means both, the Apple ABI and runtime, while Mach-O means the ObjFW runtime on Mach-O. Index: README.md ================================================================== --- README.md +++ README.md @@ -1,16 +1,21 @@ -ObjFW is a portable, lightweight framework for the Objective C language. It -enables you to write an application in Objective C that will run on any -platform supported by ObjFW without having to worry about differences between -operating systems or various frameworks that you would otherwise need if you -want to be portable. +There are three ways you are probably reading this right now: -See https://objfw.nil.im/ for more information. + * On [ObjFW](https://objfw.nil.im/)'s homepage, via Fossil + * On [GitHub](https://github.com/ObjFW/ObjFW) + * Via an editor or pager, by opening `README.md` from a checkout or tarball + +ObjFW is developed using Fossil, so if you are reading this on GitHub or any +other place, you are most likely using a mirror.

Table of Contents

+ * [What is ObjFW?](#what) + * [License](#license) + * [Releases](#releases) + * [Cloning the repository](#cloning) * [Installation](#installation) * [macOS and iOS](#macos-and-ios) * [Building as a framework](#building-framework) * [Using the macOS or iOS framework in Xcode](#framework-in-xcode) * [Broken Xcode versions](#broken-xcode-versions) @@ -23,13 +28,107 @@ * [Nintendo DS](#nintendo-ds) * [Nintendo 3DS](#nintendo-3ds) * [Wii](#wii) * [Amiga](#amiga) * [Writing your first application with ObjFW](#first-app) + * [Documentation](#documentation) * [Bugs and feature requests](#bugs) + * [Support and community](#support) * [Commercial use](#commercial-use) + +

What is ObjFW?

+ + ObjFW is a portable, lightweight framework for the Objective-C language. It + enables you to write an application in Objective-C that will run on any + [platform](PLATFORMS.md) supported by ObjFW without having to worry about + differences between operating systems or various frameworks you would + otherwise need if you want to be portable. + + It supports all modern Objective-C features when using Clang, but is also + compatible with GCC ≥ 4.6 to allow maximum portability. + + ObjFW is intentionally incompatible with Foundation. This has two reasons: + + * GNUstep already provides a reimplementation of Foundation, which is only + compatible to a certain degree. This means that a developer still needs to + care about differences between frameworks if they want to be portable. The + idea behind ObjFW is that a developer does not need to concern themselves + with portablility and making sure their code works with multiple + frameworks: Instead, if it works it ObjFW on one platform, they can + reasonably expect it to also work with ObjFW on another platform. ObjFW + behaving differently on different operating systems (unless inevitable + because it is a platform-specific part, like the Windows Registry) is + considered a bug and will be fixed. + * Foundation predates a lot of modern Objective-C concepts. The most + prominent one is exceptions, which are only used in Foundation as a + replacement for `abort()`. This results in cumbersome error handling, + especially in initializers, which in Foundation only return `nil` on error + with no indication of what went wrong. It also means that the return of + every `init` call needs to be checked against `nil`. But in the wild, + nobody actually checks *each and every* return from `init` against `nil`, + leading to bugs. ObjFW fixes this by making exceptions a first class + citizen. + + ObjFW also comes with its own lightweight and extremely fast Objective-C + runtime, which in real world use cases was found to be significantly faster + than both GNU's and Apple's runtime. + + +

License

+ + ObjFW is released under three licenses: + + * [QPL](LICENSE.QPL) + * [GPLv2](LICENSE.GPLv2) + * [GPLv3](LICENSE.GPLv3) + + The QPL allows you to use ObjFW in any open source project. Because the GPL + does not allow using code under any other license, ObjFW is also available + under the GPLv2 and GPLv3 to allow GPL-licensed projects to use ObjFW. + + You can pick under which of those three licenses you want to use ObjFW. If + none of them work for you, contact me and we can find a solution. + + +

Releases

+ + Releases of ObjFW, as well as changelogs and the accompanying documentation + can be found [here](https://objfw.nil.im/wiki?name=Releases). + + +

Cloning the repository

+ + ObjFW is developed in a [Fossil](https://fossil-scm.org) repository, with + automatic incremental exports to Git. This means you can either clone the + Fossil repository or the Git repository - it does not make a huge difference. + The main advantage of cloning the Fossil repository over cloning the Git + repository is that you also get all the tickets, wiki pages, etc. + +

Fossil

+ + Clone the Fossil repository like this: + + $ fossil clone https://objfw.nil.im objfw.fossil + $ mkdir objfw && cd objfw + $ fossil open ../objfw.fossil + + You can then use Fossil's web interface to browse the timeline, tickets, + wiki pages, etc.: + + $ fossil ui + + It's also possible to open the same local repository multiple times, so that + you have multiple working directories all backed by the same local + repository. + +

Git

+ + To clone the Git repository, use the following: + + $ git clone https://github.com/ObjFW/ObjFW +

Installation

To install ObjFW, just run the following commands: @@ -142,13 +241,13 @@ For 64 bit binaries: $ pacman -S mingw-w64-x86_64-clang mingw-w64-x86_64-gcc-objc There is nothing wrong with installing them both, as MSYS2 has created two - entries in your start menu: `MinGW-w64 Win32 Shell` and `MinGW-w64 Win64 - Shell`. So if you want to build for 32 or 64 bit, you just start the correct - shell. + entries in your start menu: `MinGW-w64 Win32 Shell` and + `MinGW-w64 Win64 Shell`. So if you want to build for 32 or 64 bit, you just + start the correct shell. Finally, install a few more things needed to build ObjFW: $ pacman -S autoconf automake fossil make @@ -219,18 +318,47 @@ `objfw-compile` is a tool that allows building applications and libraries using ObjFW without needing a full-blown build system. If you want to use your own build system, you can get the necessary flags from `objfw-config`. + +

Documentation

+ + You can find the documentation for released versions of ObjFW + [here](https://objfw.nil.im/docs/). + + In order to build the documentation yourself (necessary to have documentation + for trunk / master), you need to have [Doxygen](https://www.doxygen.nl) + installed. Once installed, you can build the documentation from the root + directory of the repository: + + $ doxygen >/dev/null +

Bugs and feature requests

- If you find any bugs or have feature requests, feel free to send a mail to - js@nil.im! + If you find any bugs or have feature requests, please + [file a new bug](https://objfw.nil.im/tktnew) in the + [bug tracker](https://objfw.nil.im/reportlist). + + Alternatively, feel free to send a mail to js@nil.im! + + +

Support and community

+ + If you have any questions about ObjFW or would like to talk to other ObjFW + users, the following venues are available: + + * The [forum](https://objfw.nil.im/forum) + * A [Matrix](https://matrix.to/#/%23objfw:nil.im) room + * An [IRC channel](irc://chat.freenode.net/#objfw) on Freenode (`#objfw`), + bridged to the Matrix room above + + Please don't hesitate to join any or all of those!

Commercial use

If for whatever reason neither the terms of the QPL nor those of the GPL work for you, a proprietary license for ObjFW including support is available upon request. Just write a mail to js@nil.im and we can find a reasonable solution for both parties. Index: build-aux/m4/buildsys.m4 ================================================================== --- build-aux/m4/buildsys.m4 +++ build-aux/m4/buildsys.m4 @@ -1,11 +1,11 @@ dnl dnl Copyright (c) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2016, 2017, dnl 2018, 2020 dnl Jonathan Schleifer dnl -dnl https://git.nil.im/buildsys.git +dnl https://fossil.nil.im/buildsys dnl dnl Permission to use, copy, modify, and/or distribute this software for any dnl purpose with or without fee is hereby granted, provided that the above dnl copyright notice and this permission notice is present in all copies. dnl Index: buildsys.mk.in ================================================================== --- buildsys.mk.in +++ buildsys.mk.in @@ -1,11 +1,11 @@ # # Copyright (c) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, # 2017, 2018, 2020 # Jonathan Schleifer # -# https://git.nil.im/buildsys.git +# https://fossil.nil.im/buildsys # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted, provided that the above # copyright notice and this permission notice is present in all copies. # @@ -214,11 +214,11 @@ done \ fi ${AMIGA_LIB} ${AMIGA_LIB_NOINST}: ${EXT_DEPS} ${AMIGA_LIB_OBJS_START} ${AMIGA_LIB_OBJS} ${AMIGA_LIB_OBJS_EXTRA} ${LINK_STATUS} - if ${LD} -o $@ ${AMIGA_LIB_OBJS_START} ${AMIGA_LIB_OBJS} ${AMIGA_LIB_OBJS_EXTRA} ${AMIGA_LIB_LDFLAGS} ${LDFLAGS} ${LIBS}; then \ + if ${LD} -o $@ ${AMIGA_LIB_OBJS_START} ${AMIGA_LIB_OBJS} ${AMIGA_LIB_OBJS_EXTRA} ${AMIGA_LIB_LDFLAGS} ${AMIGA_LIB_LIBS}; then \ ${LINK_OK}; \ else \ ${LINK_FAILED}; \ fi Index: configure.ac ================================================================== --- configure.ac +++ configure.ac @@ -58,14 +58,14 @@ AC_SUBST(SFDC_TARGET, m68k-amigaos) AC_SUBST(SFD_FILE, amigaos3.sfd) AC_SUBST(SFDC_INLINE_H, inline.h) dnl For 68000, GCC emits calls to helper functions that dnl do not work properly in a library. - AC_SUBST(AMIGA_LIB_CFLAGS, - "-mcpu=68020 -fbaserel -ffreestanding") + t="-mcpu=68020 -fbaserel -noixemul" + AC_SUBST(AMIGA_LIB_CFLAGS, "$t -ffreestanding") AC_SUBST(AMIGA_LIB_LDFLAGS, - "-mcpu=68020 -fbaserel -resident -nostartfiles") + "$t -resident -nostartfiles") ]) AC_SUBST(LIBBASES_M, libbases.m) ;; powerpc-*-amigaos*) @@ -89,14 +89,14 @@ check_pedantic="no" # Breaks generated inlines AS_IF([test x"$enable_amiga_lib" != x"no"], [ AC_SUBST(OBJFWRT_AMIGA_LIB, objfwrt.library) AC_SUBST(CVINCLUDE_INLINE_H, inline.h) - t="-mresident32 -ffreestanding" + t="-mresident32 -ffreestanding -noixemul" AC_SUBST(AMIGA_LIB_CFLAGS, $t) t="-mresident32 -nostartfiles -nodefaultlibs" - t="$t -lc" + t="$t -noixemul -lc" AC_SUBST(AMIGA_LIB_LDFLAGS, $t) ]) AC_SUBST(LIBBASES_M, libbases.m) ]) @@ -249,10 +249,18 @@ dnl files, but not for assembly files. mips*-*-*) flag="-integrated-as" OBJCFLAGS="$OBJCFLAGS $flag" OBJFW_OBJCFLAGS="$OBJFW_OBJCFLAGS $flag" + ;; + dnl Don't use -no-integrated-as on Darwin. It breaks + dnl building for the iOS simulator. + i?86-*-darwin* | x86_64-*-darwin*) + ;; + dnl Many older Clang versions don't support jmp short. + i?86-*-* | x86_64-*-*) + ASFLAGS="$ASFLAGS -no-integrated-as" ;; dnl Clang's assembler on Windows is not complete yet dnl and cannot compile all .S files. *-*-mingw*) ASFLAGS="$ASFLAGS -no-integrated-as" @@ -597,17 +605,18 @@ ], [ AC_MSG_RESULT(exceptions unavailable!) AC_MSG_ERROR([Exceptions not accepted by compiler!]) ]) - AC_CHECK_FUNC($raise_exception, [], [ - AC_CHECK_LIB(c++, $raise_exception, [ - LIBS="-lc++ -lc++abi -lpthread $LIBS" - ], [ - AC_MSG_ERROR([_Unwind_RaiseException missing!]) - ], [-lc++abi -lpthread]) - ]) + AC_SEARCH_LIBS($raise_exception, [c++abi gcc_s gcc], [ + dnl c++abi requires pthread on OpenBSD + AS_IF([test x"$ac_lib" = x"c++abi"], [ + LIBS="$LIBS -lpthread" + ]) + ], [ + AC_MSG_ERROR([$raise_exception missing!]) + ], [-lpthread]) AC_CHECK_FUNCS(_Unwind_GetDataRelBase _Unwind_GetTextRelBase) ;; "Apple runtime") AC_DEFINE(OF_APPLE_RUNTIME, 1, Index: extra.mk.in ================================================================== --- extra.mk.in +++ extra.mk.in @@ -1,9 +1,8 @@ OBJFW_SHARED_LIB = @OBJFW_SHARED_LIB@ OBJFW_STATIC_LIB = @OBJFW_STATIC_LIB@ OBJFW_FRAMEWORK = @OBJFW_FRAMEWORK@ -# When changing: Be sure to also change these in the Xcode project! OBJFW_LIB_MAJOR = 9 OBJFW_LIB_MINOR = 0 OBJFW_LIB_MAJOR_MINOR = ${OBJFW_LIB_MAJOR}.${OBJFW_LIB_MINOR} OBJFWRT_SHARED_LIB = @OBJFWRT_SHARED_LIB@ Index: src/Makefile ================================================================== --- src/Makefile +++ src/Makefile @@ -1,10 +1,10 @@ include ../extra.mk SUBDIRS = ${RUNTIME} exceptions ${ENCODINGS} forwarding SUBDIRS_AFTER = ${BRIDGE} -DISTCLEAN = objfw-defs.h +DISTCLEAN = Info.plist objfw-defs.h SHARED_LIB = ${OBJFW_SHARED_LIB} STATIC_LIB = ${OBJFW_STATIC_LIB} FRAMEWORK = ${OBJFW_FRAMEWORK} LIB_MAJOR = ${OBJFW_LIB_MAJOR} Index: src/OFAdjacentArray.m ================================================================== --- src/OFAdjacentArray.m +++ src/OFAdjacentArray.m @@ -341,11 +341,11 @@ if (state->state >= count) return 0; state->state = (unsigned long)count; - state->itemsPtr = _array.items; + state->itemsPtr = (id *)_array.items; state->mutationsPtr = (unsigned long *)self; return (int)count; } Index: src/OFApplication.m ================================================================== --- src/OFApplication.m +++ src/OFApplication.m @@ -70,10 +70,11 @@ # define asm __asm__ # include # undef asm #endif +OF_DIRECT_MEMBERS @interface OFApplication () - (instancetype)of_init OF_METHOD_FAMILY(init); - (void)of_setArgumentCount: (int *)argc andArgumentValues: (char **[])argv; #ifdef OF_WINDOWS Index: src/OFArray+Private.h ================================================================== --- src/OFArray+Private.h +++ src/OFArray+Private.h @@ -17,10 +17,11 @@ #import "OFArray.h" OF_ASSUME_NONNULL_BEGIN +OF_DIRECT_MEMBERS @interface OFArrayEnumerator: OFEnumerator { OFArray *_array; size_t _count; unsigned long _mutations; Index: src/OFDNSResolver.h ================================================================== --- src/OFDNSResolver.h +++ src/OFDNSResolver.h @@ -63,11 +63,13 @@ /*! The server returned an error that the domain does not exist */ OF_DNS_RESOLVER_ERROR_SERVER_NAME_ERROR, /*! The server does not have support for the requested query */ OF_DNS_RESOLVER_ERROR_SERVER_NOT_IMPLEMENTED, /*! The server refused the query */ - OF_DNS_RESOLVER_ERROR_SERVER_REFUSED + OF_DNS_RESOLVER_ERROR_SERVER_REFUSED, + /*! There was no name server to query */ + OF_DNS_RESOLVER_ERROR_NO_NAME_SERVER } of_dns_resolver_error_t; /*! * @protocol OFDNSResolverQueryDelegate OFDNSResolver.h ObjFW/OFDNSResolver.h * Index: src/OFDNSResolver.m ================================================================== --- src/OFDNSResolver.m +++ src/OFDNSResolver.m @@ -63,10 +63,11 @@ @interface OFDNSResolver () - (void)of_contextTimedOut: (OFDNSResolverContext *)context; @end +OF_DIRECT_MEMBERS @interface OFDNSResolverContext: OFObject { @public OFDNSQuery *_query; OFNumber *_ID; @@ -816,10 +817,21 @@ ID = [OFNumber numberWithUInt16: (uint16_t)of_random()]; } while ([_queries objectForKey: ID] != nil); if (query.domainName.UTF8StringLength > 253) @throw [OFOutOfRangeException exception]; + + if (_settings->_nameServers.count == 0) { + id exception = [OFDNSQueryFailedException + exceptionWithQuery: query + error: OF_DNS_RESOLVER_ERROR_NO_NAME_SERVER]; + [delegate resolver: self + didPerformQuery: query + response: nil + exception: exception]; + return; + } context = [[[OFDNSResolverContext alloc] initWithQuery: query ID: ID settings: _settings @@ -878,16 +890,14 @@ exception = [OFDNSQueryFailedException exceptionWithQuery: context->_query error: OF_DNS_RESOLVER_ERROR_TIMEOUT]; - if ([context->_delegate respondsToSelector: - @selector(resolver:didPerformQuery:response:exception:)]) - [context->_delegate resolver: self - didPerformQuery: context->_query - response: nil - exception: exception]; + [context->_delegate resolver: self + didPerformQuery: context->_query + response: nil + exception: exception]; } - (bool)of_handleResponseBuffer: (unsigned char *)buffer length: (size_t)length sender: (const of_socket_address_t *)sender @@ -1039,16 +1049,14 @@ } if (exception != nil) response = nil; - if ([context->_delegate respondsToSelector: - @selector(resolver:didPerformQuery:response:exception:)]) - [context->_delegate resolver: self - didPerformQuery: context->_query - response: response - exception: exception]; + [context->_delegate resolver: self + didPerformQuery: context->_query + response: response + exception: exception]; return false; } - (bool)socket: (OFDatagramSocket *)sock @@ -1273,18 +1281,16 @@ exception = [OFDNSQueryFailedException exceptionWithQuery: context->_query error: OF_DNS_RESOLVER_ERROR_CANCELED]; - if ([context->_delegate respondsToSelector: - @selector(resolver:didPerformQuery:response:exception:)]) - [context->_delegate resolver: self - didPerformQuery: context->_query - response: nil - exception: exception]; + [context->_delegate resolver: self + didPerformQuery: context->_query + response: nil + exception: exception]; } [_queries removeAllObjects]; objc_autoreleasePoolPop(pool); } @end Index: src/OFData+CryptoHashing.m ================================================================== --- src/OFData+CryptoHashing.m +++ src/OFData+CryptoHashing.m @@ -29,11 +29,11 @@ #import "OFSHA512Hash.h" int _OFData_CryptoHashing_reference; @implementation OFData (CryptoHashing) -- (OFString *)of_cryptoHashWithClass: (Class )class +- (OFString *)of_cryptoHashWithClass: (Class )class OF_DIRECT { void *pool = objc_autoreleasePoolPush(); id hash = [class cryptoHashWithAllowsSwappableMemory: true]; size_t digestSize = [class digestSize]; Index: src/OFDictionary.m ================================================================== --- src/OFDictionary.m +++ src/OFDictionary.m @@ -46,19 +46,21 @@ @end @interface OFDictionaryPlaceholder: OFDictionary @end +OF_DIRECT_MEMBERS @interface OFDictionaryObjectEnumerator: OFEnumerator { OFDictionary *_dictionary; OFEnumerator *_keyEnumerator; } - (instancetype)initWithDictionary: (OFDictionary *)dictionary; @end +OF_DIRECT_MEMBERS @interface OFURLQueryPartAllowedCharacterSet: OFCharacterSet + (OFCharacterSet *)URLQueryPartAllowedCharacterSet; @end @implementation OFDictionaryPlaceholder @@ -222,11 +224,12 @@ return [[[self alloc] init] autorelease]; } + (instancetype)dictionaryWithDictionary: (OFDictionary *)dictionary { - return [[[self alloc] initWithDictionary: dictionary] autorelease]; + return [[(OFDictionary *)[self alloc] + initWithDictionary: dictionary] autorelease]; } + (instancetype)dictionaryWithObject: (id)object forKey: (id)key { Index: src/OFEnumerator.h ================================================================== --- src/OFEnumerator.h +++ src/OFEnumerator.h @@ -52,11 +52,11 @@ #ifndef NSINTEGER_DEFINED typedef struct { /*! Arbitrary state information for the enumeration */ unsigned long state; /*! Pointer to a C array of objects to return */ - id const __unsafe_unretained _Nullable *_Nullable itemsPtr; + id __unsafe_unretained _Nullable *_Nullable itemsPtr; /*! Arbitrary state information to detect mutations */ unsigned long *_Nullable mutationsPtr; /*! Additional arbitrary state information */ unsigned long extra[5]; } of_fast_enumeration_state_t; Index: src/OFEpollKernelEventObserver.m ================================================================== --- src/OFEpollKernelEventObserver.m +++ src/OFEpollKernelEventObserver.m @@ -90,11 +90,11 @@ [super dealloc]; } - (void)of_addObject: (id)object fileDescriptor: (int)fd - events: (int)addEvents + events: (int)addEvents OF_DIRECT { struct epoll_event event; intptr_t events; events = (intptr_t)[_FDToEvents @@ -113,11 +113,11 @@ forKey: (void *)((intptr_t)fd + 1)]; } - (void)of_removeObject: (id)object fileDescriptor: (int)fd - events: (int)removeEvents + events: (int)removeEvents OF_DIRECT { intptr_t events; events = (intptr_t)[_FDToEvents objectForKey: (void *)((intptr_t)fd + 1)]; Index: src/OFFileURLHandler.h ================================================================== --- src/OFFileURLHandler.h +++ src/OFFileURLHandler.h @@ -18,9 +18,9 @@ #import "OFURLHandler.h" OF_ASSUME_NONNULL_BEGIN @interface OFFileURLHandler: OFURLHandler -+ (bool)of_directoryExistsAtPath: (OFString *)path; ++ (bool)of_directoryExistsAtPath: (OFString *)path OF_DIRECT; @end OF_ASSUME_NONNULL_END Index: src/OFFileURLHandler.m ================================================================== --- src/OFFileURLHandler.m +++ src/OFFileURLHandler.m @@ -16,18 +16,24 @@ */ #include "config.h" #include +#include #ifdef HAVE_DIRENT_H # include #endif #include "unistd_wrapper.h" +#import "platform.h" #ifdef HAVE_SYS_STAT_H # include +#endif +#include +#ifdef OF_WINDOWS +# include #endif #ifdef HAVE_PWD_H # include #endif @@ -107,10 +113,11 @@ #if !defined(HAVE_READDIR_R) && defined(OF_HAVE_THREADS) && !defined(OF_WINDOWS) static OFMutex *readdirMutex; #endif #ifdef OF_WINDOWS +static int (*func__wutime64)(const wchar_t *, struct __utimbuf64 *); static WINAPI BOOLEAN (*func_CreateSymbolicLinkW)(LPCWSTR, LPCWSTR, DWORD); static WINAPI BOOLEAN (*func_CreateHardLinkW)(LPCWSTR, LPCWSTR, LPSECURITY_ATTRIBUTES); #endif @@ -141,10 +148,54 @@ errno = EBUSY; return; } errno = 0; +} +#endif + +#ifdef OF_AMIGAOS +static void +setErrno(void) +{ + switch (IoErr()) { + case ERROR_DELETE_PROTECTED: + case ERROR_READ_PROTECTED: + case ERROR_WRITE_PROTECTED: + errno = EACCES; + break; + case ERROR_DISK_NOT_VALIDATED: + case ERROR_OBJECT_IN_USE: + errno = EBUSY; + break; + case ERROR_OBJECT_EXISTS: + errno = EEXIST; + break; + case ERROR_DIR_NOT_FOUND: + case ERROR_NO_MORE_ENTRIES: + case ERROR_OBJECT_NOT_FOUND: + errno = ENOENT; + break; + case ERROR_NO_FREE_STORE: + errno = ENOMEM; + break; + case ERROR_DISK_FULL: + errno = ENOSPC; + break; + case ERROR_DIRECTORY_NOT_EMPTY: + errno = ENOTEMPTY; + break; + case ERROR_DISK_WRITE_PROTECTED: + errno = EROFS; + break; + case ERROR_RENAME_ACROSS_DEVICES: + errno = EXDEV; + break; + default: + errno = 0; + break; + } } #endif static int of_stat(OFString *path, of_stat_t *buffer) @@ -223,23 +274,11 @@ struct Locale *locale; struct DateStamp *date; if ((lock = Lock([path cStringWithEncoding: [OFLocale encoding]], SHARED_LOCK)) == 0) { - switch (IoErr()) { - case ERROR_OBJECT_IN_USE: - case ERROR_DISK_NOT_VALIDATED: - errno = EBUSY; - break; - case ERROR_OBJECT_NOT_FOUND: - errno = ENOENT; - break; - default: - errno = 0; - break; - } - + setErrno(); return -1; } # ifdef OF_AMIGAOS4 if ((ed = ExamineObjectTags(EX_FileLockInput, lock, TAG_END)) == NULL) { @@ -511,10 +550,14 @@ #if !defined(HAVE_READDIR_R) && !defined(OF_WINDOWS) && defined(OF_HAVE_THREADS) readdirMutex = [[OFMutex alloc] init]; #endif #ifdef OF_WINDOWS + if ((module = LoadLibrary("msvcrt.dll")) != NULL) + func__wutime64 = (int (*)(const wchar_t *, + struct __utimbuf64 *))GetProcAddress(module, "_wutime64"); + if ((module = LoadLibrary("kernel32.dll")) != NULL) { func_CreateSymbolicLinkW = (WINAPI BOOLEAN (*)(LPCWSTR, LPCWSTR, DWORD)) GetProcAddress(module, "CreateSymbolicLinkW"); func_CreateHardLinkW = @@ -595,14 +638,128 @@ objc_autoreleasePoolPop(pool); return ret; } + +- (void)of_setLastAccessDate: (OFDate *)lastAccessDate + andModificationDate: (OFDate *)modificationDate + ofItemAtURL: (OFURL *)URL + attributes: (of_file_attributes_t)attributes OF_DIRECT +{ + OFString *path = URL.fileSystemRepresentation; + of_file_attribute_key_t attributeKey = (modificationDate != nil + ? of_file_attribute_key_modification_date + : of_file_attribute_key_last_access_date); + + if (lastAccessDate == nil) + lastAccessDate = modificationDate; + if (modificationDate == nil) + modificationDate = lastAccessDate; + +#if defined(OF_WINDOWS) + if (func__wutime64 != NULL) { + struct __utimbuf64 times = { + .actime = + (__time64_t)lastAccessDate.timeIntervalSince1970, + .modtime = + (__time64_t)modificationDate.timeIntervalSince1970 + }; + + if (func__wutime64([path UTF16String], ×) != 0) + @throw [OFSetItemAttributesFailedException + exceptionWithURL: URL + attributes: attributes + failedAttribute: attributeKey + errNo: errno]; + } else { + struct _utimbuf times = { + .actime = (time_t)lastAccessDate.timeIntervalSince1970, + .modtime = + (time_t)modificationDate.timeIntervalSince1970 + }; + int status; + + if ([OFSystemInfo isWindowsNT]) + status = _wutime([path UTF16String], ×); + else + status = _utime( + [path cStringWithEncoding: [OFLocale encoding]], + ×); + + if (status != 0) + @throw [OFSetItemAttributesFailedException + exceptionWithURL: URL + attributes: attributes + failedAttribute: attributeKey + errNo: errno]; + } +#elif defined(OF_AMIGAOS) + /* AmigaOS does not support access time. */ + of_time_interval_t modificationTime = + modificationDate.timeIntervalSince1970; + struct Locale *locale; + struct DateStamp date; + + modificationTime -= 252460800; /* 1978-01-01 */ + + if (modificationTime < 0) + @throw [OFOutOfRangeException exception]; + + locale = OpenLocale(NULL); + /* + * FIXME: This does not take DST into account. But unfortunately, there + * is no way to figure out if DST should be in effect for the + * timestamp. + */ + modificationTime -= locale->loc_GMTOffset * 60.0; + CloseLocale(locale); + + date.ds_Days = modificationTime / 86400; + date.ds_Minute = ((LONG)modificationTime % 86400) / 60; + date.ds_Tick = fmod(modificationTime, 60) * TICKS_PER_SECOND; + + if (!SetFileDate([path cStringWithEncoding: [OFLocale encoding]], + &date) != 0) { + setErrno(); + + @throw [OFSetItemAttributesFailedException + exceptionWithURL: URL + attributes: attributes + failedAttribute: attributeKey + errNo: errno]; + } +#else + of_time_interval_t lastAccessTime = + lastAccessDate.timeIntervalSince1970; + of_time_interval_t modificationTime = + modificationDate.timeIntervalSince1970; + struct timeval times[2] = { + { + .tv_sec = (time_t)lastAccessTime, + .tv_usec = + (int)((lastAccessTime - times[0].tv_sec) * 1000) + }, + { + .tv_sec = (time_t)modificationTime, + .tv_usec = + (int)((modificationTime - times[1].tv_sec) * 1000) + }, + }; + + if (utimes([path cStringWithEncoding: [OFLocale encoding]], times) != 0) + @throw [OFSetItemAttributesFailedException + exceptionWithURL: URL + attributes: attributes + failedAttribute: attributeKey + errNo: errno]; +#endif +} - (void)of_setPOSIXPermissions: (OFNumber *)permissions ofItemAtURL: (OFURL *)URL - attributes: (of_file_attributes_t)attributes + attributes: (of_file_attributes_t)attributes OF_DIRECT { #ifdef OF_FILE_MANAGER_SUPPORTS_PERMISSIONS uint16_t mode = permissions.uInt16Value & 0777; OFString *path = URL.fileSystemRepresentation; int status; @@ -628,11 +785,11 @@ - (void)of_setOwner: (OFString *)owner andGroup: (OFString *)group ofItemAtURL: (OFURL *)URL attributeKey: (of_file_attribute_key_t)attributeKey - attributes: (of_file_attributes_t)attributes + attributes: (of_file_attributes_t)attributes OF_DIRECT { #ifdef OF_FILE_MANAGER_SUPPORTS_OWNER OFString *path = URL.fileSystemRepresentation; uid_t uid = -1; gid_t gid = -1; @@ -697,10 +854,11 @@ void *pool = objc_autoreleasePoolPush(); OFEnumerator OF_GENERIC(of_file_attribute_key_t) *keyEnumerator; OFEnumerator *objectEnumerator; of_file_attribute_key_t key; id object; + OFDate *lastAccessDate, *modificationDate; if (URL == nil) @throw [OFInvalidArgumentException exception]; if (![URL.scheme isEqual: _scheme]) @@ -709,11 +867,14 @@ keyEnumerator = [attributes keyEnumerator]; objectEnumerator = [attributes objectEnumerator]; while ((key = [keyEnumerator nextObject]) != nil && (object = [objectEnumerator nextObject]) != nil) { - if ([key isEqual: of_file_attribute_key_posix_permissions]) + if ([key isEqual: of_file_attribute_key_modification_date] || + [key isEqual: of_file_attribute_key_last_access_date]) + continue; + else if ([key isEqual: of_file_attribute_key_posix_permissions]) [self of_setPOSIXPermissions: object ofItemAtURL: URL attributes: attributes]; else if ([key isEqual: of_file_attribute_key_owner]) [self of_setOwner: object @@ -730,10 +891,21 @@ else @throw [OFNotImplementedException exceptionWithSelector: _cmd object: self]; } + + lastAccessDate = [attributes + objectForKey: of_file_attribute_key_last_access_date]; + modificationDate = [attributes + objectForKey: of_file_attribute_key_modification_date]; + + if (lastAccessDate != nil || modificationDate != nil) + [self of_setLastAccessDate: lastAccessDate + andModificationDate: modificationDate + ofItemAtURL: URL + attributes: attributes]; objc_autoreleasePoolPop(pool); } - (bool)fileExistsAtURL: (OFURL *)URL @@ -813,38 +985,15 @@ #elif defined(OF_AMIGAOS) BPTR lock; if ((lock = CreateDir( [path cStringWithEncoding: [OFLocale encoding]])) == 0) { - int errNo; - - switch (IoErr()) { - case ERROR_NO_FREE_STORE: - case ERROR_DISK_FULL: - errNo = ENOSPC; - break; - case ERROR_OBJECT_IN_USE: - case ERROR_DISK_NOT_VALIDATED: - errNo = EBUSY; - break; - case ERROR_OBJECT_EXISTS: - errNo = EEXIST; - break; - case ERROR_OBJECT_NOT_FOUND: - errNo = ENOENT; - break; - case ERROR_DISK_WRITE_PROTECTED: - errNo = EROFS; - break; - default: - errNo = 0; - break; - } + setErrno(); @throw [OFCreateDirectoryFailedException exceptionWithURL: URL - errNo: errNo]; + errNo: errno]; } UnLock(lock); #else if (mkdir([path cStringWithEncoding: [OFLocale encoding]], 0777) != 0) @@ -965,28 +1114,15 @@ of_string_encoding_t encoding = [OFLocale encoding]; BPTR lock; if ((lock = Lock([path cStringWithEncoding: encoding], SHARED_LOCK)) == 0) { - int errNo; - - switch (IoErr()) { - case ERROR_OBJECT_IN_USE: - case ERROR_DISK_NOT_VALIDATED: - errNo = EBUSY; - break; - case ERROR_OBJECT_NOT_FOUND: - errNo = ENOENT; - break; - default: - errNo = 0; - break; - } + setErrno(); @throw [OFOpenItemFailedException exceptionWithURL: URL mode: nil - errNo: errNo]; + errNo: errno]; } @try { # ifdef OF_AMIGAOS4 struct ExamineData *ed; @@ -1201,33 +1337,14 @@ #endif } #ifdef OF_AMIGAOS if (!DeleteFile([path cStringWithEncoding: [OFLocale encoding]])) { - int errNo; - - switch (IoErr()) { - case ERROR_OBJECT_IN_USE: - case ERROR_DISK_NOT_VALIDATED: - errNo = EBUSY; - break; - case ERROR_OBJECT_NOT_FOUND: - errNo = ENOENT; - break; - case ERROR_DISK_WRITE_PROTECTED: - errNo = EROFS; - break; - case ERROR_DELETE_PROTECTED: - errNo = EACCES; - break; - default: - errNo = 0; - break; - } + setErrno(); @throw [OFRemoveItemFailedException exceptionWithURL: URL - errNo: errNo]; + errNo: errno]; } #endif objc_autoreleasePoolPop(pool); } @@ -1337,38 +1454,16 @@ if (!Rename([source.fileSystemRepresentation cStringWithEncoding: encoding], [destination.fileSystemRepresentation cStringWithEncoding: encoding])) { - int errNo; - - switch (IoErr()) { - case ERROR_RENAME_ACROSS_DEVICES: - errNo = EXDEV; - break; - case ERROR_OBJECT_IN_USE: - case ERROR_DISK_NOT_VALIDATED: - errNo = EBUSY; - break; - case ERROR_OBJECT_EXISTS: - errNo = EEXIST; - break; - case ERROR_OBJECT_NOT_FOUND: - errNo = ENOENT; - break; - case ERROR_DISK_WRITE_PROTECTED: - errNo = EROFS; - break; - default: - errNo = 0; - break; - } + setErrno(); @throw [OFMoveItemFailedException exceptionWithSourceURL: source destinationURL: destination - errNo: errNo]; + errNo: errno]; } #else int status; # ifdef OF_WINDOWS Index: src/OFGZIPStream.h ================================================================== --- src/OFGZIPStream.h +++ src/OFGZIPStream.h @@ -38,11 +38,11 @@ OF_GZIP_STREAM_ID2, OF_GZIP_STREAM_COMPRESSION_METHOD, OF_GZIP_STREAM_FLAGS, OF_GZIP_STREAM_MODIFICATION_TIME, OF_GZIP_STREAM_EXTRA_FLAGS, - OF_GZIP_STREAM_OS, + OF_GZIP_STREAM_OPERATING_SYSTEM, OF_GZIP_STREAM_EXTRA_LENGTH, OF_GZIP_STREAM_EXTRA, OF_GZIP_STREAM_NAME, OF_GZIP_STREAM_COMMENT, OF_GZIP_STREAM_HEADER_CRC16, @@ -56,34 +56,51 @@ OF_GZIP_STREAM_FLAG_EXTRA = 0x04, OF_GZIP_STREAM_FLAG_NAME = 0x08, OF_GZIP_STREAM_FLAG_COMMENT = 0x10 } _flags; uint8_t _extraFlags; - enum of_gzip_stream_os { - OF_GZIP_STREAM_OS_FAT = 0, - OF_GZIP_STREAM_OS_AMIGA = 1, - OF_GZIP_STREAM_OS_VMS = 2, - OF_GZIP_STREAM_OS_UNIX = 3, - OF_GZIP_STREAM_OS_VM_CMS = 4, - OF_GZIP_STREAM_OS_ATARI_TOS = 5, - OF_GZIP_STREAM_OS_HPFS = 6, - OF_GZIP_STREAM_OS_MACINTOSH = 7, - OF_GZIP_STREAM_OS_Z_SYSTEM = 8, - OF_GZIP_STREAM_OS_CP_M = 9, - OF_GZIP_STREAM_OS_TOPS_20 = 10, - OF_GZIP_STREAM_OS_NTFS = 11, - OF_GZIP_STREAM_OS_QDO = 12, - OF_GZIP_STREAM_OS_ACORN_RISC_OS = 13, - OF_GZIP_STREAM_OS_UNKNOWN = 255 - } _OS; + enum of_gzip_stream_operating_system { + OF_GZIP_STREAM_OPERATING_SYSTEM_FAT = 0, + OF_GZIP_STREAM_OPERATING_SYSTEM_AMIGA = 1, + OF_GZIP_STREAM_OPERATING_SYSTEM_VMS = 2, + OF_GZIP_STREAM_OPERATING_SYSTEM_UNIX = 3, + OF_GZIP_STREAM_OPERATING_SYSTEM_VM_CMS = 4, + OF_GZIP_STREAM_OPERATING_SYSTEM_ATARI_TOS = 5, + OF_GZIP_STREAM_OPERATING_SYSTEM_HPFS = 6, + OF_GZIP_STREAM_OPERATING_SYSTEM_MACINTOSH = 7, + OF_GZIP_STREAM_OPERATING_SYSTEM_Z_SYSTEM = 8, + OF_GZIP_STREAM_OPERATING_SYSTEM_CP_M = 9, + OF_GZIP_STREAM_OPERATING_SYSTEM_TOPS_20 = 10, + OF_GZIP_STREAM_OPERATING_SYSTEM_NTFS = 11, + OF_GZIP_STREAM_OPERATING_SYSTEM_QDO = 12, + OF_GZIP_STREAM_OPERATING_SYSTEM_ACORN_RISC_OS = 13, + OF_GZIP_STREAM_OPERATING_SYSTEM_UNKNOWN = 255 + } _operatingSystemMadeOn; size_t _bytesRead; uint8_t _buffer[4]; OFDate *_Nullable _modificationDate; uint16_t _extraLength; uint32_t _CRC32, _uncompressedSize; } +/*! + * @brief The operating system on which the data was compressed. + * + * This property is only guaranteed to be available once @ref atEndOfStream is + * true. + */ +@property (readonly, nonatomic) + enum of_gzip_stream_operating_system operatingSystemMadeOn; + +/*! + * @brief The modification date of the original file. + * + * This property is only guaranteed to be available once @ref atEndOfStream is + * true. + */ +@property OF_NULLABLE_PROPERTY (readonly, nonatomic) OFDate *modificationDate; + /*! * @brief Creates a new OFGZIPStream with the specified underlying stream. * * @param stream The underlying stream for the OFGZIPStream * @param mode The mode for the OFGZIPStream. Valid modes are "r" for reading Index: src/OFGZIPStream.m ================================================================== --- src/OFGZIPStream.m +++ src/OFGZIPStream.m @@ -28,10 +28,13 @@ #import "OFNotImplementedException.h" #import "OFNotOpenException.h" #import "OFTruncatedDataException.h" @implementation OFGZIPStream +@synthesize operatingSystemMadeOn = _operatingSystemMadeOn; +@synthesize modificationDate = _modificationDate; + + (instancetype)streamWithStream: (OFStream *)stream mode: (OFString *)mode { return [[[self alloc] initWithStream: stream mode: mode] autorelease]; @@ -52,10 +55,12 @@ @throw [OFNotImplementedException exceptionWithSelector: _cmd object: nil]; _stream = [stream retain]; + _operatingSystemMadeOn = + OF_GZIP_STREAM_OPERATING_SYSTEM_UNKNOWN; _CRC32 = ~0; } @catch (id e) { [self release]; @throw e; } @@ -140,16 +145,16 @@ return 0; _extraFlags = byte; _state++; break; - case OF_GZIP_STREAM_OS: + case OF_GZIP_STREAM_OPERATING_SYSTEM: if ([_stream readIntoBuffer: &byte length: 1] < 1) return 0; - _OS = byte; + _operatingSystemMadeOn = byte; _state++; break; case OF_GZIP_STREAM_EXTRA_LENGTH: if (!(_flags & OF_GZIP_STREAM_FLAG_EXTRA)) { _state += 2; Index: src/OFHTTPClient.m ================================================================== --- src/OFHTTPClient.m +++ src/OFHTTPClient.m @@ -51,10 +51,11 @@ #import "socket_helpers.h" #define REDIRECTS_DEFAULT 10 +OF_DIRECT_MEMBERS @interface OFHTTPClientRequestHandler: OFObject { @public OFHTTPClient *_client; OFHTTPRequest *_request; @@ -70,10 +71,11 @@ redirects: (unsigned int)redirects; - (void)start; - (void)closeAndReconnect; @end +OF_DIRECT_MEMBERS @interface OFHTTPClientRequestBodyStream: OFStream { OFHTTPClientRequestHandler *_handler; OFTCPSocket *_socket; bool _chunked; @@ -83,10 +85,11 @@ - (instancetype)initWithHandler: (OFHTTPClientRequestHandler *)handler socket: (OFTCPSocket *)sock; @end +OF_DIRECT_MEMBERS @interface OFHTTPClientResponse: OFHTTPResponse { OFTCPSocket *_socket; bool _hasContentLength, _chunked, _keepAlive; bool _atEndOfStream, _setAtEndOfStream; @@ -96,10 +99,11 @@ @property (nonatomic, setter=of_setKeepAlive:) bool of_keepAlive; - (instancetype)initWithSocket: (OFTCPSocket *)sock; @end +OF_DIRECT_MEMBERS @interface OFHTTPClientSyncPerformer: OFObject { OFHTTPClient *_client; OFObject *_delegate; OFHTTPResponse *_response; Index: src/OFHTTPResponse.h ================================================================== --- src/OFHTTPResponse.h +++ src/OFHTTPResponse.h @@ -72,11 +72,17 @@ @end #ifdef __cplusplus extern "C" { #endif +/*! + * @brief Returns a description string for the specified HTTP status code. + * + * @param code The HTTP status code to return a description string for + * @return A description string for the specified HTTP status code + */ extern OFString *_Nonnull of_http_status_code_to_string(short code); #ifdef __cplusplus } #endif OF_ASSUME_NONNULL_END Index: src/OFHTTPServer.m ================================================================== --- src/OFHTTPServer.m +++ src/OFHTTPServer.m @@ -55,10 +55,11 @@ */ @interface OFHTTPServer () @end +OF_DIRECT_MEMBERS @interface OFHTTPServerResponse: OFHTTPResponse { OFStreamSocket *_socket; OFHTTPServer *_server; OFHTTPRequest *_request; @@ -68,10 +69,11 @@ - (instancetype)initWithSocket: (OFStreamSocket *)sock server: (OFHTTPServer *)server request: (OFHTTPRequest *)request; @end +OF_DIRECT_MEMBERS @interface OFHTTPServerConnection: OFObject { @public OFStreamSocket *_socket; OFHTTPServer *_server; @@ -96,10 +98,11 @@ - (bool)parseHeaders: (OFString *)line; - (bool)sendErrorAndClose: (short)statusCode; - (void)createResponse; @end +OF_DIRECT_MEMBERS @interface OFHTTPServerRequestBodyStream: OFStream { OFStreamSocket *_socket; bool _chunked; intmax_t _toRead; @@ -110,10 +113,11 @@ chunked: (bool)chunked contentLength: (uintmax_t)contentLength; @end #ifdef OF_HAVE_THREADS +OF_DIRECT_MEMBERS @interface OFHTTPServerThread: OFThread - (void)stop; @end #endif Index: src/OFINICategory+Private.h ================================================================== --- src/OFINICategory+Private.h +++ src/OFINICategory+Private.h @@ -20,14 +20,15 @@ OF_ASSUME_NONNULL_BEGIN @class OFStream; +OF_DIRECT_MEMBERS @interface OFINICategory () - (instancetype)of_initWithName: (OFString *)name OF_METHOD_FAMILY(init); - (void)of_parseLine: (OFString *)line; - (bool)of_writeToStream: (OFStream *)stream encoding: (of_string_encoding_t)encoding first: (bool)first; @end OF_ASSUME_NONNULL_END Index: src/OFINICategory.m ================================================================== --- src/OFINICategory.m +++ src/OFINICategory.m @@ -120,11 +120,11 @@ @end @implementation OFINICategory @synthesize name = _name; -- (instancetype)of_initWithName: (OFString *)name +- (instancetype)of_initWithName: (OFString *)name OF_DIRECT { self = [super init]; @try { _name = [name copy]; Index: src/OFINIFile.m ================================================================== --- src/OFINIFile.m +++ src/OFINIFile.m @@ -27,10 +27,11 @@ #import "OFINICategory+Private.h" #import "OFInvalidFormatException.h" #import "OFOpenItemFailedException.h" +OF_DIRECT_MEMBERS @interface OFINIFile () - (void)of_parseFile: (OFString *)path encoding: (of_string_encoding_t)encoding; @end Index: src/OFINIFileSettings.m ================================================================== --- src/OFINIFileSettings.m +++ src/OFINIFileSettings.m @@ -54,11 +54,11 @@ [super dealloc]; } - (void)of_getCategory: (OFString **)category andKey: (OFString **)key - forPath: (OFString *)path + forPath: (OFString *)path OF_DIRECT { size_t pos = [path rangeOfString: @"." options: OF_STRING_SEARCH_BACKWARDS].location; if (pos == OF_NOT_FOUND) { Index: src/OFKernelEventObserver.m ================================================================== --- src/OFKernelEventObserver.m +++ src/OFKernelEventObserver.m @@ -219,11 +219,11 @@ for (id object in _readObjects) { void *pool = objc_autoreleasePoolPush(); if ([object isKindOfClass: [OFStream class]] && [object hasDataInReadBuffer] && - ![object of_isWaitingForDelimiter]) { + ![(OFStream *)object of_isWaitingForDelimiter]) { if ([_delegate respondsToSelector: @selector(objectIsReadyForReading:)]) [_delegate objectIsReadyForReading: object]; foundInReadBuffer = true; Index: src/OFLHAArchive.m ================================================================== --- src/OFLHAArchive.m +++ src/OFLHAArchive.m @@ -36,10 +36,11 @@ #import "OFNotOpenException.h" #import "OFOutOfRangeException.h" #import "OFTruncatedDataException.h" #import "OFWriteFailedException.h" +OF_DIRECT_MEMBERS @interface OFLHAArchiveFileReadStream: OFStream { OFStream *_stream, *_decompressedStream; OFLHAArchiveEntry *_entry; uint32_t _toRead, _bytesConsumed; @@ -50,10 +51,11 @@ - (instancetype)of_initWithStream: (OFStream *)stream entry: (OFLHAArchiveEntry *)entry; - (void)of_skip; @end +OF_DIRECT_MEMBERS @interface OFLHAArchiveFileWriteStream: OFStream { OFMutableLHAArchiveEntry *_entry; of_string_encoding_t _encoding; OFSeekableStream *_stream; Index: src/OFLHAArchiveEntry+Private.h ================================================================== --- src/OFLHAArchiveEntry+Private.h +++ src/OFLHAArchiveEntry+Private.h @@ -17,10 +17,11 @@ #import "OFLHAArchive.h" OF_ASSUME_NONNULL_BEGIN +OF_DIRECT_MEMBERS @interface OFLHAArchiveEntry () - (instancetype)of_initWithHeader: (char [_Nonnull 21])header stream: (OFStream *)stream encoding: (of_string_encoding_t)encoding OF_METHOD_FAMILY(init); Index: src/OFLHADecompressingStream.h ================================================================== --- src/OFLHADecompressingStream.h +++ src/OFLHADecompressingStream.h @@ -19,10 +19,11 @@ OF_ASSUME_NONNULL_BEGIN #define OF_LHA_DECOMPRESSING_STREAM_BUFFER_SIZE 4096 +OF_DIRECT_MEMBERS @interface OFLHADecompressingStream: OFStream { OFStream *_stream; uint8_t _distanceBits, _dictionaryBits; unsigned char _buffer[OF_LHA_DECOMPRESSING_STREAM_BUFFER_SIZE]; Index: src/OFList.m ================================================================== --- src/OFList.m +++ src/OFList.m @@ -26,10 +26,11 @@ #import "OFArray.h" #import "OFEnumerationMutationException.h" #import "OFInvalidArgumentException.h" +OF_DIRECT_MEMBERS @interface OFListEnumerator: OFEnumerator { OFList *_list; of_list_object_t *_Nullable _current; unsigned long _mutations; Index: src/OFMD5Hash.m ================================================================== --- src/OFMD5Hash.m +++ src/OFMD5Hash.m @@ -26,10 +26,11 @@ #import "OFOutOfRangeException.h" #define DIGEST_SIZE 16 #define BLOCK_SIZE 64 +OF_DIRECT_MEMBERS @interface OFMD5Hash () - (void)of_resetState; @end #define F(a, b, c) (((a) & (b)) | (~(a) & (c))) Index: src/OFMapTable+Private.h ================================================================== --- src/OFMapTable+Private.h +++ src/OFMapTable+Private.h @@ -17,10 +17,11 @@ #import "OFMapTable.h" OF_ASSUME_NONNULL_BEGIN +OF_DIRECT_MEMBERS @interface OFMapTableEnumeratorWrapper: OFEnumerator { OFMapTableEnumerator *_enumerator; id _object; } Index: src/OFMapTable.m ================================================================== --- src/OFMapTable.m +++ src/OFMapTable.m @@ -59,16 +59,18 @@ defaultEqual(void *object1, void *object2) { return (object1 == object2); } +OF_DIRECT_MEMBERS @interface OFMapTable () - (void)of_setObject: (void *)object forKey: (void *)key hash: (uint32_t)hash; @end +OF_DIRECT_MEMBERS @interface OFMapTableEnumerator () - (instancetype)of_initWithMapTable: (OFMapTable *)mapTable buckets: (struct of_map_table_bucket **)buckets capacity: (uint32_t)capacity mutationsPointer: (unsigned long *)mutationsPtr @@ -291,11 +293,11 @@ } return NULL; } -- (void)of_resizeForCount: (uint32_t)count +- (void)of_resizeForCount: (uint32_t)count OF_DIRECT { uint32_t fullness, capacity; struct of_map_table_bucket **buckets; if (count > UINT32_MAX / sizeof(*_buckets) || count > UINT32_MAX / 8) Index: src/OFMutableAdjacentArray.m ================================================================== --- src/OFMutableAdjacentArray.m +++ src/OFMutableAdjacentArray.m @@ -326,11 +326,11 @@ if (state->state >= count) return 0; state->state = (unsigned long)count; - state->itemsPtr = _array.items; + state->itemsPtr = (id *)_array.items; state->mutationsPtr = &_mutations; return (int)count; } Index: src/OFMutableString.m ================================================================== --- src/OFMutableString.m +++ src/OFMutableString.m @@ -233,11 +233,11 @@ #ifdef OF_HAVE_UNICODE_TABLES - (void)of_convertWithWordStartTable: (const of_unichar_t *const [])startTable wordMiddleTable: (const of_unichar_t *const [])middleTable wordStartTableSize: (size_t)startTableSize - wordMiddleTableSize: (size_t)middleTableSize + wordMiddleTableSize: (size_t)middleTableSize OF_DIRECT { void *pool = objc_autoreleasePoolPush(); const of_unichar_t *characters = self.characters; size_t length = self.length; bool isStart = true; @@ -265,10 +265,11 @@ objc_autoreleasePoolPop(pool); } #else - (void)of_convertWithWordStartFunction: (char (*)(char))startFunction wordMiddleFunction: (char (*)(char))middleFunction + OF_DIRECT { void *pool = objc_autoreleasePoolPush(); const of_unichar_t *characters = self.characters; size_t length = self.length; bool isStart = true; Index: src/OFMutableUTF8String.m ================================================================== --- src/OFMutableUTF8String.m +++ src/OFMutableUTF8String.m @@ -71,11 +71,11 @@ } - (void)of_convertWithWordStartTable: (const of_unichar_t *const[])startTable wordMiddleTable: (const of_unichar_t *const[])middleTable wordStartTableSize: (size_t)startTableSize - wordMiddleTableSize: (size_t)middleTableSize + wordMiddleTableSize: (size_t)middleTableSize OF_DIRECT { of_unichar_t *unicodeString; size_t unicodeLen, newCStringLength; size_t i, j; char *newCString; Index: src/OFPollKernelEventObserver.m ================================================================== --- src/OFPollKernelEventObserver.m +++ src/OFPollKernelEventObserver.m @@ -69,11 +69,11 @@ [super dealloc]; } - (void)of_addObject: (id)object fileDescriptor: (int)fd - events: (short)events + events: (short)events OF_DIRECT { struct pollfd *FDs; size_t count; bool found; @@ -108,11 +108,11 @@ } } - (void)of_removeObject: (id)object fileDescriptor: (int)fd - events: (short)events + events: (short)events OF_DIRECT { struct pollfd *FDs; size_t nFDs; if (fd < 0) Index: src/OFRIPEMD160Hash.m ================================================================== --- src/OFRIPEMD160Hash.m +++ src/OFRIPEMD160Hash.m @@ -26,10 +26,11 @@ #import "OFOutOfRangeException.h" #define DIGEST_SIZE 20 #define BLOCK_SIZE 64 +OF_DIRECT_MEMBERS @interface OFRIPEMD160Hash () - (void)of_resetState; @end #define F(a, b, c) ((a) ^ (b) ^ (c)) Index: src/OFRunLoop+Private.h ================================================================== --- src/OFRunLoop+Private.h +++ src/OFRunLoop+Private.h @@ -31,10 +31,11 @@ exception: (nullable id)exception; - (id)of_connectionFailedExceptionForErrNo: (int)errNo; @end #endif +OF_DIRECT_MEMBERS @interface OFRunLoop () + (void)of_setMainRunLoop: (OFRunLoop *)runLoop; #ifdef OF_HAVE_SOCKETS + (void)of_addAsyncReadForStream: (OFStream *) stream Index: src/OFRunLoop.h ================================================================== --- src/OFRunLoop.h +++ src/OFRunLoop.h @@ -47,11 +47,11 @@ extern "C" { #endif /*! * @brief The default mode for an OFRunLoop. */ -extern of_run_loop_mode_t of_run_loop_mode_default; +extern const of_run_loop_mode_t of_run_loop_mode_default; #ifdef __cplusplus } #endif /*! Index: src/OFRunLoop.m ================================================================== --- src/OFRunLoop.m +++ src/OFRunLoop.m @@ -43,11 +43,11 @@ #import "OFTimer+Private.h" #import "OFDate.h" #import "OFObserveFailedException.h" -of_run_loop_mode_t of_run_loop_mode_default = @"of_run_loop_mode_default"; +const of_run_loop_mode_t of_run_loop_mode_default = @"of_run_loop_mode_default"; static OFRunLoop *mainRunLoop = nil; @interface OFRunLoopState: OFObject #ifdef OF_HAVE_SOCKETS @@ -76,10 +76,11 @@ # endif #endif } @end +OF_DIRECT_MEMBERS @interface OFRunLoop () - (OFRunLoopState *)of_stateForMode: (of_run_loop_mode_t)mode create: (bool)create; @end Index: src/OFSHA1Hash.m ================================================================== --- src/OFSHA1Hash.m +++ src/OFSHA1Hash.m @@ -26,10 +26,11 @@ #import "OFOutOfRangeException.h" #define DIGEST_SIZE 20 #define BLOCK_SIZE 64 +OF_DIRECT_MEMBERS @interface OFSHA1Hash () - (void)of_resetState; @end #define F(a, b, c, d) ((d) ^ ((b) & ((c) ^ (d)))) Index: src/OFSPXSocket.m ================================================================== --- src/OFSPXSocket.m +++ src/OFSPXSocket.m @@ -43,10 +43,11 @@ - (bool)of_connectSocketToAddress: (const of_socket_address_t *)address errNo: (int *)errNo; - (void)of_closeSocket; @end +OF_DIRECT_MEMBERS @interface OFSPXSocketAsyncConnectDelegate: OFObject { OFSPXSocket *_socket; unsigned char _node[IPX_NODE_LEN]; uint32_t _network; Index: src/OFSPXStreamSocket.m ================================================================== --- src/OFSPXStreamSocket.m +++ src/OFSPXStreamSocket.m @@ -43,10 +43,11 @@ - (bool)of_connectSocketToAddress: (const of_socket_address_t *)address errNo: (int *)errNo; - (void)of_closeSocket; @end +OF_DIRECT_MEMBERS @interface OFSPXStreamSocketAsyncConnectDelegate: OFObject { OFSPXStreamSocket *_socket; unsigned char _node[IPX_NODE_LEN]; Index: src/OFSelectKernelEventObserver.m ================================================================== --- src/OFSelectKernelEventObserver.m +++ src/OFSelectKernelEventObserver.m @@ -226,12 +226,13 @@ events = select(_maxFD + 1, &readFDs, &writeFDs, NULL, (timeInterval != -1 ? &timeout : NULL)); #endif if (events < 0) - @throw [OFObserveFailedException exceptionWithObserver: self - errNo: errno]; + @throw [OFObserveFailedException + exceptionWithObserver: self + errNo: of_socket_errno()]; #ifdef OF_AMIGAOS if (execSignalMask != 0 && [_delegate respondsToSelector: @selector(execSignalWasReceived:)]) [_delegate execSignalWasReceived: execSignalMask]; Index: src/OFStdIOStream+Private.h ================================================================== --- src/OFStdIOStream+Private.h +++ src/OFStdIOStream+Private.h @@ -17,10 +17,11 @@ #import "OFStdIOStream.h" OF_ASSUME_NONNULL_BEGIN +OF_DIRECT_MEMBERS @interface OFStdIOStream () #ifndef OF_AMIGAOS - (instancetype)of_initWithFileDescriptor: (int)fd OF_METHOD_FAMILY(init); #else - (instancetype)of_initWithHandle: (BPTR)handle Index: src/OFStdIOStream.m ================================================================== --- src/OFStdIOStream.m +++ src/OFStdIOStream.m @@ -41,14 +41,19 @@ #import "OFInvalidArgumentException.h" #import "OFNotOpenException.h" #import "OFOutOfRangeException.h" #import "OFReadFailedException.h" #import "OFWriteFailedException.h" + +#ifdef OF_IOS +# undef HAVE_ISATTY +#endif #ifdef OF_AMIGAOS # include # include +# undef HAVE_ISATTY #endif /* References for static linking */ #ifdef OF_WINDOWS void @@ -96,11 +101,11 @@ date.microsecond / 1000, me, getpid(), msg]; objc_autoreleasePoolPop(pool); } -#if defined(HAVE_ISATTY) && !defined(OF_AMIGAOS) +#ifdef HAVE_ISATTY static int colorToANSI(OFColor *color) { if ([color isEqual: [OFColor black]]) return 30; @@ -386,11 +391,11 @@ return OF_RETAIN_COUNT_MAX; } - (bool)hasTerminal { -#if defined(HAVE_ISATTY) && !defined(OF_AMIGAOS) +#ifdef HAVE_ISATTY return isatty(_fd); #else return false; #endif } @@ -423,11 +428,11 @@ #endif } - (void)setForegroundColor: (OFColor *)color { -#if defined(HAVE_ISATTY) && !defined(OF_AMIGAOS) +#ifdef HAVE_ISATTY int code; if (!isatty(_fd)) return; @@ -438,11 +443,11 @@ #endif } - (void)setBackgroundColor: (OFColor *)color { -#if defined(HAVE_ISATTY) && !defined(OF_AMIGAOS) +#ifdef HAVE_ISATTY int code; if (!isatty(_fd)) return; @@ -453,41 +458,41 @@ #endif } - (void)reset { -#if defined(HAVE_ISATTY) && !defined(OF_AMIGAOS) +#ifdef HAVE_ISATTY if (!isatty(_fd)) return; [self writeString: @"\033[0m"]; #endif } - (void)clear { -#if defined(HAVE_ISATTY) && !defined(OF_AMIGAOS) +#ifdef HAVE_ISATTY if (!isatty(_fd)) return; [self writeString: @"\033[2J"]; #endif } - (void)eraseLine { -#if defined(HAVE_ISATTY) && !defined(OF_AMIGAOS) +#ifdef HAVE_ISATTY if (!isatty(_fd)) return; [self writeString: @"\033[2K"]; #endif } - (void)setCursorColumn: (unsigned int)column { -#if defined(HAVE_ISATTY) && !defined(OF_AMIGAOS) +#ifdef HAVE_ISATTY if (!isatty(_fd)) return; [self writeFormat: @"\033[%uG", column + 1]; #endif @@ -496,11 +501,11 @@ - (void)setCursorPosition: (of_point_t)position { if (position.x < 0 || position.y < 0) @throw [OFInvalidArgumentException exception]; -#if defined(HAVE_ISATTY) && !defined(OF_AMIGAOS) +#ifdef HAVE_ISATTY if (!isatty(_fd)) return; [self writeFormat: @"\033[%u;%uH", (unsigned)position.y + 1, (unsigned)position.x + 1]; @@ -507,11 +512,11 @@ #endif } - (void)setRelativeCursorPosition: (of_point_t)position { -#if defined(HAVE_ISATTY) && !defined(OF_AMIGAOS) +#ifdef HAVE_ISATTY if (!isatty(_fd)) return; if (position.x > 0) [self writeFormat: @"\033[%uC", (unsigned)position.x]; Index: src/OFStream+Private.h ================================================================== --- src/OFStream+Private.h +++ src/OFStream+Private.h @@ -17,11 +17,12 @@ #import "OFStream.h" OF_ASSUME_NONNULL_BEGIN +OF_DIRECT_MEMBERS @interface OFStream () @property (readonly, nonatomic, getter=of_isWaitingForDelimiter) bool of_waitingForDelimiter; @end OF_ASSUME_NONNULL_END Index: src/OFString.m ================================================================== --- src/OFString.m +++ src/OFString.m @@ -86,13 +86,13 @@ @interface OFString () - (size_t)of_getCString: (char *)cString maxLength: (size_t)maxLength encoding: (of_string_encoding_t)encoding - lossy: (bool)lossy; + lossy: (bool)lossy OF_DIRECT; - (const char *)of_cStringWithEncoding: (of_string_encoding_t)encoding - lossy: (bool)lossy; + lossy: (bool)lossy OF_DIRECT; - (OFString *)of_JSONRepresentationWithOptions: (int)options depth: (size_t)depth; @end @interface OFStringPlaceholder: OFString @@ -374,11 +374,11 @@ return (id)[[OFUTF8String alloc] init]; } - (instancetype)initWithUTF8String: (const char *)UTF8String { - id string; + OFUTF8String *string; size_t length; void *storage; length = strlen(UTF8String); string = of_alloc_object([OFUTF8String class], length + 1, 1, &storage); @@ -389,11 +389,11 @@ } - (instancetype)initWithUTF8String: (const char *)UTF8String length: (size_t)UTF8StringLength { - id string; + OFUTF8String *string; void *storage; string = of_alloc_object([OFUTF8String class], UTF8StringLength + 1, 1, &storage); @@ -422,11 +422,11 @@ - (instancetype)initWithCString: (const char *)cString encoding: (of_string_encoding_t)encoding { if (encoding == OF_STRING_ENCODING_UTF_8) { - id string; + OFUTF8String *string; size_t length; void *storage; length = strlen(cString); string = of_alloc_object([OFUTF8String class], length + 1, 1, @@ -444,11 +444,11 @@ - (instancetype)initWithCString: (const char *)cString encoding: (of_string_encoding_t)encoding length: (size_t)cStringLength { if (encoding == OF_STRING_ENCODING_UTF_8) { - id string; + OFUTF8String *string; void *storage; string = of_alloc_object([OFUTF8String class], cStringLength + 1, 1, &storage); Index: src/OFTarArchive.m ================================================================== --- src/OFTarArchive.m +++ src/OFTarArchive.m @@ -32,10 +32,11 @@ #import "OFNotOpenException.h" #import "OFOutOfRangeException.h" #import "OFTruncatedDataException.h" #import "OFWriteFailedException.h" +OF_DIRECT_MEMBERS @interface OFTarArchiveFileReadStream: OFStream { OFTarArchiveEntry *_entry; OFStream *_stream; uint64_t _toRead; @@ -45,10 +46,11 @@ - (instancetype)of_initWithStream: (OFStream *)stream entry: (OFTarArchiveEntry *)entry; - (void)of_skip; @end +OF_DIRECT_MEMBERS @interface OFTarArchiveFileWriteStream: OFStream { OFTarArchiveEntry *_entry; OFStream *_stream; uint64_t _toWrite; Index: src/OFTarArchiveEntry+Private.h ================================================================== --- src/OFTarArchiveEntry+Private.h +++ src/OFTarArchiveEntry+Private.h @@ -20,14 +20,15 @@ OF_ASSUME_NONNULL_BEGIN @class OFStream; +OF_DIRECT_MEMBERS @interface OFTarArchiveEntry () - (instancetype)of_initWithHeader: (unsigned char [_Nonnull 512])header encoding: (of_string_encoding_t)encoding OF_METHOD_FAMILY(init); - (void)of_writeToStream: (OFStream *)stream encoding: (of_string_encoding_t)encoding; @end OF_ASSUME_NONNULL_END Index: src/OFThread+Private.h ================================================================== --- src/OFThread+Private.h +++ src/OFThread+Private.h @@ -18,11 +18,12 @@ #import "OFThread.h" OF_ASSUME_NONNULL_BEGIN #ifdef OF_HAVE_THREADS +OF_DIRECT_MEMBERS @interface OFThread () + (void)of_createMainThread; @end #endif OF_ASSUME_NONNULL_END Index: src/OFTimer+Private.h ================================================================== --- src/OFTimer+Private.h +++ src/OFTimer+Private.h @@ -17,11 +17,12 @@ #import "OFTimer.h" OF_ASSUME_NONNULL_BEGIN +OF_DIRECT_MEMBERS @interface OFTimer () - (void)of_setInRunLoop: (nullable OFRunLoop *)runLoop mode: (nullable of_run_loop_mode_t)mode; @end OF_ASSUME_NONNULL_END Index: src/OFTimer.m ================================================================== --- src/OFTimer.m +++ src/OFTimer.m @@ -327,11 +327,12 @@ object: (id)object1 object: (id)object2 object: (id)object3 object: (id)object4 arguments: (uint8_t)arguments - repeats: (bool)repeats OF_METHOD_FAMILY(init) + repeats: (bool)repeats + OF_METHOD_FAMILY(init) OF_DIRECT { self = [super init]; @try { _fireDate = [fireDate retain]; Index: src/OFUDPSocket+Private.h ================================================================== --- src/OFUDPSocket+Private.h +++ src/OFUDPSocket+Private.h @@ -17,11 +17,12 @@ #import "OFUDPSocket.h" OF_ASSUME_NONNULL_BEGIN +OF_DIRECT_MEMBERS @interface OFUDPSocket () - (uint16_t)of_bindToAddress: (of_socket_address_t *)address extraType: (int)extraType; @end OF_ASSUME_NONNULL_END Index: src/OFUDPSocket.m ================================================================== --- src/OFUDPSocket.m +++ src/OFUDPSocket.m @@ -37,11 +37,11 @@ @implementation OFUDPSocket @dynamic delegate; - (uint16_t)of_bindToAddress: (of_socket_address_t *)address - extraType: (int)extraType + extraType: (int)extraType OF_DIRECT { void *pool = objc_autoreleasePoolPush(); OFString *host; uint16_t port; #if SOCK_CLOEXEC == 0 && defined(HAVE_FCNTL) && defined(FD_CLOEXEC) Index: src/OFURL.m ================================================================== --- src/OFURL.m +++ src/OFURL.m @@ -85,10 +85,11 @@ { URLQueryOrFragmentAllowedCharacterSet = [[OFURLQueryOrFragmentAllowedCharacterSet alloc] init]; } +OF_DIRECT_MEMBERS @interface OFInvertedCharacterSetWithoutPercent: OFCharacterSet { OFCharacterSet *_characterSet; bool (*_characterIsMember)(id, SEL, of_unichar_t); } Index: src/OFUTF8String+Private.h ================================================================== --- src/OFUTF8String+Private.h +++ src/OFUTF8String+Private.h @@ -17,12 +17,13 @@ #import "OFUTF8String.h" OF_ASSUME_NONNULL_BEGIN +OF_DIRECT_MEMBERS @interface OFUTF8String () - (instancetype)of_initWithUTF8String: (const char *)UTF8String length: (size_t)UTF8StringLength storage: (char *)storage OF_METHOD_FAMILY(init); @end OF_ASSUME_NONNULL_END Index: src/OFWindowsRegistryKey.m ================================================================== --- src/OFWindowsRegistryKey.m +++ src/OFWindowsRegistryKey.m @@ -32,10 +32,11 @@ #import "OFInvalidFormatException.h" #import "OFOpenWindowsRegistryKeyFailedException.h" #import "OFOutOfRangeException.h" #import "OFSetWindowsRegistryValueFailedException.h" +OF_DIRECT_MEMBERS @interface OFWindowsRegistryKey () - (instancetype)of_initWithHKey: (HKEY)hKey close: (bool)close; @end Index: src/OFXMLElement.m ================================================================== --- src/OFXMLElement.m +++ src/OFXMLElement.m @@ -426,11 +426,11 @@ } - (OFString *)of_XMLStringWithParent: (OFXMLElement *)parent namespaces: (OFDictionary *)allNamespaces indentation: (unsigned int)indentation - level: (unsigned int)level + level: (unsigned int)level OF_DIRECT { void *pool; char *cString; size_t length, i; OFString *prefix, *parentPrefix; Index: src/OFXMLParser.h ================================================================== --- src/OFXMLParser.h +++ src/OFXMLParser.h @@ -151,12 +151,11 @@ OF_XMLPARSER_IN_CDATA_OPENING, OF_XMLPARSER_IN_CDATA, OF_XMLPARSER_IN_COMMENT_OPENING, OF_XMLPARSER_IN_COMMENT_1, OF_XMLPARSER_IN_COMMENT_2, - OF_XMLPARSER_IN_DOCTYPE, - OF_XMLPARSER_NUM_STATES + OF_XMLPARSER_IN_DOCTYPE } _state; size_t _i, _last; const char *_Nullable _data; OFMutableData *_buffer; OFString *_Nullable _name, *_Nullable _prefix; Index: src/OFXMLParser.m ================================================================== --- src/OFXMLParser.m +++ src/OFXMLParser.m @@ -39,36 +39,59 @@ #import "OFInvalidFormatException.h" #import "OFMalformedXMLException.h" #import "OFOutOfRangeException.h" #import "OFUnboundPrefixException.h" -typedef void (*state_function_t)(id, SEL); -static SEL selectors[OF_XMLPARSER_NUM_STATES]; -static state_function_t lookupTable[OF_XMLPARSER_NUM_STATES]; - @interface OFXMLParser () -- (void)of_inByteOrderMarkState; -- (void)of_outsideTagState; -- (void)of_tagOpenedState; -- (void)of_inProcessingInstructionsState; -- (void)of_inTagNameState; -- (void)of_inCloseTagNameState; -- (void)of_inTagState; -- (void)of_inAttributeNameState; -- (void)of_expectAttributeEqualSignState; -- (void)of_expectAttributeDelimiterState; -- (void)of_inAttributeValueState; -- (void)of_expectTagCloseState; -- (void)of_expectSpaceOrTagCloseState; -- (void)of_inExclamationMarkState; -- (void)of_inCDATAOpeningState; -- (void)of_inCDATAState; -- (void)of_inCommentOpeningState; -- (void)of_inCommentState1; -- (void)of_inCommentState2; -- (void)of_inDOCTYPEState; @end + +static void inByteOrderMarkState(OFXMLParser *); +static void outsideTagState(OFXMLParser *); +static void tagOpenedState(OFXMLParser *); +static void inProcessingInstructionsState(OFXMLParser *); +static void inTagNameState(OFXMLParser *); +static void inCloseTagNameState(OFXMLParser *); +static void inTagState(OFXMLParser *); +static void inAttributeNameState(OFXMLParser *); +static void expectAttributeEqualSignState(OFXMLParser *); +static void expectAttributeDelimiterState(OFXMLParser *); +static void inAttributeValueState(OFXMLParser *); +static void expectTagCloseState(OFXMLParser *); +static void expectSpaceOrTagCloseState(OFXMLParser *); +static void inExclamationMarkState(OFXMLParser *); +static void inCDATAOpeningState(OFXMLParser *); +static void inCDATAState(OFXMLParser *); +static void inCommentOpeningState(OFXMLParser *); +static void inCommentState1(OFXMLParser *); +static void inCommentState2(OFXMLParser *); +static void inDOCTYPEState(OFXMLParser *); +typedef void (*state_function_t)(OFXMLParser *); +static state_function_t lookupTable[] = { + [OF_XMLPARSER_IN_BYTE_ORDER_MARK] = inByteOrderMarkState, + [OF_XMLPARSER_OUTSIDE_TAG] = outsideTagState, + [OF_XMLPARSER_TAG_OPENED] = tagOpenedState, + [OF_XMLPARSER_IN_PROCESSING_INSTRUCTIONS] = + inProcessingInstructionsState, + [OF_XMLPARSER_IN_TAG_NAME] = inTagNameState, + [OF_XMLPARSER_IN_CLOSE_TAG_NAME] = inCloseTagNameState, + [OF_XMLPARSER_IN_TAG] = inTagState, + [OF_XMLPARSER_IN_ATTRIBUTE_NAME] = inAttributeNameState, + [OF_XMLPARSER_EXPECT_ATTRIBUTE_EQUAL_SIGN] = + expectAttributeEqualSignState, + [OF_XMLPARSER_EXPECT_ATTRIBUTE_DELIMITER] = + expectAttributeDelimiterState, + [OF_XMLPARSER_IN_ATTRIBUTE_VALUE] = inAttributeValueState, + [OF_XMLPARSER_EXPECT_TAG_CLOSE] = expectTagCloseState, + [OF_XMLPARSER_EXPECT_SPACE_OR_TAG_CLOSE] = expectSpaceOrTagCloseState, + [OF_XMLPARSER_IN_EXCLAMATION_MARK] = inExclamationMarkState, + [OF_XMLPARSER_IN_CDATA_OPENING] = inCDATAOpeningState, + [OF_XMLPARSER_IN_CDATA] = inCDATAState, + [OF_XMLPARSER_IN_COMMENT_OPENING] = inCommentOpeningState, + [OF_XMLPARSER_IN_COMMENT_1] = inCommentState1, + [OF_XMLPARSER_IN_COMMENT_2] = inCommentState2, + [OF_XMLPARSER_IN_DOCTYPE] = inDOCTYPEState +}; static OF_INLINE void appendToBuffer(OFMutableData *buffer, const char *string, of_string_encoding_t encoding, size_t length) { @@ -165,46 +188,10 @@ } @implementation OFXMLParser @synthesize delegate = _delegate, depthLimit = _depthLimit; -+ (void)initialize -{ - const SEL selectors_[OF_XMLPARSER_NUM_STATES] = { - @selector(of_inByteOrderMarkState), - @selector(of_outsideTagState), - @selector(of_tagOpenedState), - @selector(of_inProcessingInstructionsState), - @selector(of_inTagNameState), - @selector(of_inCloseTagNameState), - @selector(of_inTagState), - @selector(of_inAttributeNameState), - @selector(of_expectAttributeEqualSignState), - @selector(of_expectAttributeDelimiterState), - @selector(of_inAttributeValueState), - @selector(of_expectTagCloseState), - @selector(of_expectSpaceOrTagCloseState), - @selector(of_inExclamationMarkState), - @selector(of_inCDATAOpeningState), - @selector(of_inCDATAState), - @selector(of_inCommentOpeningState), - @selector(of_inCommentState1), - @selector(of_inCommentState2), - @selector(of_inDOCTYPEState) - }; - memcpy(selectors, selectors_, sizeof(selectors_)); - - for (size_t i = 0; i < OF_XMLPARSER_NUM_STATES; i++) { - if (![self instancesRespondToSelector: selectors[i]]) - @throw [OFInitializationFailedException - exceptionWithClass: self]; - - lookupTable[i] = (state_function_t) - [self instanceMethodForSelector: selectors[i]]; - } -} - + (instancetype)parser { return [[[self alloc] init] autorelease]; } @@ -261,11 +248,11 @@ _data = buffer; for (_i = _last = 0; _i < length; _i++) { size_t j = _i; - lookupTable[_state](self, selectors[_state]); + lookupTable[_state](self); /* Ensure we don't count this character twice */ if (_i != j) continue; @@ -317,116 +304,119 @@ [file release]; } } #endif -/* - * The following methods handle the different states of the parser. They are - * looked up in +[initialize] and put in a lookup table to speed things up. - * One dispatch for every character would be way too slow! - */ - -- (void)of_inByteOrderMarkState -{ - if (_data[_i] != "\xEF\xBB\xBF"[_level]) { - if (_level == 0) { - _state = OF_XMLPARSER_OUTSIDE_TAG; - _i--; +static void +inByteOrderMarkState(OFXMLParser *self) +{ + if (self->_data[self->_i] != "\xEF\xBB\xBF"[self->_level]) { + if (self->_level == 0) { + self->_state = OF_XMLPARSER_OUTSIDE_TAG; + self->_i--; return; } @throw [OFMalformedXMLException exceptionWithParser: self]; } - if (_level++ == 2) - _state = OF_XMLPARSER_OUTSIDE_TAG; + if (self->_level++ == 2) + self->_state = OF_XMLPARSER_OUTSIDE_TAG; - _last = _i + 1; + self->_last = self->_i + 1; } /* Not in a tag */ -- (void)of_outsideTagState +static void +outsideTagState(OFXMLParser *self) { size_t length; - if ((_finishedParsing || _previous.count < 1) && _data[_i] != ' ' && - _data[_i] != '\t' && _data[_i] != '\n' && _data[_i] != '\r' && - _data[_i] != '<') + if ((self->_finishedParsing || self->_previous.count < 1) && + self->_data[self->_i] != ' ' && self->_data[self->_i] != '\t' && + self->_data[self->_i] != '\n' && self->_data[self->_i] != '\r' && + self->_data[self->_i] != '<') @throw [OFMalformedXMLException exceptionWithParser: self]; - if (_data[_i] != '<') + if (self->_data[self->_i] != '<') return; - if ((length = _i - _last) > 0) - appendToBuffer(_buffer, _data + _last, _encoding, length); + if ((length = self->_i - self->_last) > 0) + appendToBuffer(self->_buffer, self->_data + self->_last, + self->_encoding, length); - if (_buffer.count > 0) { + if (self->_buffer.count > 0) { void *pool = objc_autoreleasePoolPush(); - OFString *characters = transformString(self, _buffer, 0, true); + OFString *characters = transformString(self, self->_buffer, 0, + true); - if ([_delegate respondsToSelector: + if ([self->_delegate respondsToSelector: @selector(parser:foundCharacters:)]) - [_delegate parser: self - foundCharacters: characters]; + [self->_delegate parser: self + foundCharacters: characters]; objc_autoreleasePoolPop(pool); } - [_buffer removeAllItems]; + [self->_buffer removeAllItems]; - _last = _i + 1; - _state = OF_XMLPARSER_TAG_OPENED; + self->_last = self->_i + 1; + self->_state = OF_XMLPARSER_TAG_OPENED; } /* Tag was just opened */ -- (void)of_tagOpenedState +static void +tagOpenedState(OFXMLParser *self) { - if (_finishedParsing && _data[_i] != '!' && _data[_i] != '?') + if (self->_finishedParsing && self->_data[self->_i] != '!' && + self->_data[self->_i] != '?') @throw [OFMalformedXMLException exceptionWithParser: self]; - switch (_data[_i]) { + switch (self->_data[self->_i]) { case '?': - _last = _i + 1; - _state = OF_XMLPARSER_IN_PROCESSING_INSTRUCTIONS; - _level = 0; + self->_last = self->_i + 1; + self->_state = OF_XMLPARSER_IN_PROCESSING_INSTRUCTIONS; + self->_level = 0; break; case '/': - _last = _i + 1; - _state = OF_XMLPARSER_IN_CLOSE_TAG_NAME; - _acceptProlog = false; + self->_last = self->_i + 1; + self->_state = OF_XMLPARSER_IN_CLOSE_TAG_NAME; + self->_acceptProlog = false; break; case '!': - _last = _i + 1; - _state = OF_XMLPARSER_IN_EXCLAMATION_MARK; - _acceptProlog = false; + self->_last = self->_i + 1; + self->_state = OF_XMLPARSER_IN_EXCLAMATION_MARK; + self->_acceptProlog = false; break; default: - if (_depthLimit > 0 && _previous.count >= _depthLimit) + if (self->_depthLimit > 0 && + self->_previous.count >= self->_depthLimit) @throw [OFOutOfRangeException exception]; - _state = OF_XMLPARSER_IN_TAG_NAME; - _acceptProlog = false; - _i--; + self->_state = OF_XMLPARSER_IN_TAG_NAME; + self->_acceptProlog = false; + self->_i--; break; } } /* */ -- (bool)of_parseXMLProcessingInstructions: (OFString *)pi +static bool +parseXMLProcessingInstructions(OFXMLParser *self, OFString *pi) { const char *cString; size_t length, last; int PIState = 0; OFString *attribute = nil; OFMutableString *value = nil; char piDelimiter = 0; bool hasVersion = false; - if (!_acceptProlog) + if (!self->_acceptProlog) return false; - _acceptProlog = false; + self->_acceptProlog = false; pi = [pi substringWithRange: of_range(3, pi.length - 3)]; pi = pi.stringByDeletingEnclosingWhitespaces; cString = pi.UTF8String; @@ -449,11 +439,11 @@ if (cString[i] != '=') continue; attribute = [OFString stringWithCString: cString + last - encoding: _encoding + encoding: self->_encoding length: i - last]; last = i + 1; PIState = 2; break; @@ -470,11 +460,11 @@ if (cString[i] != piDelimiter) continue; value = [OFMutableString stringWithCString: cString + last - encoding: _encoding + encoding: self->_encoding length: i - last]; if ([attribute isEqual: @"version"]) { if (![value hasPrefix: @"1."]) return false; @@ -482,11 +472,11 @@ hasVersion = true; } if ([attribute isEqual: @"encoding"]) { @try { - _encoding = + self->_encoding = of_string_parse_encoding(value); } @catch (OFInvalidArgumentException *e) { @throw [OFInvalidEncodingException exception]; } @@ -504,532 +494,568 @@ return true; } /* Inside processing instructions */ -- (void)of_inProcessingInstructionsState +static void +inProcessingInstructionsState(OFXMLParser *self) { - if (_data[_i] == '?') - _level = 1; - else if (_level == 1 && _data[_i] == '>') { + if (self->_data[self->_i] == '?') + self->_level = 1; + else if (self->_level == 1 && self->_data[self->_i] == '>') { void *pool = objc_autoreleasePoolPush(); OFString *PI; - appendToBuffer(_buffer, _data + _last, _encoding, _i - _last); - PI = transformString(self, _buffer, 1, false); + appendToBuffer(self->_buffer, self->_data + self->_last, + self->_encoding, self->_i - self->_last); + PI = transformString(self, self->_buffer, 1, false); if ([PI isEqual: @"xml"] || [PI hasPrefix: @"xml "] || [PI hasPrefix: @"xml\t"] || [PI hasPrefix: @"xml\r"] || [PI hasPrefix: @"xml\n"]) - if (![self of_parseXMLProcessingInstructions: PI]) + if (!parseXMLProcessingInstructions(self, PI)) @throw [OFMalformedXMLException exceptionWithParser: self]; - if ([_delegate respondsToSelector: + if ([self->_delegate respondsToSelector: @selector(parser:foundProcessingInstructions:)]) - [_delegate parser: self + [self->_delegate parser: self foundProcessingInstructions: PI]; objc_autoreleasePoolPop(pool); - [_buffer removeAllItems]; + [self->_buffer removeAllItems]; - _last = _i + 1; - _state = OF_XMLPARSER_OUTSIDE_TAG; + self->_last = self->_i + 1; + self->_state = OF_XMLPARSER_OUTSIDE_TAG; } else - _level = 0; + self->_level = 0; } /* Inside a tag, no name yet */ -- (void)of_inTagNameState +static void +inTagNameState(OFXMLParser *self) { void *pool; const char *bufferCString, *tmp; size_t length, bufferLength; OFString *bufferString; - if (_data[_i] != ' ' && _data[_i] != '\t' && _data[_i] != '\n' && - _data[_i] != '\r' && _data[_i] != '>' && _data[_i] != '/') + if (self->_data[self->_i] != ' ' && self->_data[self->_i] != '\t' && + self->_data[self->_i] != '\n' && self->_data[self->_i] != '\r' && + self->_data[self->_i] != '>' && self->_data[self->_i] != '/') return; - if ((length = _i - _last) > 0) - appendToBuffer(_buffer, _data + _last, _encoding, length); + if ((length = self->_i - self->_last) > 0) + appendToBuffer(self->_buffer, self->_data + self->_last, + self->_encoding, length); pool = objc_autoreleasePoolPush(); - bufferCString = _buffer.items; - bufferLength = _buffer.count; + bufferCString = self->_buffer.items; + bufferLength = self->_buffer.count; bufferString = [OFString stringWithUTF8String: bufferCString length: bufferLength]; if ((tmp = memchr(bufferCString, ':', bufferLength)) != NULL) { - _name = [[OFString alloc] + self->_name = [[OFString alloc] initWithUTF8String: tmp + 1 length: bufferLength - (tmp - bufferCString) - 1]; - _prefix = [[OFString alloc] + self->_prefix = [[OFString alloc] initWithUTF8String: bufferCString length: tmp - bufferCString]; } else { - _name = [bufferString copy]; - _prefix = nil; + self->_name = [bufferString copy]; + self->_prefix = nil; } - if (_data[_i] == '>' || _data[_i] == '/') { + if (self->_data[self->_i] == '>' || self->_data[self->_i] == '/') { OFString *namespace; - namespace = namespaceForPrefix(_prefix, _namespaces); + namespace = namespaceForPrefix(self->_prefix, + self->_namespaces); - if (_prefix != nil && namespace == nil) + if (self->_prefix != nil && namespace == nil) @throw [OFUnboundPrefixException - exceptionWithPrefix: _prefix + exceptionWithPrefix: self->_prefix parser: self]; - if ([_delegate respondsToSelector: @selector(parser: + if ([self->_delegate respondsToSelector: @selector(parser: didStartElement:prefix:namespace:attributes:)]) - [_delegate parser: self - didStartElement: _name - prefix: _prefix - namespace: namespace - attributes: nil]; - - if (_data[_i] == '/') { - if ([_delegate respondsToSelector: + [self->_delegate parser: self + didStartElement: self->_name + prefix: self->_prefix + namespace: namespace + attributes: nil]; + + if (self->_data[self->_i] == '/') { + if ([self->_delegate respondsToSelector: @selector(parser:didEndElement:prefix:namespace:)]) - [_delegate parser: self - didEndElement: _name - prefix: _prefix - namespace: namespace]; + [self->_delegate parser: self + didEndElement: self->_name + prefix: self->_prefix + namespace: namespace]; - if (_previous.count == 0) - _finishedParsing = true; + if (self->_previous.count == 0) + self->_finishedParsing = true; } else - [_previous addObject: bufferString]; + [self->_previous addObject: bufferString]; - [_name release]; - [_prefix release]; - _name = _prefix = nil; + [self->_name release]; + [self->_prefix release]; + self->_name = self->_prefix = nil; - _state = (_data[_i] == '/' + self->_state = (self->_data[self->_i] == '/' ? OF_XMLPARSER_EXPECT_TAG_CLOSE : OF_XMLPARSER_OUTSIDE_TAG); } else - _state = OF_XMLPARSER_IN_TAG; + self->_state = OF_XMLPARSER_IN_TAG; - if (_data[_i] != '/') - [_namespaces addObject: [OFMutableDictionary dictionary]]; + if (self->_data[self->_i] != '/') + [self->_namespaces addObject: [OFMutableDictionary dictionary]]; objc_autoreleasePoolPop(pool); - [_buffer removeAllItems]; - _last = _i + 1; + [self->_buffer removeAllItems]; + self->_last = self->_i + 1; } /* Inside a close tag, no name yet */ -- (void)of_inCloseTagNameState +static void +inCloseTagNameState(OFXMLParser *self) { void *pool; const char *bufferCString, *tmp; size_t length, bufferLength; OFString *bufferString, *namespace; - if (_data[_i] != ' ' && _data[_i] != '\t' && _data[_i] != '\n' && - _data[_i] != '\r' && _data[_i] != '>') + if (self->_data[self->_i] != ' ' && self->_data[self->_i] != '\t' && + self->_data[self->_i] != '\n' && self->_data[self->_i] != '\r' && + self->_data[self->_i] != '>') return; - if ((length = _i - _last) > 0) - appendToBuffer(_buffer, _data + _last, _encoding, length); + if ((length = self->_i - self->_last) > 0) + appendToBuffer(self->_buffer, self->_data + self->_last, + self->_encoding, length); pool = objc_autoreleasePoolPush(); - bufferCString = _buffer.items; - bufferLength = _buffer.count; + bufferCString = self->_buffer.items; + bufferLength = self->_buffer.count; bufferString = [OFString stringWithUTF8String: bufferCString length: bufferLength]; if ((tmp = memchr(bufferCString, ':', bufferLength)) != NULL) { - _name = [[OFString alloc] + self->_name = [[OFString alloc] initWithUTF8String: tmp + 1 length: bufferLength - (tmp - bufferCString) - 1]; - _prefix = [[OFString alloc] + self->_prefix = [[OFString alloc] initWithUTF8String: bufferCString length: tmp - bufferCString]; } else { - _name = [bufferString copy]; - _prefix = nil; - } - - if (![_previous.lastObject isEqual: bufferString]) - @throw [OFMalformedXMLException exceptionWithParser: self]; - - [_previous removeLastObject]; - - [_buffer removeAllItems]; - - namespace = namespaceForPrefix(_prefix, _namespaces); - if (_prefix != nil && namespace == nil) - @throw [OFUnboundPrefixException exceptionWithPrefix: _prefix - parser: self]; - - if ([_delegate respondsToSelector: - @selector(parser:didEndElement:prefix:namespace:)]) - [_delegate parser: self - didEndElement: _name - prefix: _prefix - namespace: namespace]; + self->_name = [bufferString copy]; + self->_prefix = nil; + } + + if (![self->_previous.lastObject isEqual: bufferString]) + @throw [OFMalformedXMLException exceptionWithParser: self]; + + [self->_previous removeLastObject]; + + [self->_buffer removeAllItems]; + + namespace = namespaceForPrefix(self->_prefix, self->_namespaces); + if (self->_prefix != nil && namespace == nil) + @throw [OFUnboundPrefixException + exceptionWithPrefix: self->_prefix + parser: self]; + + if ([self->_delegate respondsToSelector: + @selector(parser:didEndElement:prefix:namespace:)]) + [self->_delegate parser: self + didEndElement: self->_name + prefix: self->_prefix + namespace: namespace]; objc_autoreleasePoolPop(pool); - [_namespaces removeLastObject]; - [_name release]; - [_prefix release]; - _name = _prefix = nil; + [self->_namespaces removeLastObject]; + [self->_name release]; + [self->_prefix release]; + self->_name = self->_prefix = nil; - _last = _i + 1; - _state = (_data[_i] == '>' + self->_last = self->_i + 1; + self->_state = (self->_data[self->_i] == '>' ? OF_XMLPARSER_OUTSIDE_TAG : OF_XMLPARSER_EXPECT_SPACE_OR_TAG_CLOSE); - if (_previous.count == 0) - _finishedParsing = true; + if (self->_previous.count == 0) + self->_finishedParsing = true; } /* Inside a tag, name found */ -- (void)of_inTagState +static void +inTagState(OFXMLParser *self) { void *pool; OFString *namespace; OFXMLAttribute *const *attributesObjects; size_t attributesCount; - if (_data[_i] != '>' && _data[_i] != '/') { - if (_data[_i] != ' ' && _data[_i] != '\t' && - _data[_i] != '\n' && _data[_i] != '\r') { - _last = _i; - _state = OF_XMLPARSER_IN_ATTRIBUTE_NAME; - _i--; + if (self->_data[self->_i] != '>' && self->_data[self->_i] != '/') { + if (self->_data[self->_i] != ' ' && + self->_data[self->_i] != '\t' && + self->_data[self->_i] != '\n' && + self->_data[self->_i] != '\r') { + self->_last = self->_i; + self->_state = OF_XMLPARSER_IN_ATTRIBUTE_NAME; + self->_i--; } return; } - attributesObjects = _attributes.objects; - attributesCount = _attributes.count; - - namespace = namespaceForPrefix(_prefix, _namespaces); - - if (_prefix != nil && namespace == nil) - @throw [OFUnboundPrefixException exceptionWithPrefix: _prefix - parser: self]; + attributesObjects = self->_attributes.objects; + attributesCount = self->_attributes.count; + + namespace = namespaceForPrefix(self->_prefix, self->_namespaces); + + if (self->_prefix != nil && namespace == nil) + @throw [OFUnboundPrefixException + exceptionWithPrefix: self->_prefix + parser: self]; for (size_t j = 0; j < attributesCount; j++) - resolveAttributeNamespace(attributesObjects[j], _namespaces, - self); + resolveAttributeNamespace(attributesObjects[j], + self->_namespaces, self); pool = objc_autoreleasePoolPush(); - if ([_delegate respondsToSelector: + if ([self->_delegate respondsToSelector: @selector(parser:didStartElement:prefix:namespace:attributes:)]) - [_delegate parser: self - didStartElement: _name - prefix: _prefix - namespace: namespace - attributes: _attributes]; - - if (_data[_i] == '/') { - if ([_delegate respondsToSelector: + [self->_delegate parser: self + didStartElement: self->_name + prefix: self->_prefix + namespace: namespace + attributes: self->_attributes]; + + if (self->_data[self->_i] == '/') { + if ([self->_delegate respondsToSelector: @selector(parser:didEndElement:prefix:namespace:)]) - [_delegate parser: self - didEndElement: _name - prefix: _prefix - namespace: namespace]; - - if (_previous.count == 0) - _finishedParsing = true; - - [_namespaces removeLastObject]; - } else if (_prefix != nil) { - OFString *str = [OFString stringWithFormat: @"%@:%@", - _prefix, _name]; - [_previous addObject: str]; + [self->_delegate parser: self + didEndElement: self->_name + prefix: self->_prefix + namespace: namespace]; + + if (self->_previous.count == 0) + self->_finishedParsing = true; + + [self->_namespaces removeLastObject]; + } else if (self->_prefix != nil) { + OFString *str = [OFString stringWithFormat: + @"%@:%@", self->_prefix, self->_name]; + [self->_previous addObject: str]; } else - [_previous addObject: _name]; + [self->_previous addObject: self->_name]; objc_autoreleasePoolPop(pool); - [_name release]; - [_prefix release]; - [_attributes removeAllObjects]; - _name = _prefix = nil; + [self->_name release]; + [self->_prefix release]; + [self->_attributes removeAllObjects]; + self->_name = self->_prefix = nil; - _last = _i + 1; - _state = (_data[_i] == '/' + self->_last = self->_i + 1; + self->_state = (self->_data[self->_i] == '/' ? OF_XMLPARSER_EXPECT_TAG_CLOSE : OF_XMLPARSER_OUTSIDE_TAG); } /* Looking for attribute name */ -- (void)of_inAttributeNameState +static void +inAttributeNameState(OFXMLParser *self) { void *pool; OFString *bufferString; const char *bufferCString, *tmp; size_t length, bufferLength; - if (_data[_i] != '=' && _data[_i] != ' ' && _data[_i] != '\t' && - _data[_i] != '\n' && _data[_i] != '\r') + if (self->_data[self->_i] != '=' && self->_data[self->_i] != ' ' && + self->_data[self->_i] != '\t' && self->_data[self->_i] != '\n' && + self->_data[self->_i] != '\r') return; - if ((length = _i - _last) > 0) - appendToBuffer(_buffer, _data + _last, _encoding, length); + if ((length = self->_i - self->_last) > 0) + appendToBuffer(self->_buffer, self->_data + self->_last, + self->_encoding, length); pool = objc_autoreleasePoolPush(); - bufferString = [OFString stringWithUTF8String: _buffer.items - length: _buffer.count]; + bufferString = [OFString stringWithUTF8String: self->_buffer.items + length: self->_buffer.count]; bufferCString = bufferString.UTF8String; bufferLength = bufferString.UTF8StringLength; if ((tmp = memchr(bufferCString, ':', bufferLength)) != NULL) { - _attributeName = [[OFString alloc] + self->_attributeName = [[OFString alloc] initWithUTF8String: tmp + 1 length: bufferLength - (tmp - bufferCString) - 1]; - _attributePrefix = [[OFString alloc] + self->_attributePrefix = [[OFString alloc] initWithUTF8String: bufferCString length: tmp - bufferCString]; } else { - _attributeName = [bufferString copy]; - _attributePrefix = nil; + self->_attributeName = [bufferString copy]; + self->_attributePrefix = nil; } objc_autoreleasePoolPop(pool); - [_buffer removeAllItems]; + [self->_buffer removeAllItems]; - _last = _i + 1; - _state = (_data[_i] == '=' + self->_last = self->_i + 1; + self->_state = (self->_data[self->_i] == '=' ? OF_XMLPARSER_EXPECT_ATTRIBUTE_DELIMITER : OF_XMLPARSER_EXPECT_ATTRIBUTE_EQUAL_SIGN); } /* Expecting equal sign of an attribute */ -- (void)of_expectAttributeEqualSignState +static void +expectAttributeEqualSignState(OFXMLParser *self) { - if (_data[_i] == '=') { - _last = _i + 1; - _state = OF_XMLPARSER_EXPECT_ATTRIBUTE_DELIMITER; + if (self->_data[self->_i] == '=') { + self->_last = self->_i + 1; + self->_state = OF_XMLPARSER_EXPECT_ATTRIBUTE_DELIMITER; return; } - if (_data[_i] != ' ' && _data[_i] != '\t' && _data[_i] != '\n' && - _data[_i] != '\r') + if (self->_data[self->_i] != ' ' && self->_data[self->_i] != '\t' && + self->_data[self->_i] != '\n' && self->_data[self->_i] != '\r') @throw [OFMalformedXMLException exceptionWithParser: self]; } /* Expecting name/value delimiter of an attribute */ -- (void)of_expectAttributeDelimiterState +static void +expectAttributeDelimiterState(OFXMLParser *self) { - _last = _i + 1; + self->_last = self->_i + 1; - if (_data[_i] == ' ' || _data[_i] == '\t' || _data[_i] == '\n' || - _data[_i] == '\r') + if (self->_data[self->_i] == ' ' || self->_data[self->_i] == '\t' || + self->_data[self->_i] == '\n' || self->_data[self->_i] == '\r') return; - if (_data[_i] != '\'' && _data[_i] != '"') + if (self->_data[self->_i] != '\'' && self->_data[self->_i] != '"') @throw [OFMalformedXMLException exceptionWithParser: self]; - _delimiter = _data[_i]; - _state = OF_XMLPARSER_IN_ATTRIBUTE_VALUE; + self->_delimiter = self->_data[self->_i]; + self->_state = OF_XMLPARSER_IN_ATTRIBUTE_VALUE; } /* Looking for attribute value */ -- (void)of_inAttributeValueState +static void +inAttributeValueState(OFXMLParser *self) { void *pool; OFString *attributeValue; size_t length; OFXMLAttribute *attribute; - if (_data[_i] != _delimiter) + if (self->_data[self->_i] != self->_delimiter) return; - if ((length = _i - _last) > 0) - appendToBuffer(_buffer, _data + _last, _encoding, length); + if ((length = self->_i - self->_last) > 0) + appendToBuffer(self->_buffer, self->_data + self->_last, + self->_encoding, length); pool = objc_autoreleasePoolPush(); - attributeValue = transformString(self, _buffer, 0, true); - - if (_attributePrefix == nil && [_attributeName isEqual: @"xmlns"]) - [_namespaces.lastObject setObject: attributeValue - forKey: @""]; - if ([_attributePrefix isEqual: @"xmlns"]) - [_namespaces.lastObject setObject: attributeValue - forKey: _attributeName]; - - attribute = [OFXMLAttribute attributeWithName: _attributeName - namespace: _attributePrefix + attributeValue = transformString(self, self->_buffer, 0, true); + + if (self->_attributePrefix == nil && + [self->_attributeName isEqual: @"xmlns"]) + [self->_namespaces.lastObject setObject: attributeValue + forKey: @""]; + if ([self->_attributePrefix isEqual: @"xmlns"]) + [self->_namespaces.lastObject setObject: attributeValue + forKey: self->_attributeName]; + + attribute = [OFXMLAttribute attributeWithName: self->_attributeName + namespace: self->_attributePrefix stringValue: attributeValue]; - attribute->_useDoubleQuotes = (_delimiter == '"'); - [_attributes addObject: attribute]; + attribute->_useDoubleQuotes = (self->_delimiter == '"'); + [self->_attributes addObject: attribute]; objc_autoreleasePoolPop(pool); - [_buffer removeAllItems]; - [_attributeName release]; - [_attributePrefix release]; - _attributeName = _attributePrefix = nil; + [self->_buffer removeAllItems]; + [self->_attributeName release]; + [self->_attributePrefix release]; + self->_attributeName = self->_attributePrefix = nil; - _last = _i + 1; - _state = OF_XMLPARSER_IN_TAG; + self->_last = self->_i + 1; + self->_state = OF_XMLPARSER_IN_TAG; } /* Expecting closing '>' */ -- (void)of_expectTagCloseState +static void +expectTagCloseState(OFXMLParser *self) { - if (_data[_i] == '>') { - _last = _i + 1; - _state = OF_XMLPARSER_OUTSIDE_TAG; + if (self->_data[self->_i] == '>') { + self->_last = self->_i + 1; + self->_state = OF_XMLPARSER_OUTSIDE_TAG; } else @throw [OFMalformedXMLException exceptionWithParser: self]; } /* Expecting closing '>' or space */ -- (void)of_expectSpaceOrTagCloseState +static void +expectSpaceOrTagCloseState(OFXMLParser *self) { - if (_data[_i] == '>') { - _last = _i + 1; - _state = OF_XMLPARSER_OUTSIDE_TAG; - } else if (_data[_i] != ' ' && _data[_i] != '\t' && - _data[_i] != '\n' && _data[_i] != '\r') + if (self->_data[self->_i] == '>') { + self->_last = self->_i + 1; + self->_state = OF_XMLPARSER_OUTSIDE_TAG; + } else if (self->_data[self->_i] != ' ' && + self->_data[self->_i] != '\t' && self->_data[self->_i] != '\n' && + self->_data[self->_i] != '\r') @throw [OFMalformedXMLException exceptionWithParser: self]; } /* In _finishedParsing && self->_data[self->_i] != '-') @throw [OFMalformedXMLException exceptionWithParser: self]; - if (_data[_i] == '-') - _state = OF_XMLPARSER_IN_COMMENT_OPENING; - else if (_data[_i] == '[') { - _state = OF_XMLPARSER_IN_CDATA_OPENING; - _level = 0; - } else if (_data[_i] == 'D') { - _state = OF_XMLPARSER_IN_DOCTYPE; - _level = 0; + if (self->_data[self->_i] == '-') + self->_state = OF_XMLPARSER_IN_COMMENT_OPENING; + else if (self->_data[self->_i] == '[') { + self->_state = OF_XMLPARSER_IN_CDATA_OPENING; + self->_level = 0; + } else if (self->_data[self->_i] == 'D') { + self->_state = OF_XMLPARSER_IN_DOCTYPE; + self->_level = 0; } else @throw [OFMalformedXMLException exceptionWithParser: self]; - _last = _i + 1; + self->_last = self->_i + 1; } /* CDATA */ -- (void)of_inCDATAOpeningState -{ - if (_data[_i] != "CDATA["[_level]) - @throw [OFMalformedXMLException exceptionWithParser: self]; - - if (++_level == 6) { - _state = OF_XMLPARSER_IN_CDATA; - _level = 0; - } - - _last = _i + 1; -} - -- (void)of_inCDATAState -{ - - if (_data[_i] == ']') - _level++; - else if (_data[_i] == '>' && _level >= 2) { +static void +inCDATAOpeningState(OFXMLParser *self) +{ + if (self->_data[self->_i] != "CDATA["[self->_level]) + @throw [OFMalformedXMLException exceptionWithParser: self]; + + if (++self->_level == 6) { + self->_state = OF_XMLPARSER_IN_CDATA; + self->_level = 0; + } + + self->_last = self->_i + 1; +} + +static void +inCDATAState(OFXMLParser *self) +{ + if (self->_data[self->_i] == ']') + self->_level++; + else if (self->_data[self->_i] == '>' && self->_level >= 2) { void *pool = objc_autoreleasePoolPush(); OFString *CDATA; - appendToBuffer(_buffer, _data + _last, _encoding, _i - _last); - CDATA = transformString(self, _buffer, 2, false); + appendToBuffer(self->_buffer, self->_data + self->_last, + self->_encoding, self->_i - self->_last); + CDATA = transformString(self, self->_buffer, 2, false); - if ([_delegate respondsToSelector: + if ([self->_delegate respondsToSelector: @selector(parser:foundCDATA:)]) - [_delegate parser: self - foundCDATA: CDATA]; + [self->_delegate parser: self + foundCDATA: CDATA]; objc_autoreleasePoolPop(pool); - [_buffer removeAllItems]; + [self->_buffer removeAllItems]; - _last = _i + 1; - _state = OF_XMLPARSER_OUTSIDE_TAG; + self->_last = self->_i + 1; + self->_state = OF_XMLPARSER_OUTSIDE_TAG; } else - _level = 0; + self->_level = 0; } /* Comment */ -- (void)of_inCommentOpeningState +static void +inCommentOpeningState(OFXMLParser *self) { - if (_data[_i] != '-') + if (self->_data[self->_i] != '-') @throw [OFMalformedXMLException exceptionWithParser: self]; - _last = _i + 1; - _state = OF_XMLPARSER_IN_COMMENT_1; - _level = 0; -} - -- (void)of_inCommentState1 -{ - if (_data[_i] == '-') - _level++; - else - _level = 0; - - if (_level == 2) - _state = OF_XMLPARSER_IN_COMMENT_2; -} - -- (void)of_inCommentState2 + self->_last = self->_i + 1; + self->_state = OF_XMLPARSER_IN_COMMENT_1; + self->_level = 0; +} + +static void +inCommentState1(OFXMLParser *self) +{ + if (self->_data[self->_i] == '-') + self->_level++; + else + self->_level = 0; + + if (self->_level == 2) + self->_state = OF_XMLPARSER_IN_COMMENT_2; +} + +static void +inCommentState2(OFXMLParser *self) { void *pool; OFString *comment; - if (_data[_i] != '>') + if (self->_data[self->_i] != '>') @throw [OFMalformedXMLException exceptionWithParser: self]; pool = objc_autoreleasePoolPush(); - appendToBuffer(_buffer, _data + _last, _encoding, _i - _last); - comment = transformString(self, _buffer, 2, false); + appendToBuffer(self->_buffer, self->_data + self->_last, + self->_encoding, self->_i - self->_last); + comment = transformString(self, self->_buffer, 2, false); - if ([_delegate respondsToSelector: @selector(parser:foundComment:)]) - [_delegate parser: self - foundComment: comment]; + if ([self->_delegate respondsToSelector: + @selector(parser:foundComment:)]) + [self->_delegate parser: self + foundComment: comment]; objc_autoreleasePoolPop(pool); - [_buffer removeAllItems]; + [self->_buffer removeAllItems]; - _last = _i + 1; - _state = OF_XMLPARSER_OUTSIDE_TAG; + self->_last = self->_i + 1; + self->_state = OF_XMLPARSER_OUTSIDE_TAG; } /* In */ -- (void)of_inDOCTYPEState +static void +inDOCTYPEState(OFXMLParser *self) { - if ((_level < 6 && _data[_i] != "OCTYPE"[_level]) || - (_level == 6 && _data[_i] != ' ' && _data[_i] != '\t' && - _data[_i] != '\n' && _data[_i] != '\r')) + if ((self->_level < 6 && + self->_data[self->_i] != "OCTYPE"[self->_level]) || + (self->_level == 6 && self->_data[self->_i] != ' ' && + self->_data[self->_i] != '\t' && self->_data[self->_i] != '\n' && + self->_data[self->_i] != '\r')) @throw [OFMalformedXMLException exceptionWithParser: self]; - _level++; + self->_level++; - if (_level > 6 && _data[_i] == '>') - _state = OF_XMLPARSER_OUTSIDE_TAG; + if (self->_level > 6 && self->_data[self->_i] == '>') + self->_state = OF_XMLPARSER_OUTSIDE_TAG; - _last = _i + 1; + self->_last = self->_i + 1; } - (size_t)lineNumber { return _lineNumber; Index: src/OFZIPArchive.m ================================================================== --- src/OFZIPArchive.m +++ src/OFZIPArchive.m @@ -50,17 +50,19 @@ * FIXME: Current limitations: * - Split archives are not supported. * - Encrypted files cannot be read. */ +OF_DIRECT_MEMBERS @interface OFZIPArchive () - (void)of_readZIPInfo; - (void)of_readEntries; - (void)of_closeLastReturnedStream; - (void)of_writeCentralDirectory; @end +OF_DIRECT_MEMBERS @interface OFZIPArchiveLocalFileHeader: OFObject { @public uint16_t _minVersionNeeded, _generalPurposeBitFlag, _compressionMethod; uint16_t _lastModifiedFileTime, _lastModifiedFileDate; @@ -72,10 +74,11 @@ - (instancetype)initWithStream: (OFStream *)stream; - (bool)matchesEntry: (OFZIPArchiveEntry *)entry; @end +OF_DIRECT_MEMBERS @interface OFZIPArchiveFileReadStream: OFStream { OFStream *_stream, *_decompressedStream; OFZIPArchiveEntry *_entry; uint64_t _toRead; @@ -85,10 +88,11 @@ - (instancetype)of_initWithStream: (OFStream *)stream entry: (OFZIPArchiveEntry *)entry; @end +OF_DIRECT_MEMBERS @interface OFZIPArchiveFileWriteStream: OFStream { OFStream *_stream; uint32_t _CRC32; @public Index: src/OFZIPArchiveEntry+Private.h ================================================================== --- src/OFZIPArchiveEntry+Private.h +++ src/OFZIPArchiveEntry+Private.h @@ -22,15 +22,16 @@ @interface OFZIPArchiveEntry () @property (readonly, nonatomic) uint16_t of_lastModifiedFileTime, of_lastModifiedFileDate; @property (readonly, nonatomic) int64_t of_localFileHeaderOffset; -- (instancetype)of_initWithStream: (OFStream *)stream OF_METHOD_FAMILY(init); -- (uint64_t)of_writeToStream: (OFStream *)stream; +- (instancetype)of_initWithStream: (OFStream *)stream + OF_METHOD_FAMILY(init) OF_DIRECT; +- (uint64_t)of_writeToStream: (OFStream *)stream OF_DIRECT; @end @interface OFMutableZIPArchiveEntry () @property (readwrite, nonatomic, setter=of_setLocalFileHeaderOffset:) int64_t of_localFileHeaderOffset; @end OF_ASSUME_NONNULL_END Index: src/ObjFW.h ================================================================== --- src/ObjFW.h +++ src/ObjFW.h @@ -68,10 +68,12 @@ # import "OFINIFile.h" # import "OFSettings.h" #endif #ifdef OF_HAVE_SOCKETS # import "OFStreamSocket.h" +# import "OFDatagramSocket.h" +# import "OFSequencedPacketSocket.h" # import "OFTCPSocket.h" # import "OFUDPSocket.h" # import "OFTLSSocket.h" # import "OFKernelEventObserver.h" # import "OFDNSQuery.h" @@ -246,10 +248,11 @@ #import "OFLocking.h" #import "OFThread.h" #import "once.h" #ifdef OF_HAVE_THREADS # import "thread.h" +# import "tlskey.h" # import "mutex.h" # import "condition.h" # import "OFMutex.h" # import "OFRecursiveMutex.h" # import "OFCondition.h" Index: src/exceptions/OFDNSQueryFailedException.m ================================================================== --- src/exceptions/OFDNSQueryFailedException.m +++ src/exceptions/OFDNSQueryFailedException.m @@ -42,10 +42,12 @@ case OF_DNS_RESOLVER_ERROR_SERVER_NOT_IMPLEMENTED: return @"The server does not have support for the requested " @"query."; case OF_DNS_RESOLVER_ERROR_SERVER_REFUSED: return @"The server refused the query."; + case OF_DNS_RESOLVER_ERROR_NO_NAME_SERVER: + return @"There was no name server to query."; default: return @"Unknown error."; } } Index: src/forwarding/apple-forwarding-i386.S ================================================================== --- src/forwarding/apple-forwarding-i386.S +++ src/forwarding/apple-forwarding-i386.S @@ -15,123 +15,133 @@ * file. */ #include "config.h" +.intel_syntax noprefix + .globl _of_forward .globl _of_forward_stret .section __TEXT, __cstring, cstring_literals -str_forwardingTargetForSelector_: +Lstr_forwardingTargetForSelector_: .asciz "forwardingTargetForSelector:" .section __OBJC, __message_refs, literal_pointers, no_dead_strip -sel_forwardingTargetForSelector_: - .long str_forwardingTargetForSelector_ +Lsel_forwardingTargetForSelector_: + .long Lstr_forwardingTargetForSelector_ .section __OBJC, __image_info .long 0, 0 .section __TEXT, __text, regular, pure_instructions _of_forward: - pushl %ebp - movl %esp, %ebp + push ebp + mov ebp, esp - pushl %ebx - subl $20, %esp + push ebx + sub esp, 20 call get_eip 0: - movl 8(%ebp), %eax - movl %eax, (%esp) + mov eax, [ebp+8] + mov [esp], eax call _object_getClass - movl %eax, (%esp) - movl sel_forwardingTargetForSelector_-0b(%ebx), %eax - movl %eax, 4(%esp) + mov [esp], eax + .att_syntax /* Next line is broken in Intel syntax */ + movl Lsel_forwardingTargetForSelector_-0b(%ebx), %eax + .intel_syntax noprefix + mov [esp+4], eax call _class_respondsToSelector - testl %eax, %eax + test eax, eax jz 0f - movl 8(%ebp), %eax - movl %eax, (%esp) - movl sel_forwardingTargetForSelector_-0b(%ebx), %eax - movl %eax, 4(%esp) - movl 12(%ebp), %eax - movl %eax, 8(%esp) + mov eax, [ebp+8] + mov [esp], eax + .att_syntax /* Next line is broken in Intel syntax */ + movl Lsel_forwardingTargetForSelector_-0b(%ebx), %eax + .intel_syntax noprefix + mov [esp+4], eax + mov eax, [ebp+12] + mov [esp+8], eax call _objc_msgSend - testl %eax, %eax + test eax, eax jz 0f - cmpl 8(%ebp), %eax + cmp eax, [ebp+8] je 0f - movl %eax, 8(%ebp) + mov [ebp+8], eax - addl $20, %esp - popl %ebx - popl %ebp + add esp, 20 + pop ebx + pop ebp jmp _objc_msgSend 0: - addl $20, %esp - popl %ebx - popl %ebp + add esp, 20 + pop ebx + pop ebp jmp _of_method_not_found _of_forward_stret: - pushl %ebp - movl %esp, %ebp + push ebp + mov ebp, esp - pushl %ebx - subl $20, %esp + push ebx + sub esp, 20 call get_eip 0: - movl 12(%ebp), %eax - movl %eax, (%esp) + mov eax, [ebp+12] + mov [esp], eax call _object_getClass - movl %eax, (%esp) - movl sel_forwardingTargetForSelector_-0b(%ebx), %eax - movl %eax, 4(%esp) + mov [esp], eax + .att_syntax /* Next line is broken in Intel syntax */ + movl Lsel_forwardingTargetForSelector_-0b(%ebx), %eax + .intel_syntax noprefix + mov [esp+4], eax call _class_respondsToSelector - testl %eax, %eax + test eax, eax jz 0f - movl 12(%ebp), %eax - movl %eax, (%esp) - movl sel_forwardingTargetForSelector_-0b(%ebx), %eax - movl %eax, 4(%esp) - movl 16(%ebp), %eax - movl %eax, 8(%esp) + mov eax, [ebp+12] + mov [esp], eax + .att_syntax /* Next line is broken in Intel syntax */ + movl Lsel_forwardingTargetForSelector_-0b(%ebx), %eax + .intel_syntax noprefix + mov [esp+4], eax + mov eax, [ebp+16] + mov [esp+8], eax call _objc_msgSend - testl %eax, %eax + test eax, eax jz 0f - cmpl 12(%ebp), %eax + cmp eax, [ebp+12] je 0f - movl %eax, 12(%ebp) + mov [ebp+12], eax - addl $20, %esp - popl %ebx - popl %ebp + add esp, 20 + pop ebx + pop ebp jmp _objc_msgSend_stret 0: - addl $20, %esp - popl %ebx - popl %ebp + add esp, 20 + pop ebx + pop ebp jmp _of_method_not_found_stret get_eip: - movl (%esp), %ebx + mov ebx, [esp] ret Index: src/forwarding/apple-forwarding-x86_64.S ================================================================== --- src/forwarding/apple-forwarding-x86_64.S +++ src/forwarding/apple-forwarding-x86_64.S @@ -15,10 +15,12 @@ * file. */ #include "config.h" +.intel_syntax noprefix + .globl _of_forward .globl _of_forward_stret .section __TEXT, __objc_methname, cstring_literals str_forwardingTargetForSelector_: @@ -31,150 +33,150 @@ .section __DATA, __objc_imageinfo, regular, no_dead_strip .long 0, 0 .section __TEXT, __text, regular, pure_instructions _of_forward: - pushq %rbp - movq %rsp, %rbp + push rbp + mov rbp, rsp /* Save all arguments */ - subq $0xC0, %rsp /* 16-byte alignment */ - movq %rax, -0x8(%rbp) - movq %rdi, -0x10(%rbp) - movq %rsi, -0x18(%rbp) - movq %rdx, -0x20(%rbp) - movq %rcx, -0x28(%rbp) - movq %r8, -0x30(%rbp) - movq %r9, -0x38(%rbp) - movaps %xmm0, -0x50(%rbp) - movaps %xmm1, -0x60(%rbp) - movaps %xmm2, -0x70(%rbp) - movaps %xmm3, -0x80(%rbp) - movaps %xmm4, -0x90(%rbp) - movaps %xmm5, -0xA0(%rbp) - movaps %xmm6, -0xB0(%rbp) - movaps %xmm7, -0xC0(%rbp) + sub rsp, 0xC0 /* 16-byte alignment */ + mov [rbp-0x08], rax + mov [rbp-0x10], rdi + mov [rbp-0x18], rsi + mov [rbp-0x20], rdx + mov [rbp-0x28], rcx + mov [rbp-0x30], r8 + mov [rbp-0x38], r9 + movaps [rbp-0x50], xmm0 + movaps [rbp-0x60], xmm1 + movaps [rbp-0x70], xmm2 + movaps [rbp-0x80], xmm3 + movaps [rbp-0x90], xmm4 + movaps [rbp-0xA0], xmm5 + movaps [rbp-0xB0], xmm6 + movaps [rbp-0xC0], xmm7 call _object_getClass - movq %rax, %rdi - movq sel_forwardingTargetForSelector_(%rip), %rsi + mov rdi, rax + mov rsi, [rip+sel_forwardingTargetForSelector_] call _class_respondsToSelector - testq %rax, %rax + test rax, rax jz 0f - movq -0x10(%rbp), %rdi - movq sel_forwardingTargetForSelector_(%rip), %rsi - movq -0x18(%rbp), %rdx + mov rdi, [rbp-0x10] + mov rsi, [rip+sel_forwardingTargetForSelector_] + mov rdx, [rbp-0x18] call _objc_msgSend - testq %rax, %rax + test rax, rax jz 0f - cmpq -0x10(%rbp), %rax + cmp rax, [rbp-0x10] je 0f - movq %rax, %rdi + mov rdi, rax /* Restore all arguments, except %rdi */ - movaps -0xC0(%rbp), %xmm7 - movaps -0xB0(%rbp), %xmm6 - movaps -0xA0(%rbp), %xmm5 - movaps -0x90(%rbp), %xmm4 - movaps -0x80(%rbp), %xmm3 - movaps -0x70(%rbp), %xmm2 - movaps -0x60(%rbp), %xmm1 - movaps -0x50(%rbp), %xmm0 - movq -0x38(%rbp), %r9 - movq -0x30(%rbp), %r8 - movq -0x28(%rbp), %rcx - movq -0x20(%rbp), %rdx - movq -0x18(%rbp), %rsi - movq -0x8(%rbp), %rax - - movq %rbp, %rsp - popq %rbp + movaps xmm7, [rbp-0xC0] + movaps xmm6, [rbp-0xB0] + movaps xmm5, [rbp-0xA0] + movaps xmm4, [rbp-0x90] + movaps xmm3, [rbp-0x80] + movaps xmm2, [rbp-0x70] + movaps xmm1, [rbp-0x60] + movaps xmm0, [rbp-0x50] + mov r9, [rbp-0x38] + mov r8, [rbp-0x30] + mov rcx, [rbp-0x28] + mov rdx, [rbp-0x20] + mov rsi, [rbp-0x18] + mov rax, [rbp-0x08] + + mov rsp, rbp + pop rbp jmp _objc_msgSend 0: - movq -0x10(%rbp), %rdi - movq -0x18(%rbp), %rsi + mov rdi, [rbp-0x10] + mov rsi, [rbp-0x18] - movq %rbp, %rsp - popq %rbp + mov rsp, rbp + pop rbp jmp _of_method_not_found _of_forward_stret: - pushq %rbp - movq %rsp, %rbp + push rbp + mov rbp, rsp /* Save all arguments */ - subq $0xC0, %rsp /* 16-byte alignment */ - movq %rax, -0x8(%rbp) - movq %rdi, -0x10(%rbp) - movq %rsi, -0x18(%rbp) - movq %rdx, -0x20(%rbp) - movq %rcx, -0x28(%rbp) - movq %r8, -0x30(%rbp) - movq %r9, -0x38(%rbp) - movaps %xmm0, -0x50(%rbp) - movaps %xmm1, -0x60(%rbp) - movaps %xmm2, -0x70(%rbp) - movaps %xmm3, -0x80(%rbp) - movaps %xmm4, -0x90(%rbp) - movaps %xmm5, -0xA0(%rbp) - movaps %xmm6, -0xB0(%rbp) - movaps %xmm7, -0xC0(%rbp) - - movq %rsi, %rdi + sub rsp, 0xC0 /* 16-byte alignment */ + mov [rbp-0x08], rax + mov [rbp-0x10], rdi + mov [rbp-0x18], rsi + mov [rbp-0x20], rdx + mov [rbp-0x28], rcx + mov [rbp-0x30], r8 + mov [rbp-0x38], r9 + movaps [rbp-0x50], xmm0 + movaps [rbp-0x60], xmm1 + movaps [rbp-0x70], xmm2 + movaps [rbp-0x80], xmm3 + movaps [rbp-0x90], xmm4 + movaps [rbp-0xA0], xmm5 + movaps [rbp-0xB0], xmm6 + movaps [rbp-0xC0], xmm7 + + mov rdi, rsi call _object_getClass - movq %rax, %rdi - movq sel_forwardingTargetForSelector_(%rip), %rsi + mov rdi, rax + mov rsi, [rip+sel_forwardingTargetForSelector_] call _class_respondsToSelector - testq %rax, %rax + test rax, rax jz 0f - movq -0x18(%rbp), %rdi - movq sel_forwardingTargetForSelector_(%rip), %rsi - movq -0x20(%rbp), %rdx + mov rdi, [rbp-0x18] + mov rsi, [rip+sel_forwardingTargetForSelector_] + mov rdx, [rbp-0x20] call _objc_msgSend - testq %rax, %rax + test rax, rax jz 0f - cmpq -0x18(%rbp), %rax + cmp rax, [rbp-0x18] je 0f - movq %rax, %rsi + mov rsi, rax /* Restore all arguments, except %rsi */ - movaps -0xC0(%rbp), %xmm7 - movaps -0xB0(%rbp), %xmm6 - movaps -0xA0(%rbp), %xmm5 - movaps -0x90(%rbp), %xmm4 - movaps -0x80(%rbp), %xmm3 - movaps -0x70(%rbp), %xmm2 - movaps -0x60(%rbp), %xmm1 - movaps -0x50(%rbp), %xmm0 - movq -0x38(%rbp), %r9 - movq -0x30(%rbp), %r8 - movq -0x28(%rbp), %rcx - movq -0x20(%rbp), %rdx - movq -0x10(%rbp), %rdi - movq -0x8(%rbp), %rax - - movq %rbp, %rsp - popq %rbp + movaps xmm7, [rbp-0xC0] + movaps xmm6, [rbp-0xB0] + movaps xmm5, [rbp-0xA0] + movaps xmm4, [rbp-0x90] + movaps xmm3, [rbp-0x80] + movaps xmm2, [rbp-0x70] + movaps xmm1, [rbp-0x60] + movaps xmm0, [rbp-0x50] + mov r9, [rbp-0x38] + mov r8, [rbp-0x30] + mov rcx, [rbp-0x28] + mov rdx, [rbp-0x20] + mov rdi, [rbp-0x10] + mov rax, [rbp-0x08] + + mov rsp, rbp + pop rbp jmp _objc_msgSend_stret 0: - movq -0x10(%rbp), %rdi - movq -0x18(%rbp), %rsi - movq -0x20(%rbp), %rdx + mov rdi, [rbp-0x10] + mov rsi, [rbp-0x18] + mov rdx, [rbp-0x20] - movq %rbp, %rsp - popq %rbp + mov rsp, rbp + pop rbp jmp _of_method_not_found_stret ADDED src/forwarding/forwarding-sparc-elf.S Index: src/forwarding/forwarding-sparc-elf.S ================================================================== --- src/forwarding/forwarding-sparc-elf.S +++ src/forwarding/forwarding-sparc-elf.S @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, + * 2018, 2019, 2020 + * 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" + +#include "platform.h" + +.globl of_forward +.globl of_forward_stret + +.section .text +of_forward: + save %sp, -96, %sp + + sethi %hi(_GLOBAL_OFFSET_TABLE_ - 4), %l7 + call add_pc + add %l7, %lo(_GLOBAL_OFFSET_TABLE_ + 4), %l7 + + mov %i0, %o0 + call object_getClass + nop + + sethi %hi(sel_forwardingTargetForSelector_), %o1 + or %o1, %lo(sel_forwardingTargetForSelector_), %o1 + ld [%l7 + %o1], %o1 + call class_respondsToSelector + nop + + cmp %o0, 0 + be 0f + + mov %i0, %o0 + sethi %hi(sel_forwardingTargetForSelector_), %o1 + or %o1, %lo(sel_forwardingTargetForSelector_), %o1 + ld [%l7 + %o1], %o1 + call objc_msg_lookup + nop + mov %o0, %l0 + + mov %i0, %o0 + sethi %hi(sel_forwardingTargetForSelector_), %o1 + or %o1, %lo(sel_forwardingTargetForSelector_), %o1 + ld [%l7 + %o1], %o1 + jmpl %l0, %o7 + mov %i1, %o2 + + cmp %o0, 0 + be 0f + cmp %o0, %i0 + be 0f + + mov %o0, %i0 + call objc_msg_lookup + mov %i1, %o1 + + jmpl %o0, %g0 + restore + +0: + call of_method_not_found + restore +.type of_forward, %function +.size of_forward, .-of_forward + +of_forward_stret: + save %sp, -96, %sp + + sethi %hi(_GLOBAL_OFFSET_TABLE_ - 4), %l7 + call add_pc + add %l7, %lo(_GLOBAL_OFFSET_TABLE_ + 4), %l7 + + mov %i1, %o0 + call object_getClass + nop + + sethi %hi(sel_forwardingTargetForSelector_), %o1 + or %o1, %lo(sel_forwardingTargetForSelector_), %o1 + ld [%l7 + %o1], %o1 + call class_respondsToSelector + nop + + cmp %o0, 0 + be 0f + + mov %i1, %o0 + sethi %hi(sel_forwardingTargetForSelector_), %o1 + or %o1, %lo(sel_forwardingTargetForSelector_), %o1 + ld [%l7 + %o1], %o1 + call objc_msg_lookup + nop + mov %o0, %l0 + + mov %i1, %o0 + sethi %hi(sel_forwardingTargetForSelector_), %o1 + or %o1, %lo(sel_forwardingTargetForSelector_), %o1 + ld [%l7 + %o1], %o1 + jmpl %l0, %o7 + mov %i2, %o2 + + cmp %o0, 0 + be 0f + cmp %o0, %i1 + be 0f + + mov %o0, %i1 + call objc_msg_lookup + mov %i2, %o1 + + jmpl %o0, %g0 + restore + +0: + call of_method_not_found_stret + restore +.type of_forward_stret, %function +.size of_forward_stret, .-of_forward_stret + +init: + save %sp, -96, %sp + + sethi %hi(_GLOBAL_OFFSET_TABLE_ - 4), %l7 + call add_pc + add %l7, %lo(_GLOBAL_OFFSET_TABLE_ + 4), %l7 + + sethi %hi(module), %i0 + or %i0, %lo(module), %i0 + ld [%l7 + %i0], %i0 + + call __objc_exec_class + restore + +add_pc: + jmp %o7 + 8 + add %l7, %o7, %l7 + +#ifdef OF_SOLARIS +.section .init_array, "aw" +#else +.section .ctors, "aw", %progbits +#endif + .word init + +.section .rodata +str_forwardingTargetForSelector_: + .asciz "forwardingTargetForSelector:" + +.section .data +sel_forwardingTargetForSelector_: + .word str_forwardingTargetForSelector_, 0 + .word 0, 0 +symtab: + .word 0, sel_forwardingTargetForSelector_ + .half 0, 0 + .word 0 + .word 0 +module: + .word 8, 16, 0, symtab + +#ifdef OF_LINUX +.section .note.GNU-stack, "", %progbits +#endif Index: src/forwarding/forwarding-sparc64-elf.S ================================================================== --- src/forwarding/forwarding-sparc64-elf.S +++ src/forwarding/forwarding-sparc64-elf.S @@ -61,15 +61,13 @@ or %o1, %lo(sel_forwardingTargetForSelector_), %o1 ldx [%l7 + %o1], %o1 call class_respondsToSelector nop - cmp %o0, 0 - be,pn %xcc, 0f - nop + brz,pn %o0, 0f - mov %i0, %o0 + mov %i0, %o0 sethi %hi(sel_forwardingTargetForSelector_), %o1 or %o1, %lo(sel_forwardingTargetForSelector_), %o1 ldx [%l7 + %o1], %o1 call objc_msg_lookup nop @@ -80,18 +78,15 @@ or %o1, %lo(sel_forwardingTargetForSelector_), %o1 ldx [%l7 + %o1], %o1 jmpl %l0, %o7 mov %i1, %o2 - cmp %o0, 0 - be,pn %xcc, 0f - nop - cmp %o0, %i0 - be,pn %xcc, 0f - nop - - mov %o0, %i0 + brz,pn %o0, 0f + cmp %o0, %i0 + be,pn %xcc, 0f + + mov %o0, %i0 call objc_msg_lookup mov %i1, %o1 /* * Restore all floating point registers as they can be used for @@ -159,15 +154,13 @@ or %o1, %lo(sel_forwardingTargetForSelector_), %o1 ldx [%l7 + %o1], %o1 call class_respondsToSelector nop - cmp %o0, 0 - be,pn %xcc, 0f - nop + brz,pn %o0, 0f - mov %i1, %o0 + mov %i1, %o0 sethi %hi(sel_forwardingTargetForSelector_), %o1 or %o1, %lo(sel_forwardingTargetForSelector_), %o1 ldx [%l7 + %o1], %o1 call objc_msg_lookup nop @@ -178,18 +171,15 @@ or %o1, %lo(sel_forwardingTargetForSelector_), %o1 ldx [%l7 + %o1], %o1 jmpl %l0, %o7 mov %i2, %o2 - cmp %o0, 0 - be,pn %xcc, 0f - nop - cmp %o0, %i1 - be,pn %xcc, 0f - nop - - mov %o0, %i1 + brz,pn %o0, 0f + cmp %o0, %i1 + be,pn %xcc, 0f + + mov %o0, %i1 call objc_msg_lookup mov %i2, %o1 /* * Restore all floating point registers as they can be used for Index: src/forwarding/forwarding-x86-elf.S ================================================================== --- src/forwarding/forwarding-x86-elf.S +++ src/forwarding/forwarding-x86-elf.S @@ -17,175 +17,165 @@ #include "config.h" #include "platform.h" +.intel_syntax noprefix + .globl of_forward .globl of_forward_stret .section .text of_forward: - pushl %ebp - movl %esp, %ebp + push ebp + mov ebp, esp - pushl %ebx - subl $20, %esp + push ebx + sub esp, 20 call get_eip + add ebx, offset _GLOBAL_OFFSET_TABLE_ + + mov eax, [ebp+8] + mov [esp], eax + call object_getClass@PLT + + mov [esp], eax + lea eax, [ebx+sel_forwardingTargetForSelector_@GOTOFF] + mov [esp+4], eax + call class_respondsToSelector@PLT + + test eax, eax + jz short 0f + + mov eax, [ebp+8] + mov [esp], eax + lea eax, [ebx+sel_forwardingTargetForSelector_@GOTOFF] + mov [esp+4], eax + call objc_msg_lookup@PLT + + mov edx, [ebp+8] + mov [esp], edx + lea edx, [ebx+sel_forwardingTargetForSelector_@GOTOFF] + mov [esp+4], edx + mov edx, [ebp+12] + mov [esp+8], edx + call eax + + test eax, eax + jz short 0f + cmp eax, [ebp+8] + je short 0f + + mov [ebp+8], eax + mov [esp], eax + mov eax, [ebp+12] + mov [esp+4], eax + call objc_msg_lookup@PLT + + add esp, 20 + pop ebx + pop ebp + + jmp eax + 0: - addl $_GLOBAL_OFFSET_TABLE_, %ebx - - movl 8(%ebp), %eax - movl %eax, (%esp) - movl object_getClass@GOT(%ebx), %eax - call *%eax - - movl %eax, (%esp) - leal sel_forwardingTargetForSelector_@GOTOFF(%ebx), %eax - movl %eax, 4(%esp) - movl class_respondsToSelector@GOT(%ebx), %eax - call *%eax - - testl %eax, %eax - jz 1f - - movl 8(%ebp), %eax - movl %eax, (%esp) - leal sel_forwardingTargetForSelector_@GOTOFF(%ebx), %eax - movl %eax, 4(%esp) - movl objc_msg_lookup@GOT(%ebx), %eax - call *%eax - - movl 8(%ebp), %edx - movl %edx, (%esp) - leal sel_forwardingTargetForSelector_@GOTOFF(%ebx), %edx - movl %edx, 4(%esp) - movl 12(%ebp), %edx - movl %edx, 8(%esp) - call *%eax - - testl %eax, %eax - jz 1f - cmpl 8(%ebp), %eax - je 1f - - movl %eax, 8(%ebp) - movl %eax, (%esp) - movl 12(%ebp), %eax - movl %eax, 4(%esp) - movl objc_msg_lookup@GOT(%ebx), %eax - call *%eax - - addl $20, %esp - popl %ebx - popl %ebp - - jmp *%eax - -1: - movl of_method_not_found@GOT(%ebx), %eax - - addl $20, %esp - popl %ebx - popl %ebp - - jmp *%eax + lea eax, [ebx+of_method_not_found@GOTOFF] + + add esp, 20 + pop ebx + pop ebp + + jmp eax .type of_forward, %function .size of_forward, .-of_forward of_forward_stret: - pushl %ebp - movl %esp, %ebp + push ebp + mov ebp, esp - pushl %ebx - subl $20, %esp + push ebx + sub esp, 20 call get_eip + add ebx, offset _GLOBAL_OFFSET_TABLE_ + + mov eax, [ebp+12] + mov [esp], eax + call object_getClass@PLT + + mov [esp], eax + lea eax, [ebx+sel_forwardingTargetForSelector_@GOTOFF] + mov [esp+4], eax + call class_respondsToSelector@PLT + + test eax, eax + jz short 0f + + mov eax, [ebp+12] + mov [esp], eax + lea eax, [ebx+sel_forwardingTargetForSelector_@GOTOFF] + mov [esp+4], eax + call objc_msg_lookup@PLT + + mov edx, [ebp+12] + mov [esp], edx + lea edx, [ebx+sel_forwardingTargetForSelector_@GOTOFF] + mov [esp+4], edx + mov edx, [ebp+16] + mov [esp+8], edx + call eax + + test eax, eax + jz short 0f + cmp eax, [ebp+12] + je short 0f + + mov [ebp+12], eax + mov [esp], eax + mov eax, [ebp+16] + mov [esp+4], eax + call objc_msg_lookup_stret@PLT + + add esp, 20 + pop ebx + pop ebp + + jmp eax + 0: - addl $_GLOBAL_OFFSET_TABLE_, %ebx - - movl 12(%ebp), %eax - movl %eax, (%esp) - movl object_getClass@GOT(%ebx), %eax - call *%eax - - movl %eax, (%esp) - leal sel_forwardingTargetForSelector_@GOTOFF(%ebx), %eax - movl %eax, 4(%esp) - movl class_respondsToSelector@GOT(%ebx), %eax - call *%eax - - testl %eax, %eax - jz 1f - - movl 12(%ebp), %eax - movl %eax, (%esp) - leal sel_forwardingTargetForSelector_@GOTOFF(%ebx), %eax - movl %eax, 4(%esp) - movl objc_msg_lookup@GOT(%ebx), %eax - call *%eax - - movl 12(%ebp), %edx - movl %edx, (%esp) - leal sel_forwardingTargetForSelector_@GOTOFF(%ebx), %edx - movl %edx, 4(%esp) - movl 16(%ebp), %edx - movl %edx, 8(%esp) - call *%eax - - testl %eax, %eax - jz 1f - cmpl 12(%ebp), %eax - je 1f - - movl %eax, 12(%ebp) - movl %eax, (%esp) - movl 16(%ebp), %eax - movl %eax, 4(%esp) - movl objc_msg_lookup_stret@GOT(%ebx), %eax - call *%eax - - addl $20, %esp - popl %ebx - popl %ebp - - jmp *%eax - -1: - movl of_method_not_found_stret@GOT(%ebx), %eax - - addl $20, %esp - popl %ebx - popl %ebp - - jmp *%eax + lea eax, [ebx+of_method_not_found_stret@GOTOFF] + + add esp, 20 + pop ebx + pop ebp + + jmp eax .type of_forward_stret, %function .size of_forward_stret, .-of_forward_stret init: - pushl %ebp - movl %esp, %ebp + push ebp + mov ebp, esp - pushl %ebx - subl $4, %esp + push ebx + sub esp, 4 call get_eip -0: - add $_GLOBAL_OFFSET_TABLE_, %ebx - - leal module@GOTOFF(%ebx), %eax - movl %eax, (%esp) - movl __objc_exec_class@GOT(%ebx), %eax - call *%eax - - addl $4, %esp - popl %ebx - popl %ebp + add ebx, offset _GLOBAL_OFFSET_TABLE_ + + lea eax, [ebx+module@GOTOFF] + mov [esp], eax + call __objc_exec_class@PLT + + add esp, 4 + pop ebx + pop ebp ret get_eip: - movl (%esp), %ebx + mov ebx, [esp] ret #ifdef OF_SOLARIS .section .init_array, "aw" #else Index: src/forwarding/forwarding-x86-win32.S ================================================================== --- src/forwarding/forwarding-x86-win32.S +++ src/forwarding/forwarding-x86-win32.S @@ -15,167 +15,144 @@ * file. */ #include "config.h" +.intel_syntax noprefix + .globl _of_forward .globl _of_forward_stret .section .text _of_forward: - pushl %ebp - movl %esp, %ebp + push ebp + mov ebp, esp + + push ebx + sub esp, 20 + + mov eax, [ebp+8] + mov [esp], eax + call _object_getClass + + mov [esp], eax + mov eax, offset sel_forwardingTargetForSelector_ + mov [esp+4], eax + call _class_respondsToSelector + + test eax, eax + jz short 0f + + mov eax, [ebp+8] + mov [esp], eax + mov eax, offset sel_forwardingTargetForSelector_ + mov [esp+4], eax + call _objc_msg_lookup + + mov edx, [ebp+8] + mov [esp], edx + mov edx, offset sel_forwardingTargetForSelector_ + mov [esp+4], edx + mov edx, [ebp+12] + mov [esp+8], edx + call eax + + test eax, eax + jz short 0f + cmp eax, [ebp+8] + je short 0f + + mov [ebp+8], eax + mov [esp], eax + mov eax, [ebp+12] + mov [esp+4], eax + call _objc_msg_lookup - pushl %ebx - subl $20, %esp + add esp, 20 + pop ebx + pop ebp - call get_eip + jmp eax + 0: - - movl 8(%ebp), %eax - movl %eax, (%esp) - leal _object_getClass-0b(%ebx), %eax - call *%eax - - movl %eax, (%esp) - leal sel_forwardingTargetForSelector_-0b(%ebx), %eax - movl %eax, 4(%esp) - leal _class_respondsToSelector-0b(%ebx), %eax - call *%eax - - testl %eax, %eax - jz 1f - - movl 8(%ebp), %eax - movl %eax, (%esp) - leal sel_forwardingTargetForSelector_-0b(%ebx), %eax - movl %eax, 4(%esp) - leal _objc_msg_lookup-0b(%ebx), %eax - call *%eax - - movl 8(%ebp), %edx - movl %edx, (%esp) - leal sel_forwardingTargetForSelector_-0b(%ebx), %edx - movl %edx, 4(%esp) - movl 12(%ebp), %edx - movl %edx, 8(%esp) - call *%eax - - testl %eax, %eax - jz 1f - cmpl 8(%ebp), %eax - je 1f - - movl %eax, 8(%ebp) - movl %eax, (%esp) - movl 12(%ebp), %eax - movl %eax, 4(%esp) - leal _objc_msg_lookup-0b(%ebx), %eax - call *%eax - - addl $20, %esp - popl %ebx - popl %ebp - - jmp *%eax - -1: - leal _of_method_not_found-0b(%ebx), %eax - - addl $20, %esp - popl %ebx - popl %ebp - - jmp *%eax + add esp, 20 + pop ebx + pop ebp + + jmp _of_method_not_found _of_forward_stret: - pushl %ebp - movl %esp, %ebp + push ebp + mov ebp, esp + + push ebx + sub esp, 20 + + mov eax, [ebp+12] + mov [esp], eax + call _object_getClass + + mov [esp], eax + mov eax, offset sel_forwardingTargetForSelector_ + mov [esp+4], eax + call _class_respondsToSelector + + test eax, eax + jz short 0f + + mov eax, [ebp+12] + mov [esp], eax + mov eax, offset sel_forwardingTargetForSelector_ + mov [esp+4], eax + call _objc_msg_lookup + + mov edx, [ebp+12] + mov [esp], edx + mov edx, offset sel_forwardingTargetForSelector_ + mov [esp+4], edx + mov edx, [ebp+16] + mov [esp+8], edx + call eax + + test eax, eax + jz short 0f + cmp eax, [ebp+12] + je short 0f + + mov [ebp+12], eax + mov [esp], eax + mov eax, [ebp+16] + mov [esp+4], eax + call _objc_msg_lookup_stret - pushl %ebx - subl $20, %esp + add esp, 20 + pop ebx + pop ebp - call get_eip + jmp eax + 0: - - movl 12(%ebp), %eax - movl %eax, (%esp) - leal _object_getClass-0b(%ebx), %eax - call *%eax - - movl %eax, (%esp) - leal sel_forwardingTargetForSelector_-0b(%ebx), %eax - movl %eax, 4(%esp) - leal _class_respondsToSelector-0b(%ebx), %eax - call *%eax - - testl %eax, %eax - jz 1f - - movl 12(%ebp), %eax - movl %eax, (%esp) - leal sel_forwardingTargetForSelector_-0b(%ebx), %eax - movl %eax, 4(%esp) - leal _objc_msg_lookup-0b(%ebx), %eax - call *%eax - - movl 12(%ebp), %edx - movl %edx, (%esp) - leal sel_forwardingTargetForSelector_-0b(%ebx), %edx - movl %edx, 4(%esp) - movl 16(%ebp), %edx - movl %edx, 8(%esp) - call *%eax - - testl %eax, %eax - jz 1f - cmpl 12(%ebp), %eax - je 1f - - movl %eax, 12(%ebp) - movl %eax, (%esp) - movl 16(%ebp), %eax - movl %eax, 4(%esp) - leal _objc_msg_lookup_stret-0b(%ebx), %eax - call *%eax - - addl $20, %esp - popl %ebx - popl %ebp - - jmp *%eax - -1: - leal _of_method_not_found_stret-0b(%ebx), %eax - - addl $20, %esp - popl %ebx - popl %ebp - - jmp *%eax + add esp, 20 + pop ebx + pop ebp + + jmp _of_method_not_found_stret init: - pushl %ebp - movl %esp, %ebp - - pushl %ebx - subl $4, %esp - - call get_eip -0: - leal module-0b(%ebx), %eax - movl %eax, (%esp) - leal ___objc_exec_class-0b(%ebx), %eax - call *%eax - - addl $4, %esp - popl %ebx - popl %ebp - ret - -get_eip: - movl (%esp), %ebx + push ebp + mov ebp, esp + + push ebx + sub esp, 4 + + mov eax, offset module + mov [esp], eax + call ___objc_exec_class + + add esp, 4 + pop ebx + pop ebp ret .section .ctors, "aw" .long init Index: src/forwarding/forwarding-x86_64-elf.S ================================================================== --- src/forwarding/forwarding-x86_64-elf.S +++ src/forwarding/forwarding-x86_64-elf.S @@ -17,188 +17,190 @@ #include "config.h" #include "platform.h" +.intel_syntax noprefix + .globl of_forward .globl of_forward_stret .section .text of_forward: - pushq %rbp - movq %rsp, %rbp + push rbp + mov rbp, rsp /* Save all arguments */ - subq $0xC0, %rsp /* 16-byte alignment */ - movq %rax, -0x8(%rbp) - movq %rdi, -0x10(%rbp) - movq %rsi, -0x18(%rbp) - movq %rdx, -0x20(%rbp) - movq %rcx, -0x28(%rbp) - movq %r8, -0x30(%rbp) - movq %r9, -0x38(%rbp) - movaps %xmm0, -0x50(%rbp) - movaps %xmm1, -0x60(%rbp) - movaps %xmm2, -0x70(%rbp) - movaps %xmm3, -0x80(%rbp) - movaps %xmm4, -0x90(%rbp) - movaps %xmm5, -0xA0(%rbp) - movaps %xmm6, -0xB0(%rbp) - movaps %xmm7, -0xC0(%rbp) + sub rsp, 0xC0 /* 16-byte alignment */ + mov [rbp-0x08], rax + mov [rbp-0x10], rdi + mov [rbp-0x18], rsi + mov [rbp-0x20], rdx + mov [rbp-0x28], rcx + mov [rbp-0x30], r8 + mov [rbp-0x38], r9 + movaps [rbp-0x50], xmm0 + movaps [rbp-0x60], xmm1 + movaps [rbp-0x70], xmm2 + movaps [rbp-0x80], xmm3 + movaps [rbp-0x90], xmm4 + movaps [rbp-0xA0], xmm5 + movaps [rbp-0xB0], xmm6 + movaps [rbp-0xC0], xmm7 call object_getClass@PLT - movq %rax, %rdi - leaq sel_forwardingTargetForSelector_(%rip), %rsi + mov rdi, rax + lea rsi, [rip+sel_forwardingTargetForSelector_] call class_respondsToSelector@PLT - testq %rax, %rax - jz 0f - - movq -0x10(%rbp), %rdi - leaq sel_forwardingTargetForSelector_(%rip), %rsi - call objc_msg_lookup@PLT - - movq -0x10(%rbp), %rdi - leaq sel_forwardingTargetForSelector_(%rip), %rsi - movq -0x18(%rbp), %rdx - call *%rax - - testq %rax, %rax - jz 0f - cmpq -0x10(%rbp), %rax - je 0f - - movq %rax, -0x10(%rbp) - - movq %rax, %rdi - movq -0x18(%rbp), %rsi - call objc_msg_lookup@PLT - movq %rax, %r11 + test rax, rax + jz short 0f + + mov rdi, [rbp-0x10] + lea rsi, [rip+sel_forwardingTargetForSelector_] + call objc_msg_lookup@PLT + + mov rdi, [rbp-0x10] + lea rsi, [rip+sel_forwardingTargetForSelector_] + mov rdx, [rbp-0x18] + call rax + + test rax, rax + jz short 0f + cmp rax, [rbp-0x10] + je short 0f + + mov [rbp-0x10], rax + + mov rdi, rax + mov rsi, [rbp-0x18] + call objc_msg_lookup@PLT + mov r11, rax /* Restore all arguments */ - movaps -0xC0(%rbp), %xmm7 - movaps -0xB0(%rbp), %xmm6 - movaps -0xA0(%rbp), %xmm5 - movaps -0x90(%rbp), %xmm4 - movaps -0x80(%rbp), %xmm3 - movaps -0x70(%rbp), %xmm2 - movaps -0x60(%rbp), %xmm1 - movaps -0x50(%rbp), %xmm0 - movq -0x38(%rbp), %r9 - movq -0x30(%rbp), %r8 - movq -0x28(%rbp), %rcx - movq -0x20(%rbp), %rdx - movq -0x18(%rbp), %rsi - movq -0x10(%rbp), %rdi - movq -0x8(%rbp), %rax - - movq %rbp, %rsp - popq %rbp - - jmpq *%r11 + movaps xmm7, [rbp-0xC0] + movaps xmm6, [rbp-0xB0] + movaps xmm5, [rbp-0xA0] + movaps xmm4, [rbp-0x90] + movaps xmm3, [rbp-0x80] + movaps xmm2, [rbp-0x70] + movaps xmm1, [rbp-0x60] + movaps xmm0, [rbp-0x50] + mov r9, [rbp-0x38] + mov r8, [rbp-0x30] + mov rcx, [rbp-0x28] + mov rdx, [rbp-0x20] + mov rsi, [rbp-0x18] + mov rdi, [rbp-0x10] + mov rax, [rbp-0x08] + + mov rsp, rbp + pop rbp + + jmp r11 0: - movq -0x10(%rbp), %rdi - movq -0x18(%rbp), %rsi + mov rdi, [rbp-0x10] + mov rsi, [rbp-0x18] - movq %rbp, %rsp - popq %rbp + mov rsp, rbp + pop rbp jmp of_method_not_found@PLT .type of_forward, %function .size of_forward, .-of_forward of_forward_stret: - pushq %rbp - movq %rsp, %rbp + push rbp + mov rbp, rsp /* Save all arguments */ - subq $0xC0, %rsp /* 16-byte alignment */ - movq %rax, -0x8(%rbp) - movq %rdi, -0x10(%rbp) - movq %rsi, -0x18(%rbp) - movq %rdx, -0x20(%rbp) - movq %rcx, -0x28(%rbp) - movq %r8, -0x30(%rbp) - movq %r9, -0x38(%rbp) - movaps %xmm0, -0x50(%rbp) - movaps %xmm1, -0x60(%rbp) - movaps %xmm2, -0x70(%rbp) - movaps %xmm3, -0x80(%rbp) - movaps %xmm4, -0x90(%rbp) - movaps %xmm5, -0xA0(%rbp) - movaps %xmm6, -0xB0(%rbp) - movaps %xmm7, -0xC0(%rbp) - - movq %rsi, %rdi + sub rsp, 0xC0 /* 16-byte alignment */ + mov [rbp-0x08], rax + mov [rbp-0x10], rdi + mov [rbp-0x18], rsi + mov [rbp-0x20], rdx + mov [rbp-0x28], rcx + mov [rbp-0x30], r8 + mov [rbp-0x38], r9 + movaps [rbp-0x50], xmm0 + movaps [rbp-0x60], xmm1 + movaps [rbp-0x70], xmm2 + movaps [rbp-0x80], xmm3 + movaps [rbp-0x90], xmm4 + movaps [rbp-0xA0], xmm5 + movaps [rbp-0xB0], xmm6 + movaps [rbp-0xC0], xmm7 + + mov rdi, rsi call object_getClass@PLT - movq %rax, %rdi - leaq sel_forwardingTargetForSelector_(%rip), %rsi + mov rdi, rax + lea rsi, [rip+sel_forwardingTargetForSelector_] call class_respondsToSelector@PLT - testq %rax, %rax - jz 0f + test rax, rax + jz short 0f - movq -0x18(%rbp), %rdi - leaq sel_forwardingTargetForSelector_(%rip), %rsi + mov rdi, [rbp-0x18] + lea rsi, [rip+sel_forwardingTargetForSelector_] call objc_msg_lookup@PLT - movq -0x18(%rbp), %rdi - leaq sel_forwardingTargetForSelector_(%rip), %rsi - movq -0x20(%rbp), %rdx - call *%rax - - testq %rax, %rax - jz 0f - cmpq -0x18(%rbp), %rax - je 0f - - movq %rax, -0x18(%rbp) - - movq %rax, %rdi - movq -0x20(%rbp), %rsi + mov rdi, [rbp-0x18] + lea rsi, [rip+sel_forwardingTargetForSelector_] + mov rdx, [rbp-0x20] + call rax + + test rax, rax + jz short 0f + cmp rax, [rbp-0x18] + je short 0f + + mov [rbp-0x18], rax + + mov rdi, rax + mov rsi, [rbp-0x20] call objc_msg_lookup_stret@PLT - movq %rax, %r11 + mov r11, rax /* Restore all arguments */ - movaps -0xC0(%rbp), %xmm7 - movaps -0xB0(%rbp), %xmm6 - movaps -0xA0(%rbp), %xmm5 - movaps -0x90(%rbp), %xmm4 - movaps -0x80(%rbp), %xmm3 - movaps -0x70(%rbp), %xmm2 - movaps -0x60(%rbp), %xmm1 - movaps -0x50(%rbp), %xmm0 - movq -0x38(%rbp), %r9 - movq -0x30(%rbp), %r8 - movq -0x28(%rbp), %rcx - movq -0x20(%rbp), %rdx - movq -0x18(%rbp), %rsi - movq -0x10(%rbp), %rdi - movq -0x8(%rbp), %rax - - movq %rbp, %rsp - popq %rbp - - jmpq *%r11 + movaps xmm7, [rbp-0xC0] + movaps xmm6, [rbp-0xB0] + movaps xmm5, [rbp-0xA0] + movaps xmm4, [rbp-0x90] + movaps xmm3, [rbp-0x80] + movaps xmm2, [rbp-0x70] + movaps xmm1, [rbp-0x60] + movaps xmm0, [rbp-0x50] + mov r9, [rbp-0x38] + mov r8, [rbp-0x30] + mov rcx, [rbp-0x28] + mov rdx, [rbp-0x20] + mov rsi, [rbp-0x18] + mov rdi, [rbp-0x10] + mov rax, [rbp-0x08] + + mov rsp, rbp + pop rbp + + jmp r11 0: - movq -0x10(%rbp), %rdi - movq -0x18(%rbp), %rsi - movq -0x20(%rbp), %rdx + mov rdi, [rbp-0x10] + mov rsi, [rbp-0x18] + mov rdx, [rbp-0x20] - movq %rbp, %rsp - popq %rbp + mov rsp, rbp + pop rbp jmp of_method_not_found_stret@PLT .type of_forward_stret, %function .size of_forward_stret, .-of_forward_stret init: - leaq module(%rip), %rdi + lea rdi, [rip+module] jmp __objc_exec_class@PLT #ifdef OF_SOLARIS .section .init_array, "aw" #else Index: src/forwarding/forwarding-x86_64-macho.S ================================================================== --- src/forwarding/forwarding-x86_64-macho.S +++ src/forwarding/forwarding-x86_64-macho.S @@ -17,184 +17,186 @@ #include "config.h" #include "platform.h" +.intel_syntax noprefix + .globl _of_forward .globl _of_forward_stret .section __TEXT, __text, regular, pure_instructions _of_forward: - pushq %rbp - movq %rsp, %rbp + push rbp + mov rbp, rsp /* Save all arguments */ - subq $0xC0, %rsp /* 16-byte alignment */ - movq %rax, -0x8(%rbp) - movq %rdi, -0x10(%rbp) - movq %rsi, -0x18(%rbp) - movq %rdx, -0x20(%rbp) - movq %rcx, -0x28(%rbp) - movq %r8, -0x30(%rbp) - movq %r9, -0x38(%rbp) - movaps %xmm0, -0x50(%rbp) - movaps %xmm1, -0x60(%rbp) - movaps %xmm2, -0x70(%rbp) - movaps %xmm3, -0x80(%rbp) - movaps %xmm4, -0x90(%rbp) - movaps %xmm5, -0xA0(%rbp) - movaps %xmm6, -0xB0(%rbp) - movaps %xmm7, -0xC0(%rbp) + sub rsp, 0xC0 /* 16-byte alignment */ + mov [rbp-0x08], rax + mov [rbp-0x10], rdi + mov [rbp-0x18], rsi + mov [rbp-0x20], rdx + mov [rbp-0x28], rcx + mov [rbp-0x30], r8 + mov [rbp-0x38], r9 + movaps [rbp-0x50], xmm0 + movaps [rbp-0x60], xmm1 + movaps [rbp-0x70], xmm2 + movaps [rbp-0x80], xmm3 + movaps [rbp-0x90], xmm4 + movaps [rbp-0xA0], xmm5 + movaps [rbp-0xB0], xmm6 + movaps [rbp-0xC0], xmm7 call _object_getClass - movq %rax, %rdi - leaq sel_forwardingTargetForSelector_(%rip), %rsi + mov rdi, rax + lea rsi, [rip+sel_forwardingTargetForSelector_] call _class_respondsToSelector - testq %rax, %rax + test rax, rax jz 0f - movq -0x10(%rbp), %rdi - leaq sel_forwardingTargetForSelector_(%rip), %rsi + mov rdi, [rbp-0x10] + lea rsi, [rip+sel_forwardingTargetForSelector_] call _objc_msg_lookup - movq -0x10(%rbp), %rdi - leaq sel_forwardingTargetForSelector_(%rip), %rsi - movq -0x18(%rbp), %rdx - call *%rax + mov rdi, [rbp-0x10] + lea rsi, [rip+sel_forwardingTargetForSelector_] + mov rdx, [rbp-0x18] + call rax - testq %rax, %rax + test rax, rax jz 0f - cmpq -0x10(%rbp), %rax + cmp rax, [rbp-0x10] je 0f - movq %rax, -0x10(%rbp) + mov [rbp-0x10], rax - movq %rax, %rdi - movq -0x18(%rbp), %rsi + mov rdi, rax + mov rsi, [rbp-0x18] call _objc_msg_lookup - movq %rax, %r11 + mov r11, rax /* Restore all arguments */ - movaps -0xC0(%rbp), %xmm7 - movaps -0xB0(%rbp), %xmm6 - movaps -0xA0(%rbp), %xmm5 - movaps -0x90(%rbp), %xmm4 - movaps -0x80(%rbp), %xmm3 - movaps -0x70(%rbp), %xmm2 - movaps -0x60(%rbp), %xmm1 - movaps -0x50(%rbp), %xmm0 - movq -0x38(%rbp), %r9 - movq -0x30(%rbp), %r8 - movq -0x28(%rbp), %rcx - movq -0x20(%rbp), %rdx - movq -0x18(%rbp), %rsi - movq -0x10(%rbp), %rdi - movq -0x8(%rbp), %rax - - movq %rbp, %rsp - popq %rbp - - jmpq *%r11 + movaps xmm7, [rbp-0xC0] + movaps xmm6, [rbp-0xB0] + movaps xmm5, [rbp-0xA0] + movaps xmm4, [rbp-0x90] + movaps xmm3, [rbp-0x80] + movaps xmm2, [rbp-0x70] + movaps xmm1, [rbp-0x60] + movaps xmm0, [rbp-0x50] + mov r9, [rbp-0x38] + mov r8, [rbp-0x30] + mov rcx, [rbp-0x28] + mov rdx, [rbp-0x20] + mov rsi, [rbp-0x18] + mov rdi, [rbp-0x10] + mov rax, [rbp-0x08] + + mov rsp, rbp + pop rbp + + jmp r11 0: - movq -0x10(%rbp), %rdi - movq -0x18(%rbp), %rsi + mov rdi, [rbp-0x10] + mov rsi, [rbp-0x18] - movq %rbp, %rsp - popq %rbp + mov rsp, rbp + pop rbp jmp _of_method_not_found _of_forward_stret: - pushq %rbp - movq %rsp, %rbp + push rbp + mov rbp, rsp /* Save all arguments */ - subq $0xC0, %rsp /* 16-byte alignment */ - movq %rax, -0x8(%rbp) - movq %rdi, -0x10(%rbp) - movq %rsi, -0x18(%rbp) - movq %rdx, -0x20(%rbp) - movq %rcx, -0x28(%rbp) - movq %r8, -0x30(%rbp) - movq %r9, -0x38(%rbp) - movaps %xmm0, -0x50(%rbp) - movaps %xmm1, -0x60(%rbp) - movaps %xmm2, -0x70(%rbp) - movaps %xmm3, -0x80(%rbp) - movaps %xmm4, -0x90(%rbp) - movaps %xmm5, -0xA0(%rbp) - movaps %xmm6, -0xB0(%rbp) - movaps %xmm7, -0xC0(%rbp) - - movq %rsi, %rdi + sub rsp, 0xC0 /* 16-byte alignment */ + mov [rbp-0x08], rax + mov [rbp-0x10], rdi + mov [rbp-0x18], rsi + mov [rbp-0x20], rdx + mov [rbp-0x28], rcx + mov [rbp-0x30], r8 + mov [rbp-0x38], r9 + movaps [rbp-0x50], xmm0 + movaps [rbp-0x60], xmm1 + movaps [rbp-0x70], xmm2 + movaps [rbp-0x80], xmm3 + movaps [rbp-0x90], xmm4 + movaps [rbp-0xA0], xmm5 + movaps [rbp-0xB0], xmm6 + movaps [rbp-0xC0], xmm7 + + mov rdi, rsi call _object_getClass - movq %rax, %rdi - leaq sel_forwardingTargetForSelector_(%rip), %rsi + mov rdi, rax + lea rsi, [rip+sel_forwardingTargetForSelector_] call _class_respondsToSelector - testq %rax, %rax + test rax, rax jz 0f - movq -0x18(%rbp), %rdi - leaq sel_forwardingTargetForSelector_(%rip), %rsi + mov rdi, [rbp-0x18] + lea rsi, [rip+sel_forwardingTargetForSelector_] call _objc_msg_lookup - movq -0x18(%rbp), %rdi - leaq sel_forwardingTargetForSelector_(%rip), %rsi - movq -0x20(%rbp), %rdx - call *%rax + mov rdi, [rbp-0x18] + lea rsi, [rip+sel_forwardingTargetForSelector_] + mov rdx, [rbp-0x20] + call rax - testq %rax, %rax + test rax, rax jz 0f - cmpq -0x18(%rbp), %rax + cmp rax, [rbp-0x18] je 0f - movq %rax, -0x18(%rbp) + mov [rbp-0x18], rax - movq %rax, %rdi - movq -0x20(%rbp), %rsi + mov rdi, rax + mov rsi, [rbp-0x20] call _objc_msg_lookup_stret - movq %rax, %r11 + mov r11, rax /* Restore all arguments */ - movaps -0xC0(%rbp), %xmm7 - movaps -0xB0(%rbp), %xmm6 - movaps -0xA0(%rbp), %xmm5 - movaps -0x90(%rbp), %xmm4 - movaps -0x80(%rbp), %xmm3 - movaps -0x70(%rbp), %xmm2 - movaps -0x60(%rbp), %xmm1 - movaps -0x50(%rbp), %xmm0 - movq -0x38(%rbp), %r9 - movq -0x30(%rbp), %r8 - movq -0x28(%rbp), %rcx - movq -0x20(%rbp), %rdx - movq -0x18(%rbp), %rsi - movq -0x10(%rbp), %rdi - movq -0x8(%rbp), %rax - - movq %rbp, %rsp - popq %rbp - - jmpq *%r11 + movaps xmm7, [rbp-0xC0] + movaps xmm6, [rbp-0xB0] + movaps xmm5, [rbp-0xA0] + movaps xmm4, [rbp-0x90] + movaps xmm3, [rbp-0x80] + movaps xmm2, [rbp-0x70] + movaps xmm1, [rbp-0x60] + movaps xmm0, [rbp-0x50] + mov r9, [rbp-0x38] + mov r8, [rbp-0x30] + mov rcx, [rbp-0x28] + mov rdx, [rbp-0x20] + mov rsi, [rbp-0x18] + mov rdi, [rbp-0x10] + mov rax, [rbp-0x08] + + mov rsp, rbp + pop rbp + + jmp r11 0: - movq -0x10(%rbp), %rdi - movq -0x18(%rbp), %rsi - movq -0x20(%rbp), %rdx + mov rdi, [rbp-0x10] + mov rsi, [rbp-0x18] + mov rdx, [rbp-0x20] - movq %rbp, %rsp - popq %rbp + mov rsp, rbp + pop rbp jmp _of_method_not_found_stret init: - leaq module(%rip), %rdi + lea rdi, [rip+module] jmp ___objc_exec_class .section __DATA, __mod_init_func, mod_init_funcs .quad init Index: src/forwarding/forwarding-x86_64-win64.S ================================================================== --- src/forwarding/forwarding-x86_64-win64.S +++ src/forwarding/forwarding-x86_64-win64.S @@ -15,160 +15,162 @@ * file. */ #include "config.h" +.intel_syntax noprefix + .globl of_forward .globl of_forward_stret .section .text of_forward: - pushq %rbp - movq %rsp, %rbp + push rbp + mov rbp, rsp /* Save all arguments */ - subq $0x90, %rsp /* 16-byte alignment */ - movq %rax, -0x28(%rbp) - movq %rcx, -0x30(%rbp) - movq %rdx, -0x38(%rbp) - movq %r8, -0x40(%rbp) - movq %r9, -0x48(%rbp) - movaps %xmm0, -0x60(%rbp) - movaps %xmm1, -0x70(%rbp) - movaps %xmm2, -0x80(%rbp) - movaps %xmm3, -0x90(%rbp) + sub rsp, 0x90 /* 16-byte alignment */ + mov [rbp-0x28], rax + mov [rbp-0x30], rcx + mov [rbp-0x38], rdx + mov [rbp-0x40], r8 + mov [rbp-0x48], r9 + movaps [rbp-0x60], xmm0 + movaps [rbp-0x70], xmm1 + movaps [rbp-0x80], xmm2 + movaps [rbp-0x90], xmm3 call object_getClass - movq %rax, %rcx - leaq sel_forwardingTargetForSelector_(%rip), %rdx + mov rcx, rax + mov rdx, offset sel_forwardingTargetForSelector_ call class_respondsToSelector - testq %rax, %rax - jz 0f - - movq -0x30(%rbp), %rcx - leaq sel_forwardingTargetForSelector_(%rip), %rdx - call objc_msg_lookup - - movq -0x30(%rbp), %rcx - leaq sel_forwardingTargetForSelector_(%rip), %rdx - movq -0x38(%rbp), %r8 - call *%rax - - testq %rax, %rax - jz 0f - cmpq -0x30(%rbp), %rax - je 0f - - movq %rax, -0x30(%rbp) - - movq %rax, %rcx - movq -0x38(%rbp), %rdx - call objc_msg_lookup - movq %rax, %r11 + test rax, rax + jz short 0f + + mov rcx, [rbp-0x30] + mov rdx, offset sel_forwardingTargetForSelector_ + call objc_msg_lookup + + mov rcx, [rbp-0x30] + mov rdx, offset sel_forwardingTargetForSelector_ + mov r8, [rbp-0x38] + call rax + + test rax, rax + jz short 0f + cmp rax, [rbp-0x30] + je short 0f + + mov [rbp-0x30], rax + + mov rcx, rax + mov rdx, [rbp-0x38] + call objc_msg_lookup + mov r11, rax /* Restore all arguments */ - movaps -0x90(%rbp), %xmm3 - movaps -0x80(%rbp), %xmm2 - movaps -0x70(%rbp), %xmm1 - movaps -0x60(%rbp), %xmm0 - movq -0x48(%rbp), %r9 - movq -0x40(%rbp), %r8 - movq -0x38(%rbp), %rdx - movq -0x30(%rbp), %rcx - movq -0x28(%rbp), %rax - - movq %rbp, %rsp - popq %rbp - - jmpq *%r11 + movaps xmm3, [rbp-0x90] + movaps xmm2, [rbp-0x80] + movaps xmm1, [rbp-0x70] + movaps xmm0, [rbp-0x60] + mov r9, [rbp-0x48] + mov r8, [rbp-0x40] + mov rdx, [rbp-0x38] + mov rcx, [rbp-0x30] + mov rax, [rbp-0x28] + + mov rsp, rbp + pop rbp + + jmp r11 0: - movq -0x30(%rbp), %rcx - movq -0x38(%rbp), %rdx + mov rcx, [rbp-0x30] + mov rdx, [rbp-0x38] - movq %rbp, %rsp - popq %rbp + mov rsp, rbp + pop rbp jmp of_method_not_found of_forward_stret: - pushq %rbp - movq %rsp, %rbp + push rbp + mov rbp, rsp /* Save all arguments */ - subq $0x90, %rsp /* 16-byte alignment */ - movq %rax, -0x28(%rbp) - movq %rcx, -0x30(%rbp) - movq %rdx, -0x38(%rbp) - movq %r8, -0x40(%rbp) - movq %r9, -0x48(%rbp) - movaps %xmm0, -0x60(%rbp) - movaps %xmm1, -0x70(%rbp) - movaps %xmm2, -0x80(%rbp) - movaps %xmm3, -0x90(%rbp) - - movq %rdx, %rcx + sub rsp, 0x90 /* 16-byte alignment */ + mov [rbp-0x28], rax + mov [rbp-0x30], rcx + mov [rbp-0x38], rdx + mov [rbp-0x40], r8 + mov [rbp-0x48], r9 + movaps [rbp-0x60], xmm0 + movaps [rbp-0x70], xmm1 + movaps [rbp-0x80], xmm2 + movaps [rbp-0x90], xmm3 + + mov rcx, rdx call object_getClass - movq %rax, %rcx - leaq sel_forwardingTargetForSelector_(%rip), %rdx + mov rcx, rax + mov rdx, offset sel_forwardingTargetForSelector_ call class_respondsToSelector - testq %rax, %rax - jz 0f + test rax, rax + jz short 0f - movq -0x38(%rbp), %rcx - leaq sel_forwardingTargetForSelector_(%rip), %rdx + mov rcx, [rbp-0x38] + mov rdx, offset sel_forwardingTargetForSelector_ call objc_msg_lookup - movq -0x38(%rbp), %rcx - leaq sel_forwardingTargetForSelector_(%rip), %rdx - movq -0x40(%rbp), %r8 - call *%rax - - testq %rax, %rax - jz 0f - cmpq -0x38(%rbp), %rax - je 0f - - movq %rax, -0x38(%rbp) - - movq %rax, %rcx - movq -0x40(%rbp), %rdx + mov rcx, [rbp-0x38] + mov rdx, offset sel_forwardingTargetForSelector_ + mov r8, [rbp-0x40] + call rax + + test rax, rax + jz short 0f + cmp rax, [rbp-0x38] + je short 0f + + mov [rbp-0x38], rax + + mov rcx, rax + mov rdx, [rbp-0x40] call objc_msg_lookup_stret - movq %rax, %r11 + mov r11, rax /* Restore all arguments */ - movaps -0x90(%rbp), %xmm3 - movaps -0x80(%rbp), %xmm2 - movaps -0x70(%rbp), %xmm1 - movaps -0x60(%rbp), %xmm0 - movq -0x48(%rbp), %r9 - movq -0x40(%rbp), %r8 - movq -0x38(%rbp), %rdx - movq -0x30(%rbp), %rcx - movq -0x28(%rbp), %rax - - movq %rbp, %rsp - popq %rbp - - jmpq *%r11 + movaps xmm3, [rbp-0x90] + movaps xmm2, [rbp-0x80] + movaps xmm1, [rbp-0x70] + movaps xmm0, [rbp-0x60] + mov r9, [rbp-0x48] + mov r8, [rbp-0x40] + mov rdx, [rbp-0x38] + mov rcx, [rbp-0x30] + mov rax, [rbp-0x28] + + mov rsp, rbp + pop rbp + + jmp r11 0: - movq -0x30(%rbp), %rcx - movq -0x38(%rbp), %rdx - movq -0x40(%rbp), %r8 + mov rcx, [rbp-0x30] + mov rdx, [rbp-0x38] + mov r8, [rbp-0x40] - movq %rbp, %rsp - popq %rbp + mov rsp, rbp + pop rbp jmp of_method_not_found_stret init: - leaq module(%rip), %rcx + mov rcx, offset module jmp __objc_exec_class .section .ctors, "aw" .quad init Index: src/forwarding/forwarding.S ================================================================== --- src/forwarding/forwarding.S +++ src/forwarding/forwarding.S @@ -45,10 +45,12 @@ # include "forwarding-powerpc-elf.S" # elif defined(OF_MIPS) # include "forwarding-mips-elf.S" # elif defined(OF_SPARC64) # include "forwarding-sparc64-elf.S" +# elif defined(OF_SPARC) +# include "forwarding-sparc-elf.S" # endif # elif defined(OF_MACH_O) # if defined(OF_X86_64) # include "forwarding-x86_64-macho.S" # endif Index: src/macros.h ================================================================== --- src/macros.h +++ src/macros.h @@ -306,10 +306,21 @@ #if __has_attribute(__swift_name__) # define OF_SWIFT_NAME(name) __attribute__((__swift_name__(name))) #else # define OF_SWIFT_NAME(name) #endif + +#if __has_attribute(__objc_direct__) && defined(OF_APPLE_RUNTIME) +# define OF_DIRECT __attribute__((__objc_direct__)) +#else +# define OF_DIRECT +#endif +#if __has_attribute(__objc_direct_members__) && defined(OF_APPLE_RUNTIME) +# define OF_DIRECT_MEMBERS __attribute__((__objc_direct_members__)) +#else +# define OF_DIRECT_MEMBERS +#endif #ifdef __GNUC__ # ifdef OF_X86_64 # define OF_X86_64_ASM # endif @@ -353,11 +364,11 @@ # endif #else # if defined(OF_ELF) # if defined(OF_X86_64) || defined(OF_X86) || \ defined(OF_ARM64) || defined(OF_ARM) || defined(OF_POWERPC) || \ - defined(OF_MIPS) || defined(OF_SPARC64) + defined(OF_MIPS) || defined(OF_SPARC64) || defined(OF_SPARC) # define OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR # if __OBJFW_RUNTIME_ABI__ >= 800 # define OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR_STRET # endif # endif Index: src/pbkdf2.h ================================================================== --- src/pbkdf2.h +++ src/pbkdf2.h @@ -28,36 +28,51 @@ /*! @file */ @class OFHMAC; +/*! + * @brief The parameters for @ref of_pbkdf2. + */ +typedef struct of_pbkdf2_parameters_t { + /*! @brief The HMAC to use to derive a key. */ + OFHMAC *HMAC; + /*! @brief The number of iterations to perform. */ + size_t iterations; + /*! @brief The salt to derive a key with. */ + const unsigned char *salt; + /*! @brief The length of the salt. */ + size_t saltLength; + /*! @brief The password to derive a key from. */ + const char *password; + /*! @brief The length of the password. */ + size_t passwordLength; + /*! @brief The buffer to write the key to. */ + unsigned char *key; + /*! + * @brief The desired length for the derived key. + * + * @ref key needs to have enough storage. + */ + size_t keyLength; + /*! @brief Whether data may be stored in swappable memory. */ + bool allowsSwappableMemory; +} of_pbkdf2_parameters_t; + #ifdef __cplusplus extern "C" { #endif /*! - * @brief Derive a key from a password and a salt. - * - * @note This will call @ref OFHMAC::reset on the @ref OFHMAC first, making it - * possible to reuse the @ref OFHMAC, but also meaning all previous - * results from the @ref OFHMAC get invalidated if they have not been - * copied. - * - * @param HMAC The HMAC to use to derive a key - * @param iterations The number of iterations to perform - * @param salt The salt to derive a key with - * @param saltLength The length of the salt - * @param password The password to derive a key from - * @param passwordLength The length of the password - * @param key The buffer to write the key to - * @param keyLength The desired length for the derived key (key needs to have - * enough storage) - * @param allowsSwappableMemory Whether data may be stored in swappable memory - */ -extern void of_pbkdf2(OFHMAC *HMAC, size_t iterations, - const unsigned char *salt, size_t saltLength, - const char *password, size_t passwordLength, - unsigned char *key, size_t keyLength, bool allowsSwappableMemory); + * @brief Derives a key from a password and a salt using PBKDF2. + * + * @note This will call @ref OFHMAC::reset on the `HMAC` first, making it + * possible to reuse the `HMAC`, but also meaning all previous results + * from the `HMAC` get invalidated if they have not been copied. + * + * @param param The parameters to use + */ +extern void of_pbkdf2(of_pbkdf2_parameters_t param); #ifdef __cplusplus } #endif OF_ASSUME_NONNULL_END Index: src/pbkdf2.m ================================================================== --- src/pbkdf2.m +++ src/pbkdf2.m @@ -26,79 +26,79 @@ #import "OFOutOfMemoryException.h" #import "OFOutOfRangeException.h" #import "pbkdf2.h" -void of_pbkdf2(OFHMAC *HMAC, size_t iterations, - const unsigned char *salt, size_t saltLength, - const char *password, size_t passwordLength, - unsigned char *key, size_t keyLength, bool allowsSwappableMemory) +void +of_pbkdf2(of_pbkdf2_parameters_t param) { void *pool = objc_autoreleasePoolPush(); - size_t blocks, digestSize = HMAC.digestSize; + size_t blocks, digestSize = param.HMAC.digestSize; OFSecureData *buffer = [OFSecureData dataWithCount: digestSize - allowsSwappableMemory: allowsSwappableMemory]; + allowsSwappableMemory: param.allowsSwappableMemory]; OFSecureData *digest = [OFSecureData dataWithCount: digestSize - allowsSwappableMemory: allowsSwappableMemory]; + allowsSwappableMemory: param.allowsSwappableMemory]; unsigned char *bufferItems = buffer.mutableItems; unsigned char *digestItems = digest.mutableItems; OFSecureData *extendedSalt; unsigned char *extendedSaltItems; - if (HMAC == nil || iterations == 0 || salt == NULL || - password == NULL || key == NULL || keyLength == 0) + if (param.HMAC == nil || param.iterations == 0 || param.salt == NULL || + param.password == NULL || param.key == NULL || param.keyLength == 0) @throw [OFInvalidArgumentException exception]; - blocks = keyLength / digestSize; - if (keyLength % digestSize != 0) + blocks = param.keyLength / digestSize; + if (param.keyLength % digestSize != 0) blocks++; - if (saltLength > SIZE_MAX - 4 || blocks > UINT32_MAX) + if (param.saltLength > SIZE_MAX - 4 || blocks > UINT32_MAX) @throw [OFOutOfRangeException exception]; - extendedSalt = [OFSecureData dataWithCount: saltLength + 4 - allowsSwappableMemory: allowsSwappableMemory]; + extendedSalt = [OFSecureData + dataWithCount: param.saltLength + 4 + allowsSwappableMemory: param.allowsSwappableMemory]; extendedSaltItems = extendedSalt.mutableItems; @try { uint32_t i = OF_BSWAP32_IF_LE(1); - [HMAC setKey: password - length: passwordLength]; + [param.HMAC setKey: param.password + length: param.passwordLength]; - memcpy(extendedSaltItems, salt, saltLength); + memcpy(extendedSaltItems, param.salt, param.saltLength); - while (keyLength > 0) { + while (param.keyLength > 0) { size_t length; - memcpy(extendedSaltItems + saltLength, &i, 4); - - [HMAC reset]; - [HMAC updateWithBuffer: extendedSaltItems - length: saltLength + 4]; - memcpy(bufferItems, HMAC.digest, digestSize); - memcpy(digestItems, HMAC.digest, digestSize); - - for (size_t j = 1; j < iterations; j++) { - [HMAC reset]; - [HMAC updateWithBuffer: digestItems - length: digestSize]; - memcpy(digestItems, HMAC.digest, digestSize); + memcpy(extendedSaltItems + param.saltLength, &i, 4); + + [param.HMAC reset]; + [param.HMAC updateWithBuffer: extendedSaltItems + length: param.saltLength + 4]; + memcpy(bufferItems, param.HMAC.digest, digestSize); + memcpy(digestItems, param.HMAC.digest, digestSize); + + for (size_t j = 1; j < param.iterations; j++) { + [param.HMAC reset]; + [param.HMAC updateWithBuffer: digestItems + length: digestSize]; + memcpy(digestItems, param.HMAC.digest, + digestSize); for (size_t k = 0; k < digestSize; k++) bufferItems[k] ^= digestItems[k]; } length = digestSize; - if (length > keyLength) - length = keyLength; + if (length > param.keyLength) + length = param.keyLength; - memcpy(key, bufferItems, length); - key += length; - keyLength -= length; + memcpy(param.key, bufferItems, length); + param.key += length; + param.keyLength -= length; i = OF_BSWAP32_IF_LE(OF_BSWAP32_IF_LE(i) + 1); } } @catch (id e) { [extendedSalt zero]; @@ -105,10 +105,10 @@ [buffer zero]; [digest zero]; @throw e; } @finally { - [HMAC zero]; + [param.HMAC zero]; } objc_autoreleasePoolPop(pool); } Index: src/platform/amiga/thread.m ================================================================== --- src/platform/amiga/thread.m +++ src/platform/amiga/thread.m @@ -166,16 +166,19 @@ bool of_thread_join(of_thread_t thread) { ObtainSemaphore(&thread->semaphore); - @try { - if (thread->done) { - free(thread); - return true; - } + + if (thread->done) { + ReleaseSemaphore(&thread->semaphore); + + free(thread); + return true; + } + @try { if (thread->detached || thread->joinTask != NULL) { errno = EINVAL; return false; } Index: src/platform/windows/thread.m ================================================================== --- src/platform/windows/thread.m +++ src/platform/windows/thread.m @@ -21,10 +21,23 @@ #import "thread.h" #import "macros.h" #include + +struct thread_context { + void (*function)(id); + id object; +}; + +static WINAPI void +functionWrapper(struct thread_context *context) +{ + context->function(context->object); + + free(context); +} bool of_thread_attr_init(of_thread_attr_t *attr) { attr->priority = 0; @@ -35,29 +48,15 @@ bool of_thread_new(of_thread_t *thread, const char *name, void (*function)(id), id object, const of_thread_attr_t *attr) { - *thread = CreateThread(NULL, (attr != NULL ? attr->stackSize : 0), - (LPTHREAD_START_ROUTINE)function, (void *)object, 0, NULL); - - if (thread == NULL) { - switch (GetLastError()) { - case ERROR_NOT_ENOUGH_MEMORY: - errno = ENOMEM; - return false; - case ERROR_ACCESS_DENIED: - errno = EACCES; - return false; - default: - OF_ENSURE(0); - } - } + DWORD priority = THREAD_PRIORITY_NORMAL; + struct thread_context *context; + DWORD threadID; if (attr != NULL && attr->priority != 0) { - DWORD priority; - if (attr->priority < -1 || attr->priority > 1) { errno = EINVAL; return false; } @@ -67,14 +66,45 @@ (THREAD_PRIORITY_NORMAL - THREAD_PRIORITY_LOWEST); else priority = THREAD_PRIORITY_NORMAL + attr->priority * (THREAD_PRIORITY_HIGHEST - THREAD_PRIORITY_NORMAL); + } + + if ((context = malloc(sizeof(*context))) == NULL) { + errno = ENOMEM; + return false; + } + + context->function = function; + context->object = object; + + *thread = CreateThread(NULL, (attr != NULL ? attr->stackSize : 0), + (LPTHREAD_START_ROUTINE)functionWrapper, context, 0, &threadID); + + if (thread == NULL) { + int errNo; + + switch (GetLastError()) { + case ERROR_NOT_ENOUGH_MEMORY: + errNo = ENOMEM; + break; + case ERROR_ACCESS_DENIED: + errNo = EACCES; + break; + default: + OF_ENSURE(0); + } - OF_ENSURE(!SetThreadPriority(*thread, priority)); + free(context); + errno = errNo; + return false; } + if (attr != NULL && attr->priority != 0) + OF_ENSURE(!SetThreadPriority(*thread, priority)); + return true; } bool of_thread_join(of_thread_t thread) Index: src/runtime/exception.m ================================================================== --- src/runtime/exception.m +++ src/runtime/exception.m @@ -752,12 +752,13 @@ e->exception.class = GNUCOBJC_EXCEPTION_CLASS; e->exception.cleanup = (emergency ? emergencyExceptionCleanup : cleanup); e->object = object; - if (_Unwind_RaiseException(&e->exception) == _URC_END_OF_STACK && - uncaughtExceptionHandler != NULL) + _Unwind_RaiseException(&e->exception); + + if (uncaughtExceptionHandler != NULL) uncaughtExceptionHandler(object); OBJC_ERROR("_Unwind_RaiseException() returned!") } Index: src/runtime/lookup-asm/lookup-asm-sparc-elf.S ================================================================== --- src/runtime/lookup-asm/lookup-asm-sparc-elf.S +++ src/runtime/lookup-asm/lookup-asm-sparc-elf.S @@ -52,15 +52,20 @@ #endif ld [%o2 + %o4], %o2 ld [%o2 + %o5], %o2 cmp %o2, 0 - be \not_found + be 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 Index: src/runtime/lookup-asm/lookup-asm-x86-elf.S ================================================================== --- src/runtime/lookup-asm/lookup-asm-x86-elf.S +++ src/runtime/lookup-asm/lookup-asm-x86-elf.S @@ -17,63 +17,64 @@ #include "config.h" #include "platform.h" +.intel_syntax noprefix + .globl objc_msg_lookup .globl objc_msg_lookup_stret .globl objc_msg_lookup_super .globl objc_msg_lookup_super_stret .section .text .macro generate_lookup name not_found \name: - movl 4(%esp), %edx - testl %edx, %edx - jz ret_nil + mov edx, [esp+4] + test edx, edx + jz short ret_nil - movl (%edx), %edx - movl 32(%edx), %edx + mov edx, [edx] + mov edx, [edx+32] .Lmain_\name: - movl 8(%esp), %eax + mov eax, [esp+8] #ifdef OF_SELUID24 - movzbl 2(%eax), %ecx - movl (%edx,%ecx,4), %edx + movzx ecx, byte ptr [eax+2] + mov edx, [edx+ecx*4] #endif - movzbl 1(%eax), %ecx - movl (%edx,%ecx,4), %edx - movzbl (%eax), %ecx - movl (%edx,%ecx,4), %eax + movzx ecx, byte ptr [eax+1] + mov edx, [edx+ecx*4] + movzx ecx, byte ptr [eax] + mov eax, [edx+ecx*4] - testl %eax, %eax - jz 0f + test eax, eax + jz short 0f ret 0: call get_eip -1: - addl $_GLOBAL_OFFSET_TABLE_, %eax - movl \not_found@GOT(%eax), %eax - jmp *%eax + add eax, offset _GLOBAL_OFFSET_TABLE_ + lea eax, [eax+\not_found@GOTOFF] + jmp eax .type \name, %function .size \name, .-\name .endm .macro generate_lookup_super name lookup \name: - movl 4(%esp), %edx - movl (%edx), %eax - cmpl $0, %eax - je ret_nil - - movl %eax, 4(%esp) - movl 4(%edx), %edx - movl 32(%edx), %edx - jmp .Lmain_\lookup + mov edx, [esp+4] + mov eax, [edx] + test eax, eax + jz short ret_nil + + mov [esp+4], eax + mov edx, [edx+4] + mov edx, [edx+32] + jmp short .Lmain_\lookup .type \name, %function .size \name, .-\name .endm generate_lookup objc_msg_lookup objc_method_not_found @@ -81,20 +82,20 @@ generate_lookup_super objc_msg_lookup_super objc_msg_lookup generate_lookup_super objc_msg_lookup_super_stret objc_msg_lookup_stret ret_nil: call get_eip -0: - addl $nil_method-0b, %eax + add eax, offset _GLOBAL_OFFSET_TABLE_ + lea eax, [eax+nil_method@GOTOFF] ret nil_method: - xorl %eax, %eax + xor eax, eax ret get_eip: - movl (%esp), %eax + mov eax, [esp] ret #ifdef OF_LINUX .section .note.GNU-stack, "", %progbits #endif Index: src/runtime/lookup-asm/lookup-asm-x86-win32.S ================================================================== --- src/runtime/lookup-asm/lookup-asm-x86-win32.S +++ src/runtime/lookup-asm/lookup-asm-x86-win32.S @@ -14,76 +14,69 @@ * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ #include "config.h" + +.intel_syntax noprefix .globl _objc_msg_lookup .globl _objc_msg_lookup_stret .globl _objc_msg_lookup_super .globl _objc_msg_lookup_super_stret .section .text .macro generate_lookup name not_found \name: - movl 4(%esp), %edx - testl %edx, %edx - jz ret_nil + mov edx, [esp+4] + test edx, edx + jz short ret_nil - movl (%edx), %edx - movl 32(%edx), %edx + mov edx, [edx] + mov edx, [edx+32] .Lmain_\name: - movl 8(%esp), %eax + mov eax, [esp+8] #ifdef OF_SELUID24 - movzbl 2(%eax), %ecx - movl (%edx,%ecx,4), %edx + movzx ecx, byte ptr [eax+2] + mov edx, [edx+ecx*4] #endif - movzbl 1(%eax), %ecx - movl (%edx,%ecx,4), %edx - movzbl (%eax), %ecx - movl (%edx,%ecx,4), %eax + movzx ecx, byte ptr [eax+1] + mov edx, [edx+ecx*4] + movzx ecx, byte ptr [eax] + mov eax, [edx+ecx*4] - testl %eax, %eax - jz 0f + test eax, eax + jz short 0f ret 0: - call get_eip -1: - addl $\not_found-1b, %eax - jmp *%eax + jmp \not_found .endm .macro generate_lookup_super name lookup \name: - movl 4(%esp), %edx - movl (%edx), %eax - cmpl $0, %eax - je ret_nil - - movl %eax, 4(%esp) - movl 4(%edx), %edx - movl 32(%edx), %edx - jmp .Lmain_\lookup + mov edx, [esp+4] + mov eax, [edx] + test eax, eax + jz short ret_nil + + mov [esp+4], eax + mov edx, [edx+4] + mov edx, [edx+32] + jmp short .Lmain_\lookup .endm generate_lookup _objc_msg_lookup _objc_method_not_found generate_lookup _objc_msg_lookup_stret _objc_method_not_found_stret generate_lookup_super _objc_msg_lookup_super _objc_msg_lookup generate_lookup_super _objc_msg_lookup_super_stret _objc_msg_lookup_stret ret_nil: - call get_eip -0: - addl $nil_method-0b, %eax + mov eax, offset nil_method ret nil_method: - xorl %eax, %eax - ret - -get_eip: - movl (%esp), %eax + xor eax, eax ret Index: src/runtime/lookup-asm/lookup-asm-x86_64-elf.S ================================================================== --- src/runtime/lookup-asm/lookup-asm-x86_64-elf.S +++ src/runtime/lookup-asm/lookup-asm-x86_64-elf.S @@ -17,54 +17,56 @@ #include "config.h" #include "platform.h" +.intel_syntax noprefix + .globl objc_msg_lookup .globl objc_msg_lookup_stret .globl objc_msg_lookup_super .globl objc_msg_lookup_super_stret .section .text .macro generate_lookup name not_found \name: - testq %rdi, %rdi - jz ret_nil + test rdi, rdi + jz short ret_nil - movq (%rdi), %r8 - movq 64(%r8), %r8 + mov r8, [rdi] + mov r8, [r8+64] .Lmain_\name: - movq (%rsi), %rax - movzbl %ah, %ecx - movzbl %al, %edx + mov rax, [rsi] + movzx ecx, ah + movzx edx, al #ifdef OF_SELUID24 - shrl $16, %eax + shr eax, 16 - movq (%r8,%rax,8), %r8 + mov r8, [r8+rax*8] #endif - movq (%r8,%rcx,8), %r8 - movq (%r8,%rdx,8), %rax + mov r8, [r8+rcx*8] + mov rax, [r8+rdx*8] - testq %rax, %rax - jz \not_found@PLT + test rax, rax + jz short \not_found@PLT ret .type \name, %function .size \name, .-\name .endm .macro generate_lookup_super name lookup \name: - movq %rdi, %r8 - movq (%rdi), %rdi - testq %rdi, %rdi - jz ret_nil - - movq 8(%r8), %r8 - movq 64(%r8), %r8 - jmp .Lmain_\lookup + mov r8, rdi + mov rdi, [rdi] + test rdi, rdi + jz short ret_nil + + mov r8, [r8+8] + mov r8, [r8+64] + jmp short .Lmain_\lookup .type \name, %function .size \name, .-\name .endm generate_lookup objc_msg_lookup objc_method_not_found @@ -71,15 +73,15 @@ generate_lookup objc_msg_lookup_stret objc_method_not_found_stret generate_lookup_super objc_msg_lookup_super objc_msg_lookup generate_lookup_super objc_msg_lookup_super_stret objc_msg_lookup_stret ret_nil: - leaq nil_method(%rip), %rax + lea rax, [rip+nil_method] ret nil_method: - xorq %rax, %rax + xor rax, rax ret #ifdef OF_LINUX .section .note.GNU-stack, "", %progbits #endif Index: src/runtime/lookup-asm/lookup-asm-x86_64-macho.S ================================================================== --- src/runtime/lookup-asm/lookup-asm-x86_64-macho.S +++ src/runtime/lookup-asm/lookup-asm-x86_64-macho.S @@ -14,62 +14,64 @@ * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ #include "config.h" + +.intel_syntax noprefix .globl _objc_msg_lookup .globl _objc_msg_lookup_stret .globl _objc_msg_lookup_super .globl _objc_msg_lookup_super_stret .section __TEXT, __text, regular, pure_instructions .macro generate_lookup $0: - testq %rdi, %rdi + test rdi, rdi jz ret_nil - movq (%rdi), %r8 - movq 64(%r8), %r8 + mov r8, [rdi] + mov r8, [r8+64] Lmain_$0: - movq (%rsi), %rax - movzbl %ah, %ecx - movzbl %al, %edx + mov rax, [rsi] + movzx ecx, ah + movzx edx, al #ifdef OF_SELUID24 - shrl $$16, %eax + shr eax, 16 - movq (%r8,%rax,8), %r8 + mov r8, [r8+rax*8] #endif - movq (%r8,%rcx,8), %r8 - movq (%r8,%rdx,8), %rax + mov r8, [r8+rcx*8] + mov rax, [r8+rdx*8] - testq %rax, %rax + test rax, rax jz $1 ret .endmacro .macro generate_lookup_super $0: - movq %rdi, %r8 - movq (%rdi), %rdi - testq %rdi, %rdi + mov r8, rdi + mov rdi, [rdi] + test rdi, rdi jz ret_nil - movq 8(%r8), %r8 - movq 64(%r8), %r8 + mov r8, [r8+8] + mov r8, [r8+64] jmp Lmain_$1 .endmacro generate_lookup _objc_msg_lookup, _objc_method_not_found generate_lookup _objc_msg_lookup_stret, _objc_method_not_found_stret generate_lookup_super _objc_msg_lookup_super, _objc_msg_lookup generate_lookup_super _objc_msg_lookup_super_stret, _objc_msg_lookup_stret ret_nil: - leaq nil_method(%rip), %rax + lea rax, [rip+nil_method] ret nil_method: - movq %rdi, %rax + mov rax, rdi ret Index: src/runtime/lookup-asm/lookup-asm-x86_64-win64.S ================================================================== --- src/runtime/lookup-asm/lookup-asm-x86_64-win64.S +++ src/runtime/lookup-asm/lookup-asm-x86_64-win64.S @@ -15,69 +15,71 @@ * file. */ #include "config.h" +.intel_syntax noprefix + .globl objc_msg_lookup .globl objc_msg_lookup_stret .globl objc_msg_lookup_super .globl objc_msg_lookup_super_stret .section .text .macro generate_lookup name not_found \name: - testq %rcx, %rcx - jz ret_nil + test %rcx, %rcx + jz short ret_nil - movq (%rcx), %r8 - movq 56(%r8), %r8 + mov r8, [rcx] + mov r8, [r8+56] .Lmain_\name: - movq %rcx, %r10 - movq %rdx, %r11 + mov r10, rcx + mov r11, rdx - movq (%rdx), %rax - movzbl %ah, %ecx - movzbl %al, %edx + mov rax, [rdx] + movzx ecx, ah + movzx edx, al #ifdef OF_SELUID24 - shrl $16, %eax + shr eax, 16 - movq (%r8,%rax,8), %r8 + mov r8, [r8+rax*8] #endif - movq (%r8,%rcx,8), %r8 - movq (%r8,%rdx,8), %rax + mov r8, [r8+rcx*8] + mov rax, [r8+rdx*8] - testq %rax, %rax - jz 0f + test rax, rax + jz short 0f ret 0: - movq %r10, %rcx - movq %r11, %rdx + mov rcx, r10 + mov rdx, r11 jmp \not_found .endm .macro generate_lookup_super name lookup \name: - movq %rcx, %r8 - movq (%rcx), %rcx - testq %rcx, %rcx - jz ret_nil - - movq 8(%r8), %r8 - movq 56(%r8), %r8 - jmp .Lmain_\lookup + mov r8, rcx + mov rcx, [rcx] + test rcx, rcx + jz short ret_nil + + mov r8, [r8+8] + mov r8, [r8+56] + jmp short .Lmain_\lookup .endm generate_lookup objc_msg_lookup objc_method_not_found generate_lookup objc_msg_lookup_stret objc_method_not_found_stret generate_lookup_super objc_msg_lookup_super objc_msg_lookup generate_lookup_super objc_msg_lookup_super_stret objc_msg_lookup_stret ret_nil: - leaq nil_method(%rip), %rax + mov rax, offset nil_method ret nil_method: - xorq %rax, %rax + xor rax, rax ret Index: src/scrypt.h ================================================================== --- src/scrypt.h +++ src/scrypt.h @@ -28,22 +28,55 @@ /*! @file */ @class OFHMAC; +/*! + * @brief The parameters for @ref of_scrypt. + */ +typedef struct of_scrypt_parameters_t { + /*! @brief The block size to use. */ + size_t blockSize; + /*! @brief The CPU/memory cost factor to use. */ + size_t costFactor; + /*! @brief The parallelization to use. */ + size_t parallelization; + /*! @brief The salt to derive a key with. */ + const unsigned char *salt; + /*! @brief The length of the salt. */ + size_t saltLength; + /*! @brief The password to derive a key from. */ + const char *password; + /*! @brief The length of the password. */ + size_t passwordLength; + /*! @brief The buffer to write the key to. */ + unsigned char *key; + /*! + * @brief The desired length for the derived key. + * + * @ref key needs to have enough storage. + */ + size_t keyLength; + /*! @brief Whether data may be stored in swappable memory. */ + bool allowsSwappableMemory; +} of_scrypt_parameters_t; + #ifdef __cplusplus extern "C" { #endif extern void of_salsa20_8_core(uint32_t buffer[_Nonnull 16]); extern void of_scrypt_block_mix(uint32_t *output, const uint32_t *input, size_t blockSize); extern void of_scrypt_romix(uint32_t *buffer, size_t blockSize, size_t costFactor, uint32_t *tmp); -extern void of_scrypt(size_t blockSize, size_t costFactor, - size_t parallelization, const unsigned char *salt, size_t saltLength, - const char *password, size_t passwordLength, - unsigned char *key, size_t keyLength, bool allowsSwappableMemory); + +/*! + * @brief Derives a key from a password and a salt using scrypt. + * + * @param param The parameters to use + */ +extern void of_scrypt(of_scrypt_parameters_t param); #ifdef __cplusplus } #endif OF_ASSUME_NONNULL_END Index: src/scrypt.m ================================================================== --- src/scrypt.m +++ src/scrypt.m @@ -83,12 +83,12 @@ { uint32_t tmp[16]; /* Check defined here and executed in of_scrypt() */ #define OVERFLOW_CHECK_1 \ - if (blockSize > SIZE_MAX / 2 || \ - 2 * blockSize - 1 > SIZE_MAX / 16) \ + if (param.blockSize > SIZE_MAX / 2 || \ + 2 * param.blockSize - 1 > SIZE_MAX / 16) \ @throw [OFOutOfRangeException exception]; memcpy(tmp, input + (2 * blockSize - 1) * 16, 64); for (size_t i = 0; i < 2 * blockSize; i++) { @@ -110,12 +110,12 @@ void of_scrypt_romix(uint32_t *buffer, size_t blockSize, size_t costFactor, uint32_t *tmp) { /* Check defined here and executed in of_scrypt() */ -#define OVERFLOW_CHECK_2 \ - if (blockSize > SIZE_MAX / 128 / costFactor) \ +#define OVERFLOW_CHECK_2 \ + if (param.blockSize > SIZE_MAX / 128 / param.costFactor) \ @throw [OFOutOfRangeException exception]; uint32_t *tmp2 = tmp + 32 * blockSize; memcpy(tmp, buffer, 128 * blockSize); @@ -137,20 +137,19 @@ if (i < costFactor - 1) memcpy(tmp, buffer, 128 * blockSize); } } -void of_scrypt(size_t blockSize, size_t costFactor, - size_t parallelization, const unsigned char *salt, size_t saltLength, - const char *password, size_t passwordLength, - unsigned char *key, size_t keyLength, bool allowsSwappableMemory) +void +of_scrypt(of_scrypt_parameters_t param) { OFSecureData *tmp = nil, *buffer = nil; OFHMAC *HMAC = nil; - if (blockSize == 0 || costFactor <= 1 || - (costFactor & (costFactor - 1)) != 0 || parallelization == 0) + if (param.blockSize == 0 || param.costFactor <= 1 || + (param.costFactor & (param.costFactor - 1)) != 0 || + param.parallelization == 0) @throw [OFInvalidArgumentException exception]; /* * These are defined by the functions above. They are defined there so * that the check is next to the code and easy to verify, but actually @@ -160,45 +159,63 @@ OVERFLOW_CHECK_2 @try { uint32_t *tmpItems, *bufferItems; - if (costFactor > SIZE_MAX - 1 || - (costFactor + 1) > SIZE_MAX / 128) + if (param.costFactor > SIZE_MAX - 1 || + (param.costFactor + 1) > SIZE_MAX / 128) @throw [OFOutOfRangeException exception]; tmp = [[OFSecureData alloc] - initWithItemSize: blockSize - count: (costFactor + 1) * 128 - allowsSwappableMemory: allowsSwappableMemory]; + initWithItemSize: param.blockSize + count: (param.costFactor + 1) * 128 + allowsSwappableMemory: param.allowsSwappableMemory]; tmpItems = tmp.mutableItems; - if (parallelization > SIZE_MAX / 128) + if (param.parallelization > SIZE_MAX / 128) @throw [OFOutOfRangeException exception]; buffer = [[OFSecureData alloc] - initWithItemSize: blockSize - count: parallelization * 128 - allowsSwappableMemory: allowsSwappableMemory]; + initWithItemSize: param.blockSize + count: param.parallelization * 128 + allowsSwappableMemory: param.allowsSwappableMemory]; bufferItems = buffer.mutableItems; HMAC = [[OFHMAC alloc] initWithHashClass: [OFSHA256Hash class] - allowsSwappableMemory: allowsSwappableMemory]; - - of_pbkdf2(HMAC, 1, salt, saltLength, password, passwordLength, - (unsigned char *)bufferItems, - parallelization * 128 * blockSize, allowsSwappableMemory); - - for (size_t i = 0; i < parallelization; i++) - of_scrypt_romix(bufferItems + i * 32 * blockSize, - blockSize, costFactor, tmpItems); - - of_pbkdf2(HMAC, 1, (unsigned char *)bufferItems, - parallelization * 128 * blockSize, password, passwordLength, - key, keyLength, allowsSwappableMemory); + allowsSwappableMemory: param.allowsSwappableMemory]; + + of_pbkdf2((of_pbkdf2_parameters_t){ + .HMAC = HMAC, + .iterations = 1, + .salt = param.salt, + .saltLength = param.saltLength, + .password = param.password, + .passwordLength = param.passwordLength, + .key = (unsigned char *)bufferItems, + .keyLength = param.parallelization * 128 * + param.blockSize, + .allowsSwappableMemory = param.allowsSwappableMemory + }); + + for (size_t i = 0; i < param.parallelization; i++) + of_scrypt_romix(bufferItems + i * 32 * param.blockSize, + param.blockSize, param.costFactor, tmpItems); + + of_pbkdf2((of_pbkdf2_parameters_t){ + .HMAC = HMAC, + .iterations = 1, + .salt = (unsigned char *)bufferItems, + .saltLength = param.parallelization * 128 * + param.blockSize, + .password = param.password, + .passwordLength = param.passwordLength, + .key = param.key, + .keyLength = param.keyLength, + .allowsSwappableMemory = param.allowsSwappableMemory + }); } @finally { [tmp release]; [buffer release]; [HMAC release]; } } Index: tests/Makefile ================================================================== --- tests/Makefile +++ tests/Makefile @@ -4,10 +4,11 @@ CLEAN = EBOOT.PBP \ boot.dol \ ${PROG_NOINST}.arm9 \ ${PROG_NOINST}.nds +DISTCLEAN = Info.plist PROG_NOINST = tests${PROG_SUFFIX} STATIC_LIB_NOINST = ${TESTS_STATIC_LIB} SRCS = ForwardingTests.m \ OFArrayTests.m \ Index: tests/OFDNSResolverTests.m ================================================================== --- tests/OFDNSResolverTests.m +++ tests/OFDNSResolverTests.m @@ -17,12 +17,10 @@ #include "config.h" #import "TestsAppDelegate.h" -static OFString *module = @"OFDNSResolverTests"; - @implementation TestsAppDelegate (OFDNSResolverTests) - (void)DNSResolverTests { void *pool = objc_autoreleasePoolPush(); OFDNSResolver *resolver = [OFDNSResolver resolver]; @@ -62,14 +60,14 @@ [of_stdout writeFormat: @"[OFDNSResolver] Min number of dots in absolute name: %u\n", resolver.minNumberOfDotsInAbsoluteName]; [of_stdout writeFormat: @"[OFDNSResolver] Uses TCP: %u\n", - module, resolver.usesTCP]; + resolver.usesTCP]; [of_stdout writeFormat: @"[OFDNSResolver] Config reload interval: %lf\n", resolver.configReloadInterval]; objc_autoreleasePoolPop(pool); } @end Index: tests/OFLocaleTests.m ================================================================== --- tests/OFLocaleTests.m +++ tests/OFLocaleTests.m @@ -24,20 +24,20 @@ { void *pool = objc_autoreleasePoolPush(); of_stdout.foregroundColor = [OFColor lime]; - [of_stdout writeFormat: @"[OFLocale]: Language: %@\n", + [of_stdout writeFormat: @"[OFLocale] Language: %@\n", [OFLocale language]]; - [of_stdout writeFormat: @"[OFLocale]: Territory: %@\n", + [of_stdout writeFormat: @"[OFLocale] Territory: %@\n", [OFLocale territory]]; - [of_stdout writeFormat: @"[OFLocale]: Encoding: %@\n", + [of_stdout writeFormat: @"[OFLocale] Encoding: %@\n", of_string_name_of_encoding([OFLocale encoding])]; - [of_stdout writeFormat: @"[OFLocale]: Decimal point: %@\n", + [of_stdout writeFormat: @"[OFLocale] Decimal point: %@\n", [OFLocale decimalPoint]]; objc_autoreleasePoolPop(pool); } @end Index: tests/OFSPXSocketTests.m ================================================================== --- tests/OFSPXSocketTests.m +++ tests/OFSPXSocketTests.m @@ -163,18 +163,32 @@ memcpy(delegate->_expectedNode, node, IPX_NODE_LEN); delegate->_expectedNetwork = network = of_socket_address_get_ipx_network(&address1); delegate->_expectedPort = port = of_socket_address_get_port(&address1); - [sockClient asyncConnectToNode: node - network: network - port: port]; - - [[OFRunLoop mainRunLoop] runUntilDate: - [OFDate dateWithTimeIntervalSinceNow: 2]]; - - TEST(@"-[asyncAccept] & -[asyncConnectToNode:network:port:]", - delegate->_accepted && delegate->_connected) + @try { + [sockClient asyncConnectToNode: node + network: network + port: port]; + + [[OFRunLoop mainRunLoop] runUntilDate: + [OFDate dateWithTimeIntervalSinceNow: 2]]; + + TEST(@"-[asyncAccept] & -[asyncConnectToNode:network:port:]", + delegate->_accepted && delegate->_connected) + } @catch (OFObserveFailedException *e) { + switch (e.errNo) { + case ENOTSOCK: + of_stdout.foregroundColor = [OFColor lime]; + [of_stdout writeLine: + @"[OFSPXSocket] -[asyncAccept] & " + @"-[asyncConnectToNode:network:port:]: select() " + @"not supported for SPX, skipping test"]; + break; + default: + @throw e; + } + } objc_autoreleasePoolPop(pool); } @end Index: tests/OFSPXStreamSocketTests.m ================================================================== --- tests/OFSPXStreamSocketTests.m +++ tests/OFSPXStreamSocketTests.m @@ -167,18 +167,32 @@ memcpy(delegate->_expectedNode, node, IPX_NODE_LEN); delegate->_expectedNetwork = network = of_socket_address_get_ipx_network(&address1); delegate->_expectedPort = port = of_socket_address_get_port(&address1); - [sockClient asyncConnectToNode: node - network: network - port: port]; - - [[OFRunLoop mainRunLoop] runUntilDate: - [OFDate dateWithTimeIntervalSinceNow: 2]]; - - TEST(@"-[asyncAccept] & -[asyncConnectToNode:network:port:]", - delegate->_accepted && delegate->_connected) + @try { + [sockClient asyncConnectToNode: node + network: network + port: port]; + + [[OFRunLoop mainRunLoop] runUntilDate: + [OFDate dateWithTimeIntervalSinceNow: 2]]; + + TEST(@"-[asyncAccept] & -[asyncConnectToNode:network:port:]", + delegate->_accepted && delegate->_connected) + } @catch (OFObserveFailedException *e) { + switch (e.errNo) { + case ENOTSOCK: + of_stdout.foregroundColor = [OFColor lime]; + [of_stdout writeLine: + @"[OFSPXStreamSocket] -[asyncAccept] & " + @"-[asyncConnectToNode:network:port:]: select() " + @"not supported for SPX, skipping test"]; + break; + default: + @throw e; + } + } objc_autoreleasePoolPop(pool); } @end Index: tests/PBKDF2Tests.m ================================================================== --- tests/PBKDF2Tests.m +++ tests/PBKDF2Tests.m @@ -32,47 +32,96 @@ unsigned char key[25]; /* Test vectors from RFC 6070 */ TEST(@"PBKDF2-SHA1, 1 iteration", - R(of_pbkdf2(HMAC, 1, (unsigned char *)"salt", 4, "password", 8, key, - 20, true)) && - memcmp(key, "\x0C\x60\xC8\x0F\x96\x1F\x0E\x71\xF3\xA9\xB5\x24\xAF" - "\x60\x12\x06\x2F\xE0\x37\xA6", 20) == 0) + R(of_pbkdf2((of_pbkdf2_parameters_t){ + .HMAC = HMAC, + .iterations = 1, + .salt = (unsigned char *)"salt", + .saltLength = 4, + .password = "password", + .passwordLength = 8, + .key = key, + .keyLength = 20, + .allowsSwappableMemory = true + })) && memcmp(key, "\x0C\x60\xC8\x0F\x96\x1F\x0E\x71\xF3\xA9\xB5" + "\x24\xAF\x60\x12\x06\x2F\xE0\x37\xA6", 20) == 0) TEST(@"PBKDF2-SHA1, 2 iterations", - R(of_pbkdf2(HMAC, 2, (unsigned char *)"salt", 4, "password", 8, key, - 20, true)) && - memcmp(key, "\xEA\x6C\x01\x4D\xC7\x2D\x6F\x8C\xCD\x1E\xD9\x2A\xCE" - "\x1D\x41\xF0\xD8\xDE\x89\x57", 20) == 0) + R(of_pbkdf2((of_pbkdf2_parameters_t){ + .HMAC = HMAC, + .iterations = 2, + .salt = (unsigned char *)"salt", + .saltLength = 4, + .password = "password", + .passwordLength = 8, + .key = key, + .keyLength = 20, + .allowsSwappableMemory = true + })) && memcmp(key, "\xEA\x6C\x01\x4D\xC7\x2D\x6F\x8C\xCD\x1E\xD9" + "\x2A\xCE\x1D\x41\xF0\xD8\xDE\x89\x57", 20) == 0) TEST(@"PBKDF2-SHA1, 4096 iterations", - R(of_pbkdf2(HMAC, 4096, (unsigned char *)"salt", 4, "password", 8, - key, 20, true)) && - memcmp(key, "\x4B\x00\x79\x01\xB7\x65\x48\x9A\xBE\xAD\x49\xD9\x26" - "\xF7\x21\xD0\x65\xA4\x29\xC1", 20) == 0) + R(of_pbkdf2((of_pbkdf2_parameters_t){ + .HMAC = HMAC, + .iterations = 4096, + .salt = (unsigned char *)"salt", + .saltLength = 4, + .password = "password", + .passwordLength = 8, + .key = key, + .keyLength = 20, + .allowsSwappableMemory = true + })) && memcmp(key, "\x4B\x00\x79\x01\xB7\x65\x48\x9A\xBE\xAD\x49" + "\xD9\x26\xF7\x21\xD0\x65\xA4\x29\xC1", 20) == 0) /* This test takes too long, even on a fast machine. */ #if 0 TEST(@"PBKDF2-SHA1, 16777216 iterations", - R(of_pbkdf2(HMAC, 16777216, (unsigned char *)"salt", 4, "password", - 8, key, 20, true)) && - memcmp(key, "\xEE\xFE\x3D\x61\xCD\x4D\xA4\xE4\xE9\x94\x5B\x3D\x6B" - "\xA2\x15\x8C\x26\x34\xE9\x84", 20) == 0) + R(of_pbkdf2((of_pbkdf2_parameters_t){ + .HMAC = HMAC, + .iterations = 16777216, + .salt = (unsigned char *)"salt", + .saltLength = 4, + .password = "password", + .passwordLength = 8, + .key = key, + .keyLength = 20, + .allowsSwappableMemory = true + })) && memcmp(key, "\xEE\xFE\x3D\x61\xCD\x4D\xA4\xE4\xE9\x94\x5B" + "\x3D\x6B\xA2\x15\x8C\x26\x34\xE9\x84", 20) == 0) #endif TEST(@"PBKDF2-SHA1, 4096 iterations, key > 1 block", - R(of_pbkdf2(HMAC, 4096, - (unsigned char *)"saltSALTsaltSALTsaltSALTsaltSALTsalt", 36, - "passwordPASSWORDpassword", 24, key, 25, true)) && + R(of_pbkdf2((of_pbkdf2_parameters_t){ + .HMAC = HMAC, + .iterations = 4096, + .salt = (unsigned char *)"saltSALTsaltSALTsalt" + "SALTsaltSALTsalt", + .saltLength = 36, + .password = "passwordPASSWORDpassword", + .passwordLength = 24, + .key = key, + .keyLength = 25, + .allowsSwappableMemory = true + })) && memcmp(key, "\x3D\x2E\xEC\x4F\xE4\x1C\x84\x9B\x80\xC8\xD8\x36\x62" - "\xC0\xE4\x4A\x8B\x29\x1A\x96\x4C\xF2\xF0\x70\x38", 25) == 0) + "\xC0\xE4\x4A\x8B\x29\x1A\x96\x4C\xF2\xF0\x70\x38", 25) == 0) TEST(@"PBKDF2-SHA1, 4096 iterations, key < 1 block", - R(of_pbkdf2(HMAC, 4096, (unsigned char *)"sa\0lt", 5, "pass\0word", - 9, key, 16, true)) && - memcmp(key, "\x56\xFA\x6A\xA7\x55\x48\x09\x9D\xCC\x37\xD7\xF0\x34" - "\x25\xE0\xC3", 16) == 0) + R(of_pbkdf2((of_pbkdf2_parameters_t){ + .HMAC = HMAC, + .iterations = 4096, + .salt = (unsigned char *)"sa\0lt", + .saltLength = 5, + .password = "pass\0word", + .passwordLength = 9, + .key = key, + .keyLength = 16, + .allowsSwappableMemory = true + })) && memcmp(key, "\x56\xFA\x6A\xA7\x55\x48\x09\x9D\xCC\x37\xD7" + "\xF0\x34\x25\xE0\xC3", 16) == 0) objc_autoreleasePoolPop(pool); } @end Index: tests/ScryptTests.m ================================================================== --- tests/ScryptTests.m +++ tests/ScryptTests.m @@ -154,28 +154,66 @@ R(memcpy(ROMixBuffer, ROMixInput, 128)) && R(of_scrypt_romix(ROMixBuffer, 1, 16, ROMixTmp)) && memcmp(ROMixBuffer, ROMixOutput, 128) == 0) TEST(@"scrypt test vector #1", - R(of_scrypt(1, 16, 1, (unsigned char *)"", 0, "", 0, output, 64, - true)) && memcmp(output, testVector1, 64) == 0) + R(of_scrypt((of_scrypt_parameters_t){ + .blockSize = 1, + .costFactor = 16, + .parallelization = 1, + .salt = (unsigned char *)"", + .saltLength = 0, + .password = "", + .passwordLength = 0, + .key = output, + .keyLength = 64, + .allowsSwappableMemory = true + })) && memcmp(output, testVector1, 64) == 0) TEST(@"scrypt test vector #2", - R(of_scrypt(8, 1024, 16, (unsigned char *)"NaCl", 4, "password", 8, - output, 64, true)) && memcmp(output, testVector2, 64) == 0) + R(of_scrypt((of_scrypt_parameters_t){ + .blockSize = 8, + .costFactor = 1024, + .parallelization = 16, + .salt = (unsigned char *)"NaCl", + .saltLength = 4, + .password = "password", + .passwordLength = 8, + .key = output, + .keyLength = 64, + .allowsSwappableMemory = true + })) && memcmp(output, testVector2, 64) == 0) TEST(@"scrypt test vector #3", - R(of_scrypt(8, 16384, 1, (unsigned char *)"SodiumChloride", 14, - "pleaseletmein", 13, output, 64, true)) && - memcmp(output, testVector3, 64) == 0) + R(of_scrypt((of_scrypt_parameters_t){ + .blockSize = 8, + .costFactor = 16384, + .parallelization = 1, + .salt = (unsigned char *)"SodiumChloride", + .saltLength = 14, + .password = "pleaseletmein", + .passwordLength = 13, + .key = output, + .keyLength = 64, + .allowsSwappableMemory = true + })) && memcmp(output, testVector3, 64) == 0) /* The forth test vector is too expensive to include it in the tests. */ #if 0 TEST(@"scrypt test vector #4", - R(of_scrypt(8, 1048576, 1, (unsigned char *)"SodiumChloride", 14, - "pleaseletmein", 13, output, 64, true)) && - memcmp(output, testVector4, 64) == 0) + R(of_scrypt((of_scrypt_parameters_t){ + .blockSize = 8, + .costFactor = 1048576, + .parallelization = 1, + .salt = (unsigned char *)"SodiumChloride", + .saltLength = 14, + .password = "pleaseletmein", + .passwordLength = 13, + .key = output, + .keyLength = 64, + .allowsSwappableMemory = true + })) && memcmp(output, testVector4, 64) == 0) #endif objc_autoreleasePoolPop(pool); } @end Index: tests/TestsAppDelegate.m ================================================================== --- tests/TestsAppDelegate.m +++ tests/TestsAppDelegate.m @@ -213,26 +213,24 @@ - (void)outputSuccess: (OFString *)test inModule: (OFString *)module { if (of_stdout.hasTerminal) { - of_stdout.cursorColumn = 0; of_stdout.foregroundColor = [OFColor lime]; [of_stdout eraseLine]; - [of_stdout writeFormat: @"[%@] %@: ok\n", module, test]; + [of_stdout writeFormat: @"\r[%@] %@: ok\n", module, test]; } else [of_stdout writeLine: @"ok"]; } - (void)outputFailure: (OFString *)test inModule: (OFString *)module { if (of_stdout.hasTerminal) { - of_stdout.cursorColumn = 0; of_stdout.foregroundColor = [OFColor red]; [of_stdout eraseLine]; - [of_stdout writeFormat: @"[%@] %@: failed\n", module, test]; + [of_stdout writeFormat: @"\r[%@] %@: failed\n", module, test]; #ifdef OF_WII [of_stdout reset]; [of_stdout writeLine: @"Press A to continue!"]; @@ -285,11 +283,11 @@ gspWaitForVBlank(); } #endif - of_stdout.cursorColumn = 0; + [of_stdout writeString: @"\r"]; [of_stdout reset]; [of_stdout eraseLine]; } else [of_stdout writeLine: @"failed"]; } Index: tests/plugin/Makefile ================================================================== --- tests/plugin/Makefile +++ tests/plugin/Makefile @@ -1,9 +1,11 @@ +DISTCLEAN = Info.plist + PLUGIN_NOINST = TestPlugin${PLUGIN_SUFFIX} SRCS = TestPlugin.m include ../../buildsys.mk include ../../extra.mk CPPFLAGS += -I../.. -I../../src -I../../src/runtime LIBS := ${TESTPLUGIN_LIBS} ${LIBS} LD = ${OBJC} Index: utils/ofarc/GZIPArchive.m ================================================================== --- utils/ofarc/GZIPArchive.m +++ utils/ofarc/GZIPArchive.m @@ -41,10 +41,26 @@ [fileManager setAttributes: destinationAttributes ofItemAtPath: destination]; #endif } + +static void +setModificationDate(OFString *path, OFGZIPStream *stream) +{ + OFDate *modificationDate = stream.modificationDate; + of_file_attributes_t attributes; + + if (modificationDate == nil) + return; + + attributes = [OFDictionary + dictionaryWithObject: modificationDate + forKey: of_file_attribute_key_modification_date]; + [[OFFileManager defaultManager] setAttributes: attributes + ofItemAtPath: path]; +} @implementation GZIPArchive + (void)initialize { if (self == [GZIPArchive class]) @@ -129,10 +145,13 @@ app->_exitStatus = 1; return; } } + [output close]; + setModificationDate(fileName, _stream); + if (app->_outputLevel >= 0) { [of_stdout writeString: @"\r"]; [of_stdout writeLine: OF_LOCALIZED(@"extracting_file_done", @"Extracting %[file]... done", @"file", fileName)]; Index: utils/ofarc/LHAArchive.m ================================================================== --- utils/ofarc/LHAArchive.m +++ utils/ofarc/LHAArchive.m @@ -53,10 +53,34 @@ [[OFFileManager defaultManager] setAttributes: attributes ofItemAtPath: path]; #endif } + +static void +setModificationDate(OFString *path, OFLHAArchiveEntry *entry) +{ + OFDate *modificationDate = entry.modificationDate; + of_file_attributes_t attributes; + + if (modificationDate == nil) { + /* + * Fall back to the original date if we have no modification + * date, as the modification date is a UNIX extension. + */ + modificationDate = entry.date; + + if (modificationDate == nil) + return; + } + + attributes = [OFDictionary + dictionaryWithObject: modificationDate + forKey: of_file_attribute_key_modification_date]; + [[OFFileManager defaultManager] setAttributes: attributes + ofItemAtPath: path]; +} @implementation LHAArchive + (void)initialize { if (self == [LHAArchive class]) @@ -283,10 +307,11 @@ if ([fileName hasSuffix: @"/"]) { [fileManager createDirectoryAtPath: outFileName createParents: true]; setPermissions(outFileName, entry); + setModificationDate(outFileName, entry); if (app->_outputLevel >= 0) { [of_stdout writeString: @"\r"]; [of_stdout writeLine: OF_LOCALIZED( @"extracting_file_done", @@ -339,10 +364,13 @@ @"file", fileName, @"percent", percentString)]; } } + [output close]; + setModificationDate(outFileName, entry); + if (app->_outputLevel >= 0) { [of_stdout writeString: @"\r"]; [of_stdout writeLine: OF_LOCALIZED( @"extracting_file_done", @"Extracting %[file]... done", Index: utils/ofarc/TarArchive.m ================================================================== --- utils/ofarc/TarArchive.m +++ utils/ofarc/TarArchive.m @@ -41,10 +41,26 @@ [[OFFileManager defaultManager] setAttributes: attributes ofItemAtPath: path]; #endif } + +static void +setModificationDate(OFString *path, OFTarArchiveEntry *entry) +{ + OFDate *modificationDate = entry.modificationDate; + of_file_attributes_t attributes; + + if (modificationDate == nil) + return; + + attributes = [OFDictionary + dictionaryWithObject: modificationDate + forKey: of_file_attribute_key_modification_date]; + [[OFFileManager defaultManager] setAttributes: attributes + ofItemAtPath: path]; +} @implementation TarArchive + (void)initialize { if (self == [TarArchive class]) @@ -304,10 +320,11 @@ (type == OF_TAR_ARCHIVE_ENTRY_TYPE_FILE && [fileName hasSuffix: @"/"])) { [fileManager createDirectoryAtPath: outFileName createParents: true]; setPermissions(outFileName, entry); + setModificationDate(outFileName, entry); if (app->_outputLevel >= 0) { [of_stdout writeString: @"\r"]; [of_stdout writeLine: OF_LOCALIZED( @"extracting_file_done", @@ -360,10 +377,13 @@ @"file", fileName, @"percent", percentString)]; } } + [output close]; + setModificationDate(outFileName, entry); + if (app->_outputLevel >= 0) { [of_stdout writeString: @"\r"]; [of_stdout writeLine: OF_LOCALIZED( @"extracting_file_done", @"Extracting %[file]... done", Index: utils/ofarc/ZIPArchive.m ================================================================== --- utils/ofarc/ZIPArchive.m +++ utils/ofarc/ZIPArchive.m @@ -54,10 +54,26 @@ [[OFFileManager defaultManager] setAttributes: attributes ofItemAtPath: path]; } #endif } + +static void +setModificationDate(OFString *path, OFZIPArchiveEntry *entry) +{ + OFDate *modificationDate = entry.modificationDate; + of_file_attributes_t attributes; + + if (modificationDate == nil) + return; + + attributes = [OFDictionary + dictionaryWithObject: modificationDate + forKey: of_file_attribute_key_modification_date]; + [[OFFileManager defaultManager] setAttributes: attributes + ofItemAtPath: path]; +} @implementation ZIPArchive + (void)initialize { if (self == [ZIPArchive class]) @@ -260,10 +276,11 @@ if ([fileName hasSuffix: @"/"]) { [fileManager createDirectoryAtPath: outFileName createParents: true]; setPermissions(outFileName, entry); + setModificationDate(outFileName, entry); if (app->_outputLevel >= 0) { [of_stdout writeString: @"\r"]; [of_stdout writeLine: OF_LOCALIZED( @"extracting_file_done", @@ -316,10 +333,13 @@ @"file", fileName, @"percent", percentString)]; } } + [output close]; + setModificationDate(outFileName, entry); + if (app->_outputLevel >= 0) { [of_stdout writeString: @"\r"]; [of_stdout writeLine: OF_LOCALIZED( @"extracting_file_done", @"Extracting %[file]... done",