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 diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 0000000000..b6ae0190e5 --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,22 @@ +#!/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]] + ] + ) +} + +def pipeline +node { + dir('dlang/ci') { + clone 'https://github.com/Dicebot/dlangci.git', 'master' + } + pipeline = load 'dlang/ci/pipeline.groovy' +} +pipeline.runPipeline() 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. diff --git a/changelog/disable-TypeInfo.init.dd b/changelog/disable-TypeInfo.init.dd new file mode 100644 index 0000000000..824635eae3 --- /dev/null +++ b/changelog/disable-TypeInfo.init.dd @@ -0,0 +1,12 @@ +`TypeInfo.init` has been `@disable`d. + +$(REF_OBJECT_SHORT TypeInfo.init) has been `@disable`d. 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. diff --git a/circle.yml b/circle.yml index 5977d59a63..1f6682064d 100644 --- a/circle.yml +++ b/circle.yml @@ -7,11 +7,10 @@ dependencies: test: override: - make -f posix.mak style + - ./circleci.sh setup-repos - ./circleci.sh coverage: parallel: true 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 ca85a114ce..2f4941f518 100755 --- a/circleci.sh +++ b/circleci.sh @@ -2,32 +2,41 @@ 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} +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; 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 @@ -51,37 +60,58 @@ 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 - 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 + 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)" # 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 } +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 diff --git a/mak/COPY b/mak/COPY index ab914e078f..3b5fa33d98 100644 --- a/mak/COPY +++ b/mak/COPY @@ -95,6 +95,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\netinet\tcp.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/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/posix.mak b/posix.mak index befd52c9b4..22d76dfc87 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 @@ -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) @@ -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 test/typeinfo ADDITIONAL_TESTS+=$(if $(SHARED),test/shared,) endif 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) 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) diff --git a/src/core/internal/string.d b/src/core/internal/string.d index 96f2e580db..47741772a3 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,18 +190,24 @@ 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; - - 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/core/memory.d b/src/core/memory.d index 0a4270557d..573ed2e8b2 100644 --- a/src/core/memory.d +++ b/src/core/memory.d @@ -809,3 +809,105 @@ 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); + + // 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); +} + +// 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 +} 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 ) { /// @@ -452,10 +530,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 +616,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; @@ -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 @@ -822,9 +923,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 +943,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 +957,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 +1056,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 +1079,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 +1112,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 +1142,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 +1169,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 +1211,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 +1233,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 ) { @@ -1153,6 +1254,28 @@ else version( FreeBSD ) int fileno(FILE*); } + /// + int snprintf(scope char* s, size_t n, scope const char* format, ...); + /// + 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, ...); /// @@ -1245,9 +1368,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 +1390,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 +1412,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 +1422,7 @@ else } /// -void perror(in char* s); +void perror(scope const char* s); version(CRuntime_DigitalMars) { @@ -1406,28 +1529,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) diff --git a/src/core/stdc/stdlib.d b/src/core/stdc/stdlib.d index 9348c7d107..f3b8a7b7fb 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: @@ -75,38 +75,39 @@ 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; 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 +115,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 +130,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 +176,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 +199,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 +223,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/core/stdc/string.d b/src/core/stdc/string.d index abec39b449..8135cfe9b5 100644 --- a/src/core/stdc/string.d +++ b/src/core/stdc/string.d @@ -29,80 +29,84 @@ 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, 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, 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); diff --git a/src/core/stdc/tgmath.d b/src/core/stdc/tgmath.d index d6fe71975f..901e656d5f 100644 --- a/src/core/stdc/tgmath.d +++ b/src/core/stdc/tgmath.d @@ -567,6 +567,554 @@ version( FreeBSD ) /// alias core.stdc.complex.cprojl cproj; +// alias core.stdc.complex.creal creal; +// 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; 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/stdcpp/typeinfo.d b/src/core/stdcpp/typeinfo.d index a535dbf802..5dc3e18a79 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(); } } @@ -117,8 +112,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; diff --git a/src/core/sync/mutex.d b/src/core/sync/mutex.d index bdedb09986..605438c38f 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; } @@ -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 @@ -55,62 +57,92 @@ class Mutex : /** * Initializes a mutex object. * - * Throws: - * SyncError on error. */ - this() nothrow @trusted + this() @trusted nothrow @nogc + { + this(true); + } + + /// ditto + this() shared @trusted nothrow @nogc { - version( Windows ) + 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)) + { + version (Windows) { - InitializeCriticalSection( &m_hndl ); + InitializeCriticalSection(cast(CRITICAL_SECTION*) &m_hndl); } - else version( Posix ) + else version (Posix) { + import core.internal.abort : abort; 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) || + abort("Error: pthread_mutexattr_init failed."); - if( pthread_mutexattr_settype( &attr, PTHREAD_MUTEX_RECURSIVE ) ) - throw new SyncError( "Unable to initialize mutex" ); + scope (exit) !pthread_mutexattr_destroy(&attr) || + abort("Error: pthread_mutexattr_destroy failed."); - if( pthread_mutex_init( &m_hndl, &attr ) ) - throw new SyncError( "Unable to initialize mutex" ); + !pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE) || + abort("Error: pthread_mutexattr_settype failed."); + + !pthread_mutex_init(cast(pthread_mutex_t*) &m_hndl, &attr) || + abort("Error: pthread_mutex_init failed."); } + m_proxy.link = this; - this.__monitor = &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 ) nothrow @trusted + this(Object obj) @trusted nothrow @nogc + { + this(obj, true); + } + + /// ditto + this(Object obj) shared @trusted nothrow @nogc + { + this(obj, true); + } + + // Undocumented, useful only in Mutex.this(Object). + 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 = &m_proxy; + obj.__monitor = cast(void*) &m_proxy; } - ~this() + ~this() @trusted nothrow @nogc { - 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" ); + import core.internal.abort : abort; + !pthread_mutex_destroy(&m_hndl) || + abort("Error: pthread_mutex_init failed."); } this.__monitor = null; } @@ -125,30 +157,37 @@ 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() { lock_nothrow(); } - // undocumented function for internal use - final void lock_nothrow() nothrow @trusted @nogc + /// ditto + @trusted void lock() shared + { + lock_nothrow(); + } + + /// ditto + final void lock_nothrow(this Q)() nothrow @trusted @nogc + if (is(Q == Mutex) || is(Q == shared Mutex)) { - 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; } } @@ -156,30 +195,37 @@ 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() { unlock_nothrow(); } - // undocumented function for internal use - final void unlock_nothrow() nothrow @trusted @nogc + /// ditto + @trusted void unlock() shared + { + unlock_nothrow(); + } + + /// ditto + final void unlock_nothrow(this Q)() nothrow @trusted @nogc + if (is(Q == Mutex) || is(Q == shared Mutex)) { - 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; } } @@ -188,31 +234,45 @@ 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() + bool tryLock() @trusted + { + return tryLock_nothrow(); + } + + /// ditto + bool tryLock() shared @trusted { - version( Windows ) + return tryLock_nothrow(); + } + + /// ditto + final bool tryLock_nothrow(this Q)() nothrow @trusted @nogc + if (is(Q == Mutex) || is(Q == shared Mutex)) + { + 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 +286,7 @@ private: package: - version( Posix ) + version (Posix) { pthread_mutex_t* handleAddr() { @@ -235,41 +295,126 @@ 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; -//////////////////////////////////////////////////////////////////////////////// -// Unit Tests -//////////////////////////////////////////////////////////////////////////////// + void* p = malloc(__traits(classInstanceSize, Mutex)); + auto ti = typeid(Mutex); + p[0 .. ti.initializer.length] = ti.initializer[]; -version( unittest ) + 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); +} + +// Test single-thread (non-shared) use. +unittest { - private import core.thread; + Mutex m = new Mutex(); + m.lock(); - unittest - { - auto mutex = new Mutex; - int numThreads = 10; - int numTries = 1000; - int lockCount = 0; + m.tryLock(); + m.unlock(); + + m.unlock(); +} + +unittest +{ + import core.thread; - 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); } 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/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: diff --git a/src/core/sys/linux/sched.d b/src/core/sys/linux/sched.d index 6dc6e33655..fe5fd72b8c 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: @@ -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 { 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/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 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/iconv.d b/src/core/sys/posix/iconv.d index 792778cd6e..1bde829f52 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); 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 9ef960633e..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*); @@ -499,8 +562,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()); @@ -558,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; @@ -628,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); @@ -719,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 @@ -788,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*); @@ -834,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*); @@ -976,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 @@ -1071,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*); @@ -1133,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 4fb3655888..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/"; @@ -344,3 +348,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); 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 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) ) { 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); 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) { diff --git a/src/core/thread.d b/src/core/thread.d index a8e071ff71..0c9904ce15 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. @@ -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 = @@ -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. @@ -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 ); @@ -260,7 +260,7 @@ version( Windows ) } - HANDLE GetCurrentThreadHandle() + HANDLE GetCurrentThreadHandle() nothrow @nogc { const uint DUPLICATE_SAME_ACCESS = 0x00000002; @@ -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) { @@ -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; } @@ -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 ) { @@ -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 ) { @@ -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)) @@ -1176,7 +1190,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 +1386,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 +1511,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; } @@ -1509,7 +1523,7 @@ private: /////////////////////////////////////////////////////////////////////////// - final void pushContext( Context* c ) nothrow + final void pushContext( Context* c ) nothrow @nogc in { assert( !c.within ); @@ -1522,7 +1536,7 @@ private: } - final void popContext() nothrow + final void popContext() nothrow @nogc in { assert( m_curr && m_curr.within ); @@ -1536,7 +1550,7 @@ private: } - final Context* topContext() nothrow + final Context* topContext() nothrow @nogc in { assert( m_curr ); @@ -1644,12 +1658,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 +1709,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 +1735,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 +1766,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 +1810,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 +1926,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 +2053,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 +2186,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 +2212,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 +2274,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 +2941,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 +2960,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 +2978,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,17 +3137,17 @@ 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 (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); } -private void* getStackTop() nothrow +private void* getStackTop() nothrow @nogc { version (D_InlineAsm_X86) asm pure nothrow @nogc { naked; mov EAX, ESP; ret; } @@ -3146,7 +3160,7 @@ private void* getStackTop() nothrow } -private void* getStackBottom() nothrow +private void* getStackBottom() nothrow @nogc { version (Windows) { @@ -3188,6 +3202,17 @@ private void* getStackBottom() nothrow 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; @@ -3220,7 +3245,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 +3267,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 +3547,7 @@ shared static this() private { - extern (C) void fiber_entryPoint() + extern (C) void fiber_entryPoint() nothrow { Fiber obj = Fiber.getThis(); assert( obj ); @@ -3550,9 +3575,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 +4018,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 +4060,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); @@ -4063,7 +4093,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 ); @@ -4109,7 +4139,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 +4153,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 +4161,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 +4194,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 +4208,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 +4233,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 +4267,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 +4294,7 @@ private: // // Initializes a fiber object which has no associated executable function. // - this() nothrow + this() @safe pure nothrow @nogc { m_call = Call.NO; } @@ -4393,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; @@ -4443,7 +4474,7 @@ private: // // Free this fiber's stack. // - final void freeStack() nothrow + final void freeStack() nothrow @nogc in { assert( m_pmem && m_ctxt ); @@ -4486,7 +4517,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 +4852,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; } @@ -4838,7 +4869,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; @@ -4872,7 +4903,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; 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..6cd1c65e04 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; @@ -1086,6 +1104,22 @@ public: } } + /++ + Allow Duration to be used as a boolean. + 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 @@ -1140,9 +1174,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); } } diff --git a/src/gc/config.d b/src/gc/config.d index 7cb5b1e6c8..b0789cd2b2 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 (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 + * 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; } diff --git a/src/gc/impl/conservative/gc.d b/src/gc/impl/conservative/gc.d index a1f894dbc1..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; @@ -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) @@ -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. @@ -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/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/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/object.d b/src/object.d index da5bde6e2d..ba00985e1e 100644 --- a/src/object.d +++ b/src/object.d @@ -207,30 +207,19 @@ 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) { 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; @@ -296,11 +285,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, @@ -530,7 +517,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) ~ "]"; @@ -1473,7 +1460,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); @@ -1538,46 +1525,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) { @@ -1587,7 +1574,7 @@ const: return null; } - @property TypeInfo_Class[] localClasses() nothrow pure + @property TypeInfo_Class[] localClasses() nothrow pure @nogc { if (flags & MIlocalClasses) { @@ -1597,7 +1584,7 @@ const: return null; } - @property string name() nothrow pure + @property string name() nothrow pure @nogc { if (true || flags & MIname) // always available for now { @@ -1715,7 +1702,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; @@ -3241,6 +3228,302 @@ 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)) +{ + if (lhs is rhs) + return 0; + // Regard null references as always being "less than" + if (!lhs) + return -1; + if (!rhs) + return 1; + return lhs.opCmp(rhs); +} + +int __cmp(T)(const T[] lhs, const T[] rhs) @trusted +if (__traits(isScalar, T)) +{ + // 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; + foreach (const u; 0 .. len) + { + 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 < b.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; + } + 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; + 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]; } + + // All unsigned byte-wide types = > dstrcmp + immutable len = s1.length <= s2.length ? s1.length : s2.length; + + foreach (const u; 0 .. len) + { + 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 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); +} + +// integral types +@safe unittest +{ + void compareMinMax(T)() + { + T[2] a = [T.max, T.max]; + T[2] b = [T.min, T.min]; + + assert(__cmp(a, b) > 0); + assert(__cmp(b, a) < 0); + } + + compareMinMax!int; + compareMinMax!uint; + compareMinMax!long; + compareMinMax!ulong; + compareMinMax!short; + compareMinMax!ushort; + compareMinMax!byte; + compareMinMax!dchar; + compareMinMax!wchar; +} + +// char types (dstrcmp) +@safe unittest +{ + void compareMinMax(T)() + { + T[2] a = [T.max, T.max]; + T[2] b = [T.min, T.min]; + + assert(__cmp(a, b) > 0); + assert(__cmp(b, a) < 0); + } + + compareMinMax!ubyte; + compareMinMax!bool; + compareMinMax!char; + compareMinMax!(const char); + + string s1 = "aaaa"; + string s2 = "bbbb"; + assert(__cmp(s2, s1) > 0); + assert(__cmp(s1, s2) < 0); +} + +// fp types +@safe unittest +{ + void compareMinMax(T)() + { + T[2] a = [T.max, T.max]; + T[2] b = [T.min_normal, T.min_normal]; + + assert(__cmp(a, b) > 0); + assert(__cmp(b, a) < 0); + } + + 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); +} + +// objects +@safe unittest +{ + class C + { + int i; + this(int i) { this.i = i; } + + override int opCmp(Object c) const @safe + { + return i - (cast(C)c).i; + } + } + + 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([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 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/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/dmain2.d b/src/rt/dmain2.d index 6aacc153a9..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(); @@ -492,7 +496,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 +525,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 +613,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); } 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; diff --git a/src/rt/lifetime.d b/src/rt/lifetime.d index 87f0e8dab8..fb6e07474f 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); } /** @@ -1548,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); @@ -1565,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); @@ -1908,7 +1936,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) diff --git a/src/rt/minfo.d b/src/rt/minfo.d index 5757c7673d..8e49a99c45 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; } @@ -182,8 +182,7 @@ struct ModuleGroup ignore } - // Change default to .abort in 2.074 - auto onCycle = OnCycle.deprecate; + auto onCycle = OnCycle.abort; switch(cycleHandling) with(OnCycle) { diff --git a/src/rt/minit.asm b/src/rt/minit.asm index 72bd5d868c..64a307fdf2 100644 --- a/src/rt/minit.asm +++ b/src/rt/minit.asm @@ -10,7 +10,10 @@ ; (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 ifdef _WIN32 DATAGRP EQU FLAT @@ -61,7 +64,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 'CODE' +__DPbegin: +DPB ends +DP segment dword use32 public 'CODE' +DP ends +DPE segment dword use32 public 'CODE' +__DPend: +DPE ends + +CGROUP group DPB,DP,DPE + +; These segments bracket TP, which contains the TLS pointer references + public __TPbegin, __TPend +TPB segment dword use32 public 'CODE' +__TPbegin: +TPB ends +TP segment dword use32 public 'CODE' +TP ends +TPE segment dword use32 public 'CODE' +__TPend: +TPE ends + +CGROUP 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 +100,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 +108,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 67225d9b94..9aaa62d036 100644 Binary files a/src/rt/minit.obj and b/src/rt/minit.obj differ 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/sections.d b/src/rt/sections.d index 4e32a77663..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) @@ -56,17 +58,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..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"); @@ -66,22 +73,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[]; } @@ -114,22 +121,24 @@ __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. */ -void initSections() +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; } /*** * Gets called on program shutdown just after GC is terminated. */ -void finiSections() +void finiSections() nothrow @nogc { _isRuntimeInitialized = false; } @@ -141,12 +150,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 +170,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 +187,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 +206,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 +219,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 +240,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(); } @@ -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) { @@ -277,7 +287,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 +481,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 +556,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 +581,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 +599,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 +608,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 +624,7 @@ nothrow: return map; } - DSO* dsoForHandle(void* handle) + DSO* dsoForHandle(void* handle) nothrow @nogc { DSO* pdso; !pthread_mutex_lock(&_handleToDSOMutex) || assert(0); @@ -624,7 +634,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 +642,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 +650,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; @@ -663,6 +673,8 @@ nothrow: 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; @@ -686,7 +698,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 +714,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]) { @@ -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,15 +822,16 @@ 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(); } -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 +845,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(); @@ -837,6 +867,8 @@ const(void)[] getCopyRelocSection() nothrow 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); @@ -857,7 +889,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 +933,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 +958,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 +988,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..1343c94985 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,41 +49,73 @@ struct SectionGroup private: ModuleGroup _moduleGroup; - void[][2] _gcRanges; + version(conservative) + void[][2] _gcRanges; + else + void[][] _gcRanges; } -void initSections() +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() +void finiSections() nothrow @nogc { + import core.stdc.stdlib : free; + + version(conservative) {} else + free(_sections._gcRanges.ptr); } -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 { } 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: @@ -90,9 +124,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) @@ -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 diff --git a/src/rt/sections_win64.d b/src/rt/sections_win64.d index 8606581373..0dbeb48599 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) @@ -31,12 +33,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,45 +51,74 @@ struct SectionGroup return pbeg[0 .. pend - pbeg]; } - @property inout(void[])[] gcRanges() inout + @property inout(void[])[] gcRanges() inout nothrow @nogc { return _gcRanges[]; } private: ModuleGroup _moduleGroup; - void[][1] _gcRanges; + version(conservative) + void[][1] _gcRanges; + else + void[][] _gcRanges; } -void initSections() +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() +void finiSections() nothrow @nogc { .free(cast(void*)_sections.modules.ptr); + version(conservative) {} else + .free(_sections._gcRanges.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 { } 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: @@ -99,7 +130,7 @@ extern(C) extern __gshared void* _minfo_end; } -immutable(ModuleInfo*)[] getModuleInfos() +immutable(ModuleInfo*)[] getModuleInfos() nothrow @nogc out (result) { foreach(m; result) @@ -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 @@ -197,14 +233,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); 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; 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); - } -} 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; +} 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..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(scope 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: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) 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(); +} diff --git a/win32.mak b/win32.mak index f4ee566ed2..bf3bee7168 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= @@ -473,6 +473,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 89f28a4941..a025b06f06 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 @@ -484,6 +484,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 $** $@