Skip to content
This repository has been archived by the owner on Oct 12, 2022. It is now read-only.

Commit

Permalink
Fix issue 14870 - Add new "abort" internal module and function, which…
Browse files Browse the repository at this point in the history
… will always print a

message to stderr, even in release mode. This can be used to replace
assert(0, msg) which does not print the message.
  • Loading branch information
schveiguy committed Aug 10, 2015
1 parent dbd72a2 commit 3f9c4a6
Show file tree
Hide file tree
Showing 9 changed files with 254 additions and 121 deletions.
1 change: 1 addition & 0 deletions mak/COPY
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ COPY=\
$(IMPDIR)\core\time.d \
$(IMPDIR)\core\vararg.d \
\
$(IMPDIR)\core\internal\abort.d \
$(IMPDIR)\core\internal\convert.d \
$(IMPDIR)\core\internal\hash.d \
$(IMPDIR)\core\internal\string.d \
Expand Down
1 change: 1 addition & 0 deletions mak/MANIFEST
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ MANIFEST=\
src\core\time.d \
src\core\vararg.d \
\
src\core\internal\abort.d \
src\core\internal\convert.d \
src\core\internal\hash.d \
src\core\internal\string.d \
Expand Down
1 change: 1 addition & 0 deletions mak/SRCS
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ SRCS=\
src\core\time.d \
src\core\vararg.d \
\
src\core\internal\abort.d \
src\core\internal\convert.d \
src\core\internal\hash.d \
src\core\internal\string.d \
Expand Down
45 changes: 45 additions & 0 deletions src/core/internal/abort.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
module core.internal.abort;

/*
* Use instead of assert(0, msg), since this does not print a message for -release compiled
* code, and druntime is -release compiled.
*/
void abort(string msg, string filename = __FILE__, size_t line = __LINE__) @nogc nothrow @safe
{
import core.stdc.stdlib: c_abort = abort;
// use available OS system calls to print the message to stderr
version(Posix)
{
import core.sys.posix.unistd: write;
static void writeStr(const(char)[][] m...) @nogc nothrow @trusted
{
foreach(s; m)
write(2, s.ptr, s.length);
}
}
else version(Windows)
{
import core.sys.windows.windows: GetStdHandle, STD_ERROR_HANDLE, WriteFile, INVALID_HANDLE_VALUE;
auto h = (() @trusted => GetStdHandle(STD_ERROR_HANDLE))();
if(h == INVALID_HANDLE_VALUE)
// attempt best we can to print the message
assert(0, msg);
void writeStr(const(char)[][] m...) @nogc nothrow @trusted
{
foreach(s; m)
{
assert(s.length <= uint.max);
WriteFile(h, s.ptr, cast(uint)s.length, null, null);
}
}
}
else
static assert(0, "Unsupported OS");

import core.internal.string;
UnsignedStringBuf strbuff;

// write an appropriate message, then abort the program
writeStr("Aborting from ", filename, "(", line.unsignedToTempString(strbuff, 10), ") ", msg);
c_abort();
}
92 changes: 92 additions & 0 deletions src/core/internal/string.d
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,25 @@ char[] unsignedToTempString(ulong value, char[] buf, uint radix) @safe
return buf[i .. $];
}

private struct TempStringNoAlloc
{
// need to handle 65 bytes for radix of 2 with negative sign.
private char[65] _buf;
private ubyte _len;
auto get() return
{
return _buf[$-_len..$];
}
alias get this;
}

auto unsignedToTempString(ulong value, uint radix) @safe
{
TempStringNoAlloc result;
result._len = unsignedToTempString(value, result._buf, radix).length & 0xff;
return result;
}

unittest
{
UnsignedStringBuf buf;
Expand All @@ -37,8 +56,81 @@ unittest
assert(long.sizeof.unsignedToTempString(buf, 10) == "8");
assert(uint.max.unsignedToTempString(buf, 10) == "4294967295");
assert(ulong.max.unsignedToTempString(buf, 10) == "18446744073709551615");

// use stack allocated struct version
assert(0.unsignedToTempString(10) == "0");
assert(1.unsignedToTempString(10) == "1");
assert(12.unsignedToTempString(10) == "12");
assert(0x12ABCF .unsignedToTempString(16) == "12abcf");
assert(long.sizeof.unsignedToTempString(10) == "8");
assert(uint.max.unsignedToTempString(10) == "4294967295");
assert(ulong.max.unsignedToTempString(10) == "18446744073709551615");
}

alias SignedStringBuf = char[20];

auto signedToTempString(long value, char[] buf, uint radix) @safe
{
bool neg = value < 0;
if(neg)
value = cast(ulong)-value;
auto r = unsignedToTempString(value, buf, radix);
if(neg)
{
// about to do a slice without a bounds check
assert(r.ptr > buf.ptr);
r = (() @trusted => r.ptr[-1..r.length])();
r[0] = '-';
}
return r;
}

auto signedToTempString(long value, uint radix) @safe
{
bool neg = value < 0;
if(neg)
value = cast(ulong)-value;
auto r = unsignedToTempString(value, radix);
if(neg)
{
r._len++;
r.get()[0] = '-';
}
return r;
}

unittest
{
SignedStringBuf buf;
assert(0.signedToTempString(buf, 10) == "0");
assert(1.signedToTempString(buf, 10) == "1");
assert((-1).signedToTempString(buf, 10) == "-1");
assert(12.signedToTempString(buf, 10) == "12");
assert((-12).signedToTempString(buf, 10) == "-12");
assert(0x12ABCF .signedToTempString(buf, 16) == "12abcf");
assert((-0x12ABCF) .signedToTempString(buf, 16) == "-12abcf");
assert(long.sizeof.signedToTempString(buf, 10) == "8");
assert(int.max.signedToTempString(buf, 10) == "2147483647");
assert(int.min.signedToTempString(buf, 10) == "-2147483648");
assert(long.max.signedToTempString(buf, 10) == "9223372036854775807");
assert(long.min.signedToTempString(buf, 10) == "-9223372036854775808");

// use stack allocated struct version
assert(0.signedToTempString(10) == "0");
assert(1.signedToTempString(10) == "1");
assert((-1).signedToTempString(10) == "-1");
assert(12.signedToTempString(10) == "12");
assert((-12).signedToTempString(10) == "-12");
assert(0x12ABCF .signedToTempString(16) == "12abcf");
assert((-0x12ABCF) .signedToTempString(16) == "-12abcf");
assert(long.sizeof.signedToTempString(10) == "8");
assert(int.max.signedToTempString(10) == "2147483647");
assert(int.min.signedToTempString(10) == "-2147483648");
assert(long.max.signedToTempString(10) == "9223372036854775807");
assert(long.min.signedToTempString(10) == "-9223372036854775808");
assert(long.max.signedToTempString(2) == "111111111111111111111111111111111111111111111111111111111111111");
assert(long.min.signedToTempString(2) == "-1000000000000000000000000000000000000000000000000000000000000000");
}

int dstrcmp( in char[] s1, in char[] s2 ) @trusted
{
Expand Down
2 changes: 1 addition & 1 deletion src/core/stdc/stdlib.d
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ void* realloc(void* ptr, size_t size);
void free(void* ptr);

///
void abort();
void abort() @safe;
///
void exit(int status);
///
Expand Down
Loading

0 comments on commit 3f9c4a6

Please sign in to comment.