From 5d31c424bfc1a24d86056a2232be90a628dd319d Mon Sep 17 00:00:00 2001 From: Nemanja Boric <4burgos@gmail.com> Date: Thu, 20 Oct 2016 20:24:45 +0200 Subject: [PATCH 01/82] Add linux-specific `core.sys.linux.sys.file` module This adds core.sys.linux.file module which contains flock function definition and values of the parameters to pass. --- mak/COPY | 1 + src/core/sys/linux/sys/file.d | 34 ++++++++++++++++++++++++++++++++++ win32.mak | 3 +++ win64.mak | 3 +++ 4 files changed, 41 insertions(+) create mode 100644 src/core/sys/linux/sys/file.d diff --git a/mak/COPY b/mak/COPY index 58ed65e7b1..9e4f544109 100644 --- a/mak/COPY +++ b/mak/COPY @@ -93,6 +93,7 @@ COPY=\ $(IMPDIR)\core\sys\linux\unistd.d \ \ $(IMPDIR)\core\sys\linux\sys\auxv.d \ + $(IMPDIR)\core\sys\linux\sys\file.d \ $(IMPDIR)\core\sys\linux\sys\inotify.d \ $(IMPDIR)\core\sys\linux\sys\mman.d \ $(IMPDIR)\core\sys\linux\sys\signalfd.d \ diff --git a/src/core/sys/linux/sys/file.d b/src/core/sys/linux/sys/file.d new file mode 100644 index 0000000000..ccdfd24503 --- /dev/null +++ b/src/core/sys/linux/sys/file.d @@ -0,0 +1,34 @@ +/** + * D header file for Linux file ops. + * + * Copyright: Copyright Nemanja Boric 2016. + * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0). + * Authors: Nemanja Boric + */ +module core.sys.linux.sys.file; + +version (linux): +extern (C): +nothrow: +@nogc: + +/* Operations for the `flock' call. */ +/// Shared lock +enum LOCK_SH = 0x01; +/// Exclusive lock +enum LOCK_EX = 0x02; +/// Unlock +enum LOCK_UN = 0x08; + +/// Don't block when locking. +/// Can be OR'd into one of the above. +enum LOCK_NB = 0x04; + +/// Apply or remove an advisory lock on an open file +/// Params: +/// fd = file to apply or remove lock from +/// operation = lock operation to perform +/// Returns: +/// 0 on success, -1 on failure, with .errno +/// set appropriately. +int flock(int fd, int operation) @trusted; diff --git a/win32.mak b/win32.mak index 109a44adc8..e19718c2d5 100644 --- a/win32.mak +++ b/win32.mak @@ -467,6 +467,9 @@ $(IMPDIR)\core\sys\linux\unistd.d : src\core\sys\linux\unistd.d $(IMPDIR)\core\sys\linux\sys\auxv.d : src\core\sys\linux\sys\auxv.d copy $** $@ +$(IMPDIR)\core\sys\linux\sys\file.d : src\core\sys\linux\sys\file.d + copy $** $@ + $(IMPDIR)\core\sys\linux\sys\inotify.d : src\core\sys\linux\sys\inotify.d copy $** $@ diff --git a/win64.mak b/win64.mak index ddded63a08..16b7ffe0c4 100644 --- a/win64.mak +++ b/win64.mak @@ -475,6 +475,9 @@ $(IMPDIR)\core\sys\linux\unistd.d : src\core\sys\linux\unistd.d $(IMPDIR)\core\sys\linux\sys\auxv.d : src\core\sys\linux\sys\auxv.d copy $** $@ +$(IMPDIR)\core\sys\linux\sys\file.d : src\core\sys\linux\sys\file.d + copy $** $@ + $(IMPDIR)\core\sys\linux\sys\inotify.d : src\core\sys\linux\sys\inotify.d copy $** $@ From 7149012fc641d8873d02a52f6c4823d53a340164 Mon Sep 17 00:00:00 2001 From: kinke Date: Fri, 9 Dec 2016 20:07:50 +0100 Subject: [PATCH 02/82] [MSVCRT] core.stdcpp.typeinfo: Don't implement exception ctors Implementing them (wrongly btw, ignoring the msg) leads to an implicit call to the `super` ctor of base class `core.stdcpp.exception.std.exception`, which is only declared in D. Even if the ctor signature was correct (see below), it's mangled differently (see https://github.com/dlang/dmd/pull/5884), so there'd be an unresolved external anyway. So don't implement it, just declare it (also done for Glibc) to defer the linking error. Quality-wise, the 2 `core.stdcpp` modules are at most at an alpha stage for MSVCRT. Other issues I've noted so far using **VS 2015**: * The signature of the `core.stdcpp.exception.std.exception.this()` ctor is wrong. There's no default, i.e., parameter-less one, only `std::exception::exception(const char *_Message = "unknown", int x=1)`. * `std::exception` only contains a pointer, no additional `bool` field. * The signature of `core.stdcpp.typeinfo.std.type_info.name()` is wrong. It doesn't take any arguments. The first 2 aren't crucial, as these C++ exceptions are most likely never constructed on the D side. But the last one will need to be fixed. @rainers: Which VS versions does DMD currently support? --- src/core/stdcpp/typeinfo.d | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/core/stdcpp/typeinfo.d b/src/core/stdcpp/typeinfo.d index a535dbf802..f6c0c20f8b 100644 --- a/src/core/stdcpp/typeinfo.d +++ b/src/core/stdcpp/typeinfo.d @@ -71,8 +71,6 @@ else version (CRuntime_Microsoft) { class type_info { - - public: //virtual ~this(); void dtor() { } // reserve slot in vtbl[] //bool operator==(const type_info rhs) const; @@ -83,21 +81,18 @@ else version (CRuntime_Microsoft) private: void* pdata; char[1] _name; - //this(const type_info rhs); //type_info operator=(const type_info rhs); } class bad_cast : core.stdcpp.exception.std.exception { - this(const(char)* msg = "bad cast") { } - this(const bad_cast) { } + this(const(char)* msg = "bad cast"); //virtual ~this(); } class bad_typeid : core.stdcpp.exception.std.exception { - this(const(char)* msg = "bad typeid") { } - this(const bad_typeid) { } + this(const(char)* msg = "bad typeid"); //virtual ~this(); } } From 958b9f77176fdbe23c68700dc0d8db03dc8c58a5 Mon Sep 17 00:00:00 2001 From: ZombineDev Date: Tue, 27 Dec 2016 23:16:23 +0200 Subject: [PATCH 03/82] Add attributes core.thread part 1 This commit adds attributes to those functions in `core.thread` that don't require changes outside of the module. Not much of this has profound effect to the users but makes adding a templated `Thread`/`Fiber` classes on the user's callback much easier later on, which should help address the need for `@nogc` and `nothrow` threading primitives. --- src/core/thread.d | 110 ++++++++++++++++++++++++---------------------- 1 file changed, 57 insertions(+), 53 deletions(-) diff --git a/src/core/thread.d b/src/core/thread.d index a8e071ff71..865980f0f5 100644 --- a/src/core/thread.d +++ b/src/core/thread.d @@ -1,4 +1,4 @@ -/** +/** * The thread module provides support for thread creation and management. * * Copyright: Copyright Sean Kelly 2005 - 2012. @@ -260,7 +260,7 @@ version( Windows ) } - HANDLE GetCurrentThreadHandle() + HANDLE GetCurrentThreadHandle() nothrow @nogc { const uint DUPLICATE_SAME_ACCESS = 0x00000002; @@ -560,7 +560,7 @@ class Thread * In: * fn must not be null. */ - this( void function() fn, size_t sz = 0 ) + this( void function() fn, size_t sz = 0 ) @safe pure nothrow @nogc in { assert( fn ); @@ -568,7 +568,7 @@ class Thread body { this(sz); - m_fn = fn; + () @trusted { m_fn = fn; }(); m_call = Call.FN; m_curr = &m_main; } @@ -585,7 +585,7 @@ class Thread * In: * dg must not be null. */ - this( void delegate() dg, size_t sz = 0 ) + this( void delegate() dg, size_t sz = 0 ) @safe pure nothrow @nogc in { assert( dg ); @@ -593,7 +593,7 @@ class Thread body { this(sz); - m_dg = dg; + () @trusted { m_dg = dg; }(); m_call = Call.DG; m_curr = &m_main; } @@ -802,7 +802,7 @@ class Thread * * The value is unique for the current process. */ - final @property ThreadID id() + final @property ThreadID id() @safe @nogc { synchronized( this ) { @@ -817,7 +817,7 @@ class Thread * Returns: * The name of this thread. */ - final @property string name() + final @property string name() @safe @nogc { synchronized( this ) { @@ -832,7 +832,7 @@ class Thread * Params: * val = The new name of this thread. */ - final @property void name( string val ) + final @property void name( string val ) @safe @nogc { synchronized( this ) { @@ -851,7 +851,7 @@ class Thread * Returns: * true if this is a daemon thread. */ - final @property bool isDaemon() + final @property bool isDaemon() @safe @nogc { synchronized( this ) { @@ -870,7 +870,7 @@ class Thread * Params: * val = The new daemon status for this thread. */ - final @property void isDaemon( bool val ) + final @property void isDaemon( bool val ) @safe @nogc { synchronized( this ) { @@ -885,7 +885,7 @@ class Thread * Returns: * true if the thread is running, false if not. */ - final @property bool isRunning() nothrow + final @property bool isRunning() nothrow @nogc { if( m_addr == m_addr.init ) { @@ -1176,7 +1176,7 @@ class Thread * deleting this object is undefined. If the current thread is not * attached to the runtime, a null reference is returned. */ - static Thread getThis() nothrow + static Thread getThis() @safe nothrow @nogc { // NOTE: This function may not be called until thread_init has // completed. See thread_suspendAll for more information @@ -1372,7 +1372,7 @@ private: // Initializes a thread object which has no associated executable function. // This is used for the main thread initialized in thread_init(). // - this(size_t sz = 0) + this(size_t sz = 0) @safe pure nothrow @nogc { if (sz) { @@ -1497,7 +1497,7 @@ private: // // Sets a thread-local reference to the current thread object. // - static void setThis( Thread t ) + static void setThis( Thread t ) nothrow @nogc { sm_this = t; } @@ -1536,7 +1536,7 @@ private: } - final Context* topContext() nothrow + final Context* topContext() nothrow @nogc in { assert( m_curr ); @@ -1644,12 +1644,12 @@ private: // Careful as the GC acquires this lock after the GC lock to suspend all // threads any GC usage with slock held can result in a deadlock through // lock order inversion. - @property static Mutex slock() nothrow + @property static Mutex slock() nothrow @nogc { return cast(Mutex)_locks[0].ptr; } - @property static Mutex criticalRegionLock() nothrow + @property static Mutex criticalRegionLock() nothrow @nogc { return cast(Mutex)_locks[1].ptr; } @@ -1695,7 +1695,7 @@ private: // // Add a context to the global context list. // - static void add( Context* c ) nothrow + static void add( Context* c ) nothrow @nogc in { assert( c ); @@ -1721,7 +1721,7 @@ private: // // This assumes slock being acquired. This isn't done here to // avoid double locking when called from remove(Thread) - static void remove( Context* c ) nothrow + static void remove( Context* c ) nothrow @nogc in { assert( c ); @@ -1752,7 +1752,7 @@ private: // // Add a thread to the global thread list. // - static void add( Thread t, bool rmAboutToStart = true ) nothrow + static void add( Thread t, bool rmAboutToStart = true ) nothrow @nogc in { assert( t ); @@ -1796,7 +1796,7 @@ private: // // Remove a thread from the global thread list. // - static void remove( Thread t ) nothrow + static void remove( Thread t ) nothrow @nogc in { assert( t ); @@ -1912,13 +1912,13 @@ version( CoreDdoc ) * This function should be called at most once, prior to thread_init(). * This function is Posix-only. */ - extern (C) void thread_setGCSignals(int suspendSignalNo, int resumeSignalNo) + extern (C) void thread_setGCSignals(int suspendSignalNo, int resumeSignalNo) nothrow @nogc { } } else version( Posix ) { - extern (C) void thread_setGCSignals(int suspendSignalNo, int resumeSignalNo) + extern (C) void thread_setGCSignals(int suspendSignalNo, int resumeSignalNo) nothrow @nogc in { assert(suspendSignalNumber == 0); @@ -2039,7 +2039,7 @@ extern (C) void thread_term() /** * */ -extern (C) bool thread_isMainThread() +extern (C) bool thread_isMainThread() nothrow @nogc { return Thread.getThis() is Thread.sm_main; } @@ -2172,7 +2172,7 @@ version( Windows ) * * $(D extern(C) void rt_moduleTlsDtor();) */ -extern (C) void thread_detachThis() nothrow +extern (C) void thread_detachThis() nothrow @nogc { if (auto t = Thread.getThis()) Thread.remove(t); @@ -2198,7 +2198,7 @@ extern (C) void thread_detachByAddr( ThreadID addr ) /// ditto -extern (C) void thread_detachInstance( Thread t ) +extern (C) void thread_detachInstance( Thread t ) nothrow @nogc { Thread.remove( t ); } @@ -2260,7 +2260,7 @@ static Thread thread_findByAddr( ThreadID addr ) * Params: * t = A reference to the current thread. May be null. */ -extern (C) void thread_setThis(Thread t) +extern (C) void thread_setThis(Thread t) nothrow @nogc { Thread.setThis(t); } @@ -2927,7 +2927,7 @@ extern (C) void thread_scanAll( scope ScanAllThreadsFn scan ) nothrow * In: * The calling thread must be attached to the runtime. */ -extern (C) void thread_enterCriticalRegion() +extern (C) void thread_enterCriticalRegion() @nogc in { assert(Thread.getThis()); @@ -2946,7 +2946,7 @@ body * In: * The calling thread must be attached to the runtime. */ -extern (C) void thread_exitCriticalRegion() +extern (C) void thread_exitCriticalRegion() @nogc in { assert(Thread.getThis()); @@ -2964,7 +2964,7 @@ body * In: * The calling thread must be attached to the runtime. */ -extern (C) bool thread_inCriticalRegion() +extern (C) bool thread_inCriticalRegion() @nogc in { assert(Thread.getThis()); @@ -3123,9 +3123,8 @@ extern(C) void thread_processGCMarks( scope IsMarkedDg isMarked ) nothrow } -extern (C) +extern (C) @nogc nothrow { -nothrow: version (CRuntime_Glibc) int pthread_getattr_np(pthread_t thread, pthread_attr_t* attr); version (FreeBSD) int pthread_attr_get_np(pthread_t thread, pthread_attr_t* attr); version (Solaris) int thr_stksegment(stack_t* stk); @@ -3133,7 +3132,7 @@ nothrow: } -private void* getStackTop() nothrow +private void* getStackTop() nothrow @nogc { version (D_InlineAsm_X86) asm pure nothrow @nogc { naked; mov EAX, ESP; ret; } @@ -3146,7 +3145,7 @@ private void* getStackTop() nothrow } -private void* getStackBottom() nothrow +private void* getStackBottom() nothrow @nogc { version (Windows) { @@ -3220,7 +3219,7 @@ private void* getStackBottom() nothrow * Returns: * The address of the stack top. */ -extern (C) void* thread_stackTop() nothrow +extern (C) void* thread_stackTop() nothrow @nogc in { // Not strictly required, but it gives us more flexibility. @@ -3242,7 +3241,7 @@ body * Returns: * The address of the stack bottom. */ -extern (C) void* thread_stackBottom() nothrow +extern (C) void* thread_stackBottom() nothrow @nogc in { assert(Thread.getThis()); @@ -3522,7 +3521,7 @@ shared static this() private { - extern (C) void fiber_entryPoint() + extern (C) void fiber_entryPoint() nothrow { Fiber obj = Fiber.getThis(); assert( obj ); @@ -3550,9 +3549,9 @@ private // Look above the definition of 'class Fiber' for some information about the implementation of this routine version( AsmExternal ) - extern (C) void fiber_switchContext( void** oldp, void* newp ) nothrow; + extern (C) void fiber_switchContext( void** oldp, void* newp ) nothrow @nogc; else - extern (C) void fiber_switchContext( void** oldp, void* newp ) nothrow + extern (C) void fiber_switchContext( void** oldp, void* newp ) nothrow @nogc { // NOTE: The data pushed and popped in this routine must match the // default stack created by Fiber.initStack or the initial @@ -3993,7 +3992,7 @@ class Fiber /** * Cleans up any remaining resources used by this object. */ - ~this() nothrow + ~this() nothrow @nogc { // NOTE: A live reference to this object will exist on its associated // stack from the first time its call() method has been called @@ -4035,6 +4034,11 @@ class Fiber * Any exception not handled by this fiber if rethrow = false, null * otherwise. */ + // Not marked with any attributes, even though `nothrow @nogc` works + // because it calls arbitrary user code. Most of the implementation + // is already `@nogc nothrow`, but in order for `Fiber.call` to + // propagate the attributes of the user's function, the Fiber + // class needs to be templated. final Throwable call( Rethrow rethrow = Rethrow.yes ) { return rethrow ? call!(Rethrow.yes)() : call!(Rethrow.no); @@ -4109,7 +4113,7 @@ class Fiber * In: * This fiber must be in state TERM or HOLD. */ - final void reset() nothrow + final void reset() nothrow @nogc in { assert( m_state == State.TERM || m_state == State.HOLD ); @@ -4123,7 +4127,7 @@ class Fiber } /// ditto - final void reset( void function() fn ) nothrow + final void reset( void function() fn ) nothrow @nogc { reset(); m_fn = fn; @@ -4131,7 +4135,7 @@ class Fiber } /// ditto - final void reset( void delegate() dg ) nothrow + final void reset( void delegate() dg ) nothrow @nogc { reset(); m_dg = dg; @@ -4164,7 +4168,7 @@ class Fiber * Returns: * The state of this fiber as an enumerated value. */ - final @property State state() const nothrow + final @property State state() const @safe pure nothrow @nogc { return m_state; } @@ -4178,7 +4182,7 @@ class Fiber /** * Forces a context switch to occur away from the calling fiber. */ - static void yield() nothrow + static void yield() nothrow @nogc { Fiber cur = getThis(); assert( cur, "Fiber.yield() called with no active fiber" ); @@ -4203,7 +4207,7 @@ class Fiber * In: * t must not be null. */ - static void yieldAndThrow( Throwable t ) nothrow + static void yieldAndThrow( Throwable t ) nothrow @nogc in { assert( t ); @@ -4237,7 +4241,7 @@ class Fiber * The fiber object representing the calling fiber or null if no fiber * is currently active within this thread. The result of deleting this object is undefined. */ - static Fiber getThis() nothrow + static Fiber getThis() @safe nothrow @nogc { return sm_this; } @@ -4264,7 +4268,7 @@ private: // // Initializes a fiber object which has no associated executable function. // - this() nothrow + this() @safe pure nothrow @nogc { m_call = Call.NO; } @@ -4443,7 +4447,7 @@ private: // // Free this fiber's stack. // - final void freeStack() nothrow + final void freeStack() nothrow @nogc in { assert( m_pmem && m_ctxt ); @@ -4486,7 +4490,7 @@ private: // Initialize the allocated stack. // Look above the definition of 'class Fiber' for some information about the implementation of this routine // - final void initStack() nothrow + final void initStack() nothrow @nogc in { assert( m_ctxt.tstack && m_ctxt.tstack == m_ctxt.bstack ); @@ -4821,7 +4825,7 @@ private: // // Sets a thread-local reference to the current fiber object. // - static void setThis( Fiber f ) nothrow + static void setThis( Fiber f ) nothrow @nogc { sm_this = f; } @@ -4872,7 +4876,7 @@ private: // // Switches out of the current stack and into the enclosing stack. // - final void switchOut() nothrow + final void switchOut() nothrow @nogc { Thread tobj = Thread.getThis(); void** oldp = &m_ctxt.tstack; From d7581e817b37ccc0f4a502704ddcdb375a3b095a Mon Sep 17 00:00:00 2001 From: ZombineDev Date: Tue, 27 Dec 2016 23:17:38 +0200 Subject: [PATCH 04/82] Add attributes core.thread part 2 This commit fixes `Thread.~this()`, `thread_attachThis` and partially `thread_entryPoint` and `thread_attachByAddrB`. `thread_entryPoint` can't be made `@nogc` because it calls `Thread.run`, `rt_moduleTlsCtor` and `rt_moduleTlsDtor`, which can execute arbitrary user code. `thread_attachByAddrB` can't be made `@nogc` because it calls `thread_findByAddr`, which calls `Thread.opApply`, which can't be `@nogc` because it calls a non-`@nogc` delegate. This change is a bit large because many call-sites needed to be fixed in one go: * On posix, `thread_entryPoint` calls `inheritLoadedLibraries` and `cleanupLoadedLibraries`, and `Thread.start` calls `rt.sections.pinLoadedLibraries` and `unpinLoadedLibraries`. * `Thread.~this()` calls `rt.tlsgc.destroy`, which in turn calls `rt.sections.finiTLSRanges`, which is implemented in `rt.secions_{platform}`. * Similarly, `thread_attachThis` calls `rt.tlsgc.init`, which in turn calls `rt.sections.initTLSRanges`, which is implemented in `rt.secions_{platform}`. On some platforms `rt.sections.initTLSRanges` calls `rt.minfo.ModuleGroup.this`, so I made it `nothrow` and `@nogc` too. * Additionally, `rt.sections.initSections` and `finiSections` were easy to fix, so I added appropriate attributes to them, even though they are called only from `rt.dmain2.rt_init`. Finally, some function from `rt.sections_elf_shared` was accessing `ModuleInfo.name` which wasn't marked as `@nogc`, so I went through `object.ModuleInfo` and made all of its members `@nogc` (they were already `nothrow`). --- src/core/sys/freebsd/dlfcn.d | 5 ++- src/core/sys/linux/dlfcn.d | 1 + src/core/thread.d | 10 ++--- src/object.d | 26 ++++++------- src/rt/minfo.d | 4 +- src/rt/sections.d | 16 ++++---- src/rt/sections_android.d | 24 ++++++------ src/rt/sections_elf_shared.d | 73 ++++++++++++++++++------------------ src/rt/sections_osx_x86.d | 10 ++--- src/rt/sections_osx_x86_64.d | 10 ++--- src/rt/sections_solaris.d | 8 ++-- src/rt/sections_win32.d | 12 +++--- src/rt/sections_win64.d | 20 +++++----- src/rt/tlsgc.d | 4 +- 14 files changed, 112 insertions(+), 111 deletions(-) diff --git a/src/core/sys/freebsd/dlfcn.d b/src/core/sys/freebsd/dlfcn.d index bcb41a44f7..812cb4c17b 100644 --- a/src/core/sys/freebsd/dlfcn.d +++ b/src/core/sys/freebsd/dlfcn.d @@ -12,6 +12,7 @@ public import core.sys.posix.dlfcn; version (FreeBSD): extern (C): nothrow: +@nogc: enum __BSD_VISIBLE = true; @@ -68,7 +69,7 @@ static if (__BSD_VISIBLE) int __dlfunc_dummy; }; - alias void function(__dlfunc_arg) dlfunc_t; + alias dlfunc_t = void function(__dlfunc_arg); /* * Structures, returned by the RTLD_DI_SERINFO dlinfo() request. @@ -87,7 +88,7 @@ static if (__BSD_VISIBLE) private template __externC(RT, P...) { - alias extern(C) RT function(P) nothrow @nogc __externC; + alias __externC = extern(C) RT function(P) nothrow @nogc; } /* XSI functions first. */ diff --git a/src/core/sys/linux/dlfcn.d b/src/core/sys/linux/dlfcn.d index 7abf6ddde5..3756a04a31 100644 --- a/src/core/sys/linux/dlfcn.d +++ b/src/core/sys/linux/dlfcn.d @@ -8,6 +8,7 @@ module core.sys.linux.dlfcn; version (linux): extern (C): nothrow: +@nogc: public import core.sys.posix.dlfcn; import core.sys.linux.config; diff --git a/src/core/thread.d b/src/core/thread.d index 865980f0f5..82e8feb03e 100644 --- a/src/core/thread.d +++ b/src/core/thread.d @@ -29,8 +29,8 @@ private // interface to rt.tlsgc import core.internal.traits : externDFunc; - alias rt_tlsgc_init = externDFunc!("rt.tlsgc.init", void* function()); - alias rt_tlsgc_destroy = externDFunc!("rt.tlsgc.destroy", void function(void*)); + alias rt_tlsgc_init = externDFunc!("rt.tlsgc.init", void* function() nothrow @nogc); + alias rt_tlsgc_destroy = externDFunc!("rt.tlsgc.destroy", void function(void*) nothrow @nogc); alias ScanDg = void delegate(void* pstart, void* pend) nothrow; alias rt_tlsgc_scan = @@ -193,7 +193,7 @@ version( Windows ) // // Entry point for Windows threads // - extern (Windows) uint thread_entryPoint( void* arg ) + extern (Windows) uint thread_entryPoint( void* arg ) nothrow { Thread obj = cast(Thread) arg; assert( obj ); @@ -298,7 +298,7 @@ else version( Posix ) // // Entry point for POSIX threads // - extern (C) void* thread_entryPoint( void* arg ) + extern (C) void* thread_entryPoint( void* arg ) nothrow { version (Shared) { @@ -602,7 +602,7 @@ class Thread /** * Cleans up any remaining resources used by this object. */ - ~this() + ~this() nothrow @nogc { if( m_addr == m_addr.init ) { diff --git a/src/object.d b/src/object.d index 9086698903..169ce3064f 100644 --- a/src/object.d +++ b/src/object.d @@ -1470,7 +1470,7 @@ struct ModuleInfo } const: - private void* addrOf(int flag) nothrow pure + private void* addrOf(int flag) nothrow pure @nogc in { assert(flag >= MItlsctor && flag <= MIname); @@ -1535,46 +1535,46 @@ const: assert(0); } - @property uint index() nothrow pure { return _index; } + @property uint index() nothrow pure @nogc { return _index; } - @property uint flags() nothrow pure { return _flags; } + @property uint flags() nothrow pure @nogc { return _flags; } - @property void function() tlsctor() nothrow pure + @property void function() tlsctor() nothrow pure @nogc { return flags & MItlsctor ? *cast(typeof(return)*)addrOf(MItlsctor) : null; } - @property void function() tlsdtor() nothrow pure + @property void function() tlsdtor() nothrow pure @nogc { return flags & MItlsdtor ? *cast(typeof(return)*)addrOf(MItlsdtor) : null; } - @property void* xgetMembers() nothrow pure + @property void* xgetMembers() nothrow pure @nogc { return flags & MIxgetMembers ? *cast(typeof(return)*)addrOf(MIxgetMembers) : null; } - @property void function() ctor() nothrow pure + @property void function() ctor() nothrow pure @nogc { return flags & MIctor ? *cast(typeof(return)*)addrOf(MIctor) : null; } - @property void function() dtor() nothrow pure + @property void function() dtor() nothrow pure @nogc { return flags & MIdtor ? *cast(typeof(return)*)addrOf(MIdtor) : null; } - @property void function() ictor() nothrow pure + @property void function() ictor() nothrow pure @nogc { return flags & MIictor ? *cast(typeof(return)*)addrOf(MIictor) : null; } - @property void function() unitTest() nothrow pure + @property void function() unitTest() nothrow pure @nogc { return flags & MIunitTest ? *cast(typeof(return)*)addrOf(MIunitTest) : null; } - @property immutable(ModuleInfo*)[] importedModules() nothrow pure + @property immutable(ModuleInfo*)[] importedModules() nothrow pure @nogc { if (flags & MIimportedModules) { @@ -1584,7 +1584,7 @@ const: return null; } - @property TypeInfo_Class[] localClasses() nothrow pure + @property TypeInfo_Class[] localClasses() nothrow pure @nogc { if (flags & MIlocalClasses) { @@ -1594,7 +1594,7 @@ const: return null; } - @property string name() nothrow pure + @property string name() nothrow pure @nogc { if (true || flags & MIname) // always available for now { diff --git a/src/rt/minfo.d b/src/rt/minfo.d index 602bbcfa46..190cce279c 100644 --- a/src/rt/minfo.d +++ b/src/rt/minfo.d @@ -43,12 +43,12 @@ enum struct ModuleGroup { - this(immutable(ModuleInfo*)[] modules) + this(immutable(ModuleInfo*)[] modules) nothrow @nogc { _modules = modules; } - @property immutable(ModuleInfo*)[] modules() const + @property immutable(ModuleInfo*)[] modules() const nothrow @nogc { return _modules; } diff --git a/src/rt/sections.d b/src/rt/sections.d index 4e32a77663..0cbd5e594f 100644 --- a/src/rt/sections.d +++ b/src/rt/sections.d @@ -56,17 +56,17 @@ template isSectionGroup(T) is(typeof({ foreach_reverse (ref T; T) {}})); } static assert(isSectionGroup!(SectionGroup)); -static assert(is(typeof(&initSections) == void function())); -static assert(is(typeof(&finiSections) == void function())); +static assert(is(typeof(&initSections) == void function() nothrow @nogc)); +static assert(is(typeof(&finiSections) == void function() nothrow @nogc)); static assert(is(typeof(&initTLSRanges) RT == return) && - is(typeof(&initTLSRanges) == RT function()) && - is(typeof(&finiTLSRanges) == void function(RT)) && + is(typeof(&initTLSRanges) == RT function() nothrow @nogc) && + is(typeof(&finiTLSRanges) == void function(RT) nothrow @nogc) && is(typeof(&scanTLSRanges) == void function(RT, scope void delegate(void*, void*) nothrow) nothrow)); version (Shared) { - static assert(is(typeof(&pinLoadedLibraries) == void* function() nothrow)); - static assert(is(typeof(&unpinLoadedLibraries) == void function(void*) nothrow)); - static assert(is(typeof(&inheritLoadedLibraries) == void function(void*))); - static assert(is(typeof(&cleanupLoadedLibraries) == void function())); + static assert(is(typeof(&pinLoadedLibraries) == void* function() nothrow @nogc)); + static assert(is(typeof(&unpinLoadedLibraries) == void function(void*) nothrow @nogc)); + static assert(is(typeof(&inheritLoadedLibraries) == void function(void*) nothrow @nogc)); + static assert(is(typeof(&cleanupLoadedLibraries) == void function() nothrow @nogc)); } diff --git a/src/rt/sections_android.d b/src/rt/sections_android.d index 79e2a642e1..de7a4130b6 100644 --- a/src/rt/sections_android.d +++ b/src/rt/sections_android.d @@ -32,24 +32,24 @@ struct SectionGroup return dg(_sections); } - @property immutable(ModuleInfo*)[] modules() const + @property immutable(ModuleInfo*)[] modules() const nothrow @nogc { return _moduleGroup.modules; } - @property ref inout(ModuleGroup) moduleGroup() inout + @property ref inout(ModuleGroup) moduleGroup() inout nothrow @nogc { return _moduleGroup; } - @property immutable(FuncTable)[] ehTables() const + @property immutable(FuncTable)[] ehTables() const nothrow @nogc { auto pbeg = cast(immutable(FuncTable)*)&__start_deh; auto pend = cast(immutable(FuncTable)*)&__stop_deh; return pbeg[0 .. pend - pbeg]; } - @property inout(void[])[] gcRanges() inout + @property inout(void[])[] gcRanges() inout nothrow @nogc { return _gcRanges[]; } @@ -59,7 +59,7 @@ private: void[][1] _gcRanges; } -void initSections() +void initSections() nothrow @nogc { pthread_key_create(&_tlsKey, null); @@ -72,17 +72,17 @@ void initSections() _sections._gcRanges[0] = pbeg[0 .. pend - pbeg]; } -void finiSections() +void finiSections() nothrow @nogc { pthread_key_delete(_tlsKey); } -void[]* initTLSRanges() +void[]* initTLSRanges() nothrow @nogc { return &getTLSBlock(); } -void finiTLSRanges(void[]* rng) +void finiTLSRanges(void[]* rng) nothrow @nogc { .free(rng.ptr); .free(rng); @@ -108,7 +108,7 @@ version(X86) { // NB: the compiler mangles this function as '___tls_get_addr' // even though it is extern(D) - extern(D) void* ___tls_get_addr( void* p ) + extern(D) void* ___tls_get_addr( void* p ) nothrow @nogc { debug(PRINTF) printf(" ___tls_get_addr input - %p\n", p); immutable offset = cast(size_t)(p - cast(void*)&_tlsstart); @@ -119,7 +119,7 @@ version(X86) } else version(ARM) { - extern(C) void* __tls_get_addr( void** p ) + extern(C) void* __tls_get_addr( void** p ) nothrow @nogc { debug(PRINTF) printf(" __tls_get_addr input - %p\n", *p); immutable offset = cast(size_t)(*p - cast(void*)&_tlsstart); @@ -135,7 +135,7 @@ private: __gshared pthread_key_t _tlsKey; -ref void[] getTLSBlock() +ref void[] getTLSBlock() nothrow @nogc { auto pary = cast(void[]*)pthread_getspecific(_tlsKey); if (pary is null) @@ -151,7 +151,7 @@ ref void[] getTLSBlock() return *pary; } -ref void[] getTLSBlockAlloc() +ref void[] getTLSBlockAlloc() nothrow @nogc { auto pary = &getTLSBlock(); if (!pary.length) diff --git a/src/rt/sections_elf_shared.d b/src/rt/sections_elf_shared.d index 4741e1a7e5..ba9ef98a89 100644 --- a/src/rt/sections_elf_shared.d +++ b/src/rt/sections_elf_shared.d @@ -66,22 +66,22 @@ struct DSO return 0; } - @property immutable(ModuleInfo*)[] modules() const + @property immutable(ModuleInfo*)[] modules() const nothrow @nogc { return _moduleGroup.modules; } - @property ref inout(ModuleGroup) moduleGroup() inout + @property ref inout(ModuleGroup) moduleGroup() inout nothrow @nogc { return _moduleGroup; } - @property immutable(FuncTable)[] ehTables() const + @property immutable(FuncTable)[] ehTables() const nothrow @nogc { return null; } - @property inout(void[])[] gcRanges() inout + @property inout(void[])[] gcRanges() inout nothrow @nogc { return _gcRanges[]; } @@ -118,7 +118,7 @@ version (FreeBSD) private __gshared void* dummy_ref; /**** * Gets called on program startup just before GC is initialized. */ -void initSections() +void initSections() nothrow @nogc { _isRuntimeInitialized = true; // reference symbol to support weak linkage @@ -129,7 +129,7 @@ void initSections() /*** * Gets called on program shutdown just after GC is terminated. */ -void finiSections() +void finiSections() nothrow @nogc { _isRuntimeInitialized = false; } @@ -141,12 +141,12 @@ version (Shared) /*** * Called once per thread; returns array of thread local storage ranges */ - Array!(ThreadDSO)* initTLSRanges() + Array!(ThreadDSO)* initTLSRanges() @nogc nothrow { return &_loadedDSOs; } - void finiTLSRanges(Array!(ThreadDSO)* tdsos) + void finiTLSRanges(Array!(ThreadDSO)* tdsos) @nogc nothrow { // Nothing to do here. tdsos used to point to the _loadedDSOs instance // in the dying thread's TLS segment and as such is not valid anymore. @@ -161,7 +161,7 @@ version (Shared) } // interface for core.thread to inherit loaded libraries - void* pinLoadedLibraries() nothrow + void* pinLoadedLibraries() nothrow @nogc { auto res = cast(Array!(ThreadDSO)*)calloc(1, Array!(ThreadDSO).sizeof); res.length = _loadedDSOs.length; @@ -178,7 +178,7 @@ version (Shared) return res; } - void unpinLoadedLibraries(void* p) nothrow + void unpinLoadedLibraries(void* p) nothrow @nogc { auto pary = cast(Array!(ThreadDSO)*)p; // In case something failed we need to undo the pinning. @@ -197,7 +197,7 @@ version (Shared) // Called before TLS ctors are ran, copy over the loaded libraries // of the parent thread. - void inheritLoadedLibraries(void* p) + void inheritLoadedLibraries(void* p) nothrow @nogc { assert(_loadedDSOs.empty); _loadedDSOs.swap(*cast(Array!(ThreadDSO)*)p); @@ -210,7 +210,7 @@ version (Shared) } // Called after all TLS dtors ran, decrements all remaining dlopen refs. - void cleanupLoadedLibraries() + void cleanupLoadedLibraries() nothrow @nogc { foreach (ref tdso; _loadedDSOs) { @@ -231,12 +231,12 @@ else /*** * Called once per thread; returns array of thread local storage ranges */ - Array!(void[])* initTLSRanges() + Array!(void[])* initTLSRanges() nothrow @nogc { return &_tlsRanges; } - void finiTLSRanges(Array!(void[])* rngs) + void finiTLSRanges(Array!(void[])* rngs) nothrow @nogc { rngs.reset(); } @@ -277,7 +277,7 @@ version (Shared) void[] _tlsRange; alias _pdso this; // update the _tlsRange for the executing thread - void updateTLSRange() + void updateTLSRange() nothrow @nogc { _tlsRange = getTLSRange(_pdso._tlsMod, _pdso._tlsSize); } @@ -471,7 +471,7 @@ extern(C) void _d_dso_registry(CompilerDSOData* data) version (Shared) { - ThreadDSO* findThreadDSO(DSO* pdso) + ThreadDSO* findThreadDSO(DSO* pdso) nothrow @nogc { foreach (ref tdata; _loadedDSOs) if (tdata._pdso == pdso) return &tdata; @@ -546,13 +546,13 @@ version (Shared) // helper functions /////////////////////////////////////////////////////////////////////////////// -void initLocks() +void initLocks() nothrow @nogc { version (Shared) !pthread_mutex_init(&_handleToDSOMutex, null) || assert(0); } -void finiLocks() +void finiLocks() nothrow @nogc { version (Shared) !pthread_mutex_destroy(&_handleToDSOMutex) || assert(0); @@ -571,13 +571,13 @@ void runModuleDestructors(DSO* pdso, bool runTlsDtors) pdso._moduleGroup.runDtors(); } -void registerGCRanges(DSO* pdso) +void registerGCRanges(DSO* pdso) nothrow @nogc { foreach (rng; pdso._gcRanges) GC.addRange(rng.ptr, rng.length); } -void unregisterGCRanges(DSO* pdso) +void unregisterGCRanges(DSO* pdso) nothrow @nogc { foreach (rng; pdso._gcRanges) GC.removeRange(rng.ptr); @@ -589,7 +589,7 @@ version (Shared) void runFinalizers(DSO* pdso) GC.runFinalizers(seg); } -void freeDSO(DSO* pdso) +void freeDSO(DSO* pdso) nothrow @nogc { pdso._gcRanges.reset(); version (Shared) pdso._codeSegments.reset(); @@ -598,15 +598,15 @@ void freeDSO(DSO* pdso) version (Shared) { -nothrow: - link_map* linkMapForHandle(void* handle) +@nogc nothrow: + link_map* linkMapForHandle(void* handle) nothrow @nogc { link_map* map; dlinfo(handle, RTLD_DI_LINKMAP, &map) == 0 || assert(0); return map; } - link_map* exeLinkMap(link_map* map) + link_map* exeLinkMap(link_map* map) nothrow @nogc { assert(map); while (map.l_prev !is null) @@ -614,7 +614,7 @@ nothrow: return map; } - DSO* dsoForHandle(void* handle) + DSO* dsoForHandle(void* handle) nothrow @nogc { DSO* pdso; !pthread_mutex_lock(&_handleToDSOMutex) || assert(0); @@ -624,7 +624,7 @@ nothrow: return pdso; } - void setDSOForHandle(DSO* pdso, void* handle) + void setDSOForHandle(DSO* pdso, void* handle) nothrow @nogc { !pthread_mutex_lock(&_handleToDSOMutex) || assert(0); assert(handle !in _handleToDSO); @@ -632,7 +632,7 @@ nothrow: !pthread_mutex_unlock(&_handleToDSOMutex) || assert(0); } - void unsetDSOForHandle(DSO* pdso, void* handle) + void unsetDSOForHandle(DSO* pdso, void* handle) nothrow @nogc { !pthread_mutex_lock(&_handleToDSOMutex) || assert(0); assert(_handleToDSO[handle] == pdso); @@ -640,7 +640,7 @@ nothrow: !pthread_mutex_unlock(&_handleToDSOMutex) || assert(0); } - void getDependencies(in ref dl_phdr_info info, ref Array!(DSO*) deps) + void getDependencies(in ref dl_phdr_info info, ref Array!(DSO*) deps) nothrow @nogc { // get the entries of the .dynamic section ElfW!"Dyn"[] dyns; @@ -686,7 +686,7 @@ nothrow: } } - void* handleForName(const char* name) + void* handleForName(const char* name) nothrow @nogc { auto handle = .dlopen(name, RTLD_NOLOAD | RTLD_LAZY); if (handle !is null) .dlclose(handle); // drop reference count @@ -702,7 +702,7 @@ nothrow: * Scan segments in Linux dl_phdr_info struct and store * the TLS and writeable data segments in *pdso. */ -void scanSegments(in ref dl_phdr_info info, DSO* pdso) +void scanSegments(in ref dl_phdr_info info, DSO* pdso) nothrow @nogc { foreach (ref phdr; info.dlpi_phdr[0 .. info.dlpi_phnum]) { @@ -800,8 +800,7 @@ version (FreeBSD) extern(C) const(char)* getprogname() nothrow @nogc; version (FreeBSD) return getprogname(); } -nothrow -const(char)[] dsoName(const char* dlpi_name) +const(char)[] dsoName(const char* dlpi_name) nothrow @nogc { // the main executable doesn't have a name in its dlpi_name field const char* p = dlpi_name[0] != 0 ? dlpi_name : progname; @@ -815,7 +814,7 @@ extern(C) } /// get the BSS section of the executable to check for copy relocations -const(void)[] getCopyRelocSection() nothrow +const(void)[] getCopyRelocSection() nothrow @nogc { auto bss_start = rt_get_bss_start(); auto bss_end = rt_get_end(); @@ -857,7 +856,7 @@ const(void)[] getCopyRelocSection() nothrow * chains. */ void checkModuleCollisions(in ref dl_phdr_info info, in immutable(ModuleInfo)*[] modules, - in void[] copyRelocSection) nothrow + in void[] copyRelocSection) nothrow @nogc in { assert(modules.length); } body { @@ -901,7 +900,7 @@ body * Returns: * the dlopen handle for that DSO or null if addr is not within a loaded DSO */ -version (Shared) void* handleForAddr(void* addr) +version (Shared) void* handleForAddr(void* addr) nothrow @nogc { Dl_info info = void; if (dladdr(addr, &info) != 0) @@ -926,7 +925,7 @@ struct tls_index size_t ti_offset; } -extern(C) void* __tls_get_addr(tls_index* ti); +extern(C) void* __tls_get_addr(tls_index* ti) nothrow @nogc; /* The dynamic thread vector (DTV) pointers may point 0x8000 past the start of * each TLS block. This is at least true for PowerPC and Mips platforms. @@ -956,7 +955,7 @@ else version(MIPS64) else static assert( false, "Platform not supported." ); -void[] getTLSRange(size_t mod, size_t sz) +void[] getTLSRange(size_t mod, size_t sz) nothrow @nogc { if (mod == 0) return null; diff --git a/src/rt/sections_osx_x86.d b/src/rt/sections_osx_x86.d index dc8a4b7721..94605bc3b7 100644 --- a/src/rt/sections_osx_x86.d +++ b/src/rt/sections_osx_x86.d @@ -79,7 +79,7 @@ __gshared bool _isRuntimeInitialized; /**** * Gets called on program startup just before GC is initialized. */ -void initSections() +void initSections() nothrow @nogc { pthread_key_create(&_tlsKey, null); _dyld_register_func_for_add_image(§ions_osx_onAddImage); @@ -89,19 +89,19 @@ void initSections() /*** * Gets called on program shutdown just after GC is terminated. */ -void finiSections() +void finiSections() nothrow @nogc { _sections._gcRanges.reset(); pthread_key_delete(_tlsKey); _isRuntimeInitialized = false; } -void[]* initTLSRanges() +void[]* initTLSRanges() nothrow @nogc { return &getTLSBlock(); } -void finiTLSRanges(void[]* rng) +void finiTLSRanges(void[]* rng) nothrow @nogc { .free(rng.ptr); .free(rng); @@ -157,7 +157,7 @@ body assert(0); } -ref void[] getTLSBlock() +ref void[] getTLSBlock() nothrow @nogc { auto pary = cast(void[]*)pthread_getspecific(_tlsKey); if (pary is null) diff --git a/src/rt/sections_osx_x86_64.d b/src/rt/sections_osx_x86_64.d index 1bfcef3680..662e537fad 100644 --- a/src/rt/sections_osx_x86_64.d +++ b/src/rt/sections_osx_x86_64.d @@ -78,7 +78,7 @@ __gshared bool _isRuntimeInitialized; /**** * Gets called on program startup just before GC is initialized. */ -void initSections() +void initSections() nothrow @nogc { _dyld_register_func_for_add_image(§ions_osx_onAddImage); _isRuntimeInitialized = true; @@ -87,13 +87,13 @@ void initSections() /*** * Gets called on program shutdown just after GC is terminated. */ -void finiSections() +void finiSections() nothrow @nogc { _sections._gcRanges.reset(); _isRuntimeInitialized = false; } -void[] initTLSRanges() +void[] initTLSRanges() nothrow @nogc { void* start = null; size_t size = 0; @@ -102,7 +102,7 @@ void[] initTLSRanges() return start[0 .. size]; } -void finiTLSRanges(void[] rng) +void finiTLSRanges(void[] rng) nothrow @nogc { } @@ -114,7 +114,7 @@ void scanTLSRanges(void[] rng, scope void delegate(void* pbeg, void* pend) nothr private: -extern(C) void _d_dyld_getTLSRange(void*, void**, size_t*); +extern(C) void _d_dyld_getTLSRange(void*, void**, size_t*) nothrow @nogc; __gshared SectionGroup _sections; ubyte dummyTlsSymbol; diff --git a/src/rt/sections_solaris.d b/src/rt/sections_solaris.d index bf7773de91..ec608db132 100644 --- a/src/rt/sections_solaris.d +++ b/src/rt/sections_solaris.d @@ -56,7 +56,7 @@ private: void[][1] _gcRanges; } -void initSections() +void initSections() nothrow @nogc { auto mbeg = cast(immutable ModuleInfo**)&__start_minfo; auto mend = cast(immutable ModuleInfo**)&__stop_minfo; @@ -67,18 +67,18 @@ void initSections() _sections._gcRanges[0] = pbeg[0 .. pend - pbeg]; } -void finiSections() +void finiSections() nothrow @nogc { } -void[] initTLSRanges() +void[] initTLSRanges() nothrow @nogc { auto pbeg = cast(void*)&_tlsstart; auto pend = cast(void*)&_tlsend; return pbeg[0 .. pend - pbeg]; } -void finiTLSRanges(void[] rng) +void finiTLSRanges(void[] rng) nothrow @nogc { } diff --git a/src/rt/sections_win32.d b/src/rt/sections_win32.d index 526dc4d650..ca6d3d04e3 100644 --- a/src/rt/sections_win32.d +++ b/src/rt/sections_win32.d @@ -50,7 +50,7 @@ private: void[][2] _gcRanges; } -void initSections() +void initSections() nothrow @nogc { _sections._moduleGroup = ModuleGroup(getModuleInfos()); @@ -64,18 +64,18 @@ void initSections() _sections._gcRanges[1] = bssbeg[0 .. bssend - bssbeg]; } -void finiSections() +void finiSections() nothrow @nogc { } -void[] initTLSRanges() +void[] initTLSRanges() nothrow @nogc { auto pbeg = cast(void*)&_tlsstart; auto pend = cast(void*)&_tlsend; return pbeg[0 .. pend - pbeg]; } -void finiTLSRanges(void[] rng) +void finiTLSRanges(void[] rng) nothrow @nogc { } @@ -90,9 +90,9 @@ __gshared SectionGroup _sections; // Windows: this gets initialized by minit.asm extern(C) __gshared immutable(ModuleInfo*)[] _moduleinfo_array; -extern(C) void _minit(); +extern(C) void _minit() nothrow @nogc; -immutable(ModuleInfo*)[] getModuleInfos() +immutable(ModuleInfo*)[] getModuleInfos() nothrow @nogc out (result) { foreach(m; result) diff --git a/src/rt/sections_win64.d b/src/rt/sections_win64.d index 8606581373..834e9048d7 100644 --- a/src/rt/sections_win64.d +++ b/src/rt/sections_win64.d @@ -31,12 +31,12 @@ struct SectionGroup return dg(_sections); } - @property immutable(ModuleInfo*)[] modules() const + @property immutable(ModuleInfo*)[] modules() const nothrow @nogc { return _moduleGroup.modules; } - @property ref inout(ModuleGroup) moduleGroup() inout + @property ref inout(ModuleGroup) moduleGroup() inout nothrow @nogc { return _moduleGroup; } @@ -49,7 +49,7 @@ struct SectionGroup return pbeg[0 .. pend - pbeg]; } - @property inout(void[])[] gcRanges() inout + @property inout(void[])[] gcRanges() inout nothrow @nogc { return _gcRanges[]; } @@ -59,7 +59,7 @@ private: void[][1] _gcRanges; } -void initSections() +void initSections() nothrow @nogc { _sections._moduleGroup = ModuleGroup(getModuleInfos()); @@ -69,19 +69,19 @@ void initSections() cast(ulong)_sections._gcRanges[0].length); } -void finiSections() +void finiSections() nothrow @nogc { .free(cast(void*)_sections.modules.ptr); } -void[] initTLSRanges() +void[] initTLSRanges() nothrow @nogc { auto pbeg = cast(void*)&_tls_start; auto pend = cast(void*)&_tls_end; return pbeg[0 .. pend - pbeg]; } -void finiTLSRanges(void[] rng) +void finiTLSRanges(void[] rng) nothrow @nogc { } @@ -99,7 +99,7 @@ extern(C) extern __gshared void* _minfo_end; } -immutable(ModuleInfo*)[] getModuleInfos() +immutable(ModuleInfo*)[] getModuleInfos() nothrow @nogc out (result) { foreach(m; result) @@ -197,14 +197,14 @@ struct IMAGE_SECTION_HEADER uint Characteristics; } -bool compareSectionName(ref IMAGE_SECTION_HEADER section, string name) nothrow +bool compareSectionName(ref IMAGE_SECTION_HEADER section, string name) nothrow @nogc { if (name[] != section.Name[0 .. name.length]) return false; return name.length == 8 || section.Name[name.length] == 0; } -void[] findImageSection(string name) nothrow +void[] findImageSection(string name) nothrow @nogc { if (name.length > 8) // section name from string table not supported return null; diff --git a/src/rt/tlsgc.d b/src/rt/tlsgc.d index f5eef1e51c..e7e823d6b8 100644 --- a/src/rt/tlsgc.d +++ b/src/rt/tlsgc.d @@ -29,7 +29,7 @@ struct Data * Initialization hook, called FROM each thread. No assumptions about * module initialization state should be made. */ -void* init() +void* init() nothrow @nogc { auto data = cast(Data*).malloc(Data.sizeof); import core.exception; @@ -47,7 +47,7 @@ void* init() * Finalization hook, called FOR each thread. No assumptions about * module initialization state should be made. */ -void destroy(void* data) +void destroy(void* data) nothrow @nogc { // do module specific finalization rt.sections.finiTLSRanges((cast(Data*)data).tlsRanges); From f533e9311bca084119e7b35ca5aa331aecc28228 Mon Sep 17 00:00:00 2001 From: ZombineDev Date: Tue, 27 Dec 2016 23:18:02 +0200 Subject: [PATCH 05/82] Add attributes core.thread part 3 This commit adds attributes to Fiber.callImpl. The call chain looks like this: -> core.thread.Fiber.callImpl -> core.Fiber.switchIn -> core.Thread.pushContext/core.Thread.popContext -> core.thread.swapContext -> depending on the platform: -> rt.deh_win32/deh_win64_posix._d_eh_swapContext (On Windows and sometimes on Posix) -> rt.dwarfeh._d_eh_swapContextDwarf (on Posix) --- src/core/thread.d | 14 +++++++------- src/rt/deh_win32.d | 2 +- src/rt/deh_win64_posix.d | 2 +- src/rt/dwarfeh.d | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/core/thread.d b/src/core/thread.d index 82e8feb03e..6beb3b034d 100644 --- a/src/core/thread.d +++ b/src/core/thread.d @@ -125,7 +125,7 @@ private * where the stack was last swapped out, or null when a fiber stack * is switched in for the first time. */ - extern(C) void* _d_eh_swapContext(void* newContext) nothrow; + extern(C) void* _d_eh_swapContext(void* newContext) nothrow @nogc; version (DigitalMars) { @@ -133,9 +133,9 @@ private alias _d_eh_swapContext swapContext; else { - extern(C) void* _d_eh_swapContextDwarf(void* newContext) nothrow; + extern(C) void* _d_eh_swapContextDwarf(void* newContext) nothrow @nogc; - void* swapContext(void* newContext) nothrow + void* swapContext(void* newContext) nothrow @nogc { /* Detect at runtime which scheme is being used. * Eventually, determine it statically. @@ -1509,7 +1509,7 @@ private: /////////////////////////////////////////////////////////////////////////// - final void pushContext( Context* c ) nothrow + final void pushContext( Context* c ) nothrow @nogc in { assert( !c.within ); @@ -1522,7 +1522,7 @@ private: } - final void popContext() nothrow + final void popContext() nothrow @nogc in { assert( m_curr && m_curr.within ); @@ -4067,7 +4067,7 @@ class Fiber return rethrow ? call!(Rethrow.yes)() : call!(Rethrow.no); } - private void callImpl() nothrow + private void callImpl() nothrow @nogc in { assert( m_state == State.HOLD ); @@ -4842,7 +4842,7 @@ private: // // Switches into the stack held by this fiber. // - final void switchIn() nothrow + final void switchIn() nothrow @nogc { Thread tobj = Thread.getThis(); void** oldp = &tobj.m_curr.tstack; diff --git a/src/rt/deh_win32.d b/src/rt/deh_win32.d index 31821205d7..6d44847550 100644 --- a/src/rt/deh_win32.d +++ b/src/rt/deh_win32.d @@ -381,7 +381,7 @@ EXCEPTION_RECORD * inflightExceptionList = null; /*********************************** * Switch out inflightExceptionList on fiber context switches. */ -extern(C) void* _d_eh_swapContext(void* newContext) nothrow +extern(C) void* _d_eh_swapContext(void* newContext) nothrow @nogc { auto old = inflightExceptionList; inflightExceptionList = cast(EXCEPTION_RECORD*)newContext; diff --git a/src/rt/deh_win64_posix.d b/src/rt/deh_win64_posix.d index 3109f8d31f..5b17b23137 100644 --- a/src/rt/deh_win64_posix.d +++ b/src/rt/deh_win64_posix.d @@ -98,7 +98,7 @@ private /// __inflight is per-stack, not per-thread, and as such needs to be /// swapped out on fiber context switches. - extern(C) void* _d_eh_swapContext(void* newContext) nothrow + extern(C) void* _d_eh_swapContext(void* newContext) nothrow @nogc { auto old = __inflight; __inflight = cast(InFlight*)newContext; diff --git a/src/rt/dwarfeh.d b/src/rt/dwarfeh.d index 18d60b2e00..e650fb35ae 100644 --- a/src/rt/dwarfeh.d +++ b/src/rt/dwarfeh.d @@ -157,7 +157,7 @@ extern(C) Throwable __dmd_begin_catch(_Unwind_Exception* exceptionObject) * Returns: * previous value of stack */ -extern(C) void* _d_eh_swapContextDwarf(void* newContext) nothrow +extern(C) void* _d_eh_swapContextDwarf(void* newContext) nothrow @nogc { auto old = ExceptionHeader.stack; ExceptionHeader.stack = cast(ExceptionHeader*)newContext; From 9c80299fd88d2549440140aa0dddd90529384fc5 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Sun, 8 Jan 2017 19:58:19 -0800 Subject: [PATCH 06/82] compile with -dip1000 --- posix.mak | 2 +- win32.mak | 4 ++-- win64.mak | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/posix.mak b/posix.mak index befd52c9b4..ec31bb0d5e 100644 --- a/posix.mak +++ b/posix.mak @@ -53,7 +53,7 @@ ifeq (solaris,$(OS)) endif # Set DFLAGS -UDFLAGS:=-conf= -Isrc -Iimport -w -dip25 $(MODEL_FLAG) $(OPTIONAL_PIC) $(OPTIONAL_COVERAGE) +UDFLAGS:=-conf= -Isrc -Iimport -w -dip1000 $(MODEL_FLAG) $(OPTIONAL_PIC) $(OPTIONAL_COVERAGE) ifeq ($(BUILD),debug) UDFLAGS += -g -debug DFLAGS:=$(UDFLAGS) diff --git a/win32.mak b/win32.mak index f4ee566ed2..0be6b86a86 100644 --- a/win32.mak +++ b/win32.mak @@ -9,8 +9,8 @@ CC=dmc DOCDIR=doc IMPDIR=import -DFLAGS=-m$(MODEL) -conf= -O -release -dip25 -inline -w -Isrc -Iimport -UDFLAGS=-m$(MODEL) -conf= -O -release -dip25 -w -Isrc -Iimport +DFLAGS=-m$(MODEL) -conf= -O -release -dip1000 -inline -w -Isrc -Iimport +UDFLAGS=-m$(MODEL) -conf= -O -release -dip1000 -w -Isrc -Iimport DDOCFLAGS=-conf= -c -w -o- -Isrc -Iimport -version=CoreDdoc CFLAGS= diff --git a/win64.mak b/win64.mak index fea4d5d475..5252deb178 100644 --- a/win64.mak +++ b/win64.mak @@ -17,8 +17,8 @@ IMPDIR=import MAKE=make -DFLAGS=-m$(MODEL) -conf= -O -release -dip25 -inline -w -Isrc -Iimport -UDFLAGS=-m$(MODEL) -conf= -O -release -dip25 -w -Isrc -Iimport +DFLAGS=-m$(MODEL) -conf= -O -release -dip1000 -inline -w -Isrc -Iimport +UDFLAGS=-m$(MODEL) -conf= -O -release -dip1000 -w -Isrc -Iimport DDOCFLAGS=-conf= -c -w -o- -Isrc -Iimport -version=CoreDdoc #CFLAGS=/O2 /I"$(VCDIR)"\INCLUDE /I"$(SDKDIR)"\Include From d4f4560902d57aed1fa29644728a675a50ecbba6 Mon Sep 17 00:00:00 2001 From: Alexandru Razvan Caciulescu Date: Fri, 13 Jan 2017 14:38:11 +0200 Subject: [PATCH 07/82] Fix 17081 - Bodies in extern cpp functions in D files are not linked --- src/core/stdcpp/typeinfo.d | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/core/stdcpp/typeinfo.d b/src/core/stdcpp/typeinfo.d index a535dbf802..9d0341b5e6 100644 --- a/src/core/stdcpp/typeinfo.d +++ b/src/core/stdcpp/typeinfo.d @@ -117,8 +117,15 @@ else version (CRuntime_Glibc) { void dtor1(); // consume destructor slot in vtbl[] void dtor2(); // consume destructor slot in vtbl[] - final const(char)* name(); - final bool before(const type_info) const; + final const(char)* name()() const nothrow { + return _name[0] == '*' ? _name + 1 : _name; + } + final bool before()(const type_info _arg) const { + import core.stdc.string : strcmp; + return (_name[0] == '*' && _arg._name[0] == '*') + ? _name < _arg._name + : strcmp(_name, _arg._name) < 0; + } //bool operator==(const type_info) const; bool __is_pointer_p() const; bool __is_function_p() const; From 8dc386e1027f5620e6525bbd920f95ec25514387 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Sat, 14 Jan 2017 00:23:44 +0100 Subject: [PATCH 08/82] Always use same-type pointers when subtracting them --- src/gc/impl/conservative/gc.d | 16 ++++++++-------- src/gc/pooltable.d | 6 +++--- src/rt/lifetime.d | 2 +- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/gc/impl/conservative/gc.d b/src/gc/impl/conservative/gc.d index a1f894dbc1..d0b969106f 100644 --- a/src/gc/impl/conservative/gc.d +++ b/src/gc/impl/conservative/gc.d @@ -1974,7 +1974,7 @@ struct Gcx //printf("marking range: [%p..%p] (%#zx)\n", p1, p2, cast(size_t)p2 - cast(size_t)p1); Lnext: for (; p1 < p2; p1++) { - auto p = cast(byte *)(*p1); + auto p = *p1; //if (log) debug(PRINTF) printf("\tmark %p\n", p); if (p >= minAddr && p < maxAddr) @@ -2124,7 +2124,7 @@ struct Gcx { pool = list.pool; assert(pool); - pool.freebits.set(cast(size_t)(cast(byte*)list - pool.baseAddr) / 16); + pool.freebits.set(cast(size_t)(cast(void*)list - pool.baseAddr) / 16); } } @@ -2190,7 +2190,7 @@ struct Gcx if (!pool.mark.test(biti)) { - byte *p = pool.baseAddr + pn * PAGESIZE; + void *p = pool.baseAddr + pn * PAGESIZE; void* q = sentinel_add(p); sentinel_Invariant(q); @@ -2242,8 +2242,8 @@ struct Gcx if (bin < B_PAGE) { immutable size = binsize[bin]; - byte *p = pool.baseAddr + pn * PAGESIZE; - byte *ptop = p + PAGESIZE; + void *p = pool.baseAddr + pn * PAGESIZE; + void *ptop = p + PAGESIZE; immutable base = pn * (PAGESIZE/16); immutable bitstride = size / 16; @@ -2318,7 +2318,7 @@ struct Gcx size_t bitstride = size / 16; size_t bitbase = pn * (PAGESIZE / 16); size_t bittop = bitbase + (PAGESIZE / 16); - byte* p; + void* p; biti = bitbase; for (biti = bitbase; biti < bittop; biti += bitstride) @@ -2599,8 +2599,8 @@ struct Gcx struct Pool { - byte* baseAddr; - byte* topAddr; + void* baseAddr; + void* topAddr; GCBits mark; // entries already scanned, or should not be scanned GCBits freebits; // entries that are on the free list GCBits finals; // entries that need finalizer run on them diff --git a/src/gc/pooltable.d b/src/gc/pooltable.d index da2796dc98..75cf7a8fcd 100644 --- a/src/gc/pooltable.d +++ b/src/gc/pooltable.d @@ -155,13 +155,13 @@ nothrow: assert(_maxAddr == pools[npools - 1].topAddr); } - @property const(byte)* minAddr() pure const { return _minAddr; } - @property const(byte)* maxAddr() pure const { return _maxAddr; } + @property const(void)* minAddr() pure const { return _minAddr; } + @property const(void)* maxAddr() pure const { return _maxAddr; } package: Pool** pools; size_t npools; - byte* _minAddr, _maxAddr; + void* _minAddr, _maxAddr; } unittest diff --git a/src/rt/lifetime.d b/src/rt/lifetime.d index 87f0e8dab8..03df8d31a4 100644 --- a/src/rt/lifetime.d +++ b/src/rt/lifetime.d @@ -1908,7 +1908,7 @@ byte[] _d_arrayappendcTX(const TypeInfo ti, ref byte[] px, size_t n) size_t newcap = void; // for scratch space // calculate the extent of the array given the base. - size_t offset = px.ptr - __arrayStart(info); + size_t offset = cast(void*)px.ptr - __arrayStart(info); if(info.base && (info.attr & BlkAttr.APPENDABLE)) { if(info.size >= PAGESIZE) From 3e63b54a495a0e8034ec4d57f88047d399a66604 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Mon, 16 Jan 2017 02:39:46 -0800 Subject: [PATCH 09/82] string.d: add return and scope --- src/core/stdc/string.d | 58 +++++++++++++++++++++--------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/src/core/stdc/string.d b/src/core/stdc/string.d index abec39b449..103076de54 100644 --- a/src/core/stdc/string.d +++ b/src/core/stdc/string.d @@ -29,80 +29,80 @@ nothrow: @nogc: /// -pure void* memchr(in void* s, int c, size_t n); +pure void* memchr(return const void* s, int c, size_t n); /// -pure int memcmp(in void* s1, in void* s2, size_t n); +pure int memcmp(scope const void* s1, scope const void* s2, size_t n); /// -pure void* memcpy(void* s1, in void* s2, size_t n); +pure void* memcpy(return void* s1, scope const void* s2, size_t n); version (Windows) { /// - int memicmp(in char* s1, in char* s2, size_t n); + int memicmp(scope const char* s1, scope const char* s2, size_t n); } /// -pure void* memmove(void* s1, in void* s2, size_t n); +pure void* memmove(return void* s1, scope const void* s2, size_t n); /// -pure void* memset(void* s, int c, size_t n); +pure void* memset(return void* s, int c, size_t n); /// -pure char* strcpy(char* s1, in char* s2); +pure char* strcpy(return char* s1, scope const char* s2); /// -pure char* strncpy(char* s1, in char* s2, size_t n); +pure char* strncpy(return char* s1, scope const char* s2, size_t n); /// -pure char* strcat(char* s1, in char* s2); +pure char* strcat(return char* s1, scope const char* s2); /// -pure char* strncat(char* s1, in char* s2, size_t n); +pure char* strncat(return char* s1, scope const char* s2, size_t n); /// -pure int strcmp(in char* s1, in char* s2); +pure int strcmp(scope const char* s1, scope const char* s2); /// -int strcoll(in char* s1, in char* s2); +int strcoll(scope const char* s1, scope const char* s2); /// -pure int strncmp(in char* s1, in char* s2, size_t n); +pure int strncmp(scope const char* s1, scope const char* s2, size_t n); /// -size_t strxfrm(char* s1, in char* s2, size_t n); +size_t strxfrm(scope char* s1, scope const char* s2, size_t n); /// -pure char* strchr(in char* s, int c); +pure inout(char)* strchr(return inout(char)* s, int c); /// -pure size_t strcspn(in char* s1, in char* s2); +pure size_t strcspn(scope const char* s1, scope const char* s2); /// -pure char* strpbrk(in char* s1, in char* s2); +pure inout(char)* strpbrk(return inout(char)* s1, scope const char* s2); /// -pure char* strrchr(in char* s, int c); +pure inout(char)* strrchr(return inout(char)* s, int c); /// -pure size_t strspn(in char* s1, in char* s2); +pure size_t strspn(scope const char* s1, scope const char* s2); /// -pure char* strstr(in char* s1, in char* s2); +pure inout(char)* strstr(return inout(char)* s1, scope const char* s2); /// -char* strtok(char* s1, in char* s2); +char* strtok(return char* s1, scope const char* s2); /// char* strerror(int errnum); version (CRuntime_Glibc) { /// - const(char)* strerror_r(int errnum, char* buf, size_t buflen); + const(char)* strerror_r(int errnum, return char* buf, size_t buflen); } else version (Darwin) { - int strerror_r(int errnum, char* buf, size_t buflen); + int strerror_r(int errnum, scope char* buf, size_t buflen); } else version (FreeBSD) { - int strerror_r(int errnum, char* buf, size_t buflen); + int strerror_r(int errnum, scope char* buf, size_t buflen); } else version (OpenBSD) { - int strerror_r(int errnum, char* buf, size_t buflen); + int strerror_r(int errnum, scope char* buf, size_t buflen); } else version (Solaris) { - int strerror_r(int errnum, char* buf, size_t buflen); + int strerror_r(int errnum, scope char* buf, size_t buflen); } else version (CRuntime_Bionic) { /// - int strerror_r(int errnum, char* buf, size_t buflen); + int strerror_r(int errnum, scope char* buf, size_t buflen); } /// -pure size_t strlen(in char* s); +pure size_t strlen(scope const char* s); /// -char* strdup(in char *s); +char* strdup(scope const char *s); From 94eeda692278d16e4a89a7118ce7c4a19e50d578 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Sat, 21 Jan 2017 18:29:07 -0800 Subject: [PATCH 10/82] core.stdc.stdio: annotate with 'scope' --- src/core/stdc/stdio.d | 150 +++++++++++++++++++++--------------------- 1 file changed, 75 insertions(+), 75 deletions(-) diff --git a/src/core/stdc/stdio.d b/src/core/stdc/stdio.d index d8e2c7a04d..532fc3a2d5 100644 --- a/src/core/stdc/stdio.d +++ b/src/core/stdc/stdio.d @@ -452,10 +452,10 @@ else version( OpenBSD ) int _lbfsize; void* _cookie; - int function(void*) _close; - int function(void*, char*, int) _read; - fpos_t function(void*, fpos_t, int) _seek; - int function(void*, in char*, int) _write; + int function(void*) _close; + int function(void*, scope char*, int) _read; + fpos_t function(void*, fpos_t, int) _seek; + int function(void*, scope const char*, int) _write; __sbuf _ext; ubyte* _up; @@ -538,10 +538,10 @@ else version( CRuntime_Bionic ) int _lbfsize; void* _cookie; - int function(void*) _close; - int function(void*, char*, int) _read; - fpos_t function(void*, fpos_t, int) _seek; - int function(void*, in char*, int) _write; + int function(void*) _close; + int function(void*, scope char*, int) _read; + fpos_t function(void*, fpos_t, int) _seek; + int function(void*, scope const char*, int) _write; __sbuf _ext; ubyte* _up; @@ -822,9 +822,9 @@ else } /// -int remove(in char* filename); +int remove(scope const char* filename); /// -int rename(in char* from, in char* to); +int rename(scope const char* from, scope const char* to); /// @trusted FILE* tmpfile(); // No unsafe pointer manipulation. @@ -842,9 +842,9 @@ int fclose(FILE* stream); } /// -FILE* fopen(in char* filename, in char* mode); +FILE* fopen(scope const char* filename, scope const char* mode); /// -FILE* freopen(in char* filename, in char* mode, FILE* stream); +FILE* freopen(scope const char* filename, scope const char* mode, FILE* stream); /// void setbuf(FILE* stream, char* buf); @@ -856,91 +856,91 @@ version (MinGW) // Prefer the MinGW versions over the MSVC ones, as the latter don't handle // reals at all. /// - int __mingw_fprintf(FILE* stream, in char* format, ...); + int __mingw_fprintf(FILE* stream, scope const char* format, ...); /// alias __mingw_fprintf fprintf; /// - int __mingw_fscanf(FILE* stream, in char* format, ...); + int __mingw_fscanf(FILE* stream, scope const char* format, ...); /// alias __mingw_fscanf fscanf; /// - int __mingw_sprintf(char* s, in char* format, ...); + int __mingw_sprintf(scope char* s, scope const char* format, ...); /// alias __mingw_sprintf sprintf; /// - int __mingw_sscanf(in char* s, in char* format, ...); + int __mingw_sscanf(scope const char* s, scope const char* format, ...); /// alias __mingw_sscanf sscanf; /// - int __mingw_vfprintf(FILE* stream, in char* format, va_list arg); + int __mingw_vfprintf(FILE* stream, scope const char* format, va_list arg); /// alias __mingw_vfprintf vfprintf; /// - int __mingw_vfscanf(FILE* stream, in char* format, va_list arg); + int __mingw_vfscanf(FILE* stream, scope const char* format, va_list arg); /// alias __mingw_vfscanf vfscanf; /// - int __mingw_vsprintf(char* s, in char* format, va_list arg); + int __mingw_vsprintf(scope char* s, scope const char* format, va_list arg); /// alias __mingw_vsprintf vsprintf; /// - int __mingw_vsscanf(in char* s, in char* format, va_list arg); + int __mingw_vsscanf(scope const char* s, scope const char* format, va_list arg); /// alias __mingw_vsscanf vsscanf; /// - int __mingw_vprintf(in char* format, va_list arg); + int __mingw_vprintf(scope const char* format, va_list arg); /// alias __mingw_vprintf vprintf; /// - int __mingw_vscanf(in char* format, va_list arg); + int __mingw_vscanf(scope const char* format, va_list arg); /// alias __mingw_vscanf vscanf; /// - int __mingw_printf(in char* format, ...); + int __mingw_printf(scope const char* format, ...); /// alias __mingw_printf printf; /// - int __mingw_scanf(in char* format, ...); + int __mingw_scanf(scope const char* format, ...); /// alias __mingw_scanf scanf; } else { /// - int fprintf(FILE* stream, in char* format, ...); + int fprintf(FILE* stream, scope const char* format, ...); /// - int fscanf(FILE* stream, in char* format, ...); + int fscanf(FILE* stream, scope const char* format, ...); /// - int sprintf(char* s, in char* format, ...); + int sprintf(scope char* s, scope const char* format, ...); /// - int sscanf(in char* s, in char* format, ...); + int sscanf(scope const char* s, scope const char* format, ...); /// - int vfprintf(FILE* stream, in char* format, va_list arg); + int vfprintf(FILE* stream, scope const char* format, va_list arg); /// - int vfscanf(FILE* stream, in char* format, va_list arg); + int vfscanf(FILE* stream, scope const char* format, va_list arg); /// - int vsprintf(char* s, in char* format, va_list arg); + int vsprintf(scope char* s, scope const char* format, va_list arg); /// - int vsscanf(in char* s, in char* format, va_list arg); + int vsscanf(scope const char* s, scope const char* format, va_list arg); /// - int vprintf(in char* format, va_list arg); + int vprintf(scope const char* format, va_list arg); /// - int vscanf(in char* format, va_list arg); + int vscanf(scope const char* format, va_list arg); /// - int printf(in char* format, ...); + int printf(scope const char* format, ...); /// - int scanf(in char* format, ...); + int scanf(scope const char* format, ...); } // No unsafe pointer manipulation. @@ -955,11 +955,11 @@ else /// char* fgets(char* s, int n, FILE* stream); /// -int fputs(in char* s, FILE* stream); +int fputs(scope const char* s, FILE* stream); /// char* gets(char* s); /// -int puts(in char* s); +int puts(scope const char* s); // No unsafe pointer manipulation. extern (D) @trusted @@ -978,17 +978,17 @@ extern (D) @trusted @trusted int ungetc(int c, FILE* stream); // No unsafe pointer manipulation. /// -size_t fread(void* ptr, size_t size, size_t nmemb, FILE* stream); +size_t fread(scope void* ptr, size_t size, size_t nmemb, FILE* stream); /// -size_t fwrite(in void* ptr, size_t size, size_t nmemb, FILE* stream); +size_t fwrite(scope const void* ptr, size_t size, size_t nmemb, FILE* stream); // No unsafe pointer manipulation. @trusted { /// - int fgetpos(FILE* stream, fpos_t * pos); + int fgetpos(FILE* stream, scope fpos_t * pos); /// - int fsetpos(FILE* stream, in fpos_t* pos); + int fsetpos(FILE* stream, scope const fpos_t* pos); /// int fseek(FILE* stream, c_long offset, int whence); @@ -1011,14 +1011,14 @@ version( MinGW ) pure int ferror(FILE* stream) { return stream._flag&_IOERR; } } /// - int __mingw_snprintf(char* s, size_t n, in char* fmt, ...); + int __mingw_snprintf(scope char* s, size_t n, scope const char* fmt, ...); /// alias __mingw_snprintf _snprintf; /// alias __mingw_snprintf snprintf; /// - int __mingw_vsnprintf(char* s, size_t n, in char* format, va_list arg); + int __mingw_vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg); /// alias __mingw_vsnprintf _vsnprintf; /// @@ -1041,12 +1041,12 @@ else version( CRuntime_DigitalMars ) pure int fileno(FILE* stream) { return stream._file; } } /// - int _snprintf(char* s, size_t n, in char* fmt, ...); + int _snprintf(scope char* s, size_t n, scope const char* fmt, ...); /// alias _snprintf snprintf; /// - int _vsnprintf(char* s, size_t n, in char* format, va_list arg); + int _vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg); /// alias _vsnprintf vsnprintf; } @@ -1068,14 +1068,14 @@ else version( CRuntime_Microsoft ) } /// - int _snprintf(char* s, size_t n, in char* format, ...); + int _snprintf(scope char* s, size_t n, scope const char* format, ...); /// - int snprintf(char* s, size_t n, in char* format, ...); + int snprintf(scope char* s, size_t n, scope const char* format, ...); /// - int _vsnprintf(char* s, size_t n, in char* format, va_list arg); + int _vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg); /// - int vsnprintf(char* s, size_t n, in char* format, va_list arg); + int vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg); /// int _fputc_nolock(int c, FILE *fp); @@ -1110,9 +1110,9 @@ else version( CRuntime_Glibc ) } /// - int snprintf(char* s, size_t n, in char* format, ...); + int snprintf(scope char* s, size_t n, scope const char* format, ...); /// - int vsnprintf(char* s, size_t n, in char* format, va_list arg); + int vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg); } else version( Darwin ) { @@ -1132,9 +1132,9 @@ else version( Darwin ) } /// - int snprintf(char* s, size_t n, in char* format, ...); + int snprintf(scope char* s, size_t n, scope const char* format, ...); /// - int vsnprintf(char* s, size_t n, in char* format, va_list arg); + int vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg); } else version( FreeBSD ) { @@ -1154,9 +1154,9 @@ else version( FreeBSD ) } /// - int snprintf(char* s, size_t n, in char* format, ...); + int snprintf(scope char* s, size_t n, scope const char* format, ...); /// - int vsnprintf(char* s, size_t n, in char* format, va_list arg); + int vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg); } else version( OpenBSD ) { @@ -1245,9 +1245,9 @@ else version( OpenBSD ) } /// - int snprintf(char* s, size_t n, in char* format, ...); + int snprintf(scope char* s, size_t n, scope const char* format, ...); /// - int vsnprintf(char* s, size_t n, in char* format, va_list arg); + int vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg); } else version (Solaris) { @@ -1267,9 +1267,9 @@ else version (Solaris) } /// - int snprintf(char* s, size_t n, in char* format, ...); + int snprintf(scope char* s, size_t n, scope const char* format, ...); /// - int vsnprintf(char* s, size_t n, in char* format, va_list arg); + int vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg); } else version( CRuntime_Bionic ) { @@ -1289,9 +1289,9 @@ else version( CRuntime_Bionic ) } /// - int snprintf(char* s, size_t n, in char* format, ...); + int snprintf(scope char* s, size_t n, scope const char* format, ...); /// - int vsnprintf(char* s, size_t n, in char* format, va_list arg); + int vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg); } else { @@ -1299,7 +1299,7 @@ else } /// -void perror(in char* s); +void perror(scope const char* s); version(CRuntime_DigitalMars) { @@ -1406,28 +1406,28 @@ version(CRuntime_DigitalMars) STDERR_FILENO = 2, } - int open(const(char)* filename, int flags, ...); /// + int open(scope const(char)* filename, int flags, ...); /// alias _open = open; /// - int _wopen(const wchar* filename, int oflag, ...); /// - int sopen(const char* filename, int oflag, int shflag, ...); /// + int _wopen(scope const wchar* filename, int oflag, ...); /// + int sopen(scope const char* filename, int oflag, int shflag, ...); /// alias _sopen = sopen; /// - int _wsopen(const wchar* filename, int oflag, int shflag, ...); /// + int _wsopen(scope const wchar* filename, int oflag, int shflag, ...); /// int close(int fd); /// alias _close = close; /// - FILE *fdopen(int fd, const(char)* flags); /// + FILE *fdopen(int fd, scope const(char)* flags); /// alias _fdopen = fdopen; /// - FILE *_wfdopen(int fd, const(wchar)* flags); /// + FILE *_wfdopen(int fd, scope const(wchar)* flags); /// } else version (CRuntime_Microsoft) { - int _open(const char* filename, int oflag, ...); /// - int _wopen(const wchar* filename, int oflag, ...); /// - int _sopen(const char* filename, int oflag, int shflag, ...); /// - int _wsopen(const wchar* filename, int oflag, int shflag, ...); /// + int _open(scope const char* filename, int oflag, ...); /// + int _wopen(scope const wchar* filename, int oflag, ...); /// + int _sopen(scope const char* filename, int oflag, int shflag, ...); /// + int _wsopen(scope const wchar* filename, int oflag, int shflag, ...); /// int _close(int fd); /// - FILE *_fdopen(int fd, const(char)* flags); /// - FILE *_wfdopen(int fd, const(wchar)* flags); /// + FILE *_fdopen(int fd, scope const(char)* flags); /// + FILE *_wfdopen(int fd, scope const(wchar)* flags); /// } version (Windows) From 9f21c4208a885a96f890190e0baa1869ba9e845b Mon Sep 17 00:00:00 2001 From: ZombineDev Date: Wed, 28 Dec 2016 15:15:55 +0200 Subject: [PATCH 11/82] Fix coding style in core.sync.mutex --- src/core/sync/mutex.d | 87 +++++++++++++++++++++---------------------- 1 file changed, 43 insertions(+), 44 deletions(-) diff --git a/src/core/sync/mutex.d b/src/core/sync/mutex.d index bdedb09986..e360f5b990 100644 --- a/src/core/sync/mutex.d +++ b/src/core/sync/mutex.d @@ -18,11 +18,11 @@ module core.sync.mutex; public import core.sync.exception; -version( Windows ) +version (Windows) { private import core.sys.windows.windows; } -else version( Posix ) +else version (Posix) { private import core.sys.posix.pthread; } @@ -58,13 +58,13 @@ class Mutex : * Throws: * SyncError on error. */ - this() nothrow @trusted + this() @trusted nothrow { - version( Windows ) + version (Windows) { - InitializeCriticalSection( &m_hndl ); + InitializeCriticalSection(&m_hndl); } - else version( Posix ) + else version (Posix) { pthread_mutexattr_t attr = void; @@ -78,6 +78,7 @@ class Mutex : if( pthread_mutex_init( &m_hndl, &attr ) ) throw new SyncError( "Unable to initialize mutex" ); } + m_proxy.link = this; this.__monitor = &m_proxy; } @@ -89,10 +90,10 @@ class Mutex : * In: * o must not already have a monitor. */ - this( Object o ) nothrow @trusted + this(Object o) @trusted nothrow in { - assert( o.__monitor is null ); + assert(o.__monitor is null); } body { @@ -103,11 +104,11 @@ class Mutex : ~this() { - version( Windows ) + version (Windows) { - DeleteCriticalSection( &m_hndl ); + DeleteCriticalSection(&m_hndl); } - else version( Posix ) + else version (Posix) { int rc = pthread_mutex_destroy( &m_hndl ); assert( !rc, "Unable to destroy mutex" ); @@ -136,19 +137,18 @@ class Mutex : // undocumented function for internal use final void lock_nothrow() nothrow @trusted @nogc { - version( Windows ) + version (Windows) { - EnterCriticalSection( &m_hndl ); + EnterCriticalSection(&m_hndl); } - else version( Posix ) + else version (Posix) { - int rc = pthread_mutex_lock( &m_hndl ); - if( rc ) - { - SyncError syncErr = cast(SyncError) cast(void*) typeid(SyncError).initializer; - syncErr.msg = "Unable to lock mutex."; - throw syncErr; - } + if (pthread_mutex_lock(&m_hndl) == 0) + return; + + SyncError syncErr = cast(SyncError) cast(void*) typeid(SyncError).initializer; + syncErr.msg = "Unable to lock mutex."; + throw syncErr; } } @@ -167,19 +167,18 @@ class Mutex : // undocumented function for internal use final void unlock_nothrow() nothrow @trusted @nogc { - version( Windows ) + version (Windows) { - LeaveCriticalSection( &m_hndl ); + LeaveCriticalSection(&m_hndl); } - else version( Posix ) + else version (Posix) { - int rc = pthread_mutex_unlock( &m_hndl ); - if( rc ) - { - SyncError syncErr = cast(SyncError) cast(void*) typeid(SyncError).initializer; - syncErr.msg = "Unable to unlock mutex."; - throw syncErr; - } + if (pthread_mutex_unlock(&m_hndl) == 0) + return; + + SyncError syncErr = cast(SyncError) cast(void*) typeid(SyncError).initializer; + syncErr.msg = "Unable to unlock mutex."; + throw syncErr; } } @@ -196,23 +195,23 @@ class Mutex : */ bool tryLock() { - version( Windows ) + version (Windows) { - return TryEnterCriticalSection( &m_hndl ) != 0; + return TryEnterCriticalSection(&m_hndl) != 0; } - else version( Posix ) + else version (Posix) { - return pthread_mutex_trylock( &m_hndl ) == 0; + return pthread_mutex_trylock(&m_hndl) == 0; } } private: - version( Windows ) + version (Windows) { CRITICAL_SECTION m_hndl; } - else version( Posix ) + else version (Posix) { pthread_mutex_t m_hndl; } @@ -226,7 +225,7 @@ private: package: - version( Posix ) + version (Posix) { pthread_mutex_t* handleAddr() { @@ -241,7 +240,7 @@ package: //////////////////////////////////////////////////////////////////////////////// -version( unittest ) +version (unittest) { private import core.thread; @@ -255,9 +254,9 @@ version( unittest ) void testFn() { - for( int i = 0; i < numTries; ++i ) + for (int i = 0; i < numTries; ++i) { - synchronized( mutex ) + synchronized (mutex) { ++lockCount; } @@ -266,10 +265,10 @@ version( unittest ) auto group = new ThreadGroup; - for( int i = 0; i < numThreads; ++i ) - group.create( &testFn ); + for (int i = 0; i < numThreads; ++i) + group.create(&testFn); group.joinAll(); - assert( lockCount == numThreads * numTries ); + assert(lockCount == numThreads * numTries); } } From 5523188db5071c19407a652d089dceae246f0dd8 Mon Sep 17 00:00:00 2001 From: ZombineDev Date: Wed, 28 Dec 2016 16:24:15 +0200 Subject: [PATCH 12/82] Make core.sync.mutex.Mutex.this()/this(Object)/~this() nothrow and @nogc --- src/core/sync/mutex.d | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/src/core/sync/mutex.d b/src/core/sync/mutex.d index e360f5b990..a86fcc4231 100644 --- a/src/core/sync/mutex.d +++ b/src/core/sync/mutex.d @@ -55,10 +55,8 @@ class Mutex : /** * Initializes a mutex object. * - * Throws: - * SyncError on error. */ - this() @trusted nothrow + this() @trusted nothrow @nogc { version (Windows) { @@ -68,15 +66,16 @@ class Mutex : { pthread_mutexattr_t attr = void; - if( pthread_mutexattr_init( &attr ) ) - throw new SyncError( "Unable to initialize mutex" ); - scope(exit) pthread_mutexattr_destroy( &attr ); + !pthread_mutexattr_init(&attr) || + assert (0, "Unable to initialize mutex"); + + scope (exit) pthread_mutexattr_destroy(&attr); - if( pthread_mutexattr_settype( &attr, PTHREAD_MUTEX_RECURSIVE ) ) - throw new SyncError( "Unable to initialize mutex" ); + !pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE) || + assert (0, "Unable to initialize mutex"); - if( pthread_mutex_init( &m_hndl, &attr ) ) - throw new SyncError( "Unable to initialize mutex" ); + !pthread_mutex_init(&m_hndl, &attr) || + assert (0, "Unable to initialize mutex"); } m_proxy.link = this; @@ -90,7 +89,7 @@ class Mutex : * In: * o must not already have a monitor. */ - this(Object o) @trusted nothrow + this(Object o) @trusted nothrow @nogc in { assert(o.__monitor is null); @@ -102,7 +101,7 @@ class Mutex : } - ~this() + ~this() @trusted nothrow @nogc { version (Windows) { @@ -110,8 +109,8 @@ class Mutex : } else version (Posix) { - int rc = pthread_mutex_destroy( &m_hndl ); - assert( !rc, "Unable to destroy mutex" ); + !pthread_mutex_destroy(&m_hndl) || + assert (0, "Unable to destroy mutex"); } this.__monitor = null; } From 7d39fdce22051dedd138c5c1bdf45a0dd23b9ed5 Mon Sep 17 00:00:00 2001 From: ZombineDev Date: Wed, 28 Dec 2016 16:30:39 +0200 Subject: [PATCH 13/82] Make `shared(core.sync.mutex.Mutex)` usable in `@safe` code Additionally add `shared` overloads to: + core.sys.windows.winbase: * EnterCriticalSection * LeaveCriticalSection * TryEnterCriticalSection + core.sys.posix.pthread: * pthread_mutex_lock * pthread_mutex_unlock * pthread_mutex_trylock Also add `tryLock_nothrow` version of `Mutex.tryLock`. --- src/core/sync/mutex.d | 65 ++++++++++++++++++++++++++++++---- src/core/sys/posix/pthread.d | 3 ++ src/core/sys/windows/winbase.d | 3 ++ 3 files changed, 64 insertions(+), 7 deletions(-) diff --git a/src/core/sync/mutex.d b/src/core/sync/mutex.d index a86fcc4231..d77afaa62b 100644 --- a/src/core/sync/mutex.d +++ b/src/core/sync/mutex.d @@ -57,10 +57,22 @@ class Mutex : * */ this() @trusted nothrow @nogc + { + this(true); + } + + /// ditto + this() shared @trusted nothrow @nogc + { + this(true); + } + + private this(this Q)(bool _unused_) @trusted nothrow @nogc + if (is(Q == Mutex) || is(Q == shared Mutex)) { version (Windows) { - InitializeCriticalSection(&m_hndl); + InitializeCriticalSection(cast(CRITICAL_SECTION*)&m_hndl); } else version (Posix) { @@ -74,12 +86,12 @@ class Mutex : !pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE) || assert (0, "Unable to initialize mutex"); - !pthread_mutex_init(&m_hndl, &attr) || + !pthread_mutex_init(cast(pthread_mutex_t*)&m_hndl, &attr) || assert (0, "Unable to initialize mutex"); } m_proxy.link = this; - this.__monitor = &m_proxy; + this.__monitor = cast(void*)&m_proxy; } @@ -90,6 +102,18 @@ class Mutex : * o must not already have a monitor. */ this(Object o) @trusted nothrow @nogc + { + this(o, true); + } + + /// ditto + this(Object o) shared @trusted nothrow @nogc + { + this(o, true); + } + + this(this Q)(Object o, bool _unused_) @trusted nothrow @nogc + if (is(Q == Mutex) || is(Q == shared Mutex)) in { assert(o.__monitor is null); @@ -97,7 +121,7 @@ class Mutex : body { this(); - o.__monitor = &m_proxy; + o.__monitor = cast(void*)&m_proxy; } @@ -133,8 +157,15 @@ class Mutex : lock_nothrow(); } + /// ditto + @trusted void lock() shared + { + lock_nothrow(); + } + // undocumented function for internal use - final void lock_nothrow() nothrow @trusted @nogc + final void lock_nothrow(this Q)() nothrow @trusted @nogc + if (is(Q == Mutex) || is(Q == shared Mutex)) { version (Windows) { @@ -163,8 +194,15 @@ class Mutex : unlock_nothrow(); } + /// ditto + @trusted void unlock() shared + { + unlock_nothrow(); + } + // undocumented function for internal use - final void unlock_nothrow() nothrow @trusted @nogc + final void unlock_nothrow(this Q)() nothrow @trusted @nogc + if (is(Q == Mutex) || is(Q == shared Mutex)) { version (Windows) { @@ -192,7 +230,20 @@ class Mutex : * Returns: * true if the lock was acquired and false if not. */ - bool tryLock() + bool tryLock() @trusted + { + return tryLock_nothrow(); + } + + /// ditto + bool tryLock() shared @trusted + { + return tryLock_nothrow(); + } + + // undocumented function for internal use + final bool tryLock_nothrow(this Q)() nothrow @trusted @nogc + if (is(Q == Mutex) || is(Q == shared Mutex)) { version (Windows) { diff --git a/src/core/sys/posix/pthread.d b/src/core/sys/posix/pthread.d index 9ef960633e..60cd76d589 100644 --- a/src/core/sys/posix/pthread.d +++ b/src/core/sys/posix/pthread.d @@ -499,8 +499,11 @@ int pthread_key_delete(pthread_key_t); int pthread_mutex_destroy(pthread_mutex_t*); int pthread_mutex_init(pthread_mutex_t*, pthread_mutexattr_t*) @trusted; int pthread_mutex_lock(pthread_mutex_t*); +int pthread_mutex_lock(shared(pthread_mutex_t)*); int pthread_mutex_trylock(pthread_mutex_t*); +int pthread_mutex_trylock(shared(pthread_mutex_t)*); int pthread_mutex_unlock(pthread_mutex_t*); +int pthread_mutex_unlock(shared(pthread_mutex_t)*); int pthread_mutexattr_destroy(pthread_mutexattr_t*); int pthread_mutexattr_init(pthread_mutexattr_t*) @trusted; int pthread_once(pthread_once_t*, void function()); diff --git a/src/core/sys/windows/winbase.d b/src/core/sys/windows/winbase.d index 6441beb0c5..e4890a1f3d 100644 --- a/src/core/sys/windows/winbase.d +++ b/src/core/sys/windows/winbase.d @@ -1745,6 +1745,7 @@ extern (Windows) nothrow @nogc { BOOL EndUpdateResourceA(HANDLE, BOOL); BOOL EndUpdateResourceW(HANDLE, BOOL); void EnterCriticalSection(LPCRITICAL_SECTION); + void EnterCriticalSection(shared(CRITICAL_SECTION)*); BOOL EnumResourceLanguagesA(HMODULE, LPCSTR, LPCSTR, ENUMRESLANGPROC, LONG_PTR); BOOL EnumResourceLanguagesW(HMODULE, LPCWSTR, LPCWSTR, ENUMRESLANGPROC, LONG_PTR); BOOL EnumResourceNamesA(HMODULE, LPCSTR, ENUMRESNAMEPROC, LONG_PTR); @@ -1927,6 +1928,7 @@ WINBASEAPI DWORD WINAPI GetCurrentThreadId(void); BOOL IsBadStringPtrW(LPCWSTR, UINT_PTR); BOOL IsBadWritePtr(PVOID, UINT_PTR); void LeaveCriticalSection(LPCRITICAL_SECTION); + void LeaveCriticalSection(shared(CRITICAL_SECTION)*); HINSTANCE LoadLibraryA(LPCSTR); HINSTANCE LoadLibraryW(LPCWSTR); HINSTANCE LoadLibraryExA(LPCSTR, HANDLE, DWORD); @@ -2313,6 +2315,7 @@ WINBASEAPI BOOL WINAPI SetEvent(HANDLE); BOOL SystemTimeToTzSpecificLocalTime(LPTIME_ZONE_INFORMATION, LPSYSTEMTIME, LPSYSTEMTIME); BOOL TzSpecificLocalTimeToSystemTime(LPTIME_ZONE_INFORMATION, LPSYSTEMTIME, LPSYSTEMTIME); BOOL TryEnterCriticalSection(LPCRITICAL_SECTION); + BOOL TryEnterCriticalSection(shared(CRITICAL_SECTION)*); BOOL UnlockFileEx(HANDLE, DWORD, DWORD, DWORD, LPOVERLAPPED); BOOL UpdateResourceA(HANDLE, LPCSTR, LPCSTR, WORD, PVOID, DWORD); BOOL UpdateResourceW(HANDLE, LPCWSTR, LPCWSTR, WORD, PVOID, DWORD); From f4810b4bdd07b32eb8b3b852493c1f1e72bce3f7 Mon Sep 17 00:00:00 2001 From: ZombineDev Date: Wed, 28 Dec 2016 16:44:57 +0200 Subject: [PATCH 14/82] [WIP] Improve core.sync.mutex documentation --- src/core/sync/mutex.d | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/core/sync/mutex.d b/src/core/sync/mutex.d index d77afaa62b..98675ef910 100644 --- a/src/core/sync/mutex.d +++ b/src/core/sync/mutex.d @@ -31,7 +31,6 @@ else static assert(false, "Platform not supported"); } - //////////////////////////////////////////////////////////////////////////////// // Mutex // @@ -43,6 +42,9 @@ else /** * This class represents a general purpose, recursive mutex. + * + * Implemented using pthread_mutex on Posix and CRITICAL_SECTION + * on Windows. */ class Mutex : Object.Monitor @@ -67,6 +69,7 @@ class Mutex : this(true); } + // Undocumented, useful only in Mutex.this(). private this(this Q)(bool _unused_) @trusted nothrow @nogc if (is(Q == Mutex) || is(Q == shared Mutex)) { @@ -112,7 +115,8 @@ class Mutex : this(o, true); } - this(this Q)(Object o, bool _unused_) @trusted nothrow @nogc + // Undocumented, useful only in Mutex.this(Object). + private this(this Q)(Object o, bool _unused_) @trusted nothrow @nogc if (is(Q == Mutex) || is(Q == shared Mutex)) in { @@ -163,7 +167,7 @@ class Mutex : lock_nothrow(); } - // undocumented function for internal use + /// ditto final void lock_nothrow(this Q)() nothrow @trusted @nogc if (is(Q == Mutex) || is(Q == shared Mutex)) { @@ -200,7 +204,7 @@ class Mutex : unlock_nothrow(); } - // undocumented function for internal use + /// ditto final void unlock_nothrow(this Q)() nothrow @trusted @nogc if (is(Q == Mutex) || is(Q == shared Mutex)) { @@ -241,7 +245,7 @@ class Mutex : return tryLock_nothrow(); } - // undocumented function for internal use + /// ditto final bool tryLock_nothrow(this Q)() nothrow @trusted @nogc if (is(Q == Mutex) || is(Q == shared Mutex)) { From 60f37a2552549c4491c7e23b2c5d3054f723a847 Mon Sep 17 00:00:00 2001 From: ZombineDev Date: Sat, 14 Jan 2017 00:46:27 +0200 Subject: [PATCH 15/82] [core.sync.mutex] Add a note to the docs about nothrow --- src/core/sync/mutex.d | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/core/sync/mutex.d b/src/core/sync/mutex.d index 98675ef910..8e4998994c 100644 --- a/src/core/sync/mutex.d +++ b/src/core/sync/mutex.d @@ -153,8 +153,9 @@ class Mutex : * If this lock is not already held by the caller, the lock is acquired, * then the internal counter is incremented by one. * - * Throws: - * SyncError on error. + * Note: + * `Mutex.lock` does not throw, but a class derived from Mutex can throw. + * Use `lock_nothrow` in `nothrow @nogc` code. */ @trusted void lock() { @@ -190,8 +191,9 @@ class Mutex : * Decrements the internal lock count by one. If this brings the count to * zero, the lock is released. * - * Throws: - * SyncError on error. + * Note: + * `Mutex.unlock` does not throw, but a class derived from Mutex can throw. + * Use `unlock_nothrow` in `nothrow @nogc` code. */ @trusted void unlock() { @@ -228,11 +230,12 @@ class Mutex : * the lock is acquired if it is not already held, and then the internal * counter is incremented by one. * - * Throws: - * SyncError on error. - * * Returns: * true if the lock was acquired and false if not. + * + * Note: + * `Mutex.tryLock` does not throw, but a class derived from Mutex can throw. + * Use `tryLock_nothrow` in `nothrow @nogc` code. */ bool tryLock() @trusted { From 0291197f119f2df8a896fe88352d31138c5de7fc Mon Sep 17 00:00:00 2001 From: ZombineDev Date: Sat, 14 Jan 2017 00:54:37 +0200 Subject: [PATCH 16/82] [core.sync.mutex] Change assert(0, msg) to abort(msg); improve error messages --- src/core/sync/mutex.d | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/core/sync/mutex.d b/src/core/sync/mutex.d index 8e4998994c..2257a8a664 100644 --- a/src/core/sync/mutex.d +++ b/src/core/sync/mutex.d @@ -79,18 +79,19 @@ class Mutex : } else version (Posix) { + import core.internal.abort : abort; pthread_mutexattr_t attr = void; !pthread_mutexattr_init(&attr) || - assert (0, "Unable to initialize mutex"); + abort("Unable to initialize mutex"); scope (exit) pthread_mutexattr_destroy(&attr); !pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE) || - assert (0, "Unable to initialize mutex"); + abort("Unable to initialize mutex"); !pthread_mutex_init(cast(pthread_mutex_t*)&m_hndl, &attr) || - assert (0, "Unable to initialize mutex"); + abort("Unable to initialize mutex"); } m_proxy.link = this; @@ -120,7 +121,8 @@ class Mutex : if (is(Q == Mutex) || is(Q == shared Mutex)) in { - assert(o.__monitor is null); + assert(o.__monitor is null, + "The provided object has a monitor already set!"); } body { @@ -137,8 +139,9 @@ class Mutex : } else version (Posix) { + import core.internal.abort : abort; !pthread_mutex_destroy(&m_hndl) || - assert (0, "Unable to destroy mutex"); + abort("Unable to destroy mutex"); } this.__monitor = null; } From 5e4b740b1fd9c4b02caa4c8b1edcd3711d2e492b Mon Sep 17 00:00:00 2001 From: ZombineDev Date: Sat, 14 Jan 2017 02:33:08 +0200 Subject: [PATCH 17/82] [core.sync.mutex] Cleanup existing unittest --- src/core/sync/mutex.d | 40 ++++++++++++++++------------------------ 1 file changed, 16 insertions(+), 24 deletions(-) diff --git a/src/core/sync/mutex.d b/src/core/sync/mutex.d index 2257a8a664..0d1c2413c4 100644 --- a/src/core/sync/mutex.d +++ b/src/core/sync/mutex.d @@ -295,40 +295,32 @@ package: } -//////////////////////////////////////////////////////////////////////////////// -// Unit Tests -//////////////////////////////////////////////////////////////////////////////// - -version (unittest) +unittest { - private import core.thread; + import core.thread; + auto mutex = new Mutex; + int numThreads = 10; + int numTries = 1000; + int lockCount = 0; - unittest + void testFn() { - auto mutex = new Mutex; - int numThreads = 10; - int numTries = 1000; - int lockCount = 0; - - void testFn() + for (int i = 0; i < numTries; ++i) { - for (int i = 0; i < numTries; ++i) + synchronized (mutex) { - synchronized (mutex) - { - ++lockCount; - } + ++lockCount; } } + } - auto group = new ThreadGroup; + auto group = new ThreadGroup; - for (int i = 0; i < numThreads; ++i) - group.create(&testFn); + for (int i = 0; i < numThreads; ++i) + group.create(&testFn); - group.joinAll(); - assert(lockCount == numThreads * numTries); - } + group.joinAll(); + assert(lockCount == numThreads * numTries); } From ff38e5ea31a66a290fc8bdaef82fde7026484bbc Mon Sep 17 00:00:00 2001 From: ZombineDev Date: Sat, 14 Jan 2017 02:34:44 +0200 Subject: [PATCH 18/82] [core.sync.mutex] Add a @safe ddoc-ed test and a @nogc nothrow one --- src/core/sync/mutex.d | 80 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/src/core/sync/mutex.d b/src/core/sync/mutex.d index 0d1c2413c4..8ef7bff6fe 100644 --- a/src/core/sync/mutex.d +++ b/src/core/sync/mutex.d @@ -294,7 +294,87 @@ package: } } +/// +/* @safe nothrow -> see druntime PR 1726 */ +// Test regular usage. +unittest +{ + import core.thread : Thread; + + class Resource + { + Mutex mtx; + int cargo; + + this() shared @safe nothrow + { + mtx = new shared Mutex(); + cargo = 42; + } + + void useResource() shared @safe nothrow @nogc + { + mtx.lock_nothrow(); + cargo++; + mtx.unlock_nothrow(); + } + } + + shared Resource res = new shared Resource(); + + auto otherThread = new Thread( + { + foreach (i; 0 .. 10000) + res.useResource(); + }).start(); + + foreach (i; 0 .. 10000) + res.useResource(); + + otherThread.join(); + assert (res.cargo == 20042); +} + +// Test @nogc usage. +@system @nogc nothrow unittest +{ + import core.stdc.stdlib : malloc, free; + + void* p = malloc(__traits(classInstanceSize, Mutex)); + + auto ti = typeid(Mutex); + p[0 .. ti.initializer.length] = ti.initializer[]; + + shared Mutex mtx = cast(shared(Mutex))p; + mtx.__ctor(); + + mtx.lock_nothrow(); + + { // test recursive locking + mtx.tryLock_nothrow(); + mtx.unlock_nothrow(); + } + + mtx.unlock_nothrow(); + + // In general destorying classes like this is not + // safe, but since we know that the only base class + // of Mutex is Object and it doesn't have a dtor + // we can simply call the non-virtual __dtor() here. + + // Ok to cast away shared because destruction + // should happen only from a single thread. + (cast(Mutex)mtx).__dtor(); + + // Verify that the underlying implementation has been destroyed + // by checking that locking is not possible. This assumes + // that the underlying implementation is well behaved + // and makes the object non-lockable upon destruction. + assert(!mtx.tryLock_nothrow()); + + free(cast(void*)mtx); +} unittest { From ac71591e259a46cf56e5b7a83fee93d7e3f5435e Mon Sep 17 00:00:00 2001 From: ZombineDev Date: Sat, 14 Jan 2017 02:51:12 +0200 Subject: [PATCH 19/82] [core.sync.mutex] Add a test for non-shared use of Mutex --- src/core/sync/mutex.d | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/core/sync/mutex.d b/src/core/sync/mutex.d index 8ef7bff6fe..b2033b620c 100644 --- a/src/core/sync/mutex.d +++ b/src/core/sync/mutex.d @@ -376,6 +376,19 @@ unittest free(cast(void*)mtx); } +// Test single-thread (non-shared) use. +unittest +{ + Mutex m = new Mutex(); + + m.lock(); + + m.tryLock(); + m.unlock(); + + m.unlock(); +} + unittest { import core.thread; From 90b1db62e6947bde77982df3df26f86543ec21ae Mon Sep 17 00:00:00 2001 From: ZombineDev Date: Tue, 24 Jan 2017 22:06:17 +0200 Subject: [PATCH 20/82] [core.sync.mutex] Abort if pthread_mutexattr_destroy fails * Also make the error messages more descriptive --- src/core/sync/mutex.d | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/core/sync/mutex.d b/src/core/sync/mutex.d index b2033b620c..65eee4ddb4 100644 --- a/src/core/sync/mutex.d +++ b/src/core/sync/mutex.d @@ -83,15 +83,16 @@ class Mutex : pthread_mutexattr_t attr = void; !pthread_mutexattr_init(&attr) || - abort("Unable to initialize mutex"); + abort("Error: pthread_mutexattr_init failed!"); - scope (exit) pthread_mutexattr_destroy(&attr); + scope (exit) !pthread_mutexattr_destroy(&attr) || + abort("Error: pthread_mutexattr_destroy failed!"); !pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE) || - abort("Unable to initialize mutex"); + abort("Error: pthread_mutexattr_settype failed!"); !pthread_mutex_init(cast(pthread_mutex_t*)&m_hndl, &attr) || - abort("Unable to initialize mutex"); + abort("Error: pthread_mutex_init failed!"); } m_proxy.link = this; From 7e5d669aa2b840f1c8335897d06564ddb062de1c Mon Sep 17 00:00:00 2001 From: ZombineDev Date: Wed, 25 Jan 2017 17:00:26 +0200 Subject: [PATCH 21/82] [core.sync.mutex] Address Andrei's comments --- src/core/sync/mutex.d | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/core/sync/mutex.d b/src/core/sync/mutex.d index 65eee4ddb4..605438c38f 100644 --- a/src/core/sync/mutex.d +++ b/src/core/sync/mutex.d @@ -43,7 +43,7 @@ else /** * This class represents a general purpose, recursive mutex. * - * Implemented using pthread_mutex on Posix and CRITICAL_SECTION + * Implemented using `pthread_mutex` on Posix and `CRITICAL_SECTION` * on Windows. */ class Mutex : @@ -75,7 +75,7 @@ class Mutex : { version (Windows) { - InitializeCriticalSection(cast(CRITICAL_SECTION*)&m_hndl); + InitializeCriticalSection(cast(CRITICAL_SECTION*) &m_hndl); } else version (Posix) { @@ -83,52 +83,52 @@ class Mutex : pthread_mutexattr_t attr = void; !pthread_mutexattr_init(&attr) || - abort("Error: pthread_mutexattr_init failed!"); + abort("Error: pthread_mutexattr_init failed."); scope (exit) !pthread_mutexattr_destroy(&attr) || - abort("Error: pthread_mutexattr_destroy failed!"); + abort("Error: pthread_mutexattr_destroy failed."); !pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE) || - abort("Error: pthread_mutexattr_settype failed!"); + abort("Error: pthread_mutexattr_settype failed."); - !pthread_mutex_init(cast(pthread_mutex_t*)&m_hndl, &attr) || - abort("Error: pthread_mutex_init failed!"); + !pthread_mutex_init(cast(pthread_mutex_t*) &m_hndl, &attr) || + abort("Error: pthread_mutex_init failed."); } m_proxy.link = this; - this.__monitor = cast(void*)&m_proxy; + this.__monitor = cast(void*) &m_proxy; } /** - * Initializes a mutex object and sets it as the monitor for o. + * Initializes a mutex object and sets it as the monitor for `obj`. * * In: - * o must not already have a monitor. + * `obj` must not already have a monitor. */ - this(Object o) @trusted nothrow @nogc + this(Object obj) @trusted nothrow @nogc { - this(o, true); + this(obj, true); } /// ditto - this(Object o) shared @trusted nothrow @nogc + this(Object obj) shared @trusted nothrow @nogc { - this(o, true); + this(obj, true); } // Undocumented, useful only in Mutex.this(Object). - private this(this Q)(Object o, bool _unused_) @trusted nothrow @nogc + private this(this Q)(Object obj, bool _unused_) @trusted nothrow @nogc if (is(Q == Mutex) || is(Q == shared Mutex)) in { - assert(o.__monitor is null, + assert(obj.__monitor is null, "The provided object has a monitor already set!"); } body { this(); - o.__monitor = cast(void*)&m_proxy; + obj.__monitor = cast(void*) &m_proxy; } @@ -142,7 +142,7 @@ class Mutex : { import core.internal.abort : abort; !pthread_mutex_destroy(&m_hndl) || - abort("Unable to destroy mutex"); + abort("Error: pthread_mutex_init failed."); } this.__monitor = null; } @@ -347,7 +347,7 @@ unittest auto ti = typeid(Mutex); p[0 .. ti.initializer.length] = ti.initializer[]; - shared Mutex mtx = cast(shared(Mutex))p; + shared Mutex mtx = cast(shared(Mutex)) p; mtx.__ctor(); mtx.lock_nothrow(); @@ -366,7 +366,7 @@ unittest // Ok to cast away shared because destruction // should happen only from a single thread. - (cast(Mutex)mtx).__dtor(); + (cast(Mutex) mtx).__dtor(); // Verify that the underlying implementation has been destroyed // by checking that locking is not possible. This assumes @@ -374,7 +374,7 @@ unittest // and makes the object non-lockable upon destruction. assert(!mtx.tryLock_nothrow()); - free(cast(void*)mtx); + free(cast(void*) mtx); } // Test single-thread (non-shared) use. From d64e81c75cd13dd80bd70dbcb27aefa608f49354 Mon Sep 17 00:00:00 2001 From: Nemanja Boric Date: Thu, 26 Jan 2017 18:52:49 +0100 Subject: [PATCH 22/82] Add bindings for POSIX getdelim and getline --- src/core/sys/posix/stdio.d | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/core/sys/posix/stdio.d b/src/core/sys/posix/stdio.d index 4fb3655888..c085c862ce 100644 --- a/src/core/sys/posix/stdio.d +++ b/src/core/sys/posix/stdio.d @@ -344,3 +344,7 @@ unittest assert(memcmp(ptr, testdata.ptr, testdata.length*wchar_t.sizeof) == 0); assert(fclose(f) == 0); } + + +ssize_t getdelim (char** lineptr, size_t* n, int delimiter, FILE* stream); +ssize_t getline (char** lineptr, size_t* n, FILE* stream); From 0b6d766c1dcf7452aa867ccedf5e77d1de4f0f7b Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Sat, 28 Jan 2017 03:28:48 -0800 Subject: [PATCH 23/82] [scope] update core.demangle for 'scope' mangling --- src/core/demangle.d | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/core/demangle.d b/src/core/demangle.d index 56b2fe3db7..22e7e402ac 100644 --- a/src/core/demangle.d +++ b/src/core/demangle.d @@ -876,6 +876,8 @@ private struct Demangle FuncAttrNothrow FuncAttrProperty FuncAttrRef + FuncAttrReturn + FuncAttrScope FuncAttrTrusted FuncAttrSafe @@ -903,6 +905,9 @@ private struct Demangle FuncAttrReturn: Nj + FuncAttrScope: + Nl + Arguments: Argument Argument Arguments @@ -955,7 +960,7 @@ private struct Demangle { // FuncAttrs breakFuncAttrs: - while( 'N' == front ) + while ('N' == front) { popFront(); switch( front ) @@ -1003,6 +1008,10 @@ private struct Demangle popFront(); put( "return " ); continue; + case 'l': // FuncAttrScope + popFront(); + put( "scope " ); + continue; default: error(); } @@ -1963,6 +1972,10 @@ version(unittest) ["_D8link657429__T3fooHVE8link65746Methodi0Z3fooFZi", "int link6574.foo!(0).foo()"], ["_D4test22__T4funcVAyaa3_610a62Z4funcFNaNbNiNfZAya", `pure nothrow @nogc @safe immutable(char)[] test.func!("a\x0ab").func()`], ["_D3foo3barFzkZzi", "cent foo.bar(ucent)"], + ["_D5bug145Class3fooMFNlZPv", "scope void* bug14.Class.foo()"], + ["_D5bug145Class3barMFNjZPv", "return void* bug14.Class.bar()"], + ["_D5bug143fooFMPvZPv", "void* bug14.foo(scope void*)"], + ["_D5bug143barFMNkPvZPv", "void* bug14.bar(scope return void*)"], ]; template staticIota(int x) From 79dbaa7a52c032ff24232a82e544453dde10f287 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Sat, 28 Jan 2017 21:46:01 -0800 Subject: [PATCH 24/82] [scope] add 'scope' to delegates --- src/rt/dmain2.d | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/rt/dmain2.d b/src/rt/dmain2.d index 6aacc153a9..f17ca91004 100644 --- a/src/rt/dmain2.d +++ b/src/rt/dmain2.d @@ -492,7 +492,7 @@ extern (C) int _d_run_main(int argc, char **argv, MainFunc mainFunc) return result; } -private void formatThrowable(Throwable t, void delegate(in char[] s) nothrow sink) +private void formatThrowable(Throwable t, scope void delegate(in char[] s) nothrow sink) { for (; t; t = t.next) { @@ -521,7 +521,7 @@ extern (C) void _d_print_throwable(Throwable t) { wchar_t* ptr; size_t len; - void sink(in char[] s) nothrow + void sink(in char[] s) scope nothrow { if (!s.length) return; int swlen = MultiByteToWideChar( @@ -609,7 +609,7 @@ extern (C) void _d_print_throwable(Throwable t) } } - void sink(in char[] buf) nothrow + void sink(in char[] buf) scope nothrow { fprintf(stderr, "%.*s", cast(int)buf.length, buf.ptr); } From a4cf6c3da0fae56188d4d7629cc2f5c618e079e8 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Sat, 28 Jan 2017 21:50:57 -0800 Subject: [PATCH 25/82] [scope] add 'scope' to delegates --- src/gc/impl/conservative/gc.d | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gc/impl/conservative/gc.d b/src/gc/impl/conservative/gc.d index d0b969106f..fe1ca5f858 100644 --- a/src/gc/impl/conservative/gc.d +++ b/src/gc/impl/conservative/gc.d @@ -1952,7 +1952,7 @@ struct Gcx /** * Search a range of memory values and mark any pointers into the GC pool. */ - void mark(void *pbot, void *ptop) nothrow + void mark(void *pbot, void *ptop) scope nothrow { void **p1 = cast(void **)pbot; void **p2 = cast(void **)ptop; @@ -2443,7 +2443,7 @@ struct Gcx * Warning! This should only be called while the world is stopped inside * the fullcollect function. */ - int isMarked(void *addr) nothrow + int isMarked(void *addr) scope nothrow { // first, we find the Pool this block is in, then check to see if the // mark bit is clear. From 78bead03871daf0afb7c0a3490552199e27df6e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Per=20Nordl=C3=B6w?= Date: Wed, 18 Jan 2017 23:41:05 +0100 Subject: [PATCH 26/82] Add pureMalloc, pureCalloc and pureRealloc --- src/core/memory.d | 100 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/src/core/memory.d b/src/core/memory.d index 0a4270557d..fcfc090d17 100644 --- a/src/core/memory.d +++ b/src/core/memory.d @@ -809,3 +809,103 @@ struct GC gc_runFinalizers( segment ); } } + +/** + * Pure variants of C's memory allocation functions `malloc`, `calloc` and + * `realloc`. Purity is achieved via resetting the `errno` to it's value prior + * to being called, removing the function's global state mutation. + * + * See_Also: + * $(LINK2 https://dlang.org/spec/function.html#pure-functions, D's rules for purity), + * which allow for memory allocation under specific circumstances. + */ +void* pureMalloc(size_t size) @trusted pure @nogc nothrow +{ + const errno = fakePureGetErrno(); + void* ret = fakePureMalloc(size); + if (!ret || errno != 0) + { + cast(void)fakePureSetErrno(errno); + } + return ret; +} +/// ditto +void* pureCalloc(size_t nmemb, size_t size) @trusted pure @nogc nothrow +{ + const errno = fakePureGetErrno(); + void* ret = fakePureCalloc(nmemb, size); + if (!ret || errno != 0) + { + cast(void)fakePureSetErrno(errno); + } + return ret; +} +/// ditto +void* pureRealloc(void* ptr, size_t size) pure @nogc nothrow +{ + const errno = fakePureGetErrno(); + void* ret = fakePureRealloc(ptr, size); + if (!ret || errno != 0) + { + cast(void)fakePureSetErrno(errno); + } + return ret; +} + +/// +nothrow @nogc unittest +{ + import core.stdc.stdlib : free; + + ubyte[] fun(size_t n) pure + { + void* p = pureMalloc(n); + p !is null || n == 0 || assert(0); + scope(failure) p = pureRealloc(p, 0); + p = pureRealloc(p, n *= 2); + p !is null || n == 0 || assert(0); + return cast(ubyte[]) p[0 .. n]; + } + + auto buf = fun(100); + assert(buf.length == 200); + free(buf.ptr); +} + +pure @nogc nothrow unittest +{ + const int errno = fakePureGetErrno(); + + void* x = pureMalloc(10); // normal allocation + assert(errno == fakePureGetErrno()); // errno shouldn't change + assert(x !is null); // allocation should succeed + + x = pureRealloc(x, 10); // normal reallocation + assert(errno == fakePureGetErrno()); // errno shouldn't change + assert(x !is null); // allocation should succeed + + fakePureFree(x); + + void* y = pureCalloc(10, 1); // normal zeroed allocation + assert(errno == fakePureGetErrno()); // errno shouldn't change + assert(y !is null); // allocation should succeed + + fakePureFree(y); + + void* z = pureMalloc(size_t.max); // won't affect `errno` + assert(errno == fakePureGetErrno()); // errno shouldn't change + assert(z is null); +} + +// locally purified for internal use here only +extern (C) private pure @system @nogc nothrow +{ + pragma(mangle, "getErrno") int fakePureGetErrno(); + pragma(mangle, "setErrno") int fakePureSetErrno(int); + + pragma(mangle, "malloc") void* fakePureMalloc(size_t); + pragma(mangle, "calloc") void* fakePureCalloc(size_t nmemb, size_t size); + pragma(mangle, "realloc") void* fakePureRealloc(void* ptr, size_t size); + + pragma(mangle, "free") void fakePureFree(void* ptr); // needed by unittests +} From 0fcdfdc89626cdebdf6d098b2c16cac04e20251f Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Mon, 30 Jan 2017 23:59:23 +0100 Subject: [PATCH 27/82] fix pureMalloc test for Win32 --- src/core/memory.d | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/core/memory.d b/src/core/memory.d index fcfc090d17..573ed2e8b2 100644 --- a/src/core/memory.d +++ b/src/core/memory.d @@ -892,7 +892,9 @@ pure @nogc nothrow unittest fakePureFree(y); - void* z = pureMalloc(size_t.max); // won't affect `errno` + // subtract 2 because snn.lib adds 2 unconditionally before passing + // the size to the Windows API + void* z = pureMalloc(size_t.max - 2); // won't affect `errno` assert(errno == fakePureGetErrno()); // errno shouldn't change assert(z is null); } From fb263ad4bdae2399b94e18d631a5387ef33d29cb Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Mon, 6 Feb 2017 16:58:24 -0800 Subject: [PATCH 28/82] make toString() @safe in core.sys.windows.stacktrace --- src/core/sys/windows/stacktrace.d | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/sys/windows/stacktrace.d b/src/core/sys/windows/stacktrace.d index 7695ddc448..1a6925f199 100644 --- a/src/core/sys/windows/stacktrace.d +++ b/src/core/sys/windows/stacktrace.d @@ -87,7 +87,7 @@ public: } - override string toString() const + @trusted override string toString() const { string result; @@ -121,7 +121,7 @@ public: * Returns: * An array of strings with the results. */ - static char[][] resolve(const(ulong)[] addresses) + @trusted static char[][] resolve(const(ulong)[] addresses) { synchronized( typeid(StackTrace) ) { From cad212304db88c4b5bfdce52846393b117885e4f Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Tue, 7 Feb 2017 18:59:17 -0800 Subject: [PATCH 29/82] [scope] add annotations to core.internal.string --- src/core/internal/string.d | 10 +++++----- src/object.d | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/core/internal/string.d b/src/core/internal/string.d index 96f2e580db..28b1e36246 100644 --- a/src/core/internal/string.d +++ b/src/core/internal/string.d @@ -15,7 +15,7 @@ nothrow: alias UnsignedStringBuf = char[20]; -char[] unsignedToTempString(ulong value, char[] buf, uint radix = 10) @safe +char[] unsignedToTempString(ulong value, return char[] buf, uint radix = 10) @safe { size_t i = buf.length; do @@ -69,7 +69,7 @@ unittest alias SignedStringBuf = char[20]; -auto signedToTempString(long value, char[] buf, uint radix) @safe +char[] signedToTempString(long value, return char[] buf, uint radix) @safe { bool neg = value < 0; if(neg) @@ -78,8 +78,8 @@ auto signedToTempString(long value, char[] buf, uint radix) @safe if(neg) { // about to do a slice without a bounds check - auto trustedSlice() @trusted { assert(r.ptr > buf.ptr); return (r.ptr-1)[0..r.length+1]; } - r = trustedSlice(); + auto trustedSlice(return char[] r) @trusted { assert(r.ptr > buf.ptr); return (r.ptr-1)[0..r.length+1]; } + r = trustedSlice(r); r[0] = '-'; } return r; @@ -190,7 +190,7 @@ unittest assert(3.numDigits!2 == 2); } -int dstrcmp( in char[] s1, in char[] s2 ) @trusted +int dstrcmp( scope const char[] s1, scope const char[] s2 ) @trusted { import core.stdc.string : memcmp; diff --git a/src/object.d b/src/object.d index edf6ac42ed..38b6144b3b 100644 --- a/src/object.d +++ b/src/object.d @@ -230,7 +230,7 @@ class TypeInfo { import core.internal.traits : externDFunc; alias dstrcmp = externDFunc!("core.internal.string.dstrcmp", - int function(in char[] s1, in char[] s2) @trusted pure nothrow @nogc); + int function(scope const char[] s1, scope const char[] s2) @trusted pure nothrow @nogc); if (this is o) return 0; @@ -530,7 +530,7 @@ class TypeInfo_StaticArray : TypeInfo { import core.internal.traits : externDFunc; alias sizeToTempString = externDFunc!("core.internal.string.unsignedToTempString", - char[] function(ulong, char[], uint) @safe pure nothrow @nogc); + char[] function(ulong, return char[], uint) @safe pure nothrow @nogc); char[20] tmpBuff = void; return value.toString() ~ "[" ~ sizeToTempString(len, tmpBuff, 10) ~ "]"; @@ -1715,7 +1715,7 @@ class Throwable : Object { import core.internal.traits : externDFunc; alias sizeToTempString = externDFunc!("core.internal.string.unsignedToTempString", - char[] function(ulong, char[], uint) @safe pure nothrow @nogc); + char[] function(ulong, return char[], uint) @safe pure nothrow @nogc); char[20] tmpBuff = void; From 68a31f355afc3d0c9af6151d477a3e2dc0fb7609 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Fri, 10 Feb 2017 02:41:49 -0800 Subject: [PATCH 30/82] add _d_assertp, _d_unittestp, _d_arrayboundsp --- src/core/exception.d | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/core/exception.d b/src/core/exception.d index 701dff2c30..2473e0b747 100644 --- a/src/core/exception.d +++ b/src/core/exception.d @@ -621,9 +621,10 @@ extern (C) /* One of these three is called upon an assert() fail. */ - void _d_assertm(immutable(ModuleInfo)* m, uint line) + void _d_assertp(immutable(char)* file, uint line) { - onAssertError(m.name, line); + import core.stdc.string : strlen; + onAssertError(file[0 .. strlen(file)], line); } void _d_assert_msg(string msg, string file, uint line) @@ -638,9 +639,10 @@ extern (C) /* One of these three is called upon an assert() fail inside of a unittest block */ - void _d_unittestm(immutable(ModuleInfo)* m, uint line) + void _d_unittestp(immutable(char)* file, uint line) { - _d_unittest(m.name, line); + import core.stdc.string : strlen; + _d_unittest(file[0 .. strlen(file)], line); } void _d_unittest_msg(string msg, string file, uint line) @@ -655,9 +657,10 @@ extern (C) /* Called when an array index is out of bounds */ - void _d_array_bounds(immutable(ModuleInfo)* m, uint line) + void _d_arrayboundsp(immutable(char*) file, uint line) { - onRangeError(m.name, line); + import core.stdc.string : strlen; + onRangeError(file[0 .. strlen(file)], line); } void _d_arraybounds(string file, uint line) From ca68ae46c5597e3f2a33ebb5cac52ea1e12ce2be Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Sun, 12 Feb 2017 01:29:28 -0800 Subject: [PATCH 31/82] line_trace.exp: make more resistant to 'scope' changes --- test/exceptions/Makefile | 2 +- test/exceptions/line_trace.exp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/exceptions/Makefile b/test/exceptions/Makefile index 3c651d846a..5aa22b2631 100644 --- a/test/exceptions/Makefile +++ b/test/exceptions/Makefile @@ -17,7 +17,7 @@ all: $(addprefix $(ROOT)/,$(addsuffix .done,$(TESTS))) $(ROOT)/line_trace.done: $(ROOT)/line_trace @echo Testing line_trace $(QUIET)$(TIMELIMIT)$(ROOT)/line_trace $(RUN_ARGS) > $(ROOT)/line_trace.output - $(QUIET)$(SED) "s/\[0x[0-9a-f]*\]/\[ADDR\]/g" $(ROOT)/line_trace.output | $(DIFF) line_trace.exp - + $(QUIET)$(SED) "s/\[0x[0-9a-f]*\]/\[ADDR\]/g; s/scope //g; s/Nl//g" $(ROOT)/line_trace.output | $(DIFF) line_trace.exp - @rm -f $(ROOT)/line_trace.output @touch $@ diff --git a/test/exceptions/line_trace.exp b/test/exceptions/line_trace.exp index bec4cab697..c0909b653b 100644 --- a/test/exceptions/line_trace.exp +++ b/test/exceptions/line_trace.exp @@ -3,7 +3,7 @@ object.Exception@src/line_trace.d(17): exception src/line_trace.d:17 void line_trace.f1() [ADDR] src/line_trace.d:5 _Dmain [ADDR] src/rt/dmain2.d:472 _D2rt6dmain211_d_run_mainUiPPaPUAAaZiZ6runAllMFZ9__lambda1MFZv [ADDR] -src/rt/dmain2.d:447 void rt.dmain2._d_run_main(int, char**, extern (C) int function(char[][])*).tryExec(scope void delegate()) [ADDR] +src/rt/dmain2.d:447 void rt.dmain2._d_run_main(int, char**, extern (C) int function(char[][])*).tryExec(void delegate()) [ADDR] src/rt/dmain2.d:472 void rt.dmain2._d_run_main(int, char**, extern (C) int function(char[][])*).runAll() [ADDR] -src/rt/dmain2.d:447 void rt.dmain2._d_run_main(int, char**, extern (C) int function(char[][])*).tryExec(scope void delegate()) [ADDR] +src/rt/dmain2.d:447 void rt.dmain2._d_run_main(int, char**, extern (C) int function(char[][])*).tryExec(void delegate()) [ADDR] src/rt/dmain2.d:480 _d_run_main [ADDR] From 2a6e5b01feb98c4b6f76aa76d69f1e98ebda58bc Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Sun, 12 Feb 2017 11:50:06 +0100 Subject: [PATCH 32/82] scan DATA and TLS according to compiler generated pointer infos --- src/rt/minit.asm | 38 ++++++++++++++++++++++---- src/rt/minit.obj | Bin 317 -> 484 bytes src/rt/sections_win32.d | 59 +++++++++++++++++++++++++++++++++------- 3 files changed, 82 insertions(+), 15 deletions(-) diff --git a/src/rt/minit.asm b/src/rt/minit.asm index 72bd5d868c..a932442545 100644 --- a/src/rt/minit.asm +++ b/src/rt/minit.asm @@ -10,7 +10,9 @@ ; (See accompanying file LICENSE or copy at ; http://www.boost.org/LICENSE_1_0.txt) ; -include macros.asm +;include macros.asm + + .model FLAT ifdef _WIN32 DATAGRP EQU FLAT @@ -61,7 +63,34 @@ XOE ends DGROUP group FMB,FM,FME - begcode minit +; These segments bracket DP, which contains the _DATA pointer references + public __DPbegin, __DPend +DPB segment dword use32 public 'DATA' +__DPbegin: +DPB ends +DP segment dword use32 public 'DATA' +DP ends +DPE segment dword use32 public 'DATA' +__DPend: +DPE ends + +DGROUP group DPB,DP,DPE + +; These segments bracket TP, which contains the TLS pointer references + public __TPbegin, __TPend +TPB segment dword use32 public 'DATA' +__TPbegin: +TPB ends +TP segment dword use32 public 'DATA' +TP ends +TPE segment dword use32 public 'DATA' +__TPend: +TPE ends + +DGROUP group TPB,TP,TPE + +_TEXT segment para use32 public 'CODE' + assume CS:_TEXT ; extern (C) void _minit(); ; Converts array of ModuleInfo pointers to a D dynamic array of them, @@ -70,7 +99,7 @@ DGROUP group FMB,FM,FME ; extern (C) ModuleInfo[] _moduleinfo_array; public __minit -__minit proc near +__minit: mov EDX,offset DATAGRP:FMB mov EAX,offset DATAGRP:FME mov dword ptr __moduleinfo_array+4,EDX @@ -78,8 +107,7 @@ __minit proc near shr EAX,2 ; convert to array length mov dword ptr __moduleinfo_array,EAX ret -__minit endp - endcode minit +_TEXT ends end diff --git a/src/rt/minit.obj b/src/rt/minit.obj index 67225d9b945cd67c9e77ca96baf700a5aa3446e6..fde08d4999199a9e151600dde13b63f15454ecee 100644 GIT binary patch literal 484 zcmX|;y>1gh5XWcs?rfjG5^ilbDe?f3EJZwlk2|Nq@_`r062;2MPIQuemVzSzRmyx7 zE}}TH;>4JWmI~+q@c^_4DH3wQ3(#gWn~gHX%9#uQ92Y=2401F}} zA}fe|tKRTwhBQMgN47+>%UYu+X zWoLJ{^A@hh9_VtVO!oTy-kTAH<8cvKE-hsc^^z`$pW{_vF6{)-tKLqWkovDxo|Je{ zfAv|B&cyxMClZJx?tX!e-W}Kg3;Z?DK$;@ev-vt8z*o(mbvrE63T%A;_K$tg`A2nD Yh9#DmwM>fzmlbN8M+{(e3v>>30RR91 literal 317 zcmZn=Vh|`UN{%TiiOJ2(%Pi4LEY5u~&4Ph}&BZ;)KQw^J&6g>{pV`gV35Z>poq~gz zBmA9!*pEv!oUJ$F)(nlgJm>$oA5U~S9bc%vV?L!A&Ff9hL4r|VpWO%|T!o>K5O@xX036BsHBhVm* PCt_kujQU+n3=Aaztd&av diff --git a/src/rt/sections_win32.d b/src/rt/sections_win32.d index ca6d3d04e3..0c09b5cd0b 100644 --- a/src/rt/sections_win32.d +++ b/src/rt/sections_win32.d @@ -18,6 +18,8 @@ version(CRuntime_DigitalMars): debug(PRINTF) import core.stdc.stdio; import rt.minfo; +//version = conservative; + struct SectionGroup { static int opApply(scope int delegate(ref SectionGroup) dg) @@ -47,25 +49,48 @@ struct SectionGroup private: ModuleGroup _moduleGroup; - void[][2] _gcRanges; + version(conservative) + void[][2] _gcRanges; + else + void[][] _gcRanges; } void initSections() nothrow @nogc { _sections._moduleGroup = ModuleGroup(getModuleInfos()); - auto databeg = cast(void*)&_xi_a; - auto dataend = cast(void*)_moduleinfo_array.ptr; - _sections._gcRanges[0] = databeg[0 .. dataend - databeg]; - - // skip module info and CONST segment - auto bssbeg = cast(void*)&_edata; - auto bssend = cast(void*)&_end; - _sections._gcRanges[1] = bssbeg[0 .. bssend - bssbeg]; + version(conservative) + { + auto databeg = cast(void*)&_xi_a; + auto dataend = cast(void*)_moduleinfo_array.ptr; + _sections._gcRanges[0] = databeg[0 .. dataend - databeg]; + + // skip module info and CONST segment + auto bssbeg = cast(void*)&_edata; + auto bssend = cast(void*)&_end; + _sections._gcRanges[1] = bssbeg[0 .. bssend - bssbeg]; + } + else + { + import core.stdc.stdlib : malloc; + + size_t count = &_DPend - &_DPbegin; + auto ranges = cast(void[]*) malloc(count * (void[]).sizeof); + for (size_t i = 0; i < count; i++) + { + void* addr = (&_DPbegin)[i]; + ranges[i] = (cast(void**)addr)[0..1]; // TODO: optimize consecutive pointers into single range + } + _sections._gcRanges = ranges[0..count]; + } } void finiSections() nothrow @nogc { + import core.stdc.stdlib : free; + + version(conservative) {} else + free(_sections._gcRanges.ptr); } void[] initTLSRanges() nothrow @nogc @@ -81,7 +106,16 @@ void finiTLSRanges(void[] rng) nothrow @nogc void scanTLSRanges(void[] rng, scope void delegate(void* pbeg, void* pend) nothrow dg) nothrow { - dg(rng.ptr, rng.ptr + rng.length); + version(conservative) + { + dg(rng.ptr, rng.ptr + rng.length); + } + else + { + size_t count = &_TPend - &_TPbegin; + for (auto p = &_TPbegin; p < &_TPend; p++) + dg(rng.ptr + *p, rng.ptr + *p + (void*).sizeof); + } } private: @@ -112,6 +146,11 @@ extern(C) int _xi_a; // &_xi_a just happens to be start of data segment int _edata; // &_edata is start of BSS segment int _end; // &_end is past end of BSS + + void* _DPbegin; // first entry in the array of pointers addresses + void* _DPend; // &_DPend points after last entry of array + uint _TPbegin; // first entry in the array of TLS offsets of pointers + uint _TPend; // &_DPend points after last entry of array } extern From 2d38937e3ff6597a143e83cf2d2d38c76b117d56 Mon Sep 17 00:00:00 2001 From: Nemanja Boric <4burgos@gmail.com> Date: Wed, 19 Oct 2016 21:02:08 +0200 Subject: [PATCH 33/82] Fix issue 16470: Segfault with negative array length If the array length is too large, and the element size small enough, the overflow might go undetected in the check while multiplying array size and element size, but it can later manifest when adding padding, etc. https://issues.dlang.org/show_bug.cgi?id=16470 --- src/rt/lifetime.d | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/src/rt/lifetime.d b/src/rt/lifetime.d index 03df8d31a4..1b763ab0cf 100644 --- a/src/rt/lifetime.d +++ b/src/rt/lifetime.d @@ -274,9 +274,17 @@ bool __setArrayAllocLength(ref BlkInfo info, size_t newlength, bool isshared, co if(info.size <= 256) { - if(newlength + SMALLPAD + typeInfoSize > info.size) + import core.checkedint; + + bool overflow; + auto newlength_padded = addu(newlength, + addu(SMALLPAD, typeInfoSize, overflow), + overflow); + + if(newlength_padded > info.size || overflow) // new size does not fit inside block return false; + auto length = cast(ubyte *)(info.base + info.size - typeInfoSize - SMALLPAD); if(oldlength != ~0) { @@ -406,24 +414,38 @@ size_t __arrayPad(size_t size, const TypeInfo tinext) nothrow pure @trusted */ BlkInfo __arrayAlloc(size_t arrsize, const TypeInfo ti, const TypeInfo tinext) nothrow pure { + import core.checkedint; + size_t typeInfoSize = structTypeInfoSize(tinext); size_t padsize = arrsize > MAXMEDSIZE ? LARGEPAD : ((arrsize > MAXSMALLSIZE ? MEDPAD : SMALLPAD) + typeInfoSize); - if (arrsize + padsize < arrsize) + bool overflow; + auto padded_size = addu(arrsize, padsize, overflow); + + if (overflow) return BlkInfo(); uint attr = (!(tinext.flags & 1) ? BlkAttr.NO_SCAN : 0) | BlkAttr.APPENDABLE; if (typeInfoSize) attr |= BlkAttr.STRUCTFINAL | BlkAttr.FINALIZE; - return GC.qalloc(arrsize + padsize, attr, ti); + return GC.qalloc(padded_size, attr, ti); } BlkInfo __arrayAlloc(size_t arrsize, ref BlkInfo info, const TypeInfo ti, const TypeInfo tinext) { + import core.checkedint; + if (!info.base) return __arrayAlloc(arrsize, ti, tinext); - return GC.qalloc(arrsize + __arrayPad(arrsize, tinext), info.attr, ti); + bool overflow; + auto padded_size = addu(arrsize, __arrayPad(arrsize, tinext), overflow); + if (overflow) + { + return BlkInfo(); + } + + return GC.qalloc(padded_size, info.attr, ti); } /** From 0de554a84091fb7094d46508c415dab66eb9b86e Mon Sep 17 00:00:00 2001 From: Nemanja Boric <4burgos@gmail.com> Date: Wed, 19 Oct 2016 21:34:40 +0200 Subject: [PATCH 34/82] Check if the array allocation succeded --- src/rt/lifetime.d | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/rt/lifetime.d b/src/rt/lifetime.d index 1b763ab0cf..fb6e07474f 100644 --- a/src/rt/lifetime.d +++ b/src/rt/lifetime.d @@ -1570,6 +1570,10 @@ body { info = __arrayAlloc(newsize, ti, tinext); } + + if (info.base is null) + goto Loverflow; + __setArrayAllocLength(info, newsize, isshared, tinext); if(!isshared) __insertBlkInfoCache(info, bic); @@ -1587,6 +1591,8 @@ body { // pointer was null, need to allocate auto info = __arrayAlloc(newsize, ti, tinext); + if (info.base is null) + goto Loverflow; __setArrayAllocLength(info, newsize, isshared, tinext); if(!isshared) __insertBlkInfoCache(info, null); From f1ce9d8bc085f83761150ac83ed6e0373e516f77 Mon Sep 17 00:00:00 2001 From: Nemanja Boric <4burgos@gmail.com> Date: Wed, 19 Oct 2016 21:51:43 +0200 Subject: [PATCH 35/82] Add tests for "Out of memory exception" --- posix.mak | 2 +- test/allocations/Makefile | 23 +++++++++++++++++++ test/allocations/src/overflow_from_existing.d | 6 +++++ test/allocations/src/overflow_from_zero.d | 6 +++++ 4 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 test/allocations/Makefile create mode 100644 test/allocations/src/overflow_from_existing.d create mode 100644 test/allocations/src/overflow_from_zero.d diff --git a/posix.mak b/posix.mak index ec31bb0d5e..024cc4a9e6 100644 --- a/posix.mak +++ b/posix.mak @@ -197,7 +197,7 @@ $(DRUNTIME): $(OBJS) $(SRCS) UT_MODULES:=$(patsubst src/%.d,$(ROOT)/unittest/%,$(SRCS)) HAS_ADDITIONAL_TESTS:=$(shell test -d test && echo 1) ifeq ($(HAS_ADDITIONAL_TESTS),1) - ADDITIONAL_TESTS:=test/init_fini test/exceptions test/coverage test/profile test/cycles + ADDITIONAL_TESTS:=test/init_fini test/exceptions test/coverage test/profile test/cycles test/allocations ADDITIONAL_TESTS+=$(if $(SHARED),test/shared,) endif diff --git a/test/allocations/Makefile b/test/allocations/Makefile new file mode 100644 index 0000000000..aea249be58 --- /dev/null +++ b/test/allocations/Makefile @@ -0,0 +1,23 @@ +include ../common.mak + +TESTS:=overflow_from_zero overflow_from_existing + +DIFF:=diff +SED:=sed + +.PHONY: all clean +all: $(addprefix $(ROOT)/,$(addsuffix .done,$(TESTS))) + +$(ROOT)/overflow_from_zero.done: STDERR_EXP="Memory allocation failed" +$(ROOT)/overflow_from_existing.done: STDERR_EXP="Memory allocation failed" +$(ROOT)/%.done: $(ROOT)/% + @echo Testing $* + $(NEGATE) $(QUIET)$(TIMELIMIT)$(ROOT)/$* $(RUN_ARGS) 2>&1 1>/dev/null | head -n 1 | grep -qF $(STDERR_EXP) + @touch $@ + +$(ROOT)/unittest_assert: DFLAGS+=-unittest +$(ROOT)/%: $(SRC)/%.d + $(QUIET)$(DMD) $(DFLAGS) -of$@ $< + +clean: + rm -rf $(GENERATED) diff --git a/test/allocations/src/overflow_from_existing.d b/test/allocations/src/overflow_from_existing.d new file mode 100644 index 0000000000..bbe84434a1 --- /dev/null +++ b/test/allocations/src/overflow_from_existing.d @@ -0,0 +1,6 @@ +void main() +{ + void[] buffer; + buffer.length = 1; + buffer.length = size_t.max; +} diff --git a/test/allocations/src/overflow_from_zero.d b/test/allocations/src/overflow_from_zero.d new file mode 100644 index 0000000000..31f8a1753a --- /dev/null +++ b/test/allocations/src/overflow_from_zero.d @@ -0,0 +1,6 @@ +void main() +{ + void[] buffer; + buffer.length = 0; + buffer.length = size_t.max; +} From fe160cb22d035f21f5bb39ec86553728bec45f91 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Sat, 21 Jan 2017 18:57:13 -0800 Subject: [PATCH 36/82] core.stdc.stdlib: annotate with 'scope' --- src/core/stdc/stdlib.d | 58 +++++++++++++++++++++--------------------- src/rt/profilegc.d | 2 +- src/rt/qsort.d | 28 ++++++++++---------- src/rt/trace.d | 4 +-- 4 files changed, 46 insertions(+), 46 deletions(-) diff --git a/src/core/stdc/stdlib.d b/src/core/stdc/stdlib.d index 9348c7d107..01b3722c9b 100644 --- a/src/core/stdc/stdlib.d +++ b/src/core/stdc/stdlib.d @@ -32,11 +32,11 @@ extern (C): /* Placed outside @nogc in order to not constrain what the callback does. */ /// -alias int function(in void*, in void*) _compare_fp_t; +alias int function(scope const void*, scope const void*) _compare_fp_t; /// -void* bsearch(in void* key, in void* base, size_t nmemb, size_t size, _compare_fp_t compar); +inout(void)* bsearch(scope const void* key, scope inout(void)* base, size_t nmemb, size_t size, _compare_fp_t compar); /// -void qsort(void* base, size_t nmemb, size_t size, _compare_fp_t compar); +void qsort(scope void* base, size_t nmemb, size_t size, _compare_fp_t compar); nothrow: @@ -81,32 +81,32 @@ else version(CRuntime_Bionic) enum RAND_MAX = 0x7fffffff; else static assert( false, "Unsupported platform" ); /// -double atof(in char* nptr); +double atof(scope const char* nptr); /// -int atoi(in char* nptr); +int atoi(scope const char* nptr); /// -c_long atol(in char* nptr); +c_long atol(scope const char* nptr); /// -long atoll(in char* nptr); +long atoll(scope const char* nptr); /// -double strtod(in char* nptr, char** endptr); +double strtod(scope inout(char)* nptr, scope inout(char)** endptr); /// -float strtof(in char* nptr, char** endptr); +float strtof(scope inout(char)* nptr, scope inout(char)** endptr); /// -c_long strtol(in char* nptr, char** endptr, int base); +c_long strtol(scope inout(char)* nptr, scope inout(char)** endptr, int base); /// -long strtoll(in char* nptr, char** endptr, int base); +long strtoll(scope inout(char)* nptr, scope inout(char)** endptr, int base); /// -c_ulong strtoul(in char* nptr, char** endptr, int base); +c_ulong strtoul(scope inout(char)* nptr, scope inout(char)** endptr, int base); /// -ulong strtoull(in char* nptr, char** endptr, int base); +ulong strtoull(scope inout(char)* nptr, scope inout(char)** endptr, int base); version (CRuntime_Microsoft) { - // strtold exists starting from VS2013, so we make this a template to avoid link errors + // strtold exists starting from VS2013, so we give it D linkage to avoid link errors /// - real strtold()(in char* nptr, char** endptr) + extern (D) real strtold(scope inout(char)* nptr, inout(char)** endptr) { // Fake it 'till we make it return strtod(nptr, endptr); } @@ -114,14 +114,14 @@ version (CRuntime_Microsoft) else version (MinGW) { /// - real __mingw_strtold(in char* nptr, char** endptr); + real __mingw_strtold(scope inout(char)* nptr, scope inout(char)** endptr); /// alias __mingw_strtold strtold; } else version (CRuntime_Bionic) { /// - real strtold(in char* nptr, char** endptr) + real strtold(scope inout(char)* nptr, scope inout(char)** endptr) { // Fake it again till we make it return strtod(nptr, endptr); } @@ -129,7 +129,7 @@ else version (CRuntime_Bionic) else { /// - real strtold(in char* nptr, char** endptr); + real strtold(scope inout(char)* nptr, scope inout(char)** endptr); } // No unsafe pointer manipulation. @@ -175,9 +175,9 @@ int atexit(void function() func); void _Exit(int status); /// -char* getenv(in char* name); +char* getenv(scope const char* name); /// -int system(in char* string); +int system(scope const char* string); // These only operate on integer values. @trusted @@ -198,15 +198,15 @@ int system(in char* string); } /// -int mblen(in char* s, size_t n); +int mblen(scope const char* s, size_t n); /// -int mbtowc(wchar_t* pwc, in char* s, size_t n); +int mbtowc(scope wchar_t* pwc, scope const char* s, size_t n); /// -int wctomb(char*s, wchar_t wc); +int wctomb(scope char* s, wchar_t wc); /// -size_t mbstowcs(wchar_t* pwcs, in char* s, size_t n); +size_t mbstowcs(scope wchar_t* pwcs, scope const char* s, size_t n); /// -size_t wcstombs(char* s, in wchar_t* pwcs, size_t n); +size_t wcstombs(scope char* s, scope const wchar_t* pwcs, size_t n); /// version( DigitalMars ) @@ -222,12 +222,12 @@ else version( GNU ) version( CRuntime_Microsoft ) { /// - ulong _strtoui64(in char *,char **,int); + ulong _strtoui64(scope inout(char)*, scope inout(char)**,int); /// - ulong _wcstoui64(in wchar *,wchar **,int); + ulong _wcstoui64(scope inout(wchar)*, scope inout(wchar)**,int); /// - long _strtoi64(in char *,char **,int); + long _strtoi64(scope inout(char)*, scope inout(char)**,int); /// - long _wcstoi64(in wchar *,wchar **,int); + long _wcstoi64(scope inout(wchar)*, scope inout(wchar)**,int); } diff --git a/src/rt/profilegc.d b/src/rt/profilegc.d index f750808892..a3c5ce6235 100644 --- a/src/rt/profilegc.d +++ b/src/rt/profilegc.d @@ -117,7 +117,7 @@ shared static ~this() Entry entry; // qsort() comparator to sort by count field - extern (C) static int qsort_cmp(const void *r1, const void *r2) + extern (C) static int qsort_cmp(scope const void *r1, scope const void *r2) { auto result1 = cast(Result*)r1; auto result2 = cast(Result*)r2; diff --git a/src/rt/qsort.d b/src/rt/qsort.d index 80b1e2fcce..6c3e71c35c 100644 --- a/src/rt/qsort.d +++ b/src/rt/qsort.d @@ -29,12 +29,12 @@ else version (WatchOS) version (CRuntime_Glibc) { - alias extern (C) int function(const void *, const void *, void *) Cmp; - extern (C) void qsort_r(void *base, size_t nmemb, size_t size, Cmp cmp, void *arg); + alias extern (C) int function(scope const void *, scope const void *, scope void *) Cmp; + extern (C) void qsort_r(scope void *base, size_t nmemb, size_t size, Cmp cmp, scope void *arg); - extern (C) void[] _adSort(void[] a, TypeInfo ti) + extern (C) void[] _adSort(return scope void[] a, TypeInfo ti) { - extern (C) int cmp(in void* p1, in void* p2, void* ti) + extern (C) int cmp(scope const void* p1, scope const void* p2, scope void* ti) { return (cast(TypeInfo)ti).compare(p1, p2); } @@ -44,12 +44,12 @@ version (CRuntime_Glibc) } else version (FreeBSD) { - alias extern (C) int function(void *, const void *, const void *) Cmp; - extern (C) void qsort_r(void *base, size_t nmemb, size_t size, void *thunk, Cmp cmp); + alias extern (C) int function(scope void *, scope const void *, scope const void *) Cmp; + extern (C) void qsort_r(scope void *base, size_t nmemb, size_t size, scope void *thunk, Cmp cmp); - extern (C) void[] _adSort(void[] a, TypeInfo ti) + extern (C) void[] _adSort(return scope void[] a, TypeInfo ti) { - extern (C) int cmp(void* ti, in void* p1, in void* p2) + extern (C) int cmp(scope void* ti, scope const void* p1, scope const void* p2) { return (cast(TypeInfo)ti).compare(p1, p2); } @@ -59,12 +59,12 @@ else version (FreeBSD) } else version (Darwin) { - alias extern (C) int function(void *, const void *, const void *) Cmp; - extern (C) void qsort_r(void *base, size_t nmemb, size_t size, void *thunk, Cmp cmp); + alias extern (C) int function(scope void *, scope const void *, scope const void *) Cmp; + extern (C) void qsort_r(scope void *base, size_t nmemb, size_t size, scope void *thunk, Cmp cmp); - extern (C) void[] _adSort(void[] a, TypeInfo ti) + extern (C) void[] _adSort(return scope void[] a, TypeInfo ti) { - extern (C) int cmp(void* ti, in void* p1, in void* p2) + extern (C) int cmp(scope void* ti, scope const void* p1, scope const void* p2) { return (cast(TypeInfo)ti).compare(p1, p2); } @@ -76,9 +76,9 @@ else { private TypeInfo tiglobal; - extern (C) void[] _adSort(void[] a, TypeInfo ti) + extern (C) void[] _adSort(return scope void[] a, TypeInfo ti) { - extern (C) int cmp(in void* p1, in void* p2) + extern (C) int cmp(scope const void* p1, scope const void* p2) { return tiglobal.compare(p1, p2); } diff --git a/src/rt/trace.d b/src/rt/trace.d index e21997e70d..07fd333cd0 100644 --- a/src/rt/trace.d +++ b/src/rt/trace.d @@ -156,7 +156,7 @@ private void stack_free(Stack *s) ////////////////////////////////////// // Qsort() comparison routine for array of pointers to SymPair's. -private int sympair_cmp(in void* e1, in void* e2) +private int sympair_cmp(scope const void* e1, scope const void* e2) { auto count1 = (*cast(SymPair**)e1).count; auto count2 = (*cast(SymPair**)e2).count; @@ -271,7 +271,7 @@ private void trace_array(Symbol*[] psymbols, Symbol *s, ref uint u) ////////////////////////////////////// // Qsort() comparison routine for array of pointers to Symbol's. -private int symbol_cmp(in void* e1, in void* e2) +private int symbol_cmp(scope const void* e1, scope const void* e2) { auto ps1 = cast(Symbol **)e1; auto ps2 = cast(Symbol **)e2; From b947d44a6f2050a32261b3dfac96d5b5ad7578a5 Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Mon, 13 Feb 2017 12:08:47 +0100 Subject: [PATCH 37/82] implement precise scan DATA and TLS for MS-COFF builds --- src/rt/sections_win64.d | 46 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/src/rt/sections_win64.d b/src/rt/sections_win64.d index 834e9048d7..f7f1d0ecc7 100644 --- a/src/rt/sections_win64.d +++ b/src/rt/sections_win64.d @@ -19,6 +19,8 @@ debug(PRINTF) import core.stdc.stdio; import core.stdc.stdlib : malloc, free; import rt.deh, rt.minfo; +//version = conservative; + struct SectionGroup { static int opApply(scope int delegate(ref SectionGroup) dg) @@ -56,7 +58,10 @@ struct SectionGroup private: ModuleGroup _moduleGroup; - void[][1] _gcRanges; + version(conservative) + void[][1] _gcRanges; + else + void[][] _gcRanges; } void initSections() nothrow @nogc @@ -64,14 +69,31 @@ void initSections() nothrow @nogc _sections._moduleGroup = ModuleGroup(getModuleInfos()); // the ".data" image section includes both object file sections ".data" and ".bss" - _sections._gcRanges[0] = findImageSection(".data"); - debug(PRINTF) printf("found .data section: [%p,+%llx]\n", _sections._gcRanges[0].ptr, - cast(ulong)_sections._gcRanges[0].length); + void[] dataSection = findImageSection(".data"); + debug(PRINTF) printf("found .data section: [%p,+%llx]\n", dataSection.ptr, + cast(ulong)dataSection.length); + version(conservative) + { + _sections._gcRanges[0] = dataSection; + } + else + { + size_t count = &_DP_end - &_DP_beg; + auto ranges = cast(void[]*) malloc(count * (void[]).sizeof); + for (size_t i = 0; i < count; i++) + { + void* addr = dataSection.ptr + (&_DP_beg)[i]; + ranges[i] = (cast(void**)addr)[0..1]; // TODO: optimize consecutive pointers into single range + } + _sections._gcRanges = ranges[0..count]; + } } void finiSections() nothrow @nogc { .free(cast(void*)_sections.modules.ptr); + version(conservative) {} else + .free(_sections._gcRanges.ptr); } void[] initTLSRanges() nothrow @nogc @@ -87,7 +109,16 @@ void finiTLSRanges(void[] rng) nothrow @nogc void scanTLSRanges(void[] rng, scope void delegate(void* pbeg, void* pend) nothrow dg) nothrow { - dg(rng.ptr, rng.ptr + rng.length); + version(conservative) + { + dg(rng.ptr, rng.ptr + rng.length); + } + else + { + size_t count = &_TP_end - &_TP_beg; + for (auto p = &_TP_beg; p < &_TP_end; p++) + dg(rng.ptr + *p, rng.ptr + *p + (void*).sizeof); + } } private: @@ -142,6 +173,11 @@ extern(C) void* _deh_beg; void* _deh_end; + + uint _DP_beg; + uint _DP_end; + uint _TP_beg; + uint _TP_end; } extern From d198b68d97d8044f4690ae72b15af47624d040a3 Mon Sep 17 00:00:00 2001 From: Sebastian Wilzbach Date: Sun, 25 Dec 2016 09:51:50 +0100 Subject: [PATCH 38/82] CircleCi: use master as fallback for DMD --- circle.yml | 1 + circleci.sh | 26 ++++++++++++++++++++------ 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/circle.yml b/circle.yml index 5977d59a63..75ce6ddb19 100644 --- a/circle.yml +++ b/circle.yml @@ -7,6 +7,7 @@ dependencies: test: override: - make -f posix.mak style + - ./circleci.sh setup-repos - ./circleci.sh coverage: parallel: true timeout: 1200 diff --git a/circleci.sh b/circleci.sh index ca85a114ce..198d47de33 100755 --- a/circleci.sh +++ b/circleci.sh @@ -19,7 +19,8 @@ install_deps() { fi for i in {0..4}; do - if curl -fsS -A "$CURL_USER_AGENT" --max-time 5 https://dlang.org/install.sh -O; then + if curl -fsS -A "$CURL_USER_AGENT" --max-time 5 https://dlang.org/install.sh -O || + curl -fsS -A "$CURL_USER_AGENT" --max-time 5 https://nightlies.dlang.org/install.sh -O ; then break elif [ $i -ge 4 ]; then sleep $((1 << $i)) @@ -51,12 +52,15 @@ clone() { done } -coverage() { +setup_repos() { + # set a default in case we run into rate limit restrictions + local base_branch="" if [ -n "${CIRCLE_PR_NUMBER:-}" ]; then - local base_branch=$(curl -fsSL https://api.github.com/repos/dlang/$CIRCLE_PROJECT_REPONAME/pulls/$CIRCLE_PR_NUMBER | jq -r '.base.ref') + base_branch=$((curl -fsSL https://api.github.com/repos/dlang/$CIRCLE_PROJECT_REPONAME/pulls/$CIRCLE_PR_NUMBER || echo) | jq -r '.base.ref') else - local base_branch=$CIRCLE_BRANCH + base_branch=$CIRCLE_BRANCH fi + base_branch=${base_branch:-"master"} # merge upstream branch with changes, s.t. we check with the latest changes if [ -n "${CIRCLE_PR_NUMBER:-}" ]; then @@ -69,9 +73,18 @@ coverage() { git merge -m "Automatic merge" $current_branch fi + for proj in dmd ; do + if [ $base_branch != master ] && [ $base_branch != stable ] && + ! git ls-remote --exit-code --heads https://github.com/dlang/$proj.git $base_branch > /dev/null; then + # use master as fallback for other repos to test feature branches + clone https://github.com/dlang/$proj.git ../$proj master --depth 1 + else + clone https://github.com/dlang/$proj.git ../$proj $base_branch --depth 1 + fi + done +} - clone https://github.com/dlang/dmd.git ../dmd $base_branch --depth 1 - +coverage() { # load environment for bootstrap compiler source "$(CURL_USER_AGENT=\"$CURL_USER_AGENT\" bash ~/dlang/install.sh dmd-$HOST_DMD_VER --activate)" @@ -83,5 +96,6 @@ coverage() { case $1 in install-deps) install_deps ;; + setup-repos) setup_repos ;; coverage) coverage ;; esac From 71b8a6f5b75413801466cdc06d300ad1fd8a85c4 Mon Sep 17 00:00:00 2001 From: Sebastian Wilzbach Date: Thu, 16 Feb 2017 14:47:08 +0100 Subject: [PATCH 39/82] Set bootstrap DMD version to 2.072.2 --- circleci.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/circleci.sh b/circleci.sh index 198d47de33..4780a521aa 100755 --- a/circleci.sh +++ b/circleci.sh @@ -2,7 +2,7 @@ set -uexo pipefail -HOST_DMD_VER=2.068.2 # same as in dmd/src/posix.mak +HOST_DMD_VER=2.072.2 # same as in dmd/src/posix.mak CURL_USER_AGENT="CirleCI $(curl --version | head -n 1)" N=2 CIRCLE_NODE_INDEX=${CIRCLE_NODE_INDEX:-0} From 190001d27b381b0cde77fe95d6b499a0c39d4b7f Mon Sep 17 00:00:00 2001 From: Sebastian Wilzbach Date: Thu, 16 Feb 2017 15:25:24 +0100 Subject: [PATCH 40/82] Add fallback for CodeCov --- circle.yml | 4 +--- circleci.sh | 49 +++++++++++++++++++++++++++++++++---------------- 2 files changed, 34 insertions(+), 19 deletions(-) diff --git a/circle.yml b/circle.yml index 75ce6ddb19..1f6682064d 100644 --- a/circle.yml +++ b/circle.yml @@ -13,6 +13,4 @@ test: timeout: 1200 post: - # CodeCov gets confused by stored .lst files - - rm -rf test/coverage/generated - - bash <(curl -s https://codecov.io/bash) + - ./circleci.sh codecov diff --git a/circleci.sh b/circleci.sh index 4780a521aa..d20cad3df8 100755 --- a/circleci.sh +++ b/circleci.sh @@ -6,29 +6,37 @@ HOST_DMD_VER=2.072.2 # same as in dmd/src/posix.mak CURL_USER_AGENT="CirleCI $(curl --version | head -n 1)" N=2 CIRCLE_NODE_INDEX=${CIRCLE_NODE_INDEX:-0} +CIRCLE_PROJECT_REPONAME=${CIRCLE_PROJECT_REPONAME:-druntime} case $CIRCLE_NODE_INDEX in 0) MODEL=64 ;; 1) MODEL=32 ;; esac -install_deps() { - if [ $MODEL -eq 32 ]; then - sudo apt-get update - sudo apt-get install g++-multilib - fi - +download() { + local url="$1" + local fallbackurl="$2" + local outputfile="$3" for i in {0..4}; do - if curl -fsS -A "$CURL_USER_AGENT" --max-time 5 https://dlang.org/install.sh -O || - curl -fsS -A "$CURL_USER_AGENT" --max-time 5 https://nightlies.dlang.org/install.sh -O ; then + if curl -fsS -A "$CURL_USER_AGENT" --max-time 5 "$url" -o "$outputfile" || + curl -fsS -A "$CURL_USER_AGENT" --max-time 5 "$fallbackurl" -o "$outputfile" ; then break elif [ $i -ge 4 ]; then sleep $((1 << $i)) else - echo 'Failed to download install script' 1>&2 + echo "Failed to download script ${outputfile}" 1>&2 exit 1 fi done +} + +install_deps() { + if [ $MODEL -eq 32 ]; then + sudo apt-get update + sudo apt-get install g++-multilib + fi + + download "https://dlang.org/install.sh" "https://nightlies.dlang.org/install.sh" "install.sh" source "$(CURL_USER_AGENT=\"$CURL_USER_AGENT\" bash install.sh dmd-$HOST_DMD_VER --activate)" $DC --version @@ -64,13 +72,13 @@ setup_repos() { # merge upstream branch with changes, s.t. we check with the latest changes if [ -n "${CIRCLE_PR_NUMBER:-}" ]; then - local current_branch=$(git rev-parse --abbrev-ref HEAD) - git config user.name dummyuser - git config user.email dummyuser@dummyserver.com - git remote add upstream https://github.com/dlang/druntime.git - git fetch upstream - git checkout -f upstream/$base_branch - git merge -m "Automatic merge" $current_branch + local head=$(git rev-parse HEAD) + git fetch https://github.com/dlang/$CIRCLE_PROJECT_REPONAME.git $base_branch + git checkout -f FETCH_HEAD + local base=$(git rev-parse HEAD) + git config user.name 'CI' + git config user.email '<>' + git merge -m "Merge $head into $base" $head fi for proj in dmd ; do @@ -94,8 +102,17 @@ coverage() { TEST_COVERAGE="1" make -j$N -C . -f posix.mak MODEL=$MODEL unittest-debug } +codecov() +{ + # CodeCov gets confused by lst files which it can't matched + rm -rf test/runnable/extra-files + download "https://codecov.io/bash" "https://raw.githubusercontent.com/codecov/codecov-bash/master/codecov" "codecov.sh" + bash codecov.sh +} + case $1 in install-deps) install_deps ;; setup-repos) setup_repos ;; coverage) coverage ;; + codecov) codecov ;; esac From 1682d130f6c499713f2845b0ab77c2b49701da87 Mon Sep 17 00:00:00 2001 From: Steven Schveighoffer Date: Fri, 17 Feb 2017 09:47:28 -0500 Subject: [PATCH 41/82] Update handling of previously undetected cycles to abort execution. --- src/rt/minfo.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rt/minfo.d b/src/rt/minfo.d index 190cce279c..838865a547 100644 --- a/src/rt/minfo.d +++ b/src/rt/minfo.d @@ -183,7 +183,7 @@ struct ModuleGroup } // Change default to .abort in 2.073 - auto onCycle = OnCycle.deprecate; + auto onCycle = OnCycle.abort; switch(cycleHandling) with(OnCycle) { From e47d8b4890434a5df6b42f9b81a186fb5d6e2160 Mon Sep 17 00:00:00 2001 From: Sebastian Wilzbach Date: Sat, 18 Feb 2017 00:02:04 +0100 Subject: [PATCH 42/82] Update changelog README --- changelog/README.md | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/changelog/README.md b/changelog/README.md index 48ceb6a06b..874d70fe0f 100644 --- a/changelog/README.md +++ b/changelog/README.md @@ -1,21 +1,31 @@ +This directory will get copied to dlang.org and cleared when master gets +merged into stable prior to a new release. + How to add a new changelog entry to the pending changelog? ========================================================== -This will get copied to dlang.org and cleared when master gets -merged into stable prior to a new release. +Create a new file in the `changelog` folder. It should end with `.dd` and look +similar to a git commit message. The first line represents the title of the change. +After an empty line follows the long description: ``` -My fancy new feature X +My fancy title of the new feature -A long description of the new feature. +A long description of the new feature in `std.range`. +It can be followed by an example: ------- -import std.range; -import std.algorithm.comparison; +import std.range : padLeft, padRight; +import std.algorithm.comparison : equal; assert([1, 2, 3, 4, 5].padLeft(0, 7).equal([0, 0, 1, 2, 3, 4, 5])); assert("Hello World!".padRight('!', 15).equal("Hello World!!!!")); ------- +and links to the documentation, e.g. $(REF drop, std, range) or +$(REF_ALTTEXT a custom name for the function, drop, std, range). + +Links to the spec can look like this $(LINK2 $(ROOT_DIR)spec/module.html, this) +and of course you can link to other $(LINK2 https://forum.dlang.org/, external resources). ``` The title can't contain links (it's already one). @@ -24,11 +34,9 @@ For more infos, see the [Ddoc spec](https://dlang.org/spec/ddoc.html). Preview changes --------------- -If you have cloned the [tools](https://github.com/dlang/tools) and [dlang.org](https://github.com/dlang/dlang.org) repo), -you can preview the changelog: +If you have cloned the [tools](https://github.com/dlang/tools) and [dlang.org](https://github.com/dlang/dlang.org) repo, +you can preview the changelog with: ``` -../tools/changed.d -o ../dlang.org/changelog/pending.dd && make -C ../dlang.org -f posix.mak html +make -C ../dlang.org -f posix.mak pending_changelog ``` - -and then open `../dlang.org/web/changelog/pending.html` with your favorite browser. From e5f05f33de0c6b7670f8342463296e6486c06d5b Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Sat, 18 Feb 2017 09:23:49 +0100 Subject: [PATCH 43/82] OMF: move pointer reference data to CODE segment --- src/rt/minit.asm | 19 ++++++++++--------- src/rt/minit.obj | Bin 484 -> 485 bytes 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/rt/minit.asm b/src/rt/minit.asm index a932442545..64a307fdf2 100644 --- a/src/rt/minit.asm +++ b/src/rt/minit.asm @@ -10,7 +10,8 @@ ; (See accompanying file LICENSE or copy at ; http://www.boost.org/LICENSE_1_0.txt) ; -;include macros.asm +; With VC installed, build with: +; ml /omf minit.asm .model FLAT @@ -65,29 +66,29 @@ DGROUP group FMB,FM,FME ; These segments bracket DP, which contains the _DATA pointer references public __DPbegin, __DPend -DPB segment dword use32 public 'DATA' +DPB segment dword use32 public 'CODE' __DPbegin: DPB ends -DP segment dword use32 public 'DATA' +DP segment dword use32 public 'CODE' DP ends -DPE segment dword use32 public 'DATA' +DPE segment dword use32 public 'CODE' __DPend: DPE ends -DGROUP group DPB,DP,DPE +CGROUP group DPB,DP,DPE ; These segments bracket TP, which contains the TLS pointer references public __TPbegin, __TPend -TPB segment dword use32 public 'DATA' +TPB segment dword use32 public 'CODE' __TPbegin: TPB ends -TP segment dword use32 public 'DATA' +TP segment dword use32 public 'CODE' TP ends -TPE segment dword use32 public 'DATA' +TPE segment dword use32 public 'CODE' __TPend: TPE ends -DGROUP group TPB,TP,TPE +CGROUP group TPB,TP,TPE _TEXT segment para use32 public 'CODE' assume CS:_TEXT diff --git a/src/rt/minit.obj b/src/rt/minit.obj index fde08d4999199a9e151600dde13b63f15454ecee..9aaa62d036f590b699220915cc90d6f6cd036df8 100644 GIT binary patch delta 316 zcmaFD{FGU)ft!IdH#0A@L@%*8_s+Cv1_maV0H%-tHfQ%B|ImrzzV%@<*cmdV83aTb zw}V&=4BR4&H-M~_3=C`{jB_C@K@rAD5Eh3B<7^0vN0@O2h{eJnB+S?c5#twToC;yF zio*0Vi83yLh_Q>p^m2+a&V-2RGmA3LhcNj>8K=x*V&ICJ#lgV)pZPz_e^!rKd<-oA zIsbG0=l;+0pZ7nX=wx0-gIH#6_V{?0fYiJc1_p*B69gETIXOWBNvY|Xc|f5rAR!*0 rPzYS;;RHSgW{5U93|KmkTZpa3{{fSRg0SQr=vpnd4)n&R+1xz=pD5biQkEN7KZAnTqmCrO+8Kwu-0@JOk&2+6=^O)|H z9i~}rV0Y^tV)4Y6mRJcTl2|&D{8W9~*fvox9uJ0-;sC&F*@dyT3Hy`7ym0BeNwG`W cfBGmBn8eMpzu9wjM*Xmj!2P=$Rgbjw3!T46Hvj+t From 37491945208d827deec4d700749710048b7818b6 Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Sat, 18 Feb 2017 15:44:55 +0100 Subject: [PATCH 44/82] windows: disable precise scanning of DATA/TLS --- src/rt/sections_win32.d | 2 +- src/rt/sections_win64.d | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rt/sections_win32.d b/src/rt/sections_win32.d index 0c09b5cd0b..1343c94985 100644 --- a/src/rt/sections_win32.d +++ b/src/rt/sections_win32.d @@ -18,7 +18,7 @@ version(CRuntime_DigitalMars): debug(PRINTF) import core.stdc.stdio; import rt.minfo; -//version = conservative; +version = conservative; struct SectionGroup { diff --git a/src/rt/sections_win64.d b/src/rt/sections_win64.d index f7f1d0ecc7..0dbeb48599 100644 --- a/src/rt/sections_win64.d +++ b/src/rt/sections_win64.d @@ -19,7 +19,7 @@ debug(PRINTF) import core.stdc.stdio; import core.stdc.stdlib : malloc, free; import rt.deh, rt.minfo; -//version = conservative; +version = conservative; struct SectionGroup { From aa92c867a1e3700ac7fcd13e61afaa8616b2b9eb Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Sat, 18 Feb 2017 17:50:30 -0800 Subject: [PATCH 45/82] workaround sscanf bug in old snn.lib --- src/gc/config.d | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/src/gc/config.d b/src/gc/config.d index 7cb5b1e6c8..3ac7403b9c 100644 --- a/src/gc/config.d +++ b/src/gc/config.d @@ -180,8 +180,32 @@ body assert(n > 4 && n < fmt.length); int nscanned; - if (sscanf(str.ptr, fmt.ptr, &res, &nscanned) < 1) - return parseError("a float", optname, str); + version (Win32) + { + /* Older sscanf's in snn.lib can write to its first argument, causing a crash + * if the string is in readonly memory. Recent updates to DMD + * https://github.com/dlang/dmd/pull/6546 + * put string literals in readonly memory. + * Although sscanf has been fixed, + * http://ftp.digitalmars.com/snn.lib + * this workaround is here so it still works with the older snn.lib. + */ + // Create mutable copy of str + const length = str.length; + char* mptr = cast(char*)malloc(length + 1); + assert(mptr); + memcpy(mptr, str.ptr, length); + mptr[length] = 0; + const result = sscanf(mptr, fmt.ptr, &res, &nscanned); + free(mptr); + if (result < 1) + return parseError("a float", optname, str); + } + else + { + if (sscanf(str.ptr, fmt.ptr, &res, &nscanned) < 1) + return parseError("a float", optname, str); + } str = str[nscanned .. $]; return true; } From bdaeba55cc3716633373be305baac3d386aef48b Mon Sep 17 00:00:00 2001 From: Martin Nowak Date: Tue, 21 Feb 2017 12:53:18 +0100 Subject: [PATCH 46/82] use correct version CRuntime_DigitalMars --- src/gc/config.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gc/config.d b/src/gc/config.d index 3ac7403b9c..b0789cd2b2 100644 --- a/src/gc/config.d +++ b/src/gc/config.d @@ -180,7 +180,7 @@ body assert(n > 4 && n < fmt.length); int nscanned; - version (Win32) + version (CRuntime_DigitalMars) { /* Older sscanf's in snn.lib can write to its first argument, causing a crash * if the string is in readonly memory. Recent updates to DMD From 2d06b368aff08368266a1b4b78b7bef0d98f3132 Mon Sep 17 00:00:00 2001 From: Tomer Filiba Date: Tue, 21 Feb 2017 18:15:24 +0200 Subject: [PATCH 47/82] Fix wrong version name in core.sys.linux.ifaddrs --- src/core/sys/linux/ifaddrs.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/sys/linux/ifaddrs.d b/src/core/sys/linux/ifaddrs.d index 1fc5e88513..bfdd59bf8f 100644 --- a/src/core/sys/linux/ifaddrs.d +++ b/src/core/sys/linux/ifaddrs.d @@ -18,7 +18,7 @@ module core.sys.linux.ifaddrs; import core.sys.posix.sys.socket; -version (Linux): +version (linux): extern (C): nothrow: @nogc: From b925aa2467bfc204d2cc02b3c67e71f60353db17 Mon Sep 17 00:00:00 2001 From: Nemanja Boric Date: Fri, 24 Feb 2017 16:12:35 +0100 Subject: [PATCH 48/82] Change version(Linux) to version(linux) --- src/core/sys/linux/sched.d | 2 +- src/core/sys/linux/sys/netinet/tcp.d | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/sys/linux/sched.d b/src/core/sys/linux/sched.d index 6dc6e33655..52938b55e5 100644 --- a/src/core/sys/linux/sched.d +++ b/src/core/sys/linux/sched.d @@ -18,7 +18,7 @@ import core.sys.posix.sched; import core.sys.posix.config; import core.sys.posix.sys.types; -version (Linux): +version (linux): extern (C): @nogc: nothrow: diff --git a/src/core/sys/linux/sys/netinet/tcp.d b/src/core/sys/linux/sys/netinet/tcp.d index b4acdd23c4..67458f63c1 100644 --- a/src/core/sys/linux/sys/netinet/tcp.d +++ b/src/core/sys/linux/sys/netinet/tcp.d @@ -43,7 +43,7 @@ module core.sys.linux.sys.netinet.tcp; * @(#)tcp.h 8.1 (Berkeley) 6/10/93 */ -version (Linux): +version (linux): /// User-settable options (used with setsockopt). enum From 2bf7ad5dfdc891ea5b0afa49beff790e926cc184 Mon Sep 17 00:00:00 2001 From: Vladimir Panteleev Date: Sun, 26 Feb 2017 04:32:40 +0000 Subject: [PATCH 49/82] core.sys.linux.sched: Fix DDoc syntax --- src/core/sys/linux/sched.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/sys/linux/sched.d b/src/core/sys/linux/sched.d index 52938b55e5..fe5fd72b8c 100644 --- a/src/core/sys/linux/sched.d +++ b/src/core/sys/linux/sched.d @@ -67,7 +67,7 @@ struct cpu_set_t cpu_mask[__CPU_SETSIZE / __NCPUBITS] __bits; } -/// Access macros for `cpu_set' (missing a lot of them) +/// Access macros for 'cpu_set' (missing a lot of them) cpu_mask CPU_SET(size_t cpu, cpu_set_t* cpusetp) pure { From 6ed294bb9a09ce8d63743951ae03b535eaeff4f1 Mon Sep 17 00:00:00 2001 From: Martin Nowak Date: Sun, 26 Feb 2017 17:38:25 +0100 Subject: [PATCH 50/82] adding Jenkinsfile to hook with new ci2.dawg.eu instance - should transfer the ownership of the ci repo to dlang/ci --- Jenkinsfile | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 Jenkinsfile diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 0000000000..eb9fbdedab --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,20 @@ +#!/bin/env groovy + +def clone (repo_url, git_ref = "master") { + checkout( + poll: false, + scm: [ + $class: 'GitSCM', + branches: [[name: git_ref]], + extensions: [[$class: 'CleanBeforeCheckout']], + userRemoteConfigs: [[url: repo_url]] + ] + ) +} + +node { + dir('dlang/ci') { + clone 'https://github.com/Dicebot/dlangci.git' + } + load 'dlang/ci/pipeline.groovy' +} From 611a4a85caf320b4a920ca3e78eae29b26d52681 Mon Sep 17 00:00:00 2001 From: RazvanN7 Date: Wed, 1 Mar 2017 15:13:06 +0200 Subject: [PATCH 51/82] Updated makefile to use generated/os/release/model/dmd --- posix.mak | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/posix.mak b/posix.mak index 024cc4a9e6..a2f7bc1f50 100644 --- a/posix.mak +++ b/posix.mak @@ -21,7 +21,7 @@ ifneq ($(BUILD),release) endif endif -DMD=../dmd/src/dmd +DMD=../dmd/generated/$(OS)/release/$(MODEL)/dmd INSTALL_DIR=../install DOCDIR=doc From 0b555a2e6f44113d892d4c177aceb7aec74d3969 Mon Sep 17 00:00:00 2001 From: MoGu Date: Wed, 1 Mar 2017 08:04:23 +0800 Subject: [PATCH 52/82] Update windows console text attributes --- src/core/sys/windows/wincon.d | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/src/core/sys/windows/wincon.d b/src/core/sys/windows/wincon.d index 5c32b7ba8b..7a1be88561 100644 --- a/src/core/sys/windows/wincon.d +++ b/src/core/sys/windows/wincon.d @@ -17,14 +17,24 @@ private import core.sys.windows.w32api, core.sys.windows.windef; // FIXME: clean up Windows version support enum { - FOREGROUND_BLUE = 1, - FOREGROUND_GREEN = 2, - FOREGROUND_RED = 4, - FOREGROUND_INTENSITY = 8, - BACKGROUND_BLUE = 16, - BACKGROUND_GREEN = 32, - BACKGROUND_RED = 64, - BACKGROUND_INTENSITY = 128 + FOREGROUND_BLUE = 0x0001, + FOREGROUND_GREEN = 0x0002, + FOREGROUND_RED = 0x0004, + FOREGROUND_INTENSITY = 0x0008, + BACKGROUND_BLUE = 0x0010, + BACKGROUND_GREEN = 0x0020, + BACKGROUND_RED = 0x0040, + BACKGROUND_INTENSITY = 0x0080, + + COMMON_LVB_LEADING_BYTE = 0x0100, + COMMON_LVB_TRAILING_BYTE = 0x0200, + COMMON_LVB_GRID_HORIZONTAL = 0x0400, + COMMON_LVB_GRID_LVERTICAL = 0x0800, + COMMON_LVB_GRID_RVERTICAL = 0x1000, + COMMON_LVB_REVERSE_VIDEO = 0x4000, + COMMON_LVB_UNDERSCORE = 0x8000, + + COMMON_LVB_SBCSDBCS = 0x0300, } static if (_WIN32_WINNT >= 0x501) { From 094e5620f529dae56d0af78779ddeedd454a288d Mon Sep 17 00:00:00 2001 From: Steven Schveighoffer Date: Thu, 2 Mar 2017 15:47:29 -0500 Subject: [PATCH 53/82] Remove unused rt.typeinfo.ti_AC --- mak/SRCS | 1 - src/rt/typeinfo/ti_AC.d | 104 ---------------------------------------- 2 files changed, 105 deletions(-) delete mode 100644 src/rt/typeinfo/ti_AC.d diff --git a/mak/SRCS b/mak/SRCS index 33b85fce49..90e795f7c5 100644 --- a/mak/SRCS +++ b/mak/SRCS @@ -305,7 +305,6 @@ SRCS=\ src\rt\util\container\hashtab.d \ src\rt\util\container\treap.d \ \ - src\rt\typeinfo\ti_AC.d \ src\rt\typeinfo\ti_Acdouble.d \ src\rt\typeinfo\ti_Acfloat.d \ src\rt\typeinfo\ti_Acreal.d \ diff --git a/src/rt/typeinfo/ti_AC.d b/src/rt/typeinfo/ti_AC.d deleted file mode 100644 index cbfd5bd22c..0000000000 --- a/src/rt/typeinfo/ti_AC.d +++ /dev/null @@ -1,104 +0,0 @@ -/** - * TypeInfo support code. - * - * Copyright: Copyright Digital Mars 2004 - 2009. - * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0). - * Authors: Walter Bright - */ - -/* Copyright Digital Mars 2004 - 2009. - * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE or copy at - * http://www.boost.org/LICENSE_1_0.txt) - */ -module rt.typeinfo.ti_AC; - -// Object[] - -/* -NOTE: It is sometimes used for arrays of -classes or (incorrectly) interfaces. -But naked `TypeInfo_Array` is mostly used. -See @@@BUG12303@@@. -*/ -class TypeInfo_AC : TypeInfo_Array -{ - override string toString() const { return TypeInfo.toString(); } - - override bool opEquals(Object o) { return TypeInfo.opEquals(o); } - - override size_t getHash(in void* p) @trusted const - { - Object[] s = *cast(Object[]*)p; - size_t hash = 0; - - foreach (Object o; s) - { - if (o) - hash += o.toHash(); - } - return hash; - } - - override bool equals(in void* p1, in void* p2) const - { - Object[] s1 = *cast(Object[]*)p1; - Object[] s2 = *cast(Object[]*)p2; - - if (s1.length == s2.length) - { - for (size_t u = 0; u < s1.length; u++) - { - Object o1 = s1[u]; - Object o2 = s2[u]; - - // Do not pass null's to Object.opEquals() - if (o1 is o2 || - (!(o1 is null) && !(o2 is null) && o1.opEquals(o2))) - continue; - return false; - } - return true; - } - return false; - } - - override int compare(in void* p1, in void* p2) const - { - Object[] s1 = *cast(Object[]*)p1; - Object[] s2 = *cast(Object[]*)p2; - auto c = cast(sizediff_t)(s1.length - s2.length); - if (c == 0) - { - for (size_t u = 0; u < s1.length; u++) - { - Object o1 = s1[u]; - Object o2 = s2[u]; - - if (o1 is o2) - continue; - - // Regard null references as always being "less than" - if (o1) - { - if (!o2) - return 1; - c = o1.opCmp(o2); - if (c == 0) - continue; - break; - } - else - { - return -1; - } - } - } - return c < 0 ? -1 : c > 0 ? 1 : 0; - } - - override @property inout(TypeInfo) next() inout - { - return cast(inout)typeid(Object); - } -} From 51bd8111826138f1c40d347d93adceb6f9ba3356 Mon Sep 17 00:00:00 2001 From: Vladimir Panteleev Date: Sat, 4 Mar 2017 14:14:02 +0000 Subject: [PATCH 54/82] .gitignore: Fix Makefile rule The introduction of the .gitignore rule lacked any description or rationale (PR #682), so I'm guessing this is to allow people to create a local Makefile so that `make` works without needing to specify `-f posix.mak`. Fix this rule so that it doesn't apply to the actually versioned Makefile files under the test directory. --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index e820d19877..865d7846e5 100644 --- a/.gitignore +++ b/.gitignore @@ -7,7 +7,7 @@ druntime.json .DS_Store trace.def trace.log -Makefile +/Makefile /errno_c*.obj /msvc*.obj make From d388315aa7dd43a08caed8957cd1247b70f71278 Mon Sep 17 00:00:00 2001 From: Vladimir Panteleev Date: Sat, 4 Mar 2017 14:16:25 +0000 Subject: [PATCH 55/82] Add tests for class/struct/array comparisons PR #1781 is moving array comparisons to a new template; the initial implementation included changes which may have introduced performance and behavior regressions. Add explicit tests for these cases to detect such regressions. --- posix.mak | 2 +- test/typeinfo/Makefile | 17 ++++++++ test/typeinfo/src/comparison.d | 78 ++++++++++++++++++++++++++++++++++ 3 files changed, 96 insertions(+), 1 deletion(-) create mode 100644 test/typeinfo/Makefile create mode 100644 test/typeinfo/src/comparison.d diff --git a/posix.mak b/posix.mak index 024cc4a9e6..d23156054c 100644 --- a/posix.mak +++ b/posix.mak @@ -197,7 +197,7 @@ $(DRUNTIME): $(OBJS) $(SRCS) UT_MODULES:=$(patsubst src/%.d,$(ROOT)/unittest/%,$(SRCS)) HAS_ADDITIONAL_TESTS:=$(shell test -d test && echo 1) ifeq ($(HAS_ADDITIONAL_TESTS),1) - ADDITIONAL_TESTS:=test/init_fini test/exceptions test/coverage test/profile test/cycles test/allocations + ADDITIONAL_TESTS:=test/init_fini test/exceptions test/coverage test/profile test/cycles test/allocations test/typeinfo ADDITIONAL_TESTS+=$(if $(SHARED),test/shared,) endif diff --git a/test/typeinfo/Makefile b/test/typeinfo/Makefile new file mode 100644 index 0000000000..6c371684d7 --- /dev/null +++ b/test/typeinfo/Makefile @@ -0,0 +1,17 @@ +include ../common.mak + +TESTS:=comparison + +.PHONY: all clean +all: $(addprefix $(ROOT)/,$(addsuffix .done,$(TESTS))) + +$(ROOT)/%.done: $(ROOT)/% + @echo Testing $* + $(QUIET)$(TIMELIMIT)$(ROOT)/$* $(RUN_ARGS) + @touch $@ + +$(ROOT)/%: $(SRC)/%.d + $(QUIET)$(DMD) $(DFLAGS) -of$@ $< + +clean: + rm -rf $(ROOT) diff --git a/test/typeinfo/src/comparison.d b/test/typeinfo/src/comparison.d new file mode 100644 index 0000000000..a6719ba546 --- /dev/null +++ b/test/typeinfo/src/comparison.d @@ -0,0 +1,78 @@ +// https://github.com/dlang/druntime/pull/1781 + +struct S +{ + int i; + static int comparisons; + int opCmp(const S s) const { comparisons++; return i - s.i; } +} + +void testStructs() +{ + auto s1 = S(1); + auto s2 = S(2); + auto s3 = S(3); + auto s4 = S(4); + + // Test lexicographical order + + assert(s1 < s2 && s2 < s3); + assert([s1, s2, s3] < [s1, s3]); + assert([s1, s2] < [s1, s2, s3]); + + // Test number of comparisons for nested types + + S.comparisons = 0; + assert(s1 < s2); + assert(S.comparisons == 1); + + S.comparisons = 0; + assert([s1, s2] < [s3, s4]); + assert(S.comparisons == 1); + + S.comparisons = 0; + assert([[s1, s2]] < [[s3, s4]]); + assert(S.comparisons == 1); +} + +class C +{ + this(int i) { this.i = i; } + int i; + static int comparisons; + override int opCmp(Object c) const { comparisons++; return i - (cast(C)c).i; } +} + +void testClasses() +{ + auto c1 = new C(1); + auto c2 = new C(2); + auto c3 = new C(3); + auto c4 = new C(4); + + // Test lexicographical order + + assert(c1 < c2 && c2 < c3); + assert([c1, c2, c3] < [c1, c3]); + assert([c1, c2] < [c1, c2, c3]); + + // Test number of comparisons for nested types + + C.comparisons = 0; + assert(c1 < c2); + assert(C.comparisons == 1); + + C.comparisons = 0; + assert([c1, c2] < [c3, c4]); + assert(C.comparisons == 1); + + C.comparisons = 0; + assert([[c1, c2]] < [[c3, c4]]); + assert(C.comparisons == 1); +} + +void main() +{ + testStructs(); + testClasses(); +} From d03a8948b4846af20210ad4258e5ab6402abf97c Mon Sep 17 00:00:00 2001 From: Sebastian Wilzbach Date: Sat, 4 Mar 2017 22:45:24 +0100 Subject: [PATCH 56/82] Remove dmd.conf target from CircleCi --- circleci.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/circleci.sh b/circleci.sh index ca85a114ce..a2f7e641d5 100755 --- a/circleci.sh +++ b/circleci.sh @@ -77,7 +77,6 @@ coverage() { # build dmd and druntime make -j$N -C ../dmd/src -f posix.mak MODEL=$MODEL HOST_DMD=$DMD all - make -j$N -C ../dmd/src -f posix.mak MODEL=$MODEL HOST_DMD=$DMD dmd.conf TEST_COVERAGE="1" make -j$N -C . -f posix.mak MODEL=$MODEL unittest-debug } From ed4818b1093d2da67803d24303896a937221239a Mon Sep 17 00:00:00 2001 From: somzzz Date: Thu, 19 Jan 2017 04:51:19 -0800 Subject: [PATCH 57/82] array compare template function --- src/object.d | 220 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 220 insertions(+) diff --git a/src/object.d b/src/object.d index 38b6144b3b..154827bbc5 100644 --- a/src/object.d +++ b/src/object.d @@ -3241,6 +3241,226 @@ template RTInfo(T) enum RTInfo = null; } +int _adCmpT(T1, T2)(T1[] s1, T2[] s2) +{ + // U1 gets the unqualified version of T1 + static if (is(T1 W == immutable W)) alias U1 = W; + else static if (is(T1 W == const W)) alias U1 = W; + else alias U1 = T1; + + // U2 gets the unqualified version of T2 + static if (is(T2 U == immutable U)) alias U2 = U; + else static if (is(T2 U == const U)) alias U2 = U; + else alias U2 = T2; + + // objects + static if (is(U1 : Object) && is(U2 : Object)) + { + auto c = cast(sizediff_t)(s1.length - s2.length); + if (c == 0) + { + for (size_t u = 0; u < s1.length; u++) + { + Object o1 = s1[u]; + Object o2 = s2[u]; + + if (o1 is o2) + continue; + + // Regard null references as always being "less than" + if (o1) + { + if (!o2) + return 1; + c = o1.opCmp(o2); + if (c == 0) + continue; + break; + } + else + { + return -1; + } + } + } + return c < 0 ? -1 : c > 0 ? 1 : 0; + } + + // floating point types + static if ((is(U1 == float) && is(U2 == float)) + || (is(U1 == double) && is(U2 == double)) + || (is(U1 == real) && is(U2 == real)) + || (is(U1 == ifloat) && is(U2 == ifloat)) + || (is(U1 == idouble) && is(U2 == idouble)) + || (is(U1 == ireal) && is(U2 == ireal)) + || (is(U1 == cfloat) && is(U2 == cfloat)) + || (is(U1 == cdouble) && is(U2 == cdouble)) + || (is(U1 == creal) && is(U2 == creal))) + { + template Floating(T) + if (is(T == cfloat) || is(T == cdouble) || is(T == creal)) + { + pure nothrow @safe: + int compare(T f1, T f2) + { + int result; + + if (f1.re < f2.re) + result = -1; + else if (f1.re > f2.re) + result = 1; + else if (f1.im < f2.im) + result = -1; + else if (f1.im > f2.im) + result = 1; + else + result = 0; + return result; + } + } + + template Floating(T) + if (is(T == float) || is(T == double) || is(T == real)) + { + pure nothrow @safe: + int compare(T d1, T d2) + { + if (d1 != d1 || d2 != d2) // if either are NaN + { + if (d1 != d1) + { + if (d2 != d2) + return 0; + return -1; + } + return 1; + } + return (d1 == d2) ? 0 : ((d1 < d2) ? -1 : 1); + } + } + + template Array(T) + if (is(T == float) || is(T == double) || is(T == real) || + is(T == cfloat) || is(T == cdouble) || is(T == creal)) + { + pure nothrow @safe: + int compare(T[] s1, T[] s2) + { + size_t len = s1.length; + if (s2.length < len) + len = s2.length; + for (size_t u = 0; u < len; u++) + { + if (int c = Floating!T.compare(s1[u], s2[u])) + return c; + } + if (s1.length < s2.length) + return -1; + else if (s1.length > s2.length) + return 1; + return 0; + } + } + + static if (is(U1 == ifloat)) alias F = float; + else static if (is(U1 == idouble)) alias F = double; + else static if (is(U1 == ireal)) alias F = real; + else alias F = U1; + + return () @trusted { return Array!F.compare(cast(F[])s1, cast(F[])s2); }(); + } + + // integral, char types + else + { + size_t len = s1.length; + + if (s2.length < len) + len = s2.length; + + for (size_t u = 0; u < len; u++) + { + if (s1[u] < s2[u]) + return -1; + else if (s1[u] > s2[u]) + return 1; + } + + if (s1.length < s2.length) + return -1; + else if (s1.length > s2.length) + return 1; + + return 0; + } +} + +// integral types +unittest +{ + void compareMinMax(T)() + { + T[] a = [T.max, T.max]; + T[] b = [T.min, T.min]; + + assert(a > b); + assert(b < a); + } + + compareMinMax!int; + compareMinMax!uint; + compareMinMax!long; + compareMinMax!ulong; + compareMinMax!short; + compareMinMax!ushort; + compareMinMax!byte; + compareMinMax!ubyte; + compareMinMax!bool; +} + +// char types +unittest +{ + void compareMinMax(T)() + { + T[] a = [T.max, T.max]; + T[] b = [T.min, T.min]; + + assert(a > b); + assert(b < a); + } + + compareMinMax!char; + compareMinMax!dchar; + compareMinMax!wchar; +} + +// fp types +unittest +{ + void compareMinMax(T)() + { + T[] a = [T.max, T.max]; + T[] b = [T.min_normal, T.min_normal]; + + assert(a > b); + assert(b < a); + } + + compareMinMax!real; + compareMinMax!float; + compareMinMax!double; + compareMinMax!ireal; + compareMinMax!ifloat; + compareMinMax!idouble; + compareMinMax!creal; + //compareMinMax!cfloat; + compareMinMax!cdouble; + + // qualifiers + compareMinMax!(const real); + compareMinMax!(immutable real); +} // Helper functions From 3e667945e51472423f27e262aa449878067ef000 Mon Sep 17 00:00:00 2001 From: somzzz Date: Fri, 3 Mar 2017 03:10:32 -0800 Subject: [PATCH 58/82] fixed nits & added tests & dstrcmp --- src/object.d | 273 +++++++++++++++++++++++++++++---------------------- 1 file changed, 158 insertions(+), 115 deletions(-) diff --git a/src/object.d b/src/object.d index 154827bbc5..2692059b2f 100644 --- a/src/object.d +++ b/src/object.d @@ -3241,19 +3241,76 @@ template RTInfo(T) enum RTInfo = null; } -int _adCmpT(T1, T2)(T1[] s1, T2[] s2) +private template Floating1(T) +if (is(T == cfloat) || is(T == cdouble) || is(T == creal)) +{ + // Use rt.cmath2._Ccmp instead ? + int compare(T f1, T f2) + { + int result; + + if (f1.re < f2.re) + result = -1; + else if (f1.re > f2.re) + result = 1; + else if (f1.im < f2.im) + result = -1; + else if (f1.im > f2.im) + result = 1; + else + result = 0; + return result; + } +} + +private template Floating1(T) +if (is(T == float) || is(T == double) || is(T == real)) { - // U1 gets the unqualified version of T1 - static if (is(T1 W == immutable W)) alias U1 = W; - else static if (is(T1 W == const W)) alias U1 = W; - else alias U1 = T1; + int compare(T d1, T d2) + { + if (d1 != d1 || d2 != d2) // if either is NaN + { + if (d1 != d1) + { + if (d2 != d2) + return 0; + return -1; + } + return 1; + } + return d1 < d2 ? -1 : (d1 > d2); + } +} - // U2 gets the unqualified version of T2 - static if (is(T2 U == immutable U)) alias U2 = U; - else static if (is(T2 U == const U)) alias U2 = U; - else alias U2 = T2; +private template Array1(T) +if (is(T == float) || is(T == double) || is(T == real) || + is(T == cfloat) || is(T == cdouble) || is(T == creal)) +{ + int compare(T[] s1, T[] s2) + { + auto len = s1.length; + if (s2.length < len) + len = s2.length; + + foreach (const u; 0 .. len) + { + if (int c = Floating1!T.compare(s1[u], s2[u])) + return c; + } + return s1.length < s2.length ? -1 : (s1.length > s2.length); + } +} + +int _adCmpT(T1, T2)(T1[] s1, T2[] s2) +{ + import core.internal.traits : Unqual; + alias U1 = Unqual!T1; + alias U2 = Unqual!T2; // objects + // Old code went to object.d/TypeInfo_array.compare and then to + // object.d/TypeInfo_Class.compare + // which combined result in the same code as below. static if (is(U1 : Object) && is(U2 : Object)) { auto c = cast(sizediff_t)(s1.length - s2.length); @@ -3261,8 +3318,8 @@ int _adCmpT(T1, T2)(T1[] s1, T2[] s2) { for (size_t u = 0; u < s1.length; u++) { - Object o1 = s1[u]; - Object o2 = s2[u]; + auto o1 = () @trusted { return s1.ptr[u]; }(); + auto o2 = () @trusted { return s2.ptr[u]; }(); if (o1 is o2) continue; @@ -3273,9 +3330,8 @@ int _adCmpT(T1, T2)(T1[] s1, T2[] s2) if (!o2) return 1; c = o1.opCmp(o2); - if (c == 0) - continue; - break; + if (c != 0) + break; } else { @@ -3283,115 +3339,74 @@ int _adCmpT(T1, T2)(T1[] s1, T2[] s2) } } } - return c < 0 ? -1 : c > 0 ? 1 : 0; + return c < 0 ? -1 : (c > 0); } // floating point types - static if ((is(U1 == float) && is(U2 == float)) - || (is(U1 == double) && is(U2 == double)) - || (is(U1 == real) && is(U2 == real)) - || (is(U1 == ifloat) && is(U2 == ifloat)) - || (is(U1 == idouble) && is(U2 == idouble)) - || (is(U1 == ireal) && is(U2 == ireal)) - || (is(U1 == cfloat) && is(U2 == cfloat)) - || (is(U1 == cdouble) && is(U2 == cdouble)) - || (is(U1 == creal) && is(U2 == creal))) - { - template Floating(T) - if (is(T == cfloat) || is(T == cdouble) || is(T == creal)) - { - pure nothrow @safe: - int compare(T f1, T f2) - { - int result; - - if (f1.re < f2.re) - result = -1; - else if (f1.re > f2.re) - result = 1; - else if (f1.im < f2.im) - result = -1; - else if (f1.im > f2.im) - result = 1; - else - result = 0; - return result; - } - } + else static if (__traits(isFloating, U1)) + { + static if (is(U1 == ifloat)) alias F = float; + else static if (is(U1 == idouble)) alias F = double; + else static if (is(U1 == ireal)) alias F = real; + else alias F = U1; - template Floating(T) - if (is(T == float) || is(T == double) || is(T == real)) + return () @trusted { return Array1!F.compare(cast(F[])s1, cast(F[])s2); }(); + } + + // char types = > dstrcmp + else static if ((is(U1 == ubyte) && is(U2 == ubyte)) + || (is(U1 == void) && is(U2 == void)) + || (is(U1 == bool) && is(U2 == bool)) + || (is(U1 == char) && is(U2 == char))) + { + if (!__ctfe) { - pure nothrow @safe: - int compare(T d1, T d2) - { - if (d1 != d1 || d2 != d2) // if either are NaN - { - if (d1 != d1) - { - if (d2 != d2) - return 0; - return -1; - } - return 1; - } - return (d1 == d2) ? 0 : ((d1 < d2) ? -1 : 1); - } + import core.internal.string : dstrcmp; + return () @trusted { return dstrcmp(cast(char[])s1, cast(char[])s2); }(); } - - template Array(T) - if (is(T == float) || is(T == double) || is(T == real) || - is(T == cfloat) || is(T == cdouble) || is(T == creal)) + else { - pure nothrow @safe: - int compare(T[] s1, T[] s2) + // pretty ugly... + auto len = s1.length; + + if (s2.length < len) + len = s2.length; + + foreach (const u; 0 .. len) { - size_t len = s1.length; - if (s2.length < len) - len = s2.length; - for (size_t u = 0; u < len; u++) - { - if (int c = Floating!T.compare(s1[u], s2[u])) - return c; - } - if (s1.length < s2.length) + auto e1 = () @trusted { return s1.ptr[u]; }(); + auto e2 = () @trusted { return s2.ptr[u]; }(); + + if (e1 < e2) return -1; - else if (s1.length > s2.length) + else if (e1 > e2) return 1; - return 0; } - } - - static if (is(U1 == ifloat)) alias F = float; - else static if (is(U1 == idouble)) alias F = double; - else static if (is(U1 == ireal)) alias F = real; - else alias F = U1; - return () @trusted { return Array!F.compare(cast(F[])s1, cast(F[])s2); }(); + return s1.length < s2.length ? -1 : (s1.length > s2.length); + } } - // integral, char types + // integral else { - size_t len = s1.length; + auto len = s1.length; if (s2.length < len) len = s2.length; - for (size_t u = 0; u < len; u++) + foreach (const u; 0 .. len) { - if (s1[u] < s2[u]) + auto e1 = () @trusted { return s1.ptr[u]; }(); + auto e2 = () @trusted { return s2.ptr[u]; }(); + + if (e1 < e2) return -1; - else if (s1[u] > s2[u]) + else if (e1 > e2) return 1; } - if (s1.length < s2.length) - return -1; - else if (s1.length > s2.length) - return 1; - - return 0; + return s1.length < s2.length ? -1 : (s1.length > s2.length); } } @@ -3400,11 +3415,11 @@ unittest { void compareMinMax(T)() { - T[] a = [T.max, T.max]; - T[] b = [T.min, T.min]; + T[2] a = [T.max, T.max]; + T[2] b = [T.min, T.min]; - assert(a > b); - assert(b < a); + assert(_adCmpT(a, b) > 0); + assert(_adCmpT(b, a) < 0); } compareMinMax!int; @@ -3414,25 +3429,31 @@ unittest compareMinMax!short; compareMinMax!ushort; compareMinMax!byte; - compareMinMax!ubyte; - compareMinMax!bool; + compareMinMax!dchar; + compareMinMax!wchar; } -// char types +// char types (dstrcmp) unittest { void compareMinMax(T)() { - T[] a = [T.max, T.max]; - T[] b = [T.min, T.min]; + T[2] a = [T.max, T.max]; + T[2] b = [T.min, T.min]; - assert(a > b); - assert(b < a); + assert(_adCmpT(a, b) > 0); + assert(_adCmpT(b, a) < 0); } + compareMinMax!ubyte; + compareMinMax!bool; compareMinMax!char; - compareMinMax!dchar; - compareMinMax!wchar; + compareMinMax!(const char); + + string s1 = "aaaa"; + string s2 = "bbbb"; + assert(_adCmpT(s2, s1) > 0); + assert(_adCmpT(s1, s2) < 0); } // fp types @@ -3440,11 +3461,11 @@ unittest { void compareMinMax(T)() { - T[] a = [T.max, T.max]; - T[] b = [T.min_normal, T.min_normal]; + T[2] a = [T.max, T.max]; + T[2] b = [T.min_normal, T.min_normal]; - assert(a > b); - assert(b < a); + assert(_adCmpT(a, b) > 0); + assert(_adCmpT(b, a) < 0); } compareMinMax!real; @@ -3462,6 +3483,28 @@ unittest compareMinMax!(immutable real); } +//objects +unittest +{ + class C + { + int i; + this(int i) { this.i = i; } + + override int opCmp(Object c) const + { + return i - (cast(C)c).i; + } + } + + auto c1 = new C(1); + auto c2 = new C(2); + + assert(_adCmpT([c1, c1], [c2, c2]) < 0); + assert(_adCmpT([c2, c2], [c1, c1]) > 0); +} + + // Helper functions private inout(TypeInfo) getElement(inout TypeInfo value) @trusted pure nothrow From 9afe2122ef28f16c7f9736ff68ecd9afff554550 Mon Sep 17 00:00:00 2001 From: somzzz Date: Sun, 5 Mar 2017 06:38:13 -0800 Subject: [PATCH 59/82] fixed breaking change & code adjustments --- src/object.d | 213 +++++++++++++++++++++++++-------------------------- 1 file changed, 106 insertions(+), 107 deletions(-) diff --git a/src/object.d b/src/object.d index 2692059b2f..8c3b06fb24 100644 --- a/src/object.d +++ b/src/object.d @@ -3241,107 +3241,49 @@ template RTInfo(T) enum RTInfo = null; } -private template Floating1(T) -if (is(T == cfloat) || is(T == cdouble) || is(T == creal)) -{ - // Use rt.cmath2._Ccmp instead ? - int compare(T f1, T f2) - { - int result; - - if (f1.re < f2.re) - result = -1; - else if (f1.re > f2.re) - result = 1; - else if (f1.im < f2.im) - result = -1; - else if (f1.im > f2.im) - result = 1; - else - result = 0; - return result; - } -} - -private template Floating1(T) -if (is(T == float) || is(T == double) || is(T == real)) -{ - int compare(T d1, T d2) - { - if (d1 != d1 || d2 != d2) // if either is NaN - { - if (d1 != d1) - { - if (d2 != d2) - return 0; - return -1; - } - return 1; - } - return d1 < d2 ? -1 : (d1 > d2); - } -} - -private template Array1(T) -if (is(T == float) || is(T == double) || is(T == real) || - is(T == cfloat) || is(T == cdouble) || is(T == creal)) -{ - int compare(T[] s1, T[] s2) - { - auto len = s1.length; - if (s2.length < len) - len = s2.length; - - foreach (const u; 0 .. len) - { - if (int c = Floating1!T.compare(s1[u], s2[u])) - return c; - } - return s1.length < s2.length ? -1 : (s1.length > s2.length); - } -} - -int _adCmpT(T1, T2)(T1[] s1, T2[] s2) +int __cmp(T1, T2)(T1[] s1, T2[] s2) { import core.internal.traits : Unqual; alias U1 = Unqual!T1; alias U2 = Unqual!T2; + static @trusted ref R at(R)(R[] r, size_t i) { return r.ptr[i]; } + // objects // Old code went to object.d/TypeInfo_array.compare and then to // object.d/TypeInfo_Class.compare // which combined result in the same code as below. static if (is(U1 : Object) && is(U2 : Object)) { - auto c = cast(sizediff_t)(s1.length - s2.length); - if (c == 0) + auto len = s1.length; + + if (s2.length < len) + len = s2.length; + + foreach (const u; 0 .. len) { - for (size_t u = 0; u < s1.length; u++) - { - auto o1 = () @trusted { return s1.ptr[u]; }(); - auto o2 = () @trusted { return s2.ptr[u]; }(); + auto o1 = at(s1, u); + auto o2 = at(s2, u); - if (o1 is o2) - continue; + if (o1 is o2) + continue; - // Regard null references as always being "less than" - if (o1) - { - if (!o2) - return 1; - c = o1.opCmp(o2); - if (c != 0) - break; - } - else - { - return -1; - } + // Regard null references as always being "less than" + if (o1) + { + if (!o2) + return 1; + auto c = o1.opCmp(o2); + if (c != 0) + return c < 0 ? -1 : 1; + } + else + { + return -1; } } - return c < 0 ? -1 : (c > 0); + return s1.length < s2.length ? -1 : (s1.length > s2.length); } - // floating point types else static if (__traits(isFloating, U1)) { @@ -3350,9 +3292,52 @@ int _adCmpT(T1, T2)(T1[] s1, T2[] s2) else static if (is(U1 == ireal)) alias F = real; else alias F = U1; - return () @trusted { return Array1!F.compare(cast(F[])s1, cast(F[])s2); }(); - } + static int compare(F f1, F f2) + { + static if (is(F == cfloat) || is(F == cdouble) || is(F == creal)) + { + // Use rt.cmath2._Ccmp instead ? + int result; + + if (f1.re < f2.re) + result = -1; + else if (f1.re > f2.re) + result = 1; + else if (f1.im < f2.im) + result = -1; + else if (f1.im > f2.im) + result = 1; + else + result = 0; + return result; + } + else static if (is(F == float) || is(F == double) || is(F == real)) + { + // d1 is NaN 2^0 + d2 is NaN 2^1 + auto NaNs = (f1 != f1) | ((f2 != f2) << 1); + + return (NaNs == 3) ? 0 : + (NaNs == 2) ? 1 : + (NaNs == 1) ? -1 : + (f1 < f2) ? -1 : (f1 > f2); + } + else static assert(false, "Internal error"); + } + + auto len = s1.length; + if (s2.length < len) + len = s2.length; + + auto fpArray1 = () { return cast(F[])s1; }(); + auto fpArray2 = () { return cast(F[])s2; }(); + foreach (const u; 0 .. len) + { + if (int c = compare(fpArray1[u], fpArray2[u])) + return c; + } + return s1.length < s2.length ? -1 : (s1.length > s2.length); + } // char types = > dstrcmp else static if ((is(U1 == ubyte) && is(U2 == ubyte)) || (is(U1 == void) && is(U2 == void)) @@ -3374,8 +3359,8 @@ int _adCmpT(T1, T2)(T1[] s1, T2[] s2) foreach (const u; 0 .. len) { - auto e1 = () @trusted { return s1.ptr[u]; }(); - auto e2 = () @trusted { return s2.ptr[u]; }(); + auto e1 = at(s1, u); + auto e2 = at(s2, u); if (e1 < e2) return -1; @@ -3386,8 +3371,7 @@ int _adCmpT(T1, T2)(T1[] s1, T2[] s2) return s1.length < s2.length ? -1 : (s1.length > s2.length); } } - - // integral + // integral, struct, nested arrays else { auto len = s1.length; @@ -3397,15 +3381,30 @@ int _adCmpT(T1, T2)(T1[] s1, T2[] s2) foreach (const u; 0 .. len) { - auto e1 = () @trusted { return s1.ptr[u]; }(); - auto e2 = () @trusted { return s2.ptr[u]; }(); + auto e1 = at(s1, u); + auto e2 = at(s2, u); - if (e1 < e2) - return -1; - else if (e1 > e2) - return 1; + // structs + static if (__traits(compiles, e1.opCmp(e2))) + { + auto c = e1.opCmp(e2); + if (c != 0) + return c < 0 ? -1 : 1; + } + else static if (__traits(compiles, _adCmp(e1, e2))) + { + auto c = _adCmp(e1, e2); + if (c != 0) + return c < 0 ? -1 : 1; + } + else + { + if (e1 < e2) + return -1; + else if (e1 > e2) + return 1; + } } - return s1.length < s2.length ? -1 : (s1.length > s2.length); } } @@ -3418,8 +3417,8 @@ unittest T[2] a = [T.max, T.max]; T[2] b = [T.min, T.min]; - assert(_adCmpT(a, b) > 0); - assert(_adCmpT(b, a) < 0); + assert(__cmp(a, b) > 0); + assert(__cmp(b, a) < 0); } compareMinMax!int; @@ -3441,8 +3440,8 @@ unittest T[2] a = [T.max, T.max]; T[2] b = [T.min, T.min]; - assert(_adCmpT(a, b) > 0); - assert(_adCmpT(b, a) < 0); + assert(__cmp(a, b) > 0); + assert(__cmp(b, a) < 0); } compareMinMax!ubyte; @@ -3452,8 +3451,8 @@ unittest string s1 = "aaaa"; string s2 = "bbbb"; - assert(_adCmpT(s2, s1) > 0); - assert(_adCmpT(s1, s2) < 0); + assert(__cmp(s2, s1) > 0); + assert(__cmp(s1, s2) < 0); } // fp types @@ -3464,8 +3463,8 @@ unittest T[2] a = [T.max, T.max]; T[2] b = [T.min_normal, T.min_normal]; - assert(_adCmpT(a, b) > 0); - assert(_adCmpT(b, a) < 0); + assert(__cmp(a, b) > 0); + assert(__cmp(b, a) < 0); } compareMinMax!real; @@ -3500,8 +3499,8 @@ unittest auto c1 = new C(1); auto c2 = new C(2); - assert(_adCmpT([c1, c1], [c2, c2]) < 0); - assert(_adCmpT([c2, c2], [c1, c1]) > 0); + assert(__cmp([c1, c1], [c2, c2]) < 0); + assert(__cmp([c2, c2], [c1, c1]) > 0); } From cbe8288943bc1a1415e3adb1b4a768f54cf4c449 Mon Sep 17 00:00:00 2001 From: somzzz Date: Sun, 5 Mar 2017 13:45:17 -0800 Subject: [PATCH 60/82] Comments and nits --- src/object.d | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/object.d b/src/object.d index 8c3b06fb24..c361c790ab 100644 --- a/src/object.d +++ b/src/object.d @@ -3241,6 +3241,9 @@ template RTInfo(T) enum RTInfo = null; } +// This function is called by the compiler when dealing with array +// comparisons in the semantic analysis phase of CmpExp. The ordering +// comparison is lowered to a call to this template. int __cmp(T1, T2)(T1[] s1, T2[] s2) { import core.internal.traits : Unqual; @@ -3364,7 +3367,8 @@ int __cmp(T1, T2)(T1[] s1, T2[] s2) if (e1 < e2) return -1; - else if (e1 > e2) + + if (e1 > e2) return 1; } @@ -3391,9 +3395,9 @@ int __cmp(T1, T2)(T1[] s1, T2[] s2) if (c != 0) return c < 0 ? -1 : 1; } - else static if (__traits(compiles, _adCmp(e1, e2))) + else static if (__traits(compiles, __cmp(e1, e2))) { - auto c = _adCmp(e1, e2); + auto c = __cmp(e1, e2); if (c != 0) return c < 0 ? -1 : 1; } @@ -3401,7 +3405,8 @@ int __cmp(T1, T2)(T1[] s1, T2[] s2) { if (e1 < e2) return -1; - else if (e1 > e2) + + if (e1 > e2) return 1; } } From 6c1c6cf7c144734f97faeb3a18b9193d6299e279 Mon Sep 17 00:00:00 2001 From: Andrei Alexandrescu Date: Mon, 6 Mar 2017 15:08:47 -0500 Subject: [PATCH 61/82] One more pass through __cmp --- src/core/internal/string.d | 30 +++++--- src/object.d | 151 +++++++++++-------------------------- 2 files changed, 62 insertions(+), 119 deletions(-) diff --git a/src/core/internal/string.d b/src/core/internal/string.d index 28b1e36246..47741772a3 100644 --- a/src/core/internal/string.d +++ b/src/core/internal/string.d @@ -192,16 +192,22 @@ unittest int dstrcmp( scope const char[] s1, scope const char[] s2 ) @trusted { - import core.stdc.string : memcmp; - - int ret = 0; - auto len = s1.length; - if( s2.length < len ) - len = s2.length; - if( 0 != (ret = memcmp( s1.ptr, s2.ptr, len )) ) - return ret; - return s1.length > s2.length ? 1 : - s1.length == s2.length ? 0 : -1; -} - + immutable len = s1.length <= s2.length ? s1.length : s2.length; + if (__ctfe) + { + foreach (const u; 0 .. len) + { + if (s1[u] != s2[u]) + return s1[u] > s2[u] ? 1 : -1; + } + } + else + { + import core.stdc.string : memcmp; + const ret = memcmp( s1.ptr, s2.ptr, len ); + if( ret ) + return ret; + } + return s1.length < s2.length ? -1 : (s1.length > s2.length); +} diff --git a/src/object.d b/src/object.d index c361c790ab..5661ea0051 100644 --- a/src/object.d +++ b/src/object.d @@ -3241,6 +3241,23 @@ template RTInfo(T) enum RTInfo = null; } +private int __cmp(F)(const F f1, const F f2) +if (__traits(isFloating, F)) +{ + static if (is(F == cfloat) || is(F == cdouble) || is(F == creal)) + { + // Use rt.cmath2._Ccmp instead ? + auto r = __cmp(f1.re, f2.re); + if (!r) r = __cmp(f1.im, f2.im); + return r; + } + else static if (is(F == float) || is(F == double) || is(F == real)) + { + return (f1 > f2) - (f2 > f1); + } + else static assert(false, "Internal error"); +} + // This function is called by the compiler when dealing with array // comparisons in the semantic analysis phase of CmpExp. The ordering // comparison is lowered to a call to this template. @@ -3249,6 +3266,7 @@ int __cmp(T1, T2)(T1[] s1, T2[] s2) import core.internal.traits : Unqual; alias U1 = Unqual!T1; alias U2 = Unqual!T2; + static assert(is(U1 == U2), "Internal error."); static @trusted ref R at(R)(R[] r, size_t i) { return r.ptr[i]; } @@ -3258,10 +3276,7 @@ int __cmp(T1, T2)(T1[] s1, T2[] s2) // which combined result in the same code as below. static if (is(U1 : Object) && is(U2 : Object)) { - auto len = s1.length; - - if (s2.length < len) - len = s2.length; + immutable len = s1.length <= s2.length ? s1.length : s2.length; foreach (const u; 0 .. len) { @@ -3278,7 +3293,7 @@ int __cmp(T1, T2)(T1[] s1, T2[] s2) return 1; auto c = o1.opCmp(o2); if (c != 0) - return c < 0 ? -1 : 1; + return c; } else { @@ -3287,127 +3302,49 @@ int __cmp(T1, T2)(T1[] s1, T2[] s2) } return s1.length < s2.length ? -1 : (s1.length > s2.length); } - // floating point types - else static if (__traits(isFloating, U1)) + // Imaginary types + else static if (is(U1 == ifloat) || is(U1 == idouble) || is(U1 == ireal)) { + // Special-case imaginary types to use comparison for "concrete" types static if (is(U1 == ifloat)) alias F = float; else static if (is(U1 == idouble)) alias F = double; else static if (is(U1 == ireal)) alias F = real; - else alias F = U1; - - static int compare(F f1, F f2) - { - static if (is(F == cfloat) || is(F == cdouble) || is(F == creal)) - { - // Use rt.cmath2._Ccmp instead ? - int result; - - if (f1.re < f2.re) - result = -1; - else if (f1.re > f2.re) - result = 1; - else if (f1.im < f2.im) - result = -1; - else if (f1.im > f2.im) - result = 1; - else - result = 0; - return result; - } - else static if (is(F == float) || is(F == double) || is(F == real)) - { - // d1 is NaN 2^0 + d2 is NaN 2^1 - auto NaNs = (f1 != f1) | ((f2 != f2) << 1); - - return (NaNs == 3) ? 0 : - (NaNs == 2) ? 1 : - (NaNs == 1) ? -1 : - (f1 < f2) ? -1 : (f1 > f2); - } - else static assert(false, "Internal error"); - } - auto len = s1.length; - if (s2.length < len) - len = s2.length; - - auto fpArray1 = () { return cast(F[])s1; }(); - auto fpArray2 = () { return cast(F[])s2; }(); - - foreach (const u; 0 .. len) - { - if (int c = compare(fpArray1[u], fpArray2[u])) - return c; - } - return s1.length < s2.length ? -1 : (s1.length > s2.length); + auto fpArray1 = () @trusted { return cast(F[])s1; }(); + auto fpArray2 = () @trusted { return cast(F[])s2; }(); + return __cmp(fpArray1, fpArray2); } - // char types = > dstrcmp - else static if ((is(U1 == ubyte) && is(U2 == ubyte)) - || (is(U1 == void) && is(U2 == void)) - || (is(U1 == bool) && is(U2 == bool)) - || (is(U1 == char) && is(U2 == char))) + // All unsigned byte-wide types = > dstrcmp + else static if (is(U1 == ubyte) || is(U1 == void) || is(U1 == bool) + || is(U1 == char)) { - if (!__ctfe) - { - import core.internal.string : dstrcmp; - return () @trusted { return dstrcmp(cast(char[])s1, cast(char[])s2); }(); - } - else - { - // pretty ugly... - auto len = s1.length; - - if (s2.length < len) - len = s2.length; - - foreach (const u; 0 .. len) - { - auto e1 = at(s1, u); - auto e2 = at(s2, u); - - if (e1 < e2) - return -1; - - if (e1 > e2) - return 1; - } - - return s1.length < s2.length ? -1 : (s1.length > s2.length); - } + import core.internal.string : dstrcmp; + return (() @trusted => dstrcmp(cast(char[])s1, cast(char[])s2))(); } - // integral, struct, nested arrays + // Everything else else { - auto len = s1.length; - - if (s2.length < len) - len = s2.length; + immutable len = s1.length <= s2.length ? s1.length : s2.length; foreach (const u; 0 .. len) { - auto e1 = at(s1, u); - auto e2 = at(s2, u); - // structs - static if (__traits(compiles, e1.opCmp(e2))) + static if (__traits(compiles, at(s1, u).opCmp(at(s2, u)))) { - auto c = e1.opCmp(e2); + auto c = at(s1, u).opCmp(at(s2, u)); if (c != 0) - return c < 0 ? -1 : 1; + return c; } - else static if (__traits(compiles, __cmp(e1, e2))) + else static if (__traits(compiles, __cmp(at(s1, u), at(s2, u)))) { - auto c = __cmp(e1, e2); + auto c = __cmp(at(s1, u), at(s2, u)); if (c != 0) - return c < 0 ? -1 : 1; + return c; } else { - if (e1 < e2) - return -1; - - if (e1 > e2) - return 1; + if (at(s1, u) != at(s2, u)) + return at(s1, u) < at(s2, u) ? -1 : 1; } } return s1.length < s2.length ? -1 : (s1.length > s2.length); @@ -3415,7 +3352,7 @@ int __cmp(T1, T2)(T1[] s1, T2[] s2) } // integral types -unittest +@safe unittest { void compareMinMax(T)() { @@ -3438,7 +3375,7 @@ unittest } // char types (dstrcmp) -unittest +@safe unittest { void compareMinMax(T)() { @@ -3461,7 +3398,7 @@ unittest } // fp types -unittest +@safe unittest { void compareMinMax(T)() { From 1fa3903cc7e7fd6325bfb386302e24864decae98 Mon Sep 17 00:00:00 2001 From: Andrei Alexandrescu Date: Mon, 6 Mar 2017 18:02:34 -0500 Subject: [PATCH 62/82] Factor in implementation for class and interface types --- src/object.d | 72 ++++++++++++++++++++++------------------------------ 1 file changed, 30 insertions(+), 42 deletions(-) diff --git a/src/object.d b/src/object.d index 5661ea0051..84833b39d2 100644 --- a/src/object.d +++ b/src/object.d @@ -3241,6 +3241,7 @@ template RTInfo(T) enum RTInfo = null; } +// Compare floating point numbers for ordering (one instantiation per width). private int __cmp(F)(const F f1, const F f2) if (__traits(isFloating, F)) { @@ -3251,11 +3252,31 @@ if (__traits(isFloating, F)) if (!r) r = __cmp(f1.im, f2.im); return r; } - else static if (is(F == float) || is(F == double) || is(F == real)) + else { return (f1 > f2) - (f2 > f1); } - else static assert(false, "Internal error"); +} + +// Compare class and interface objects for ordering. +private int __cmp(Obj)(Obj lhs, Obj rhs) +if (is(Obj : Object)) +{ + if (o1 is o2) + return 0; + // Regard null references as always being "less than" + if (o1) + { + if (!o2) + return 1; + auto c = o1.opCmp(o2); + if (c != 0) + return c; + } + else + { + return -1; + } } // This function is called by the compiler when dealing with array @@ -3270,40 +3291,8 @@ int __cmp(T1, T2)(T1[] s1, T2[] s2) static @trusted ref R at(R)(R[] r, size_t i) { return r.ptr[i]; } - // objects - // Old code went to object.d/TypeInfo_array.compare and then to - // object.d/TypeInfo_Class.compare - // which combined result in the same code as below. - static if (is(U1 : Object) && is(U2 : Object)) - { - immutable len = s1.length <= s2.length ? s1.length : s2.length; - - foreach (const u; 0 .. len) - { - auto o1 = at(s1, u); - auto o2 = at(s2, u); - - if (o1 is o2) - continue; - - // Regard null references as always being "less than" - if (o1) - { - if (!o2) - return 1; - auto c = o1.opCmp(o2); - if (c != 0) - return c; - } - else - { - return -1; - } - } - return s1.length < s2.length ? -1 : (s1.length > s2.length); - } - // Imaginary types - else static if (is(U1 == ifloat) || is(U1 == idouble) || is(U1 == ireal)) + // Use the same implementation for real and imaginary floats + static if (is(U1 == ifloat) || is(U1 == idouble) || is(U1 == ireal)) { // Special-case imaginary types to use comparison for "concrete" types static if (is(U1 == ifloat)) alias F = float; @@ -3321,23 +3310,22 @@ int __cmp(T1, T2)(T1[] s1, T2[] s2) import core.internal.string : dstrcmp; return (() @trusted => dstrcmp(cast(char[])s1, cast(char[])s2))(); } - // Everything else + // Everything else: class, interface, struct, other built-ins else { immutable len = s1.length <= s2.length ? s1.length : s2.length; foreach (const u; 0 .. len) { - // structs - static if (__traits(compiles, at(s1, u).opCmp(at(s2, u)))) + static if (__traits(compiles, __cmp(at(s1, u), at(s2, u)))) { - auto c = at(s1, u).opCmp(at(s2, u)); + auto c = __cmp(at(s1, u), at(s2, u)); if (c != 0) return c; } - else static if (__traits(compiles, __cmp(at(s1, u), at(s2, u)))) + else static if (__traits(compiles, at(s1, u).opCmp(at(s2, u)))) { - auto c = __cmp(at(s1, u), at(s2, u)); + auto c = at(s1, u).opCmp(at(s2, u)); if (c != 0) return c; } From 3d9ce7f80400cb8f77d5e4ca915c968ddb1c91d2 Mon Sep 17 00:00:00 2001 From: Andrei Alexandrescu Date: Mon, 6 Mar 2017 19:43:27 -0500 Subject: [PATCH 63/82] Fix __cmp for object types, was not even called --- src/object.d | 37 +++++++++++++++++-------------------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/src/object.d b/src/object.d index 84833b39d2..4f28490512 100644 --- a/src/object.d +++ b/src/object.d @@ -3242,19 +3242,19 @@ template RTInfo(T) } // Compare floating point numbers for ordering (one instantiation per width). -private int __cmp(F)(const F f1, const F f2) +private int __cmp(F)(const F lhs, const F rhs) if (__traits(isFloating, F)) { static if (is(F == cfloat) || is(F == cdouble) || is(F == creal)) { // Use rt.cmath2._Ccmp instead ? - auto r = __cmp(f1.re, f2.re); - if (!r) r = __cmp(f1.im, f2.im); + auto r = __cmp(lhs.re, lhs.re); + if (!r) r = __cmp(lhs.im, lhs.im); return r; } else { - return (f1 > f2) - (f2 > f1); + return (lhs > rhs) - (lhs > rhs); } } @@ -3262,21 +3262,14 @@ if (__traits(isFloating, F)) private int __cmp(Obj)(Obj lhs, Obj rhs) if (is(Obj : Object)) { - if (o1 is o2) + if (lhs is rhs) return 0; // Regard null references as always being "less than" - if (o1) - { - if (!o2) - return 1; - auto c = o1.opCmp(o2); - if (c != 0) - return c; - } - else - { + if (!lhs) return -1; - } + if (!rhs) + return 1; + return lhs.opCmp(rhs); } // This function is called by the compiler when dealing with array @@ -3413,14 +3406,14 @@ int __cmp(T1, T2)(T1[] s1, T2[] s2) } //objects -unittest +@safe unittest { class C { int i; this(int i) { this.i = i; } - override int opCmp(Object c) const + override int opCmp(Object c) const @safe { return i - (cast(C)c).i; } @@ -3428,12 +3421,16 @@ unittest auto c1 = new C(1); auto c2 = new C(2); + assert(__cmp(c1, null) > 0); + assert(__cmp(null, c1) < 0); + assert(__cmp(c1, c1) == 0); + assert(__cmp(c1, c2) < 0); + assert(__cmp(c2, c1) > 0); - assert(__cmp([c1, c1], [c2, c2]) < 0); + assert(__cmp([c1, c1][], [c2, c2][]) < 0); assert(__cmp([c2, c2], [c1, c1]) > 0); } - // Helper functions private inout(TypeInfo) getElement(inout TypeInfo value) @trusted pure nothrow From f3a0e19ab4a4cd377e847df7525ed45c7f23efa6 Mon Sep 17 00:00:00 2001 From: Andrei Alexandrescu Date: Mon, 6 Mar 2017 20:32:24 -0500 Subject: [PATCH 64/82] Fix copypasta mistake --- src/object.d | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/object.d b/src/object.d index 4f28490512..d02e149b23 100644 --- a/src/object.d +++ b/src/object.d @@ -3248,13 +3248,13 @@ if (__traits(isFloating, F)) static if (is(F == cfloat) || is(F == cdouble) || is(F == creal)) { // Use rt.cmath2._Ccmp instead ? - auto r = __cmp(lhs.re, lhs.re); - if (!r) r = __cmp(lhs.im, lhs.im); + auto r = __cmp(lhs.re, rhs.re); + if (!r) r = __cmp(lhs.im, rhs.im); return r; } else { - return (lhs > rhs) - (lhs > rhs); + return (lhs > rhs) - (lhs < rhs); } } From 51bdf2e83f2dd5ecc1b2d00d202457d1ba1b0c9f Mon Sep 17 00:00:00 2001 From: Temtaime Date: Tue, 7 Mar 2017 11:00:37 +0300 Subject: [PATCH 65/82] Add missing function to iconv. --- src/core/sys/posix/iconv.d | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/core/sys/posix/iconv.d b/src/core/sys/posix/iconv.d index 792778cd6e..b405092392 100644 --- a/src/core/sys/posix/iconv.d +++ b/src/core/sys/posix/iconv.d @@ -7,6 +7,7 @@ iconv_open(3) Allocates the descriptor for code conversion iconv(3) Performs the conversion + iconvctl(3) Control iconv behavior iconv_close(3) Deallocates allocated resources Copyright: Copyright (c) 2016 Sociomantic Labs. All rights reserved. @@ -20,6 +21,15 @@ module core.sys.posix.iconv; +enum +{ + ICONV_TRIVIALP = 0, /* int *argument */ + ICONV_GET_TRANSLITERATE = 1, /* int *argument */ + ICONV_SET_TRANSLITERATE = 2, /* const int *argument */ + ICONV_GET_DISCARD_ILSEQ = 3, /* int *argument */ + ICONV_SET_DISCARD_ILSEQ = 4, /* const int *argument */ +} + version (Posix): extern (C): nothrow: @@ -40,5 +50,10 @@ size_t iconv (iconv_t cd, in char** inbuf, char** outbuf, size_t* outbytesleft); +/// iconvctl queries or adjusts the behavior of the iconv function, +/// when invoked with the specified conversion descriptor, +/// depending on the request value. +int iconvctl (iconv_t cd, int request, void* argument); + /// Free resources allocated for descriptor CD for code conversion. int iconv_close (iconv_t cd); From ea250cce9b40c039fa0c363d14667e4e2fdd51c6 Mon Sep 17 00:00:00 2001 From: Temtaime Date: Tue, 7 Mar 2017 18:45:38 +0300 Subject: [PATCH 66/82] Update iconv.d --- src/core/sys/posix/iconv.d | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/sys/posix/iconv.d b/src/core/sys/posix/iconv.d index b405092392..14670f063d 100644 --- a/src/core/sys/posix/iconv.d +++ b/src/core/sys/posix/iconv.d @@ -21,7 +21,7 @@ module core.sys.posix.iconv; -enum +enum { ICONV_TRIVIALP = 0, /* int *argument */ ICONV_GET_TRANSLITERATE = 1, /* int *argument */ @@ -50,7 +50,7 @@ size_t iconv (iconv_t cd, in char** inbuf, char** outbuf, size_t* outbytesleft); -/// iconvctl queries or adjusts the behavior of the iconv function, +/// iconvctl queries or adjusts the behavior of the iconv function, /// when invoked with the specified conversion descriptor, /// depending on the request value. int iconvctl (iconv_t cd, int request, void* argument); From 24e775ad12171eaf4fd16b3feb578dc69354f5b4 Mon Sep 17 00:00:00 2001 From: Andrei Alexandrescu Date: Tue, 7 Mar 2017 10:56:09 -0500 Subject: [PATCH 67/82] Preserve legacy weird behavior by which structs and unions in arrays were compared with memcmp --- src/object.d | 109 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 67 insertions(+), 42 deletions(-) diff --git a/src/object.d b/src/object.d index d02e149b23..82224c2759 100644 --- a/src/object.d +++ b/src/object.d @@ -3272,10 +3272,34 @@ if (is(Obj : Object)) return lhs.opCmp(rhs); } +int __cmp(T)(const T[] lhs, const T[] rhs) @trusted +if (__traits(isScalar, T)) +{ + immutable len = lhs.length <= rhs.length ? lhs.length : rhs.length; + foreach (const u; 0 .. len) + { + static if (__traits(isFloating, T)) + { + auto r = __cmp(lhs.ptr[u], rhs.ptr[u]); + if (r) return r; + } + else static if (is(T == ubyte) || is(T == void) || is(T == bool) + || is(T == char)) + { + import core.internal.string : dstrcmp; + return dstrcmp(cast(char[]) lhs, cast(char[]) rhs); + } + else if (lhs.ptr[u] != rhs.ptr[u]) + return lhs.ptr[u] < rhs.ptr[u] ? -1 : 1; + } + return lhs.length < rhs.length ? -1 : (lhs.length > rhs.length); +} + // This function is called by the compiler when dealing with array // comparisons in the semantic analysis phase of CmpExp. The ordering // comparison is lowered to a call to this template. int __cmp(T1, T2)(T1[] s1, T2[] s2) +if (!__traits(isScalar, T1)) { import core.internal.traits : Unqual; alias U1 = Unqual!T1; @@ -3284,52 +3308,37 @@ int __cmp(T1, T2)(T1[] s1, T2[] s2) static @trusted ref R at(R)(R[] r, size_t i) { return r.ptr[i]; } - // Use the same implementation for real and imaginary floats - static if (is(U1 == ifloat) || is(U1 == idouble) || is(U1 == ireal)) - { - // Special-case imaginary types to use comparison for "concrete" types - static if (is(U1 == ifloat)) alias F = float; - else static if (is(U1 == idouble)) alias F = double; - else static if (is(U1 == ireal)) alias F = real; - - auto fpArray1 = () @trusted { return cast(F[])s1; }(); - auto fpArray2 = () @trusted { return cast(F[])s2; }(); - return __cmp(fpArray1, fpArray2); - } // All unsigned byte-wide types = > dstrcmp - else static if (is(U1 == ubyte) || is(U1 == void) || is(U1 == bool) - || is(U1 == char)) - { - import core.internal.string : dstrcmp; - return (() @trusted => dstrcmp(cast(char[])s1, cast(char[])s2))(); - } - // Everything else: class, interface, struct, other built-ins - else - { - immutable len = s1.length <= s2.length ? s1.length : s2.length; + immutable len = s1.length <= s2.length ? s1.length : s2.length; - foreach (const u; 0 .. len) + foreach (const u; 0 .. len) + { + static if (__traits(compiles, __cmp(at(s1, u), at(s2, u)))) { - static if (__traits(compiles, __cmp(at(s1, u), at(s2, u)))) - { - auto c = __cmp(at(s1, u), at(s2, u)); - if (c != 0) - return c; - } - else static if (__traits(compiles, at(s1, u).opCmp(at(s2, u)))) - { - auto c = at(s1, u).opCmp(at(s2, u)); - if (c != 0) - return c; - } - else - { - if (at(s1, u) != at(s2, u)) - return at(s1, u) < at(s2, u) ? -1 : 1; - } + auto c = __cmp(at(s1, u), at(s2, u)); + if (c != 0) + return c; + } + else static if (__traits(compiles, at(s1, u).opCmp(at(s2, u)))) + { + auto c = at(s1, u).opCmp(at(s2, u)); + if (c != 0) + return c; + } + else static if (__traits(compiles, at(s1, u) < at(s2, u))) + { + if (at(s1, u) != at(s2, u)) + return at(s1, u) < at(s2, u) ? -1 : 1; + } + else + { + // TODO: fix this legacy bad behavior, see + // https://issues.dlang.org/show_bug.cgi?id=17244 + import core.stdc.string : memcmp; + return (() @trusted => memcmp(&at(s1, u), &at(s2, u), U1.sizeof))(); } - return s1.length < s2.length ? -1 : (s1.length > s2.length); } + return s1.length < s2.length ? -1 : (s1.length > s2.length); } // integral types @@ -3405,7 +3414,7 @@ int __cmp(T1, T2)(T1[] s1, T2[] s2) compareMinMax!(immutable real); } -//objects +// objects @safe unittest { class C @@ -3431,6 +3440,22 @@ int __cmp(T1, T2)(T1[] s1, T2[] s2) assert(__cmp([c2, c2], [c1, c1]) > 0); } +// structs +@safe unittest +{ + struct C + { + ubyte i; + this(ubyte i) { this.i = i; } + } + + auto c1 = C(1); + auto c2 = C(2); + + assert(__cmp([c1, c1][], [c2, c2][]) < 0); + assert(__cmp([c2, c2], [c1, c1]) > 0); +} + // Helper functions private inout(TypeInfo) getElement(inout TypeInfo value) @trusted pure nothrow From 7d07225bda809f69106819da04a10ff8cd082c28 Mon Sep 17 00:00:00 2001 From: Andrei Alexandrescu Date: Tue, 7 Mar 2017 13:39:40 -0500 Subject: [PATCH 68/82] Further reduction of code --- src/object.d | 59 +++++++++++++++++++++++++--------------------------- 1 file changed, 28 insertions(+), 31 deletions(-) diff --git a/src/object.d b/src/object.d index 82224c2759..a14f2cadaa 100644 --- a/src/object.d +++ b/src/object.d @@ -3241,23 +3241,6 @@ template RTInfo(T) enum RTInfo = null; } -// Compare floating point numbers for ordering (one instantiation per width). -private int __cmp(F)(const F lhs, const F rhs) -if (__traits(isFloating, F)) -{ - static if (is(F == cfloat) || is(F == cdouble) || is(F == creal)) - { - // Use rt.cmath2._Ccmp instead ? - auto r = __cmp(lhs.re, rhs.re); - if (!r) r = __cmp(lhs.im, rhs.im); - return r; - } - else - { - return (lhs > rhs) - (lhs < rhs); - } -} - // Compare class and interface objects for ordering. private int __cmp(Obj)(Obj lhs, Obj rhs) if (is(Obj : Object)) @@ -3275,24 +3258,38 @@ if (is(Obj : Object)) int __cmp(T)(const T[] lhs, const T[] rhs) @trusted if (__traits(isScalar, T)) { - immutable len = lhs.length <= rhs.length ? lhs.length : rhs.length; - foreach (const u; 0 .. len) + static if (is(T == ubyte) || is(T == void) || is(T == bool) + || is(T == char)) { - static if (__traits(isFloating, T)) - { - auto r = __cmp(lhs.ptr[u], rhs.ptr[u]); - if (r) return r; - } - else static if (is(T == ubyte) || is(T == void) || is(T == bool) - || is(T == char)) + import core.internal.string : dstrcmp; + return dstrcmp(cast(char[]) lhs, cast(char[]) rhs); + } + else + { + immutable len = lhs.length <= rhs.length ? lhs.length : rhs.length; + foreach (const u; 0 .. len) { - import core.internal.string : dstrcmp; - return dstrcmp(cast(char[]) lhs, cast(char[]) rhs); + static if (__traits(isFloating, T)) + { + immutable a = lhs.ptr[u], b = rhs.ptr[u]; + static if (is(T == cfloat) || is(T == cdouble) + || is(T == creal)) + { + // Use rt.cmath2._Ccmp instead ? + auto r = (a.re > b.re) - (a.re < b.re); + if (!r) r = (a.im > b.im) - (a.im < a.im); + } + else + { + const r = (a > b) - (a < b); + } + if (r) return r; + } + else if (lhs.ptr[u] != rhs.ptr[u]) + return lhs.ptr[u] < rhs.ptr[u] ? -1 : 1; } - else if (lhs.ptr[u] != rhs.ptr[u]) - return lhs.ptr[u] < rhs.ptr[u] ? -1 : 1; + return lhs.length < rhs.length ? -1 : (lhs.length > rhs.length); } - return lhs.length < rhs.length ? -1 : (lhs.length > rhs.length); } // This function is called by the compiler when dealing with array From 8107d51eba00c2f68f6d1f9332d179d8413cf66f Mon Sep 17 00:00:00 2001 From: Andrei Alexandrescu Date: Tue, 7 Mar 2017 13:50:19 -0500 Subject: [PATCH 69/82] Aw what the heck implemented reuse of implementation for all builtin types --- src/object.d | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/src/object.d b/src/object.d index a14f2cadaa..c74deecf00 100644 --- a/src/object.d +++ b/src/object.d @@ -3258,12 +3258,32 @@ if (is(Obj : Object)) int __cmp(T)(const T[] lhs, const T[] rhs) @trusted if (__traits(isScalar, T)) { - static if (is(T == ubyte) || is(T == void) || is(T == bool) - || is(T == char)) + // Compute U as the implementation type for T + static if (is(T == ubyte) || is(T == void) || is(T == bool)) + alias U = char; + else static if (is(T == wchar)) + alias U = ushort; + else static if (is(T == dchar)) + alias U = uint; + else static if (is(T == ifloat)) + alias U = float; + else static if (is(T == idouble)) + alias U = double; + else static if (is(T == ireal)) + alias U = real; + else + alias U = T; + + static if (is(U == char)) { import core.internal.string : dstrcmp; return dstrcmp(cast(char[]) lhs, cast(char[]) rhs); } + else static if (!is(U == T)) + { + // Reuse another implementation + return __cmp(cast(U[]) lhs, cast(U[]) rhs); + } else { immutable len = lhs.length <= rhs.length ? lhs.length : rhs.length; From fc83c27b4acf6acd88e4ace21ae47d91603440c5 Mon Sep 17 00:00:00 2001 From: Andrei Alexandrescu Date: Tue, 7 Mar 2017 14:00:37 -0500 Subject: [PATCH 70/82] Oooops... --- src/object.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/object.d b/src/object.d index c74deecf00..fb1709450b 100644 --- a/src/object.d +++ b/src/object.d @@ -3297,7 +3297,7 @@ if (__traits(isScalar, T)) { // Use rt.cmath2._Ccmp instead ? auto r = (a.re > b.re) - (a.re < b.re); - if (!r) r = (a.im > b.im) - (a.im < a.im); + if (!r) r = (a.im > b.im) - (a.im < b.im); } else { From c996f02008d5c56e4c0dc275200c294bf8196943 Mon Sep 17 00:00:00 2001 From: Jonathan M Davis Date: Tue, 7 Mar 2017 21:42:15 -0800 Subject: [PATCH 71/82] Small code simplification in core.time. We already have the type with Args[i], so there's no need to ask args[i] for its type. --- src/core/time.d | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/time.d b/src/core/time.d index 69c288d3b0..c4e1aeaa33 100644 --- a/src/core/time.d +++ b/src/core/time.d @@ -1140,9 +1140,9 @@ public: foreach(i, unit; units) { static if(unit == "nsecs") - args[i] = cast(typeof(args[i]))convert!("hnsecs", "nsecs")(hnsecs); + args[i] = cast(Args[i])convert!("hnsecs", "nsecs")(hnsecs); else - args[i] = cast(typeof(args[i]))splitUnitsFromHNSecs!unit(hnsecs); + args[i] = cast(Args[i])splitUnitsFromHNSecs!unit(hnsecs); } } From f72b3fe1406bf12c924502d24a6737ab3ba02199 Mon Sep 17 00:00:00 2001 From: Martin Nowak Date: Thu, 9 Mar 2017 18:34:50 +0100 Subject: [PATCH 72/82] run pipeline outside of node block - to avoid executor startvation, see Dicebot/dlangci#30 --- Jenkinsfile | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index eb9fbdedab..aad543ddce 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -12,9 +12,11 @@ def clone (repo_url, git_ref = "master") { ) } +def pipeline node { dir('dlang/ci') { - clone 'https://github.com/Dicebot/dlangci.git' + cleanCheckout 'https://github.com/Dicebot/dlangci.git', 'master' } - load 'dlang/ci/pipeline.groovy' + pipeline = load 'dlang/ci/pipeline.groovy' } +pipeline.runPipeline() From 3d8d4a45c01832fb657c16a656b6e1566d77fb21 Mon Sep 17 00:00:00 2001 From: Nikolay Tolstokulakov Date: Thu, 4 Feb 2016 13:40:21 +0600 Subject: [PATCH 73/82] netbsd patch --- osmodel.mak | 3 + src/core/runtime.d | 16 + src/core/stdc/config.d | 2 + src/core/stdc/errno.d | 132 ++++++++ src/core/stdc/fenv.d | 46 +++ src/core/stdc/locale.d | 17 + src/core/stdc/math.d | 545 +++++++++++++++++++++++++++++++- src/core/stdc/stdio.d | 123 ++++++++ src/core/stdc/stdlib.d | 1 + src/core/stdc/string.d | 4 + src/core/stdc/tgmath.d | 549 +++++++++++++++++++++++++++++++++ src/core/stdc/time.d | 11 + src/core/thread.d | 27 ++ src/core/threadasm.S | 2 +- src/core/time.d | 18 ++ src/gc/os.d | 1 + src/rt/bss_section.c | 2 +- src/rt/dmain2.d | 4 + src/rt/sections.d | 2 + src/rt/sections_elf_shared.d | 33 ++ test/exceptions/line_trace.exp | 10 +- test/shared/src/load.d | 1 + 22 files changed, 1541 insertions(+), 8 deletions(-) diff --git a/osmodel.mak b/osmodel.mak index f56716a363..48e01f17d6 100644 --- a/osmodel.mak +++ b/osmodel.mak @@ -15,6 +15,9 @@ ifeq (,$(OS)) ifeq (OpenBSD,$(uname_S)) OS:=openbsd endif + ifeq (NetBSD,$(uname_S)) + OS:=netbsd + endif ifeq (Solaris,$(uname_S)) OS:=solaris endif diff --git a/src/core/runtime.d b/src/core/runtime.d index 184fed7b9a..4655391c5f 100644 --- a/src/core/runtime.d +++ b/src/core/runtime.d @@ -456,6 +456,8 @@ extern (C) bool runModuleUnitTests() import core.sys.darwin.execinfo; else version( FreeBSD ) import core.sys.freebsd.execinfo; + else version( NetBSD ) + import core.sys.netbsd.execinfo; else version( Windows ) import core.sys.windows.stacktrace; else version( Solaris ) @@ -538,6 +540,8 @@ Throwable.TraceInfo defaultTraceHandler( void* ptr = null ) import core.sys.darwin.execinfo; else version( FreeBSD ) import core.sys.freebsd.execinfo; + else version( NetBSD ) + import core.sys.netbsd.execinfo; else version( Windows ) import core.sys.windows.stacktrace; else version( Solaris ) @@ -735,6 +739,18 @@ Throwable.TraceInfo defaultTraceHandler( void* ptr = null ) symEnd = eptr - buf.ptr; } } + else version( NetBSD ) + { + // format is: 0x00000000 <_D6module4funcAFZv+0x78> at module + auto bptr = cast(char*) memchr( buf.ptr, '<', buf.length ); + auto eptr = cast(char*) memchr( buf.ptr, '+', buf.length ); + + if( bptr++ && eptr ) + { + symBeg = bptr - buf.ptr; + symEnd = eptr - buf.ptr; + } + } else version( Solaris ) { // format is object'symbol+offset [pc] diff --git a/src/core/stdc/config.d b/src/core/stdc/config.d index f5f4504d3f..f8931404c6 100644 --- a/src/core/stdc/config.d +++ b/src/core/stdc/config.d @@ -127,6 +127,8 @@ else version( DigitalMars ) alias real c_long_double; else version( OpenBSD ) alias real c_long_double; + else version( NetBSD ) + alias real c_long_double; else version( Solaris ) alias real c_long_double; else version( Darwin ) diff --git a/src/core/stdc/errno.d b/src/core/stdc/errno.d index 40f503e3ba..8d309b3a85 100644 --- a/src/core/stdc/errno.d +++ b/src/core/stdc/errno.d @@ -1110,6 +1110,138 @@ else version( FreeBSD ) enum EPROTO = 92; /// Protocol error enum ELAST = 92; /// Must be equal largest errno } +else version (NetBSD) +{ + // http://cvsweb.netbsd.org/bsdweb.cgi/~checkout~/src/sys/sys/errno.h + enum EPERM = 1; + enum ENOENT = 2; + enum ESRCH = 3; + enum EINTR = 4; + enum EIO = 5; + enum ENXIO = 6; + enum E2BIG = 7; + enum ENOEXEC = 8; + enum EBADF = 9; + enum ECHILD = 10; + enum EDEADLK = 11; + /// + enum ENOMEM = 12; + enum EACCES = 13; + enum EFAULT = 14; + enum ENOTBLK = 15; + enum EBUSY = 16; + enum EEXIST = 17; + enum EXDEV = 18; + enum ENODEV = 19; + enum ENOTDIR = 20; + enum EISDIR = 21; + enum EINVAL = 22; + enum ENFILE = 23; + enum EMFILE = 24; + enum ENOTTY = 25; + enum ETXTBSY = 26; + enum EFBIG = 27; + enum ENOSPC = 28; + enum ESPIPE = 29; + enum EROFS = 30; + enum EMLINK = 31; + enum EPIPE = 32; + /// + enum EDOM = 33; + enum ERANGE = 34; + + /// + enum EAGAIN = 35; + enum EWOULDBLOCK = EAGAIN; + enum EINPROGRESS = 36; + enum EALREADY = 37; + + /// + enum ENOTSOCK = 38; + enum EDESTADDRREQ = 39; + enum EMSGSIZE = 40; + enum EPROTOTYPE = 41; + enum ENOPROTOOPT = 42; + enum EPROTONOSUPPORT = 43; + enum ESOCKTNOSUPPORT = 44; + enum EOPNOTSUPP = 45; + enum EPFNOSUPPORT = 46; + enum EAFNOSUPPORT = 47; + enum EADDRINUSE = 48; + enum EADDRNOTAVAIL = 49; + + /// + enum ENETDOWN = 50; + enum ENETUNREACH = 51; + enum ENETRESET = 52; + enum ECONNABORTED = 53; + enum ECONNRESET = 54; + enum ENOBUFS = 55; + enum EISCONN = 56; + enum ENOTCONN = 57; + enum ESHUTDOWN = 58; + enum ETOOMANYREFS = 59; + enum ETIMEDOUT = 60; + enum ECONNREFUSED = 61; + enum ELOOP = 62; + enum ENAMETOOLONG = 63; + + /// + enum EHOSTDOWN = 64; + enum EHOSTUNREACH = 65; + enum ENOTEMPTY = 66; + + /// + enum EPROCLIM = 67; + enum EUSERS = 68; + enum EDQUOT = 69; + + /// + enum ESTALE = 70; + enum EREMOTE = 71; + enum EBADRPC = 72; + enum ERPCMISMATCH = 73; + enum EPROGUNAVAIL = 74; + enum EPROGMISMATCH = 75; + enum EPROCUNAVAIL = 76; + + enum ENOLCK = 77; + enum ENOSYS = 78; + + enum EFTYPE = 79; + enum EAUTH = 80; + enum ENEEDAUTH = 81; + + /// + enum EIDRM = 82; + enum ENOMSG = 83; + enum EOVERFLOW = 84; + /// + enum EILSEQ = 85; + + /// + enum ENOTSUP = 86; + + /// + enum ECANCELED = 87; + + /// + enum EBADMSG = 88; + + /// + enum ENODATA = 89; + enum ENOSR = 90; + enum ENOSTR = 91; + enum ETIME = 92; + + /// + enum ENOATTR = 93; + + /// + enum EMULTIHOP = 94; + enum ENOLINK = 95; + enum EPROTO = 96; +} else version( OpenBSD ) { enum EPERM = 1; /// Operation not permitted diff --git a/src/core/stdc/fenv.d b/src/core/stdc/fenv.d index 08a98bd6d8..0739075210 100644 --- a/src/core/stdc/fenv.d +++ b/src/core/stdc/fenv.d @@ -196,6 +196,46 @@ else version ( FreeBSD ) alias ushort fexcept_t; } +else version ( NetBSD ) +{ + version(X86_64) + { + struct fenv_t + { + struct _x87 + { + uint control; /* Control word register */ + uint status; /* Status word register */ + uint tag; /* Tag word register */ + uint[4] others; /* EIP, Pointer Selector, etc */ + }; + _x87 x87; + + uint mxcsr; /* Control and status register */ + } + } + version(X86) + { + struct fenv_t + { + struct _x87 + { + ushort control; /* Control word register */ + ushort unused1; + ushort status; /* Status word register */ + ushort unused2; + ushort tag; /* Tag word register */ + ushort unused3; + uint[4] others; /* EIP, Pointer Selector, etc */ + }; + _x87 x87; + uint32_t mxcsr; /* Control and status register */ + }; + + } + + alias uint fexcept_t; +} else version ( OpenBSD ) { struct fenv_t @@ -326,6 +366,12 @@ else version( FreeBSD ) /// enum FE_DFL_ENV = &__fe_dfl_env; } +else version( NetBSD ) +{ + private extern const fenv_t __fe_dfl_env; + /// + enum FE_DFL_ENV = &__fe_dfl_env; +} else version( OpenBSD ) { private extern const fenv_t __fe_dfl_env; diff --git a/src/core/stdc/locale.d b/src/core/stdc/locale.d index 8e602943f0..aa7c61ed98 100644 --- a/src/core/stdc/locale.d +++ b/src/core/stdc/locale.d @@ -135,6 +135,23 @@ else version(FreeBSD) /// enum LC_MESSAGES = 6; } +else version(NetBSD) +{ + /// + enum LC_ALL = 0; + /// + enum LC_COLLATE = 1; + /// + enum LC_CTYPE = 2; + /// + enum LC_MONETARY = 3; + /// + enum LC_NUMERIC = 4; + /// + enum LC_TIME = 5; + /// + enum LC_MESSAGES = 6; +} else version(OpenBSD) { /// diff --git a/src/core/stdc/math.d b/src/core/stdc/math.d index d8c1441b5d..e58afce314 100644 --- a/src/core/stdc/math.d +++ b/src/core/stdc/math.d @@ -53,6 +53,13 @@ version (FreeBSD) /// enum int FP_ILOGBNAN = int.max; } +else version (NetBSD) +{ + /// + enum int FP_ILOGB0 = -int.max; + /// + enum int FP_ILOGBNAN = int.max; +} else version (OpenBSD) { /// @@ -972,6 +979,97 @@ else version( OpenBSD ) int signbit(real x) { return __signbit(x); } } } +else version( NetBSD ) +{ + enum + { + /// + FP_INFINITE = 0, + /// + FP_NAN = 1, + /// + FP_NORMAL = 2, + /// + FP_SUBNORMAL = 3, + /// + FP_ZERO = 4, + } + + enum + { + /// + FP_FAST_FMA = 0, + /// + FP_FAST_FMAF = 0, + /// + FP_FAST_FMAL = 0, + } + + uint __fpclassifyf(float x); + uint __fpclassifyd(double x); + uint __fpclassifyl(real x); + + extern (D) + { + //int fpclassify(real-floating x); + /// + int fpclassify(float x) { return __fpclassifyf(x); } + /// + int fpclassify(double x) { return __fpclassifyd(x); } + /// + int fpclassify(real x) + { + return (real.sizeof == double.sizeof) + ? __fpclassifyd(x) + : __fpclassifyl(x); + } + + //int isfinite(real-floating x); + /// + int isfinite(float x) { return fpclassify(x) >= FP_NORMAL; } + /// + int isfinite(double x) { return fpclassify(x) >= FP_NORMAL; } + /// + int isfinite(real x) { return fpclassify(x) >= FP_NORMAL; } + + //int isinf(real-floating x); + /// + int isinf(float x) { return fpclassify(x) == FP_INFINITE; } + /// + int isinf(double x) { return fpclassify(x) == FP_INFINITE; } + /// + int isinf(real x) { return fpclassify(x) == FP_INFINITE; } + + //int isnan(real-floating x); + /// + int isnan(float x) { return fpclassify(x) == FP_NAN; } + /// + int isnan(double x) { return fpclassify(x) == FP_NAN; } + /// + int isnan(real x) { return fpclassify(x) == FP_NAN; } + + //int isnormal(real-floating x); + /// + int isnormal(float x) { return fpclassify(x) == FP_NORMAL; } + /// + int isnormal(double x) { return fpclassify(x) == FP_NORMAL; } + /// + int isnormal(real x) { return fpclassify(x) == FP_NORMAL; } + + //int signbit(real-floating x); + /// + int signbit(float x) { return (cast(short*)&(x))[1] & 0x8000; } + /// + int signbit(double x) { return (cast(short*)&(x))[3] & 0x8000; } + /// + int signbit(real x) + { + return (real.sizeof == double.sizeof) + ? (cast(short*)&(x))[3] & 0x8000 + : (cast(short*)&(x))[4] & 0x8000; + } + } +} else version( Solaris ) { int __isnanf(float x); @@ -1609,7 +1707,7 @@ else version( FreeBSD ) } else { - /// + /// real acosl(real x); /// real asinl(real x); @@ -2009,6 +2107,451 @@ else version( FreeBSD ) /// float fmaf(float x, float y, float z); } +else version(NetBSD) +{ + + /// + real acosl(real x); + /// + real asinl(real x); + /// + real atanl(real x); + /// + real atan2l(real y, real x); + /// + real cosl(real x); + /// + real sinl(real x); + /// + real tanl(real x); + /// + real exp2l(real x); + /// + real frexpl(real value, int* exp); + /// + int ilogbl(real x); + /// + real ldexpl(real x, int exp); + /// + real logbl(real x); + /// + real modfl(real value, real *iptr); + /// + real scalbnl(real x, int n); + /// + real scalblnl(real x, c_long n); + /// + real fabsl(real x); + /// + real hypotl(real x, real y); + /// + real sqrtl(real x); + /// + real ceill(real x); + /// + real floorl(real x); + /// + real nearbyintl(real x); + /// + real rintl(real x); + /// + c_long lrintl(real x) { return cast(c_long)rintl(x); } + /// + real roundl(real x); + /// + c_long lroundl(real x) { return cast(c_long)roundl(x);} + /// + long llroundl(real x) { return cast(long)roundl(x);} + /// + real truncl(real x); + /// + real fmodl(real x, real y); + /// + real remainderl(real x, real y) { return remainder(x,y); } + /// + real remquol(real x, real y, int* quo){ return remquo(x,y,quo); } + /// + real copysignl(real x, real y); + /// + double nan(char* tagp); + /// + float nanf(char* tagp); + /// + real nanl(char* tagp); + /// + real nextafterl(real x, real y); + /// + real nexttowardl(real x, real y) { return nexttoward(cast(double) x, cast(double) y); } + /// + real fdiml(real x, real y); + /// + real fmaxl(real x, real y); + /// + real fminl(real x, real y); + /// + real fmal(real x, real y, real z); + + /// + double acos(double x); + /// + float acosf(float x); + + /// + double asin(double x); + /// + float asinf(float x); + + /// + double atan(double x); + /// + float atanf(float x); + + /// + double atan2(double y, double x); + /// + float atan2f(float y, float x); + + /// + double cos(double x); + /// + float cosf(float x); + + /// + double sin(double x); + /// + float sinf(float x); + + /// + double tan(double x); + /// + float tanf(float x); + + /// + double acosh(double x); + /// + float acoshf(float x); + /// + real acoshl(real x); + + /// + double asinh(double x); + /// + float asinhf(float x); + /// + real asinhl(real x); + + /// + double atanh(double x); + /// + float atanhf(float x); + /// + real atanhl(real x); + + /// + double cosh(double x); + /// + float coshf(float x); + /// + real coshl(real x); + + /// + double sinh(double x); + /// + float sinhf(float x); + /// + real sinhl(real x); + + /// + double tanh(double x); + /// + float tanhf(float x); + /// + real tanhl(real x); + + /// + double exp(double x); + /// + float expf(float x); + /// + real expl(real x); + + /// + double exp2(double x); + /// + float exp2f(float x); + + /// + double expm1(double x); + /// + float expm1f(float x); + /// + real expm1l(real x) { return expm1(cast(double) x); } + + /// + double frexp(double value, int* exp); + /// + float frexpf(float value, int* exp); + + /// + int ilogb(double x); + /// + int ilogbf(float x); + + /// + double ldexp(double x, int exp); + /// + float ldexpf(float x, int exp); + + /// + double log(double x); + /// + float logf(float x); + /// NetBSD has no logl. It is just alias log(double) + real logl(real x) + { + if(x<0) return real.nan; + if(x==0) return -real.infinity; + if(isnan(x) || isinf(x)) return x; + real rs = 0; + if(x>double.max) + { + immutable MAX = log(double.max); + for(; x>double.max; x /= double.max) + rs += MAX; + } + else if(xdouble.max) + { + immutable MAX = log10(double.max); + for(; x>double.max; x /= double.max) + rs += MAX; + } + else if(x + { + char[128] _mbstate8; + long _mbstateL; + } +} else version ( OpenBSD ) { enum @@ -435,6 +469,50 @@ else version( FreeBSD ) /// alias shared(__sFILE) FILE; } +else version( NetBSD ) +{ + /// + alias off_t fpos_t; + + /// + struct __sFILE + { + ubyte* _p; + int _r; + int _w; + ushort _flags; + short _file; + __sbuf _bf; + int _lbfsize; + + void* _cookie; + int function(void*) _close; + ssize_t function(void*, char*, size_t) _read; + fpos_t function(void*, fpos_t, int) _seek; + ssize_t function(void*, in char*, size_t) _write; + + __sbuf _ub; + ubyte* _up; + int _ur; + + ubyte[3] _ubuf; + ubyte[1] _nbuf; + + int function(void *) _flush; + /* Formerly used by fgetln/fgetwln; kept for binary compatibility */ + char[__sbuf.sizeof - _flush.sizeof] _lb_unused; + + + int _blksize; + off_t _offset; + static assert(off_t.sizeof==8); + } + + /// + alias __sFILE _iobuf; + /// + alias shared(__sFILE) FILE; +} else version( OpenBSD ) { /// @@ -741,6 +819,29 @@ else version( FreeBSD ) /// alias __stderrp stderr; } +else version( NetBSD ) +{ + enum + { + /// + _IOFBF = 0, + /// + _IOLBF = 1, + /// + _IONBF = 2, + } + + private extern __gshared FILE[3] __sF; + @property auto __stdin() { return &__sF[0]; } + @property auto __stdout() { return &__sF[1]; } + @property auto __stderr() { return &__sF[2]; } + /// + alias __stdin stdin; + /// + alias __stdout stdout; + /// + alias __stderr stderr; +} else version( OpenBSD ) { enum @@ -1158,6 +1259,28 @@ else version( FreeBSD ) /// int vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg); } +else version( NetBSD ) +{ + // No unsafe pointer manipulation. + @trusted + { + /// + void rewind(FILE*); + /// + pure void clearerr(FILE*); + /// + pure int feof(FILE*); + /// + pure int ferror(FILE*); + /// + int fileno(FILE*); + } + + /// + int snprintf(char* s, size_t n, in char* format, ...); + /// + int vsnprintf(char* s, size_t n, in char* format, va_list arg); +} else version( OpenBSD ) { // No unsafe pointer manipulation. diff --git a/src/core/stdc/stdlib.d b/src/core/stdc/stdlib.d index 01b3722c9b..f3b8a7b7fb 100644 --- a/src/core/stdc/stdlib.d +++ b/src/core/stdc/stdlib.d @@ -75,6 +75,7 @@ version(Windows) enum RAND_MAX = 0x7fff; else version(CRuntime_Glibc) enum RAND_MAX = 0x7fffffff; else version(Darwin) enum RAND_MAX = 0x7fffffff; else version(FreeBSD) enum RAND_MAX = 0x7fffffff; +else version(NetBSD) enum RAND_MAX = 0x7fffffff; else version(OpenBSD) enum RAND_MAX = 0x7fffffff; else version(Solaris) enum RAND_MAX = 0x7fff; else version(CRuntime_Bionic) enum RAND_MAX = 0x7fffffff; diff --git a/src/core/stdc/string.d b/src/core/stdc/string.d index 103076de54..8135cfe9b5 100644 --- a/src/core/stdc/string.d +++ b/src/core/stdc/string.d @@ -89,6 +89,10 @@ else version (FreeBSD) { int strerror_r(int errnum, scope char* buf, size_t buflen); } +else version (NetBSD) +{ + int strerror_r(int errnum, char* buf, size_t buflen); +} else version (OpenBSD) { int strerror_r(int errnum, scope char* buf, size_t buflen); diff --git a/src/core/stdc/tgmath.d b/src/core/stdc/tgmath.d index d6fe71975f..8747008c2e 100644 --- a/src/core/stdc/tgmath.d +++ b/src/core/stdc/tgmath.d @@ -571,6 +571,555 @@ version( FreeBSD ) // alias core.stdc.complex.crealf creal; // alias core.stdc.complex.creall creal; } +version( NetBSD ) +{ + /// + alias core.stdc.math.acos acos; + /// + alias core.stdc.math.acosf acos; + /// + alias core.stdc.math.acosl acos; + + /// + alias core.stdc.complex.cacos acos; + /// + alias core.stdc.complex.cacosf acos; + /// + alias core.stdc.complex.cacosl acos; + + /// + alias core.stdc.math.asin asin; + /// + alias core.stdc.math.asinf asin; + /// + alias core.stdc.math.asinl asin; + + /// + alias core.stdc.complex.casin asin; + /// + alias core.stdc.complex.casinf asin; + /// + alias core.stdc.complex.casinl asin; + + /// + alias core.stdc.math.atan atan; + /// + alias core.stdc.math.atanf atan; + /// + alias core.stdc.math.atanl atan; + + /// + alias core.stdc.complex.catan atan; + /// + alias core.stdc.complex.catanf atan; + /// + alias core.stdc.complex.catanl atan; + + /// + alias core.stdc.math.atan2 atan2; + /// + alias core.stdc.math.atan2f atan2; + /// + alias core.stdc.math.atan2l atan2; + + /// + alias core.stdc.math.cos cos; + /// + alias core.stdc.math.cosf cos; + /// + alias core.stdc.math.cosl cos; + + /// + alias core.stdc.complex.ccos cos; + /// + alias core.stdc.complex.ccosf cos; + /// + alias core.stdc.complex.ccosl cos; + + /// + alias core.stdc.math.sin sin; + /// + alias core.stdc.math.sinf sin; + /// + alias core.stdc.math.sinl sin; + + /// + alias core.stdc.complex.csin csin; + /// + alias core.stdc.complex.csinf csin; + /// + alias core.stdc.complex.csinl csin; + + /// + alias core.stdc.math.tan tan; + /// + alias core.stdc.math.tanf tan; + /// + alias core.stdc.math.tanl tan; + + /// + alias core.stdc.complex.ctan tan; + /// + alias core.stdc.complex.ctanf tan; + /// + alias core.stdc.complex.ctanl tan; + + /// + alias core.stdc.math.acosh acosh; + /// + alias core.stdc.math.acoshf acosh; + /// + alias core.stdc.math.acoshl acosh; + + /// + alias core.stdc.complex.cacosh acosh; + /// + alias core.stdc.complex.cacoshf acosh; + /// + alias core.stdc.complex.cacoshl acosh; + + /// + alias core.stdc.math.asinh asinh; + /// + alias core.stdc.math.asinhf asinh; + /// + alias core.stdc.math.asinhl asinh; + + /// + alias core.stdc.complex.casinh asinh; + /// + alias core.stdc.complex.casinhf asinh; + /// + alias core.stdc.complex.casinhl asinh; + + /// + alias core.stdc.math.atanh atanh; + /// + alias core.stdc.math.atanhf atanh; + /// + alias core.stdc.math.atanhl atanh; + + /// + alias core.stdc.complex.catanh atanh; + /// + alias core.stdc.complex.catanhf atanh; + /// + alias core.stdc.complex.catanhl atanh; + + /// + alias core.stdc.math.cosh cosh; + /// + alias core.stdc.math.coshf cosh; + /// + alias core.stdc.math.coshl cosh; + + /// + alias core.stdc.complex.ccosh cosh; + /// + alias core.stdc.complex.ccoshf cosh; + /// + alias core.stdc.complex.ccoshl cosh; + + /// + alias core.stdc.math.sinh sinh; + /// + alias core.stdc.math.sinhf sinh; + /// + alias core.stdc.math.sinhl sinh; + + /// + alias core.stdc.complex.csinh sinh; + /// + alias core.stdc.complex.csinhf sinh; + /// + alias core.stdc.complex.csinhl sinh; + + /// + alias core.stdc.math.tanh tanh; + /// + alias core.stdc.math.tanhf tanh; + /// + alias core.stdc.math.tanhl tanh; + + /// + alias core.stdc.complex.ctanh tanh; + /// + alias core.stdc.complex.ctanhf tanh; + /// + alias core.stdc.complex.ctanhl tanh; + + /// + alias core.stdc.math.exp exp; + /// + alias core.stdc.math.expf exp; + /// + alias core.stdc.math.expl exp; + + /// + alias core.stdc.complex.cexp exp; + /// + alias core.stdc.complex.cexpf exp; + /// + alias core.stdc.complex.cexpl exp; + + /// + alias core.stdc.math.exp2 exp2; + /// + alias core.stdc.math.exp2f exp2; + /// + alias core.stdc.math.exp2l exp2; + + /// + alias core.stdc.math.expm1 expm1; + /// + alias core.stdc.math.expm1f expm1; + /// + alias core.stdc.math.expm1l expm1; + + /// + alias core.stdc.math.frexp frexp; + /// + alias core.stdc.math.frexpf frexp; + /// + alias core.stdc.math.frexpl frexp; + + /// + alias core.stdc.math.ilogb ilogb; + /// + alias core.stdc.math.ilogbf ilogb; + /// + alias core.stdc.math.ilogbl ilogb; + + /// + alias core.stdc.math.ldexp ldexp; + /// + alias core.stdc.math.ldexpf ldexp; + /// + alias core.stdc.math.ldexpl ldexp; + + /// + alias core.stdc.math.log log; + /// + alias core.stdc.math.logf log; + /// + alias core.stdc.math.logl log; + + /// + alias core.stdc.complex.clog log; + /// + alias core.stdc.complex.clogf log; + /// + alias core.stdc.complex.clogl log; + + /// + alias core.stdc.math.log10 log10; + /// + alias core.stdc.math.log10f log10; + /// + alias core.stdc.math.log10l log10; + + /// + alias core.stdc.math.log1p log1p; + /// + alias core.stdc.math.log1pf log1p; + /// + alias core.stdc.math.log1pl log1p; + + /// + alias core.stdc.math.log2 log2; + /// + alias core.stdc.math.log2f log2; + /// + alias core.stdc.math.log2l log2; + + /// + alias core.stdc.math.logb logb; + /// + alias core.stdc.math.logbf logb; + /// + alias core.stdc.math.logbl logb; + + /// + alias core.stdc.math.modf modf; + /// + alias core.stdc.math.modff modf; +// alias core.stdc.math.modfl modf; + + /// + alias core.stdc.math.scalbn scalbn; + /// + alias core.stdc.math.scalbnf scalbn; + /// + alias core.stdc.math.scalbnl scalbn; + + /// + alias core.stdc.math.scalbln scalbln; + /// + alias core.stdc.math.scalblnf scalbln; + /// + alias core.stdc.math.scalblnl scalbln; + + /// + alias core.stdc.math.cbrt cbrt; + /// + alias core.stdc.math.cbrtf cbrt; + /// + alias core.stdc.math.cbrtl cbrt; + + /// + alias core.stdc.math.fabs fabs; + /// + alias core.stdc.math.fabsf fabs; + /// + alias core.stdc.math.fabsl fabs; + + /// + alias core.stdc.complex.cabs fabs; + /// + alias core.stdc.complex.cabsf fabs; + /// + alias core.stdc.complex.cabsl fabs; + + /// + alias core.stdc.math.hypot hypot; + /// + alias core.stdc.math.hypotf hypot; + /// + alias core.stdc.math.hypotl hypot; + + /// + alias core.stdc.math.pow pow; + /// + alias core.stdc.math.powf pow; + /// + alias core.stdc.math.powl pow; + + /// + alias core.stdc.complex.cpow pow; + /// + alias core.stdc.complex.cpowf pow; + /// + alias core.stdc.complex.cpowl pow; + + /// + alias core.stdc.math.sqrt sqrt; + /// + alias core.stdc.math.sqrtf sqrt; + /// + alias core.stdc.math.sqrtl sqrt; + + /// + alias core.stdc.complex.csqrt sqrt; + /// + alias core.stdc.complex.csqrtf sqrt; + /// + alias core.stdc.complex.csqrtl sqrt; + + /// + alias core.stdc.math.erf erf; + /// + alias core.stdc.math.erff erf; + /// + alias core.stdc.math.erfl erf; + + /// + alias core.stdc.math.erfc erfc; + /// + alias core.stdc.math.erfcf erfc; + /// + alias core.stdc.math.erfcl erfc; + + /// + alias core.stdc.math.lgamma lgamma; + /// + alias core.stdc.math.lgammaf lgamma; + /// + alias core.stdc.math.lgammal lgamma; + + /// + alias core.stdc.math.tgamma tgamma; + /// + alias core.stdc.math.tgammaf tgamma; + /// + alias core.stdc.math.tgammal tgamma; + + /// + alias core.stdc.math.ceil ceil; + /// + alias core.stdc.math.ceilf ceil; + /// + alias core.stdc.math.ceill ceil; + + /// + alias core.stdc.math.floor floor; + /// + alias core.stdc.math.floorf floor; + /// + alias core.stdc.math.floorl floor; + + /// + alias core.stdc.math.nearbyint nearbyint; + /// + alias core.stdc.math.nearbyintf nearbyint; + /// + alias core.stdc.math.nearbyintl nearbyint; + + /// + alias core.stdc.math.rint rint; + /// + alias core.stdc.math.rintf rint; + /// + alias core.stdc.math.rintl rint; + + /// + alias core.stdc.math.lrint lrint; + /// + alias core.stdc.math.lrintf lrint; + /// + alias core.stdc.math.lrintl lrint; + + /// + alias core.stdc.math.llrint llrint; + /// + alias core.stdc.math.llrintf llrint; + /// + alias core.stdc.math.llrintl llrint; + + /// + alias core.stdc.math.round round; + /// + alias core.stdc.math.roundf round; + /// + alias core.stdc.math.roundl round; + + /// + alias core.stdc.math.lround lround; + /// + alias core.stdc.math.lroundf lround; + /// + alias core.stdc.math.lroundl lround; + + /// + alias core.stdc.math.llround llroundl; + /// + alias core.stdc.math.llroundf llroundl; + /// + alias core.stdc.math.llroundl llroundl; + + /// + alias core.stdc.math.trunc trunc; + /// + alias core.stdc.math.truncf trunc; + /// + alias core.stdc.math.truncl trunc; + + /// + alias core.stdc.math.fmod fmod; + /// + alias core.stdc.math.fmodf fmod; + /// + alias core.stdc.math.fmodl fmod; + + /// + alias core.stdc.math.remainder remainder; + /// + alias core.stdc.math.remainderf remainder; + /// + alias core.stdc.math.remainderl remainder; + + /// + alias core.stdc.math.remquo remquo; + /// + alias core.stdc.math.remquof remquo; + /// + alias core.stdc.math.remquol remquo; + + /// + alias core.stdc.math.copysign copysign; + /// + alias core.stdc.math.copysignf copysign; + /// + alias core.stdc.math.copysignl copysign; + +// alias core.stdc.math.nan nan; +// alias core.stdc.math.nanf nan; +// alias core.stdc.math.nanl nan; + + /// + alias core.stdc.math.nextafter nextafter; + /// + alias core.stdc.math.nextafterf nextafter; + /// + alias core.stdc.math.nextafterl nextafter; + + /// + alias core.stdc.math.nexttoward nexttoward; + /// + alias core.stdc.math.nexttowardf nexttoward; + /// + alias core.stdc.math.nexttowardl nexttoward; + + /// + alias core.stdc.math.fdim fdim; + /// + alias core.stdc.math.fdimf fdim; + /// + alias core.stdc.math.fdiml fdim; + + /// + alias core.stdc.math.fmax fmax; + /// + alias core.stdc.math.fmaxf fmax; + /// + alias core.stdc.math.fmaxl fmax; + + /// + alias core.stdc.math.fmin fmin; + /// + alias core.stdc.math.fmin fmin; + /// + alias core.stdc.math.fminl fmin; + + /// + alias core.stdc.math.fma fma; + /// + alias core.stdc.math.fmaf fma; + /// + alias core.stdc.math.fmal fma; + + /// + alias core.stdc.complex.carg carg; + /// + alias core.stdc.complex.cargf carg; + /// + alias core.stdc.complex.cargl carg; + + /// + alias core.stdc.complex.cimag cimag; + /// + alias core.stdc.complex.cimagf cimag; + /// + alias core.stdc.complex.cimagl cimag; + + /// + alias core.stdc.complex.conj conj; + /// + alias core.stdc.complex.conjf conj; + /// + alias core.stdc.complex.conjl conj; + + /// + alias core.stdc.complex.cproj cproj; + /// + alias core.stdc.complex.cprojf cproj; + /// + alias core.stdc.complex.cprojl cproj; + +// alias core.stdc.complex.creal creal; +// alias core.stdc.complex.crealf creal; +// alias core.stdc.complex.creall creal; +} + else version( OpenBSD ) { /// diff --git a/src/core/stdc/time.d b/src/core/stdc/time.d index 57ae25a064..4325ca3429 100644 --- a/src/core/stdc/time.d +++ b/src/core/stdc/time.d @@ -95,6 +95,10 @@ else version( FreeBSD ) { enum clock_t CLOCKS_PER_SEC = 128; } +else version( NetBSD ) +{ + enum clock_t CLOCKS_PER_SEC = 100; +} else version( OpenBSD ) { enum clock_t CLOCKS_PER_SEC = 100; @@ -162,6 +166,13 @@ else version( FreeBSD ) /// extern __gshared const(char)*[2] tzname; // non-standard } +else version( NetBSD ) +{ + /// + void tzset(); // non-standard + /// + extern __gshared const(char)*[2] tzname; // non-standard +} else version( OpenBSD ) { /// diff --git a/src/core/thread.d b/src/core/thread.d index 6beb3b034d..0c9904ce15 100644 --- a/src/core/thread.d +++ b/src/core/thread.d @@ -936,6 +936,12 @@ class Thread */ __gshared const int PRIORITY_DEFAULT; + version(NetBSD) + { + //NetBSD does not support priority for default policy + // and it is not possible change policy without root access + int fakePriority = int.max; + } /** * Gets the scheduling priority for the associated thread. @@ -952,6 +958,10 @@ class Thread { return GetThreadPriority( m_hndl ); } + else version(NetBSD) + { + return fakePriority==int.max? PRIORITY_DEFAULT : fakePriority; + } else version( Posix ) { int policy; @@ -1016,6 +1026,10 @@ class Thread if (priocntl(idtype_t.P_LWPID, P_MYID, PC_SETPARMS, &pcparm) == -1) throw new ThreadException( "Unable to set scheduling class" ); } + else version(NetBSD) + { + fakePriority = val; + } else version( Posix ) { static if(__traits(compiles, pthread_setschedprio)) @@ -3127,6 +3141,7 @@ extern (C) @nogc nothrow { version (CRuntime_Glibc) int pthread_getattr_np(pthread_t thread, pthread_attr_t* attr); version (FreeBSD) int pthread_attr_get_np(pthread_t thread, pthread_attr_t* attr); + version (NetBSD) int pthread_attr_get_np(pthread_t thread, pthread_attr_t* attr); version (Solaris) int thr_stksegment(stack_t* stk); version (CRuntime_Bionic) int pthread_getattr_np(pthread_t thid, pthread_attr_t* attr); } @@ -3187,6 +3202,17 @@ private void* getStackBottom() nothrow @nogc pthread_attr_destroy(&attr); return addr + size; } + else version (NetBSD) + { + pthread_attr_t attr; + void* addr; size_t size; + + pthread_attr_init(&attr); + pthread_attr_get_np(pthread_self(), &attr); + pthread_attr_getstack(&attr, &addr, &size); + pthread_attr_destroy(&attr); + return addr + size; + } else version (Solaris) { stack_t stk; @@ -4397,6 +4423,7 @@ private: { version (Posix) import core.sys.posix.sys.mman; // mmap version (FreeBSD) import core.sys.freebsd.sys.mman : MAP_ANON; + version (NetBSD) import core.sys.netbsd.sys.mman : MAP_ANON; version (CRuntime_Glibc) import core.sys.linux.sys.mman : MAP_ANON; version (Darwin) import core.sys.darwin.sys.mman : MAP_ANON; diff --git a/src/core/threadasm.S b/src/core/threadasm.S index 94acbef7ba..6c068abd4b 100644 --- a/src/core/threadasm.S +++ b/src/core/threadasm.S @@ -13,7 +13,7 @@ * http://www.boost.org/LICENSE_1_0.txt) */ -#if (defined(__linux__) || defined(__FreeBSD__)) && defined(__ELF__) +#if (defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__)) && defined(__ELF__) /* * Mark the resulting object file as not requiring execution permissions on * stack memory. The absence of this section would mark the whole resulting diff --git a/src/core/time.d b/src/core/time.d index 69c288d3b0..d3a734dda1 100644 --- a/src/core/time.d +++ b/src/core/time.d @@ -313,6 +313,13 @@ else version(FreeBSD) enum ClockType uptimeCoarse = 9, uptimePrecise = 10, } +else version(NetBSD) enum ClockType +{ + normal = 0, + coarse = 2, + precise = 3, + second = 6, +} else version(Solaris) enum ClockType { normal = 0, @@ -368,6 +375,17 @@ version(Posix) case second: assert(0); } } + else version(NetBSD) + { + import core.sys.netbsd.time; + with(ClockType) final switch(clockType) + { + case coarse: return CLOCK_MONOTONIC; + case normal: return CLOCK_MONOTONIC; + case precise: return CLOCK_MONOTONIC; + case second: assert(0); + } + } else version(Solaris) { import core.sys.solaris.time; diff --git a/src/gc/os.d b/src/gc/os.d index 2593d8f26c..f5eae0eb74 100644 --- a/src/gc/os.d +++ b/src/gc/os.d @@ -40,6 +40,7 @@ else version (Posix) import core.sys.posix.sys.mman; version (FreeBSD) import core.sys.freebsd.sys.mman : MAP_ANON; + version (NetBSD) import core.sys.netbsd.sys.mman : MAP_ANON; version (CRuntime_Glibc) import core.sys.linux.sys.mman : MAP_ANON; version (Darwin) import core.sys.darwin.sys.mman : MAP_ANON; import core.stdc.stdlib; diff --git a/src/rt/bss_section.c b/src/rt/bss_section.c index 939ecb2790..b00f40d51c 100644 --- a/src/rt/bss_section.c +++ b/src/rt/bss_section.c @@ -10,7 +10,7 @@ /* These symbols are defined in the linker script and bracket the * .bss, .lbss, .lrodata and .ldata sections. */ -#if defined(__linux__) || defined(__FreeBSD__) +#if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) // Need to use weak linkage to workaround a bug in ld.bfd (Bugzilla 13025). extern int __attribute__((weak)) __bss_start, _end; diff --git a/src/rt/dmain2.d b/src/rt/dmain2.d index f17ca91004..2473f2d880 100644 --- a/src/rt/dmain2.d +++ b/src/rt/dmain2.d @@ -35,6 +35,10 @@ version (FreeBSD) { import core.stdc.fenv; } +version (NetBSD) +{ + import core.stdc.fenv; +} extern (C) void _d_monitor_staticctor(); extern (C) void _d_monitor_staticdtor(); diff --git a/src/rt/sections.d b/src/rt/sections.d index 0cbd5e594f..a12b73fb13 100644 --- a/src/rt/sections.d +++ b/src/rt/sections.d @@ -23,6 +23,8 @@ version (CRuntime_Glibc) public import rt.sections_elf_shared; else version (FreeBSD) public import rt.sections_elf_shared; +else version (NetBSD) + public import rt.sections_elf_shared; else version (Solaris) public import rt.sections_solaris; else version (Darwin) diff --git a/src/rt/sections_elf_shared.d b/src/rt/sections_elf_shared.d index ba9ef98a89..a95328b5fb 100644 --- a/src/rt/sections_elf_shared.d +++ b/src/rt/sections_elf_shared.d @@ -12,6 +12,7 @@ module rt.sections_elf_shared; version (CRuntime_Glibc) enum SharedELF = true; else version (FreeBSD) enum SharedELF = true; +else version (NetBSD) enum SharedELF = true; else enum SharedELF = false; static if (SharedELF): @@ -32,6 +33,12 @@ else version (FreeBSD) import core.sys.freebsd.sys.elf; import core.sys.freebsd.sys.link_elf; } +else version (NetBSD) +{ + import core.sys.netbsd.dlfcn; + import core.sys.netbsd.sys.elf; + import core.sys.netbsd.sys.link_elf; +} else { static assert(0, "unimplemented"); @@ -114,6 +121,7 @@ __gshared bool _isRuntimeInitialized; version (FreeBSD) private __gshared void* dummy_ref; +version (NetBSD) private __gshared void* dummy_ref; /**** * Gets called on program startup just before GC is initialized. @@ -123,6 +131,7 @@ void initSections() nothrow @nogc _isRuntimeInitialized = true; // reference symbol to support weak linkage version (FreeBSD) dummy_ref = &_d_dso_registry; + version (NetBSD) dummy_ref = &_d_dso_registry; } @@ -252,6 +261,7 @@ private: // start of linked list for ModuleInfo references version (FreeBSD) deprecated extern (C) __gshared void* _Dmodule_ref; +version (NetBSD) deprecated extern (C) __gshared void* _Dmodule_ref; version (Shared) { @@ -663,6 +673,8 @@ version (Shared) strtab = cast(const(char)*)dyn.d_un.d_ptr; else version (FreeBSD) strtab = cast(const(char)*)(info.dlpi_addr + dyn.d_un.d_ptr); // relocate + else version (NetBSD) + strtab = cast(const(char)*)(info.dlpi_addr + dyn.d_un.d_ptr); // relocate else static assert(0, "unimplemented"); break; @@ -768,6 +780,23 @@ else version (FreeBSD) bool findDSOInfoForAddr(in void* addr, dl_phdr_info* resu { return !!_rtld_addr_phdr(addr, result); } +else version (NetBSD) bool findDSOInfoForAddr(in void* addr, dl_phdr_info* result=null) nothrow @nogc +{ + static struct DG { const(void)* addr; dl_phdr_info* result; } + + extern(C) int callback(dl_phdr_info* info, size_t sz, void* arg) nothrow @nogc + { + auto p = cast(DG*)arg; + if (findSegmentForAddr(*info, p.addr)) + { + if (p.result !is null) *p.result = *info; + return 1; // break; + } + return 0; // continue iteration + } + auto dg = DG(addr, result); + return dl_iterate_phdr(&callback, &dg) != 0; +} /********************************* * Determine if 'addr' lies within shared object 'info'. @@ -793,11 +822,13 @@ bool findSegmentForAddr(in ref dl_phdr_info info, in void* addr, ElfW!"Phdr"* re version (linux) import core.sys.linux.errno : program_invocation_name; // should be in core.sys.freebsd.stdlib version (FreeBSD) extern(C) const(char)* getprogname() nothrow @nogc; +version (NetBSD) extern(C) const(char)* getprogname() nothrow @nogc; @property const(char)* progname() nothrow @nogc { version (linux) return program_invocation_name; version (FreeBSD) return getprogname(); + version (NetBSD) return getprogname(); } const(char)[] dsoName(const char* dlpi_name) nothrow @nogc @@ -836,6 +867,8 @@ const(void)[] getCopyRelocSection() nothrow @nogc enum ElfW!"Addr" exeBaseAddr = 0; else version (FreeBSD) enum ElfW!"Addr" exeBaseAddr = 0; + else version (NetBSD) + enum ElfW!"Addr" exeBaseAddr = 0; dl_phdr_info info = void; findDSOInfoForAddr(bss_start, &info) || assert(0); diff --git a/test/exceptions/line_trace.exp b/test/exceptions/line_trace.exp index c0909b653b..d0111a0360 100644 --- a/test/exceptions/line_trace.exp +++ b/test/exceptions/line_trace.exp @@ -2,8 +2,8 @@ object.Exception@src/line_trace.d(17): exception ---------------- src/line_trace.d:17 void line_trace.f1() [ADDR] src/line_trace.d:5 _Dmain [ADDR] -src/rt/dmain2.d:472 _D2rt6dmain211_d_run_mainUiPPaPUAAaZiZ6runAllMFZ9__lambda1MFZv [ADDR] -src/rt/dmain2.d:447 void rt.dmain2._d_run_main(int, char**, extern (C) int function(char[][])*).tryExec(void delegate()) [ADDR] -src/rt/dmain2.d:472 void rt.dmain2._d_run_main(int, char**, extern (C) int function(char[][])*).runAll() [ADDR] -src/rt/dmain2.d:447 void rt.dmain2._d_run_main(int, char**, extern (C) int function(char[][])*).tryExec(void delegate()) [ADDR] -src/rt/dmain2.d:480 _d_run_main [ADDR] +src/rt/dmain2.d:476 _D2rt6dmain211_d_run_mainUiPPaPUAAaZiZ6runAllMFZ9__lambda1MFZv [ADDR] +src/rt/dmain2.d:451 void rt.dmain2._d_run_main(int, char**, extern (C) int function(char[][])*).tryExec(void delegate()) [ADDR] +src/rt/dmain2.d:476 void rt.dmain2._d_run_main(int, char**, extern (C) int function(char[][])*).runAll() [ADDR] +src/rt/dmain2.d:451 void rt.dmain2._d_run_main(int, char**, extern (C) int function(char[][])*).tryExec(void delegate()) [ADDR] +src/rt/dmain2.d:484 _d_run_main [ADDR] diff --git a/test/shared/src/load.d b/test/shared/src/load.d index 4b114a6d07..c23302117f 100644 --- a/test/shared/src/load.d +++ b/test/shared/src/load.d @@ -2,6 +2,7 @@ import core.runtime, core.stdc.stdio, core.thread; version (linux) import core.sys.linux.dlfcn; else version (FreeBSD) import core.sys.freebsd.dlfcn; +else version (NetBSD) import core.sys.netbsd.dlfcn; else static assert(0, "unimplemented"); void loadSym(T)(void* handle, ref T val, const char* mangle) From 0b1172b7a58259213d49680f754de58da7131b65 Mon Sep 17 00:00:00 2001 From: Martin Nowak Date: Fri, 10 Mar 2017 15:58:39 +0100 Subject: [PATCH 74/82] fix Jenkinsfile --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index aad543ddce..b6ae0190e5 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -15,7 +15,7 @@ def clone (repo_url, git_ref = "master") { def pipeline node { dir('dlang/ci') { - cleanCheckout 'https://github.com/Dicebot/dlangci.git', 'master' + clone 'https://github.com/Dicebot/dlangci.git', 'master' } pipeline = load 'dlang/ci/pipeline.groovy' } From 2b736083aabc96a6b21cac3a5b86023732507872 Mon Sep 17 00:00:00 2001 From: Martin Nowak Date: Fri, 10 Mar 2017 18:20:35 +0100 Subject: [PATCH 75/82] trailing ws --- src/core/sys/posix/iconv.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/sys/posix/iconv.d b/src/core/sys/posix/iconv.d index 14670f063d..1bde829f52 100644 --- a/src/core/sys/posix/iconv.d +++ b/src/core/sys/posix/iconv.d @@ -51,7 +51,7 @@ size_t iconv (iconv_t cd, in char** inbuf, size_t* outbytesleft); /// iconvctl queries or adjusts the behavior of the iconv function, -/// when invoked with the specified conversion descriptor, +/// when invoked with the specified conversion descriptor, /// depending on the request value. int iconvctl (iconv_t cd, int request, void* argument); From dd13e98dca241718a53c514a3e0d6a90a96e1422 Mon Sep 17 00:00:00 2001 From: Nikolay Tolstokulakov Date: Thu, 4 Feb 2016 13:38:50 +0600 Subject: [PATCH 76/82] netbsd patch: core/sys/posix --- src/core/stdc/tgmath.d | 1 - src/core/sys/posix/arpa/inet.d | 29 +++ src/core/sys/posix/dirent.d | 46 +++++ src/core/sys/posix/dlfcn.d | 23 +++ src/core/sys/posix/fcntl.d | 53 ++++++ src/core/sys/posix/grp.d | 21 +++ src/core/sys/posix/net/if_.d | 15 ++ src/core/sys/posix/netdb.d | 107 +++++++++++ src/core/sys/posix/netinet/in_.d | 178 ++++++++++++++++++ src/core/sys/posix/netinet/tcp.d | 4 + src/core/sys/posix/poll.d | 34 ++++ src/core/sys/posix/pthread.d | 146 +++++++++++++++ src/core/sys/posix/pwd.d | 29 +++ src/core/sys/posix/sched.d | 21 +++ src/core/sys/posix/semaphore.d | 10 ++ src/core/sys/posix/setjmp.d | 43 +++++ src/core/sys/posix/signal.d | 290 +++++++++++++++++++++++++++++- src/core/sys/posix/stdio.d | 4 + src/core/sys/posix/stdlib.d | 56 ++++++ src/core/sys/posix/sys/ioctl.d | 12 ++ src/core/sys/posix/sys/ipc.d | 25 +++ src/core/sys/posix/sys/mman.d | 59 ++++++ src/core/sys/posix/sys/resource.d | 64 +++++++ src/core/sys/posix/sys/select.d | 49 +++++ src/core/sys/posix/sys/shm.d | 26 +++ src/core/sys/posix/sys/socket.d | 211 ++++++++++++++++++++++ src/core/sys/posix/sys/stat.d | 84 +++++++++ src/core/sys/posix/sys/time.d | 19 ++ src/core/sys/posix/sys/types.d | 103 +++++++++++ src/core/sys/posix/sys/uio.d | 11 ++ src/core/sys/posix/sys/un.d | 9 + src/core/sys/posix/sys/utsname.d | 16 ++ src/core/sys/posix/sys/wait.d | 28 +++ src/core/sys/posix/syslog.d | 65 +++++++ src/core/sys/posix/termios.d | 142 +++++++++++++++ src/core/sys/posix/time.d | 45 +++++ src/core/sys/posix/ucontext.d | 56 ++++++ src/core/sys/posix/unistd.d | 171 ++++++++++++++++++ src/core/sys/posix/utime.d | 10 ++ 39 files changed, 2313 insertions(+), 2 deletions(-) diff --git a/src/core/stdc/tgmath.d b/src/core/stdc/tgmath.d index 8747008c2e..901e656d5f 100644 --- a/src/core/stdc/tgmath.d +++ b/src/core/stdc/tgmath.d @@ -1119,7 +1119,6 @@ version( NetBSD ) // alias core.stdc.complex.crealf creal; // alias core.stdc.complex.creall creal; } - else version( OpenBSD ) { /// diff --git a/src/core/sys/posix/arpa/inet.d b/src/core/sys/posix/arpa/inet.d index 552e68acfb..675a197e6d 100644 --- a/src/core/sys/posix/arpa/inet.d +++ b/src/core/sys/posix/arpa/inet.d @@ -133,6 +133,31 @@ else version( FreeBSD ) const(char)* inet_ntop(int, in void*, char*, socklen_t); int inet_pton(int, in char*, void*); } +else version(NetBSD) +{ + alias uint16_t in_port_t; + alias uint32_t in_addr_t; + + struct in_addr + { + in_addr_t s_addr; + } + + enum INET_ADDRSTRLEN = 16; + + @trusted pure + { + uint32_t htonl(uint32_t); + uint16_t htons(uint16_t); + uint32_t ntohl(uint32_t); + uint16_t ntohs(uint16_t); + } + + in_addr_t inet_addr(in char*); + char* inet_ntoa(in_addr); + const(char)* inet_ntop(int, in void*, char*, socklen_t); + int inet_pton(int, in char*, void*); +} else version( Solaris ) { alias uint16_t in_port_t; @@ -220,6 +245,10 @@ else version( FreeBSD ) { enum INET6_ADDRSTRLEN = 46; } +else version(NetBSD) +{ + enum INET6_ADDRSTRLEN = 46; +} else version( Solaris ) { enum INET6_ADDRSTRLEN = 46; diff --git a/src/core/sys/posix/dirent.d b/src/core/sys/posix/dirent.d index 0b332157af..5a51cc7378 100644 --- a/src/core/sys/posix/dirent.d +++ b/src/core/sys/posix/dirent.d @@ -162,6 +162,35 @@ else version( FreeBSD ) dirent* readdir(DIR*); } +else version(NetBSD) +{ + enum + { + DT_UNKNOWN = 0, + DT_FIFO = 1, + DT_CHR = 2, + DT_DIR = 4, + DT_BLK = 6, + DT_REG = 8, + DT_LNK = 10, + DT_SOCK = 12, + DT_WHT = 14 + } + + struct dirent + { + ulong d_fileno; + ushort d_reclen; + ushort d_namlen; + ubyte d_type; + char[512] d_name; + } + + alias void* DIR; + + dirent* __readdir30(DIR*); + alias __readdir30 readdir; +} else version( OpenBSD ) { enum @@ -283,6 +312,13 @@ version( OSX ) pragma(mangle, "rewinddir$INODE64$UNIX2003") void rewinddir(DIR*); } } +else version(NetBSD) +{ + int closedir(DIR*); + DIR* __opendir30(in char*); + alias __opendir30 opendir; + void rewinddir(DIR*); +} else { int closedir(DIR*); @@ -321,6 +357,11 @@ else version( FreeBSD ) { int readdir_r(DIR*, dirent*, dirent**); } +else version(NetBSD) +{ + int __readdir_r30(DIR*, dirent*, dirent**); + alias __readdir_r30 readdir_r; +} else version( OpenBSD ) { int readdir_r(DIR*, dirent*, dirent**); @@ -364,6 +405,11 @@ else version( FreeBSD ) void seekdir(DIR*, c_long); c_long telldir(DIR*); } +else version(NetBSD) +{ + void seekdir(DIR*, c_long); + c_long telldir(DIR*); +} else version( OpenBSD ) { void seekdir(DIR*, c_long); diff --git a/src/core/sys/posix/dlfcn.d b/src/core/sys/posix/dlfcn.d index 0ce8dda1bf..b227d1025d 100644 --- a/src/core/sys/posix/dlfcn.d +++ b/src/core/sys/posix/dlfcn.d @@ -174,6 +174,29 @@ else version( FreeBSD ) void* dli_saddr; } } +else version(NetBSD) +{ + enum RTLD_LAZY = 1; + enum RTLD_NOW = 2; + enum RTLD_GLOBAL = 0x100; + enum RTLD_LOCAL = 0x200; + enum RTLD_NODELETE = 0x01000; /* Do not remove members. */ + enum RTLD_NOLOAD = 0x02000; + + int dlclose(void*); + char* dlerror(); + void* dlopen(in char*, int); + void* dlsym(void*, in char*); + int dladdr(const(void)* addr, Dl_info* info); + + struct Dl_info + { + const(char)* dli_fname; + void* dli_fbase; + const(char)* dli_sname; + void* dli_saddr; + } +} else version( OpenBSD ) { enum RTLD_LAZY = 1; diff --git a/src/core/sys/posix/fcntl.d b/src/core/sys/posix/fcntl.d index 3e12f81e6c..7502b616d2 100644 --- a/src/core/sys/posix/fcntl.d +++ b/src/core/sys/posix/fcntl.d @@ -451,6 +451,59 @@ else version( OpenBSD ) enum AT_SYMLINK_FOLLOW = 0x04; enum AT_REMOVEDIR = 0x08; } +else version(NetBSD) +{ + enum F_DUPFD = 0; + enum F_GETFD = 1; + enum F_SETFD = 2; + enum F_GETFL = 3; + enum F_SETFL = 4; + enum F_GETOWN = 5; + enum F_SETOWN = 6; + enum F_GETLK = 7; + enum F_SETLK = 8; + enum F_SETLKW = 9; + enum F_CLOSEM = 10; + enum F_MAXFD = 11; + enum F_DUPFD_CLOEXEC= 12; + enum F_GETNOSIGPIPE = 13; + enum F_SETNOSIGPIPE = 14; + + enum FD_CLOEXEC = 1; + + enum F_RDLCK = 1; + enum F_UNLCK = 2; + enum F_WRLCK = 3; + + enum O_CREAT = 0x0200; + enum O_EXCL = 0x0800; + enum O_NOCTTY = 0x8000; + enum O_TRUNC = 0x0400; + + enum O_RDONLY = 0x0000; + enum O_WRONLY = 0x0001; + enum O_RDWR = 0x0002; + enum O_ACCMODE = 0x0003; + + enum O_NONBLOCK = 0x0004; + enum O_APPEND = 0x0008; + enum O_SYNC = 0x0080; + //enum O_DSYNC + //enum O_RSYNC + + struct flock + { + off_t l_start; + off_t l_len; + pid_t l_pid; + short l_type; + short l_whence; + } + + + int creat(in char*, mode_t); + int open(in char*, int, ...); +} else version (Solaris) { enum F_DUPFD = 0; diff --git a/src/core/sys/posix/grp.d b/src/core/sys/posix/grp.d index 43c6c030ba..1f6ec9514f 100644 --- a/src/core/sys/posix/grp.d +++ b/src/core/sys/posix/grp.d @@ -77,6 +77,16 @@ else version( FreeBSD ) char** gr_mem; } } +else version(NetBSD) +{ + struct group + { + char* gr_name; + char* gr_passwd; + gid_t gr_gid; + char** gr_mem; + } +} else version( OpenBSD ) { struct group @@ -138,6 +148,11 @@ else version( FreeBSD ) int getgrnam_r(in char*, group*, char*, size_t, group**); int getgrgid_r(gid_t, group*, char*, size_t, group**); } +else version(NetBSD) +{ + int getgrnam_r(in char*, group*, char*, size_t, group**); + int getgrgid_r(gid_t, group*, char*, size_t, group**); +} else version( OpenBSD ) { int getgrnam_r(in char*, group*, char*, size_t, group**); @@ -183,6 +198,12 @@ else version( FreeBSD ) @trusted void endgrent(); @trusted void setgrent(); } +else version(NetBSD) +{ + group* getgrent(); + @trusted void endgrent(); + @trusted void setgrent(); +} else version( OpenBSD ) { group* getgrent(); diff --git a/src/core/sys/posix/net/if_.d b/src/core/sys/posix/net/if_.d index 7fd75f03d2..60e51a844b 100644 --- a/src/core/sys/posix/net/if_.d +++ b/src/core/sys/posix/net/if_.d @@ -91,6 +91,21 @@ else version( FreeBSD ) if_nameindex_t* if_nameindex(); void if_freenameindex(if_nameindex_t*); } +else version(NetBSD) +{ + struct if_nameindex_t + { + uint if_index; + char* if_name; + } + + enum IF_NAMESIZE = 16; + + uint if_nametoindex(in char*); + char* if_indextoname(uint, char*); + if_nameindex_t* if_nameindex(); + void if_freenameindex(if_nameindex_t*); +} else version( CRuntime_Bionic ) { enum IF_NAMESIZE = 16; diff --git a/src/core/sys/posix/netdb.d b/src/core/sys/posix/netdb.d index be88fa4535..60ae944d89 100644 --- a/src/core/sys/posix/netdb.d +++ b/src/core/sys/posix/netdb.d @@ -396,6 +396,113 @@ else version( FreeBSD ) enum EAI_SYSTEM = 11; enum EAI_OVERFLOW = 14; } +else version(NetBSD) +{ + struct hostent + { + char* h_name; + char** h_aliases; + int h_addrtype; + int h_length; + char** h_addr_list; + extern (D) char* h_addr() @property { return h_addr_list[0]; } // non-standard + } + + struct netent + { + char* n_name; + char** n_aliases; + int n_addrtype; + uint32_t n_net; +/+ todo +#if (defined(__sparc__) && defined(_LP64)) || \ + (defined(__sh__) && defined(_LP64) && (_BYTE_ORDER == _BIG_ENDIAN)) + int __n_pad0; /* ABI compatibility */ +#endif + uint32_t n_net; /*%< network # */ +#if defined(__alpha__) || (defined(__i386__) && defined(_LP64)) || \ + (defined(__sh__) && defined(_LP64) && (_BYTE_ORDER == _LITTLE_ENDIAN)) + int __n_pad0; /* ABI compatibility */ +#endif + ++/ + } + + struct protoent + { + char* p_name; + char** p_aliases; + int p_proto; + } + + struct servent + { + char* s_name; + char** s_aliases; + int s_port; + char* s_proto; + } + + enum IPPORT_RESERVED = 1024; + + //h_errno + + enum HOST_NOT_FOUND = 1; + enum NO_DATA = 4; + enum NO_RECOVERY = 3; + enum TRY_AGAIN = 2; + + struct addrinfo + { + int ai_flags; + int ai_family; + int ai_socktype; + int ai_protocol; +/+todo +#if defined(__sparc__) && defined(_LP64) + int __ai_pad0; /* ABI compatibility */ +#endif ++/ + socklen_t ai_addrlen; +/+todo +#if defined(__alpha__) || (defined(__i386__) && defined(_LP64)) + int __ai_pad0; /* ABI compatibility */ +#endif ++/ + char* ai_canonname; + sockaddr* ai_addr; + addrinfo* ai_next; + } + + enum AI_PASSIVE = 0x1; + enum AI_CANONNAME = 0x2; + enum AI_NUMERICHOST = 0x4; + enum AI_NUMERICSERV = 0x8; + enum AI_V4MAPPED = 0x800; + enum AI_ALL = 0x100; + enum AI_ADDRCONFIG = 0x400; + + enum NI_NOFQDN = 0x1; + enum NI_NUMERICHOST = 0x2; + enum NI_NAMEREQD = 0x4; + enum NI_NUMERICSERV = 0x8; + enum NI_DGRAM = 0x10; + enum NI_WITHSCOPEID = 0x00000020; + enum NI_NUMERICSCOPE = 0x00000040; + enum NI_MAXHOST = 1025; // non-standard + enum NI_MAXSERV = 32; // non-standard + + enum EAI_AGAIN = 2; + enum EAI_BADFLAGS = 3; + enum EAI_FAIL = 4; + enum EAI_FAMILY = 5; + enum EAI_MEMORY = 6; + enum EAI_NONAME = 8; + enum EAI_SERVICE = 9; + enum EAI_SOCKTYPE = 10; + enum EAI_SYSTEM = 11; + enum EAI_OVERFLOW = 14; +} else version( OpenBSD ) { struct hostent diff --git a/src/core/sys/posix/netinet/in_.d b/src/core/sys/posix/netinet/in_.d index 5ac0bcd92c..061ed48933 100644 --- a/src/core/sys/posix/netinet/in_.d +++ b/src/core/sys/posix/netinet/in_.d @@ -211,6 +211,41 @@ else version( FreeBSD ) //enum INET_ADDRSTRLEN = 16; } +else version(NetBSD) +{ + struct sockaddr_in + { + ubyte sin_len; + sa_family_t sin_family; + in_port_t sin_port; + in_addr sin_addr; + ubyte[8] sin_zero; + } + + enum + { + IPPROTO_IP = 0, + IPPROTO_ICMP = 1, + IPPROTO_IGMP = 2, + IPPROTO_GGP = 3, + IPPROTO_TCP = 6, + IPPROTO_PUP = 12, + IPPROTO_UDP = 17, + IPPROTO_IDP = 22, + IPPROTO_ND = 77, + IPPROTO_MAX = 256 + } + + enum : uint + { + INADDR_ANY = 0x00000000, + INADDR_BROADCAST = 0xffffffff, + INADDR_LOOPBACK = 0x7f000001, + INADDR_NONE = 0xffffffff + } + + //enum INET_ADDRSTRLEN = 16; +} else version( Solaris ) { struct sockaddr_in @@ -722,6 +757,145 @@ else version( FreeBSD ) __IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_GLOBAL; } } +else version(NetBSD) +{ + struct in6_addr + { + union + { + uint8_t[16] s6_addr; + uint16_t[8] s6_addr16; + uint32_t[4] s6_addr32; + } + } + + struct sockaddr_in6 + { + uint8_t sin6_len; + sa_family_t sin6_family; + in_port_t sin6_port; + uint32_t sin6_flowinfo; + in6_addr sin6_addr; + uint32_t sin6_scope_id; + } + + extern __gshared immutable in6_addr in6addr_any; + extern __gshared immutable in6_addr in6addr_loopback; + + struct ipv6_mreq + { + in6_addr ipv6mr_multiaddr; + uint ipv6mr_interface; + } + + enum : uint + { + IPPROTO_IPV6 = 41, + + //INET6_ADDRSTRLEN = 46, + + IPV6_JOIN_GROUP = 12, + IPV6_LEAVE_GROUP = 13, + IPV6_MULTICAST_HOPS = 10, + IPV6_MULTICAST_IF = 9, + IPV6_MULTICAST_LOOP = 11, + IPV6_UNICAST_HOPS = 4, + IPV6_V6ONLY = 27, + } + + private enum + { + __IPV6_ADDR_SCOPE_NODELOCAL = 0x01, + __IPV6_ADDR_SCOPE_INTFACELOCAL = 0x01, + __IPV6_ADDR_SCOPE_LINKLOCAL = 0x02, + __IPV6_ADDR_SCOPE_SITELOCAL = 0x05, + __IPV6_ADDR_SCOPE_ORGLOCAL = 0x08, + __IPV6_ADDR_SCOPE_GLOBAL = 0x0e, + } + + // macros + extern (D) int IN6_IS_ADDR_UNSPECIFIED( in in6_addr* a ) pure + { + return (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[0]) == 0) && + (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[4]) == 0) && + (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[8]) == 0) && + (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[12]) == 0); + } + + extern (D) int IN6_IS_ADDR_LOOPBACK( in in6_addr* a ) pure + { + return (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[0]) == 0) && + (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[4]) == 0) && + (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[8]) == 0) && + (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[12]) == ntohl(1)); + } + + extern (D) int IN6_IS_ADDR_V4COMPAT( in in6_addr* a ) pure + { + return (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[0]) == 0) && + (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[4]) == 0) && + (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[8]) == 0) && + (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[12]) != 0) && + (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[12]) != ntohl(1)); + } + + extern (D) int IN6_IS_ADDR_V4MAPPED( in in6_addr* a ) pure + { + return (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[0]) == 0) && + (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[4]) == 0) && + (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[8]) == ntohl(0x0000ffff)); + } + + extern (D) int IN6_IS_ADDR_LINKLOCAL( in in6_addr* a ) pure + { + return a.s6_addr[0] == 0xfe && (a.s6_addr[1] & 0xc0) == 0x80; + } + + extern (D) int IN6_IS_ADDR_SITELOCAL( in in6_addr* a ) pure + { + return a.s6_addr[0] == 0xfe && (a.s6_addr[1] & 0xc0) == 0xc0; + } + + extern (D) int IN6_IS_ADDR_MULTICAST( in in6_addr* a ) pure + { + return a.s6_addr[0] == 0xff; + } + + extern (D) uint8_t __IPV6_ADDR_MC_SCOPE( in in6_addr* a ) pure + { + return a.s6_addr[1] & 0x0f; + } + + extern (D) int IN6_IS_ADDR_MC_NODELOCAL( in in6_addr* a ) pure + { + return IN6_IS_ADDR_MULTICAST(a) && + __IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_NODELOCAL; + } + + extern (D) int IN6_IS_ADDR_MC_LINKLOCAL( in in6_addr* a ) pure + { + return IN6_IS_ADDR_MULTICAST(a) && + __IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_LINKLOCAL; + } + + extern (D) int IN6_IS_ADDR_MC_SITELOCAL( in in6_addr* a ) pure + { + return IN6_IS_ADDR_MULTICAST(a) && + __IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_SITELOCAL; + } + + extern (D) int IN6_IS_ADDR_MC_ORGLOCAL( in in6_addr* a ) pure + { + return IN6_IS_ADDR_MULTICAST(a) && + __IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_ORGLOCAL; + } + + extern (D) int IN6_IS_ADDR_MC_GLOBAL( in in6_addr* a ) pure + { + return IN6_IS_ADDR_MULTICAST(a) && + __IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_GLOBAL; + } +} else version( Solaris ) { struct in6_addr @@ -998,6 +1172,10 @@ else version( FreeBSD ) { enum uint IPPROTO_RAW = 255; } +else version(NetBSD) +{ + enum uint IPPROTO_RAW = 255; +} else version( Solaris ) { enum uint IPPROTO_RAW = 255; diff --git a/src/core/sys/posix/netinet/tcp.d b/src/core/sys/posix/netinet/tcp.d index ad3e00cfc1..40ac9dd369 100644 --- a/src/core/sys/posix/netinet/tcp.d +++ b/src/core/sys/posix/netinet/tcp.d @@ -47,6 +47,10 @@ else version( FreeBSD ) { enum TCP_NODELAY = 1; } +else version(NetBSD) +{ + enum TCP_NODELAY = 1; +} else version( Solaris ) { enum TCP_NODELAY = 1; diff --git a/src/core/sys/posix/poll.d b/src/core/sys/posix/poll.d index dc3ead60ce..4e67b4a37e 100644 --- a/src/core/sys/posix/poll.d +++ b/src/core/sys/posix/poll.d @@ -152,6 +152,40 @@ else version( FreeBSD ) int poll(pollfd*, nfds_t, int); } +else version(NetBSD) +{ + alias uint nfds_t; + + struct pollfd + { + int fd; + short events; + short revents; + }; + + enum + { + POLLIN = 0x0001, + POLLPRI = 0x0002, + POLLOUT = 0x0004, + POLLRDNORM = 0x0040, + POLLWRNORM = POLLOUT, + POLLRDBAND = 0x0080, + POLLWRBAND = 0x0100, + //POLLEXTEND = 0x0200, + //POLLATTRIB = 0x0400, + //POLLNLINK = 0x0800, + //POLLWRITE = 0x1000, + POLLERR = 0x0008, + POLLHUP = 0x0010, + POLLNVAL = 0x0020, + + POLLSTANDARD = (POLLIN|POLLPRI|POLLOUT|POLLRDNORM|POLLRDBAND| + POLLWRBAND|POLLERR|POLLHUP|POLLNVAL) + } + + int poll(pollfd*, nfds_t, int); +} else version( OpenBSD ) { alias uint nfds_t; diff --git a/src/core/sys/posix/pthread.d b/src/core/sys/posix/pthread.d index 60cd76d589..d7b51b3d01 100644 --- a/src/core/sys/posix/pthread.d +++ b/src/core/sys/posix/pthread.d @@ -218,6 +218,42 @@ else version( FreeBSD ) enum PTHREAD_COND_INITIALIZER = null; enum PTHREAD_RWLOCK_INITIALIZER = null; } +else version(NetBSD) +{ + enum PRI_NONE = -1; + enum + { + PTHREAD_INHERIT_SCHED = 0x0, + + PTHREAD_CREATE_DETACHED = 1, + PTHREAD_CREATE_JOINABLE = 0, + PTHREAD_EXPLICIT_SCHED = 1, + } + + enum + { + PTHREAD_PROCESS_PRIVATE = 0, + PTHREAD_PROCESS_SHARED = 1, + } + + enum + { + PTHREAD_CANCEL_ENABLE = 0, + PTHREAD_CANCEL_DISABLE = 1, + PTHREAD_CANCEL_DEFERRED = 0, + PTHREAD_CANCEL_ASYNCHRONOUS = 1, + } + + enum PTHREAD_CANCELED = cast(void*) 1; + + enum PTHREAD_DONE_INIT = 1; + + enum PTHREAD_MUTEX_INITIALIZER = pthread_mutex_t(0x33330003); + + enum PTHREAD_ONCE_INIT = pthread_once_t(PTHREAD_MUTEX_INITIALIZER); + enum PTHREAD_COND_INITIALIZER = pthread_cond_t(0x55550005); + enum PTHREAD_RWLOCK_INITIALIZER = pthread_rwlock_t(0x99990009); +} else version( OpenBSD ) { enum @@ -412,6 +448,33 @@ else version( FreeBSD ) void __pthread_cleanup_push_imp(_pthread_cleanup_routine_nogc, void*, _pthread_cleanup_info*) @nogc; void __pthread_cleanup_pop_imp(int); } +else version(NetBSD) +{ + alias void function(void*) _pthread_cleanup_routine; + + struct _pthread_cleanup_store + { + void*[4] pthread_cleanup_pad; + } + + struct pthread_cleanup + { + _pthread_cleanup_store __cleanup_info__ = void; + + extern (D) void push()( _pthread_cleanup_routine cleanup_routine, void* cleanup_arg ) + { + pthread__cleanup_push( cleanup_routine, cleanup_arg, &__cleanup_info__ ); + } + + extern (D) void pop()( int execute ) + { + pthread__cleanup_pop( execute, &__cleanup_info__ ); + } + } + + void pthread__cleanup_push(_pthread_cleanup_routine, void*, void*); + void pthread__cleanup_pop(int, void *); +} else version ( OpenBSD ) { void pthread_cleanup_push(void function(void*), void*); @@ -561,6 +624,18 @@ else version( FreeBSD ) int pthread_barrierattr_init(pthread_barrierattr_t*); int pthread_barrierattr_setpshared(pthread_barrierattr_t*, int); } +else version(NetBSD) +{ + enum PTHREAD_BARRIER_SERIAL_THREAD = 1234567; + + int pthread_barrier_destroy(pthread_barrier_t*); + int pthread_barrier_init(pthread_barrier_t*, in pthread_barrierattr_t*, uint); + int pthread_barrier_wait(pthread_barrier_t*); + int pthread_barrierattr_destroy(pthread_barrierattr_t*); + int pthread_barrierattr_getpshared(in pthread_barrierattr_t*, int*); + int pthread_barrierattr_init(pthread_barrierattr_t*); + int pthread_barrierattr_setpshared(pthread_barrierattr_t*, int); +} else version( OpenBSD ) { enum PTHREAD_BARRIER_SERIAL_THREAD = -1; @@ -631,6 +706,14 @@ else version( FreeBSD ) int pthread_spin_trylock(pthread_spinlock_t*); int pthread_spin_unlock(pthread_spinlock_t*); } +else version(NetBSD) +{ + int pthread_spin_init(pthread_spinlock_t*, int); + int pthread_spin_destroy(pthread_spinlock_t*); + int pthread_spin_lock(pthread_spinlock_t*); + int pthread_spin_trylock(pthread_spinlock_t*); + int pthread_spin_unlock(pthread_spinlock_t*); +} else version( OpenBSD ) { int pthread_spin_init(pthread_spinlock_t*, int); @@ -722,6 +805,24 @@ else version( FreeBSD ) int pthread_mutexattr_settype(pthread_mutexattr_t*, int) @trusted; int pthread_setconcurrency(int); } +else version(NetBSD) +{ + enum + { + PTHREAD_MUTEX_NORMAL = 0, + PTHREAD_MUTEX_ERRORCHECK = 1, + PTHREAD_MUTEX_RECURSIVE = 2, + PTHREAD_MUTEX_TYPE_MAX + } + enum PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_ERRORCHECK; + + int pthread_attr_getguardsize(in pthread_attr_t*, size_t*); + int pthread_attr_setguardsize(pthread_attr_t*, size_t); + int pthread_getconcurrency(); + int pthread_mutexattr_gettype(pthread_mutexattr_t*, int*); + int pthread_mutexattr_settype(pthread_mutexattr_t*, int) @trusted; + int pthread_setconcurrency(int); +} else version( OpenBSD ) { enum @@ -791,6 +892,9 @@ else version( FreeBSD ) { int pthread_getcpuclockid(pthread_t, clockid_t*); } +else version(NetBSD) +{ +} else version( OpenBSD ) { int pthread_getcpuclockid(pthread_t, clockid_t*); @@ -837,6 +941,12 @@ else version( FreeBSD ) int pthread_rwlock_timedrdlock(pthread_rwlock_t*, in timespec*); int pthread_rwlock_timedwrlock(pthread_rwlock_t*, in timespec*); } +else version(NetBSD) +{ + int pthread_mutex_timedlock(pthread_mutex_t*, in timespec*); + int pthread_rwlock_timedrdlock(pthread_rwlock_t*, in timespec*); + int pthread_rwlock_timedwrlock(pthread_rwlock_t*, in timespec*); +} else version( OpenBSD ) { int pthread_mutex_timedlock(pthread_mutex_t*, in timespec*); @@ -979,6 +1089,24 @@ else version( FreeBSD ) int pthread_setschedparam(pthread_t, int, sched_param*); // int pthread_setschedprio(pthread_t, int); // not implemented } +else version(NetBSD) +{ + enum + { + PTHREAD_SCOPE_PROCESS = 0, + PTHREAD_SCOPE_SYSTEM = 0x1 + } + + int pthread_attr_getinheritsched(in pthread_attr_t*, int*); + int pthread_attr_getschedpolicy(in pthread_attr_t*, int*); + int pthread_attr_getscope(in pthread_attr_t*, int*); + int pthread_attr_setinheritsched(pthread_attr_t*, int); + int pthread_attr_setschedpolicy(pthread_attr_t*, int); + int pthread_attr_setscope(in pthread_attr_t*, int); + int pthread_getschedparam(pthread_t, int*, sched_param*); + int pthread_setschedparam(pthread_t, int, sched_param*); + //int pthread_setschedprio(pthread_t, int); +} else version( OpenBSD ) { enum @@ -1074,6 +1202,15 @@ else version( FreeBSD ) int pthread_attr_setstackaddr(pthread_attr_t*, void*); int pthread_attr_setstacksize(pthread_attr_t*, size_t); } +else version(NetBSD) +{ + int pthread_attr_getstack(in pthread_attr_t*, void**, size_t*); + int pthread_attr_getstackaddr(in pthread_attr_t*, void**); + int pthread_attr_getstacksize(in pthread_attr_t*, size_t*); + int pthread_attr_setstack(pthread_attr_t*, void*, size_t); + int pthread_attr_setstackaddr(pthread_attr_t*, void*); + int pthread_attr_setstacksize(pthread_attr_t*, size_t); +} else version( OpenBSD ) { int pthread_attr_getstack(in pthread_attr_t*, void**, size_t*); @@ -1136,6 +1273,15 @@ else version( FreeBSD ) int pthread_rwlockattr_getpshared(in pthread_rwlockattr_t*, int*); int pthread_rwlockattr_setpshared(pthread_rwlockattr_t*, int); } +else version(NetBSD) +{ + int pthread_condattr_getpshared(in pthread_condattr_t*, int*); + int pthread_condattr_setpshared(pthread_condattr_t*, int); + int pthread_mutexattr_getpshared(in pthread_mutexattr_t*, int*); + int pthread_mutexattr_setpshared(pthread_mutexattr_t*, int); + int pthread_rwlockattr_getpshared(in pthread_rwlockattr_t*, int*); + int pthread_rwlockattr_setpshared(pthread_rwlockattr_t*, int); +} else version( OpenBSD ) { } diff --git a/src/core/sys/posix/pwd.d b/src/core/sys/posix/pwd.d index ddd35f9952..34590c7fe5 100644 --- a/src/core/sys/posix/pwd.d +++ b/src/core/sys/posix/pwd.d @@ -94,6 +94,22 @@ else version( FreeBSD ) int pw_fields; /* internal: fields filled in */ } } +else version(NetBSD) +{ + struct passwd + { + char* pw_name; /* user name */ + char* pw_passwd; /* encrypted password */ + uid_t pw_uid; /* user uid */ + gid_t pw_gid; /* user gid */ + time_t pw_change; /* password change time */ + char* pw_class; /* user access class */ + char* pw_gecos; /* Honeywell login info */ + char* pw_dir; /* home directory */ + char* pw_shell; /* default shell */ + time_t pw_expire; /* account expiration */ + } +} else version( OpenBSD ) { struct passwd @@ -168,6 +184,13 @@ else version( FreeBSD ) int getpwnam_r(in char*, passwd*, char*, size_t, passwd**); int getpwuid_r(uid_t, passwd*, char*, size_t, passwd**); } +else version(NetBSD) +{ + int __getpwnam_r50(in char*, passwd*, char*, size_t, passwd**); + alias __getpwnam_r50 getpwnam_r; + int __getpwuid_r50(uid_t, passwd*, char*, size_t, passwd**); + alias __getpwuid_r50 getpwuid_r; +} else version( OpenBSD ) { int getpwnam_r(in char*, passwd*, char*, size_t, passwd**); @@ -213,6 +236,12 @@ else version ( FreeBSD ) passwd* getpwent(); void setpwent(); } +else version (NetBSD) +{ + void endpwent(); + passwd* getpwent(); + void setpwent(); +} else version ( OpenBSD ) { void endpwent(); diff --git a/src/core/sys/posix/sched.d b/src/core/sys/posix/sched.d index 637545cf16..3f93b989bb 100644 --- a/src/core/sys/posix/sched.d +++ b/src/core/sys/posix/sched.d @@ -95,6 +95,17 @@ else version( FreeBSD ) enum SCHED_OTHER = 2; enum SCHED_RR = 3; } +else version(NetBSD) +{ + struct sched_param + { + int sched_priority; + } + + enum SCHED_FIFO = 1; + enum SCHED_OTHER = 0; + enum SCHED_RR = 2; +} else version( OpenBSD ) { struct sched_param @@ -164,6 +175,10 @@ else version( FreeBSD ) { int sched_yield(); } +else version(NetBSD) +{ + int sched_yield(); +} else version( OpenBSD ) { int sched_yield(); @@ -208,6 +223,12 @@ else version( FreeBSD ) int sched_get_priority_max(int); int sched_rr_get_interval(pid_t, timespec*); } +else version(NetBSD) +{ + int sched_get_priority_min(int); + int sched_get_priority_max(int); + int sched_rr_get_interval(pid_t, timespec*); +} else version( OpenBSD ) { int sched_get_priority_min(int); diff --git a/src/core/sys/posix/semaphore.d b/src/core/sys/posix/semaphore.d index ba29482285..32027eefb9 100644 --- a/src/core/sys/posix/semaphore.d +++ b/src/core/sys/posix/semaphore.d @@ -90,6 +90,12 @@ else version( FreeBSD ) enum SEM_FAILED = cast(sem_t*) null; } +else version(NetBSD) +{ + alias size_t sem_t; + + enum SEM_FAILED = cast(sem_t*) null; +} else version( OpenBSD ) { struct __sem { } @@ -153,6 +159,10 @@ else version( FreeBSD ) { int sem_timedwait(sem_t*, in timespec*); } +else version(NetBSD) +{ + int sem_timedwait(sem_t*, in timespec*); +} else version( OpenBSD ) { int sem_timedwait(sem_t*, in timespec*); diff --git a/src/core/sys/posix/setjmp.d b/src/core/sys/posix/setjmp.d index 8a1d4cc59f..3c8a78ee25 100644 --- a/src/core/sys/posix/setjmp.d +++ b/src/core/sys/posix/setjmp.d @@ -170,6 +170,26 @@ else version( FreeBSD ) int setjmp(ref jmp_buf); void longjmp(ref jmp_buf, int); } +else version(NetBSD) +{ + // + version( X86 ) + { + enum _JBLEN = 13; + struct _jmp_buf { int[_JBLEN + 1] _jb; } + } + else version( X86_64) + { + enum _JBLEN = 11; + struct _jmp_buf { c_long[_JBLEN] _jb; } + } + else + static assert(0); + alias _jmp_buf[_JBLEN] jmp_buf; + + int setjmp(ref jmp_buf); + void longjmp(ref jmp_buf, int); +} else version( OpenBSD ) { // @@ -277,6 +297,24 @@ else version( FreeBSD ) int sigsetjmp(ref sigjmp_buf); void siglongjmp(ref sigjmp_buf, int); } +else version(NetBSD) +{ + // + version( X86 ) + { + struct _sigjmp_buf { int[_JBLEN + 1] _ssjb; } + } + else version( X86_64) + { + struct _sigjmp_buf { c_long[_JBLEN] _sjb; } + } + else + static assert(0); + alias _sigjmp_buf[_JBLEN + 1] sigjmp_buf; + + int sigsetjmp(ref sigjmp_buf); + void siglongjmp(ref sigjmp_buf, int); +} else version( OpenBSD ) { alias sigjmp_buf = c_long[_JBLEN + 1]; @@ -310,6 +348,11 @@ else version( FreeBSD ) int _setjmp(ref jmp_buf); void _longjmp(ref jmp_buf, int); } +else version(NetBSD) +{ + int _setjmp(ref jmp_buf); + void _longjmp(ref jmp_buf, int); +} else version( OpenBSD ) { int _setjmp(ref jmp_buf); diff --git a/src/core/sys/posix/signal.d b/src/core/sys/posix/signal.d index dcdac9ab10..b14848a8ec 100644 --- a/src/core/sys/posix/signal.d +++ b/src/core/sys/posix/signal.d @@ -164,6 +164,11 @@ else version (FreeBSD) { enum SIGRTMAX = 126; } // Note: it appears that FreeBSD (prior to 7) and OSX do not support realtime signals +else version(NetBSD) +{ + enum SIGRTMIN = 33; + enum SIGRTMAX = 63; +} version( linux ) { @@ -434,6 +439,30 @@ else version( FreeBSD ) enum SIGUSR2 = 31; enum SIGURG = 16; } +else version(NetBSD) +{ + //SIGABRT (defined in core.stdc.signal) + enum SIGALRM = 14; + enum SIGBUS = 10; + enum SIGCHLD = 20; + enum SIGCONT = 19; + //SIGFPE (defined in core.stdc.signal) + enum SIGHUP = 1; + //SIGILL (defined in core.stdc.signal) + //SIGINT (defined in core.stdc.signal) + enum SIGKILL = 9; + enum SIGPIPE = 13; + enum SIGQUIT = 3; + //SIGSEGV (defined in core.stdc.signal) + enum SIGSTOP = 17; + //SIGTERM (defined in core.stdc.signal) + enum SIGTSTP = 18; + enum SIGTTIN = 21; + enum SIGTTOU = 22; + enum SIGUSR1 = 30; + enum SIGUSR2 = 31; + enum SIGURG = 16; +} else version( OpenBSD ) { //SIGABRT (defined in core.stdc.signal) @@ -516,7 +545,20 @@ else version( FreeBSD ) sigset_t sa_mask; } } -else version( OpenBSD ) +else version(NetBSD) +{ + struct sigaction_t + { + union + { + sigfn_t sa_handler; + sigactfn_t sa_sigaction; + } + sigset_t sa_mask; + int sa_flags; + } +} +else version(OpenBSD) { struct sigaction_t { @@ -933,6 +975,100 @@ else version( FreeBSD ) int sigsuspend(in sigset_t *); int sigwait(in sigset_t*, int*); } +else version(NetBSD) +{ + enum SIG_HOLD = cast(sigfn_t2) 3; + + struct sigset_t + { + uint[4] __bits; + } + + enum SA_NOCLDSTOP = 8; + + enum SIG_BLOCK = 1; + enum SIG_UNBLOCK = 2; + enum SIG_SETMASK = 3; + + union sigval_t { + int sival_int; + void *sival_ptr; + }; + struct _rt{ + pid_t _pid; + uid_t _uid; + sigval_t _value; + }; + struct _child{ + pid_t _pid; + uid_t _uid; + int _status; + clock_t _utime; + clock_t _stime; + }; + struct _fault{ + void *_addr; + int _trap; + int _trap2; + int _trap3; + }; + struct _poll{ + long _band; + int _fd; + }; + union _reason{ + _rt rt; + _child child; + _fault fault; + _poll poll; + }; + struct _ksiginfo { + int _signo; + int _code; + int _errno; +/+#ifdef _LP64 + /* In _LP64 the union starts on an 8-byte boundary. */ + int _pad; +#endif+/ + _reason reason; + }; + + + union siginfo_t + { + ubyte[128] si_pad;/* Total size; for future expansion */ + _ksiginfo _info; + @property ref c_long si_band() return { return _info.reason.poll._band; } + } + + enum SI_USER = 0; + enum SI_QUEUE = -1; + enum SI_TIMER = -2; + enum SI_ASYNCIO = -3; + enum SI_MESGQ = -4; + + int kill(pid_t, int); + int __sigaction14(int, in sigaction_t*, sigaction_t*); + int __sigaddset14(sigset_t*, int); + int __sigdelset14(sigset_t*, int); + int __sigemptyset14(sigset_t *); + int __sigfillset14(sigset_t *); + int __sigismember14(in sigset_t *, int); + int __sigpending14(sigset_t *); + int __sigprocmask14(int, in sigset_t*, sigset_t*); + int __sigsuspend14(in sigset_t *); + int sigwait(in sigset_t*, int*); + + alias __sigaction14 sigaction; + alias __sigaddset14 sigaddset; + alias __sigdelset14 sigdelset; + alias __sigemptyset14 sigemptyset; + alias __sigfillset14 sigfillset; + alias __sigismember14 sigismember; + alias __sigpending14 sigpending; + alias __sigprocmask14 sigprocmask; + alias __sigsuspend14 sigsuspend; +} else version( OpenBSD ) { enum SIG_CATCH = cast(sigfn_t2) 2; @@ -1780,6 +1916,130 @@ else version( FreeBSD ) int sigpause(int); int sigrelse(int); } +else version(NetBSD) +{ + // No SIGPOLL on *BSD + enum SIGPROF = 27; + enum SIGSYS = 12; + enum SIGTRAP = 5; + enum SIGVTALRM = 26; + enum SIGXCPU = 24; + enum SIGXFSZ = 25; + + enum + { + SA_ONSTACK = 0x0001, + SA_RESTART = 0x0002, + SA_RESETHAND = 0x0004, + SA_NODEFER = 0x0010, + SA_NOCLDWAIT = 0x0020, + SA_SIGINFO = 0x0040, + } + + enum + { + SS_ONSTACK = 0x0001, + SS_DISABLE = 0x0004, + } + + enum MINSIGSTKSZ = 8192; + enum SIGSTKSZ = (MINSIGSTKSZ + 32768); +; + //ucontext_t (defined in core.sys.posix.ucontext) + //mcontext_t (defined in core.sys.posix.ucontext) + + struct stack_t + { + void* ss_sp; + size_t ss_size; + int ss_flags; + } + + struct sigstack + { + void* ss_sp; + int ss_onstack; + } + + enum + { + ILL_ILLOPC = 1, + ILL_ILLOPN, + ILL_ILLADR, + ILL_ILLTRP, + ILL_PRVOPC, + ILL_PRVREG, + ILL_COPROC, + ILL_BADSTK, + } + + enum + { + BUS_ADRALN = 1, + BUS_ADRERR, + BUS_OBJERR, + } + + enum + { + SEGV_MAPERR = 1, + SEGV_ACCERR, + } + + enum + { + FPE_INTOVF = 1, + FPE_INTDIV, + FPE_FLTDIV, + FPE_FLTOVF, + FPE_FLTUND, + FPE_FLTRES, + FPE_FLTINV, + FPE_FLTSUB, + } + + enum + { + TRAP_BRKPT = 1, + TRAP_TRACE, + } + + enum + { + CLD_EXITED = 1, + CLD_KILLED, + CLD_DUMPED, + CLD_TRAPPED, + CLD_STOPPED, + CLD_CONTINUED, + } + + enum + { + POLL_IN = 1, + POLL_OUT, + POLL_MSG, + POLL_ERR, + POLL_PRI, + POLL_HUP, + } + + //sigfn_t bsd_signal(int sig, sigfn_t func); + sigfn_t sigset(int sig, sigfn_t func); + + nothrow: + @nogc: + //sigfn_t2 bsd_signal(int sig, sigfn_t2 func); + sigfn_t2 sigset(int sig, sigfn_t2 func); + + int killpg(pid_t, int); + int sigaltstack(in stack_t*, stack_t*); + int sighold(int); + int sigignore(int); + int siginterrupt(int, int); + int sigpause(int); + int sigrelse(int); +} else version (OpenBSD) { // No SIGPOLL on *BSD @@ -2199,6 +2459,14 @@ else version( FreeBSD ) c_long tv_nsec; } } +else version(NetBSD) +{ + struct timespec + { + time_t tv_sec; + c_long tv_nsec; + } +} else version( OpenBSD ) { struct timespec @@ -2302,6 +2570,21 @@ else version( FreeBSD ) int sigtimedwait(in sigset_t*, siginfo_t*, in timespec*); int sigwaitinfo(in sigset_t*, siginfo_t*); } +else version(NetBSD) +{ + struct sigevent + { + int sigev_notify; + int sigev_signo; + sigval sigev_value; + void function(sigval) sigev_notify_function; + void /* pthread_attr_t */*sigev_notify_attributes; + } + + int sigqueue(pid_t, int, in sigval); + int sigtimedwait(in sigset_t*, siginfo_t*, in timespec*); + int sigwaitinfo(in sigset_t*, siginfo_t*); +} else version (OpenBSD) { } @@ -2378,6 +2661,11 @@ else version( FreeBSD ) int pthread_kill(pthread_t, int); int pthread_sigmask(int, in sigset_t*, sigset_t*); } +else version(NetBSD) +{ + int pthread_kill(pthread_t, int); + int pthread_sigmask(int, in sigset_t*, sigset_t*); +} else version( OpenBSD ) { int pthread_kill(pthread_t, int); diff --git a/src/core/sys/posix/stdio.d b/src/core/sys/posix/stdio.d index c085c862ce..2650af5f9d 100644 --- a/src/core/sys/posix/stdio.d +++ b/src/core/sys/posix/stdio.d @@ -291,6 +291,10 @@ version( FreeBSD ) { enum P_tmpdir = "/var/tmp/"; } +version(NetBSD) +{ + enum P_tmpdir = "/var/tmp/"; +} version( OpenBSD ) { enum P_tmpdir = "/tmp/"; diff --git a/src/core/sys/posix/stdlib.d b/src/core/sys/posix/stdlib.d index 4afd346d46..e4777def65 100644 --- a/src/core/sys/posix/stdlib.d +++ b/src/core/sys/posix/stdlib.d @@ -100,6 +100,10 @@ else version( FreeBSD ) { int posix_memalign(void**, size_t, size_t); } +else version(NetBSD) +{ + int posix_memalign(void**, size_t, size_t); +} else version( OpenBSD ) { int posix_memalign(void**, size_t, size_t); @@ -138,6 +142,13 @@ else version( FreeBSD ) void* valloc(size_t); // LEGACY non-standard } +else version(NetBSD) +{ + int setenv(in char*, in char*, int); + int __unsetenv13(in char*); + alias __unsetenv13 unsetenv; + void* valloc(size_t); // LEGACY non-standard +} else version( OpenBSD ) { int setenv(in char*, in char*, int); @@ -179,6 +190,10 @@ else version( FreeBSD ) { int rand_r(uint*); } +else version(NetBSD) +{ + int rand_r(uint*); +} else version( OpenBSD ) { int rand_r(uint*); @@ -366,6 +381,47 @@ else version( FreeBSD ) void srandom(uint); int unlockpt(int); } +else version(NetBSD) +{ + //WNOHANG (defined in core.sys.posix.sys.wait) + //WUNTRACED (defined in core.sys.posix.sys.wait) + //WEXITSTATUS (defined in core.sys.posix.sys.wait) + //WIFEXITED (defined in core.sys.posix.sys.wait) + //WIFSIGNALED (defined in core.sys.posix.sys.wait) + //WIFSTOPPED (defined in core.sys.posix.sys.wait) + //WSTOPSIG (defined in core.sys.posix.sys.wait) + //WTERMSIG (defined in core.sys.posix.sys.wait) + + c_long a64l(in char*); + double drand48(); + //char* ecvt(double, int, int *, int *); // LEGACY + double erand48(ref ushort[3]); + //char* fcvt(double, int, int *, int *); // LEGACY + //char* gcvt(double, int, char*); // LEGACY + int getsubopt(char**, in char**, char**); + int grantpt(int); + char* initstate(uint, char*, size_t); + c_long jrand48(ref ushort[3]); + char* l64a(c_long); + void lcong48(ref ushort[7]); + c_long lrand48(); + char* mktemp(char*); // LEGACY + int mkstemp(char*); + char* mkdtemp(char*); // Defined in IEEE 1003.1, 2008 Edition + c_long mrand48(); + c_long nrand48(ref ushort[3]); + int posix_openpt(int); + char* ptsname(int); + int putenv(char*); + c_long random(); + char* realpath(in char*, char*); + ushort *seed48(ref ushort[3]); + void setkey(in char*); + char* setstate(in char*); + void srand48(c_long); + void srandom(uint); + int unlockpt(int); +} else version( OpenBSD ) { //WNOHANG (defined in core.sys.posix.sys.wait) diff --git a/src/core/sys/posix/sys/ioctl.d b/src/core/sys/posix/sys/ioctl.d index abeffe3f22..8c2e778d82 100644 --- a/src/core/sys/posix/sys/ioctl.d +++ b/src/core/sys/posix/sys/ioctl.d @@ -367,6 +367,18 @@ else version (FreeBSD) int ioctl(int, c_ulong, ...); } +else version (NetBSD) +{ + struct winsize + { + ushort ws_row; + ushort ws_col; + ushort ws_xpixel; + ushort ws_ypixel; + } + + int ioctl(int, c_ulong, ...); +} else version (Solaris) { int ioctl(int fildes, int request, ...); diff --git a/src/core/sys/posix/sys/ipc.d b/src/core/sys/posix/sys/ipc.d index 32ccffd46b..5c9c2526b6 100644 --- a/src/core/sys/posix/sys/ipc.d +++ b/src/core/sys/posix/sys/ipc.d @@ -124,6 +124,31 @@ else version( FreeBSD ) key_t ftok(in char*, int); } +else version(NetBSD) +{ + struct ipc_perm + { + uid_t cuid; + gid_t cgid; + uid_t uid; + gid_t gid; + mode_t mode; + ushort seq; + key_t key; + } + + enum IPC_CREAT = 0x0100; // 01000 + enum IPC_EXCL = 0x0200; // 02000 + enum IPC_NOWAIT = 0x0400; // 04000 + + enum key_t IPC_PRIVATE = 0; + + enum IPC_RMID = 0; + enum IPC_SET = 1; + enum IPC_STAT = 2; + + key_t ftok(in char*, int); +} else version( CRuntime_Bionic ) { // All except ftok are from the linux kernel headers. diff --git a/src/core/sys/posix/sys/mman.d b/src/core/sys/posix/sys/mman.d index 134e8c2699..104c29da2e 100644 --- a/src/core/sys/posix/sys/mman.d +++ b/src/core/sys/posix/sys/mman.d @@ -85,6 +85,15 @@ else version( FreeBSD ) enum POSIX_MADV_DONTNEED = 4; int posix_madvise(void *addr, size_t len, int advice); } +else version(NetBSD) +{ + enum POSIX_MADV_NORMAL = 0; + enum POSIX_MADV_RANDOM = 1; + enum POSIX_MADV_SEQUENTIAL = 2; + enum POSIX_MADV_WILLNEED = 3; + enum POSIX_MADV_DONTNEED = 4; + int posix_madvise(void *addr, size_t len, int advice); +} else version (Solaris) { } @@ -127,6 +136,13 @@ else version( FreeBSD ) enum PROT_WRITE = 0x02; enum PROT_EXEC = 0x04; } +else version(NetBSD) +{ + enum PROT_NONE = 0x00; + enum PROT_READ = 0x01; + enum PROT_WRITE = 0x02; + enum PROT_EXEC = 0x04; +} else version (Solaris) { enum PROT_NONE = 0x00; @@ -173,6 +189,11 @@ else version( FreeBSD ) void* mmap(void*, size_t, int, int, int, off_t); int munmap(void*, size_t); } +else version(NetBSD) +{ + void* mmap(void*, size_t, int, int, int, off_t); + int munmap(void*, size_t); +} else version (Solaris) { void* mmap(void*, size_t, int, int, int, off_t); @@ -327,6 +348,22 @@ else version( FreeBSD ) int msync(void*, size_t, int); } +else version(NetBSD) +{ + enum MAP_SHARED = 0x0001; + enum MAP_PRIVATE = 0x0002; + enum MAP_FIXED = 0x0010; + enum MAP_ANON = 0x1000; + + enum MAP_FAILED = cast(void*)-1; + + enum MS_SYNC = 0x0004; + enum MS_ASYNC = 0x0001; + enum MS_INVALIDATE = 0x0002; + + int __msync13(void*, size_t, int); + alias msync = __msync13; +} else version (Solaris) { enum MAP_SHARED = 0x0001; @@ -438,6 +475,14 @@ else version( FreeBSD ) int mlockall(int); int munlockall(); } +else version(NetBSD) +{ + enum MCL_CURRENT = 0x0001; + enum MCL_FUTURE = 0x0002; + + int mlockall(int); + int munlockall(); +} else version (Solaris) { enum MCL_CURRENT = 0x0001; @@ -482,6 +527,11 @@ else version( FreeBSD ) int mlock(in void*, size_t); int munlock(in void*, size_t); } +else version(NetBSD) +{ + int mlock(in void*, size_t); + int munlock(in void*, size_t); +} else version (Solaris) { int mlock(in void*, size_t); @@ -516,6 +566,10 @@ else version( FreeBSD ) { int mprotect(void*, size_t, int); } +else version(NetBSD) +{ + int mprotect(void*, size_t, int); +} else version (Solaris) { int mprotect(void*, size_t, int); @@ -552,6 +606,11 @@ else version( FreeBSD ) int shm_open(in char*, int, mode_t); int shm_unlink(in char*); } +else version(NetBSD) +{ + int shm_open(in char*, int, mode_t); + int shm_unlink(in char*); +} else version (Solaris) { int shm_open(in char*, int, mode_t); diff --git a/src/core/sys/posix/sys/resource.d b/src/core/sys/posix/sys/resource.d index f7d61d9fd0..2823aa5069 100644 --- a/src/core/sys/posix/sys/resource.d +++ b/src/core/sys/posix/sys/resource.d @@ -243,6 +243,64 @@ else version (FreeBSD) RLIMIT_AS = 10, } } +else version (NetBSD) +{ + enum + { + PRIO_PROCESS = 0, + PRIO_PGRP = 1, + PRIO_USER = 2, + } + + alias long rlim_t; + + enum + { + RLIM_INFINITY = (cast(rlim_t)((cast(ulong) 1 << 63) - 1)), + // FreeBSD explicitly does not define the following: + //RLIM_SAVED_MAX, + //RLIM_SAVED_CUR, + } + + enum + { + RUSAGE_SELF = 0, + RUSAGE_CHILDREN = -1, + } + + struct rusage + { + timeval ru_utime; + timeval ru_stime; + c_long ru_maxrss; + alias ru_ixrss ru_first; + c_long ru_ixrss; + c_long ru_idrss; + c_long ru_isrss; + c_long ru_minflt; + c_long ru_majflt; + c_long ru_nswap; + c_long ru_inblock; + c_long ru_oublock; + c_long ru_msgsnd; + c_long ru_msgrcv; + c_long ru_nsignals; + c_long ru_nvcsw; + c_long ru_nivcsw; + alias ru_nivcsw ru_last; + } + + enum + { + RLIMIT_CORE = 4, + RLIMIT_CPU = 0, + RLIMIT_DATA = 2, + RLIMIT_FSIZE = 1, + RLIMIT_NOFILE = 8, + RLIMIT_STACK = 3, + RLIMIT_AS = 10, + } +} else version (Solaris) { enum @@ -415,6 +473,12 @@ else version (FreeBSD) int getrusage(int, rusage*); int setrlimit(int, in rlimit*); } +else version (NetBSD) +{ + int getrlimit(int, rlimit*); + int getrusage(int, rusage*); + int setrlimit(int, in rlimit*); +} else version (Solaris) { int getrlimit(int, rlimit*); diff --git a/src/core/sys/posix/sys/select.d b/src/core/sys/posix/sys/select.d index 3bdd21078f..c63ddf3a6d 100644 --- a/src/core/sys/posix/sys/select.d +++ b/src/core/sys/posix/sys/select.d @@ -221,6 +221,55 @@ else version( FreeBSD ) int pselect(int, fd_set*, fd_set*, fd_set*, in timespec*, in sigset_t*); int select(int, fd_set*, fd_set*, fd_set*, timeval*); } +else version(NetBSD) +{ + private + { + alias c_ulong __fd_mask; + enum _NFDBITS = __fd_mask.sizeof * 8; + } + + enum uint FD_SETSIZE = 256; + + struct fd_set + { + __fd_mask[(FD_SETSIZE + (_NFDBITS - 1)) / _NFDBITS] __fds_bits; + } + + extern (D) __fd_mask __fdset_mask(uint n) + { + return cast(__fd_mask) 1 << (n % _NFDBITS); + } + + extern (D) void FD_CLR( int n, fd_set* p ) + { + p.__fds_bits[n / _NFDBITS] &= ~__fdset_mask(n); + } + + extern (D) bool FD_ISSET( int n, const(fd_set)* p ) + { + return (p.__fds_bits[n / _NFDBITS] & __fdset_mask(n)) != 0; + } + + extern (D) void FD_SET( int n, fd_set* p ) + { + p.__fds_bits[n / _NFDBITS] |= __fdset_mask(n); + } + + extern (D) void FD_ZERO( fd_set* p ) + { + fd_set *_p; + size_t _n; + + _p = p; + _n = (FD_SETSIZE + (_NFDBITS - 1)) / _NFDBITS; + while (_n > 0) + _p.__fds_bits[--_n] = 0; + } + + int pselect(int, fd_set*, fd_set*, fd_set*, in timespec*, in sigset_t*); + int select(int, fd_set*, fd_set*, fd_set*, timeval*); +} else version (Solaris) { private diff --git a/src/core/sys/posix/sys/shm.d b/src/core/sys/posix/sys/shm.d index 7e0f1f4248..3f20acb68c 100644 --- a/src/core/sys/posix/sys/shm.d +++ b/src/core/sys/posix/sys/shm.d @@ -130,6 +130,32 @@ else version( FreeBSD ) int shmdt(in void*); int shmget(key_t, size_t, int); } +else version(NetBSD) +{ + enum SHM_RDONLY = 0x01000; // 010000 + enum SHM_RND = 0x02000; // 020000 + enum SHMLBA = 1 << 12; // PAGE_SIZE = (1< + { + enum _ALIGNBYTES = /+c_int+/ int.sizeof - 1; + extern (D) size_t _ALIGN( size_t p ) { return (p + _ALIGNBYTES) & ~_ALIGNBYTES; } + } + + extern (D) ubyte* CMSG_DATA( cmsghdr* cmsg ) + { + return cast(ubyte*) cmsg + _ALIGN( cmsghdr.sizeof ); + } + + extern (D) cmsghdr* CMSG_NXTHDR( msghdr* mhdr, cmsghdr* cmsg ) + { + if( cmsg == null ) + { + return CMSG_FIRSTHDR( mhdr ); + } + else + { + if( cast(ubyte*) cmsg + _ALIGN( cmsg.cmsg_len ) + _ALIGN( cmsghdr.sizeof ) > + cast(ubyte*) mhdr.msg_control + mhdr.msg_controllen ) + return null; + else + return cast(cmsghdr*) (cast(ubyte*) cmsg + _ALIGN( cmsg.cmsg_len )); + } + } + + extern (D) cmsghdr* CMSG_FIRSTHDR( msghdr* mhdr ) + { + return mhdr.msg_controllen >= cmsghdr.sizeof ? cast(cmsghdr*) mhdr.msg_control : null; + } + + struct linger + { + int l_onoff; + int l_linger; + } + + enum + { + SOCK_DGRAM = 2, + SOCK_RDM = 4, + SOCK_SEQPACKET = 5, + SOCK_STREAM = 1 + } + + enum : uint + { + SOL_SOCKET = 0xffff + } + + enum : uint + { + SO_DEBUG = 0x0001, /* turn on debugging info recording */ + SO_ACCEPTCONN = 0x0002, /* socket has had listen() */ + SO_REUSEADDR = 0x0004, /* allow local address reuse */ + SO_KEEPALIVE = 0x0008, /* keep connections alive */ + SO_DONTROUTE = 0x0010, /* just use interface addresses */ + SO_BROADCAST = 0x0020, /* permit sending of broadcast msgs */ + SO_USELOOPBACK = 0x0040, /* bypass hardware when possible */ + SO_LINGER = 0x0080, /* linger on close if data present */ + SO_OOBINLINE = 0x0100, /* leave received OOB data in line */ + SO_REUSEPORT = 0x0200, /* allow local address & port reuse */ + /* SO_OTIMESTAMP 0x0400 */ + SO_NOSIGPIPE = 0x0800, /* no SIGPIPE from EPIPE */ + SO_ACCEPTFILTER = 0x1000, /* there is an accept filter */ + SO_TIMESTAMP = 0x2000, /* timestamp received dgram traffic */ + + /* + * Additional options, not kept in so_options. + */ + SO_SNDBUF = 0x1001, /* send buffer size */ + SO_RCVBUF = 0x1002, /* receive buffer size */ + SO_SNDLOWAT = 0x1003, /* send low-water mark */ + SO_RCVLOWAT = 0x1004, /* receive low-water mark */ + /* SO_OSNDTIMEO 0x1005 */ + /* SO_ORCVTIMEO 0x1006 */ + SO_ERROR = 0x1007, /* get error status and clear */ + SO_TYPE = 0x1008, /* get socket type */ + SO_OVERFLOWED = 0x1009, /* datagrams: return packets dropped */ + + SO_NOHEADER = 0x100a, /* user supplies no header to kernel; + * kernel removes header and supplies + * payload + */ + SO_SNDTIMEO = 0x100b, /* send timeout */ + SO_RCVTIMEO = 0x100c /* receive timeout */ + + } + + enum + { + SOMAXCONN = 128 + } + + enum : uint + { + MSG_OOB = 0x0001, /* process out-of-band data */ + MSG_PEEK = 0x0002, /* peek at incoming message */ + MSG_DONTROUTE = 0x0004, /* send without using routing tables */ + MSG_EOR = 0x0008, /* data completes record */ + MSG_TRUNC = 0x0010, /* data discarded before delivery */ + MSG_CTRUNC = 0x0020, /* control data lost before delivery */ + MSG_WAITALL = 0x0040, /* wait for full request or error */ + MSG_DONTWAIT = 0x0080, /* this message should be nonblocking */ + MSG_BCAST = 0x0100, /* this message was rcvd using link-level brdcst */ + MSG_MCAST = 0x0200, /* this message was rcvd using link-level mcast */ + MSG_NOSIGNAL = 0x0400 /* do not generate SIGPIPE on EOF */ + } + + enum + { + AF_APPLETALK = 16, + AF_INET = 2, + AF_IPX = 23, + AF_UNIX = 1, + AF_UNSPEC = 0 + } + + enum + { + SHUT_RD = 0, + SHUT_WR = 1, + SHUT_RDWR = 2 + } + + int accept(int, sockaddr*, socklen_t*); + int bind(int, in sockaddr*, socklen_t); + int connect(int, in sockaddr*, socklen_t); + int getpeername(int, sockaddr*, socklen_t*); + int getsockname(int, sockaddr*, socklen_t*); + int getsockopt(int, int, int, void*, socklen_t*); + int listen(int, int); + ssize_t recv(int, void*, size_t, int); + ssize_t recvfrom(int, void*, size_t, int, sockaddr*, socklen_t*); + ssize_t recvmsg(int, msghdr*, int); + ssize_t send(int, in void*, size_t, int); + ssize_t sendmsg(int, in msghdr*, int); + ssize_t sendto(int, in void*, size_t, int, in sockaddr*, socklen_t); + int setsockopt(int, int, int, in void*, socklen_t); + int shutdown(int, int); + int socket(int, int, int); + int sockatmark(int); + int socketpair(int, int, int, ref int[2]); +} else version (Solaris) { alias uint socklen_t; @@ -1320,6 +1517,13 @@ else version( FreeBSD ) AF_INET6 = 28 } } +else version(NetBSD) +{ + enum + { + AF_INET6 = 24 + } +} else version (Solaris) { enum @@ -1367,6 +1571,13 @@ else version( FreeBSD ) SOCK_RAW = 3 } } +else version(NetBSD) +{ + enum + { + SOCK_RAW = 3 + } +} else version (Solaris) { enum diff --git a/src/core/sys/posix/sys/stat.d b/src/core/sys/posix/sys/stat.d index 2fa4f86fb3..669b7c7a5b 100644 --- a/src/core/sys/posix/sys/stat.d +++ b/src/core/sys/posix/sys/stat.d @@ -803,6 +803,68 @@ else version( FreeBSD ) int futimens(int fd, ref const(timespec)[2] times); } } +else version(NetBSD) +{ + struct stat_t + { + dev_t st_dev; /* inode's device */ + mode_t st_mode; /* inode protection mode */ + ino_t st_ino; /* inode's number */ + nlink_t st_nlink; /* number of hard links */ + uid_t st_uid; /* user ID of the file's owner */ + gid_t st_gid; /* group ID of the file's group */ + dev_t st_rdev; /* device type */ + time_t st_atime; /* time of last access */ + long st_atimensec; /* nsec of last access */ + time_t st_mtime; /* time of last data modification */ + long st_mtimensec; /* nsec of last data modification */ + time_t st_ctime; /* time of last file status change */ + long st_ctimensec; /* nsec of last file status change */ + time_t st_birthtime; /* time of creation */ + long st_birthtimensec; /* nsec of time of creation */ + off_t st_size; /* file size, in bytes */ + blkcnt_t st_blocks; /* blocks allocated for file */ + blksize_t st_blksize; /* optimal blocksize for I/O */ + uint32_t st_flags; /* user defined flags for file */ + uint32_t st_gen; /* file generation number */ + uint32_t[2] st_spare; + } + + enum S_IRUSR = 0x100; // octal 0000400 + enum S_IWUSR = 0x080; // octal 0000200 + enum S_IXUSR = 0x040; // octal 0000100 + enum S_IRWXU = 0x1C0; // octal 0000700 + + enum S_IRGRP = 0x020; // octal 0000040 + enum S_IWGRP = 0x010; // octal 0000020 + enum S_IXGRP = 0x008; // octal 0000010 + enum S_IRWXG = 0x038; // octal 0000070 + + enum S_IROTH = 0x4; // 0000004 + enum S_IWOTH = 0x2; // 0000002 + enum S_IXOTH = 0x1; // 0000001 + enum S_IRWXO = 0x7; // 0000007 + + enum S_ISUID = 0x800; // octal 0004000 + enum S_ISGID = 0x400; // octal 0002000 + enum S_ISVTX = 0x200; // octal 0001000 + + private + { + extern (D) bool S_ISTYPE( mode_t mode, uint mask ) + { + return ( mode & S_IFMT ) == mask; + } + } + + extern (D) bool S_ISBLK( mode_t mode ) { return S_ISTYPE( mode, S_IFBLK ); } + extern (D) bool S_ISCHR( mode_t mode ) { return S_ISTYPE( mode, S_IFCHR ); } + extern (D) bool S_ISDIR( mode_t mode ) { return S_ISTYPE( mode, S_IFDIR ); } + extern (D) bool S_ISFIFO( mode_t mode ) { return S_ISTYPE( mode, S_IFIFO ); } + extern (D) bool S_ISREG( mode_t mode ) { return S_ISTYPE( mode, S_IFREG ); } + extern (D) bool S_ISLNK( mode_t mode ) { return S_ISTYPE( mode, S_IFLNK ); } + extern (D) bool S_ISSOCK( mode_t mode ) { return S_ISTYPE( mode, S_IFSOCK ); } +} else version (Solaris) { private enum _ST_FSTYPSZ = 16; @@ -1142,6 +1204,15 @@ else version( FreeBSD ) int lstat(in char*, stat_t*); int stat(in char*, stat_t*); } +else version(NetBSD) +{ + int __fstat50(int, stat_t*); + int __lstat50(in char*, stat_t*); + int __stat50(in char*, stat_t*); + alias __fstat50 fstat; + alias __lstat50 lstat; + alias __stat50 stat; +} else version( CRuntime_Bionic ) { int fstat(int, stat_t*) @trusted; @@ -1211,6 +1282,19 @@ else version( FreeBSD ) int mknod(in char*, mode_t, dev_t); } +else version(NetBSD) +{ + enum S_IFMT = 0xF000; // octal 0170000 + enum S_IFBLK = 0x6000; // octal 0060000 + enum S_IFCHR = 0x2000; // octal 0020000 + enum S_IFIFO = 0x1000; // octal 0010000 + enum S_IFREG = 0x8000; // octal 0100000 + enum S_IFDIR = 0x4000; // octal 0040000 + enum S_IFLNK = 0xA000; // octal 0120000 + enum S_IFSOCK = 0xC000; // octal 0140000 + + int mknod(in char*, mode_t, dev_t); +} else version (Solaris) { enum S_IFMT = 0xF000; diff --git a/src/core/sys/posix/sys/time.d b/src/core/sys/posix/sys/time.d index b3bb1d98f7..a4bfd68f09 100644 --- a/src/core/sys/posix/sys/time.d +++ b/src/core/sys/posix/sys/time.d @@ -134,6 +134,25 @@ else version( FreeBSD ) int setitimer(int, in itimerval*, itimerval*); int utimes(in char*, ref const(timeval)[2]); } +else version(NetBSD) +{ + struct timeval + { + time_t tv_sec; + suseconds_t tv_usec; + } + + struct itimerval + { + timeval it_interval; + timeval it_value; + } + + int getitimer(int, itimerval*); + int gettimeofday(timeval*, void*); // timezone_t* is normally void* + int setitimer(int, in itimerval*, itimerval*); + int utimes(in char*, ref const(timeval)[2]); +} else version (Solaris) { struct timeval diff --git a/src/core/sys/posix/sys/types.d b/src/core/sys/posix/sys/types.d index cd2dc60d21..a609f2be22 100644 --- a/src/core/sys/posix/sys/types.d +++ b/src/core/sys/posix/sys/types.d @@ -143,6 +143,22 @@ else version( FreeBSD ) alias uint uid_t; alias uint fflags_t; } +else version(NetBSD) +{ + alias long blkcnt_t; + alias int blksize_t; + alias ulong dev_t; + alias uint gid_t; + alias ulong ino_t; + alias uint mode_t; + alias uint nlink_t; + alias ulong off_t; + alias int pid_t; + //size_t (defined in core.stdc.stddef) + alias c_long ssize_t; + alias c_long time_t; + alias uint uid_t; +} else version (Solaris) { alias char* caddr_t; @@ -274,6 +290,16 @@ else version( FreeBSD ) alias c_long suseconds_t; alias uint useconds_t; } +else version(NetBSD) +{ + alias ulong fsblkcnt_t; + alias ulong fsfilcnt_t; + alias c_long clock_t; + alias long id_t; + alias c_long key_t; + alias c_long suseconds_t; + alias uint useconds_t; +} else version (Solaris) { static if (__USE_FILE_OFFSET64) @@ -650,6 +676,74 @@ else version( FreeBSD ) alias void* pthread_rwlockattr_t; alias void* pthread_t; } +else version(NetBSD) +{ + struct pthread_queue_t { + void* ptqh_first; + void** ptqh_last; + } + + alias lwpid_t = int; + alias pthread_spin_t = ubyte; + struct pthread_attr_t { + uint pta_magic; + int pta_flags; + void* pta_private; + } + struct pthread_spinlock_t { + uint pts_magic; + pthread_spin_t pts_spin; + int pts_flags; + } + struct pthread_cond_t { + uint ptc_magic; + pthread_spin_t ptc_lock; + pthread_queue_t ptc_waiters; + pthread_mutex_t *ptc_mutex; + void* ptc_private; + } + struct pthread_condattr_t { + uint ptca_magic; + void *ptca_private; + } + struct pthread_mutex_t { + uint ptm_magic; + pthread_spin_t ptm_errorcheck; + ubyte[3] ptm_pad1; + pthread_spin_t ptm_interlock; + ubyte[3] ptm_pad2; + pthread_t ptm_owner; + void* ptm_waiters; + uint ptm_recursed; + void* ptm_spare2; + } + struct pthread_mutexattr_t{ + uint ptma_magic; + void* ptma_private; + } + struct pthread_once_t{ + pthread_mutex_t pto_mutex; + int pto_done; + } + struct pthread_rwlock_t{ + uint ptr_magic; + + pthread_spin_t ptr_interlock; + + pthread_queue_t ptr_rblocked; + pthread_queue_t ptr_wblocked; + uint ptr_nreaders; + pthread_t ptr_owner; + void *ptr_private; + } + struct pthread_rwlockattr_t{ + uint ptra_magic; + void* ptra_private; + } + + alias uint pthread_key_t; + alias void* pthread_t; +} else version (Solaris) { alias uint pthread_t; @@ -814,6 +908,11 @@ else version( FreeBSD ) alias void* pthread_barrier_t; alias void* pthread_barrierattr_t; } +else version(NetBSD) +{ + alias void* pthread_barrier_t; + alias void* pthread_barrierattr_t; +} else version( Darwin ) { } @@ -857,6 +956,10 @@ else version( FreeBSD ) { alias void* pthread_spinlock_t; } +else version(NetBSD) +{ + //already defined +} else version (Solaris) { alias pthread_mutex_t pthread_spinlock_t; diff --git a/src/core/sys/posix/sys/uio.d b/src/core/sys/posix/sys/uio.d index ffa0b3e298..9b5758742c 100644 --- a/src/core/sys/posix/sys/uio.d +++ b/src/core/sys/posix/sys/uio.d @@ -79,6 +79,17 @@ else version( FreeBSD ) ssize_t readv(int, in iovec*, int); ssize_t writev(int, in iovec*, int); } +else version(NetBSD) +{ + struct iovec + { + void* iov_base; + size_t iov_len; + } + + ssize_t readv(int, in iovec*, int); + ssize_t writev(int, in iovec*, int); +} else version (Solaris) { struct iovec diff --git a/src/core/sys/posix/sys/un.d b/src/core/sys/posix/sys/un.d index ad504d4c1c..1b6c7b08e9 100644 --- a/src/core/sys/posix/sys/un.d +++ b/src/core/sys/posix/sys/un.d @@ -69,6 +69,15 @@ else version( FreeBSD ) byte[104] sun_path; } } +else version(NetBSD) +{ + struct sockaddr_un + { + ubyte sun_len; + sa_family_t sun_family; + byte[104] sun_path; + } +} else version( Solaris ) { struct sockaddr_un diff --git a/src/core/sys/posix/sys/utsname.d b/src/core/sys/posix/sys/utsname.d index a87c5fb078..b41030a2e2 100644 --- a/src/core/sys/posix/sys/utsname.d +++ b/src/core/sys/posix/sys/utsname.d @@ -62,6 +62,22 @@ else version(FreeBSD) int uname(utsname* __name); } +else version(NetBSD) +{ + private enum utsNameLength = 256; + + struct utsname + { + char[utsNameLength] sysname; + char[utsNameLength] nodename; + char[utsNameLength] release; + // The field name is version but version is a keyword in D. + char[utsNameLength] update; + char[utsNameLength] machine; + } + + int uname(utsname* __name); +} else version(Solaris) { private enum SYS_NMLN = 257; diff --git a/src/core/sys/posix/sys/wait.d b/src/core/sys/posix/sys/wait.d index a69c885f00..6d39de7f8f 100644 --- a/src/core/sys/posix/sys/wait.d +++ b/src/core/sys/posix/sys/wait.d @@ -122,6 +122,28 @@ else version( FreeBSD ) extern (D) int WSTOPSIG( int status ) { return status >> 8; } extern (D) int WTERMSIG( int status ) { return _WSTATUS( status ); } } +else version(NetBSD) +{ + enum WNOHANG = 1; + enum WUNTRACED = 2; + + private + { + enum _WSTOPPED = 0x7F; // octal 0177 + } + + extern (D) int _WSTATUS(int status) { return (status & 0x7F); } + extern (D) int WEXITSTATUS( int status ) { return (status >> 8); } + extern (D) int WIFCONTINUED( int status ) { return status == 0x13; } + extern (D) bool WIFEXITED( int status ) { return _WSTATUS(status) == 0; } + extern (D) bool WIFSIGNALED( int status ) + { + return _WSTATUS( status ) != _WSTOPPED && _WSTATUS( status ) != 0; + } + extern (D) bool WIFSTOPPED( int status ) { return _WSTATUS( status ) == _WSTOPPED; } + extern (D) int WSTOPSIG( int status ) { return status >> 8; } + extern (D) int WTERMSIG( int status ) { return _WSTATUS( status ); } +} else version (Solaris) { enum WNOHANG = 64; @@ -214,6 +236,12 @@ else version (FreeBSD) // http://www.freebsd.org/projects/c99/ } +else version (NetBSD) +{ + enum WSTOPPED = WUNTRACED; + //enum WCONTINUED = 4; + enum WNOWAIT = 0x00010000; +} else version (Solaris) { enum WEXITED = 1; diff --git a/src/core/sys/posix/syslog.d b/src/core/sys/posix/syslog.d index 23e2fbce82..20939aa503 100644 --- a/src/core/sys/posix/syslog.d +++ b/src/core/sys/posix/syslog.d @@ -211,6 +211,71 @@ else version( FreeBSD ) void syslog (int __pri, const char *__fmt, ...); void closelog(); } +else version(NetBSD) +{ + //http://fxr.watson.org/fxr/source/sys/syslog.h + + //PRIORITY + enum { + LOG_EMERG = 0, /* system is unusable */ + LOG_ALERT = 1, /* action must be taken immediately */ + LOG_CRIT = 2, /* critical conditions */ + LOG_ERR = 3, /* error conditions */ + LOG_WARNING = 4, /* warning conditions */ + LOG_NOTICE = 5, /* normal but significant condition */ + LOG_INFO = 6, /* informational */ + LOG_DEBUG = 7, /* debug-level messages */ + }; + + //OPTIONS + enum { + LOG_PID = 0x01, /* log the pid with each message */ + LOG_CONS = 0x02, /* log on the console if errors in sending */ + LOG_ODELAY = 0x04, /* delay open until first syslog() (default) */ + LOG_NDELAY = 0x08, /* don't delay open */ + LOG_NOWAIT = 0x10, /* don't wait for console forks: DEPRECATED */ + LOG_PERROR = 0x20, /* log to stderr as well */ + }; + + //FACILITY + enum { + LOG_KERN = (0<<3), /* kernel messages */ + LOG_USER = (1<<3), /* random user-level messages */ + LOG_MAIL = (2<<3), /* mail system */ + LOG_DAEMON = (3<<3), /* system daemons */ + LOG_AUTH = (4<<3), /* security/authorization messages */ + LOG_SYSLOG = (5<<3), /* messages generated internally by syslogd */ + LOG_LPR = (6<<3), /* line printer subsystem */ + LOG_NEWS = (7<<3), /* network news subsystem */ + LOG_UUCP = (8<<3), /* UUCP subsystem */ + LOG_CRON = (9<<3), /* clock daemon */ + LOG_AUTHPRIV = (10<<3), /* security/authorization messages (private), */ + LOG_FTP = (11<<3), /* ftp daemon */ + LOG_NTP = (12<<3), /* NTP subsystem */ + LOG_SECURITY = (13<<3), /* security subsystems (firewalling, etc.) */ + LOG_CONSOLE = (14<<3), /* /dev/console output */ + + /* other codes through 15 reserved for system use */ + LOG_LOCAL0 = (16<<3), /* reserved for local use */ + LOG_LOCAL1 = (17<<3), /* reserved for local use */ + LOG_LOCAL2 = (18<<3), /* reserved for local use */ + LOG_LOCAL3 = (19<<3), /* reserved for local use */ + LOG_LOCAL4 = (20<<3), /* reserved for local use */ + LOG_LOCAL5 = (21<<3), /* reserved for local use */ + LOG_LOCAL6 = (22<<3), /* reserved for local use */ + LOG_LOCAL7 = (23<<3), /* reserved for local use */ + + LOG_NFACILITIES = 24, /* current number of facilities */ + }; + + int LOG_MASK(int pri) { return 1 << pri; } /* mask for one priority */ + int LOG_UPTO(int pri) { return (1 << (pri+1)) - 1; } /* all priorities through pri */ + + void openlog (const char *, int __option, int __facility); + int setlogmask (int __mask); + void syslog (int __pri, const char *__fmt, ...); + void closelog(); +} else version( Solaris ) { //http://pubs.opengroup.org/onlinepubs/007904875/basedefs/syslog.h.html diff --git a/src/core/sys/posix/termios.d b/src/core/sys/posix/termios.d index 5a56fd071c..8642f540ef 100644 --- a/src/core/sys/posix/termios.d +++ b/src/core/sys/posix/termios.d @@ -468,6 +468,114 @@ else version ( FreeBSD ) int tcsetattr(int, int, in termios*); } +else version (NetBSD) +{ + alias ubyte cc_t; + alias uint speed_t; + alias uint tcflag_t; + + enum NCCS = 20; + + struct termios + { + tcflag_t c_iflag; + tcflag_t c_oflag; + tcflag_t c_cflag; + tcflag_t c_lflag; + cc_t[NCCS] c_cc; + speed_t c_ispeed; + speed_t c_ospeed; + } + + enum VEOF = 0; + enum VEOL = 1; + enum VERASE = 3; + enum VINTR = 8; + enum VKILL = 5; + enum VMIN = 16; + enum VQUIT = 9; + enum VSTART = 12; + enum VSTOP = 13; + enum VSUSP = 10; + enum VTIME = 17; + + enum BRKINT = 0x0000002; + enum ICRNL = 0x0000100; + enum IGNBRK = 0x0000001; + enum IGNCR = 0x0000080; + enum IGNPAR = 0x0000004; + enum INLCR = 0x0000040; + enum INPCK = 0x0000010; + enum ISTRIP = 0x0000020; + enum IXOFF = 0x0000400; + enum IXON = 0x0000200; + enum PARMRK = 0x0000008; + + enum OPOST = 0x0000001; + + enum B0 = 0; + enum B50 = 50; + enum B75 = 75; + enum B110 = 110; + enum B134 = 134; + enum B150 = 150; + enum B200 = 200; + enum B300 = 300; + enum B600 = 600; + enum B1200 = 1200; + enum B1800 = 1800; + enum B2400 = 2400; + enum B4800 = 4800; + enum B9600 = 9600; + enum B19200 = 19200; + enum B38400 = 38400; + + enum CSIZE = 0x0000300; + enum CS5 = 0x0000000; + enum CS6 = 0x0000100; + enum CS7 = 0x0000200; + enum CS8 = 0x0000300; + enum CSTOPB = 0x0000400; + enum CREAD = 0x0000800; + enum PARENB = 0x0001000; + enum PARODD = 0x0002000; + enum HUPCL = 0x0004000; + enum CLOCAL = 0x0008000; + + enum ECHO = 0x00000008; + enum ECHOE = 0x00000002; + enum ECHOK = 0x00000004; + enum ECHONL = 0x00000010; + enum ICANON = 0x00000100; + enum IEXTEN = 0x00000400; + enum ISIG = 0x00000080; + enum NOFLSH = 0x80000000; + enum TOSTOP = 0x00400000; + + enum TCSANOW = 0; + enum TCSADRAIN = 1; + enum TCSAFLUSH = 2; + + enum TCIFLUSH = 1; + enum TCOFLUSH = 2; + enum TCIOFLUSH = 3; + + enum TCIOFF = 3; + enum TCION = 4; + enum TCOOFF = 1; + enum TCOON = 2; + + speed_t cfgetispeed(in termios*); + speed_t cfgetospeed(in termios*); + int cfsetispeed(termios*, speed_t); + int cfsetospeed(termios*, speed_t); + int tcdrain(int); + int tcflow(int, int); + int tcflush(int, int); + int tcgetattr(int, termios*); + int tcsendbreak(int, int); + int tcsetattr(int, int, in termios*); +} else version (Solaris) { alias tcflag_t = uint; @@ -743,6 +851,40 @@ else version( FreeBSD ) pid_t tcgetsid(int); } +else version(NetBSD) +{ + enum IXANY = 0x00000800; + + enum ONLCR = 0x00000002; + enum OCRNL = 0x00000010; + enum ONOCR = 0x00000020; + enum ONLRET = 0x00000040; + //enum OFILL + //enum NLDLY + //enum NL0 + //enum NL1 + //enum CRDLY + //enum CR0 + //enum CR1 + //enum CR2 + //enum CR3 + enum TABDLY = 0x00000004; + enum TAB0 = 0x00000000; + //enum TAB1 + //enum TAB2 + enum TAB3 = 0x00000004; + //enum BSDLY + //enum BS0 + //enum BS1 + //enum VTDLY + //enum VT0 + //enum VT1 + //enum FFDLY + //enum FF0 + //enum FF1 + + pid_t tcgetsid(int); +} else version (Solaris) { enum IXANY = 0x0000800; diff --git a/src/core/sys/posix/time.d b/src/core/sys/posix/time.d index ef0e3b0cbd..2bf9e96fdc 100644 --- a/src/core/sys/posix/time.d +++ b/src/core/sys/posix/time.d @@ -61,6 +61,10 @@ else version( FreeBSD ) { time_t timegm(tm*); // non-standard } +else version(NetBSD) +{ + time_t timegm(tm*); // non-standard +} else version (Solaris) { time_t timegm(tm*); // non-standard @@ -124,6 +128,11 @@ else version (FreeBSD) deprecated("Please import it from core.sys.freebsd.time instead.") alias CLOCK_MONOTONIC_FAST = core.sys.freebsd.time.CLOCK_MONOTONIC_FAST; } +else version (NetBSD) +{ + // time.h + enum CLOCK_MONOTONIC = 3; +} else version (Darwin) { // No CLOCK_MONOTONIC defined @@ -254,6 +263,30 @@ else version( FreeBSD ) int timer_getoverrun(timer_t); int timer_settime(timer_t, int, in itimerspec*, itimerspec*); } +else version(NetBSD) +{ + struct itimerspec + { + timespec it_interval; + timespec it_value; + } + + enum CLOCK_REALTIME = 0; + enum TIMER_ABSTIME = 0x01; + + alias int clockid_t; // + alias int timer_t; + + int clock_getres(clockid_t, timespec*); + int clock_gettime(clockid_t, timespec*); + int clock_settime(clockid_t, in timespec*); + int nanosleep(in timespec*, timespec*); + int timer_create(clockid_t, sigevent*, timer_t*); + int timer_delete(timer_t); + int timer_gettime(timer_t, itimerspec*); + int timer_getoverrun(timer_t); + int timer_settime(timer_t, int, in itimerspec*, itimerspec*); +} else version (Solaris) { enum CLOCK_PROCESS_CPUTIME_ID = 5; // @@ -347,6 +380,13 @@ else version( FreeBSD ) tm* gmtime_r(in time_t*, tm*); tm* localtime_r(in time_t*, tm*); } +else version(NetBSD) +{ + char* asctime_r(in tm*, char*); + char* ctime_r(in time_t*, char*); + tm* gmtime_r(in time_t*, tm*); + tm* localtime_r(in time_t*, tm*); +} else version (Solaris) { char* asctime_r(in tm*, char*); @@ -400,6 +440,11 @@ else version( FreeBSD ) //tm* getdate(in char*); char* strptime(in char*, in char*, tm*); } +else version(NetBSD) +{ + tm* getdate(in char*); + char* strptime(in char*, in char*, tm*); +} else version (Solaris) { extern __gshared c_long timezone, altzone; diff --git a/src/core/sys/posix/ucontext.d b/src/core/sys/posix/ucontext.d index 54e6cc095b..e0f393fe39 100644 --- a/src/core/sys/posix/ucontext.d +++ b/src/core/sys/posix/ucontext.d @@ -701,6 +701,62 @@ else version( FreeBSD ) int[4] __spare__; } } +else version(NetBSD) +{ + + version( X86_64 ) + { + enum { NGREG = 26 }; + alias __greg_t = ulong; + alias __gregset_t = __greg_t[NGREG]; + alias __fpregset_t = align(8)ubyte[512]; + + struct mcontext_t { + __gregset_t __gregs; + __greg_t _mc_tlsbase; + __fpregset_t __fpregs; + } + } + else version( X86 ) + { + enum { NGREG = 19 }; + alias __greg_t = ulong; + alias __gregset_t = __greg_t[_NGREG]; + struct __fpregset_t{ + union __fp_reg_set{ + struct __fpchip_state{ + int[27] __fp_state; /* Environment and registers */ + } ; /* x87 regs in fsave format */ + struct __fp_xmm_state{ + ubyte[512] __fp_xmm; + } ; /* x87 and xmm regs in fxsave format */ + int[128] __fp_fpregs; + }; + __fpregset_t __fp_reg_set; + int[33] __fp_pad; /* Historic padding */ + }; + + struct mcontext_t { + __gregset_t __gregs; + __fpregset_t __fpregs; + __greg_t _mc_tlsbase; + } + } + + struct ucontext_t + { + uint uc_flags; /* properties */ + ucontext_t * uc_link; /* context to resume */ + sigset_t uc_sigmask; /* signals blocked in this context */ + stack_t uc_stack; /* the stack used by this context */ + mcontext_t uc_mcontext; /* machine state */ + /+ todo #if defined(_UC_MACHINE_PAD) + long __uc_pad[_UC_MACHINE_PAD]; + #endif + +/ + + } +} else version ( Solaris ) { alias uint[4] upad128_t; diff --git a/src/core/sys/posix/unistd.d b/src/core/sys/posix/unistd.d index b99de41f49..8821e544dd 100644 --- a/src/core/sys/posix/unistd.d +++ b/src/core/sys/posix/unistd.d @@ -125,6 +125,11 @@ else version( FreeBSD ) off_t lseek(int, off_t, int) @trusted; int ftruncate(int, off_t) @trusted; } +else version(NetBSD) +{ + off_t lseek(int, off_t, int) @trusted; + int ftruncate(int, off_t) @trusted; +} else version( Solaris ) { version ( D_LP64 ) @@ -817,6 +822,143 @@ else version( FreeBSD ) _CS_POSIX_V6_WIDTH_RESTRICTED_ENVS = 14, } } +else version(NetBSD) +{ + enum F_OK = 0; + enum R_OK = 0x04; + enum W_OK = 0x02; + enum X_OK = 0x01; + + enum F_ULOCK = 0; + enum F_LOCK = 1; + enum F_TLOCK = 2; + enum F_TEST = 3; + + enum + { + _SC_ARG_MAX = 1, + _SC_CHILD_MAX = 2, + _O_SC_CLK_TCK = 3, + _SC_NGROUPS_MAX = 4, + _SC_OPEN_MAX = 5, + _SC_JOB_CONTROL = 6, + _SC_SAVED_IDS = 7, + _SC_VERSION = 8, + _SC_BC_BASE_MAX = 9, + _SC_BC_DIM_MAX = 10, + _SC_BC_SCALE_MAX = 11, + _SC_BC_STRING_MAX = 12, + _SC_COLL_WEIGHTS_MAX = 13, + _SC_EXPR_NEST_MAX = 14, + _SC_LINE_MAX = 15, + _SC_RE_DUP_MAX = 16, + _SC_2_VERSION = 17, + _SC_2_C_BIND = 18, + _SC_2_C_DEV = 19, + _SC_2_CHAR_TERM = 20, + _SC_2_FORT_DEV = 21, + _SC_2_FORT_RUN = 22, + _SC_2_LOCALEDEF = 23, + _SC_2_SW_DEV = 24, + _SC_2_UPE = 25, + _SC_STREAM_MAX = 26, + _SC_TZNAME_MAX = 27, + _SC_PAGESIZE = 28, + _SC_FSYNC = 29, + _SC_XOPEN_SHM = 30, + _SC_SYNCHRONIZED_IO = 31, + _SC_IOV_MAX = 32, + _SC_MAPPED_FILES = 33, + _SC_MEMLOCK = 34, + _SC_MEMLOCK_RANGE = 35, + _SC_MEMORY_PROTECTION = 36, + _SC_LOGIN_NAME_MAX = 37, + _SC_MONOTONIC_CLOCK = 38, + _SC_CLK_TCK = 39, + _SC_ATEXIT_MAX = 40, + _SC_THREADS = 41, + _SC_SEMAPHORES = 42, + _SC_BARRIERS = 43, + _SC_TIMERS = 44, + _SC_SPIN_LOCKS = 45, + _SC_READER_WRITER_LOCKS = 46, + _SC_GETGR_R_SIZE_MAX = 47, + _SC_GETPW_R_SIZE_MAX = 48, + _SC_CLOCK_SELECTION = 49, + _SC_ASYNCHRONOUS_IO = 50, + _SC_AIO_LISTIO_MAX = 51, + _SC_AIO_MAX = 52, + _SC_MESSAGE_PASSING = 53, + _SC_MQ_OPEN_MAX = 54, + _SC_MQ_PRIO_MAX = 55, + _SC_PRIORITY_SCHEDULING = 56, + _SC_THREAD_DESTRUCTOR_ITERATIONS = 57, + _SC_THREAD_KEYS_MAX = 58, + _SC_THREAD_STACK_MIN = 59, + _SC_THREAD_THREADS_MAX = 60, + _SC_THREAD_ATTR_STACKADDR = 61, + _SC_THREAD_ATTR_STACKSIZE = 62, + _SC_THREAD_PRIORITY_SCHEDULING = 63, + _SC_THREAD_PRIO_INHERIT = 64, + _SC_THREAD_PRIO_PROTECT = 65, + _SC_THREAD_PROCESS_SHARED = 66, + _SC_THREAD_SAFE_FUNCTIONS = 67, + _SC_TTY_NAME_MAX = 68, + _SC_HOST_NAME_MAX = 69, + _SC_PASS_MAX = 70, + _SC_REGEXP = 71, + _SC_SHELL = 72, + _SC_SYMLOOP_MAX = 73, + + /* Actually, they are not supported or implemented yet */ + _SC_V6_ILP32_OFF32 = 74, + _SC_V6_ILP32_OFFBIG = 75, + _SC_V6_LP64_OFF64 = 76, + _SC_V6_LPBIG_OFFBIG = 77, + _SC_2_PBS = 80, + _SC_2_PBS_ACCOUNTING = 81, + _SC_2_PBS_CHECKPOINT = 82, + _SC_2_PBS_LOCATE = 83, + _SC_2_PBS_MESSAGE = 84, + _SC_2_PBS_TRACK = 85, + + /* These are implemented */ + _SC_SPAWN = 86, + _SC_SHARED_MEMORY_OBJECTS = 87, + + /* Extensions found in Solaris and Linux. */ + _SC_PHYS_PAGES = 121, + + /* Commonly provided sysconf() extensions */ + _SC_NPROCESSORS_CONF = 1001, + _SC_NPROCESSORS_ONLN = 1002, + /* Native variables */ + _SC_SCHED_RT_TS = 2001, + _SC_SCHED_PRI_MIN = 2002, + _SC_SCHED_PRI_MAX = 2003 + + } + + enum _SC_PAGE_SIZE = _SC_PAGESIZE; + + enum + { + _CS_PATH = 1, + _CS_POSIX_V6_ILP32_OFF32_CFLAGS = 2, + _CS_POSIX_V6_ILP32_OFF32_LDFLAGS = 3, + _CS_POSIX_V6_ILP32_OFF32_LIBS = 4, + _CS_POSIX_V6_ILP32_OFFBIG_CFLAGS = 5, + _CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS = 6, + _CS_POSIX_V6_ILP32_OFFBIG_LIBS = 7, + _CS_POSIX_V6_LP64_OFF64_CFLAGS = 8, + _CS_POSIX_V6_LP64_OFF64_LDFLAGS = 9, + _CS_POSIX_V6_LP64_OFF64_LIBS = 10, + _CS_POSIX_V6_LPBIG_OFFBIG_CFLAGS = 11, + _CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGS = 12, + _CS_POSIX_V6_LPBIG_OFFBIG_LIBS = 13, + _CS_POSIX_V6_WIDTH_RESTRICTED_ENVS = 14, + } +} else version( CRuntime_Bionic ) { enum F_OK = 0; @@ -1115,6 +1257,10 @@ else version( FreeBSD ) { int fsync(int) @trusted; } +else version(NetBSD) +{ + int fsync(int) @trusted; +} else version( CRuntime_Bionic ) { int fsync(int) @trusted; @@ -1269,6 +1415,31 @@ else version( FreeBSD ) int usleep(useconds_t) @trusted; pid_t vfork(); } +else version(NetBSD) +{ + char* crypt(in char*, in char*); + //char* ctermid(char*); + void encrypt(ref char[64], int) @trusted; + int fchdir(int) @trusted; + c_long gethostid() @trusted; + int getpgid(pid_t) @trusted; + int getsid(pid_t) @trusted; + char* getwd(char*); // LEGACY + int lchown(in char*, uid_t, gid_t); + int lockf(int, int, off_t) @trusted; + int nice(int) @trusted; + ssize_t pread(int, void*, size_t, off_t); + ssize_t pwrite(int, in void*, size_t, off_t); + int setpgrp(pid_t, pid_t) @trusted; + int setregid(gid_t, gid_t) @trusted; + int setreuid(uid_t, uid_t) @trusted; + void swab(in void*, void*, ssize_t); + void sync() @trusted; + int truncate(in char*, off_t); + useconds_t ualarm(useconds_t, useconds_t) @trusted; + int usleep(useconds_t) @trusted; + pid_t vfork(); +} else version( CRuntime_Bionic ) { int fchdir(int) @trusted; diff --git a/src/core/sys/posix/utime.d b/src/core/sys/posix/utime.d index 25166f6736..89d15f56e7 100644 --- a/src/core/sys/posix/utime.d +++ b/src/core/sys/posix/utime.d @@ -74,6 +74,16 @@ else version( FreeBSD ) int utime(in char*, in utimbuf*); } +else version(NetBSD) +{ + struct utimbuf + { + time_t actime; + time_t modtime; + } + + int utime(in char*, in utimbuf*); +} else version( Solaris ) { struct utimbuf From c5bdd290029d2bb790a2130d066eab6018264890 Mon Sep 17 00:00:00 2001 From: anonymous Date: Mon, 13 Mar 2017 12:33:30 +0100 Subject: [PATCH 77/82] @disable TypeInfo.init --- changelog/disable-TypeInfo.init.dd | 6 ++++++ src/object.d | 8 +++----- 2 files changed, 9 insertions(+), 5 deletions(-) create mode 100644 changelog/disable-TypeInfo.init.dd diff --git a/changelog/disable-TypeInfo.init.dd b/changelog/disable-TypeInfo.init.dd new file mode 100644 index 0000000000..5cd5decc19 --- /dev/null +++ b/changelog/disable-TypeInfo.init.dd @@ -0,0 +1,6 @@ +TypeInfo.init has been `@disable`d. + +This is a step towards removal of `TypeInfo.init`, which is necessary to resolve +a name clash with the type property $(GLINK2 property, init). + +Use $(REF_OBJECT_SHORT TypeInfo.initializer) instead. diff --git a/src/object.d b/src/object.d index fb1709450b..0838124d88 100644 --- a/src/object.d +++ b/src/object.d @@ -296,11 +296,9 @@ class TypeInfo */ abstract const(void)[] initializer() nothrow pure const @safe @nogc; - /// $(RED Scheduled for deprecation.) Please use `initializer` instead. - deprecated("Please use initializer instead.") alias init = initializer; - // since 2.072 - version(none) @disable static const(void)[] init(); // planned for 2.073 - /* Planned for 2.074: Remove init, making way for the init type property, + /// $(RED Removed.) Please use `initializer` instead. + @disable static const(void)[] init(); // since 2.074 + /* Planned for 2.075: Remove init, making way for the init type property, fixing issue 12233. */ /** Get flags for type: 1 means GC should scan for pointers, From 47f9fe25f1967a7b235e0e13b0a9553456e78cf0 Mon Sep 17 00:00:00 2001 From: anonymous Date: Mon, 13 Mar 2017 17:09:25 +0100 Subject: [PATCH 78/82] changelog tweaks --- changelog/disable-TypeInfo.init.dd | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/changelog/disable-TypeInfo.init.dd b/changelog/disable-TypeInfo.init.dd index 5cd5decc19..824635eae3 100644 --- a/changelog/disable-TypeInfo.init.dd +++ b/changelog/disable-TypeInfo.init.dd @@ -1,6 +1,12 @@ -TypeInfo.init has been `@disable`d. +`TypeInfo.init` has been `@disable`d. -This is a step towards removal of `TypeInfo.init`, which is necessary to resolve -a name clash with the type property $(GLINK2 property, init). +$(REF_OBJECT_SHORT TypeInfo.init) has been `@disable`d. Use +$(REF_OBJECT_SHORT TypeInfo.initializer) instead. -Use $(REF_OBJECT_SHORT TypeInfo.initializer) instead. +`TypeInfo.init` is a legacy alias of the method that is now called +$(REF_OBJECT_SHORT TypeInfo.initializer). The name change is necessary because +the name "init" clashes with the type property of the same name +($(GLINK2 property, init)). + +The legacy alias has been deprecated since 2.072.0. It's going to be removed in +2.075.0. From 804c713bf11f23a596093c6a427358bb7b00566e Mon Sep 17 00:00:00 2001 From: somzzz Date: Fri, 10 Mar 2017 05:30:21 -0800 Subject: [PATCH 79/82] _equals for structs --- src/object.d | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/src/object.d b/src/object.d index fb1709450b..aae26b485e 100644 --- a/src/object.d +++ b/src/object.d @@ -3241,6 +3241,71 @@ template RTInfo(T) enum RTInfo = null; } +// lhs == rhs lowers to __equals(lhs, rhs) for arrays of all struct types. +// old path: Typeinfo_array => TypeInfo_struct +bool __equals(T1, T2)(T1[] lhs, T2[] rhs) +{ + if (lhs.length != rhs.length) + return false; + + import core.internal.traits : Unqual; + static assert(is(Unqual!T1 == Unqual!T2), "Internal error."); + + static @trusted ref R at(R)(R[] r, size_t i) { return r.ptr[i]; } + + foreach (const u; 0 .. lhs.length) + { + static if (__traits(compiles, at(lhs, u).opEquals(at(rhs, u)))) + { + if (!at(lhs, u).opEquals(at(rhs, u))) + return false; + } + else + { + if (at(lhs, u).tupleof != at(rhs, u).tupleof) + return false; + } + } + + return true; +} + +unittest +{ + struct A + { + int a; + } + + auto arr1 = [A(0), A(2)]; + auto arr2 = [A(0), A(1)]; + auto arr3 = [A(0), A(1)]; + + assert(arr1 != arr2); + assert(arr2 == arr3); +} + +unittest +{ + struct A + { + int a; + int b; + + bool opEquals(const A other) + { + return this.a == other.b && this.b == other.a; + } + } + + auto arr1 = [A(1, 0), A(0, 1)]; + auto arr2 = [A(1, 0), A(0, 1)]; + auto arr3 = [A(0, 1), A(1, 0)]; + + assert(arr1 != arr2); + assert(arr2 == arr3); +} + // Compare class and interface objects for ordering. private int __cmp(Obj)(Obj lhs, Obj rhs) if (is(Obj : Object)) From 1caa1fc2c98c0fe06b8440f435cbac744fe7729c Mon Sep 17 00:00:00 2001 From: Steven Schveighoffer Date: Thu, 16 Mar 2017 18:13:42 -0400 Subject: [PATCH 80/82] Fix issue 8411 - add opCast!bool support for Duration. --- src/core/time.d | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/core/time.d b/src/core/time.d index 12796ed600..db8c5ad3cb 100644 --- a/src/core/time.d +++ b/src/core/time.d @@ -1104,6 +1104,21 @@ public: } } + /++ + Returns `true` if this duration is non-zero. + +/ + bool opCast(T : bool)() const nothrow @nogc + { + return _hnsecs != 0; + } + + unittest + { + auto d = 10.minutes; + assert(d); + assert(!(d - d)); + assert(d + d); + } //Temporary hack until bug http://d.puremagic.com/issues/show_bug.cgi?id=5747 is fixed. Duration opCast(T)() const nothrow @nogc From 33b41c14e25f874111691f1f7a4708c8cbce4b7d Mon Sep 17 00:00:00 2001 From: Steven Schveighoffer Date: Fri, 17 Mar 2017 09:17:33 -0400 Subject: [PATCH 81/82] Fix docs --- src/core/time.d | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/core/time.d b/src/core/time.d index db8c5ad3cb..6cd1c65e04 100644 --- a/src/core/time.d +++ b/src/core/time.d @@ -1105,7 +1105,8 @@ public: } /++ - Returns `true` if this duration is non-zero. + Allow Duration to be used as a boolean. + Returns: `true` if this duration is non-zero. +/ bool opCast(T : bool)() const nothrow @nogc { From adfae798c4b4a41cb222cbeaeefa96b73d4c1f4f Mon Sep 17 00:00:00 2001 From: Jack Stouffer Date: Mon, 16 Jan 2017 08:13:56 -0500 Subject: [PATCH 82/82] Remove a catch of Throwable in object.d --- src/object.d | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/src/object.d b/src/object.d index 38b6144b3b..8f94d58600 100644 --- a/src/object.d +++ b/src/object.d @@ -207,23 +207,12 @@ class TypeInfo return typeid(this).name; } - override size_t toHash() @trusted const + override size_t toHash() @trusted const nothrow { import core.internal.traits : externDFunc; alias hashOf = externDFunc!("rt.util.hash.hashOf", size_t function(const(void)[], size_t) @trusted pure nothrow @nogc); - try - { - auto data = this.toString(); - return hashOf(data, 0); - } - catch (Throwable) - { - // This should never happen; remove when toString() is made nothrow - - // BUG: this prevents a compacting GC from working, needs to be fixed - return cast(size_t)cast(void*)this; - } + return hashOf(this.toString(), 0); } override int opCmp(Object o)