diff --git a/lphobos/build.sh b/lphobos/build.sh
index 71ace88b..57276a25 100755
--- a/lphobos/build.sh
+++ b/lphobos/build.sh
@@ -5,8 +5,8 @@ mkdir -p obj
rm -f obj/*.bc
rm -f ../lib/*.bc
-LLVMDCFLAGS="-c -odobj -oq -gc -noasm"
-LLVMDCFLAGS_ASM="-c -odobj -oq -gc"
+LLVMDCFLAGS_ASM="-c -oq -release"
+LLVMDCFLAGS="$LLVMDCFLAGS_ASM -noasm"
echo "compiling contract runtime"
llvmdc internal/contract.d -c -of../lib/llvmdcore.bc || exit 1 #-noruntime || exit 1
@@ -16,8 +16,10 @@ echo "compiling common runtime"
internal/mem.d \
internal/critical.d \
internal/dmain2.d \
+ internal/inv.d \
$LLVMDCFLAGS_ASM || exit 1
mv *.bc obj
+llvm-link -f -o=../lib/llvmdcore.bc obj/internal.*.bc ../lib/llvmdcore.bc
echo "compiling typeinfo 1"
./llvmdc-build typeinfos1.d $LLVMDCFLAGS || exit 1
@@ -47,24 +49,26 @@ mv *.bc obj
llvm-link -f -o=../lib/llvmdcore.bc obj/aApply.bc obj/aApplyR.bc obj/switch.bc ../lib/llvmdcore.bc || exit 1
echo "compiling array runtime support"
-llvmdc internal/qsort2.d $LLVMDCFLAGS || exit 1
+llvmdc internal/qsort2.d internal/adi.d internal/aaA.d $LLVMDCFLAGS || exit 1
mv *.bc obj
-llvm-link -f -o=../lib/llvmdcore.bc obj/qsort2.bc ../lib/llvmdcore.bc || exit 1
-llvmdc internal/adi.d $LLVMDCFLAGS || exit 1
-mv *.bc obj
-llvm-link -f -o=../lib/llvmdcore.bc obj/adi.bc ../lib/llvmdcore.bc || exit 1
-llvmdc internal/aaA.d $LLVMDCFLAGS || exit 1
-mv *.bc obj
-llvm-link -f -o=../lib/llvmdcore.bc obj/aaA.bc ../lib/llvmdcore.bc || exit 1
+llvm-link -f -o=../lib/llvmdcore.bc obj/qsort2.bc obj/adi.bc obj/aaA.bc ../lib/llvmdcore.bc || exit 1
echo "compiling object implementation"
-llvmdc internal/objectimpl.d -c -odobj -g || exit 1
+llvmdc internal/objectimpl.d $LLVMDCFLAGS || exit 1
+mv object.bc objectimpl.bc
+mv *.bc obj
llvm-link -f -o=../lib/llvmdcore.bc obj/objectimpl.bc ../lib/llvmdcore.bc || exit 1
-echo "compiling llvm runtime support"
-./llvmdc-build llvmsupport.d $LLVMDCFLAGS || exit 1
+echo "compiling crc32"
+llvmdc crc32.d $LLVMDCFLAGS || exit 1
mv *.bc obj
-llvm-link -f -o=../lib/llvmdcore.bc `ls obj/llvm.*.bc` ../lib/llvmdcore.bc || exit 1
+llvm-link -f -o=../lib/llvmdcore.bc ../lib/llvmdcore.bc obj/crc32.bc || exit 1
+
+echo "compiling llvm runtime support"
+# ./llvmdc-build llvmsupport.d $LLVMDCFLAGS || exit 1
+llvmdc llvmsupport.d -oq -c || exit 1
+mv *.bc obj
+llvm-link -f -o=../lib/llvmdcore.bc `ls obj/llvm*.bc` ../lib/llvmdcore.bc || exit 1
echo "compiling garbage collector"
cd gc
@@ -72,17 +76,22 @@ llvmdc $(ls *.d |grep -v win32) $LLVMDCFLAGS_ASM -I.. ||exit 1
# llvmdc gclinux.d $LLVMDCFLAGS -I.. || exit 1
# llvmdc gcx.d $LLVMDCFLAGS -I.. || exit 1
# llvmdc gcbits.d $LLVMDCFLAGS -I.. || exit 1
-# llvmdc gc.d $LLVMDCFLAGS -I.. || exit 1
-mv std.gc.bc gc.bc
+# llvmdc gc.d -oq -c -I.. || exit 1
+mv std.gc.bc std_gc.bc
mv *.bc ../obj
+# mv -v obj/*.bc ../obj
cd ..
-llvm-link -f -o=../lib/llvmdcore.bc obj/gclinux.bc obj/gcx.bc obj/gcbits.bc obj/gc.bc ../lib/llvmdcore.bc || exit 1
+llvm-link -f -o=../lib/llvmdcore.bc obj/gclinux.bc obj/gcx.bc obj/gcbits.bc obj/std_gc.bc ../lib/llvmdcore.bc || exit 1
echo "compiling phobos"
./llvmdc-build phobos.d $LLVMDCFLAGS || exit 1
mv *.bc obj
echo "linking phobos"
-llvm-link -f -o=../lib/llvmdcore.bc `ls obj/std.*.bc` ../lib/llvmdcore.bc || exit 1
+# llvm-link -f -o=../lib/llvmdcore.bc `ls obj/std.*.bc` ../lib/llvmdcore.bc || exit 1
+for i in $(ls obj/std.*.bc); do
+ echo $i
+ llvm-link -f -o=../lib/llvmdcore.bc ../lib/llvmdcore.bc $i || exit 1
+done
echo "Compiling auxiliary"
./llvmdc-build etc/c/zlib.d $LLVMDCFLAGS || exit 1
@@ -90,7 +99,6 @@ mv *.bc obj
llvm-link -f -o=../lib/llvmdcore.bc `ls obj/etc.*.bc` ../lib/llvmdcore.bc || exit 1
echo "optimizing"
-opt -stats -p -f -std-compile-opts -disable-inlining -o=../lib/llvmdcore.bc ../lib/llvmdcore.bc || exit 1
-
+opt -stats -p -f -std-compile-opts -o=../lib/llvmdcore.bc ../lib/llvmdcore.bc || exit 1
echo "SUCCESS"
diff --git a/lphobos/gc/gc.d b/lphobos/gc/gc.d
index 907b8329..4d750ff4 100644
--- a/lphobos/gc/gc.d
+++ b/lphobos/gc/gc.d
@@ -276,6 +276,10 @@ Loverflow:
_d_OutOfMemory();
}
+void* _d_newarrayvT(TypeInfo ti, size_t length) {
+ return _d_newarrayT(ti, length);
+}
+
/* For when the array has a non-zero initializer.
*/
void* _d_newarrayiT(TypeInfo ti, size_t length)
@@ -1025,4 +1029,6 @@ void* _d_arrayliteralT(TypeInfo ti, size_t length, ...)
void* ptr;
}*/
-extern(C) void* _d_allocmemoryT(size_t foo) { return malloc(foo).ptr; }
+extern(C) void* _d_allocmemoryT(TypeInfo ti) {
+ return malloc(ti.tsize).ptr; // Tit size :)
+}
diff --git a/lphobos/internal/adi.d b/lphobos/internal/adi.d
index 59670033..617ac6fe 100644
--- a/lphobos/internal/adi.d
+++ b/lphobos/internal/adi.d
@@ -1,838 +1,838 @@
-//_ adi.d
-
-/**
- * Part of the D programming language runtime library.
- * Dynamic array property support routines
- */
-
-/*
- * Copyright (C) 2000-2006 by Digital Mars, www.digitalmars.com
- * Written by Walter Bright
- *
- * This software is provided 'as-is', without any express or implied
- * warranty. In no event will the authors be held liable for any damages
- * arising from the use of this software.
- *
- * Permission is granted to anyone to use this software for any purpose,
- * including commercial applications, and to alter it and redistribute it
- * freely, in both source and binary form, subject to the following
- * restrictions:
- *
- * o The origin of this software must not be misrepresented; you must not
- * claim that you wrote the original software. If you use this software
- * in a product, an acknowledgment in the product documentation would be
- * appreciated but is not required.
- * o Altered source versions must be plainly marked as such, and must not
- * be misrepresented as being the original software.
- * o This notice may not be removed or altered from any source
- * distribution.
- */
-
-//debug=adi; // uncomment to turn on debugging printf's
-
-//import std.stdio;
-import std.c.stdio;
-import std.c.stdlib;
-import std.c.string;
-//import std.string;
-import std.outofmemory;
-import std.utf;
-
-pragma(no_typeinfo)
-struct Array
-{
- size_t length;
- void* ptr;
-}
-
-/**********************************************
- * Reverse array of chars.
- * Handled separately because embedded multibyte encodings should not be
- * reversed.
- */
-
-extern (C) char[] _adReverseChar(char[] a)
-{
- if (a.length > 1)
- {
- char[6] tmp;
- char[6] tmplo;
- char* lo = a.ptr;
- char* hi = &a[length - 1];
-
- while (lo < hi)
- { auto clo = *lo;
- auto chi = *hi;
-
- //printf("lo = %d, hi = %d\n", lo, hi);
- if (clo <= 0x7F && chi <= 0x7F)
- {
- //printf("\tascii\n");
- *lo = chi;
- *hi = clo;
- lo++;
- hi--;
- continue;
- }
-
- uint stridelo = std.utf.UTF8stride[clo];
-
- uint stridehi = 1;
- while ((chi & 0xC0) == 0x80)
- {
- chi = *--hi;
- stridehi++;
- assert(hi >= lo);
- }
- if (lo == hi)
- break;
-
- //printf("\tstridelo = %d, stridehi = %d\n", stridelo, stridehi);
- if (stridelo == stridehi)
- {
-
- memcpy(tmp.ptr, lo, stridelo);
- memcpy(lo, hi, stridelo);
- memcpy(hi, tmp.ptr, stridelo);
- lo += stridelo;
- hi--;
- continue;
- }
-
- /* Shift the whole array. This is woefully inefficient
- */
- memcpy(tmp.ptr, hi, stridehi);
- memcpy(tmplo.ptr, lo, stridelo);
- memmove(lo + stridehi, lo + stridelo , (hi - lo) - stridelo);
- memcpy(lo, tmp.ptr, stridehi);
- memcpy(hi + stridehi - stridelo, tmplo.ptr, stridelo);
-
- lo += stridehi;
- hi = hi - 1 + (stridehi - stridelo);
- }
- }
- return a;
-}
-
-unittest
-{
- string a = "abcd";
- string r;
-
- r = a.dup.reverse;
- //writefln(r);
- assert(r == "dcba");
-
- a = "a\u1235\u1234c";
- //writefln(a);
- r = a.dup.reverse;
- //writefln(r);
- assert(r == "c\u1234\u1235a");
-
- a = "ab\u1234c";
- //writefln(a);
- r = a.dup.reverse;
- //writefln(r);
- assert(r == "c\u1234ba");
-
- a = "\u3026\u2021\u3061\n";
- r = a.dup.reverse;
- assert(r == "\n\u3061\u2021\u3026");
-}
-
-
-/**********************************************
- * Reverse array of wchars.
- * Handled separately because embedded multiword encodings should not be
- * reversed.
- */
-
-extern (C) wchar[] _adReverseWchar(wchar[] a)
-{
- if (a.length > 1)
- {
- wchar[2] tmp;
- wchar* lo = a.ptr;
- wchar* hi = &a[length - 1];
-
- while (lo < hi)
- { auto clo = *lo;
- auto chi = *hi;
-
- if ((clo < 0xD800 || clo > 0xDFFF) &&
- (chi < 0xD800 || chi > 0xDFFF))
- {
- *lo = chi;
- *hi = clo;
- lo++;
- hi--;
- continue;
- }
-
- int stridelo = 1 + (clo >= 0xD800 && clo <= 0xDBFF);
-
- int stridehi = 1;
- if (chi >= 0xDC00 && chi <= 0xDFFF)
- {
- chi = *--hi;
- stridehi++;
- assert(hi >= lo);
- }
- if (lo == hi)
- break;
-
- if (stridelo == stridehi)
- { int stmp;
-
- assert(stridelo == 2);
- assert(stmp.sizeof == 2 * (*lo).sizeof);
- stmp = *cast(int*)lo;
- *cast(int*)lo = *cast(int*)hi;
- *cast(int*)hi = stmp;
- lo += stridelo;
- hi--;
- continue;
- }
-
- /* Shift the whole array. This is woefully inefficient
- */
- memcpy(tmp.ptr, hi, stridehi * wchar.sizeof);
- memcpy(hi + stridehi - stridelo, lo, stridelo * wchar.sizeof);
- memmove(lo + stridehi, lo + stridelo , (hi - (lo + stridelo)) * wchar.sizeof);
- memcpy(lo, tmp.ptr, stridehi * wchar.sizeof);
-
- lo += stridehi;
- hi = hi - 1 + (stridehi - stridelo);
- }
- }
- return a;
-}
-
-unittest
-{
- wstring a = "abcd";
- wstring r;
-
- r = a.dup.reverse;
- assert(r == "dcba");
-
- a = "a\U00012356\U00012346c";
- r = a.dup.reverse;
- assert(r == "c\U00012346\U00012356a");
-
- a = "ab\U00012345c";
- r = a.dup.reverse;
- assert(r == "c\U00012345ba");
-}
-
-
-/**********************************************
- * Support for array.reverse property.
- */
-
-extern (C) Array _adReverse(Array a, size_t szelem)
-{
- if (a.length >= 2)
- {
- byte* tmp;
- byte[16] buffer;
-
- void* lo = a.ptr;
- void* hi = a.ptr + (a.length - 1) * szelem;
-
- tmp = buffer.ptr;
- if (szelem > 16)
- {
- //version (Win32)
- tmp = cast(byte*) alloca(szelem);
- //else
- //tmp = new byte[szelem];
- }
-
- for (; lo < hi; lo += szelem, hi -= szelem)
- {
- memcpy(tmp, lo, szelem);
- memcpy(lo, hi, szelem);
- memcpy(hi, tmp, szelem);
- }
-
- version (Win32)
- {
- }
- else
- {
- //if (szelem > 16)
- // BUG: bad code is generate for delete pointer, tries
- // to call delclass.
- //delete tmp;
- }
- }
- return a;
-}
-
-unittest
-{
- debug(adi) printf("array.reverse.unittest\n");
-
- int[] a = new int[5];
- int[] b;
- size_t i;
-
- for (i = 0; i < 5; i++)
- a[i] = i;
- b = a.reverse;
- assert(b is a);
- for (i = 0; i < 5; i++)
- assert(a[i] == 4 - i);
-
- struct X20
- { // More than 16 bytes in size
- int a;
- int b, c, d, e;
- }
-
- X20[] c = new X20[5];
- X20[] d;
-
- for (i = 0; i < 5; i++)
- { c[i].a = i;
- c[i].e = 10;
- }
- d = c.reverse;
- assert(d is c);
- for (i = 0; i < 5; i++)
- {
- assert(c[i].a == 4 - i);
- assert(c[i].e == 10);
- }
-}
-
-/**********************************************
- * Support for array.reverse property for bit[].
- */
-
-version (none)
-{
-extern (C) bit[] _adReverseBit(bit[] a)
- out (result)
- {
- assert(result is a);
- }
- body
- {
- if (a.length >= 2)
- {
- bit t;
- int lo, hi;
-
- lo = 0;
- hi = a.length - 1;
- for (; lo < hi; lo++, hi--)
- {
- t = a[lo];
- a[lo] = a[hi];
- a[hi] = t;
- }
- }
- return a;
- }
-
-unittest
-{
- debug(adi) printf("array.reverse_Bit[].unittest\n");
-
- bit[] b;
- b = new bit[5];
- static bit[5] data = [1,0,1,1,0];
- int i;
-
- b[] = data[];
- b.reverse;
- for (i = 0; i < 5; i++)
- {
- assert(b[i] == data[4 - i]);
- }
-}
-}
-
-/**********************************************
- * Sort array of chars.
- */
-
-extern (C) char[] _adSortChar(char[] a)
-{
- if (a.length > 1)
- {
- dstring da = toUTF32(a);
- da.sort;
- size_t i = 0;
- foreach (dchar d; da)
- { char[4] buf;
- string t = toUTF8(buf, d);
- a[i .. i + t.length] = t[];
- i += t.length;
- }
- delete da;
- }
- return a;
-}
-
-/**********************************************
- * Sort array of wchars.
- */
-
-extern (C) wchar[] _adSortWchar(wchar[] a)
-{
- if (a.length > 1)
- {
- dstring da = toUTF32(a);
- da.sort;
- size_t i = 0;
- foreach (dchar d; da)
- { wchar[2] buf;
- wstring t = toUTF16(buf, d);
- a[i .. i + t.length] = t[];
- i += t.length;
- }
- delete da;
- }
- return a;
-}
-
-/**********************************************
- * Support for array.sort property for bit[].
- */
-
-version (none)
-{
-extern (C) bit[] _adSortBit(bit[] a)
- out (result)
- {
- assert(result is a);
- }
- body
- {
- if (a.length >= 2)
- {
- size_t lo, hi;
-
- lo = 0;
- hi = a.length - 1;
- while (1)
- {
- while (1)
- {
- if (lo >= hi)
- goto Ldone;
- if (a[lo] == true)
- break;
- lo++;
- }
-
- while (1)
- {
- if (lo >= hi)
- goto Ldone;
- if (a[hi] == false)
- break;
- hi--;
- }
-
- a[lo] = false;
- a[hi] = true;
-
- lo++;
- hi--;
- }
- Ldone:
- ;
- }
- return a;
- }
-
-unittest
-{
- debug(adi) printf("array.sort_Bit[].unittest\n");
-}
-}
-
-/***************************************
- * Support for array equality test.
- */
-
-extern (C) int _adEq(Array a1, Array a2, TypeInfo ti)
-{
- // printf("_adEq(a1.length = %d, a2.length = %d)\n", a1.length, a2.length);
- if (a1.length != a2.length)
- return 0; // not equal
- auto sz = ti.next.tsize();
- auto p1 = a1.ptr;
- auto p2 = a2.ptr;
-
-/+
- for (int i = 0; i < a1.length; i++)
- {
- printf("%4x %4x\n", (cast(short*)p1)[i], (cast(short*)p2)[i]);
- }
- printf("sz = %u\n", sz);
-+/
-
- if (sz == 1)
- // We should really have a ti.isPOD() check for this
- return (memcmp(p1, p2, a1.length) == 0);
-
- for (size_t i = 0; i < a1.length; i++)
- {
- if (!ti.next.equals(p1 + i * sz, p2 + i * sz))
- return 0; // not equal
- }
- return 1; // equal
-}
-
-unittest
-{
- debug(adi) printf("array.Eq unittest\n");
-
- string a = "hello";
-
- assert(a != "hel");
- assert(a != "helloo");
- assert(a != "betty");
- assert(a == "hello");
- assert(a != "hxxxx");
-}
-
-/***************************************
- * Support for bit array equality test for bit arrays.
- */
-
-version (none)
-{
-extern (C) int _adEqBit(Array a1, Array a2)
-{ size_t i;
-
- if (a1.length != a2.length)
- return 0; // not equal
- auto p1 = cast(byte*)a1.ptr;
- auto p2 = cast(byte*)a2.ptr;
- auto n = a1.length / 8;
- for (i = 0; i < n; i++)
- {
- if (p1[i] != p2[i])
- return 0; // not equal
- }
-
- ubyte mask;
-
- n = a1.length & 7;
- mask = cast(ubyte)((1 << n) - 1);
- //printf("i = %d, n = %d, mask = %x, %x, %x\n", i, n, mask, p1[i], p2[i]);
- return (mask == 0) || (p1[i] & mask) == (p2[i] & mask);
-}
-
-unittest
-{
- debug(adi) printf("array.EqBit unittest\n");
-
- static bit[] a = [1,0,1,0,1];
- static bit[] b = [1,0,1];
- static bit[] c = [1,0,1,0,1,0,1];
- static bit[] d = [1,0,1,1,1];
- static bit[] e = [1,0,1,0,1];
-
- assert(a != b);
- assert(a != c);
- assert(a != d);
- assert(a == e);
-}
-}
-
-/***************************************
- * Support for array compare test.
- */
-
-extern (C) int _adCmp(Array a1, Array a2, TypeInfo ti)
-{
- //printf("adCmp()\n");
- auto len = a1.length;
- if (a2.length < len)
- len = a2.length;
- auto sz = ti.tsize();
- void *p1 = a1.ptr;
- void *p2 = a2.ptr;
-
- if (sz == 1)
- { // We should really have a ti.isPOD() check for this
- auto c = memcmp(p1, p2, len);
- if (c)
- return c;
- }
- else
- {
- for (size_t i = 0; i < len; i++)
- {
- auto c = ti.compare(p1 + i * sz, p2 + i * sz);
- if (c)
- return c;
- }
- }
- if (a1.length == a2.length)
- return 0;
- return (a1.length > a2.length) ? 1 : -1;
-}
-
-unittest
-{
- debug(adi) printf("array.Cmp unittest\n");
-
- string a = "hello";
-
- assert(a > "hel");
- assert(a >= "hel");
- assert(a < "helloo");
- assert(a <= "helloo");
- assert(a > "betty");
- assert(a >= "betty");
- assert(a == "hello");
- assert(a <= "hello");
- assert(a >= "hello");
-}
-
-/***************************************
- * Support for char array compare test.
- */
-
-extern (C) int _adCmpChar(Array a1, Array a2)
-{
-version (D_InlineAsm_X86)
-{
- asm
- { naked ;
-
- push EDI ;
- push ESI ;
-
- mov ESI,a1+4[4+ESP] ;
- mov EDI,a2+4[4+ESP] ;
-
- mov ECX,a1[4+ESP] ;
- mov EDX,a2[4+ESP] ;
-
- cmp ECX,EDX ;
- jb GotLength ;
-
- mov ECX,EDX ;
-
-GotLength:
- cmp ECX,4 ;
- jb DoBytes ;
-
- // Do alignment if neither is dword aligned
- test ESI,3 ;
- jz Aligned ;
-
- test EDI,3 ;
- jz Aligned ;
-DoAlign:
- mov AL,[ESI] ; //align ESI to dword bounds
- mov DL,[EDI] ;
-
- cmp AL,DL ;
- jnz Unequal ;
-
- inc ESI ;
- inc EDI ;
-
- test ESI,3 ;
-
- lea ECX,[ECX-1] ;
- jnz DoAlign ;
-Aligned:
- mov EAX,ECX ;
-
- // do multiple of 4 bytes at a time
-
- shr ECX,2 ;
- jz TryOdd ;
-
- repe ;
- cmpsd ;
-
- jnz UnequalQuad ;
-
-TryOdd:
- mov ECX,EAX ;
-DoBytes:
- // if still equal and not end of string, do up to 3 bytes slightly
- // slower.
-
- and ECX,3 ;
- jz Equal ;
-
- repe ;
- cmpsb ;
-
- jnz Unequal ;
-Equal:
- mov EAX,a1[4+ESP] ;
- mov EDX,a2[4+ESP] ;
-
- sub EAX,EDX ;
- pop ESI ;
-
- pop EDI ;
- ret ;
-
-UnequalQuad:
- mov EDX,[EDI-4] ;
- mov EAX,[ESI-4] ;
-
- cmp AL,DL ;
- jnz Unequal ;
-
- cmp AH,DH ;
- jnz Unequal ;
-
- shr EAX,16 ;
-
- shr EDX,16 ;
-
- cmp AL,DL ;
- jnz Unequal ;
-
- cmp AH,DH ;
-Unequal:
- sbb EAX,EAX ;
- pop ESI ;
-
- or EAX,1 ;
- pop EDI ;
-
- ret ;
- }
-}
-else
-{
- int len;
- int c;
-
- //printf("adCmpChar()\n");
- len = a1.length;
- if (a2.length < len)
- len = a2.length;
- c = memcmp(cast(char *)a1.ptr, cast(char *)a2.ptr, len);
- if (!c)
- c = cast(int)a1.length - cast(int)a2.length;
- return c;
-}
-}
-
-unittest
-{
- debug(adi) printf("array.CmpChar unittest\n");
-
- string a = "hello";
-
- assert(a > "hel");
- assert(a >= "hel");
- assert(a < "helloo");
- assert(a <= "helloo");
- assert(a > "betty");
- assert(a >= "betty");
- assert(a == "hello");
- assert(a <= "hello");
- assert(a >= "hello");
-}
-
-/***************************************
- * Support for bit array compare test.
- */
-
-version (none)
-{
-extern (C) int _adCmpBit(Array a1, Array a2)
-{
- int len;
- uint i;
-
- len = a1.length;
- if (a2.length < len)
- len = a2.length;
- ubyte *p1 = cast(ubyte*)a1.ptr;
- ubyte *p2 = cast(ubyte*)a2.ptr;
- uint n = len / 8;
- for (i = 0; i < n; i++)
- {
- if (p1[i] != p2[i])
- break; // not equal
- }
- for (uint j = i * 8; j < len; j++)
- { ubyte mask = cast(ubyte)(1 << j);
- int c;
-
- c = cast(int)(p1[i] & mask) - cast(int)(p2[i] & mask);
- if (c)
- return c;
- }
- return cast(int)a1.length - cast(int)a2.length;
-}
-
-unittest
-{
- debug(adi) printf("array.CmpBit unittest\n");
-
- static bit[] a = [1,0,1,0,1];
- static bit[] b = [1,0,1];
- static bit[] c = [1,0,1,0,1,0,1];
- static bit[] d = [1,0,1,1,1];
- static bit[] e = [1,0,1,0,1];
-
- assert(a > b);
- assert(a >= b);
- assert(a < c);
- assert(a <= c);
- assert(a < d);
- assert(a <= d);
- assert(a == e);
- assert(a <= e);
- assert(a >= e);
-}
-}
-
-/**********************************
- * Support for array.dup property.
- */
-
-extern(C)
-void* _d_realloc(void*, size_t);
-
-extern(C)
-Array _adDupT(TypeInfo ti, Array a)
-{
- Array r;
- if (a.length)
- {
- auto sizeelem = ti.next.tsize(); // array element size
- auto size = a.length * sizeelem;
- r.ptr = _d_realloc(null,size);
- r.length = a.length;
- memcpy(r.ptr, a.ptr, size);
- }
- return r;
-}
-
-unittest
-{
- int[] a;
- int[] b;
- int i;
-
- debug(adi) printf("array.dup.unittest\n");
-
- a = new int[3];
- a[0] = 1; a[1] = 2; a[2] = 3;
- b = a.dup;
- assert(b.length == 3);
- for (i = 0; i < 3; i++)
- assert(b[i] == i + 1);
-}
+//_ adi.d
+
+/**
+ * Part of the D programming language runtime library.
+ * Dynamic array property support routines
+ */
+
+/*
+ * Copyright (C) 2000-2006 by Digital Mars, www.digitalmars.com
+ * Written by Walter Bright
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, in both source and binary form, subject to the following
+ * restrictions:
+ *
+ * o The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * o Altered source versions must be plainly marked as such, and must not
+ * be misrepresented as being the original software.
+ * o This notice may not be removed or altered from any source
+ * distribution.
+ */
+
+//debug=adi; // uncomment to turn on debugging printf's
+
+//import std.stdio;
+import std.c.stdio;
+import std.c.stdlib;
+import std.c.string;
+//import std.string;
+import std.outofmemory;
+import std.utf;
+
+pragma(no_typeinfo)
+struct Array
+{
+ size_t length;
+ void* ptr;
+}
+
+/**********************************************
+ * Reverse array of chars.
+ * Handled separately because embedded multibyte encodings should not be
+ * reversed.
+ */
+
+extern (C) char[] _adReverseChar(char[] a)
+{
+ if (a.length > 1)
+ {
+ char[6] tmp;
+ char[6] tmplo;
+ char* lo = a.ptr;
+ char* hi = &a[length - 1];
+
+ while (lo < hi)
+ { auto clo = *lo;
+ auto chi = *hi;
+
+ //printf("lo = %d, hi = %d\n", lo, hi);
+ if (clo <= 0x7F && chi <= 0x7F)
+ {
+ //printf("\tascii\n");
+ *lo = chi;
+ *hi = clo;
+ lo++;
+ hi--;
+ continue;
+ }
+
+ uint stridelo = std.utf.UTF8stride[clo];
+
+ uint stridehi = 1;
+ while ((chi & 0xC0) == 0x80)
+ {
+ chi = *--hi;
+ stridehi++;
+ assert(hi >= lo);
+ }
+ if (lo == hi)
+ break;
+
+ //printf("\tstridelo = %d, stridehi = %d\n", stridelo, stridehi);
+ if (stridelo == stridehi)
+ {
+
+ memcpy(tmp.ptr, lo, stridelo);
+ memcpy(lo, hi, stridelo);
+ memcpy(hi, tmp.ptr, stridelo);
+ lo += stridelo;
+ hi--;
+ continue;
+ }
+
+ /* Shift the whole array. This is woefully inefficient
+ */
+ memcpy(tmp.ptr, hi, stridehi);
+ memcpy(tmplo.ptr, lo, stridelo);
+ memmove(lo + stridehi, lo + stridelo , (hi - lo) - stridelo);
+ memcpy(lo, tmp.ptr, stridehi);
+ memcpy(hi + stridehi - stridelo, tmplo.ptr, stridelo);
+
+ lo += stridehi;
+ hi = hi - 1 + (stridehi - stridelo);
+ }
+ }
+ return a;
+}
+
+unittest
+{
+ string a = "abcd";
+ string r;
+
+ r = a.dup.reverse;
+ //writefln(r);
+ assert(r == "dcba");
+
+ a = "a\u1235\u1234c";
+ //writefln(a);
+ r = a.dup.reverse;
+ //writefln(r);
+ assert(r == "c\u1234\u1235a");
+
+ a = "ab\u1234c";
+ //writefln(a);
+ r = a.dup.reverse;
+ //writefln(r);
+ assert(r == "c\u1234ba");
+
+ a = "\u3026\u2021\u3061\n";
+ r = a.dup.reverse;
+ assert(r == "\n\u3061\u2021\u3026");
+}
+
+
+/**********************************************
+ * Reverse array of wchars.
+ * Handled separately because embedded multiword encodings should not be
+ * reversed.
+ */
+
+extern (C) wchar[] _adReverseWchar(wchar[] a)
+{
+ if (a.length > 1)
+ {
+ wchar[2] tmp;
+ wchar* lo = a.ptr;
+ wchar* hi = &a[length - 1];
+
+ while (lo < hi)
+ { auto clo = *lo;
+ auto chi = *hi;
+
+ if ((clo < 0xD800 || clo > 0xDFFF) &&
+ (chi < 0xD800 || chi > 0xDFFF))
+ {
+ *lo = chi;
+ *hi = clo;
+ lo++;
+ hi--;
+ continue;
+ }
+
+ int stridelo = 1 + (clo >= 0xD800 && clo <= 0xDBFF);
+
+ int stridehi = 1;
+ if (chi >= 0xDC00 && chi <= 0xDFFF)
+ {
+ chi = *--hi;
+ stridehi++;
+ assert(hi >= lo);
+ }
+ if (lo == hi)
+ break;
+
+ if (stridelo == stridehi)
+ { int stmp;
+
+ assert(stridelo == 2);
+ assert(stmp.sizeof == 2 * (*lo).sizeof);
+ stmp = *cast(int*)lo;
+ *cast(int*)lo = *cast(int*)hi;
+ *cast(int*)hi = stmp;
+ lo += stridelo;
+ hi--;
+ continue;
+ }
+
+ /* Shift the whole array. This is woefully inefficient
+ */
+ memcpy(tmp.ptr, hi, stridehi * wchar.sizeof);
+ memcpy(hi + stridehi - stridelo, lo, stridelo * wchar.sizeof);
+ memmove(lo + stridehi, lo + stridelo , (hi - (lo + stridelo)) * wchar.sizeof);
+ memcpy(lo, tmp.ptr, stridehi * wchar.sizeof);
+
+ lo += stridehi;
+ hi = hi - 1 + (stridehi - stridelo);
+ }
+ }
+ return a;
+}
+
+unittest
+{
+ wstring a = "abcd";
+ wstring r;
+
+ r = a.dup.reverse;
+ assert(r == "dcba");
+
+ a = "a\U00012356\U00012346c";
+ r = a.dup.reverse;
+ assert(r == "c\U00012346\U00012356a");
+
+ a = "ab\U00012345c";
+ r = a.dup.reverse;
+ assert(r == "c\U00012345ba");
+}
+
+
+/**********************************************
+ * Support for array.reverse property.
+ */
+
+extern (C) Array _adReverse(Array a, size_t szelem)
+{
+ if (a.length >= 2)
+ {
+ byte* tmp;
+ byte[16] buffer;
+
+ void* lo = a.ptr;
+ void* hi = a.ptr + (a.length - 1) * szelem;
+
+ tmp = buffer.ptr;
+ if (szelem > 16)
+ {
+ //version (Win32)
+ //tmp = cast(byte*) alloca(szelem);
+ //else
+ tmp = (new byte[szelem]).ptr;
+ }
+
+ for (; lo < hi; lo += szelem, hi -= szelem)
+ {
+ memcpy(tmp, lo, szelem);
+ memcpy(lo, hi, szelem);
+ memcpy(hi, tmp, szelem);
+ }
+
+ version (Win32)
+ {
+ }
+ else
+ {
+ //if (szelem > 16)
+ // BUG: bad code is generate for delete pointer, tries
+ // to call delclass.
+ //delete tmp;
+ }
+ }
+ return a;
+}
+
+unittest
+{
+ debug(adi) printf("array.reverse.unittest\n");
+
+ int[] a = new int[5];
+ int[] b;
+ size_t i;
+
+ for (i = 0; i < 5; i++)
+ a[i] = i;
+ b = a.reverse;
+ assert(b is a);
+ for (i = 0; i < 5; i++)
+ assert(a[i] == 4 - i);
+
+ struct X20
+ { // More than 16 bytes in size
+ int a;
+ int b, c, d, e;
+ }
+
+ X20[] c = new X20[5];
+ X20[] d;
+
+ for (i = 0; i < 5; i++)
+ { c[i].a = i;
+ c[i].e = 10;
+ }
+ d = c.reverse;
+ assert(d is c);
+ for (i = 0; i < 5; i++)
+ {
+ assert(c[i].a == 4 - i);
+ assert(c[i].e == 10);
+ }
+}
+
+/**********************************************
+ * Support for array.reverse property for bit[].
+ */
+
+version (none)
+{
+extern (C) bit[] _adReverseBit(bit[] a)
+ out (result)
+ {
+ assert(result is a);
+ }
+ body
+ {
+ if (a.length >= 2)
+ {
+ bit t;
+ int lo, hi;
+
+ lo = 0;
+ hi = a.length - 1;
+ for (; lo < hi; lo++, hi--)
+ {
+ t = a[lo];
+ a[lo] = a[hi];
+ a[hi] = t;
+ }
+ }
+ return a;
+ }
+
+unittest
+{
+ debug(adi) printf("array.reverse_Bit[].unittest\n");
+
+ bit[] b;
+ b = new bit[5];
+ static bit[5] data = [1,0,1,1,0];
+ int i;
+
+ b[] = data[];
+ b.reverse;
+ for (i = 0; i < 5; i++)
+ {
+ assert(b[i] == data[4 - i]);
+ }
+}
+}
+
+/**********************************************
+ * Sort array of chars.
+ */
+
+extern (C) char[] _adSortChar(char[] a)
+{
+ if (a.length > 1)
+ {
+ dstring da = toUTF32(a);
+ da.sort;
+ size_t i = 0;
+ foreach (dchar d; da)
+ { char[4] buf;
+ string t = toUTF8(buf, d);
+ a[i .. i + t.length] = t[];
+ i += t.length;
+ }
+ delete da;
+ }
+ return a;
+}
+
+/**********************************************
+ * Sort array of wchars.
+ */
+
+extern (C) wchar[] _adSortWchar(wchar[] a)
+{
+ if (a.length > 1)
+ {
+ dstring da = toUTF32(a);
+ da.sort;
+ size_t i = 0;
+ foreach (dchar d; da)
+ { wchar[2] buf;
+ wstring t = toUTF16(buf, d);
+ a[i .. i + t.length] = t[];
+ i += t.length;
+ }
+ delete da;
+ }
+ return a;
+}
+
+/**********************************************
+ * Support for array.sort property for bit[].
+ */
+
+version (none)
+{
+extern (C) bit[] _adSortBit(bit[] a)
+ out (result)
+ {
+ assert(result is a);
+ }
+ body
+ {
+ if (a.length >= 2)
+ {
+ size_t lo, hi;
+
+ lo = 0;
+ hi = a.length - 1;
+ while (1)
+ {
+ while (1)
+ {
+ if (lo >= hi)
+ goto Ldone;
+ if (a[lo] == true)
+ break;
+ lo++;
+ }
+
+ while (1)
+ {
+ if (lo >= hi)
+ goto Ldone;
+ if (a[hi] == false)
+ break;
+ hi--;
+ }
+
+ a[lo] = false;
+ a[hi] = true;
+
+ lo++;
+ hi--;
+ }
+ Ldone:
+ ;
+ }
+ return a;
+ }
+
+unittest
+{
+ debug(adi) printf("array.sort_Bit[].unittest\n");
+}
+}
+
+/***************************************
+ * Support for array equality test.
+ */
+
+extern (C) int _adEq(Array a1, Array a2, TypeInfo ti)
+{
+ // printf("_adEq(a1.length = %d, a2.length = %d)\n", a1.length, a2.length);
+ if (a1.length != a2.length)
+ return 0; // not equal
+ auto sz = ti.next.tsize();
+ auto p1 = a1.ptr;
+ auto p2 = a2.ptr;
+
+/+
+ for (int i = 0; i < a1.length; i++)
+ {
+ printf("%4x %4x\n", (cast(short*)p1)[i], (cast(short*)p2)[i]);
+ }
+ printf("sz = %u\n", sz);
++/
+
+ if (sz == 1)
+ // We should really have a ti.isPOD() check for this
+ return (memcmp(p1, p2, a1.length) == 0);
+
+ for (size_t i = 0; i < a1.length; i++)
+ {
+ if (!ti.next.equals(p1 + i * sz, p2 + i * sz))
+ return 0; // not equal
+ }
+ return 1; // equal
+}
+
+unittest
+{
+ debug(adi) printf("array.Eq unittest\n");
+
+ string a = "hello";
+
+ assert(a != "hel");
+ assert(a != "helloo");
+ assert(a != "betty");
+ assert(a == "hello");
+ assert(a != "hxxxx");
+}
+
+/***************************************
+ * Support for bit array equality test for bit arrays.
+ */
+
+version (none)
+{
+extern (C) int _adEqBit(Array a1, Array a2)
+{ size_t i;
+
+ if (a1.length != a2.length)
+ return 0; // not equal
+ auto p1 = cast(byte*)a1.ptr;
+ auto p2 = cast(byte*)a2.ptr;
+ auto n = a1.length / 8;
+ for (i = 0; i < n; i++)
+ {
+ if (p1[i] != p2[i])
+ return 0; // not equal
+ }
+
+ ubyte mask;
+
+ n = a1.length & 7;
+ mask = cast(ubyte)((1 << n) - 1);
+ //printf("i = %d, n = %d, mask = %x, %x, %x\n", i, n, mask, p1[i], p2[i]);
+ return (mask == 0) || (p1[i] & mask) == (p2[i] & mask);
+}
+
+unittest
+{
+ debug(adi) printf("array.EqBit unittest\n");
+
+ static bit[] a = [1,0,1,0,1];
+ static bit[] b = [1,0,1];
+ static bit[] c = [1,0,1,0,1,0,1];
+ static bit[] d = [1,0,1,1,1];
+ static bit[] e = [1,0,1,0,1];
+
+ assert(a != b);
+ assert(a != c);
+ assert(a != d);
+ assert(a == e);
+}
+}
+
+/***************************************
+ * Support for array compare test.
+ */
+
+extern (C) int _adCmp(Array a1, Array a2, TypeInfo ti)
+{
+ //printf("adCmp()\n");
+ auto len = a1.length;
+ if (a2.length < len)
+ len = a2.length;
+ auto sz = ti.tsize();
+ void *p1 = a1.ptr;
+ void *p2 = a2.ptr;
+
+ if (sz == 1)
+ { // We should really have a ti.isPOD() check for this
+ auto c = memcmp(p1, p2, len);
+ if (c)
+ return c;
+ }
+ else
+ {
+ for (size_t i = 0; i < len; i++)
+ {
+ auto c = ti.compare(p1 + i * sz, p2 + i * sz);
+ if (c)
+ return c;
+ }
+ }
+ if (a1.length == a2.length)
+ return 0;
+ return (a1.length > a2.length) ? 1 : -1;
+}
+
+unittest
+{
+ debug(adi) printf("array.Cmp unittest\n");
+
+ string a = "hello";
+
+ assert(a > "hel");
+ assert(a >= "hel");
+ assert(a < "helloo");
+ assert(a <= "helloo");
+ assert(a > "betty");
+ assert(a >= "betty");
+ assert(a == "hello");
+ assert(a <= "hello");
+ assert(a >= "hello");
+}
+
+/***************************************
+ * Support for char array compare test.
+ */
+
+extern (C) int _adCmpChar(Array a1, Array a2)
+{
+version (D_InlineAsm_X86)
+{
+ asm
+ { naked ;
+
+ push EDI ;
+ push ESI ;
+
+ mov ESI,a1+4[4+ESP] ;
+ mov EDI,a2+4[4+ESP] ;
+
+ mov ECX,a1[4+ESP] ;
+ mov EDX,a2[4+ESP] ;
+
+ cmp ECX,EDX ;
+ jb GotLength ;
+
+ mov ECX,EDX ;
+
+GotLength:
+ cmp ECX,4 ;
+ jb DoBytes ;
+
+ // Do alignment if neither is dword aligned
+ test ESI,3 ;
+ jz Aligned ;
+
+ test EDI,3 ;
+ jz Aligned ;
+DoAlign:
+ mov AL,[ESI] ; //align ESI to dword bounds
+ mov DL,[EDI] ;
+
+ cmp AL,DL ;
+ jnz Unequal ;
+
+ inc ESI ;
+ inc EDI ;
+
+ test ESI,3 ;
+
+ lea ECX,[ECX-1] ;
+ jnz DoAlign ;
+Aligned:
+ mov EAX,ECX ;
+
+ // do multiple of 4 bytes at a time
+
+ shr ECX,2 ;
+ jz TryOdd ;
+
+ repe ;
+ cmpsd ;
+
+ jnz UnequalQuad ;
+
+TryOdd:
+ mov ECX,EAX ;
+DoBytes:
+ // if still equal and not end of string, do up to 3 bytes slightly
+ // slower.
+
+ and ECX,3 ;
+ jz Equal ;
+
+ repe ;
+ cmpsb ;
+
+ jnz Unequal ;
+Equal:
+ mov EAX,a1[4+ESP] ;
+ mov EDX,a2[4+ESP] ;
+
+ sub EAX,EDX ;
+ pop ESI ;
+
+ pop EDI ;
+ ret ;
+
+UnequalQuad:
+ mov EDX,[EDI-4] ;
+ mov EAX,[ESI-4] ;
+
+ cmp AL,DL ;
+ jnz Unequal ;
+
+ cmp AH,DH ;
+ jnz Unequal ;
+
+ shr EAX,16 ;
+
+ shr EDX,16 ;
+
+ cmp AL,DL ;
+ jnz Unequal ;
+
+ cmp AH,DH ;
+Unequal:
+ sbb EAX,EAX ;
+ pop ESI ;
+
+ or EAX,1 ;
+ pop EDI ;
+
+ ret ;
+ }
+}
+else
+{
+ int len;
+ int c;
+
+ //printf("adCmpChar()\n");
+ len = a1.length;
+ if (a2.length < len)
+ len = a2.length;
+ c = memcmp(cast(char *)a1.ptr, cast(char *)a2.ptr, len);
+ if (!c)
+ c = cast(int)a1.length - cast(int)a2.length;
+ return c;
+}
+}
+
+unittest
+{
+ debug(adi) printf("array.CmpChar unittest\n");
+
+ string a = "hello";
+
+ assert(a > "hel");
+ assert(a >= "hel");
+ assert(a < "helloo");
+ assert(a <= "helloo");
+ assert(a > "betty");
+ assert(a >= "betty");
+ assert(a == "hello");
+ assert(a <= "hello");
+ assert(a >= "hello");
+}
+
+/***************************************
+ * Support for bit array compare test.
+ */
+
+version (none)
+{
+extern (C) int _adCmpBit(Array a1, Array a2)
+{
+ int len;
+ uint i;
+
+ len = a1.length;
+ if (a2.length < len)
+ len = a2.length;
+ ubyte *p1 = cast(ubyte*)a1.ptr;
+ ubyte *p2 = cast(ubyte*)a2.ptr;
+ uint n = len / 8;
+ for (i = 0; i < n; i++)
+ {
+ if (p1[i] != p2[i])
+ break; // not equal
+ }
+ for (uint j = i * 8; j < len; j++)
+ { ubyte mask = cast(ubyte)(1 << j);
+ int c;
+
+ c = cast(int)(p1[i] & mask) - cast(int)(p2[i] & mask);
+ if (c)
+ return c;
+ }
+ return cast(int)a1.length - cast(int)a2.length;
+}
+
+unittest
+{
+ debug(adi) printf("array.CmpBit unittest\n");
+
+ static bit[] a = [1,0,1,0,1];
+ static bit[] b = [1,0,1];
+ static bit[] c = [1,0,1,0,1,0,1];
+ static bit[] d = [1,0,1,1,1];
+ static bit[] e = [1,0,1,0,1];
+
+ assert(a > b);
+ assert(a >= b);
+ assert(a < c);
+ assert(a <= c);
+ assert(a < d);
+ assert(a <= d);
+ assert(a == e);
+ assert(a <= e);
+ assert(a >= e);
+}
+}
+
+/**********************************
+ * Support for array.dup property.
+ */
+
+extern(C)
+void* _d_realloc(void*, size_t);
+
+extern(C)
+Array _adDupT(TypeInfo ti, Array a)
+{
+ Array r;
+ if (a.length)
+ {
+ auto sizeelem = ti.next.tsize(); // array element size
+ auto size = a.length * sizeelem;
+ r.ptr = _d_realloc(null,size);
+ r.length = a.length;
+ memcpy(r.ptr, a.ptr, size);
+ }
+ return r;
+}
+
+unittest
+{
+ int[] a;
+ int[] b;
+ int i;
+
+ debug(adi) printf("array.dup.unittest\n");
+
+ a = new int[3];
+ a[0] = 1; a[1] = 2; a[2] = 3;
+ b = a.dup;
+ assert(b.length == 3);
+ for (i = 0; i < 3; i++)
+ assert(b[i] == i + 1);
+}
diff --git a/lphobos/internal/eh.d b/lphobos/internal/eh.d
index 6e742da6..a6fca4ac 100644
--- a/lphobos/internal/eh.d
+++ b/lphobos/internal/eh.d
@@ -287,8 +287,8 @@ extern(C) _Unwind_Reason_Code _d_eh_personality(int ver, _Unwind_Action actions,
action_walker += next_action_offset;
}
- printf("Assertion failure ;_;\n");
- assert(false);
+ /*printf("Assertion failure ;_;\n");
+ assert(false);*/
}
// These are the register numbers for SetGR that
@@ -353,12 +353,14 @@ private void _d_getLanguageSpecificTables(_Unwind_Context_Ptr context, ref ubyte
} // end of x86 Linux specific implementation
+extern(C) void* malloc(size_t size);
extern(C) void _d_throw_exception(Object e)
{
if (e !is null)
{
- _d_exception* exc_struct = new _d_exception;
+ // _d_exception* exc_struct = new _d_exception;
+ auto exc_struct = cast(_d_exception*)malloc(_d_exception.sizeof);
exc_struct.unwind_info.exception_class[] = _d_exception_class;
exc_struct.exception_object = e;
printf("Raising exception\n");
diff --git a/lphobos/llvmdc.conf b/lphobos/llvmdc.conf
index 67540fd4..4b7a9094 100644
--- a/lphobos/llvmdc.conf
+++ b/lphobos/llvmdc.conf
@@ -1,4 +1,5 @@
[Environment]
-DFLAGS=-I%@P%/../lphobos -I%@P%/../import -L-L%@P%/../lib -R%@P%/../lib
+DFLAGS=-I%@P%/../lphobos -I%@P%/../import -L-L%@P%/../lib
+# -R%@P%/../lib
diff --git a/lphobos/object.d b/lphobos/object.d
index c26082f2..15bcef15 100644
--- a/lphobos/object.d
+++ b/lphobos/object.d
@@ -81,6 +81,7 @@ class TypeInfo
OffsetTypeInfo[] offTi();
}
+pragma(no_typeinfo)
class TypeInfo_Typedef : TypeInfo
{
TypeInfo base;
@@ -205,3 +206,4 @@ class Error : Exception
this(string msg);
this(string msg, Error next);
}
+
diff --git a/lphobos/std/dateparse.d b/lphobos/std/dateparse.d
index 74b98352..197fd930 100644
--- a/lphobos/std/dateparse.d
+++ b/lphobos/std/dateparse.d
@@ -48,7 +48,7 @@ struct DateParse
*this = DateParse.init;
//version (Win32)
- buffer = (cast(char *)alloca(s.length))[0 .. s.length];
+ buffer = (cast(char *)/*alloca*/malloc(s.length))[0 .. s.length];
//else
//buffer = new char[s.length];
diff --git a/lphobos/std/file.d b/lphobos/std/file.d
index d401813e..2ee363b2 100644
--- a/lphobos/std/file.d
+++ b/lphobos/std/file.d
@@ -43,6 +43,8 @@ private import std.string;
private import std.regexp;
private import std.gc;
+version(linux) version = Unix;
+
/* =========================== Win32 ======================= */
version (Win32)
diff --git a/lphobos/std/format.d b/lphobos/std/format.d
index 4701d69c..440dd36f 100644
--- a/lphobos/std/format.d
+++ b/lphobos/std/format.d
@@ -1,1570 +1,1570 @@
-
-// Written in the D programming language.
-
-/**
- * This module implements the workhorse functionality for string and I/O formatting.
- * It's comparable to C99's vsprintf().
- *
- * Macros:
- * WIKI = Phobos/StdFormat
- */
-
-/*
- * Copyright (C) 2004-2006 by Digital Mars, www.digitalmars.com
- * Written by Walter Bright
- * Modified for LLVMDC by Tomas Lindquist Olsen
- *
- * This software is provided 'as-is', without any express or implied
- * warranty. In no event will the authors be held liable for any damages
- * arising from the use of this software.
- *
- * Permission is granted to anyone to use this software for any purpose,
- * including commercial applications, and to alter it and redistribute it
- * freely, subject to the following restrictions:
- *
- * o The origin of this software must not be misrepresented; you must not
- * claim that you wrote the original software. If you use this software
- * in a product, an acknowledgment in the product documentation would be
- * appreciated but is not required.
- * o Altered source versions must be plainly marked as such, and must not
- * be misrepresented as being the original software.
- * o This notice may not be removed or altered from any source
- * distribution.
- */
-
-module std.format;
-
-//debug=format; // uncomment to turn on debugging printf's
-
-import std.stdarg; // caller will need va_list
-
-private import std.utf;
-private import std.c.stdlib;
-private import std.c.string;
-private import std.string;
-
-version (Windows)
-{
- version (DigitalMars)
- {
- version = DigitalMarsC;
- }
-}
-
-version (DigitalMarsC)
-{
- // This is DMC's internal floating point formatting function
- extern (C)
- {
- extern char* function(int c, int flags, int precision, real* pdval,
- char* buf, int* psl, int width) __pfloatfmt;
- }
-}
-else
-{
- // Use C99 snprintf
- extern (C) int snprintf(char* s, size_t n, char* format, ...);
-}
-
-/**********************************************************************
- * Signals a mismatch between a format and its corresponding argument.
- */
-class FormatError : Error
-{
- private:
-
- this()
- {
- super("std.format");
- }
-
- this(char[] msg)
- {
- super("std.format " ~ msg);
- }
-}
-
-
-enum Mangle : char
-{
- Tvoid = 'v',
- Tbool = 'b',
- Tbyte = 'g',
- Tubyte = 'h',
- Tshort = 's',
- Tushort = 't',
- Tint = 'i',
- Tuint = 'k',
- Tlong = 'l',
- Tulong = 'm',
- Tfloat = 'f',
- Tdouble = 'd',
- Treal = 'e',
-
- Tifloat = 'o',
- Tidouble = 'p',
- Tireal = 'j',
- Tcfloat = 'q',
- Tcdouble = 'r',
- Tcreal = 'c',
-
- Tchar = 'a',
- Twchar = 'u',
- Tdchar = 'w',
-
- Tarray = 'A',
- Tsarray = 'G',
- Taarray = 'H',
- Tpointer = 'P',
- Tfunction = 'F',
- Tident = 'I',
- Tclass = 'C',
- Tstruct = 'S',
- Tenum = 'E',
- Ttypedef = 'T',
- Tdelegate = 'D',
-
- Tconst = 'x',
- Tinvariant = 'y',
-}
-
-// return the TypeInfo for a primitive type and null otherwise.
-// This is required since for arrays of ints we only have the mangled
-// char to work from. If arrays always subclassed TypeInfo_Array this
-// routine could go away.
-private TypeInfo primitiveTypeInfo(Mangle m)
-{
- TypeInfo ti;
-
- switch (m)
- {
- case Mangle.Tvoid:
- ti = typeid(void);break;
- case Mangle.Tbool:
- ti = typeid(bool);break;
- case Mangle.Tbyte:
- ti = typeid(byte);break;
- case Mangle.Tubyte:
- ti = typeid(ubyte);break;
- case Mangle.Tshort:
- ti = typeid(short);break;
- case Mangle.Tushort:
- ti = typeid(ushort);break;
- case Mangle.Tint:
- ti = typeid(int);break;
- case Mangle.Tuint:
- ti = typeid(uint);break;
- case Mangle.Tlong:
- ti = typeid(long);break;
- case Mangle.Tulong:
- ti = typeid(ulong);break;
- case Mangle.Tfloat:
- ti = typeid(float);break;
- case Mangle.Tdouble:
- ti = typeid(double);break;
- case Mangle.Treal:
- ti = typeid(real);break;
- case Mangle.Tifloat:
- ti = typeid(ifloat);break;
- case Mangle.Tidouble:
- ti = typeid(idouble);break;
- case Mangle.Tireal:
- ti = typeid(ireal);break;
- case Mangle.Tcfloat:
- ti = typeid(cfloat);break;
- case Mangle.Tcdouble:
- ti = typeid(cdouble);break;
- case Mangle.Tcreal:
- ti = typeid(creal);break;
- case Mangle.Tchar:
- ti = typeid(char);break;
- case Mangle.Twchar:
- ti = typeid(wchar);break;
- case Mangle.Tdchar:
- ti = typeid(dchar);
- default:
- ti = null;
- }
- return ti;
-}
-
-/************************************
- * Interprets variadic argument list pointed to by argptr whose types are given
- * by arguments[], formats them according to embedded format strings in the
- * variadic argument list, and sends the resulting characters to putc.
- *
- * The variadic arguments are consumed in order.
- * Each is formatted into a sequence of chars, using the default format
- * specification for its type, and the
- * characters are sequentially passed to putc.
- * If a char[], wchar[], or dchar[]
- * argument is encountered, it is interpreted as a format string. As many
- * arguments as specified in the format string are consumed and formatted
- * according to the format specifications in that string and passed to putc. If
- * there are too few remaining arguments, a FormatError is thrown. If there are
- * more remaining arguments than needed by the format specification, the default
- * processing of arguments resumes until they are all consumed.
- *
- * Params:
- * putc = Output is sent do this delegate, character by character.
- * arguments = Array of TypeInfo's, one for each argument to be formatted.
- * argptr = Points to variadic argument list.
- *
- * Throws:
- * Mismatched arguments and formats result in a FormatError being thrown.
- *
- * Format_String:
- * $(I Format strings)
- * consist of characters interspersed with
- * $(I format specifications). Characters are simply copied
- * to the output (such as putc) after any necessary conversion
- * to the corresponding UTF-8 sequence.
- *
- * A $(I format specification) starts with a '%' character,
- * and has the following grammar:
-
-
-$(I FormatSpecification):
- $(B '%%')
- $(B '%') $(I Flags) $(I Width) $(I Precision) $(I FormatChar)
-
-$(I Flags):
- $(I empty)
- $(B '-') $(I Flags)
- $(B '+') $(I Flags)
- $(B '#') $(I Flags)
- $(B '0') $(I Flags)
- $(B ' ') $(I Flags)
-
-$(I Width):
- $(I empty)
- $(I Integer)
- $(B '*')
-
-$(I Precision):
- $(I empty)
- $(B '.')
- $(B '.') $(I Integer)
- $(B '.*')
-
-$(I Integer):
- $(I Digit)
- $(I Digit) $(I Integer)
-
-$(I Digit):
- $(B '0')
- $(B '1')
- $(B '2')
- $(B '3')
- $(B '4')
- $(B '5')
- $(B '6')
- $(B '7')
- $(B '8')
- $(B '9')
-
-$(I FormatChar):
- $(B 's')
- $(B 'b')
- $(B 'd')
- $(B 'o')
- $(B 'x')
- $(B 'X')
- $(B 'e')
- $(B 'E')
- $(B 'f')
- $(B 'F')
- $(B 'g')
- $(B 'G')
- $(B 'a')
- $(B 'A')
-
-
- - $(I Flags)
-
- - $(B '-')
-
-
- Left justify the result in the field.
- It overrides any $(B 0) flag.
-
-
- $(B '+')
-
- Prefix positive numbers in a signed conversion with a $(B +).
- It overrides any $(I space) flag.
-
-
- $(B '#')
-
- Use alternative formatting:
-
- - For $(B 'o'):
-
- Add to precision as necessary so that the first digit
- of the octal formatting is a '0', even if both the argument
- and the $(I Precision) are zero.
-
- For $(B 'x') ($(B 'X')):
-
- If non-zero, prefix result with $(B 0x) ($(B 0X)).
-
- For floating point formatting:
-
- Always insert the decimal point.
-
- For $(B 'g') ($(B 'G')):
-
- Do not elide trailing zeros.
-
-
- - $(B '0')
-
- For integer and floating point formatting when not nan or
- infinity, use leading zeros
- to pad rather than spaces.
- Ignore if there's a $(I Precision).
-
-
- $(B ' ')
-
- Prefix positive numbers in a signed conversion with a space.
-
-
- - $(I Width)
-
-
- Specifies the minimum field width.
- If the width is a $(B *), the next argument, which must be
- of type $(B int), is taken as the width.
- If the width is negative, it is as if the $(B -) was given
- as a $(I Flags) character.
-
-
- $(I Precision)
-
- Gives the precision for numeric conversions.
- If the precision is a $(B *), the next argument, which must be
- of type $(B int), is taken as the precision. If it is negative,
- it is as if there was no $(I Precision).
-
-
- $(I FormatChar)
-
-
-
- - $(B 's')
-
- The corresponding argument is formatted in a manner consistent
- with its type:
-
- - $(B bool)
-
- The result is 'true' or 'false'.
-
- integral types
-
- The $(B %d) format is used.
-
- floating point types
-
- The $(B %g) format is used.
-
- string types
-
- The result is the string converted to UTF-8.
- A $(I Precision) specifies the maximum number of characters
- to use in the result.
-
- classes derived from $(B Object)
-
- The result is the string returned from the class instance's
- $(B .toString()) method.
- A $(I Precision) specifies the maximum number of characters
- to use in the result.
-
- non-string static and dynamic arrays
-
- The result is [s0, s1, ...]
- where sk is the kth element
- formatted with the default format.
-
-
- - $(B 'b','d','o','x','X')
-
- The corresponding argument must be an integral type
- and is formatted as an integer. If the argument is a signed type
- and the $(I FormatChar) is $(B d) it is converted to
- a signed string of characters, otherwise it is treated as
- unsigned. An argument of type $(B bool) is formatted as '1'
- or '0'. The base used is binary for $(B b), octal for $(B o),
- decimal
- for $(B d), and hexadecimal for $(B x) or $(B X).
- $(B x) formats using lower case letters, $(B X) uppercase.
- If there are fewer resulting digits than the $(I Precision),
- leading zeros are used as necessary.
- If the $(I Precision) is 0 and the number is 0, no digits
- result.
-
-
- $(B 'e','E')
-
- A floating point number is formatted as one digit before
- the decimal point, $(I Precision) digits after, the $(I FormatChar),
- ±, followed by at least a two digit exponent: $(I d.dddddd)e$(I ±dd).
- If there is no $(I Precision), six
- digits are generated after the decimal point.
- If the $(I Precision) is 0, no decimal point is generated.
-
-
- $(B 'f','F')
-
- A floating point number is formatted in decimal notation.
- The $(I Precision) specifies the number of digits generated
- after the decimal point. It defaults to six. At least one digit
- is generated before the decimal point. If the $(I Precision)
- is zero, no decimal point is generated.
-
-
- $(B 'g','G')
-
- A floating point number is formatted in either $(B e) or
- $(B f) format for $(B g); $(B E) or $(B F) format for
- $(B G).
- The $(B f) format is used if the exponent for an $(B e) format
- is greater than -5 and less than the $(I Precision).
- The $(I Precision) specifies the number of significant
- digits, and defaults to six.
- Trailing zeros are elided after the decimal point, if the fractional
- part is zero then no decimal point is generated.
-
-
- $(B 'a','A')
-
- A floating point number is formatted in hexadecimal
- exponential notation 0x$(I h.hhhhhh)p$(I ±d).
- There is one hexadecimal digit before the decimal point, and as
- many after as specified by the $(I Precision).
- If the $(I Precision) is zero, no decimal point is generated.
- If there is no $(I Precision), as many hexadecimal digits as
- necessary to exactly represent the mantissa are generated.
- The exponent is written in as few digits as possible,
- but at least one, is in decimal, and represents a power of 2 as in
- $(I h.hhhhhh)*2$(I ±d).
- The exponent for zero is zero.
- The hexadecimal digits, x and p are in upper case if the
- $(I FormatChar) is upper case.
-
-
- Floating point NaN's are formatted as $(B nan) if the
- $(I FormatChar) is lower case, or $(B NAN) if upper.
- Floating point infinities are formatted as $(B inf) or
- $(B infinity) if the
- $(I FormatChar) is lower case, or $(B INF) or $(B INFINITY) if upper.
-
-
-Example:
-
--------------------------
-import std.c.stdio;
-import std.format;
-
-void formattedPrint(...)
-{
- void putc(char c)
- {
- fputc(c, stdout);
- }
-
- std.format.doFormat(&putc, _arguments, _argptr);
-}
-
-...
-
-int x = 27;
-// prints 'The answer is 27:6'
-formattedPrint("The answer is %s:", x, 6);
-------------------------
- */
-
-void doFormat(void delegate(dchar) putc, TypeInfo[] arguments, void* argptr)
-{ //printf("doFormat(...)\n");
- int j;
- TypeInfo ti;
- Mangle m;
- uint flags;
- int field_width;
- int precision;
-
- enum : uint
- {
- FLdash = 1,
- FLplus = 2,
- FLspace = 4,
- FLhash = 8,
- FLlngdbl = 0x20,
- FL0pad = 0x40,
- FLprecision = 0x80,
- }
-
- static TypeInfo skipCI(TypeInfo valti)
- {
- while (1)
- {
- if (valti.classinfo.name.length == 18 &&
- valti.classinfo.name[9..18] == "Invariant")
- valti = (cast(TypeInfo_Invariant)valti).next;
- else if (valti.classinfo.name.length == 14 &&
- valti.classinfo.name[9..14] == "Const")
- valti = (cast(TypeInfo_Const)valti).next;
- else
- break;
- }
- return valti;
- }
-
- void formatArg(char fc)
- {
- bool vbit;
- ulong vnumber;
- char vchar;
- dchar vdchar;
- Object vobject;
- real vreal;
- creal vcreal;
- Mangle m2;
- int signed = 0;
- uint base = 10;
- int uc;
- char[ulong.sizeof * 8] tmpbuf; // long enough to print long in binary
- char* prefix = "";
- string s;
-
- void putstr(char[] s)
- {
- //printf("flags = 0x%x\n", flags);
- int prepad = 0;
- int postpad = 0;
- int padding = field_width - (strlen(prefix) + s.length);
- if (padding > 0)
- {
- if (flags & FLdash)
- postpad = padding;
- else
- prepad = padding;
- }
-
- if (flags & FL0pad)
- {
- while (*prefix)
- putc(*prefix++);
- while (prepad--)
- putc('0');
- }
- else
- {
- while (prepad--)
- putc(' ');
- while (*prefix)
- putc(*prefix++);
- }
-
- foreach (dchar c; s)
- putc(c);
-
- while (postpad--)
- putc(' ');
- }
-
- void putreal(real v)
- {
- //printf("putreal %Lg\n", vreal); // no 80 bit float
- //printf("putreal %g\n", vreal);
-
- switch (fc)
- {
- case 's':
- fc = 'g';
- break;
-
- case 'f', 'F', 'e', 'E', 'g', 'G', 'a', 'A':
- break;
-
- default:
- //printf("fc = '%c'\n", fc);
- Lerror:
- throw new FormatError("floating");
- }
- version (DigitalMarsC)
- {
- int sl;
- char[] fbuf = tmpbuf;
- if (!(flags & FLprecision))
- precision = 6;
- while (1)
- {
- sl = fbuf.length;
- prefix = (*__pfloatfmt)(fc, flags | FLlngdbl,
- precision, &v, cast(char*)fbuf, &sl, field_width);
- if (sl != -1)
- break;
- sl = fbuf.length * 2;
- fbuf = (cast(char*)alloca(sl * char.sizeof))[0 .. sl];
- }
- putstr(fbuf[0 .. sl]);
- }
- else
- {
- int sl;
- char[] fbuf = tmpbuf;
- char[12] format;
- format[0] = '%';
- int i = 1;
- if (flags & FLdash)
- format[i++] = '-';
- if (flags & FLplus)
- format[i++] = '+';
- if (flags & FLspace)
- format[i++] = ' ';
- if (flags & FLhash)
- format[i++] = '#';
- if (flags & FL0pad)
- format[i++] = '0';
- format[i + 0] = '*';
- format[i + 1] = '.';
- format[i + 2] = '*';
- format[i + 3] = fc;
- format[i + 4] = 0;
- //format[i + 3] = 'L'; // no 80 bit yet
- //format[i + 4] = fc;
- //format[i + 5] = 0;
- if (!(flags & FLprecision))
- precision = -1;
- while (1)
- { int n;
-
- sl = fbuf.length;
- n = snprintf(fbuf.ptr, sl, format.ptr, field_width, precision, v);
- //printf("format = '%s', n = %d\n", cast(char*)format, n);
- if (n >= 0 && n < sl)
- { sl = n;
- break;
- }
- if (n < 0)
- sl = sl * 2;
- else
- sl = n + 1;
- fbuf = (cast(char*)alloca(sl * char.sizeof))[0 .. sl];
- }
- putstr(fbuf[0 .. sl]);
- }
- return;
- }
-
- static Mangle getMan(TypeInfo ti)
- {
- auto m = cast(Mangle)ti.classinfo.name[9];
- if (ti.classinfo.name.length == 20 &&
- ti.classinfo.name[9..20] == "StaticArray")
- m = cast(Mangle)'G';
- return m;
- }
-
- void putArray(void* p, size_t len, TypeInfo valti)
- {
- //printf("\nputArray(len = %u), tsize = %u\n", len, valti.tsize());
- putc('[');
- valti = skipCI(valti);
- size_t tsize = valti.tsize();
- auto argptrSave = argptr;
- auto tiSave = ti;
- auto mSave = m;
- ti = valti;
- auto className = valti.classinfo.name;
- printf("\n%.*s\n", className.length, className.ptr);
- m = getMan(valti);
- while (len--)
- {
- //doFormat(putc, (&valti)[0 .. 1], p);
- argptr = p;
- formatArg('s');
-
- p += tsize;
- if (len > 0) putc(',');
- }
- m = mSave;
- ti = tiSave;
- argptr = argptrSave;
- putc(']');
- }
-
- void putAArray(ubyte[long] vaa, TypeInfo valti, TypeInfo keyti)
- {
- putc('[');
- bool comma=false;
- auto argptrSave = argptr;
- auto tiSave = ti;
- auto mSave = m;
- valti = skipCI(valti);
- keyti = skipCI(keyti);
- foreach(inout fakevalue; vaa)
- {
- if (comma) putc(',');
- comma = true;
- // the key comes before the value
- ubyte* key = &fakevalue - long.sizeof;
-
- //doFormat(putc, (&keyti)[0..1], key);
- argptr = key;
- ti = keyti;
- m = getMan(keyti);
- formatArg('s');
-
- putc(':');
- auto keysize = keyti.tsize;
- keysize = (keysize + 3) & ~3;
- ubyte* value = key + keysize;
- //doFormat(putc, (&valti)[0..1], value);
- argptr = value;
- ti = valti;
- m = getMan(valti);
- formatArg('s');
- }
- m = mSave;
- ti = tiSave;
- argptr = argptrSave;
- putc(']');
- }
-
- //printf("formatArg(fc = '%c', m = '%c')\n", fc, m);
- switch (m)
- {
- case Mangle.Tbool:
- vbit = va_arg!(bool)(argptr);
- if (fc != 's')
- { vnumber = vbit;
- goto Lnumber;
- }
- putstr(vbit ? "true" : "false");
- return;
-
-
- case Mangle.Tchar:
- vchar = va_arg!(char)(argptr);
- if (fc != 's')
- { vnumber = vchar;
- goto Lnumber;
- }
- L2:
- putstr((&vchar)[0 .. 1]);
- return;
-
- case Mangle.Twchar:
- vdchar = va_arg!(wchar)(argptr);
- goto L1;
-
- case Mangle.Tdchar:
- vdchar = va_arg!(dchar)(argptr);
- L1:
- if (fc != 's')
- { vnumber = vdchar;
- goto Lnumber;
- }
- if (vdchar <= 0x7F)
- { vchar = cast(char)vdchar;
- goto L2;
- }
- else
- { if (!isValidDchar(vdchar))
- throw new UtfException("invalid dchar in format", 0);
- char[4] vbuf;
- putstr(toUTF8(vbuf, vdchar));
- }
- return;
-
-
- case Mangle.Tbyte:
- signed = 1;
- vnumber = va_arg!(byte)(argptr);
- goto Lnumber;
-
- case Mangle.Tubyte:
- vnumber = va_arg!(ubyte)(argptr);
- goto Lnumber;
-
- case Mangle.Tshort:
- signed = 1;
- vnumber = va_arg!(short)(argptr);
- goto Lnumber;
-
- case Mangle.Tushort:
- vnumber = va_arg!(ushort)(argptr);
- goto Lnumber;
-
- case Mangle.Tint:
- signed = 1;
- vnumber = va_arg!(int)(argptr);
- goto Lnumber;
-
- case Mangle.Tuint:
- Luint:
- vnumber = va_arg!(uint)(argptr);
- goto Lnumber;
-
- case Mangle.Tlong:
- signed = 1;
- vnumber = cast(ulong)va_arg!(long)(argptr);
- goto Lnumber;
-
- case Mangle.Tulong:
- Lulong:
- vnumber = va_arg!(ulong)(argptr);
- goto Lnumber;
-
- case Mangle.Tclass:
- vobject = va_arg!(Object)(argptr);
- if (vobject is null)
- s = "null";
- else
- s = vobject.toString();
- goto Lputstr;
-
- case Mangle.Tpointer:
- vnumber = cast(ulong)va_arg!(void*)(argptr);
- uc = 1;
- flags |= FL0pad;
- if (!(flags & FLprecision))
- { flags |= FLprecision;
- precision = (void*).sizeof;
- }
- base = 16;
- goto Lnumber;
-
-
- case Mangle.Tfloat:
- case Mangle.Tifloat:
- if (fc == 'x' || fc == 'X')
- goto Luint;
- vreal = va_arg!(float)(argptr);
- goto Lreal;
-
- case Mangle.Tdouble:
- case Mangle.Tidouble:
- if (fc == 'x' || fc == 'X')
- goto Lulong;
- vreal = va_arg!(double)(argptr);
- goto Lreal;
-
- case Mangle.Treal:
- case Mangle.Tireal:
- vreal = va_arg!(real)(argptr);
- goto Lreal;
-
-
- case Mangle.Tcfloat:
- vcreal = va_arg!(cfloat)(argptr);
- goto Lcomplex;
-
- case Mangle.Tcdouble:
- vcreal = va_arg!(cdouble)(argptr);
- goto Lcomplex;
-
- case Mangle.Tcreal:
- vcreal = va_arg!(creal)(argptr);
- goto Lcomplex;
-
- case Mangle.Tsarray:
- //printf("static array\n");
- putArray(argptr, (cast(TypeInfo_StaticArray)ti).len, (cast(TypeInfo_StaticArray)ti).next);
- return;
-
- case Mangle.Tarray:
- //printf("dynamic array\n");
- int mi = 10;
- if (ti.classinfo.name.length == 14 &&
- ti.classinfo.name[9..14] == "Array")
- { // array of non-primitive types
- TypeInfo tn = (cast(TypeInfo_Array)ti).next;
- tn = skipCI(tn);
- switch (cast(Mangle)tn.classinfo.name[9])
- {
- case Mangle.Tchar: goto LarrayChar;
- case Mangle.Twchar: goto LarrayWchar;
- case Mangle.Tdchar: goto LarrayDchar;
- default:
- break;
- }
- void[] va = va_arg!(void[])(argptr);
- putArray(va.ptr, va.length, tn);
- return;
- }
- if (ti.classinfo.name.length == 25 &&
- ti.classinfo.name[9..25] == "AssociativeArray")
- { // associative array
- ubyte[long] vaa = va_arg!(ubyte[long])(argptr);
- putAArray(vaa,
- (cast(TypeInfo_AssociativeArray)ti).next,
- (cast(TypeInfo_AssociativeArray)ti).key);
- return;
- }
-
- //printf("primitive type\n");
- while (1)
- {
- m2 = cast(Mangle)ti.classinfo.name[mi];
- switch (m2)
- {
- case Mangle.Tchar:
- LarrayChar:
- s = va_arg!(char[])(argptr);
- goto Lputstr;
-
- case Mangle.Twchar:
- LarrayWchar:
- wchar[] sw = va_arg!(wchar[])(argptr);
- s = toUTF8(sw);
- goto Lputstr;
-
- case Mangle.Tdchar:
- LarrayDchar:
- dchar[] sd = va_arg!(dchar[])(argptr);
- s = toUTF8(sd);
- Lputstr:
- if (fc != 's')
- throw new FormatError("string");
- if (flags & FLprecision && precision < s.length)
- s = s[0 .. precision];
- putstr(s);
- break;
-
- case Mangle.Tconst:
- case Mangle.Tinvariant:
- mi++;
- continue;
-
- default:
- //printf("primitive type default handling\n");
- TypeInfo ti2 = primitiveTypeInfo(m2);
- if (!ti2)
- goto Lerror;
- void[] va = va_arg!(void[])(argptr);
- putArray(va.ptr, va.length, ti2);
- }
- return;
- }
-
- case Mangle.Ttypedef:
- ti = (cast(TypeInfo_Typedef)ti).base;
- m = cast(Mangle)ti.classinfo.name[9];
- formatArg(fc);
- return;
-
- case Mangle.Tenum:
- ti = (cast(TypeInfo_Enum)ti).base;
- m = cast(Mangle)ti.classinfo.name[9];
- formatArg(fc);
- return;
-
- case Mangle.Tstruct:
- { TypeInfo_Struct tis = cast(TypeInfo_Struct)ti;
- if (tis.xtoString is null)
- throw new FormatError("Can't convert " ~ tis.toString() ~ " to string: \"string toString()\" not defined");
- s = tis.xtoString(argptr);
- argptr += (tis.tsize() + 3) & ~3;
- goto Lputstr;
- }
-
- default:
- goto Lerror;
- }
-
- Lnumber:
- switch (fc)
- {
- case 's':
- case 'd':
- if (signed)
- { if (cast(long)vnumber < 0)
- { prefix = "-";
- vnumber = -vnumber;
- }
- else if (flags & FLplus)
- prefix = "+";
- else if (flags & FLspace)
- prefix = " ";
- }
- break;
-
- case 'b':
- signed = 0;
- base = 2;
- break;
-
- case 'o':
- signed = 0;
- base = 8;
- break;
-
- case 'X':
- uc = 1;
- if (flags & FLhash && vnumber)
- prefix = "0X";
- signed = 0;
- base = 16;
- break;
-
- case 'x':
- if (flags & FLhash && vnumber)
- prefix = "0x";
- signed = 0;
- base = 16;
- break;
-
- default:
- goto Lerror;
- }
-
- if (!signed)
- {
- switch (m)
- {
- case Mangle.Tbyte:
- vnumber &= 0xFF;
- break;
-
- case Mangle.Tshort:
- vnumber &= 0xFFFF;
- break;
-
- case Mangle.Tint:
- vnumber &= 0xFFFFFFFF;
- break;
-
- default:
- break;
- }
- }
-
- if (flags & FLprecision && fc != 'p')
- flags &= ~FL0pad;
-
- if (vnumber < base)
- {
- if (vnumber == 0 && precision == 0 && flags & FLprecision &&
- !(fc == 'o' && flags & FLhash))
- {
- putstr(null);
- return;
- }
- if (precision == 0 || !(flags & FLprecision))
- { vchar = cast(char)('0' + vnumber);
- if (vnumber < 10)
- vchar = cast(char)('0' + vnumber);
- else
- vchar = cast(char)((uc ? 'A' - 10 : 'a' - 10) + vnumber);
- goto L2;
- }
- }
-
- int n = tmpbuf.length;
- char c;
- int hexoffset = uc ? ('A' - ('9' + 1)) : ('a' - ('9' + 1));
-
- while (vnumber)
- {
- c = cast(char)((vnumber % base) + '0');
- if (c > '9')
- c += hexoffset;
- vnumber /= base;
- tmpbuf[--n] = c;
- }
- if (tmpbuf.length - n < precision && precision < tmpbuf.length)
- {
- int m = tmpbuf.length - precision;
- tmpbuf[m .. n] = '0';
- n = m;
- }
- else if (flags & FLhash && fc == 'o')
- prefix = "0";
- putstr(tmpbuf[n .. tmpbuf.length]);
- return;
-
- Lreal:
- putreal(vreal);
- return;
-
- Lcomplex:
- putreal(vcreal.re);
- putc('+');
- putreal(vcreal.im);
- putc('i');
- return;
-
- Lerror:
- throw new FormatError("formatArg");
- }
-
-
- //printf("arguments length: %u\n", arguments.length);
- for (j = 0; j < arguments.length; )
- { ti = arguments[j++];
- //printf("test1: '%.*s' %d\n", ti.classinfo.name.length, ti.classinfo.name.ptr, ti.classinfo.name.length);
- //ti.print();
-
- flags = 0;
- precision = 0;
- field_width = 0;
-
- ti = skipCI(ti);
- int mi = 9;
- do
- {
- if (ti.classinfo.name.length <= mi)
- goto Lerror;
- m = cast(Mangle)ti.classinfo.name[mi++];
- } while (m == Mangle.Tconst || m == Mangle.Tinvariant);
-
- if (m == Mangle.Tarray)
- {
- if (ti.classinfo.name.length == 14 &&
- ti.classinfo.name[9..14] == "Array")
- {
- TypeInfo tn = (cast(TypeInfo_Array)ti).next;
- tn = skipCI(tn);
- switch (cast(Mangle)tn.classinfo.name[9])
- {
- case Mangle.Tchar:
- case Mangle.Twchar:
- case Mangle.Tdchar:
- ti = tn;
- mi = 9;
- break;
- default:
- break;
- }
- }
- L1:
- Mangle m2 = cast(Mangle)ti.classinfo.name[mi];
- string fmt; // format string
- wstring wfmt;
- dstring dfmt;
-
- /* For performance reasons, this code takes advantage of the
- * fact that most format strings will be ASCII, and that the
- * format specifiers are always ASCII. This means we only need
- * to deal with UTF in a couple of isolated spots.
- */
-
- switch (m2)
- {
- case Mangle.Tchar:
- fmt = va_arg!(char[])(argptr);
- break;
-
- case Mangle.Twchar:
- wfmt = va_arg!(wchar[])(argptr);
- fmt = toUTF8(wfmt);
- break;
-
- case Mangle.Tdchar:
- dfmt = va_arg!(dchar[])(argptr);
- fmt = toUTF8(dfmt);
- break;
-
- case Mangle.Tconst:
- case Mangle.Tinvariant:
- mi++;
- goto L1;
-
- default:
- formatArg('s');
- continue;
- }
-
- for (size_t i = 0; i < fmt.length; )
- { dchar c = fmt[i++];
-
- dchar getFmtChar()
- { // Valid format specifier characters will never be UTF
- if (i == fmt.length)
- throw new FormatError("invalid specifier");
- return fmt[i++];
- }
-
- int getFmtInt()
- { int n;
-
- while (1)
- {
- n = n * 10 + (c - '0');
- if (n < 0) // overflow
- throw new FormatError("int overflow");
- c = getFmtChar();
- if (c < '0' || c > '9')
- break;
- }
- return n;
- }
-
- int getFmtStar()
- { Mangle m;
- TypeInfo ti;
-
- if (j == arguments.length)
- throw new FormatError("too few arguments");
- ti = arguments[j++];
- m = cast(Mangle)ti.classinfo.name[9];
- if (m != Mangle.Tint)
- throw new FormatError("int argument expected");
- return va_arg!(int)(argptr);
- }
-
- if (c != '%')
- {
- if (c > 0x7F) // if UTF sequence
- {
- i--; // back up and decode UTF sequence
- c = std.utf.decode(fmt, i);
- }
- Lputc:
- putc(c);
- continue;
- }
-
- // Get flags {-+ #}
- flags = 0;
- while (1)
- {
- c = getFmtChar();
- switch (c)
- {
- case '-': flags |= FLdash; continue;
- case '+': flags |= FLplus; continue;
- case ' ': flags |= FLspace; continue;
- case '#': flags |= FLhash; continue;
- case '0': flags |= FL0pad; continue;
-
- case '%': if (flags == 0)
- goto Lputc;
- default: break;
- }
- break;
- }
-
- // Get field width
- field_width = 0;
- if (c == '*')
- {
- field_width = getFmtStar();
- if (field_width < 0)
- { flags |= FLdash;
- field_width = -field_width;
- }
-
- c = getFmtChar();
- }
- else if (c >= '0' && c <= '9')
- field_width = getFmtInt();
-
- if (flags & FLplus)
- flags &= ~FLspace;
- if (flags & FLdash)
- flags &= ~FL0pad;
-
- // Get precision
- precision = 0;
- if (c == '.')
- { flags |= FLprecision;
- //flags &= ~FL0pad;
-
- c = getFmtChar();
- if (c == '*')
- {
- precision = getFmtStar();
- if (precision < 0)
- { precision = 0;
- flags &= ~FLprecision;
- }
-
- c = getFmtChar();
- }
- else if (c >= '0' && c <= '9')
- precision = getFmtInt();
- }
-
- if (j == arguments.length)
- goto Lerror;
- ti = arguments[j++];
- ti = skipCI(ti);
- mi = 9;
- do
- {
- m = cast(Mangle)ti.classinfo.name[mi++];
- } while (m == Mangle.Tconst || m == Mangle.Tinvariant);
-
- if (c > 0x7F) // if UTF sequence
- goto Lerror; // format specifiers can't be UTF
- formatArg(cast(char)c);
- }
- }
- else
- {
- formatArg('s');
- }
- }
- return;
-
-Lerror:
- throw new FormatError();
-}
-
-/* ======================== Unit Tests ====================================== */
-
-unittest
-{
- int i;
- string s;
-
- debug(format) printf("std.format.format.unittest\n");
-
- s = std.string.format("hello world! %s %s ", true, 57, 1_000_000_000, 'x', " foo");
- assert(s == "hello world! true 57 1000000000x foo");
-
- s = std.string.format(1.67, " %A ", -1.28, float.nan);
- /* The host C library is used to format floats.
- * C99 doesn't specify what the hex digit before the decimal point
- * is for %A.
- */
- version (linux)
- assert(s == "1.67 -0XA.3D70A3D70A3D8P-3 nan");
- else
- assert(s == "1.67 -0X1.47AE147AE147BP+0 nan");
-
- s = std.string.format("%x %X", 0x1234AF, 0xAFAFAFAF);
- assert(s == "1234af AFAFAFAF");
-
- s = std.string.format("%b %o", 0x1234AF, 0xAFAFAFAF);
- assert(s == "100100011010010101111 25753727657");
-
- s = std.string.format("%d %s", 0x1234AF, 0xAFAFAFAF);
- assert(s == "1193135 2947526575");
-
- s = std.string.format("%s", 1.2 + 3.4i);
- assert(s == "1.2+3.4i");
-
- s = std.string.format("%x %X", 1.32, 6.78f);
- assert(s == "3ff51eb851eb851f 40D8F5C3");
-
- s = std.string.format("%#06.*f",2,12.345);
- assert(s == "012.35");
-
- s = std.string.format("%#0*.*f",6,2,12.345);
- assert(s == "012.35");
-
- s = std.string.format("%7.4g:", 12.678);
- assert(s == " 12.68:");
-
- s = std.string.format("%7.4g:", 12.678L);
- assert(s == " 12.68:");
-
- s = std.string.format("%04f|%05d|%#05x|%#5x",-4.,-10,1,1);
- assert(s == "-4.000000|-0010|0x001| 0x1");
-
- i = -10;
- s = std.string.format("%d|%3d|%03d|%1d|%01.4f",i,i,i,i,cast(double) i);
- assert(s == "-10|-10|-10|-10|-10.0000");
-
- i = -5;
- s = std.string.format("%d|%3d|%03d|%1d|%01.4f",i,i,i,i,cast(double) i);
- assert(s == "-5| -5|-05|-5|-5.0000");
-
- i = 0;
- s = std.string.format("%d|%3d|%03d|%1d|%01.4f",i,i,i,i,cast(double) i);
- assert(s == "0| 0|000|0|0.0000");
-
- i = 5;
- s = std.string.format("%d|%3d|%03d|%1d|%01.4f",i,i,i,i,cast(double) i);
- assert(s == "5| 5|005|5|5.0000");
-
- i = 10;
- s = std.string.format("%d|%3d|%03d|%1d|%01.4f",i,i,i,i,cast(double) i);
- assert(s == "10| 10|010|10|10.0000");
-
- s = std.string.format("%.0d", 0);
- assert(s == "");
-
- s = std.string.format("%.g", .34);
- assert(s == "0.3");
-
- s = std.string.format("%.0g", .34);
- assert(s == "0.3");
-
- s = std.string.format("%.2g", .34);
- assert(s == "0.34");
-
- s = std.string.format("%0.0008f", 1e-08);
- assert(s == "0.00000001");
-
- s = std.string.format("%0.0008f", 1e-05);
- assert(s == "0.00001000");
-
- s = "helloworld";
- string r;
- r = std.string.format("%.2s", s[0..5]);
- assert(r == "he");
- r = std.string.format("%.20s", s[0..5]);
- assert(r == "hello");
- r = std.string.format("%8s", s[0..5]);
- assert(r == " hello");
-
- byte[] arrbyte = new byte[4];
- arrbyte[0] = 100;
- arrbyte[1] = -99;
- arrbyte[3] = 0;
- r = std.string.format(arrbyte);
- assert(r == "[100,-99,0,0]");
-
- ubyte[] arrubyte = new ubyte[4];
- arrubyte[0] = 100;
- arrubyte[1] = 200;
- arrubyte[3] = 0;
- r = std.string.format(arrubyte);
- assert(r == "[100,200,0,0]");
-
- short[] arrshort = new short[4];
- arrshort[0] = 100;
- arrshort[1] = -999;
- arrshort[3] = 0;
- r = std.string.format(arrshort);
- assert(r == "[100,-999,0,0]");
- r = std.string.format("%s",arrshort);
- assert(r == "[100,-999,0,0]");
-
- ushort[] arrushort = new ushort[4];
- arrushort[0] = 100;
- arrushort[1] = 20_000;
- arrushort[3] = 0;
- r = std.string.format(arrushort);
- assert(r == "[100,20000,0,0]");
-
- int[] arrint = new int[4];
- arrint[0] = 100;
- arrint[1] = -999;
- arrint[3] = 0;
- r = std.string.format(arrint);
- assert(r == "[100,-999,0,0]");
- r = std.string.format("%s",arrint);
- assert(r == "[100,-999,0,0]");
-
- long[] arrlong = new long[4];
- arrlong[0] = 100;
- arrlong[1] = -999;
- arrlong[3] = 0;
- r = std.string.format(arrlong);
- assert(r == "[100,-999,0,0]");
- r = std.string.format("%s",arrlong);
- assert(r == "[100,-999,0,0]");
-
- ulong[] arrulong = new ulong[4];
- arrulong[0] = 100;
- arrulong[1] = 999;
- arrulong[3] = 0;
- r = std.string.format(arrulong);
- assert(r == "[100,999,0,0]");
-
- string[] arr2 = new string[4];
- arr2[0] = "hello";
- arr2[1] = "world";
- arr2[3] = "foo";
- r = std.string.format(arr2);
- assert(r == "[hello,world,,foo]");
-
- r = std.string.format("%.8d", 7);
- assert(r == "00000007");
- r = std.string.format("%.8x", 10);
- assert(r == "0000000a");
-
- r = std.string.format("%-3d", 7);
- assert(r == "7 ");
-
- r = std.string.format("%*d", -3, 7);
- assert(r == "7 ");
-
- r = std.string.format("%.*d", -3, 7);
- assert(r == "7");
-
- typedef int myint;
- myint m = -7;
- r = std.string.format(m);
- assert(r == "-7");
-
- r = std.string.format("abc"c);
- assert(r == "abc");
- r = std.string.format("def"w);
- assert(r == "def");
- r = std.string.format("ghi"d);
- assert(r == "ghi");
-
- void* p = cast(void*)0xDEADBEEF;
- r = std.string.format(p);
- assert(r == "DEADBEEF");
-
- r = std.string.format("%#x", 0xabcd);
- assert(r == "0xabcd");
- r = std.string.format("%#X", 0xABCD);
- assert(r == "0XABCD");
-
- r = std.string.format("%#o", 012345);
- assert(r == "012345");
- r = std.string.format("%o", 9);
- assert(r == "11");
-
- r = std.string.format("%+d", 123);
- assert(r == "+123");
- r = std.string.format("%+d", -123);
- assert(r == "-123");
- r = std.string.format("% d", 123);
- assert(r == " 123");
- r = std.string.format("% d", -123);
- assert(r == "-123");
-
- r = std.string.format("%%");
- assert(r == "%");
-
- r = std.string.format("%d", true);
- assert(r == "1");
- r = std.string.format("%d", false);
- assert(r == "0");
-
- r = std.string.format("%d", 'a');
- assert(r == "97");
- wchar wc = 'a';
- r = std.string.format("%d", wc);
- assert(r == "97");
- dchar dc = 'a';
- r = std.string.format("%d", dc);
- assert(r == "97");
-
- byte b = byte.max;
- r = std.string.format("%x", b);
- assert(r == "7f");
- r = std.string.format("%x", ++b);
- assert(r == "80");
- r = std.string.format("%x", ++b);
- assert(r == "81");
-
- short sh = short.max;
- r = std.string.format("%x", sh);
- assert(r == "7fff");
- r = std.string.format("%x", ++sh);
- assert(r == "8000");
- r = std.string.format("%x", ++sh);
- assert(r == "8001");
-
- i = int.max;
- r = std.string.format("%x", i);
- assert(r == "7fffffff");
- r = std.string.format("%x", ++i);
- assert(r == "80000000");
- r = std.string.format("%x", ++i);
- assert(r == "80000001");
-
- r = std.string.format("%x", 10);
- assert(r == "a");
- r = std.string.format("%X", 10);
- assert(r == "A");
- r = std.string.format("%x", 15);
- assert(r == "f");
- r = std.string.format("%X", 15);
- assert(r == "F");
-
- Object c = null;
- r = std.string.format(c);
- assert(r == "null");
-
- enum TestEnum
- {
- Value1, Value2
- }
- r = std.string.format("%s", TestEnum.Value2);
- assert(r == "1");
-
- char[5][int] aa = ([3:"hello", 4:"betty"]);
- r = std.string.format("%s", aa.values);
- assert(r == "[[h,e,l,l,o],[b,e,t,t,y]]");
- r = std.string.format("%s", aa);
- assert(r == "[3:[h,e,l,l,o],4:[b,e,t,t,y]]");
-
- static const dchar[] ds = ['a','b'];
- for (int j = 0; j < ds.length; ++j)
- {
- r = std.string.format(" %d", ds[j]);
- if (j == 0)
- assert(r == " 97");
- else
- assert(r == " 98");
- }
-
- r = std.string.format(">%14d<, ", 15, [1,2,3]);
- assert(r == "> 15<, [1,2,3]");
-}
-
+
+// Written in the D programming language.
+
+/**
+ * This module implements the workhorse functionality for string and I/O formatting.
+ * It's comparable to C99's vsprintf().
+ *
+ * Macros:
+ * WIKI = Phobos/StdFormat
+ */
+
+/*
+ * Copyright (C) 2004-2006 by Digital Mars, www.digitalmars.com
+ * Written by Walter Bright
+ * Modified for LLVMDC by Tomas Lindquist Olsen
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * o The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * o Altered source versions must be plainly marked as such, and must not
+ * be misrepresented as being the original software.
+ * o This notice may not be removed or altered from any source
+ * distribution.
+ */
+
+module std.format;
+
+//debug=format; // uncomment to turn on debugging printf's
+
+import std.stdarg; // caller will need va_list
+
+private import std.utf;
+private import std.c.stdlib;
+private import std.c.string;
+private import std.string;
+
+version (Windows)
+{
+ version (DigitalMars)
+ {
+ version = DigitalMarsC;
+ }
+}
+
+version (DigitalMarsC)
+{
+ // This is DMC's internal floating point formatting function
+ extern (C)
+ {
+ extern char* function(int c, int flags, int precision, real* pdval,
+ char* buf, int* psl, int width) __pfloatfmt;
+ }
+}
+else
+{
+ // Use C99 snprintf
+ extern (C) int snprintf(char* s, size_t n, char* format, ...);
+}
+
+/**********************************************************************
+ * Signals a mismatch between a format and its corresponding argument.
+ */
+class FormatError : Error
+{
+ private:
+
+ this()
+ {
+ super("std.format");
+ }
+
+ this(char[] msg)
+ {
+ super("std.format " ~ msg);
+ }
+}
+
+
+enum Mangle : char
+{
+ Tvoid = 'v',
+ Tbool = 'b',
+ Tbyte = 'g',
+ Tubyte = 'h',
+ Tshort = 's',
+ Tushort = 't',
+ Tint = 'i',
+ Tuint = 'k',
+ Tlong = 'l',
+ Tulong = 'm',
+ Tfloat = 'f',
+ Tdouble = 'd',
+ Treal = 'e',
+
+ Tifloat = 'o',
+ Tidouble = 'p',
+ Tireal = 'j',
+ Tcfloat = 'q',
+ Tcdouble = 'r',
+ Tcreal = 'c',
+
+ Tchar = 'a',
+ Twchar = 'u',
+ Tdchar = 'w',
+
+ Tarray = 'A',
+ Tsarray = 'G',
+ Taarray = 'H',
+ Tpointer = 'P',
+ Tfunction = 'F',
+ Tident = 'I',
+ Tclass = 'C',
+ Tstruct = 'S',
+ Tenum = 'E',
+ Ttypedef = 'T',
+ Tdelegate = 'D',
+
+ Tconst = 'x',
+ Tinvariant = 'y',
+}
+
+// return the TypeInfo for a primitive type and null otherwise.
+// This is required since for arrays of ints we only have the mangled
+// char to work from. If arrays always subclassed TypeInfo_Array this
+// routine could go away.
+private TypeInfo primitiveTypeInfo(Mangle m)
+{
+ TypeInfo ti;
+
+ switch (m)
+ {
+ case Mangle.Tvoid:
+ ti = typeid(void);break;
+ case Mangle.Tbool:
+ ti = typeid(bool);break;
+ case Mangle.Tbyte:
+ ti = typeid(byte);break;
+ case Mangle.Tubyte:
+ ti = typeid(ubyte);break;
+ case Mangle.Tshort:
+ ti = typeid(short);break;
+ case Mangle.Tushort:
+ ti = typeid(ushort);break;
+ case Mangle.Tint:
+ ti = typeid(int);break;
+ case Mangle.Tuint:
+ ti = typeid(uint);break;
+ case Mangle.Tlong:
+ ti = typeid(long);break;
+ case Mangle.Tulong:
+ ti = typeid(ulong);break;
+ case Mangle.Tfloat:
+ ti = typeid(float);break;
+ case Mangle.Tdouble:
+ ti = typeid(double);break;
+ case Mangle.Treal:
+ ti = typeid(real);break;
+ case Mangle.Tifloat:
+ ti = typeid(ifloat);break;
+ case Mangle.Tidouble:
+ ti = typeid(idouble);break;
+ case Mangle.Tireal:
+ ti = typeid(ireal);break;
+ case Mangle.Tcfloat:
+ ti = typeid(cfloat);break;
+ case Mangle.Tcdouble:
+ ti = typeid(cdouble);break;
+ case Mangle.Tcreal:
+ ti = typeid(creal);break;
+ case Mangle.Tchar:
+ ti = typeid(char);break;
+ case Mangle.Twchar:
+ ti = typeid(wchar);break;
+ case Mangle.Tdchar:
+ ti = typeid(dchar);
+ default:
+ ti = null;
+ }
+ return ti;
+}
+
+/************************************
+ * Interprets variadic argument list pointed to by argptr whose types are given
+ * by arguments[], formats them according to embedded format strings in the
+ * variadic argument list, and sends the resulting characters to putc.
+ *
+ * The variadic arguments are consumed in order.
+ * Each is formatted into a sequence of chars, using the default format
+ * specification for its type, and the
+ * characters are sequentially passed to putc.
+ * If a char[], wchar[], or dchar[]
+ * argument is encountered, it is interpreted as a format string. As many
+ * arguments as specified in the format string are consumed and formatted
+ * according to the format specifications in that string and passed to putc. If
+ * there are too few remaining arguments, a FormatError is thrown. If there are
+ * more remaining arguments than needed by the format specification, the default
+ * processing of arguments resumes until they are all consumed.
+ *
+ * Params:
+ * putc = Output is sent do this delegate, character by character.
+ * arguments = Array of TypeInfo's, one for each argument to be formatted.
+ * argptr = Points to variadic argument list.
+ *
+ * Throws:
+ * Mismatched arguments and formats result in a FormatError being thrown.
+ *
+ * Format_String:
+ * $(I Format strings)
+ * consist of characters interspersed with
+ * $(I format specifications). Characters are simply copied
+ * to the output (such as putc) after any necessary conversion
+ * to the corresponding UTF-8 sequence.
+ *
+ * A $(I format specification) starts with a '%' character,
+ * and has the following grammar:
+
+
+$(I FormatSpecification):
+ $(B '%%')
+ $(B '%') $(I Flags) $(I Width) $(I Precision) $(I FormatChar)
+
+$(I Flags):
+ $(I empty)
+ $(B '-') $(I Flags)
+ $(B '+') $(I Flags)
+ $(B '#') $(I Flags)
+ $(B '0') $(I Flags)
+ $(B ' ') $(I Flags)
+
+$(I Width):
+ $(I empty)
+ $(I Integer)
+ $(B '*')
+
+$(I Precision):
+ $(I empty)
+ $(B '.')
+ $(B '.') $(I Integer)
+ $(B '.*')
+
+$(I Integer):
+ $(I Digit)
+ $(I Digit) $(I Integer)
+
+$(I Digit):
+ $(B '0')
+ $(B '1')
+ $(B '2')
+ $(B '3')
+ $(B '4')
+ $(B '5')
+ $(B '6')
+ $(B '7')
+ $(B '8')
+ $(B '9')
+
+$(I FormatChar):
+ $(B 's')
+ $(B 'b')
+ $(B 'd')
+ $(B 'o')
+ $(B 'x')
+ $(B 'X')
+ $(B 'e')
+ $(B 'E')
+ $(B 'f')
+ $(B 'F')
+ $(B 'g')
+ $(B 'G')
+ $(B 'a')
+ $(B 'A')
+
+
+ - $(I Flags)
+
+ - $(B '-')
+
-
+ Left justify the result in the field.
+ It overrides any $(B 0) flag.
+
+
- $(B '+')
+
- Prefix positive numbers in a signed conversion with a $(B +).
+ It overrides any $(I space) flag.
+
+
- $(B '#')
+
- Use alternative formatting:
+
+ - For $(B 'o'):
+
- Add to precision as necessary so that the first digit
+ of the octal formatting is a '0', even if both the argument
+ and the $(I Precision) are zero.
+
- For $(B 'x') ($(B 'X')):
+
- If non-zero, prefix result with $(B 0x) ($(B 0X)).
+
- For floating point formatting:
+
- Always insert the decimal point.
+
- For $(B 'g') ($(B 'G')):
+
- Do not elide trailing zeros.
+
+
+ - $(B '0')
+
- For integer and floating point formatting when not nan or
+ infinity, use leading zeros
+ to pad rather than spaces.
+ Ignore if there's a $(I Precision).
+
+
- $(B ' ')
+
- Prefix positive numbers in a signed conversion with a space.
+
+
+ - $(I Width)
+
-
+ Specifies the minimum field width.
+ If the width is a $(B *), the next argument, which must be
+ of type $(B int), is taken as the width.
+ If the width is negative, it is as if the $(B -) was given
+ as a $(I Flags) character.
+
+
- $(I Precision)
+
- Gives the precision for numeric conversions.
+ If the precision is a $(B *), the next argument, which must be
+ of type $(B int), is taken as the precision. If it is negative,
+ it is as if there was no $(I Precision).
+
+
- $(I FormatChar)
+
-
+
+ - $(B 's')
+
- The corresponding argument is formatted in a manner consistent
+ with its type:
+
+ - $(B bool)
+
- The result is 'true' or 'false'.
+
- integral types
+
- The $(B %d) format is used.
+
- floating point types
+
- The $(B %g) format is used.
+
- string types
+
- The result is the string converted to UTF-8.
+ A $(I Precision) specifies the maximum number of characters
+ to use in the result.
+
- classes derived from $(B Object)
+
- The result is the string returned from the class instance's
+ $(B .toString()) method.
+ A $(I Precision) specifies the maximum number of characters
+ to use in the result.
+
- non-string static and dynamic arrays
+
- The result is [s0, s1, ...]
+ where sk is the kth element
+ formatted with the default format.
+
+
+ - $(B 'b','d','o','x','X')
+
- The corresponding argument must be an integral type
+ and is formatted as an integer. If the argument is a signed type
+ and the $(I FormatChar) is $(B d) it is converted to
+ a signed string of characters, otherwise it is treated as
+ unsigned. An argument of type $(B bool) is formatted as '1'
+ or '0'. The base used is binary for $(B b), octal for $(B o),
+ decimal
+ for $(B d), and hexadecimal for $(B x) or $(B X).
+ $(B x) formats using lower case letters, $(B X) uppercase.
+ If there are fewer resulting digits than the $(I Precision),
+ leading zeros are used as necessary.
+ If the $(I Precision) is 0 and the number is 0, no digits
+ result.
+
+
- $(B 'e','E')
+
- A floating point number is formatted as one digit before
+ the decimal point, $(I Precision) digits after, the $(I FormatChar),
+ ±, followed by at least a two digit exponent: $(I d.dddddd)e$(I ±dd).
+ If there is no $(I Precision), six
+ digits are generated after the decimal point.
+ If the $(I Precision) is 0, no decimal point is generated.
+
+
- $(B 'f','F')
+
- A floating point number is formatted in decimal notation.
+ The $(I Precision) specifies the number of digits generated
+ after the decimal point. It defaults to six. At least one digit
+ is generated before the decimal point. If the $(I Precision)
+ is zero, no decimal point is generated.
+
+
- $(B 'g','G')
+
- A floating point number is formatted in either $(B e) or
+ $(B f) format for $(B g); $(B E) or $(B F) format for
+ $(B G).
+ The $(B f) format is used if the exponent for an $(B e) format
+ is greater than -5 and less than the $(I Precision).
+ The $(I Precision) specifies the number of significant
+ digits, and defaults to six.
+ Trailing zeros are elided after the decimal point, if the fractional
+ part is zero then no decimal point is generated.
+
+
- $(B 'a','A')
+
- A floating point number is formatted in hexadecimal
+ exponential notation 0x$(I h.hhhhhh)p$(I ±d).
+ There is one hexadecimal digit before the decimal point, and as
+ many after as specified by the $(I Precision).
+ If the $(I Precision) is zero, no decimal point is generated.
+ If there is no $(I Precision), as many hexadecimal digits as
+ necessary to exactly represent the mantissa are generated.
+ The exponent is written in as few digits as possible,
+ but at least one, is in decimal, and represents a power of 2 as in
+ $(I h.hhhhhh)*2$(I ±d).
+ The exponent for zero is zero.
+ The hexadecimal digits, x and p are in upper case if the
+ $(I FormatChar) is upper case.
+
+
+ Floating point NaN's are formatted as $(B nan) if the
+ $(I FormatChar) is lower case, or $(B NAN) if upper.
+ Floating point infinities are formatted as $(B inf) or
+ $(B infinity) if the
+ $(I FormatChar) is lower case, or $(B INF) or $(B INFINITY) if upper.
+
+
+Example:
+
+-------------------------
+import std.c.stdio;
+import std.format;
+
+void formattedPrint(...)
+{
+ void putc(char c)
+ {
+ fputc(c, stdout);
+ }
+
+ std.format.doFormat(&putc, _arguments, _argptr);
+}
+
+...
+
+int x = 27;
+// prints 'The answer is 27:6'
+formattedPrint("The answer is %s:", x, 6);
+------------------------
+ */
+
+void doFormat(void delegate(dchar) putc, TypeInfo[] arguments, void* argptr)
+{ //printf("doFormat(...)\n");
+ int j;
+ TypeInfo ti;
+ Mangle m;
+ uint flags;
+ int field_width;
+ int precision;
+
+ enum : uint
+ {
+ FLdash = 1,
+ FLplus = 2,
+ FLspace = 4,
+ FLhash = 8,
+ FLlngdbl = 0x20,
+ FL0pad = 0x40,
+ FLprecision = 0x80,
+ }
+
+ static TypeInfo skipCI(TypeInfo valti)
+ {
+ while (1)
+ {
+ if (valti.classinfo.name.length == 18 &&
+ valti.classinfo.name[9..18] == "Invariant")
+ valti = (cast(TypeInfo_Invariant)valti).next;
+ else if (valti.classinfo.name.length == 14 &&
+ valti.classinfo.name[9..14] == "Const")
+ valti = (cast(TypeInfo_Const)valti).next;
+ else
+ break;
+ }
+ return valti;
+ }
+
+ void formatArg(char fc)
+ {
+ bool vbit;
+ ulong vnumber;
+ char vchar;
+ dchar vdchar;
+ Object vobject;
+ real vreal;
+ creal vcreal;
+ Mangle m2;
+ int signed = 0;
+ uint base = 10;
+ int uc;
+ char[ulong.sizeof * 8] tmpbuf; // long enough to print long in binary
+ char* prefix = "";
+ string s;
+
+ void putstr(char[] s)
+ {
+ //printf("flags = 0x%x\n", flags);
+ int prepad = 0;
+ int postpad = 0;
+ int padding = field_width - (strlen(prefix) + s.length);
+ if (padding > 0)
+ {
+ if (flags & FLdash)
+ postpad = padding;
+ else
+ prepad = padding;
+ }
+
+ if (flags & FL0pad)
+ {
+ while (*prefix)
+ putc(*prefix++);
+ while (prepad--)
+ putc('0');
+ }
+ else
+ {
+ while (prepad--)
+ putc(' ');
+ while (*prefix)
+ putc(*prefix++);
+ }
+
+ foreach (dchar c; s)
+ putc(c);
+
+ while (postpad--)
+ putc(' ');
+ }
+
+ void putreal(real v)
+ {
+ //printf("putreal %Lg\n", vreal); // no 80 bit float
+ //printf("putreal %g\n", vreal);
+
+ switch (fc)
+ {
+ case 's':
+ fc = 'g';
+ break;
+
+ case 'f', 'F', 'e', 'E', 'g', 'G', 'a', 'A':
+ break;
+
+ default:
+ //printf("fc = '%c'\n", fc);
+ Lerror:
+ throw new FormatError("floating");
+ }
+ version (DigitalMarsC)
+ {
+ int sl;
+ char[] fbuf = tmpbuf;
+ if (!(flags & FLprecision))
+ precision = 6;
+ while (1)
+ {
+ sl = fbuf.length;
+ prefix = (*__pfloatfmt)(fc, flags | FLlngdbl,
+ precision, &v, cast(char*)fbuf, &sl, field_width);
+ if (sl != -1)
+ break;
+ sl = fbuf.length * 2;
+ fbuf = (cast(char*)/*alloca*/malloc(sl * char.sizeof))[0 .. sl];
+ }
+ putstr(fbuf[0 .. sl]);
+ }
+ else
+ {
+ int sl;
+ char[] fbuf = tmpbuf;
+ char[12] format;
+ format[0] = '%';
+ int i = 1;
+ if (flags & FLdash)
+ format[i++] = '-';
+ if (flags & FLplus)
+ format[i++] = '+';
+ if (flags & FLspace)
+ format[i++] = ' ';
+ if (flags & FLhash)
+ format[i++] = '#';
+ if (flags & FL0pad)
+ format[i++] = '0';
+ format[i + 0] = '*';
+ format[i + 1] = '.';
+ format[i + 2] = '*';
+ format[i + 3] = fc;
+ format[i + 4] = 0;
+ //format[i + 3] = 'L'; // no 80 bit yet
+ //format[i + 4] = fc;
+ //format[i + 5] = 0;
+ if (!(flags & FLprecision))
+ precision = -1;
+ while (1)
+ { int n;
+
+ sl = fbuf.length;
+ n = snprintf(fbuf.ptr, sl, format.ptr, field_width, precision, v);
+ //printf("format = '%s', n = %d\n", cast(char*)format, n);
+ if (n >= 0 && n < sl)
+ { sl = n;
+ break;
+ }
+ if (n < 0)
+ sl = sl * 2;
+ else
+ sl = n + 1;
+ fbuf = (cast(char*)/*alloca*/malloc(sl * char.sizeof))[0 .. sl];
+ }
+ putstr(fbuf[0 .. sl]);
+ }
+ return;
+ }
+
+ static Mangle getMan(TypeInfo ti)
+ {
+ auto m = cast(Mangle)ti.classinfo.name[9];
+ if (ti.classinfo.name.length == 20 &&
+ ti.classinfo.name[9..20] == "StaticArray")
+ m = cast(Mangle)'G';
+ return m;
+ }
+
+ void putArray(void* p, size_t len, TypeInfo valti)
+ {
+ //printf("\nputArray(len = %u), tsize = %u\n", len, valti.tsize());
+ putc('[');
+ valti = skipCI(valti);
+ size_t tsize = valti.tsize();
+ auto argptrSave = argptr;
+ auto tiSave = ti;
+ auto mSave = m;
+ ti = valti;
+ auto className = valti.classinfo.name;
+ printf("\n%.*s\n", className.length, className.ptr);
+ m = getMan(valti);
+ while (len--)
+ {
+ //doFormat(putc, (&valti)[0 .. 1], p);
+ argptr = p;
+ formatArg('s');
+
+ p += tsize;
+ if (len > 0) putc(',');
+ }
+ m = mSave;
+ ti = tiSave;
+ argptr = argptrSave;
+ putc(']');
+ }
+
+ void putAArray(ubyte[long] vaa, TypeInfo valti, TypeInfo keyti)
+ {
+ putc('[');
+ bool comma=false;
+ auto argptrSave = argptr;
+ auto tiSave = ti;
+ auto mSave = m;
+ valti = skipCI(valti);
+ keyti = skipCI(keyti);
+ foreach(inout fakevalue; vaa)
+ {
+ if (comma) putc(',');
+ comma = true;
+ // the key comes before the value
+ ubyte* key = &fakevalue - long.sizeof;
+
+ //doFormat(putc, (&keyti)[0..1], key);
+ argptr = key;
+ ti = keyti;
+ m = getMan(keyti);
+ formatArg('s');
+
+ putc(':');
+ auto keysize = keyti.tsize;
+ keysize = (keysize + 3) & ~3;
+ ubyte* value = key + keysize;
+ //doFormat(putc, (&valti)[0..1], value);
+ argptr = value;
+ ti = valti;
+ m = getMan(valti);
+ formatArg('s');
+ }
+ m = mSave;
+ ti = tiSave;
+ argptr = argptrSave;
+ putc(']');
+ }
+
+ //printf("formatArg(fc = '%c', m = '%c')\n", fc, m);
+ switch (m)
+ {
+ case Mangle.Tbool:
+ vbit = va_arg!(bool)(argptr);
+ if (fc != 's')
+ { vnumber = vbit;
+ goto Lnumber;
+ }
+ putstr(vbit ? "true" : "false");
+ return;
+
+
+ case Mangle.Tchar:
+ vchar = va_arg!(char)(argptr);
+ if (fc != 's')
+ { vnumber = vchar;
+ goto Lnumber;
+ }
+ L2:
+ putstr((&vchar)[0 .. 1]);
+ return;
+
+ case Mangle.Twchar:
+ vdchar = va_arg!(wchar)(argptr);
+ goto L1;
+
+ case Mangle.Tdchar:
+ vdchar = va_arg!(dchar)(argptr);
+ L1:
+ if (fc != 's')
+ { vnumber = vdchar;
+ goto Lnumber;
+ }
+ if (vdchar <= 0x7F)
+ { vchar = cast(char)vdchar;
+ goto L2;
+ }
+ else
+ { if (!isValidDchar(vdchar))
+ throw new UtfException("invalid dchar in format", 0);
+ char[4] vbuf;
+ putstr(toUTF8(vbuf, vdchar));
+ }
+ return;
+
+
+ case Mangle.Tbyte:
+ signed = 1;
+ vnumber = va_arg!(byte)(argptr);
+ goto Lnumber;
+
+ case Mangle.Tubyte:
+ vnumber = va_arg!(ubyte)(argptr);
+ goto Lnumber;
+
+ case Mangle.Tshort:
+ signed = 1;
+ vnumber = va_arg!(short)(argptr);
+ goto Lnumber;
+
+ case Mangle.Tushort:
+ vnumber = va_arg!(ushort)(argptr);
+ goto Lnumber;
+
+ case Mangle.Tint:
+ signed = 1;
+ vnumber = va_arg!(int)(argptr);
+ goto Lnumber;
+
+ case Mangle.Tuint:
+ Luint:
+ vnumber = va_arg!(uint)(argptr);
+ goto Lnumber;
+
+ case Mangle.Tlong:
+ signed = 1;
+ vnumber = cast(ulong)va_arg!(long)(argptr);
+ goto Lnumber;
+
+ case Mangle.Tulong:
+ Lulong:
+ vnumber = va_arg!(ulong)(argptr);
+ goto Lnumber;
+
+ case Mangle.Tclass:
+ vobject = va_arg!(Object)(argptr);
+ if (vobject is null)
+ s = "null";
+ else
+ s = vobject.toString();
+ goto Lputstr;
+
+ case Mangle.Tpointer:
+ vnumber = cast(ulong)va_arg!(void*)(argptr);
+ uc = 1;
+ flags |= FL0pad;
+ if (!(flags & FLprecision))
+ { flags |= FLprecision;
+ precision = (void*).sizeof;
+ }
+ base = 16;
+ goto Lnumber;
+
+
+ case Mangle.Tfloat:
+ case Mangle.Tifloat:
+ if (fc == 'x' || fc == 'X')
+ goto Luint;
+ vreal = va_arg!(float)(argptr);
+ goto Lreal;
+
+ case Mangle.Tdouble:
+ case Mangle.Tidouble:
+ if (fc == 'x' || fc == 'X')
+ goto Lulong;
+ vreal = va_arg!(double)(argptr);
+ goto Lreal;
+
+ case Mangle.Treal:
+ case Mangle.Tireal:
+ vreal = va_arg!(real)(argptr);
+ goto Lreal;
+
+
+ case Mangle.Tcfloat:
+ vcreal = va_arg!(cfloat)(argptr);
+ goto Lcomplex;
+
+ case Mangle.Tcdouble:
+ vcreal = va_arg!(cdouble)(argptr);
+ goto Lcomplex;
+
+ case Mangle.Tcreal:
+ vcreal = va_arg!(creal)(argptr);
+ goto Lcomplex;
+
+ case Mangle.Tsarray:
+ //printf("static array\n");
+ putArray(argptr, (cast(TypeInfo_StaticArray)ti).len, (cast(TypeInfo_StaticArray)ti).next);
+ return;
+
+ case Mangle.Tarray:
+ //printf("dynamic array\n");
+ int mi = 10;
+ if (ti.classinfo.name.length == 14 &&
+ ti.classinfo.name[9..14] == "Array")
+ { // array of non-primitive types
+ TypeInfo tn = (cast(TypeInfo_Array)ti).next;
+ tn = skipCI(tn);
+ switch (cast(Mangle)tn.classinfo.name[9])
+ {
+ case Mangle.Tchar: goto LarrayChar;
+ case Mangle.Twchar: goto LarrayWchar;
+ case Mangle.Tdchar: goto LarrayDchar;
+ default:
+ break;
+ }
+ void[] va = va_arg!(void[])(argptr);
+ putArray(va.ptr, va.length, tn);
+ return;
+ }
+ if (ti.classinfo.name.length == 25 &&
+ ti.classinfo.name[9..25] == "AssociativeArray")
+ { // associative array
+ ubyte[long] vaa = va_arg!(ubyte[long])(argptr);
+ putAArray(vaa,
+ (cast(TypeInfo_AssociativeArray)ti).next,
+ (cast(TypeInfo_AssociativeArray)ti).key);
+ return;
+ }
+
+ //printf("primitive type\n");
+ while (1)
+ {
+ m2 = cast(Mangle)ti.classinfo.name[mi];
+ switch (m2)
+ {
+ case Mangle.Tchar:
+ LarrayChar:
+ s = va_arg!(char[])(argptr);
+ goto Lputstr;
+
+ case Mangle.Twchar:
+ LarrayWchar:
+ wchar[] sw = va_arg!(wchar[])(argptr);
+ s = toUTF8(sw);
+ goto Lputstr;
+
+ case Mangle.Tdchar:
+ LarrayDchar:
+ dchar[] sd = va_arg!(dchar[])(argptr);
+ s = toUTF8(sd);
+ Lputstr:
+ if (fc != 's')
+ throw new FormatError("string");
+ if (flags & FLprecision && precision < s.length)
+ s = s[0 .. precision];
+ putstr(s);
+ break;
+
+ case Mangle.Tconst:
+ case Mangle.Tinvariant:
+ mi++;
+ continue;
+
+ default:
+ //printf("primitive type default handling\n");
+ TypeInfo ti2 = primitiveTypeInfo(m2);
+ if (!ti2)
+ goto Lerror;
+ void[] va = va_arg!(void[])(argptr);
+ putArray(va.ptr, va.length, ti2);
+ }
+ return;
+ }
+
+ case Mangle.Ttypedef:
+ ti = (cast(TypeInfo_Typedef)ti).base;
+ m = cast(Mangle)ti.classinfo.name[9];
+ formatArg(fc);
+ return;
+
+ case Mangle.Tenum:
+ ti = (cast(TypeInfo_Enum)ti).base;
+ m = cast(Mangle)ti.classinfo.name[9];
+ formatArg(fc);
+ return;
+
+ case Mangle.Tstruct:
+ { TypeInfo_Struct tis = cast(TypeInfo_Struct)ti;
+ if (tis.xtoString is null)
+ throw new FormatError("Can't convert " ~ tis.toString() ~ " to string: \"string toString()\" not defined");
+ s = tis.xtoString(argptr);
+ argptr += (tis.tsize() + 3) & ~3;
+ goto Lputstr;
+ }
+
+ default:
+ goto Lerror;
+ }
+
+ Lnumber:
+ switch (fc)
+ {
+ case 's':
+ case 'd':
+ if (signed)
+ { if (cast(long)vnumber < 0)
+ { prefix = "-";
+ vnumber = -vnumber;
+ }
+ else if (flags & FLplus)
+ prefix = "+";
+ else if (flags & FLspace)
+ prefix = " ";
+ }
+ break;
+
+ case 'b':
+ signed = 0;
+ base = 2;
+ break;
+
+ case 'o':
+ signed = 0;
+ base = 8;
+ break;
+
+ case 'X':
+ uc = 1;
+ if (flags & FLhash && vnumber)
+ prefix = "0X";
+ signed = 0;
+ base = 16;
+ break;
+
+ case 'x':
+ if (flags & FLhash && vnumber)
+ prefix = "0x";
+ signed = 0;
+ base = 16;
+ break;
+
+ default:
+ goto Lerror;
+ }
+
+ if (!signed)
+ {
+ switch (m)
+ {
+ case Mangle.Tbyte:
+ vnumber &= 0xFF;
+ break;
+
+ case Mangle.Tshort:
+ vnumber &= 0xFFFF;
+ break;
+
+ case Mangle.Tint:
+ vnumber &= 0xFFFFFFFF;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if (flags & FLprecision && fc != 'p')
+ flags &= ~FL0pad;
+
+ if (vnumber < base)
+ {
+ if (vnumber == 0 && precision == 0 && flags & FLprecision &&
+ !(fc == 'o' && flags & FLhash))
+ {
+ putstr(null);
+ return;
+ }
+ if (precision == 0 || !(flags & FLprecision))
+ { vchar = cast(char)('0' + vnumber);
+ if (vnumber < 10)
+ vchar = cast(char)('0' + vnumber);
+ else
+ vchar = cast(char)((uc ? 'A' - 10 : 'a' - 10) + vnumber);
+ goto L2;
+ }
+ }
+
+ int n = tmpbuf.length;
+ char c;
+ int hexoffset = uc ? ('A' - ('9' + 1)) : ('a' - ('9' + 1));
+
+ while (vnumber)
+ {
+ c = cast(char)((vnumber % base) + '0');
+ if (c > '9')
+ c += hexoffset;
+ vnumber /= base;
+ tmpbuf[--n] = c;
+ }
+ if (tmpbuf.length - n < precision && precision < tmpbuf.length)
+ {
+ int m = tmpbuf.length - precision;
+ tmpbuf[m .. n] = '0';
+ n = m;
+ }
+ else if (flags & FLhash && fc == 'o')
+ prefix = "0";
+ putstr(tmpbuf[n .. tmpbuf.length]);
+ return;
+
+ Lreal:
+ putreal(vreal);
+ return;
+
+ Lcomplex:
+ putreal(vcreal.re);
+ putc('+');
+ putreal(vcreal.im);
+ putc('i');
+ return;
+
+ Lerror:
+ throw new FormatError("formatArg");
+ }
+
+
+ //printf("arguments length: %u\n", arguments.length);
+ for (j = 0; j < arguments.length; )
+ { ti = arguments[j++];
+ //printf("test1: '%.*s' %d\n", ti.classinfo.name.length, ti.classinfo.name.ptr, ti.classinfo.name.length);
+ //ti.print();
+
+ flags = 0;
+ precision = 0;
+ field_width = 0;
+
+ ti = skipCI(ti);
+ int mi = 9;
+ do
+ {
+ if (ti.classinfo.name.length <= mi)
+ goto Lerror;
+ m = cast(Mangle)ti.classinfo.name[mi++];
+ } while (m == Mangle.Tconst || m == Mangle.Tinvariant);
+
+ if (m == Mangle.Tarray)
+ {
+ if (ti.classinfo.name.length == 14 &&
+ ti.classinfo.name[9..14] == "Array")
+ {
+ TypeInfo tn = (cast(TypeInfo_Array)ti).next;
+ tn = skipCI(tn);
+ switch (cast(Mangle)tn.classinfo.name[9])
+ {
+ case Mangle.Tchar:
+ case Mangle.Twchar:
+ case Mangle.Tdchar:
+ ti = tn;
+ mi = 9;
+ break;
+ default:
+ break;
+ }
+ }
+ L1:
+ Mangle m2 = cast(Mangle)ti.classinfo.name[mi];
+ string fmt; // format string
+ wstring wfmt;
+ dstring dfmt;
+
+ /* For performance reasons, this code takes advantage of the
+ * fact that most format strings will be ASCII, and that the
+ * format specifiers are always ASCII. This means we only need
+ * to deal with UTF in a couple of isolated spots.
+ */
+
+ switch (m2)
+ {
+ case Mangle.Tchar:
+ fmt = va_arg!(char[])(argptr);
+ break;
+
+ case Mangle.Twchar:
+ wfmt = va_arg!(wchar[])(argptr);
+ fmt = toUTF8(wfmt);
+ break;
+
+ case Mangle.Tdchar:
+ dfmt = va_arg!(dchar[])(argptr);
+ fmt = toUTF8(dfmt);
+ break;
+
+ case Mangle.Tconst:
+ case Mangle.Tinvariant:
+ mi++;
+ goto L1;
+
+ default:
+ formatArg('s');
+ continue;
+ }
+
+ for (size_t i = 0; i < fmt.length; )
+ { dchar c = fmt[i++];
+
+ dchar getFmtChar()
+ { // Valid format specifier characters will never be UTF
+ if (i == fmt.length)
+ throw new FormatError("invalid specifier");
+ return fmt[i++];
+ }
+
+ int getFmtInt()
+ { int n;
+
+ while (1)
+ {
+ n = n * 10 + (c - '0');
+ if (n < 0) // overflow
+ throw new FormatError("int overflow");
+ c = getFmtChar();
+ if (c < '0' || c > '9')
+ break;
+ }
+ return n;
+ }
+
+ int getFmtStar()
+ { Mangle m;
+ TypeInfo ti;
+
+ if (j == arguments.length)
+ throw new FormatError("too few arguments");
+ ti = arguments[j++];
+ m = cast(Mangle)ti.classinfo.name[9];
+ if (m != Mangle.Tint)
+ throw new FormatError("int argument expected");
+ return va_arg!(int)(argptr);
+ }
+
+ if (c != '%')
+ {
+ if (c > 0x7F) // if UTF sequence
+ {
+ i--; // back up and decode UTF sequence
+ c = std.utf.decode(fmt, i);
+ }
+ Lputc:
+ putc(c);
+ continue;
+ }
+
+ // Get flags {-+ #}
+ flags = 0;
+ while (1)
+ {
+ c = getFmtChar();
+ switch (c)
+ {
+ case '-': flags |= FLdash; continue;
+ case '+': flags |= FLplus; continue;
+ case ' ': flags |= FLspace; continue;
+ case '#': flags |= FLhash; continue;
+ case '0': flags |= FL0pad; continue;
+
+ case '%': if (flags == 0)
+ goto Lputc;
+ default: break;
+ }
+ break;
+ }
+
+ // Get field width
+ field_width = 0;
+ if (c == '*')
+ {
+ field_width = getFmtStar();
+ if (field_width < 0)
+ { flags |= FLdash;
+ field_width = -field_width;
+ }
+
+ c = getFmtChar();
+ }
+ else if (c >= '0' && c <= '9')
+ field_width = getFmtInt();
+
+ if (flags & FLplus)
+ flags &= ~FLspace;
+ if (flags & FLdash)
+ flags &= ~FL0pad;
+
+ // Get precision
+ precision = 0;
+ if (c == '.')
+ { flags |= FLprecision;
+ //flags &= ~FL0pad;
+
+ c = getFmtChar();
+ if (c == '*')
+ {
+ precision = getFmtStar();
+ if (precision < 0)
+ { precision = 0;
+ flags &= ~FLprecision;
+ }
+
+ c = getFmtChar();
+ }
+ else if (c >= '0' && c <= '9')
+ precision = getFmtInt();
+ }
+
+ if (j == arguments.length)
+ goto Lerror;
+ ti = arguments[j++];
+ ti = skipCI(ti);
+ mi = 9;
+ do
+ {
+ m = cast(Mangle)ti.classinfo.name[mi++];
+ } while (m == Mangle.Tconst || m == Mangle.Tinvariant);
+
+ if (c > 0x7F) // if UTF sequence
+ goto Lerror; // format specifiers can't be UTF
+ formatArg(cast(char)c);
+ }
+ }
+ else
+ {
+ formatArg('s');
+ }
+ }
+ return;
+
+Lerror:
+ throw new FormatError();
+}
+
+/* ======================== Unit Tests ====================================== */
+
+unittest
+{
+ int i;
+ string s;
+
+ debug(format) printf("std.format.format.unittest\n");
+
+ s = std.string.format("hello world! %s %s ", true, 57, 1_000_000_000, 'x', " foo");
+ assert(s == "hello world! true 57 1000000000x foo");
+
+ s = std.string.format(1.67, " %A ", -1.28, float.nan);
+ /* The host C library is used to format floats.
+ * C99 doesn't specify what the hex digit before the decimal point
+ * is for %A.
+ */
+ version (linux)
+ assert(s == "1.67 -0XA.3D70A3D70A3D8P-3 nan");
+ else
+ assert(s == "1.67 -0X1.47AE147AE147BP+0 nan");
+
+ s = std.string.format("%x %X", 0x1234AF, 0xAFAFAFAF);
+ assert(s == "1234af AFAFAFAF");
+
+ s = std.string.format("%b %o", 0x1234AF, 0xAFAFAFAF);
+ assert(s == "100100011010010101111 25753727657");
+
+ s = std.string.format("%d %s", 0x1234AF, 0xAFAFAFAF);
+ assert(s == "1193135 2947526575");
+
+ s = std.string.format("%s", 1.2 + 3.4i);
+ assert(s == "1.2+3.4i");
+
+ s = std.string.format("%x %X", 1.32, 6.78f);
+ assert(s == "3ff51eb851eb851f 40D8F5C3");
+
+ s = std.string.format("%#06.*f",2,12.345);
+ assert(s == "012.35");
+
+ s = std.string.format("%#0*.*f",6,2,12.345);
+ assert(s == "012.35");
+
+ s = std.string.format("%7.4g:", 12.678);
+ assert(s == " 12.68:");
+
+ s = std.string.format("%7.4g:", 12.678L);
+ assert(s == " 12.68:");
+
+ s = std.string.format("%04f|%05d|%#05x|%#5x",-4.,-10,1,1);
+ assert(s == "-4.000000|-0010|0x001| 0x1");
+
+ i = -10;
+ s = std.string.format("%d|%3d|%03d|%1d|%01.4f",i,i,i,i,cast(double) i);
+ assert(s == "-10|-10|-10|-10|-10.0000");
+
+ i = -5;
+ s = std.string.format("%d|%3d|%03d|%1d|%01.4f",i,i,i,i,cast(double) i);
+ assert(s == "-5| -5|-05|-5|-5.0000");
+
+ i = 0;
+ s = std.string.format("%d|%3d|%03d|%1d|%01.4f",i,i,i,i,cast(double) i);
+ assert(s == "0| 0|000|0|0.0000");
+
+ i = 5;
+ s = std.string.format("%d|%3d|%03d|%1d|%01.4f",i,i,i,i,cast(double) i);
+ assert(s == "5| 5|005|5|5.0000");
+
+ i = 10;
+ s = std.string.format("%d|%3d|%03d|%1d|%01.4f",i,i,i,i,cast(double) i);
+ assert(s == "10| 10|010|10|10.0000");
+
+ s = std.string.format("%.0d", 0);
+ assert(s == "");
+
+ s = std.string.format("%.g", .34);
+ assert(s == "0.3");
+
+ s = std.string.format("%.0g", .34);
+ assert(s == "0.3");
+
+ s = std.string.format("%.2g", .34);
+ assert(s == "0.34");
+
+ s = std.string.format("%0.0008f", 1e-08);
+ assert(s == "0.00000001");
+
+ s = std.string.format("%0.0008f", 1e-05);
+ assert(s == "0.00001000");
+
+ s = "helloworld";
+ string r;
+ r = std.string.format("%.2s", s[0..5]);
+ assert(r == "he");
+ r = std.string.format("%.20s", s[0..5]);
+ assert(r == "hello");
+ r = std.string.format("%8s", s[0..5]);
+ assert(r == " hello");
+
+ byte[] arrbyte = new byte[4];
+ arrbyte[0] = 100;
+ arrbyte[1] = -99;
+ arrbyte[3] = 0;
+ r = std.string.format(arrbyte);
+ assert(r == "[100,-99,0,0]");
+
+ ubyte[] arrubyte = new ubyte[4];
+ arrubyte[0] = 100;
+ arrubyte[1] = 200;
+ arrubyte[3] = 0;
+ r = std.string.format(arrubyte);
+ assert(r == "[100,200,0,0]");
+
+ short[] arrshort = new short[4];
+ arrshort[0] = 100;
+ arrshort[1] = -999;
+ arrshort[3] = 0;
+ r = std.string.format(arrshort);
+ assert(r == "[100,-999,0,0]");
+ r = std.string.format("%s",arrshort);
+ assert(r == "[100,-999,0,0]");
+
+ ushort[] arrushort = new ushort[4];
+ arrushort[0] = 100;
+ arrushort[1] = 20_000;
+ arrushort[3] = 0;
+ r = std.string.format(arrushort);
+ assert(r == "[100,20000,0,0]");
+
+ int[] arrint = new int[4];
+ arrint[0] = 100;
+ arrint[1] = -999;
+ arrint[3] = 0;
+ r = std.string.format(arrint);
+ assert(r == "[100,-999,0,0]");
+ r = std.string.format("%s",arrint);
+ assert(r == "[100,-999,0,0]");
+
+ long[] arrlong = new long[4];
+ arrlong[0] = 100;
+ arrlong[1] = -999;
+ arrlong[3] = 0;
+ r = std.string.format(arrlong);
+ assert(r == "[100,-999,0,0]");
+ r = std.string.format("%s",arrlong);
+ assert(r == "[100,-999,0,0]");
+
+ ulong[] arrulong = new ulong[4];
+ arrulong[0] = 100;
+ arrulong[1] = 999;
+ arrulong[3] = 0;
+ r = std.string.format(arrulong);
+ assert(r == "[100,999,0,0]");
+
+ string[] arr2 = new string[4];
+ arr2[0] = "hello";
+ arr2[1] = "world";
+ arr2[3] = "foo";
+ r = std.string.format(arr2);
+ assert(r == "[hello,world,,foo]");
+
+ r = std.string.format("%.8d", 7);
+ assert(r == "00000007");
+ r = std.string.format("%.8x", 10);
+ assert(r == "0000000a");
+
+ r = std.string.format("%-3d", 7);
+ assert(r == "7 ");
+
+ r = std.string.format("%*d", -3, 7);
+ assert(r == "7 ");
+
+ r = std.string.format("%.*d", -3, 7);
+ assert(r == "7");
+
+ typedef int myint;
+ myint m = -7;
+ r = std.string.format(m);
+ assert(r == "-7");
+
+ r = std.string.format("abc"c);
+ assert(r == "abc");
+ r = std.string.format("def"w);
+ assert(r == "def");
+ r = std.string.format("ghi"d);
+ assert(r == "ghi");
+
+ void* p = cast(void*)0xDEADBEEF;
+ r = std.string.format(p);
+ assert(r == "DEADBEEF");
+
+ r = std.string.format("%#x", 0xabcd);
+ assert(r == "0xabcd");
+ r = std.string.format("%#X", 0xABCD);
+ assert(r == "0XABCD");
+
+ r = std.string.format("%#o", 012345);
+ assert(r == "012345");
+ r = std.string.format("%o", 9);
+ assert(r == "11");
+
+ r = std.string.format("%+d", 123);
+ assert(r == "+123");
+ r = std.string.format("%+d", -123);
+ assert(r == "-123");
+ r = std.string.format("% d", 123);
+ assert(r == " 123");
+ r = std.string.format("% d", -123);
+ assert(r == "-123");
+
+ r = std.string.format("%%");
+ assert(r == "%");
+
+ r = std.string.format("%d", true);
+ assert(r == "1");
+ r = std.string.format("%d", false);
+ assert(r == "0");
+
+ r = std.string.format("%d", 'a');
+ assert(r == "97");
+ wchar wc = 'a';
+ r = std.string.format("%d", wc);
+ assert(r == "97");
+ dchar dc = 'a';
+ r = std.string.format("%d", dc);
+ assert(r == "97");
+
+ byte b = byte.max;
+ r = std.string.format("%x", b);
+ assert(r == "7f");
+ r = std.string.format("%x", ++b);
+ assert(r == "80");
+ r = std.string.format("%x", ++b);
+ assert(r == "81");
+
+ short sh = short.max;
+ r = std.string.format("%x", sh);
+ assert(r == "7fff");
+ r = std.string.format("%x", ++sh);
+ assert(r == "8000");
+ r = std.string.format("%x", ++sh);
+ assert(r == "8001");
+
+ i = int.max;
+ r = std.string.format("%x", i);
+ assert(r == "7fffffff");
+ r = std.string.format("%x", ++i);
+ assert(r == "80000000");
+ r = std.string.format("%x", ++i);
+ assert(r == "80000001");
+
+ r = std.string.format("%x", 10);
+ assert(r == "a");
+ r = std.string.format("%X", 10);
+ assert(r == "A");
+ r = std.string.format("%x", 15);
+ assert(r == "f");
+ r = std.string.format("%X", 15);
+ assert(r == "F");
+
+ Object c = null;
+ r = std.string.format(c);
+ assert(r == "null");
+
+ enum TestEnum
+ {
+ Value1, Value2
+ }
+ r = std.string.format("%s", TestEnum.Value2);
+ assert(r == "1");
+
+ char[5][int] aa = ([3:"hello", 4:"betty"]);
+ r = std.string.format("%s", aa.values);
+ assert(r == "[[h,e,l,l,o],[b,e,t,t,y]]");
+ r = std.string.format("%s", aa);
+ assert(r == "[3:[h,e,l,l,o],4:[b,e,t,t,y]]");
+
+ static const dchar[] ds = ['a','b'];
+ for (int j = 0; j < ds.length; ++j)
+ {
+ r = std.string.format(" %d", ds[j]);
+ if (j == 0)
+ assert(r == " 97");
+ else
+ assert(r == " 98");
+ }
+
+ r = std.string.format(">%14d<, ", 15, [1,2,3]);
+ assert(r == "> 15<, [1,2,3]");
+}
+
diff --git a/lphobos/std/mmfile.d b/lphobos/std/mmfile.d
index e1fef6c4..67f496c6 100644
--- a/lphobos/std/mmfile.d
+++ b/lphobos/std/mmfile.d
@@ -39,6 +39,8 @@ private import std.c.stdio;
private import std.c.stdlib;
private import std.string;
+version(linux) version = Unix;
+
//debug = MMFILE;
version (Win32)
diff --git a/lphobos/std/outbuffer.d b/lphobos/std/outbuffer.d
index aa89ba89..e4762628 100644
--- a/lphobos/std/outbuffer.d
+++ b/lphobos/std/outbuffer.d
@@ -268,7 +268,7 @@ class OutBuffer
if (count != -1)
break;
psize *= 2;
- p = cast(char *) alloca(psize); // buffer too small, try again with larger size
+ p = cast(char *) /*alloca*/malloc(psize); // buffer too small, try again with larger size
}
else version(GNU) {
count = vsnprintf(p,psize,f,args_copy);
@@ -278,7 +278,7 @@ class OutBuffer
psize = count + 1;
else
break;
- p = cast(char *) alloca(psize); // buffer too small, try again with larger size
+ p = cast(char *) /*alloca*/std.gc.malloc(psize); // buffer too small, try again with larger size
}
else version(linux)
{
@@ -294,7 +294,7 @@ class OutBuffer
c.stdlib.free(p);
p = (char *) c.stdlib.malloc(psize); // buffer too small, try again with larger size
+/
- p = cast(char *) alloca(psize); // buffer too small, try again with larger size
+ p = cast(char *) /*alloca*/std.gc.malloc(psize); // buffer too small, try again with larger size
}
}
write(p[0 .. count]);
diff --git a/lphobos/std/outofmemory.d b/lphobos/std/outofmemory.d
index c493c679..5187b849 100644
--- a/lphobos/std/outofmemory.d
+++ b/lphobos/std/outofmemory.d
@@ -33,10 +33,11 @@ class OutOfMemoryException : Exception
extern (C) void _d_OutOfMemory()
{
- assert(0);
- /*throw cast(OutOfMemoryException)
+ printf("Out of memory!\n");
+ *(cast(int*) 0) = 0;
+ throw cast(OutOfMemoryException)
cast(void *)
- OutOfMemoryException.classinfo.init;*/
+ OutOfMemoryException.classinfo.init;
}
static this()
diff --git a/lphobos/std/path.d b/lphobos/std/path.d
index 57d828b3..9bc91a18 100644
--- a/lphobos/std/path.d
+++ b/lphobos/std/path.d
@@ -29,6 +29,8 @@ module std.path;
import std.string;
+version(linux) version = Unix;
+
version(Unix)
{
import std.c.stdlib;
diff --git a/lphobos/std/process.d b/lphobos/std/process.d
index 977f4c05..98736d02 100644
--- a/lphobos/std/process.d
+++ b/lphobos/std/process.d
@@ -43,6 +43,8 @@ private import std.c.string;
private import std.string;
private import std.c.process;
+version(linux) version = Unix;
+
/**
* Execute command in a _command shell.
*
diff --git a/lphobos/std/random.d b/lphobos/std/random.d
index ce52e541..1320e209 100644
--- a/lphobos/std/random.d
+++ b/lphobos/std/random.d
@@ -17,6 +17,8 @@ module std.random;
// Segments of the code in this file Copyright (c) 1997 by Rick Booth
// From "Inner Loops" by Rick Booth, Addison-Wesley
+version(linux) version = Unix;
+
version (Win32)
{
extern(Windows) int QueryPerformanceCounter(ulong *count);
diff --git a/lphobos/std/regexp.d b/lphobos/std/regexp.d
index 6c276f45..450c6cbd 100644
--- a/lphobos/std/regexp.d
+++ b/lphobos/std/regexp.d
@@ -1820,7 +1820,7 @@ int trymatch(int pc, int pcend)
if (!psave && count < m)
{
//version (Win32)
- psave = cast(regmatch_t *)alloca((re_nsub + 1) * regmatch_t.sizeof);
+ psave = cast(regmatch_t *)/*alloca*/malloc((re_nsub + 1) * regmatch_t.sizeof);
//else
//psave = new regmatch_t[re_nsub + 1];
}
diff --git a/lphobos/std/socket.d b/lphobos/std/socket.d
index 646c8c82..11d87f06 100644
--- a/lphobos/std/socket.d
+++ b/lphobos/std/socket.d
@@ -44,7 +44,7 @@ module std.socket;
private import std.string, std.stdint, std.c.string, std.c.stdlib;
-
+version(linux) version = Unix;
version(Unix) version = BsdSockets;
version (skyos) { /* nothging */ }
diff --git a/lphobos/std/stream.d b/lphobos/std/stream.d
index fbf13b4c..ce635308 100644
--- a/lphobos/std/stream.d
+++ b/lphobos/std/stream.d
@@ -1139,7 +1139,7 @@ class Stream : InputStream, OutputStream {
if (count != -1)
break;
psize *= 2;
- p = cast(char*) alloca(psize);
+ p = cast(char*) /*alloca*/malloc(psize);
} else version (Unix) {
count = vsnprintf(p, psize, f, args_copy);
if (count == -1)
@@ -1148,7 +1148,7 @@ class Stream : InputStream, OutputStream {
psize = count + 1;
else
break;
- p = cast(char*) alloca(psize);
+ p = cast(char*) /*alloca*/malloc(psize);
} else
throw new Exception("unsupported platform");
}
@@ -1779,6 +1779,8 @@ enum FileMode {
Append = 10 // includes FileMode.Out
}
+version(linux) version = Unix;
+
version (Win32) {
private import std.c.windows.windows;
extern (Windows) {
@@ -2232,7 +2234,8 @@ ubyte[][NBOMS] ByteOrderMarks =
* manner with the source stream so the source stream's position and state will be
* kept in sync with the EndianStream if only non-getc functions are called.
*/
-class EndianStream : FilterStream {
+/// This causes a crash in -O2
+/+class EndianStream : FilterStream {
Endian endian; /// Endianness property of the source stream.
@@ -2510,6 +2513,7 @@ class EndianStream : FilterStream {
em.position(0);
}
}
++/
/***
* Parameterized subclass that wraps an array-like buffer with a stream