changeset 1194:1853dcd9b944

Moved some DMDFE files into a seperate dmd/root subdir to closer match the DMD file structure since 1.041.
author Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
date Fri, 03 Apr 2009 17:02:52 +0200
parents c271eca933fb
children e961851fb8be
files CMakeLists.txt dmd/array.c dmd/dchar.c dmd/dchar.h dmd/gnuc.c dmd/gnuc.h dmd/lstring.c dmd/lstring.h dmd/man.c dmd/port.h dmd/root.c dmd/root.h dmd/root/array.c dmd/root/dchar.c dmd/root/dchar.h dmd/root/gnuc.c dmd/root/gnuc.h dmd/root/lstring.c dmd/root/lstring.h dmd/root/man.c dmd/root/port.h dmd/root/root.c dmd/root/root.h dmd/root/stringtable.c dmd/root/stringtable.h dmd/stringtable.c dmd/stringtable.h
diffstat 27 files changed, 3728 insertions(+), 3726 deletions(-) [+]
line wrap: on
line diff
--- a/CMakeLists.txt	Fri Apr 03 16:35:47 2009 +0200
+++ b/CMakeLists.txt	Fri Apr 03 17:02:52 2009 +0200
@@ -131,9 +131,10 @@
 set(DEFAULT_TARGET ${HOST_TARGET} CACHE STRING "default target")
 set(DEFAULT_ALT_TARGET ${HOST_ALT_TARGET} CACHE STRING "default alt target")
 
-include_directories(. ${DMDFE_PATH} ${PROJECT_BINARY_DIR}/${DMDFE_PATH} ${PROJECT_BINARY_DIR} ${LLVM_INSTDIR}/include)
+include_directories(. ${DMDFE_PATH} ${DMDFE_PATH}/root ${PROJECT_BINARY_DIR}/${DMDFE_PATH} ${PROJECT_BINARY_DIR} ${LLVM_INSTDIR}/include)
 
 file(GLOB FE_SRC ${DMDFE_PATH}/*.c)
+file(GLOB FE_SRC_ROOT ${DMDFE_PATH}/root/*.c)
 file(GLOB GEN_SRC gen/*.cpp)
 file(GLOB IR_SRC ir/*.cpp)
 # exclude idgen and impcnvgen and generated sources, just in case
@@ -146,6 +147,7 @@
 set(LDC_SOURCE_FILES
 	${LDC_GENERATED}
 	${FE_SRC}
+	${FE_SRC_ROOT}
 	${GEN_SRC}
 	${IR_SRC}
 )
--- a/dmd/array.c	Fri Apr 03 16:35:47 2009 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,224 +0,0 @@
-
-// Copyright (c) 1999-2006 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// www.digitalmars.com
-// License for redistribution is by either the Artistic License
-// in artistic.txt, or the GNU General Public License in gnu.txt.
-// See the included readme.txt for details.
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <assert.h>
-
-#if (defined (__SVR4) && defined (__sun)) 
-#include <alloca.h>
-#endif
-
-#if _MSC_VER || __MINGW32__
-#include <malloc.h>
-#endif
-
-#if IN_GCC
-#include "gdc_alloca.h"
-#endif
-
-#if _WIN32
-#include <windows.h>
-#endif
-
-#ifndef _WIN32
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <unistd.h>
-#include <utime.h>
-#endif
-
-#include "port.h"
-#include "root.h"
-#include "dchar.h"
-#include "rmem.h"
-
-
-/********************************* Array ****************************/
-
-Array::Array()
-{
-    data = NULL;
-    dim = 0;
-    allocdim = 0;
-}
-
-Array::~Array()
-{
-    mem.free(data);
-}
-
-void Array::mark()
-{   unsigned u;
-
-    mem.mark(data);
-    for (u = 0; u < dim; u++)
-	mem.mark(data[u]);	// BUG: what if arrays of Object's?
-}
-
-void Array::reserve(unsigned nentries)
-{
-    //printf("Array::reserve: size = %d, offset = %d, nbytes = %d\n", size, offset, nbytes);
-    if (allocdim - dim < nentries)
-    {
-	allocdim = dim + nentries;
-	data = (void **)mem.realloc(data, allocdim * sizeof(*data));
-    }
-}
-
-void Array::setDim(unsigned newdim)
-{
-    if (dim < newdim)
-    {
-	reserve(newdim - dim);
-    }
-    dim = newdim;
-}
-
-void Array::fixDim()
-{
-    if (dim != allocdim)
-    {	data = (void **)mem.realloc(data, dim * sizeof(*data));
-	allocdim = dim;
-    }
-}
-
-void Array::push(void *ptr)
-{
-    reserve(1);
-    data[dim++] = ptr;
-}
-
-void *Array::pop()
-{
-    return data[--dim];
-}
-
-void Array::shift(void *ptr)
-{
-    reserve(1);
-    memmove(data + 1, data, dim * sizeof(*data));
-    data[0] = ptr;
-    dim++;
-}
-
-void Array::insert(unsigned index, void *ptr)
-{
-    reserve(1);
-    memmove(data + index + 1, data + index, (dim - index) * sizeof(*data));
-    data[index] = ptr;
-    dim++;
-}
-
-
-void Array::insert(unsigned index, Array *a)
-{
-    if (a)
-    {	unsigned d;
-
-	d = a->dim;
-	reserve(d);
-	if (dim != index)
-	    memmove(data + index + d, data + index, (dim - index) * sizeof(*data));
-	memcpy(data + index, a->data, d * sizeof(*data));
-	dim += d;
-    }
-}
-
-
-/***********************************
- * Append array a to this array.
- */
-
-void Array::append(Array *a)
-{
-    insert(dim, a);
-}
-
-void Array::remove(unsigned i)
-{
-    memmove(data + i, data + i + 1, (dim - i - 1) * sizeof(data[0]));
-    dim--;
-}
-
-char *Array::toChars()
-{
-    unsigned len;
-    unsigned u;
-    char **buf;
-    char *str;
-    char *p;
-
-    buf = (char **)alloca(dim * sizeof(char *));
-    len = 2;
-    for (u = 0; u < dim; u++)
-    {
-	buf[u] = ((Object *)data[u])->toChars();
-	len += strlen(buf[u]) + 1;
-    }
-    str = (char *)mem.malloc(len);
-
-    str[0] = '[';
-    p = str + 1;
-    for (u = 0; u < dim; u++)
-    {
-	if (u)
-	    *p++ = ',';
-	len = strlen(buf[u]);
-	memcpy(p,buf[u],len);
-	p += len;
-    }
-    *p++ = ']';
-    *p = 0;
-    return str;
-}
-
-void Array::zero()
-{
-    memset(data,0,dim * sizeof(data[0]));
-}
-
-void *Array::tos()
-{
-    return dim ? data[dim - 1] : NULL;
-}
-
-int
-#if _WIN32
-  __cdecl
-#endif
-	Array_sort_compare(const void *x, const void *y)
-{
-    Object *ox = *(Object **)x;
-    Object *oy = *(Object **)y;
-
-    return ox->compare(oy);
-}
-
-void Array::sort()
-{
-    if (dim)
-    {
-	qsort(data, dim, sizeof(Object *), Array_sort_compare);
-    }
-}
-
-Array *Array::copy()
-{
-    Array *a = new Array();
-
-    a->setDim(dim);
-    memcpy(a->data, data, dim * sizeof(void *));
-    return a;
-}
-
--- a/dmd/dchar.c	Fri Apr 03 16:35:47 2009 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,482 +0,0 @@
-
-// Copyright (c) 1999-2006 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// www.digitalmars.com
-// License for redistribution is by either the Artistic License
-// in artistic.txt, or the GNU General Public License in gnu.txt.
-// See the included readme.txt for details.
-
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <assert.h>
-
-#include "dchar.h"
-#include "rmem.h"
-
-#if M_UNICODE
-
-// Converts a char string to Unicode
-
-dchar *Dchar::dup(char *p)
-{
-    dchar *s;
-    size_t len;
-
-    if (!p)
-	return NULL;
-    len = strlen(p);
-    s = (dchar *)mem.malloc((len + 1) * sizeof(dchar));
-    for (unsigned i = 0; i < len; i++)
-    {
-	s[i] = (dchar)(p[i] & 0xFF);
-    }
-    s[len] = 0;
-    return s;
-}
-
-dchar *Dchar::memchr(dchar *p, int c, int count)
-{
-    int u;
-
-    for (u = 0; u < count; u++)
-    {
-	if (p[u] == c)
-	    return p + u;
-    }
-    return NULL;
-}
-
-#if _WIN32 && __DMC__
-__declspec(naked)
-unsigned Dchar::calcHash(const dchar *str, unsigned len)
-{
-    __asm
-    {
-	mov	ECX,4[ESP]
-	mov	EDX,8[ESP]
-	xor	EAX,EAX
-	test	EDX,EDX
-	je	L92
-
-LC8:	cmp	EDX,1
-	je	L98
-	cmp	EDX,2
-	je	LAE
-
-	add	EAX,[ECX]
-//	imul	EAX,EAX,025h
-	lea	EAX,[EAX][EAX*8]
-	add	ECX,4
-	sub	EDX,2
-	jmp	LC8
-
-L98:	mov	DX,[ECX]
-	and	EDX,0FFFFh
-	add	EAX,EDX
-	ret
-
-LAE:	add	EAX,[ECX]
-L92:	ret
-    }
-}
-#else
-hash_t Dchar::calcHash(const dchar *str, size_t len)
-{
-    unsigned hash = 0;
-
-    for (;;)
-    {
-	switch (len)
-	{
-	    case 0:
-		return hash;
-
-	    case 1:
-		hash += *(const uint16_t *)str;
-		return hash;
-
-	    case 2:
-		hash += *(const uint32_t *)str;
-		return hash;
-
-	    default:
-		hash += *(const uint32_t *)str;
-		hash *= 37;
-		str += 2;
-		len -= 2;
-		break;
-	}
-    }
-}
-#endif
-
-hash_t Dchar::icalcHash(const dchar *str, size_t len)
-{
-    hash_t hash = 0;
-
-    for (;;)
-    {
-	switch (len)
-	{
-	    case 0:
-		return hash;
-
-	    case 1:
-		hash += *(const uint16_t *)str | 0x20;
-		return hash;
-
-	    case 2:
-		hash += *(const uint32_t *)str | 0x200020;
-		return hash;
-
-	    default:
-		hash += *(const uint32_t *)str | 0x200020;
-		hash *= 37;
-		str += 2;
-		len -= 2;
-		break;
-	}
-    }
-}
-
-#elif MCBS
-
-hash_t Dchar::calcHash(const dchar *str, size_t len)
-{
-    hash_t hash = 0;
-
-    while (1)
-    {
-	switch (len)
-	{
-	    case 0:
-		return hash;
-
-	    case 1:
-		hash *= 37;
-		hash += *(const uint8_t *)str;
-		return hash;
-
-	    case 2:
-		hash *= 37;
-		hash += *(const uint16_t *)str;
-		return hash;
-
-	    case 3:
-		hash *= 37;
-		hash += (*(const uint16_t *)str << 8) +
-			((const uint8_t *)str)[2];
-		return hash;
-
-	    default:
-		hash *= 37;
-		hash += *(const uint32_t *)str;
-		str += 4;
-		len -= 4;
-		break;
-	}
-    }
-}
-
-#elif UTF8
-
-// Specification is: http://anubis.dkuug.dk/JTC1/SC2/WG2/docs/n1335
-
-char Dchar::mblen[256] =
-{
-    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-    2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
-    2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
-    3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
-    4,4,4,4,4,4,4,4,5,5,5,5,6,6,1,1,
-};
-
-dchar *Dchar::dec(dchar *pstart, dchar *p)
-{
-    while ((p[-1] & 0xC0) == 0x80)
-	p--;
-    return p;
-}
-
-int Dchar::get(dchar *p)
-{
-    unsigned c;
-    unsigned char *q = (unsigned char *)p;
-
-    c = q[0];
-    switch (mblen[c])
-    {
-	case 2:
-	    c = ((c    - 0xC0) << 6) |
-		 (q[1] - 0x80);
-	    break;
-
-	case 3:
-	    c = ((c    - 0xE0) << 12) |
-		((q[1] - 0x80) <<  6) |
-		 (q[2] - 0x80);
-	    break;
-
-	case 4:
-	    c = ((c    - 0xF0) << 18) |
-		((q[1] - 0x80) << 12) |
-		((q[2] - 0x80) <<  6) |
-		 (q[3] - 0x80);
-	    break;
-
-	case 5:
-	    c = ((c    - 0xF8) << 24) |
-		((q[1] - 0x80) << 18) |
-		((q[2] - 0x80) << 12) |
-		((q[3] - 0x80) <<  6) |
-		 (q[4] - 0x80);
-	    break;
-
-	case 6:
-	    c = ((c    - 0xFC) << 30) |
-		((q[1] - 0x80) << 24) |
-		((q[2] - 0x80) << 18) |
-		((q[3] - 0x80) << 12) |
-		((q[4] - 0x80) <<  6) |
-		 (q[5] - 0x80);
-	    break;
-    }
-    return c;
-}
-
-dchar *Dchar::put(dchar *p, unsigned c)
-{
-    if (c <= 0x7F)
-    {
-	*p++ = c;
-    }
-    else if (c <= 0x7FF)
-    {
-	p[0] = 0xC0 + (c >> 6);
-	p[1] = 0x80 + (c & 0x3F);
-	p += 2;
-    }
-    else if (c <= 0xFFFF)
-    {
-	p[0] = 0xE0 + (c >> 12);
-	p[1] = 0x80 + ((c >> 6) & 0x3F);
-	p[2] = 0x80 + (c & 0x3F);
-	p += 3;
-    }
-    else if (c <= 0x1FFFFF)
-    {
-	p[0] = 0xF0 + (c >> 18);
-	p[1] = 0x80 + ((c >> 12) & 0x3F);
-	p[2] = 0x80 + ((c >> 6) & 0x3F);
-	p[3] = 0x80 + (c & 0x3F);
-	p += 4;
-    }
-    else if (c <= 0x3FFFFFF)
-    {
-	p[0] = 0xF8 + (c >> 24);
-	p[1] = 0x80 + ((c >> 18) & 0x3F);
-	p[2] = 0x80 + ((c >> 12) & 0x3F);
-	p[3] = 0x80 + ((c >> 6) & 0x3F);
-	p[4] = 0x80 + (c & 0x3F);
-	p += 5;
-    }
-    else if (c <= 0x7FFFFFFF)
-    {
-	p[0] = 0xFC + (c >> 30);
-	p[1] = 0x80 + ((c >> 24) & 0x3F);
-	p[2] = 0x80 + ((c >> 18) & 0x3F);
-	p[3] = 0x80 + ((c >> 12) & 0x3F);
-	p[4] = 0x80 + ((c >> 6) & 0x3F);
-	p[5] = 0x80 + (c & 0x3F);
-	p += 6;
-    }
-    else
-	assert(0);		// not a UCS-4 character
-    return p;
-}
-
-hash_t Dchar::calcHash(const dchar *str, size_t len)
-{
-    hash_t hash = 0;
-
-    while (1)
-    {
-	switch (len)
-	{
-	    case 0:
-		return hash;
-
-	    case 1:
-		hash *= 37;
-		hash += *(const uint8_t *)str;
-		return hash;
-
-	    case 2:
-		hash *= 37;
-#if __I86__
-		hash += *(const uint16_t *)str;
-#else
-		hash += str[0] * 256 + str[1];
-#endif
-		return hash;
-
-	    case 3:
-		hash *= 37;
-#if __I86__
-		hash += (*(const uint16_t *)str << 8) +
-			((const uint8_t *)str)[2];
-#else
-		hash += (str[0] * 256 + str[1]) * 256 + str[2];
-#endif
-		return hash;
-
-	    default:
-		hash *= 37;
-#if __I86__
-		hash += *(const uint32_t *)str;
-#else
-		hash += ((str[0] * 256 + str[1]) * 256 + str[2]) * 256 + str[3];
-#endif
-
-		str += 4;
-		len -= 4;
-		break;
-	}
-    }
-}
-
-#else // ascii
-
-hash_t Dchar::calcHash(const dchar *str, size_t len)
-{
-    hash_t hash = 0;
-
-    while (1)
-    {
-	switch (len)
-	{
-	    case 0:
-		return hash;
-
-	    case 1:
-		hash *= 37;
-		hash += *(const uint8_t *)str;
-		return hash;
-
-	    case 2:
-		hash *= 37;
-#if __I86__
-		hash += *(const uint16_t *)str;
-#else
-		hash += str[0] * 256 + str[1];
-#endif
-		return hash;
-
-	    case 3:
-		hash *= 37;
-#if __I86__
-		hash += (*(const uint16_t *)str << 8) +
-			((const uint8_t *)str)[2];
-#else
-		hash += (str[0] * 256 + str[1]) * 256 + str[2];
-#endif
-		return hash;
-
-	    default:
-		hash *= 37;
-#if __I86__
-		hash += *(const uint32_t *)str;
-#else
-		hash += ((str[0] * 256 + str[1]) * 256 + str[2]) * 256 + str[3];
-#endif
-		str += 4;
-		len -= 4;
-		break;
-	}
-    }
-}
-
-hash_t Dchar::icalcHash(const dchar *str, size_t len)
-{
-    hash_t hash = 0;
-
-    while (1)
-    {
-	switch (len)
-	{
-	    case 0:
-		return hash;
-
-	    case 1:
-		hash *= 37;
-		hash += *(const uint8_t *)str | 0x20;
-		return hash;
-
-	    case 2:
-		hash *= 37;
-		hash += *(const uint16_t *)str | 0x2020;
-		return hash;
-
-	    case 3:
-		hash *= 37;
-		hash += ((*(const uint16_t *)str << 8) +
-			 ((const uint8_t *)str)[2]) | 0x202020;
-		return hash;
-
-	    default:
-		hash *= 37;
-		hash += *(const uint32_t *)str | 0x20202020;
-		str += 4;
-		len -= 4;
-		break;
-	}
-    }
-}
-
-#endif
-
-#if 0
-#include <stdio.h>
-
-void main()
-{
-    // Print out values to hardcode into Dchar::mblen[]
-    int c;
-    int s;
-
-    for (c = 0; c < 256; c++)
-    {
-	s = 1;
-	if (c >= 0xC0 && c <= 0xDF)
-	    s = 2;
-	if (c >= 0xE0 && c <= 0xEF)
-	    s = 3;
-	if (c >= 0xF0 && c <= 0xF7)
-	    s = 4;
-	if (c >= 0xF8 && c <= 0xFB)
-	    s = 5;
-	if (c >= 0xFC && c <= 0xFD)
-	    s = 6;
-
-	printf("%d", s);
-	if ((c & 15) == 15)
-	    printf(",\n");
-	else
-	    printf(",");
-    }
-}
-#endif
--- a/dmd/dchar.h	Fri Apr 03 16:35:47 2009 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,194 +0,0 @@
-
-// Copyright (c) 1999-2006 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// www.digitalmars.com
-// License for redistribution is by either the Artistic License
-// in artistic.txt, or the GNU General Public License in gnu.txt.
-// See the included readme.txt for details.
-
-
-#ifndef DCHAR_H
-#define DCHAR_H
-
-#if __GNUC__ && !_WIN32
-#include "gnuc.h"
-#endif
-
-#if _MSC_VER
-    // Disable useless warnings about unreferenced functions
-    #pragma warning (disable : 4514)
-#endif
-
-//#include "root.h"
-typedef size_t hash_t;
-
-#undef TEXT
-
-// NOTE: All functions accepting pointer arguments must not be NULL
-
-#if M_UNICODE
-
-#include <string.h>
-#include <wchar.h>
-
-typedef wchar_t dchar;
-#define TEXT(x)		L##x
-
-#define Dchar_mbmax	1
-
-struct Dchar
-{
-    static dchar *inc(dchar *p) { return p + 1; }
-    static dchar *dec(dchar *pstart, dchar *p) { (void)pstart; return p - 1; }
-    static int len(const dchar *p) { return wcslen(p); }
-    static dchar get(dchar *p) { return *p; }
-    static dchar getprev(dchar *pstart, dchar *p) { (void)pstart; return p[-1]; }
-    static dchar *put(dchar *p, dchar c) { *p = c; return p + 1; }
-    static int cmp(dchar *s1, dchar *s2)
-    {
-#if __DMC__
-	if (!*s1 && !*s2)	// wcscmp is broken
-	    return 0;
-#endif
-	return wcscmp(s1, s2);
-#if 0
-	return (*s1 == *s2)
-	    ? wcscmp(s1, s2)
-	    : ((int)*s1 - (int)*s2);
-#endif
-    }
-    static int memcmp(const dchar *s1, const dchar *s2, int nchars) { return ::memcmp(s1, s2, nchars * sizeof(dchar)); }
-    static int isDigit(dchar c) { return '0' <= c && c <= '9'; }
-    static int isAlpha(dchar c) { return iswalpha(c); }
-    static int isUpper(dchar c) { return iswupper(c); }
-    static int isLower(dchar c) { return iswlower(c); }
-    static int isLocaleUpper(dchar c) { return isUpper(c); }
-    static int isLocaleLower(dchar c) { return isLower(c); }
-    static int toLower(dchar c) { return isUpper(c) ? towlower(c) : c; }
-    static int toLower(dchar *p) { return toLower(*p); }
-    static int toUpper(dchar c) { return isLower(c) ? towupper(c) : c; }
-    static dchar *dup(dchar *p) { return ::_wcsdup(p); }	// BUG: out of memory?
-    static dchar *dup(char *p);
-    static dchar *chr(dchar *p, unsigned c) { return wcschr(p, (dchar)c); }
-    static dchar *rchr(dchar *p, unsigned c) { return wcsrchr(p, (dchar)c); }
-    static dchar *memchr(dchar *p, int c, int count);
-    static dchar *cpy(dchar *s1, dchar *s2) { return wcscpy(s1, s2); }
-    static dchar *str(dchar *s1, dchar *s2) { return wcsstr(s1, s2); }
-    static hash_t calcHash(const dchar *str, size_t len);
-
-    // Case insensitive versions
-    static int icmp(dchar *s1, dchar *s2) { return wcsicmp(s1, s2); }
-    static int memicmp(const dchar *s1, const dchar *s2, int nchars) { return ::wcsnicmp(s1, s2, nchars); }
-    static hash_t icalcHash(const dchar *str, size_t len);
-};
-
-#elif MCBS
-
-#include <limits.h>
-#include <mbstring.h>
-
-typedef char dchar;
-#define TEXT(x)		x
-
-#define Dchar_mbmax	MB_LEN_MAX
-
-#elif UTF8
-
-typedef char dchar;
-#define TEXT(x)		x
-
-#define Dchar_mbmax	6
-
-struct Dchar
-{
-    static char mblen[256];
-
-    static dchar *inc(dchar *p) { return p + mblen[*p & 0xFF]; }
-    static dchar *dec(dchar *pstart, dchar *p);
-    static int len(const dchar *p) { return strlen(p); }
-    static int get(dchar *p);
-    static int getprev(dchar *pstart, dchar *p)
-	{ return *dec(pstart, p) & 0xFF; }
-    static dchar *put(dchar *p, unsigned c);
-    static int cmp(dchar *s1, dchar *s2) { return strcmp(s1, s2); }
-    static int memcmp(const dchar *s1, const dchar *s2, int nchars) { return ::memcmp(s1, s2, nchars); }
-    static int isDigit(dchar c) { return '0' <= c && c <= '9'; }
-    static int isAlpha(dchar c) { return c <= 0x7F ? isalpha(c) : 0; }
-    static int isUpper(dchar c) { return c <= 0x7F ? isupper(c) : 0; }
-    static int isLower(dchar c) { return c <= 0x7F ? islower(c) : 0; }
-    static int isLocaleUpper(dchar c) { return isUpper(c); }
-    static int isLocaleLower(dchar c) { return isLower(c); }
-    static int toLower(dchar c) { return isUpper(c) ? tolower(c) : c; }
-    static int toLower(dchar *p) { return toLower(*p); }
-    static int toUpper(dchar c) { return isLower(c) ? toupper(c) : c; }
-    static dchar *dup(dchar *p) { return ::strdup(p); }	// BUG: out of memory?
-    static dchar *chr(dchar *p, int c) { return strchr(p, c); }
-    static dchar *rchr(dchar *p, int c) { return strrchr(p, c); }
-    static dchar *memchr(dchar *p, int c, int count)
-	{ return (dchar *)::memchr(p, c, count); }
-    static dchar *cpy(dchar *s1, dchar *s2) { return strcpy(s1, s2); }
-    static dchar *str(dchar *s1, dchar *s2) { return strstr(s1, s2); }
-    static hash_t calcHash(const dchar *str, size_t len);
-
-    // Case insensitive versions
-    static int icmp(dchar *s1, dchar *s2) { return _mbsicmp(s1, s2); }
-    static int memicmp(const dchar *s1, const dchar *s2, int nchars) { return ::_mbsnicmp(s1, s2, nchars); }
-};
-
-#else
-
-#include <string.h>
-
-#ifndef GCC_SAFE_DMD
-#include <ctype.h>
-#endif
-
-typedef char dchar;
-#define TEXT(x)		x
-
-#define Dchar_mbmax	1
-
-struct Dchar
-{
-    static dchar *inc(dchar *p) { return p + 1; }
-    static dchar *dec(dchar *pstart, dchar *p) { return p - 1; }
-    static int len(const dchar *p) { return strlen(p); }
-    static int get(dchar *p) { return *p & 0xFF; }
-    static int getprev(dchar *pstart, dchar *p) { return p[-1] & 0xFF; }
-    static dchar *put(dchar *p, unsigned c) { *p = c; return p + 1; }
-    static int cmp(dchar *s1, dchar *s2) { return strcmp(s1, s2); }
-    static int memcmp(const dchar *s1, const dchar *s2, int nchars) { return ::memcmp(s1, s2, nchars); }
-    static int isDigit(dchar c) { return '0' <= c && c <= '9'; }
-#ifndef GCC_SAFE_DMD
-    static int isAlpha(dchar c) { return isalpha(c); }
-    static int isUpper(dchar c) { return isupper(c); }
-    static int isLower(dchar c) { return islower(c); }
-    static int isLocaleUpper(dchar c) { return isupper(c); }
-    static int isLocaleLower(dchar c) { return islower(c); }
-    static int toLower(dchar c) { return isupper(c) ? tolower(c) : c; }
-    static int toLower(dchar *p) { return toLower(*p); }
-    static int toUpper(dchar c) { return islower(c) ? toupper(c) : c; }
-    static dchar *dup(dchar *p) { return ::strdup(p); }	// BUG: out of memory?
-#endif
-    static dchar *chr(dchar *p, int c) { return strchr(p, c); }
-    static dchar *rchr(dchar *p, int c) { return strrchr(p, c); }
-    static dchar *memchr(dchar *p, int c, int count)
-	{ return (dchar *)::memchr(p, c, count); }
-    static dchar *cpy(dchar *s1, dchar *s2) { return strcpy(s1, s2); }
-    static dchar *str(dchar *s1, dchar *s2) { return strstr(s1, s2); }
-    static hash_t calcHash(const dchar *str, size_t len);
-
-    // Case insensitive versions
-#ifdef __GNUC__
-    static int icmp(dchar *s1, dchar *s2) { return strcasecmp(s1, s2); }
-#else
-    static int icmp(dchar *s1, dchar *s2) { return stricmp(s1, s2); }
-#endif
-    static int memicmp(const dchar *s1, const dchar *s2, int nchars) { return ::memicmp(s1, s2, nchars); }
-    static hash_t icalcHash(const dchar *str, size_t len);
-};
-
-#endif
-#endif
-
--- a/dmd/gnuc.c	Fri Apr 03 16:35:47 2009 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-
-// Put functions in here missing from gnu C
-
-#include "gnuc.h"
-
-int memicmp(const char *s1, const char *s2, int n)
-{
-    int result = 0;
-
-    for (int i = 0; i < n; i++)
-    {	char c1 = s1[i];
-	char c2 = s2[i];
-
-	result = c1 - c2;
-	if (result)
-	{
-	    if ('A' <= c1 && c1 <= 'Z')
-		c1 += 'a' - 'A';
-	    if ('A' <= c2 && c2 <= 'Z')
-		c2 += 'a' - 'A';
-	    result = c1 - c2;
-	    if (result)
-		break;
-	}
-    }
-    return result;
-}
-
-int stricmp(const char *s1, const char *s2)
-{
-    int result = 0;
-
-    for (;;)
-    {	char c1 = *s1;
-	char c2 = *s2;
-
-	result = c1 - c2;
-	if (result)
-	{
-	    if ('A' <= c1 && c1 <= 'Z')
-		c1 += 'a' - 'A';
-	    if ('A' <= c2 && c2 <= 'Z')
-		c2 += 'a' - 'A';
-	    result = c1 - c2;
-	    if (result)
-		break;
-	}
-	if (!c1)
-	    break;
-	s1++;
-	s2++;
-    }
-    return result;
-}
-
--- a/dmd/gnuc.h	Fri Apr 03 16:35:47 2009 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,8 +0,0 @@
-
-#ifndef _GNUC_H
-#define _GNUC_H 1
-
-int memicmp(const char *s1, const char *s2, int n);
-int stricmp(const char *s1, const char *s2);
-
-#endif
--- a/dmd/lstring.c	Fri Apr 03 16:35:47 2009 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-// lstring.c
-
-// Copyright (c) 1999-2002 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// www.digitalmars.com
-// License for redistribution is by either the Artistic License
-// in artistic.txt, or the GNU General Public License in gnu.txt.
-// See the included readme.txt for details.
-
-#include <stdlib.h>
-
-#include "dchar.h"
-#include "rmem.h"
-#include "lstring.h"
-
-#ifdef _MSC_VER // prevent compiler internal crash
-Lstring Lstring::zero;
-#else
-Lstring Lstring::zero = LSTRING_EMPTY();
-#endif
-
-Lstring *Lstring::ctor(const dchar *p, unsigned length)
-{
-    Lstring *s;
-
-    s = alloc(length);
-    memcpy(s->string, p, length * sizeof(dchar));
-    return s;
-}
-
-Lstring *Lstring::alloc(unsigned length)
-{
-    Lstring *s;
-
-    s = (Lstring *)mem.malloc(size(length));
-    s->length = length;
-    s->string[length] = 0;
-    return s;
-}
-
-Lstring *Lstring::append(const Lstring *s)
-{
-    Lstring *t;
-
-    if (!s->length)
-	return this;
-    t = alloc(length + s->length);
-    memcpy(t->string, string, length * sizeof(dchar));
-    memcpy(t->string + length, s->string, s->length * sizeof(dchar));
-    return t;
-}
-
-Lstring *Lstring::substring(int start, int end)
-{
-    Lstring *t;
-
-    if (start == end)
-	return &zero;
-    t = alloc(end - start);
-    memcpy(t->string, string + start, (end - start) * sizeof(dchar));
-    return t;
-}
--- a/dmd/lstring.h	Fri Apr 03 16:35:47 2009 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,72 +0,0 @@
-
-// lstring.h
-// length-prefixed strings
-
-// Copyright (c) 1999-2002 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// www.digitalmars.com
-// License for redistribution is by either the Artistic License
-// in artistic.txt, or the GNU General Public License in gnu.txt.
-// See the included readme.txt for details.
-
-#ifndef LSTRING_H
-#define LSTRING_H 1
-
-#include "dchar.h"
-
-struct Lstring
-{
-    unsigned length;
-
-    // Disable warning about nonstandard extension
-    #pragma warning (disable : 4200)
-    dchar string[];
-
-    static Lstring zero;	// 0 length string
-
-    // No constructors because we want to be able to statically
-    // initialize Lstring's, and Lstrings are of variable size.
-
-    #if M_UNICODE
-    #define LSTRING(p,length) { length, L##p }
-    #else
-    #define LSTRING(p,length) { length, p }
-    #endif
-
-#if __GNUC__
-    #define LSTRING_EMPTY() { 0 }
-#else
-    #define LSTRING_EMPTY() LSTRING("", 0)
-#endif
-
-    static Lstring *ctor(const dchar *p) { return ctor(p, Dchar::len(p)); }
-    static Lstring *ctor(const dchar *p, unsigned length);
-    static unsigned size(unsigned length) { return sizeof(Lstring) + (length + 1) * sizeof(dchar); }
-    static Lstring *alloc(unsigned length);
-    Lstring *clone();
-
-    unsigned len() { return length; }
-
-    dchar *toDchars() { return string; }
-
-    hash_t hash() { return Dchar::calcHash(string, length); }
-    hash_t ihash() { return Dchar::icalcHash(string, length); }
-
-    static int cmp(const Lstring *s1, const Lstring *s2)
-    {
-	int c = s2->length - s1->length;
-	return c ? c : Dchar::memcmp(s1->string, s2->string, s1->length);
-    }
-
-    static int icmp(const Lstring *s1, const Lstring *s2)
-    {
-	int c = s2->length - s1->length;
-	return c ? c : Dchar::memicmp(s1->string, s2->string, s1->length);
-    }
-
-    Lstring *append(const Lstring *s);
-    Lstring *substring(int start, int end);
-};
-
-#endif
--- a/dmd/man.c	Fri Apr 03 16:35:47 2009 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,102 +0,0 @@
-
-// Compiler implementation of the D programming language
-// Copyright (c) 2008-2009 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// http://www.digitalmars.com
-// License for redistribution is by either the Artistic License
-// in artistic.txt, or the GNU General Public License in gnu.txt.
-// See the included readme.txt for details.
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <assert.h>
-
-#if _WIN32
-
-#include <windows.h>
-
-#pragma comment(lib,"shell32.lib")
-
-void browse(const char *url)
-{
-    ShellExecute(NULL, "open", url, NULL, NULL, SW_SHOWNORMAL);
-}
-
-#endif
-
-#if linux
-
-#include	<sys/types.h>
-#include	<sys/wait.h>
-#include	<unistd.h>
-
-void browse(const char *url)
-{
-    pid_t childpid;
-    const char *args[3];
-
-    char *browser = getenv("BROWSER");
-    if (browser)
-	browser = strdup(browser);
-    else
-	browser = "x-www-browser";
-
-    args[0] = browser;
-    args[1] = url;
-    args[2] = NULL;
-
-    childpid = fork();
-    if (childpid == 0)
-    {
-	execvp(args[0], (char**)args);
-	perror(args[0]);		// failed to execute
-	return;
-    }
-}
-
-#endif
-
-#if __APPLE__
-
-#include	<sys/types.h>
-#include	<sys/wait.h>
-#include	<unistd.h>
-
-void browse(const char *url)
-{
-    pid_t childpid;
-    const char *args[5];
-
-    char *browser = getenv("BROWSER");
-    if (browser)
-    {	browser = strdup(browser);
-	args[0] = browser;
-	args[1] = url;
-	args[2] = NULL;
-    }
-    else
-    {
-	//browser = "/Applications/Safari.app/Contents/MacOS/Safari";
-	args[0] = "open";
-	args[1] = "-a";
-	args[2] = "/Applications/Safari.app";
-	args[3] = url;
-	args[4] = NULL;
-    }
-
-    childpid = fork();
-    if (childpid == 0)
-    {
-	execvp(args[0], (char**)args);
-	perror(args[0]);		// failed to execute
-	return;
-    }
-}
-
-#endif
-
-
-#if __FreeBSD__
-#endif
--- a/dmd/port.h	Fri Apr 03 16:35:47 2009 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +0,0 @@
-
-// Copyright (c) 1999-2002 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// www.digitalmars.com
-
-#ifndef PORT_H
-#define PORT_H
-
-// Portable wrapper around compiler/system specific things.
-// The idea is to minimize #ifdef's in the app code.
-
-#ifndef TYPEDEFS
-#define TYPEDEFS
-
-#include <wchar.h>
-
-#if _MSC_VER
-typedef __int64 longlong;
-typedef unsigned __int64 ulonglong;
-#else
-typedef long long longlong;
-typedef unsigned long long ulonglong;
-#endif
-
-#endif
-
-typedef double d_time;
-
-struct Port
-{
-    static double nan;
-    static double infinity;
-    static double dbl_max;
-    static double dbl_min;
-
-#if __GNUC__
-    // These conflict with macros in math.h, should rename them
-    #undef isnan
-    #undef isfinite
-    #undef isinfinity
-    #undef signbit
-#endif
-    static int isNan(double);
-    static int isFinite(double);
-    static int isInfinity(double);
-    static int Signbit(double);
-
-    static double floor(double);
-    static double pow(double x, double y);
-
-    static ulonglong strtoull(const char *p, char **pend, int base);
-
-    static char *ull_to_string(char *buffer, ulonglong ull);
-    static wchar_t *ull_to_string(wchar_t *buffer, ulonglong ull);
-
-    // Convert ulonglong to double
-    static double ull_to_double(ulonglong ull);
-
-    // Get locale-dependent list separator
-    static char *list_separator();
-    static wchar_t *wlist_separator();
-};
-
-#endif
--- a/dmd/root.c	Fri Apr 03 16:35:47 2009 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1916 +0,0 @@
-
-// Copyright (c) 1999-2009 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// www.digitalmars.com
-// License for redistribution is by either the Artistic License
-// in artistic.txt, or the GNU General Public License in gnu.txt.
-// See the included readme.txt for details.
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <stdint.h>
-#include <assert.h>
-
-#if (defined (__SVR4) && defined (__sun))
-#include <alloca.h>
-#endif
-
-#if _MSC_VER ||__MINGW32__
-#include <malloc.h>
-#include <string>
-#endif
-
-#if _WIN32
-#include <windows.h>
-#include <direct.h>
-#endif
-
-#if POSIX
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <unistd.h>
-#include <utime.h>
-#endif
-
-#include "port.h"
-#include "root.h"
-#include "dchar.h"
-#include "rmem.h"
-#include "mars.h"
-
-#if 0 //__SC__ //def DEBUG
-extern "C" void __cdecl _assert(void *e, void *f, unsigned line)
-{
-    printf("Assert('%s','%s',%d)\n",e,f,line);
-    fflush(stdout);
-    *(char *)0 = 0;
-}
-#endif
-
-
-/*************************************
- * Convert wchar string to ascii string.
- */
-
-char *wchar2ascii(wchar_t *us)
-{
-    return wchar2ascii(us, wcslen(us));
-}
-
-char *wchar2ascii(wchar_t *us, unsigned len)
-{
-    unsigned i;
-    char *p;
-
-    p = (char *)mem.malloc(len + 1);
-    for (i = 0; i <= len; i++)
-	p[i] = (char) us[i];
-    return p;
-}
-
-int wcharIsAscii(wchar_t *us)
-{
-    return wcharIsAscii(us, wcslen(us));
-}
-
-int wcharIsAscii(wchar_t *us, unsigned len)
-{
-    unsigned i;
-
-    for (i = 0; i <= len; i++)
-    {
-	if (us[i] & ~0xFF)	// if high bits set
-	    return 0;		// it's not ascii
-    }
-    return 1;
-}
-
-
-/***********************************
- * Compare length-prefixed strings (bstr).
- */
-
-int bstrcmp(unsigned char *b1, unsigned char *b2)
-{
-    return (*b1 == *b2 && memcmp(b1 + 1, b2 + 1, *b2) == 0) ? 0 : 1;
-}
-
-/***************************************
- * Convert bstr into a malloc'd string.
- */
-
-char *bstr2str(unsigned char *b)
-{
-    char *s;
-    unsigned len;
-
-    len = *b;
-    s = (char *) mem.malloc(len + 1);
-    s[len] = 0;
-    return (char *)memcpy(s,b + 1,len);
-}
-
-/**************************************
- * Print error message and exit.
- */
-
-void error(const char *format, ...)
-{
-    va_list ap;
-
-    va_start(ap, format);
-    printf("Error: ");
-    vprintf(format, ap);
-    va_end( ap );
-    printf("\n");
-    fflush(stdout);
-
-    exit(EXIT_FAILURE);
-}
-
-#if M_UNICODE
-void error(const dchar *format, ...)
-{
-    va_list ap;
-
-    va_start(ap, format);
-    printf("Error: ");
-    vwprintf(format, ap);
-    va_end( ap );
-    printf("\n");
-    fflush(stdout);
-
-    exit(EXIT_FAILURE);
-}
-#endif
-
-void error_mem()
-{
-    error("out of memory");
-}
-
-/**************************************
- * Print warning message.
- */
-
-void warning(const char *format, ...)
-{
-    va_list ap;
-
-    va_start(ap, format);
-    printf("Warning: ");
-    vprintf(format, ap);
-    va_end( ap );
-    printf("\n");
-    fflush(stdout);
-}
-
-/****************************** Object ********************************/
-
-int Object::equals(Object *o)
-{
-    return o == this;
-}
-
-hash_t Object::hashCode()
-{
-    return (hash_t) this;
-}
-
-int Object::compare(Object *obj)
-{
-    return this - obj;
-}
-
-void Object::print()
-{
-    printf("%s %p\n", toChars(), this);
-}
-
-char *Object::toChars()
-{
-    return (char *)"Object";
-}
-
-dchar *Object::toDchars()
-{
-#if M_UNICODE
-    return L"Object";
-#else
-    return toChars();
-#endif
-}
-
-int Object::dyncast()
-{
-    return 0;
-}
-
-void Object::toBuffer(OutBuffer *b)
-{
-    b->writestring("Object");
-}
-
-void Object::mark()
-{
-}
-
-/****************************** String ********************************/
-
-String::String(char *str, int ref)
-{
-    this->str = ref ? str : mem.strdup(str);
-    this->ref = ref;
-}
-
-String::~String()
-{
-    mem.free(str);
-}
-
-void String::mark()
-{
-    mem.mark(str);
-}
-
-hash_t String::calcHash(const char *str, size_t len)
-{
-    hash_t hash = 0;
-
-    for (;;)
-    {
-	switch (len)
-	{
-	    case 0:
-		return hash;
-
-	    case 1:
-		hash *= 37;
-		hash += *(uint8_t *)str;
-		return hash;
-
-	    case 2:
-		hash *= 37;
-		hash += *(uint16_t *)str;
-		return hash;
-
-	    case 3:
-		hash *= 37;
-		hash += (*(uint16_t *)str << 8) +
-			((uint8_t *)str)[2];
-		return hash;
-
-	    default:
-		hash *= 37;
-		hash += *(uint32_t *)str;
-		str += 4;
-		len -= 4;
-		break;
-	}
-    }
-}
-
-hash_t String::calcHash(const char *str)
-{
-    return calcHash(str, strlen(str));
-}
-
-hash_t String::hashCode()
-{
-    return calcHash(str, strlen(str));
-}
-
-unsigned String::len()
-{
-    return strlen(str);
-}
-
-int String::equals(Object *obj)
-{
-    return strcmp(str,((String *)obj)->str) == 0;
-}
-
-int String::compare(Object *obj)
-{
-    return strcmp(str,((String *)obj)->str);
-}
-
-char *String::toChars()
-{
-    return str;
-}
-
-void String::print()
-{
-    printf("String '%s'\n",str);
-}
-
-
-/****************************** FileName ********************************/
-
-FileName::FileName(char *str, int ref)
-    : String(str,ref)
-{
-}
-
-char *FileName::combine(const char *path, const char *name)
-{   char *f;
-    size_t pathlen;
-    size_t namelen;
-
-    if (!path || !*path)
-	return (char *)name;
-    pathlen = strlen(path);
-    namelen = strlen(name);
-    f = (char *)mem.malloc(pathlen + 1 + namelen + 1);
-    memcpy(f, path, pathlen);
-
-    if (
-	path[pathlen - 1] != '/'
-#if _WIN32
-	&& path[pathlen - 1] != '\\' && path[pathlen - 1] != ':'
-#endif
-    )
-    {	f[pathlen] = '/';
-	pathlen++;
-    }
-
-    memcpy(f + pathlen, name, namelen + 1);
-    return f;
-}
-
-FileName::FileName(char *path, char *name)
-    : String(combine(path,name),1)
-{
-}
-
-// Split a path into an Array of paths
-Array *FileName::splitPath(const char *path)
-{
-    char c = 0;				// unnecessary initializer is for VC /W4
-    const char *p;
-    OutBuffer buf;
-    Array *array;
-
-    array = new Array();
-    if (path)
-    {
-	p = path;
-	do
-	{   char instring = 0;
-
-	    while (isspace(*p))		// skip leading whitespace
-		p++;
-	    buf.reserve(strlen(p) + 1);	// guess size of path
-            // LDC remember first character
-            const char* start = p;
-	    for (; ; p++)
-	    {
-		c = *p;
-		switch (c)
-		{
-		    case '"':
-			instring ^= 1;	// toggle inside/outside of string
-			continue;
-
-#if MACINTOSH
-		    case ',':
-#endif
-#if _WIN32
-		    case ';':
-#endif
-#if POSIX
-		    case ':':
-#endif
-			p++;
-			break;		// note that ; cannot appear as part
-					// of a path, quotes won't protect it
-
-		    case 0x1A:		// ^Z means end of file
-		    case 0:
-			break;
-
-		    case '\r':
-			continue;	// ignore carriage returns
-
-#if POSIX
-		    case '~':
-                        // LDC don't expand unless first character of path
-                        if (p != start)
-                            goto Ldefault;
-			buf.writestring(getenv("HOME"));
-			continue;
-#endif
-
-		    case ' ':
-		    case '\t':		// tabs in filenames?
-			if (!instring)	// if not in string
-			    break;	// treat as end of path
-		    default:
-                    Ldefault:
-			buf.writeByte(c);
-			continue;
-		}
-		break;
-	    }
-	    if (buf.offset)		// if path is not empty
-	    {
-		buf.writeByte(0);	// to asciiz
-		array->push(buf.extractData());
-	    }
-	} while (c);
-    }
-    return array;
-}
-
-hash_t FileName::hashCode()
-{
-#if _WIN32
-    // We need a different hashCode because it must be case-insensitive
-    size_t len = strlen(str);
-    hash_t hash = 0;
-    unsigned char *s = (unsigned char *)str;
-
-    for (;;)
-    {
-	switch (len)
-	{
-	    case 0:
-		return hash;
-
-	    case 1:
-		hash *= 37;
-		hash += *(uint8_t *)s | 0x20;
-		return hash;
-
-	    case 2:
-		hash *= 37;
-		hash += *(uint16_t *)s | 0x2020;
-		return hash;
-
-	    case 3:
-		hash *= 37;
-		hash += ((*(uint16_t *)s << 8) +
-			 ((uint8_t *)s)[2]) | 0x202020;
-		break;
-
-	    default:
-		hash *= 37;
-		hash += *(uint32_t *)s | 0x20202020;
-		s += 4;
-		len -= 4;
-		break;
-	}
-    }
-#else
-    // darwin HFS is case insensitive, though...
-    return String::hashCode();
-#endif
-}
-
-int FileName::compare(Object *obj)
-{
-#if _WIN32
-    return stricmp(str,((FileName *)obj)->str);
-#else
-    return String::compare(obj);
-#endif
-}
-
-int FileName::equals(Object *obj)
-{
-#if _WIN32
-    return stricmp(str,((FileName *)obj)->str) == 0;
-#else
-    return String::equals(obj);
-#endif
-}
-
-/************************************
- * Return !=0 if absolute path name.
- */
-
-int FileName::absolute(const char *name)
-{
-    return
-#if _WIN32
-	(*name == '\\') ||
-	(*name == '/')  ||
-	(*name && name[1] == ':') ||
-#endif
-	(*name == '/');
-}
-
-/********************************
- * Return filename extension (read-only).
- * Points past '.' of extension.
- * If there isn't one, return NULL.
- */
-
-char *FileName::ext(const char *str)
-{
-    char *e;
-    size_t len = strlen(str);
-
-    e = (char *)str + len;
-    for (;;)
-    {
-	switch (*e)
-	{   case '.':
-		return e + 1;
-
-	    case '/':
-	        break;
-
-#if _WIN32
-	    case '\\':
-	    case ':':
-		break;
-#endif
-	    default:
-		if (e == str)
-		    break;
-		e--;
-		continue;
-	}
-	return NULL;
-    }
-}
-
-char *FileName::ext()
-{
-    return ext(str);
-}
-
-/********************************
- * Return mem.malloc'd filename with extension removed.
- */
-
-char *FileName::removeExt(const char *str)
-{
-    const char *e = ext(str);
-    if (e)
-    {	size_t len = (e - str) - 1;
-	char *n = (char *)mem.malloc(len + 1);
-	memcpy(n, str, len);
-	n[len] = 0;
-	return n;
-    }
-    return mem.strdup(str);
-}
-
-/********************************
- * Return filename name excluding path (read-only).
- */
-
-char *FileName::name(const char *str)
-{
-    char *e;
-    size_t len = strlen(str);
-
-    e = (char *)str + len;
-    for (;;)
-    {
-	switch (*e)
-	{
-
-	    case '/':
-	       return e + 1;
-
-#if _WIN32
-	    case '\\':
-	    case ':':
-		return e + 1;
-#endif
-	    default:
-		if (e == str)
-		    break;
-		e--;
-		continue;
-	}
-	return e;
-    }
-}
-
-char *FileName::name()
-{
-    return name(str);
-}
-
-/**************************************
- * Return path portion of str.
- * Path will does not include trailing path separator.
- */
-
-char *FileName::path(const char *str)
-{
-    char *n = name(str);
-    char *path;
-    size_t pathlen;
-
-    if (n > str)
-    {
-
-	if (n[-1] == '/')
-	    n--;
-
-#if _WIN32
-	if (n[-1] == '\\')
-	    n--;
-#endif
-    }
-    pathlen = n - str;
-    path = (char *)mem.malloc(pathlen + 1);
-    memcpy(path, str, pathlen);
-    path[pathlen] = 0;
-    return path;
-}
-
-/**************************************
- * Replace filename portion of path.
- */
-
-char *FileName::replaceName(char *path, char *name)
-{   char *f;
-    char *n;
-    size_t pathlen;
-    size_t namelen;
-
-    if (absolute(name))
-	return name;
-
-    n = FileName::name(path);
-    if (n == path)
-	return name;
-    pathlen = n - path;
-    namelen = strlen(name);
-    f = (char *)mem.malloc(pathlen + 1 + namelen + 1);
-    memcpy(f, path, pathlen);
-
-    if  (
-	path[pathlen - 1] != '/'
-#if _WIN32
-	&& path[pathlen - 1] != '\\' && path[pathlen - 1] != ':'
-#endif
-	)
-    {	f[pathlen] = '/';
-	pathlen++;
-    }
-
-    memcpy(f + pathlen, name, namelen + 1);
-    return f;
-}
-
-/***************************
- */
-
-FileName *FileName::defaultExt(const char *name, const char *ext)
-{
-    char *e;
-    char *s;
-    size_t len;
-    size_t extlen;
-
-    e = FileName::ext(name);
-    if (e)				// if already has an extension
-	return new FileName((char *)name, 0);
-
-    len = strlen(name);
-    extlen = strlen(ext);
-    s = (char *)alloca(len + 1 + extlen + 1);
-    memcpy(s,name,len);
-    s[len] = '.';
-    memcpy(s + len + 1, ext, extlen + 1);
-    return new FileName(s, 0);
-}
-
-/***************************
- */
-
-FileName *FileName::forceExt(const char *name, const char *ext)
-{
-    char *e;
-    char *s;
-    size_t len;
-    size_t extlen;
-
-    e = FileName::ext(name);
-    if (e)				// if already has an extension
-    {
-	len = e - name;
-	extlen = strlen(ext);
-
-	s = (char *)alloca(len + extlen + 1);
-	memcpy(s,name,len);
-	memcpy(s + len, ext, extlen + 1);
-	return new FileName(s, 0);
-    }
-    else
-	return defaultExt(name, ext);	// doesn't have one
-}
-
-/******************************
- * Return !=0 if extensions match.
- */
-
-int FileName::equalsExt(const char *ext)
-{   const char *e;
-
-    e = FileName::ext();
-    if (!e && !ext)
-	return 1;
-    if (!e || !ext)
-	return 0;
-#if POSIX
-    return strcmp(e,ext) == 0;
-#endif
-#if _WIN32
-    return stricmp(e,ext) == 0;
-#endif
-}
-
-/*************************************
- * Copy file from this to to.
- */
-
-void FileName::CopyTo(FileName *to)
-{
-    File file(this);
-
-#if _WIN32
-    file.touchtime = mem.malloc(sizeof(WIN32_FIND_DATAA));	// keep same file time
-#endif
-#if POSIX
-    file.touchtime = mem.malloc(sizeof(struct stat)); // keep same file time
-#endif
-    file.readv();
-    file.name = to;
-    file.writev();
-}
-
-/*************************************
- * Search Path for file.
- * Input:
- *	cwd	if !=0, search current directory before searching path
- */
-
-char *FileName::searchPath(Array *path, const char *name, int cwd)
-{
-    if (absolute(name))
-    {
-	return exists(name) ? (char *)name : NULL;
-    }
-    if (cwd)
-    {
-	if (exists(name))
-	    return (char *)name;
-    }
-    if (path)
-    {	unsigned i;
-
-	for (i = 0; i < path->dim; i++)
-	{
-	    char *p = (char *)path->data[i];
-	    char *n = combine(p, name);
-
-	    if (exists(n))
-		return n;
-	}
-    }
-    return NULL;
-}
-
-int FileName::exists(const char *name)
-{
-#if POSIX
-    struct stat st;
-
-    if (stat(name, &st) < 0)
-	return 0;
-    if (S_ISDIR(st.st_mode))
-	return 2;
-    return 1;
-#endif
-#if _WIN32
-    DWORD dw;
-    int result;
-
-    dw = GetFileAttributesA(name);
-    if (dw == -1L)
-	result = 0;
-    else if (dw & FILE_ATTRIBUTE_DIRECTORY)
-	result = 2;
-    else
-	result = 1;
-    return result;
-#endif
-}
-
-void FileName::ensurePathExists(const char *path)
-{
-    //printf("FileName::ensurePathExists(%s)\n", path ? path : "");
-    if (path && *path)
-    {
-	if (!exists(path))
-	{
-	    char *p = FileName::path(path);
-	    if (*p)
-	    {
-#if _WIN32
-		size_t len = strlen(p);
-		if (len > 2 && p[-1] == ':')
-		{   mem.free(p);
-		    return;
-		}
-#endif
-		ensurePathExists(p);
-		mem.free(p);
-	    }
-#if _WIN32
-	    if (path[strlen(path) - 1] != '\\')
-#endif
-#if POSIX
-	    if (path[strlen(path) - 1] != '\\')
-#endif
-	    {
-		//printf("mkdir(%s)\n", path);
-#if _WIN32
-		if (mkdir(path))
-#endif
-#if POSIX
-		if (mkdir(path, 0777))
-#endif
-		    error("cannot create directory %s", path);
-	    }
-	}
-    }
-}
-
-/****************************** File ********************************/
-
-File::File(FileName *n)
-{
-    ref = 0;
-    buffer = NULL;
-    len = 0;
-    touchtime = NULL;
-    name = n;
-}
-
-File::File(char *n)
-{
-    ref = 0;
-    buffer = NULL;
-    len = 0;
-    touchtime = NULL;
-    name = new FileName(n, 0);
-}
-
-File::~File()
-{
-    if (buffer)
-    {
-	if (ref == 0)
-	    mem.free(buffer);
-#if _WIN32
-	else if (ref == 2)
-	    UnmapViewOfFile(buffer);
-#endif
-    }
-    if (touchtime)
-	mem.free(touchtime);
-}
-
-void File::mark()
-{
-    mem.mark(buffer);
-    mem.mark(touchtime);
-    mem.mark(name);
-}
-
-/*************************************
- */
-
-int File::read()
-{
-#if POSIX
-    off_t size;
-    ssize_t numread;
-    int fd;
-    struct stat buf;
-    int result = 0;
-    char *name;
-
-    name = this->name->toChars();
-    //printf("File::read('%s')\n",name);
-    fd = open(name, O_RDONLY);
-    if (fd == -1)
-    {	result = errno;
-	//printf("\topen error, errno = %d\n",errno);
-	goto err1;
-    }
-
-    if (!ref)
-	mem.free(buffer);
-    ref = 0;       // we own the buffer now
-
-    //printf("\tfile opened\n");
-    if (fstat(fd, &buf))
-    {
-	printf("\tfstat error, errno = %d\n",errno);
-        goto err2;
-    }
-    size = buf.st_size;
-    buffer = (unsigned char *) mem.malloc(size + 2);
-    if (!buffer)
-    {
-	printf("\tmalloc error, errno = %d\n",errno);
-	goto err2;
-    }
-
-    numread = ::read(fd, buffer, size);
-    if (numread != size)
-    {
-	printf("\tread error, errno = %d\n",errno);
-	goto err2;
-    }
-
-    if (touchtime)
-        memcpy(touchtime, &buf, sizeof(buf));
-
-    if (close(fd) == -1)
-    {
-	printf("\tclose error, errno = %d\n",errno);
-	goto err;
-    }
-
-    len = size;
-
-    // Always store a wchar ^Z past end of buffer so scanner has a sentinel
-    buffer[size] = 0;		// ^Z is obsolete, use 0
-    buffer[size + 1] = 0;
-    return 0;
-
-err2:
-    close(fd);
-err:
-    mem.free(buffer);
-    buffer = NULL;
-    len = 0;
-
-err1:
-    result = 1;
-    return result;
-#endif
-#if _WIN32
-    DWORD size;
-    DWORD numread;
-    HANDLE h;
-    int result = 0;
-    char *name;
-
-    name = this->name->toChars();
-    h = CreateFileA(name,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,
-	FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,0);
-    if (h == INVALID_HANDLE_VALUE)
-	goto err1;
-
-    if (!ref)
-	mem.free(buffer);
-    ref = 0;
-
-    size = GetFileSize(h,NULL);
-    buffer = (unsigned char *) mem.malloc(size + 2);
-    if (!buffer)
-	goto err2;
-
-    if (ReadFile(h,buffer,size,&numread,NULL) != TRUE)
-	goto err2;
-
-    if (numread != size)
-	goto err2;
-
-    if (touchtime)
-    {
-	if (!GetFileTime(h, NULL, NULL, &((WIN32_FIND_DATAA *)touchtime)->ftLastWriteTime))
-	    goto err2;
-    }
-
-    if (!CloseHandle(h))
-	goto err;
-
-    len = size;
-
-    // Always store a wchar ^Z past end of buffer so scanner has a sentinel
-    buffer[size] = 0;		// ^Z is obsolete, use 0
-    buffer[size + 1] = 0;
-    return 0;
-
-err2:
-    CloseHandle(h);
-err:
-    mem.free(buffer);
-    buffer = NULL;
-    len = 0;
-
-err1:
-    result = 1;
-    return result;
-#endif
-}
-
-/*****************************
- * Read a file with memory mapped file I/O.
- */
-
-int File::mmread()
-{
-#if POSIX
-    return read();
-#endif
-#if _WIN32
-    HANDLE hFile;
-    HANDLE hFileMap;
-    DWORD size;
-    char *name;
-
-    name = this->name->toChars();
-    hFile = CreateFile(name, GENERIC_READ,
-			FILE_SHARE_READ, NULL,
-			OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
-    if (hFile == INVALID_HANDLE_VALUE)
-	goto Lerr;
-    size = GetFileSize(hFile, NULL);
-    //printf(" file created, size %d\n", size);
-
-    hFileMap = CreateFileMapping(hFile,NULL,PAGE_READONLY,0,size,NULL);
-    if (CloseHandle(hFile) != TRUE)
-	goto Lerr;
-
-    if (hFileMap == NULL)
-	goto Lerr;
-
-    //printf(" mapping created\n");
-
-    if (!ref)
-	mem.free(buffer);
-    ref = 2;
-    buffer = (unsigned char *)MapViewOfFileEx(hFileMap, FILE_MAP_READ,0,0,size,NULL);
-    if (CloseHandle(hFileMap) != TRUE)
-	goto Lerr;
-    if (buffer == NULL)			// mapping view failed
-	goto Lerr;
-
-    len = size;
-    //printf(" buffer = %p\n", buffer);
-
-    return 0;
-
-Lerr:
-    return GetLastError();			// failure
-#endif
-}
-
-/*********************************************
- * Write a file.
- * Returns:
- *	0	success
- */
-
-int File::write()
-{
-#if POSIX
-    int fd;
-    ssize_t numwritten;
-    char *name;
-
-    name = this->name->toChars();
-    fd = open(name, O_CREAT | O_WRONLY | O_TRUNC, 0644);
-    if (fd == -1)
-	goto err;
-
-    numwritten = ::write(fd, buffer, len);
-    if (len != numwritten)
-	goto err2;
-    
-    if (close(fd) == -1)
-	goto err;
-
-    if (touchtime)
-    {   struct utimbuf ubuf;
-
-        ubuf.actime = ((struct stat *)touchtime)->st_atime;
-        ubuf.modtime = ((struct stat *)touchtime)->st_mtime;
-	if (utime(name, &ubuf))
-	    goto err;
-    }
-    return 0;
-
-err2:
-    close(fd);
-    ::remove(name);
-err:
-    return 1;
-#endif
-#if _WIN32
-    HANDLE h;
-    DWORD numwritten;
-    char *name;
-
-    name = this->name->toChars();
-    h = CreateFileA(name,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,
-	FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,NULL);
-    if (h == INVALID_HANDLE_VALUE)
-	goto err;
-
-    if (WriteFile(h,buffer,len,&numwritten,NULL) != TRUE)
-	goto err2;
-
-    if (len != numwritten)
-	goto err2;
-    
-    if (touchtime) {
-        SetFileTime(h, NULL, NULL, &((WIN32_FIND_DATAA *)touchtime)->ftLastWriteTime);
-    }
-    if (!CloseHandle(h))
-	goto err;
-    return 0;
-
-err2:
-    CloseHandle(h);
-    DeleteFileA(name);
-err:
-    return 1;
-#endif
-}
-
-/*********************************************
- * Append to a file.
- * Returns:
- *	0	success
- */
-
-int File::append()
-{
-#if POSIX
-    return 1;
-#endif
-#if _WIN32
-    HANDLE h;
-    DWORD numwritten;
-    char *name;
-
-    name = this->name->toChars();
-    h = CreateFileA(name,GENERIC_WRITE,0,NULL,OPEN_ALWAYS,
-	FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,NULL);
-    if (h == INVALID_HANDLE_VALUE)
-	goto err;
-
-#if 1
-    SetFilePointer(h, 0, NULL, FILE_END);
-#else // INVALID_SET_FILE_POINTER doesn't seem to have a definition
-    if (SetFilePointer(h, 0, NULL, FILE_END) == INVALID_SET_FILE_POINTER)
-	goto err;
-#endif
-
-    if (WriteFile(h,buffer,len,&numwritten,NULL) != TRUE)
-	goto err2;
-
-    if (len != numwritten)
-	goto err2;
-    
-    if (touchtime) {
-        SetFileTime(h, NULL, NULL, &((WIN32_FIND_DATAA *)touchtime)->ftLastWriteTime);
-    }
-    if (!CloseHandle(h))
-	goto err;
-    return 0;
-
-err2:
-    CloseHandle(h);
-err:
-    return 1;
-#endif
-}
-
-/**************************************
- */
-
-void File::readv()
-{
-    if (read())
-	error("Error reading file '%s'\n",name->toChars());
-}
-
-/**************************************
- */
-
-void File::mmreadv()
-{
-    if (mmread())
-	readv();
-}
-
-void File::writev()
-{
-    if (write())
-	error("Error writing file '%s'\n",name->toChars());
-}
-
-void File::appendv()
-{
-    if (write())
-	error("Error appending to file '%s'\n",name->toChars());
-}
-
-/*******************************************
- * Return !=0 if file exists.
- *	0:	file doesn't exist
- *	1:	normal file
- *	2:	directory
- */
-
-int File::exists()
-{
-#if POSIX
-    return 0;
-#endif
-#if _WIN32
-    DWORD dw;
-    int result;
-    char *name;
-
-    name = this->name->toChars();
-    if (touchtime)
-	dw = ((WIN32_FIND_DATAA *)touchtime)->dwFileAttributes;
-    else
-	dw = GetFileAttributesA(name);
-    if (dw == -1L)
-	result = 0;
-    else if (dw & FILE_ATTRIBUTE_DIRECTORY)
-	result = 2;
-    else
-	result = 1;
-    return result;
-#endif
-}
-
-void File::remove()
-{
-#if POSIX
-    ::remove(this->name->toChars());
-#endif
-#if _WIN32
-    DeleteFileA(this->name->toChars());
-#endif
-}
-
-Array *File::match(char *n)
-{
-    return match(new FileName(n, 0));
-}
-
-Array *File::match(FileName *n)
-{
-#if POSIX
-    return NULL;
-#endif
-#if _WIN32
-    HANDLE h;
-    WIN32_FIND_DATAA fileinfo;
-    Array *a;
-    char *c;
-    char *name;
-
-    a = new Array();
-    c = n->toChars();
-    name = n->name();
-    h = FindFirstFileA(c,&fileinfo);
-    if (h != INVALID_HANDLE_VALUE)
-    {
-	do
-	{
-	    // Glue path together with name
-	    char *fn;
-	    File *f;
-
-	    fn = (char *)mem.malloc(name - c + strlen(fileinfo.cFileName) + 1);
-	    memcpy(fn, c, name - c);
-	    strcpy(fn + (name - c), fileinfo.cFileName);
-	    f = new File(fn);
-	    f->touchtime = mem.malloc(sizeof(WIN32_FIND_DATAA));
-	    memcpy(f->touchtime, &fileinfo, sizeof(fileinfo));
-	    a->push(f);
-	} while (FindNextFileA(h,&fileinfo) != FALSE);
-	FindClose(h);
-    }
-    return a;
-#endif
-}
-
-int File::compareTime(File *f)
-{
-#if POSIX
-    return 0;
-#endif
-#if _WIN32
-    if (!touchtime)
-	stat();
-    if (!f->touchtime)
-	f->stat();
-    return CompareFileTime(&((WIN32_FIND_DATAA *)touchtime)->ftLastWriteTime, &((WIN32_FIND_DATAA *)f->touchtime)->ftLastWriteTime);
-#endif
-}
-
-void File::stat()
-{
-#if POSIX
-    if (!touchtime)
-    {
-	touchtime = mem.calloc(1, sizeof(struct stat));
-    }
-#endif
-#if _WIN32
-    HANDLE h;
-
-    if (!touchtime)
-    {
-	touchtime = mem.calloc(1, sizeof(WIN32_FIND_DATAA));
-    }
-    h = FindFirstFileA(name->toChars(),(WIN32_FIND_DATAA *)touchtime);
-    if (h != INVALID_HANDLE_VALUE)
-    {
-	FindClose(h);
-    }
-#endif
-}
-
-void File::checkoffset(size_t offset, size_t nbytes)
-{
-    if (offset > len || offset + nbytes > len)
-	error("Corrupt file '%s': offset x%zx off end of file",toChars(),offset);
-}
-
-char *File::toChars()
-{
-    return name->toChars();
-}
-
-
-/************************* OutBuffer *************************/
-
-OutBuffer::OutBuffer()
-{
-    data = NULL;
-    offset = 0;
-    size = 0;
-}
-
-OutBuffer::~OutBuffer()
-{
-    mem.free(data);
-}
-
-void *OutBuffer::extractData()
-{
-    void *p;
-
-    p = (void *)data;
-    data = NULL;
-    offset = 0;
-    size = 0;
-    return p;
-}
-
-void OutBuffer::mark()
-{
-    mem.mark(data);
-}
-
-void OutBuffer::reserve(unsigned nbytes)
-{
-    //printf("OutBuffer::reserve: size = %d, offset = %d, nbytes = %d\n", size, offset, nbytes);
-    if (size - offset < nbytes)
-    {
-#if defined (__x86_64__)
-	size = (offset + nbytes) * 2 + 2;
-#else
-	size = (offset + nbytes) * 2;
-#endif
-	data = (unsigned char *)mem.realloc(data, size);
-    }
-}
-
-void OutBuffer::reset()
-{
-    offset = 0;
-}
-
-void OutBuffer::setsize(unsigned size)
-{
-    offset = size;
-}
-
-void OutBuffer::write(const void *data, unsigned nbytes)
-{
-    reserve(nbytes);
-    memcpy(this->data + offset, data, nbytes);
-    offset += nbytes;
-}
-
-void OutBuffer::writebstring(unsigned char *string)
-{
-    write(string,*string + 1);
-}
-
-void OutBuffer::writestring(const char *string)
-{
-    write(string,strlen(string));
-}
-
-void OutBuffer::writedstring(const char *string)
-{
-#if M_UNICODE
-    for (; *string; string++)
-    {
-	writedchar(*string);
-    }
-#else
-    write(string,strlen(string));
-#endif
-}
-
-void OutBuffer::writedstring(const wchar_t *string)
-{
-#if M_UNICODE
-    write(string,wcslen(string) * sizeof(wchar_t));
-#else
-    for (; *string; string++)
-    {
-	writedchar(*string);
-    }
-#endif
-}
-
-void OutBuffer::prependstring(const char *string)
-{   unsigned len;
-
-    len = strlen(string);
-    reserve(len);
-    memmove(data + len, data, offset);
-    memcpy(data, string, len);
-    offset += len;
-}
-
-void OutBuffer::writenl()
-{
-#if _WIN32
-#if M_UNICODE
-    write4(0x000A000D);		// newline is CR,LF on Microsoft OS's
-#else
-    writeword(0x0A0D);		// newline is CR,LF on Microsoft OS's
-#endif
-#else
-#if M_UNICODE
-    writeword('\n');
-#else
-    writeByte('\n');
-#endif
-#endif
-}
-
-void OutBuffer::writeByte(unsigned b)
-{
-    reserve(1);
-    this->data[offset] = (unsigned char)b;
-    offset++;
-}
-
-void OutBuffer::writeUTF8(unsigned b)
-{
-    reserve(6);
-    if (b <= 0x7F)
-    {
-	this->data[offset] = (unsigned char)b;
-	offset++;
-    }
-    else if (b <= 0x7FF)
-    {
-	this->data[offset + 0] = (unsigned char)((b >> 6) | 0xC0);
-	this->data[offset + 1] = (unsigned char)((b & 0x3F) | 0x80);
-	offset += 2;
-    }
-    else if (b <= 0xFFFF)
-    {
-	this->data[offset + 0] = (unsigned char)((b >> 12) | 0xE0);
-	this->data[offset + 1] = (unsigned char)(((b >> 6) & 0x3F) | 0x80);
-	this->data[offset + 2] = (unsigned char)((b & 0x3F) | 0x80);
-	offset += 3;
-    }
-    else if (b <= 0x1FFFFF)
-    {
-	this->data[offset + 0] = (unsigned char)((b >> 18) | 0xF0);
-	this->data[offset + 1] = (unsigned char)(((b >> 12) & 0x3F) | 0x80);
-	this->data[offset + 2] = (unsigned char)(((b >> 6) & 0x3F) | 0x80);
-	this->data[offset + 3] = (unsigned char)((b & 0x3F) | 0x80);
-	offset += 4;
-    }
-    else if (b <= 0x3FFFFFF)
-    {
-	this->data[offset + 0] = (unsigned char)((b >> 24) | 0xF8);
-	this->data[offset + 1] = (unsigned char)(((b >> 18) & 0x3F) | 0x80);
-	this->data[offset + 2] = (unsigned char)(((b >> 12) & 0x3F) | 0x80);
-	this->data[offset + 3] = (unsigned char)(((b >> 6) & 0x3F) | 0x80);
-	this->data[offset + 4] = (unsigned char)((b & 0x3F) | 0x80);
-	offset += 5;
-    }
-    else if (b <= 0x7FFFFFFF)
-    {
-	this->data[offset + 0] = (unsigned char)((b >> 30) | 0xFC);
-	this->data[offset + 1] = (unsigned char)(((b >> 24) & 0x3F) | 0x80);
-	this->data[offset + 2] = (unsigned char)(((b >> 18) & 0x3F) | 0x80);
-	this->data[offset + 3] = (unsigned char)(((b >> 12) & 0x3F) | 0x80);
-	this->data[offset + 4] = (unsigned char)(((b >> 6) & 0x3F) | 0x80);
-	this->data[offset + 5] = (unsigned char)((b & 0x3F) | 0x80);
-	offset += 6;
-    }
-    else
-	assert(0);
-}
-
-void OutBuffer::writedchar(unsigned b)
-{
-    reserve(Dchar_mbmax * sizeof(dchar));
-    offset = (unsigned char *)Dchar::put((dchar *)(this->data + offset), (dchar)b) -
-		this->data;
-}
-
-void OutBuffer::prependbyte(unsigned b)
-{
-    reserve(1);
-    memmove(data + 1, data, offset);
-    data[0] = (unsigned char)b;
-    offset++;
-}
-
-void OutBuffer::writeword(unsigned w)
-{
-    reserve(2);
-    *(unsigned short *)(this->data + offset) = (unsigned short)w;
-    offset += 2;
-}
-
-void OutBuffer::writeUTF16(unsigned w)
-{
-    reserve(4);
-    if (w <= 0xFFFF)
-    {
-	*(unsigned short *)(this->data + offset) = (unsigned short)w;
-	offset += 2;
-    }
-    else if (w <= 0x10FFFF)
-    {
-	*(unsigned short *)(this->data + offset) = (unsigned short)((w >> 10) + 0xD7C0);
-	*(unsigned short *)(this->data + offset + 2) = (unsigned short)((w & 0x3FF) | 0xDC00);
-	offset += 4;
-    }
-    else
-	assert(0);
-}
-
-void OutBuffer::write4(unsigned w)
-{
-    reserve(4);
-    *(unsigned long *)(this->data + offset) = w;
-    offset += 4;
-}
-
-void OutBuffer::write(OutBuffer *buf)
-{
-    if (buf)
-    {	reserve(buf->offset);
-	memcpy(data + offset, buf->data, buf->offset);
-	offset += buf->offset;
-    }
-}
-
-void OutBuffer::write(Object *obj)
-{
-    if (obj)
-    {
-	writestring(obj->toChars());
-    }
-}
-
-void OutBuffer::fill0(unsigned nbytes)
-{
-    reserve(nbytes);
-    memset(data + offset,0,nbytes);
-    offset += nbytes;
-}
-
-void OutBuffer::align(unsigned size)
-{   unsigned nbytes;
-
-    nbytes = ((offset + size - 1) & ~(size - 1)) - offset;
-    fill0(nbytes);
-}
-
-
-////////////////////////////////////////////////////////////////
-// The compiler shipped with Visual Studio 2005 (and possible
-// other versions) does not support C99 printf format specfiers
-// such as %z and %j
-#if _MSC_VER
-using std::string;
-using std::wstring;
-
-template<typename S>
-inline void 
-search_and_replace(S& str, const S& what, const S& replacement)
-{
-    assert(!what.empty());
-    size_t pos = str.find(what);
-    while (pos != S::npos) 
-    {
-        str.replace(pos, what.size(), replacement);
-        pos = str.find(what, pos + replacement.size());
-    }
-}
-#define WORKAROUND_C99_SPECIFIERS_BUG(S,tmp,f) \
-    S tmp = f;                                 \
-    search_and_replace(fmt, S("%z"), S("%l")); \
-    search_and_replace(fmt, S("%j"), S("%i")); \
-    f = tmp.c_str();
-#else
-#define WORKAROUND_C99_SPECIFIERS_BUG(S,tmp,f)
-#endif
-
-void OutBuffer::vprintf(const char *format, va_list args)
-{
-    char buffer[128];
-    char *p;
-    unsigned psize;
-    int count;
-
-    WORKAROUND_C99_SPECIFIERS_BUG(string, fmt, format);
-
-    p = buffer;
-    psize = sizeof(buffer);
-    for (;;)
-    {
-#if _WIN32
-	count = _vsnprintf(p,psize,format,args);
-	if (count != -1)
-	    break;
-	psize *= 2;
-#elif POSIX
-        va_list va;
-        va_copy(va, args);
-/*
-  The functions vprintf(), vfprintf(), vsprintf(), vsnprintf()
-  are equivalent to the functions printf(), fprintf(), sprintf(),
-  snprintf(), respectively, except that they are called with a
-  va_list instead of a variable number of arguments. These
-  functions do not call the va_end macro. Consequently, the value
-  of ap is undefined after the call. The application should call
-  va_end(ap) itself afterwards.
- */
-	count = vsnprintf(p,psize,format,va);
-        va_end(va);
-	if (count == -1)
-	    psize *= 2;
-	else if (count >= psize)
-	    psize = count + 1;
-	else
-	    break;
-#endif
-	p = (char *) alloca(psize);	// buffer too small, try again with larger size
-    }
-    write(p,count);
-}
-
-#if M_UNICODE
-void OutBuffer::vprintf(const wchar_t *format, va_list args)
-{
-    dchar buffer[128];
-    dchar *p;
-    unsigned psize;
-    int count;
-
-    WORKAROUND_C99_SPECIFIERS_BUG(wstring, fmt, format);
-
-    p = buffer;
-    psize = sizeof(buffer) / sizeof(buffer[0]);
-    for (;;)
-    {
-#if _WIN32
-	count = _vsnwprintf(p,psize,format,args);
-	if (count != -1)
-	    break;
-	psize *= 2;
-#endif
-#if POSIX
-        va_list va;
-        va_copy(va, args);
-	count = vsnwprintf(p,psize,format,va);
-        va_end(va); 
-
-	if (count == -1)
-	    psize *= 2;
-	else if (count >= psize)
-	    psize = count + 1;
-	else
-	    break;
-#endif
-	p = (dchar *) alloca(psize * 2);	// buffer too small, try again with larger size
-    }
-    write(p,count * 2);
-}
-#endif
-
-void OutBuffer::printf(const char *format, ...)
-{
-    va_list ap;
-    va_start(ap, format);
-    vprintf(format,ap);
-    va_end(ap);
-}
-
-#if M_UNICODE
-void OutBuffer::printf(const wchar_t *format, ...)
-{
-    va_list ap;
-    va_start(ap, format);
-    vprintf(format,ap);
-    va_end(ap);
-}
-#endif
-
-void OutBuffer::bracket(char left, char right)
-{
-    reserve(2);
-    memmove(data + 1, data, offset);
-    data[0] = left;
-    data[offset + 1] = right;
-    offset += 2;
-}
-
-/******************
- * Insert left at i, and right at j.
- * Return index just past right.
- */
-
-unsigned OutBuffer::bracket(unsigned i, const char *left, unsigned j, const char *right)
-{
-    size_t leftlen = strlen(left);
-    size_t rightlen = strlen(right);
-    reserve(leftlen + rightlen);
-    insert(i, left, leftlen);
-    insert(j + leftlen, right, rightlen);
-    return j + leftlen + rightlen;
-}
-
-void OutBuffer::spread(unsigned offset, unsigned nbytes)
-{
-    reserve(nbytes);
-    memmove(data + offset + nbytes, data + offset,
-	this->offset - offset);
-    this->offset += nbytes;
-}
-
-/****************************************
- * Returns: offset + nbytes
- */
-
-unsigned OutBuffer::insert(unsigned offset, const void *p, unsigned nbytes)
-{
-    spread(offset, nbytes);
-    memmove(data + offset, p, nbytes);
-    return offset + nbytes;
-}
-
-void OutBuffer::remove(unsigned offset, unsigned nbytes)
-{
-    memmove(data + offset, data + offset + nbytes, this->offset - (offset + nbytes));
-    this->offset -= nbytes;
-}
-
-char *OutBuffer::toChars()
-{
-    writeByte(0);
-    return (char *)data;
-}
-
-/********************************* Bits ****************************/
-
-Bits::Bits()
-{
-    data = NULL;
-    bitdim = 0;
-    allocdim = 0;
-}
-
-Bits::~Bits()
-{
-    mem.free(data);
-}
-
-void Bits::mark()
-{
-    mem.mark(data);
-}
-
-void Bits::resize(unsigned bitdim)
-{
-    unsigned allocdim;
-    unsigned mask;
-
-    allocdim = (bitdim + 31) / 32;
-    data = (unsigned *)mem.realloc(data, allocdim * sizeof(data[0]));
-    if (this->allocdim < allocdim)
-	memset(data + this->allocdim, 0, (allocdim - this->allocdim) * sizeof(data[0]));
-
-    // Clear other bits in last word
-    mask = (1 << (bitdim & 31)) - 1;
-    if (mask)
-	data[allocdim - 1] &= ~mask;
-
-    this->bitdim = bitdim;
-    this->allocdim = allocdim;
-}
-
-void Bits::set(unsigned bitnum)
-{
-    data[bitnum / 32] |= 1 << (bitnum & 31);
-}
-
-void Bits::clear(unsigned bitnum)
-{
-    data[bitnum / 32] &= ~(1 << (bitnum & 31));
-}
-
-int Bits::test(unsigned bitnum)
-{
-    return data[bitnum / 32] & (1 << (bitnum & 31));
-}
-
-void Bits::set()
-{   unsigned mask;
-
-    memset(data, ~0, allocdim * sizeof(data[0]));
-
-    // Clear other bits in last word
-    mask = (1 << (bitdim & 31)) - 1;
-    if (mask)
-	data[allocdim - 1] &= mask;
-}
-
-void Bits::clear()
-{
-    memset(data, 0, allocdim * sizeof(data[0]));
-}
-
-void Bits::copy(Bits *from)
-{
-    assert(bitdim == from->bitdim);
-    memcpy(data, from->data, allocdim * sizeof(data[0]));
-}
-
-Bits *Bits::clone()
-{
-    Bits *b;
-
-    b = new Bits();
-    b->resize(bitdim);
-    b->copy(this);
-    return b;
-}
-
-void Bits::sub(Bits *b)
-{
-    unsigned u;
-
-    for (u = 0; u < allocdim; u++)
-	data[u] &= ~b->data[u];
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
--- a/dmd/root.h	Fri Apr 03 16:35:47 2009 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,357 +0,0 @@
-
-
-// Copyright (c) 1999-2006 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// www.digitalmars.com
-// License for redistribution is by either the Artistic License
-// in artistic.txt, or the GNU General Public License in gnu.txt.
-// See the included readme.txt for details.
-
-#ifndef ROOT_H
-#define ROOT_H
-
-#include <stdlib.h>
-#include <stdarg.h>
-
-#if __DMC__
-#pragma once
-#endif
-
-typedef size_t hash_t;
-
-#include "dchar.h"
-
-char *wchar2ascii(wchar_t *);
-int wcharIsAscii(wchar_t *);
-char *wchar2ascii(wchar_t *, unsigned len);
-int wcharIsAscii(wchar_t *, unsigned len);
-
-int bstrcmp(unsigned char *s1, unsigned char *s2);
-char *bstr2str(unsigned char *b);
-void error(const char *format, ...);
-void error(const wchar_t *format, ...);
-void warning(const char *format, ...);
-
-#ifndef TYPEDEFS
-#define TYPEDEFS
-
-#if _MSC_VER
-#include <float.h>  // for _isnan
-#include <malloc.h> // for alloca
-// According to VC 8.0 docs, long double is the same as double
-#define strtold strtod
-#define strtof  strtod
-#define isnan   _isnan
-
-typedef __int64 longlong;
-typedef unsigned __int64 ulonglong;
-#else
-typedef long long longlong;
-typedef unsigned long long ulonglong;
-#endif
-
-#endif
-
-longlong randomx();
-
-/*
- * Root of our class library.
- */
-
-struct OutBuffer;
-struct Array;
-
-struct Object
-{
-    Object() { }
-    virtual ~Object() { }
-
-    virtual int equals(Object *o);
-
-    /**
-     * Returns a hash code, useful for things like building hash tables of Objects.
-     */
-    virtual hash_t hashCode();
-
-    /**
-     * Return <0, ==0, or >0 if this is less than, equal to, or greater than obj.
-     * Useful for sorting Objects.
-     */
-    virtual int compare(Object *obj);
-
-    /**
-     * Pretty-print an Object. Useful for debugging the old-fashioned way.
-     */
-    virtual void print();
-
-    virtual char *toChars();
-    virtual dchar *toDchars();
-    virtual void toBuffer(OutBuffer *buf);
-
-    /**
-     * Used as a replacement for dynamic_cast. Returns a unique number
-     * defined by the library user. For Object, the return value is 0.
-     */
-    virtual int dyncast();
-
-    /**
-     * Marks pointers for garbage collector by calling mem.mark() for all pointers into heap.
-     */
-    /*virtual*/		// not used, disable for now
-	void mark();
-};
-
-struct String : Object
-{
-    int ref;			// != 0 if this is a reference to someone else's string
-    char *str;			// the string itself
-
-    String(char *str, int ref = 1);
-
-    ~String();
-
-    static hash_t calcHash(const char *str, size_t len);
-    static hash_t calcHash(const char *str);
-    hash_t hashCode();
-    unsigned len();
-    int equals(Object *obj);
-    int compare(Object *obj);
-    char *toChars();
-    void print();
-    void mark();
-};
-
-struct FileName : String
-{
-    FileName(char *str, int ref);
-    FileName(char *path, char *name);
-    hash_t hashCode();
-    int equals(Object *obj);
-    int compare(Object *obj);
-    static int absolute(const char *name);
-    static char *ext(const char *);
-    char *ext();
-    static char *removeExt(const char *str);
-    static char *name(const char *);
-    char *name();
-    static char *path(const char *);
-    static char *replaceName(char *path, char *name);
-
-    static char *combine(const char *path, const char *name);
-    static Array *splitPath(const char *path);
-    static FileName *defaultExt(const char *name, const char *ext);
-    static FileName *forceExt(const char *name, const char *ext);
-    int equalsExt(const char *ext);
-
-    void CopyTo(FileName *to);
-    static char *searchPath(Array *path, const char *name, int cwd);
-    static int exists(const char *name);
-    static void ensurePathExists(const char *path);
-};
-
-struct File : Object
-{
-    int ref;			// != 0 if this is a reference to someone else's buffer
-    unsigned char *buffer;	// data for our file
-    unsigned len;		// amount of data in buffer[]
-    void *touchtime;		// system time to use for file
-
-    FileName *name;		// name of our file
-
-    File(char *);
-    File(FileName *);
-    ~File();
-
-    void mark();
-
-    char *toChars();
-
-    /* Read file, return !=0 if error
-     */
-
-    int read();
-
-    /* Write file, either succeed or fail
-     * with error message & exit.
-     */
-
-    void readv();
-
-    /* Read file, return !=0 if error
-     */
-
-    int mmread();
-
-    /* Write file, either succeed or fail
-     * with error message & exit.
-     */
-
-    void mmreadv();
-
-    /* Write file, return !=0 if error
-     */
-
-    int write();
-
-    /* Write file, either succeed or fail
-     * with error message & exit.
-     */
-
-    void writev();
-
-    /* Return !=0 if file exists.
-     *	0:	file doesn't exist
-     *	1:	normal file
-     *	2:	directory
-     */
-
-    /* Append to file, return !=0 if error
-     */
-
-    int append();
-
-    /* Append to file, either succeed or fail
-     * with error message & exit.
-     */
-
-    void appendv();
-
-    /* Return !=0 if file exists.
-     *	0:	file doesn't exist
-     *	1:	normal file
-     *	2:	directory
-     */
-
-    int exists();
-
-    /* Given wildcard filespec, return an array of
-     * matching File's.
-     */
-
-    static Array *match(char *);
-    static Array *match(FileName *);
-
-    // Compare file times.
-    // Return	<0	this < f
-    //		=0	this == f
-    //		>0	this > f
-    int compareTime(File *f);
-
-    // Read system file statistics
-    void stat();
-
-    /* Set buffer
-     */
-
-    void setbuffer(void *buffer, unsigned len)
-    {
-	this->buffer = (unsigned char *)buffer;
-	this->len = len;
-    }
-
-    void checkoffset(size_t offset, size_t nbytes);
-
-    void remove();		// delete file
-};
-
-struct OutBuffer : Object
-{
-    unsigned char *data;
-    unsigned offset;
-    unsigned size;
-
-    OutBuffer();
-    ~OutBuffer();
-    void *extractData();
-    void mark();
-
-    void reserve(unsigned nbytes);
-    void setsize(unsigned size);
-    void reset();
-    void write(const void *data, unsigned nbytes);
-    void writebstring(unsigned char *string);
-    void writestring(const char *string);
-    void writedstring(const char *string);
-    void writedstring(const wchar_t *string);
-    void prependstring(const char *string);
-    void writenl();			// write newline
-    void writeByte(unsigned b);
-    void writebyte(unsigned b) { writeByte(b); }
-    void writeUTF8(unsigned b);
-    void writedchar(unsigned b);
-    void prependbyte(unsigned b);
-    void writeword(unsigned w);
-    void writeUTF16(unsigned w);
-    void write4(unsigned w);
-    void write(OutBuffer *buf);
-    void write(Object *obj);
-    void fill0(unsigned nbytes);
-    void align(unsigned size);
-    void vprintf(const char *format, va_list args);
-    void printf(const char *format, ...);
-#if M_UNICODE
-    void vprintf(const unsigned short *format, va_list args);
-    void printf(const unsigned short *format, ...);
-#endif
-    void bracket(char left, char right);
-    unsigned bracket(unsigned i, const char *left, unsigned j, const char *right);
-    void spread(unsigned offset, unsigned nbytes);
-    unsigned insert(unsigned offset, const void *data, unsigned nbytes);
-    void remove(unsigned offset, unsigned nbytes);
-    char *toChars();
-    char *extractString();
-};
-
-struct Array : Object
-{
-    unsigned dim;
-    unsigned allocdim;
-    void **data;
-
-    Array();
-    ~Array();
-    void mark();
-    char *toChars();
-
-    void reserve(unsigned nentries);
-    void setDim(unsigned newdim);
-    void fixDim();
-    void push(void *ptr);
-    void *pop();
-    void shift(void *ptr);
-    void insert(unsigned index, void *ptr);
-    void insert(unsigned index, Array *a);
-    void append(Array *a);
-    void remove(unsigned i);
-    void zero();
-    void *tos();
-    void sort();
-    Array *copy();
-};
-
-struct Bits : Object
-{
-    unsigned bitdim;
-    unsigned allocdim;
-    unsigned *data;
-
-    Bits();
-    ~Bits();
-    void mark();
-
-    void resize(unsigned bitdim);
-
-    void set(unsigned bitnum);
-    void clear(unsigned bitnum);
-    int test(unsigned bitnum);
-
-    void set();
-    void clear();
-    void copy(Bits *from);
-    Bits *clone();
-
-    void sub(Bits *b);
-};
-
-#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/root/array.c	Fri Apr 03 17:02:52 2009 +0200
@@ -0,0 +1,224 @@
+
+// Copyright (c) 1999-2006 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <assert.h>
+
+#if (defined (__SVR4) && defined (__sun)) 
+#include <alloca.h>
+#endif
+
+#if _MSC_VER || __MINGW32__
+#include <malloc.h>
+#endif
+
+#if IN_GCC
+#include "gdc_alloca.h"
+#endif
+
+#if _WIN32
+#include <windows.h>
+#endif
+
+#ifndef _WIN32
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <utime.h>
+#endif
+
+#include "port.h"
+#include "root.h"
+#include "dchar.h"
+#include "rmem.h"
+
+
+/********************************* Array ****************************/
+
+Array::Array()
+{
+    data = NULL;
+    dim = 0;
+    allocdim = 0;
+}
+
+Array::~Array()
+{
+    mem.free(data);
+}
+
+void Array::mark()
+{   unsigned u;
+
+    mem.mark(data);
+    for (u = 0; u < dim; u++)
+	mem.mark(data[u]);	// BUG: what if arrays of Object's?
+}
+
+void Array::reserve(unsigned nentries)
+{
+    //printf("Array::reserve: size = %d, offset = %d, nbytes = %d\n", size, offset, nbytes);
+    if (allocdim - dim < nentries)
+    {
+	allocdim = dim + nentries;
+	data = (void **)mem.realloc(data, allocdim * sizeof(*data));
+    }
+}
+
+void Array::setDim(unsigned newdim)
+{
+    if (dim < newdim)
+    {
+	reserve(newdim - dim);
+    }
+    dim = newdim;
+}
+
+void Array::fixDim()
+{
+    if (dim != allocdim)
+    {	data = (void **)mem.realloc(data, dim * sizeof(*data));
+	allocdim = dim;
+    }
+}
+
+void Array::push(void *ptr)
+{
+    reserve(1);
+    data[dim++] = ptr;
+}
+
+void *Array::pop()
+{
+    return data[--dim];
+}
+
+void Array::shift(void *ptr)
+{
+    reserve(1);
+    memmove(data + 1, data, dim * sizeof(*data));
+    data[0] = ptr;
+    dim++;
+}
+
+void Array::insert(unsigned index, void *ptr)
+{
+    reserve(1);
+    memmove(data + index + 1, data + index, (dim - index) * sizeof(*data));
+    data[index] = ptr;
+    dim++;
+}
+
+
+void Array::insert(unsigned index, Array *a)
+{
+    if (a)
+    {	unsigned d;
+
+	d = a->dim;
+	reserve(d);
+	if (dim != index)
+	    memmove(data + index + d, data + index, (dim - index) * sizeof(*data));
+	memcpy(data + index, a->data, d * sizeof(*data));
+	dim += d;
+    }
+}
+
+
+/***********************************
+ * Append array a to this array.
+ */
+
+void Array::append(Array *a)
+{
+    insert(dim, a);
+}
+
+void Array::remove(unsigned i)
+{
+    memmove(data + i, data + i + 1, (dim - i - 1) * sizeof(data[0]));
+    dim--;
+}
+
+char *Array::toChars()
+{
+    unsigned len;
+    unsigned u;
+    char **buf;
+    char *str;
+    char *p;
+
+    buf = (char **)alloca(dim * sizeof(char *));
+    len = 2;
+    for (u = 0; u < dim; u++)
+    {
+	buf[u] = ((Object *)data[u])->toChars();
+	len += strlen(buf[u]) + 1;
+    }
+    str = (char *)mem.malloc(len);
+
+    str[0] = '[';
+    p = str + 1;
+    for (u = 0; u < dim; u++)
+    {
+	if (u)
+	    *p++ = ',';
+	len = strlen(buf[u]);
+	memcpy(p,buf[u],len);
+	p += len;
+    }
+    *p++ = ']';
+    *p = 0;
+    return str;
+}
+
+void Array::zero()
+{
+    memset(data,0,dim * sizeof(data[0]));
+}
+
+void *Array::tos()
+{
+    return dim ? data[dim - 1] : NULL;
+}
+
+int
+#if _WIN32
+  __cdecl
+#endif
+	Array_sort_compare(const void *x, const void *y)
+{
+    Object *ox = *(Object **)x;
+    Object *oy = *(Object **)y;
+
+    return ox->compare(oy);
+}
+
+void Array::sort()
+{
+    if (dim)
+    {
+	qsort(data, dim, sizeof(Object *), Array_sort_compare);
+    }
+}
+
+Array *Array::copy()
+{
+    Array *a = new Array();
+
+    a->setDim(dim);
+    memcpy(a->data, data, dim * sizeof(void *));
+    return a;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/root/dchar.c	Fri Apr 03 17:02:52 2009 +0200
@@ -0,0 +1,482 @@
+
+// Copyright (c) 1999-2006 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <assert.h>
+
+#include "dchar.h"
+#include "rmem.h"
+
+#if M_UNICODE
+
+// Converts a char string to Unicode
+
+dchar *Dchar::dup(char *p)
+{
+    dchar *s;
+    size_t len;
+
+    if (!p)
+	return NULL;
+    len = strlen(p);
+    s = (dchar *)mem.malloc((len + 1) * sizeof(dchar));
+    for (unsigned i = 0; i < len; i++)
+    {
+	s[i] = (dchar)(p[i] & 0xFF);
+    }
+    s[len] = 0;
+    return s;
+}
+
+dchar *Dchar::memchr(dchar *p, int c, int count)
+{
+    int u;
+
+    for (u = 0; u < count; u++)
+    {
+	if (p[u] == c)
+	    return p + u;
+    }
+    return NULL;
+}
+
+#if _WIN32 && __DMC__
+__declspec(naked)
+unsigned Dchar::calcHash(const dchar *str, unsigned len)
+{
+    __asm
+    {
+	mov	ECX,4[ESP]
+	mov	EDX,8[ESP]
+	xor	EAX,EAX
+	test	EDX,EDX
+	je	L92
+
+LC8:	cmp	EDX,1
+	je	L98
+	cmp	EDX,2
+	je	LAE
+
+	add	EAX,[ECX]
+//	imul	EAX,EAX,025h
+	lea	EAX,[EAX][EAX*8]
+	add	ECX,4
+	sub	EDX,2
+	jmp	LC8
+
+L98:	mov	DX,[ECX]
+	and	EDX,0FFFFh
+	add	EAX,EDX
+	ret
+
+LAE:	add	EAX,[ECX]
+L92:	ret
+    }
+}
+#else
+hash_t Dchar::calcHash(const dchar *str, size_t len)
+{
+    unsigned hash = 0;
+
+    for (;;)
+    {
+	switch (len)
+	{
+	    case 0:
+		return hash;
+
+	    case 1:
+		hash += *(const uint16_t *)str;
+		return hash;
+
+	    case 2:
+		hash += *(const uint32_t *)str;
+		return hash;
+
+	    default:
+		hash += *(const uint32_t *)str;
+		hash *= 37;
+		str += 2;
+		len -= 2;
+		break;
+	}
+    }
+}
+#endif
+
+hash_t Dchar::icalcHash(const dchar *str, size_t len)
+{
+    hash_t hash = 0;
+
+    for (;;)
+    {
+	switch (len)
+	{
+	    case 0:
+		return hash;
+
+	    case 1:
+		hash += *(const uint16_t *)str | 0x20;
+		return hash;
+
+	    case 2:
+		hash += *(const uint32_t *)str | 0x200020;
+		return hash;
+
+	    default:
+		hash += *(const uint32_t *)str | 0x200020;
+		hash *= 37;
+		str += 2;
+		len -= 2;
+		break;
+	}
+    }
+}
+
+#elif MCBS
+
+hash_t Dchar::calcHash(const dchar *str, size_t len)
+{
+    hash_t hash = 0;
+
+    while (1)
+    {
+	switch (len)
+	{
+	    case 0:
+		return hash;
+
+	    case 1:
+		hash *= 37;
+		hash += *(const uint8_t *)str;
+		return hash;
+
+	    case 2:
+		hash *= 37;
+		hash += *(const uint16_t *)str;
+		return hash;
+
+	    case 3:
+		hash *= 37;
+		hash += (*(const uint16_t *)str << 8) +
+			((const uint8_t *)str)[2];
+		return hash;
+
+	    default:
+		hash *= 37;
+		hash += *(const uint32_t *)str;
+		str += 4;
+		len -= 4;
+		break;
+	}
+    }
+}
+
+#elif UTF8
+
+// Specification is: http://anubis.dkuug.dk/JTC1/SC2/WG2/docs/n1335
+
+char Dchar::mblen[256] =
+{
+    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+    2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+    2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+    3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
+    4,4,4,4,4,4,4,4,5,5,5,5,6,6,1,1,
+};
+
+dchar *Dchar::dec(dchar *pstart, dchar *p)
+{
+    while ((p[-1] & 0xC0) == 0x80)
+	p--;
+    return p;
+}
+
+int Dchar::get(dchar *p)
+{
+    unsigned c;
+    unsigned char *q = (unsigned char *)p;
+
+    c = q[0];
+    switch (mblen[c])
+    {
+	case 2:
+	    c = ((c    - 0xC0) << 6) |
+		 (q[1] - 0x80);
+	    break;
+
+	case 3:
+	    c = ((c    - 0xE0) << 12) |
+		((q[1] - 0x80) <<  6) |
+		 (q[2] - 0x80);
+	    break;
+
+	case 4:
+	    c = ((c    - 0xF0) << 18) |
+		((q[1] - 0x80) << 12) |
+		((q[2] - 0x80) <<  6) |
+		 (q[3] - 0x80);
+	    break;
+
+	case 5:
+	    c = ((c    - 0xF8) << 24) |
+		((q[1] - 0x80) << 18) |
+		((q[2] - 0x80) << 12) |
+		((q[3] - 0x80) <<  6) |
+		 (q[4] - 0x80);
+	    break;
+
+	case 6:
+	    c = ((c    - 0xFC) << 30) |
+		((q[1] - 0x80) << 24) |
+		((q[2] - 0x80) << 18) |
+		((q[3] - 0x80) << 12) |
+		((q[4] - 0x80) <<  6) |
+		 (q[5] - 0x80);
+	    break;
+    }
+    return c;
+}
+
+dchar *Dchar::put(dchar *p, unsigned c)
+{
+    if (c <= 0x7F)
+    {
+	*p++ = c;
+    }
+    else if (c <= 0x7FF)
+    {
+	p[0] = 0xC0 + (c >> 6);
+	p[1] = 0x80 + (c & 0x3F);
+	p += 2;
+    }
+    else if (c <= 0xFFFF)
+    {
+	p[0] = 0xE0 + (c >> 12);
+	p[1] = 0x80 + ((c >> 6) & 0x3F);
+	p[2] = 0x80 + (c & 0x3F);
+	p += 3;
+    }
+    else if (c <= 0x1FFFFF)
+    {
+	p[0] = 0xF0 + (c >> 18);
+	p[1] = 0x80 + ((c >> 12) & 0x3F);
+	p[2] = 0x80 + ((c >> 6) & 0x3F);
+	p[3] = 0x80 + (c & 0x3F);
+	p += 4;
+    }
+    else if (c <= 0x3FFFFFF)
+    {
+	p[0] = 0xF8 + (c >> 24);
+	p[1] = 0x80 + ((c >> 18) & 0x3F);
+	p[2] = 0x80 + ((c >> 12) & 0x3F);
+	p[3] = 0x80 + ((c >> 6) & 0x3F);
+	p[4] = 0x80 + (c & 0x3F);
+	p += 5;
+    }
+    else if (c <= 0x7FFFFFFF)
+    {
+	p[0] = 0xFC + (c >> 30);
+	p[1] = 0x80 + ((c >> 24) & 0x3F);
+	p[2] = 0x80 + ((c >> 18) & 0x3F);
+	p[3] = 0x80 + ((c >> 12) & 0x3F);
+	p[4] = 0x80 + ((c >> 6) & 0x3F);
+	p[5] = 0x80 + (c & 0x3F);
+	p += 6;
+    }
+    else
+	assert(0);		// not a UCS-4 character
+    return p;
+}
+
+hash_t Dchar::calcHash(const dchar *str, size_t len)
+{
+    hash_t hash = 0;
+
+    while (1)
+    {
+	switch (len)
+	{
+	    case 0:
+		return hash;
+
+	    case 1:
+		hash *= 37;
+		hash += *(const uint8_t *)str;
+		return hash;
+
+	    case 2:
+		hash *= 37;
+#if __I86__
+		hash += *(const uint16_t *)str;
+#else
+		hash += str[0] * 256 + str[1];
+#endif
+		return hash;
+
+	    case 3:
+		hash *= 37;
+#if __I86__
+		hash += (*(const uint16_t *)str << 8) +
+			((const uint8_t *)str)[2];
+#else
+		hash += (str[0] * 256 + str[1]) * 256 + str[2];
+#endif
+		return hash;
+
+	    default:
+		hash *= 37;
+#if __I86__
+		hash += *(const uint32_t *)str;
+#else
+		hash += ((str[0] * 256 + str[1]) * 256 + str[2]) * 256 + str[3];
+#endif
+
+		str += 4;
+		len -= 4;
+		break;
+	}
+    }
+}
+
+#else // ascii
+
+hash_t Dchar::calcHash(const dchar *str, size_t len)
+{
+    hash_t hash = 0;
+
+    while (1)
+    {
+	switch (len)
+	{
+	    case 0:
+		return hash;
+
+	    case 1:
+		hash *= 37;
+		hash += *(const uint8_t *)str;
+		return hash;
+
+	    case 2:
+		hash *= 37;
+#if __I86__
+		hash += *(const uint16_t *)str;
+#else
+		hash += str[0] * 256 + str[1];
+#endif
+		return hash;
+
+	    case 3:
+		hash *= 37;
+#if __I86__
+		hash += (*(const uint16_t *)str << 8) +
+			((const uint8_t *)str)[2];
+#else
+		hash += (str[0] * 256 + str[1]) * 256 + str[2];
+#endif
+		return hash;
+
+	    default:
+		hash *= 37;
+#if __I86__
+		hash += *(const uint32_t *)str;
+#else
+		hash += ((str[0] * 256 + str[1]) * 256 + str[2]) * 256 + str[3];
+#endif
+		str += 4;
+		len -= 4;
+		break;
+	}
+    }
+}
+
+hash_t Dchar::icalcHash(const dchar *str, size_t len)
+{
+    hash_t hash = 0;
+
+    while (1)
+    {
+	switch (len)
+	{
+	    case 0:
+		return hash;
+
+	    case 1:
+		hash *= 37;
+		hash += *(const uint8_t *)str | 0x20;
+		return hash;
+
+	    case 2:
+		hash *= 37;
+		hash += *(const uint16_t *)str | 0x2020;
+		return hash;
+
+	    case 3:
+		hash *= 37;
+		hash += ((*(const uint16_t *)str << 8) +
+			 ((const uint8_t *)str)[2]) | 0x202020;
+		return hash;
+
+	    default:
+		hash *= 37;
+		hash += *(const uint32_t *)str | 0x20202020;
+		str += 4;
+		len -= 4;
+		break;
+	}
+    }
+}
+
+#endif
+
+#if 0
+#include <stdio.h>
+
+void main()
+{
+    // Print out values to hardcode into Dchar::mblen[]
+    int c;
+    int s;
+
+    for (c = 0; c < 256; c++)
+    {
+	s = 1;
+	if (c >= 0xC0 && c <= 0xDF)
+	    s = 2;
+	if (c >= 0xE0 && c <= 0xEF)
+	    s = 3;
+	if (c >= 0xF0 && c <= 0xF7)
+	    s = 4;
+	if (c >= 0xF8 && c <= 0xFB)
+	    s = 5;
+	if (c >= 0xFC && c <= 0xFD)
+	    s = 6;
+
+	printf("%d", s);
+	if ((c & 15) == 15)
+	    printf(",\n");
+	else
+	    printf(",");
+    }
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/root/dchar.h	Fri Apr 03 17:02:52 2009 +0200
@@ -0,0 +1,194 @@
+
+// Copyright (c) 1999-2006 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+
+#ifndef DCHAR_H
+#define DCHAR_H
+
+#if __GNUC__ && !_WIN32
+#include "gnuc.h"
+#endif
+
+#if _MSC_VER
+    // Disable useless warnings about unreferenced functions
+    #pragma warning (disable : 4514)
+#endif
+
+//#include "root.h"
+typedef size_t hash_t;
+
+#undef TEXT
+
+// NOTE: All functions accepting pointer arguments must not be NULL
+
+#if M_UNICODE
+
+#include <string.h>
+#include <wchar.h>
+
+typedef wchar_t dchar;
+#define TEXT(x)		L##x
+
+#define Dchar_mbmax	1
+
+struct Dchar
+{
+    static dchar *inc(dchar *p) { return p + 1; }
+    static dchar *dec(dchar *pstart, dchar *p) { (void)pstart; return p - 1; }
+    static int len(const dchar *p) { return wcslen(p); }
+    static dchar get(dchar *p) { return *p; }
+    static dchar getprev(dchar *pstart, dchar *p) { (void)pstart; return p[-1]; }
+    static dchar *put(dchar *p, dchar c) { *p = c; return p + 1; }
+    static int cmp(dchar *s1, dchar *s2)
+    {
+#if __DMC__
+	if (!*s1 && !*s2)	// wcscmp is broken
+	    return 0;
+#endif
+	return wcscmp(s1, s2);
+#if 0
+	return (*s1 == *s2)
+	    ? wcscmp(s1, s2)
+	    : ((int)*s1 - (int)*s2);
+#endif
+    }
+    static int memcmp(const dchar *s1, const dchar *s2, int nchars) { return ::memcmp(s1, s2, nchars * sizeof(dchar)); }
+    static int isDigit(dchar c) { return '0' <= c && c <= '9'; }
+    static int isAlpha(dchar c) { return iswalpha(c); }
+    static int isUpper(dchar c) { return iswupper(c); }
+    static int isLower(dchar c) { return iswlower(c); }
+    static int isLocaleUpper(dchar c) { return isUpper(c); }
+    static int isLocaleLower(dchar c) { return isLower(c); }
+    static int toLower(dchar c) { return isUpper(c) ? towlower(c) : c; }
+    static int toLower(dchar *p) { return toLower(*p); }
+    static int toUpper(dchar c) { return isLower(c) ? towupper(c) : c; }
+    static dchar *dup(dchar *p) { return ::_wcsdup(p); }	// BUG: out of memory?
+    static dchar *dup(char *p);
+    static dchar *chr(dchar *p, unsigned c) { return wcschr(p, (dchar)c); }
+    static dchar *rchr(dchar *p, unsigned c) { return wcsrchr(p, (dchar)c); }
+    static dchar *memchr(dchar *p, int c, int count);
+    static dchar *cpy(dchar *s1, dchar *s2) { return wcscpy(s1, s2); }
+    static dchar *str(dchar *s1, dchar *s2) { return wcsstr(s1, s2); }
+    static hash_t calcHash(const dchar *str, size_t len);
+
+    // Case insensitive versions
+    static int icmp(dchar *s1, dchar *s2) { return wcsicmp(s1, s2); }
+    static int memicmp(const dchar *s1, const dchar *s2, int nchars) { return ::wcsnicmp(s1, s2, nchars); }
+    static hash_t icalcHash(const dchar *str, size_t len);
+};
+
+#elif MCBS
+
+#include <limits.h>
+#include <mbstring.h>
+
+typedef char dchar;
+#define TEXT(x)		x
+
+#define Dchar_mbmax	MB_LEN_MAX
+
+#elif UTF8
+
+typedef char dchar;
+#define TEXT(x)		x
+
+#define Dchar_mbmax	6
+
+struct Dchar
+{
+    static char mblen[256];
+
+    static dchar *inc(dchar *p) { return p + mblen[*p & 0xFF]; }
+    static dchar *dec(dchar *pstart, dchar *p);
+    static int len(const dchar *p) { return strlen(p); }
+    static int get(dchar *p);
+    static int getprev(dchar *pstart, dchar *p)
+	{ return *dec(pstart, p) & 0xFF; }
+    static dchar *put(dchar *p, unsigned c);
+    static int cmp(dchar *s1, dchar *s2) { return strcmp(s1, s2); }
+    static int memcmp(const dchar *s1, const dchar *s2, int nchars) { return ::memcmp(s1, s2, nchars); }
+    static int isDigit(dchar c) { return '0' <= c && c <= '9'; }
+    static int isAlpha(dchar c) { return c <= 0x7F ? isalpha(c) : 0; }
+    static int isUpper(dchar c) { return c <= 0x7F ? isupper(c) : 0; }
+    static int isLower(dchar c) { return c <= 0x7F ? islower(c) : 0; }
+    static int isLocaleUpper(dchar c) { return isUpper(c); }
+    static int isLocaleLower(dchar c) { return isLower(c); }
+    static int toLower(dchar c) { return isUpper(c) ? tolower(c) : c; }
+    static int toLower(dchar *p) { return toLower(*p); }
+    static int toUpper(dchar c) { return isLower(c) ? toupper(c) : c; }
+    static dchar *dup(dchar *p) { return ::strdup(p); }	// BUG: out of memory?
+    static dchar *chr(dchar *p, int c) { return strchr(p, c); }
+    static dchar *rchr(dchar *p, int c) { return strrchr(p, c); }
+    static dchar *memchr(dchar *p, int c, int count)
+	{ return (dchar *)::memchr(p, c, count); }
+    static dchar *cpy(dchar *s1, dchar *s2) { return strcpy(s1, s2); }
+    static dchar *str(dchar *s1, dchar *s2) { return strstr(s1, s2); }
+    static hash_t calcHash(const dchar *str, size_t len);
+
+    // Case insensitive versions
+    static int icmp(dchar *s1, dchar *s2) { return _mbsicmp(s1, s2); }
+    static int memicmp(const dchar *s1, const dchar *s2, int nchars) { return ::_mbsnicmp(s1, s2, nchars); }
+};
+
+#else
+
+#include <string.h>
+
+#ifndef GCC_SAFE_DMD
+#include <ctype.h>
+#endif
+
+typedef char dchar;
+#define TEXT(x)		x
+
+#define Dchar_mbmax	1
+
+struct Dchar
+{
+    static dchar *inc(dchar *p) { return p + 1; }
+    static dchar *dec(dchar *pstart, dchar *p) { return p - 1; }
+    static int len(const dchar *p) { return strlen(p); }
+    static int get(dchar *p) { return *p & 0xFF; }
+    static int getprev(dchar *pstart, dchar *p) { return p[-1] & 0xFF; }
+    static dchar *put(dchar *p, unsigned c) { *p = c; return p + 1; }
+    static int cmp(dchar *s1, dchar *s2) { return strcmp(s1, s2); }
+    static int memcmp(const dchar *s1, const dchar *s2, int nchars) { return ::memcmp(s1, s2, nchars); }
+    static int isDigit(dchar c) { return '0' <= c && c <= '9'; }
+#ifndef GCC_SAFE_DMD
+    static int isAlpha(dchar c) { return isalpha(c); }
+    static int isUpper(dchar c) { return isupper(c); }
+    static int isLower(dchar c) { return islower(c); }
+    static int isLocaleUpper(dchar c) { return isupper(c); }
+    static int isLocaleLower(dchar c) { return islower(c); }
+    static int toLower(dchar c) { return isupper(c) ? tolower(c) : c; }
+    static int toLower(dchar *p) { return toLower(*p); }
+    static int toUpper(dchar c) { return islower(c) ? toupper(c) : c; }
+    static dchar *dup(dchar *p) { return ::strdup(p); }	// BUG: out of memory?
+#endif
+    static dchar *chr(dchar *p, int c) { return strchr(p, c); }
+    static dchar *rchr(dchar *p, int c) { return strrchr(p, c); }
+    static dchar *memchr(dchar *p, int c, int count)
+	{ return (dchar *)::memchr(p, c, count); }
+    static dchar *cpy(dchar *s1, dchar *s2) { return strcpy(s1, s2); }
+    static dchar *str(dchar *s1, dchar *s2) { return strstr(s1, s2); }
+    static hash_t calcHash(const dchar *str, size_t len);
+
+    // Case insensitive versions
+#ifdef __GNUC__
+    static int icmp(dchar *s1, dchar *s2) { return strcasecmp(s1, s2); }
+#else
+    static int icmp(dchar *s1, dchar *s2) { return stricmp(s1, s2); }
+#endif
+    static int memicmp(const dchar *s1, const dchar *s2, int nchars) { return ::memicmp(s1, s2, nchars); }
+    static hash_t icalcHash(const dchar *str, size_t len);
+};
+
+#endif
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/root/gnuc.c	Fri Apr 03 17:02:52 2009 +0200
@@ -0,0 +1,55 @@
+
+// Put functions in here missing from gnu C
+
+#include "gnuc.h"
+
+int memicmp(const char *s1, const char *s2, int n)
+{
+    int result = 0;
+
+    for (int i = 0; i < n; i++)
+    {	char c1 = s1[i];
+	char c2 = s2[i];
+
+	result = c1 - c2;
+	if (result)
+	{
+	    if ('A' <= c1 && c1 <= 'Z')
+		c1 += 'a' - 'A';
+	    if ('A' <= c2 && c2 <= 'Z')
+		c2 += 'a' - 'A';
+	    result = c1 - c2;
+	    if (result)
+		break;
+	}
+    }
+    return result;
+}
+
+int stricmp(const char *s1, const char *s2)
+{
+    int result = 0;
+
+    for (;;)
+    {	char c1 = *s1;
+	char c2 = *s2;
+
+	result = c1 - c2;
+	if (result)
+	{
+	    if ('A' <= c1 && c1 <= 'Z')
+		c1 += 'a' - 'A';
+	    if ('A' <= c2 && c2 <= 'Z')
+		c2 += 'a' - 'A';
+	    result = c1 - c2;
+	    if (result)
+		break;
+	}
+	if (!c1)
+	    break;
+	s1++;
+	s2++;
+    }
+    return result;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/root/gnuc.h	Fri Apr 03 17:02:52 2009 +0200
@@ -0,0 +1,8 @@
+
+#ifndef _GNUC_H
+#define _GNUC_H 1
+
+int memicmp(const char *s1, const char *s2, int n);
+int stricmp(const char *s1, const char *s2);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/root/lstring.c	Fri Apr 03 17:02:52 2009 +0200
@@ -0,0 +1,63 @@
+// lstring.c
+
+// Copyright (c) 1999-2002 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+#include <stdlib.h>
+
+#include "dchar.h"
+#include "rmem.h"
+#include "lstring.h"
+
+#ifdef _MSC_VER // prevent compiler internal crash
+Lstring Lstring::zero;
+#else
+Lstring Lstring::zero = LSTRING_EMPTY();
+#endif
+
+Lstring *Lstring::ctor(const dchar *p, unsigned length)
+{
+    Lstring *s;
+
+    s = alloc(length);
+    memcpy(s->string, p, length * sizeof(dchar));
+    return s;
+}
+
+Lstring *Lstring::alloc(unsigned length)
+{
+    Lstring *s;
+
+    s = (Lstring *)mem.malloc(size(length));
+    s->length = length;
+    s->string[length] = 0;
+    return s;
+}
+
+Lstring *Lstring::append(const Lstring *s)
+{
+    Lstring *t;
+
+    if (!s->length)
+	return this;
+    t = alloc(length + s->length);
+    memcpy(t->string, string, length * sizeof(dchar));
+    memcpy(t->string + length, s->string, s->length * sizeof(dchar));
+    return t;
+}
+
+Lstring *Lstring::substring(int start, int end)
+{
+    Lstring *t;
+
+    if (start == end)
+	return &zero;
+    t = alloc(end - start);
+    memcpy(t->string, string + start, (end - start) * sizeof(dchar));
+    return t;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/root/lstring.h	Fri Apr 03 17:02:52 2009 +0200
@@ -0,0 +1,72 @@
+
+// lstring.h
+// length-prefixed strings
+
+// Copyright (c) 1999-2002 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+#ifndef LSTRING_H
+#define LSTRING_H 1
+
+#include "dchar.h"
+
+struct Lstring
+{
+    unsigned length;
+
+    // Disable warning about nonstandard extension
+    #pragma warning (disable : 4200)
+    dchar string[];
+
+    static Lstring zero;	// 0 length string
+
+    // No constructors because we want to be able to statically
+    // initialize Lstring's, and Lstrings are of variable size.
+
+    #if M_UNICODE
+    #define LSTRING(p,length) { length, L##p }
+    #else
+    #define LSTRING(p,length) { length, p }
+    #endif
+
+#if __GNUC__
+    #define LSTRING_EMPTY() { 0 }
+#else
+    #define LSTRING_EMPTY() LSTRING("", 0)
+#endif
+
+    static Lstring *ctor(const dchar *p) { return ctor(p, Dchar::len(p)); }
+    static Lstring *ctor(const dchar *p, unsigned length);
+    static unsigned size(unsigned length) { return sizeof(Lstring) + (length + 1) * sizeof(dchar); }
+    static Lstring *alloc(unsigned length);
+    Lstring *clone();
+
+    unsigned len() { return length; }
+
+    dchar *toDchars() { return string; }
+
+    hash_t hash() { return Dchar::calcHash(string, length); }
+    hash_t ihash() { return Dchar::icalcHash(string, length); }
+
+    static int cmp(const Lstring *s1, const Lstring *s2)
+    {
+	int c = s2->length - s1->length;
+	return c ? c : Dchar::memcmp(s1->string, s2->string, s1->length);
+    }
+
+    static int icmp(const Lstring *s1, const Lstring *s2)
+    {
+	int c = s2->length - s1->length;
+	return c ? c : Dchar::memicmp(s1->string, s2->string, s1->length);
+    }
+
+    Lstring *append(const Lstring *s);
+    Lstring *substring(int start, int end);
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/root/man.c	Fri Apr 03 17:02:52 2009 +0200
@@ -0,0 +1,102 @@
+
+// Compiler implementation of the D programming language
+// Copyright (c) 2008-2009 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// http://www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#if _WIN32
+
+#include <windows.h>
+
+#pragma comment(lib,"shell32.lib")
+
+void browse(const char *url)
+{
+    ShellExecute(NULL, "open", url, NULL, NULL, SW_SHOWNORMAL);
+}
+
+#endif
+
+#if linux
+
+#include	<sys/types.h>
+#include	<sys/wait.h>
+#include	<unistd.h>
+
+void browse(const char *url)
+{
+    pid_t childpid;
+    const char *args[3];
+
+    char *browser = getenv("BROWSER");
+    if (browser)
+	browser = strdup(browser);
+    else
+	browser = "x-www-browser";
+
+    args[0] = browser;
+    args[1] = url;
+    args[2] = NULL;
+
+    childpid = fork();
+    if (childpid == 0)
+    {
+	execvp(args[0], (char**)args);
+	perror(args[0]);		// failed to execute
+	return;
+    }
+}
+
+#endif
+
+#if __APPLE__
+
+#include	<sys/types.h>
+#include	<sys/wait.h>
+#include	<unistd.h>
+
+void browse(const char *url)
+{
+    pid_t childpid;
+    const char *args[5];
+
+    char *browser = getenv("BROWSER");
+    if (browser)
+    {	browser = strdup(browser);
+	args[0] = browser;
+	args[1] = url;
+	args[2] = NULL;
+    }
+    else
+    {
+	//browser = "/Applications/Safari.app/Contents/MacOS/Safari";
+	args[0] = "open";
+	args[1] = "-a";
+	args[2] = "/Applications/Safari.app";
+	args[3] = url;
+	args[4] = NULL;
+    }
+
+    childpid = fork();
+    if (childpid == 0)
+    {
+	execvp(args[0], (char**)args);
+	perror(args[0]);		// failed to execute
+	return;
+    }
+}
+
+#endif
+
+
+#if __FreeBSD__
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/root/port.h	Fri Apr 03 17:02:52 2009 +0200
@@ -0,0 +1,65 @@
+
+// Copyright (c) 1999-2002 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// www.digitalmars.com
+
+#ifndef PORT_H
+#define PORT_H
+
+// Portable wrapper around compiler/system specific things.
+// The idea is to minimize #ifdef's in the app code.
+
+#ifndef TYPEDEFS
+#define TYPEDEFS
+
+#include <wchar.h>
+
+#if _MSC_VER
+typedef __int64 longlong;
+typedef unsigned __int64 ulonglong;
+#else
+typedef long long longlong;
+typedef unsigned long long ulonglong;
+#endif
+
+#endif
+
+typedef double d_time;
+
+struct Port
+{
+    static double nan;
+    static double infinity;
+    static double dbl_max;
+    static double dbl_min;
+
+#if __GNUC__
+    // These conflict with macros in math.h, should rename them
+    #undef isnan
+    #undef isfinite
+    #undef isinfinity
+    #undef signbit
+#endif
+    static int isNan(double);
+    static int isFinite(double);
+    static int isInfinity(double);
+    static int Signbit(double);
+
+    static double floor(double);
+    static double pow(double x, double y);
+
+    static ulonglong strtoull(const char *p, char **pend, int base);
+
+    static char *ull_to_string(char *buffer, ulonglong ull);
+    static wchar_t *ull_to_string(wchar_t *buffer, ulonglong ull);
+
+    // Convert ulonglong to double
+    static double ull_to_double(ulonglong ull);
+
+    // Get locale-dependent list separator
+    static char *list_separator();
+    static wchar_t *wlist_separator();
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/root/root.c	Fri Apr 03 17:02:52 2009 +0200
@@ -0,0 +1,1916 @@
+
+// Copyright (c) 1999-2009 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <stdint.h>
+#include <assert.h>
+
+#if (defined (__SVR4) && defined (__sun))
+#include <alloca.h>
+#endif
+
+#if _MSC_VER ||__MINGW32__
+#include <malloc.h>
+#include <string>
+#endif
+
+#if _WIN32
+#include <windows.h>
+#include <direct.h>
+#endif
+
+#if POSIX
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <utime.h>
+#endif
+
+#include "port.h"
+#include "root.h"
+#include "dchar.h"
+#include "rmem.h"
+#include "mars.h"
+
+#if 0 //__SC__ //def DEBUG
+extern "C" void __cdecl _assert(void *e, void *f, unsigned line)
+{
+    printf("Assert('%s','%s',%d)\n",e,f,line);
+    fflush(stdout);
+    *(char *)0 = 0;
+}
+#endif
+
+
+/*************************************
+ * Convert wchar string to ascii string.
+ */
+
+char *wchar2ascii(wchar_t *us)
+{
+    return wchar2ascii(us, wcslen(us));
+}
+
+char *wchar2ascii(wchar_t *us, unsigned len)
+{
+    unsigned i;
+    char *p;
+
+    p = (char *)mem.malloc(len + 1);
+    for (i = 0; i <= len; i++)
+	p[i] = (char) us[i];
+    return p;
+}
+
+int wcharIsAscii(wchar_t *us)
+{
+    return wcharIsAscii(us, wcslen(us));
+}
+
+int wcharIsAscii(wchar_t *us, unsigned len)
+{
+    unsigned i;
+
+    for (i = 0; i <= len; i++)
+    {
+	if (us[i] & ~0xFF)	// if high bits set
+	    return 0;		// it's not ascii
+    }
+    return 1;
+}
+
+
+/***********************************
+ * Compare length-prefixed strings (bstr).
+ */
+
+int bstrcmp(unsigned char *b1, unsigned char *b2)
+{
+    return (*b1 == *b2 && memcmp(b1 + 1, b2 + 1, *b2) == 0) ? 0 : 1;
+}
+
+/***************************************
+ * Convert bstr into a malloc'd string.
+ */
+
+char *bstr2str(unsigned char *b)
+{
+    char *s;
+    unsigned len;
+
+    len = *b;
+    s = (char *) mem.malloc(len + 1);
+    s[len] = 0;
+    return (char *)memcpy(s,b + 1,len);
+}
+
+/**************************************
+ * Print error message and exit.
+ */
+
+void error(const char *format, ...)
+{
+    va_list ap;
+
+    va_start(ap, format);
+    printf("Error: ");
+    vprintf(format, ap);
+    va_end( ap );
+    printf("\n");
+    fflush(stdout);
+
+    exit(EXIT_FAILURE);
+}
+
+#if M_UNICODE
+void error(const dchar *format, ...)
+{
+    va_list ap;
+
+    va_start(ap, format);
+    printf("Error: ");
+    vwprintf(format, ap);
+    va_end( ap );
+    printf("\n");
+    fflush(stdout);
+
+    exit(EXIT_FAILURE);
+}
+#endif
+
+void error_mem()
+{
+    error("out of memory");
+}
+
+/**************************************
+ * Print warning message.
+ */
+
+void warning(const char *format, ...)
+{
+    va_list ap;
+
+    va_start(ap, format);
+    printf("Warning: ");
+    vprintf(format, ap);
+    va_end( ap );
+    printf("\n");
+    fflush(stdout);
+}
+
+/****************************** Object ********************************/
+
+int Object::equals(Object *o)
+{
+    return o == this;
+}
+
+hash_t Object::hashCode()
+{
+    return (hash_t) this;
+}
+
+int Object::compare(Object *obj)
+{
+    return this - obj;
+}
+
+void Object::print()
+{
+    printf("%s %p\n", toChars(), this);
+}
+
+char *Object::toChars()
+{
+    return (char *)"Object";
+}
+
+dchar *Object::toDchars()
+{
+#if M_UNICODE
+    return L"Object";
+#else
+    return toChars();
+#endif
+}
+
+int Object::dyncast()
+{
+    return 0;
+}
+
+void Object::toBuffer(OutBuffer *b)
+{
+    b->writestring("Object");
+}
+
+void Object::mark()
+{
+}
+
+/****************************** String ********************************/
+
+String::String(char *str, int ref)
+{
+    this->str = ref ? str : mem.strdup(str);
+    this->ref = ref;
+}
+
+String::~String()
+{
+    mem.free(str);
+}
+
+void String::mark()
+{
+    mem.mark(str);
+}
+
+hash_t String::calcHash(const char *str, size_t len)
+{
+    hash_t hash = 0;
+
+    for (;;)
+    {
+	switch (len)
+	{
+	    case 0:
+		return hash;
+
+	    case 1:
+		hash *= 37;
+		hash += *(uint8_t *)str;
+		return hash;
+
+	    case 2:
+		hash *= 37;
+		hash += *(uint16_t *)str;
+		return hash;
+
+	    case 3:
+		hash *= 37;
+		hash += (*(uint16_t *)str << 8) +
+			((uint8_t *)str)[2];
+		return hash;
+
+	    default:
+		hash *= 37;
+		hash += *(uint32_t *)str;
+		str += 4;
+		len -= 4;
+		break;
+	}
+    }
+}
+
+hash_t String::calcHash(const char *str)
+{
+    return calcHash(str, strlen(str));
+}
+
+hash_t String::hashCode()
+{
+    return calcHash(str, strlen(str));
+}
+
+unsigned String::len()
+{
+    return strlen(str);
+}
+
+int String::equals(Object *obj)
+{
+    return strcmp(str,((String *)obj)->str) == 0;
+}
+
+int String::compare(Object *obj)
+{
+    return strcmp(str,((String *)obj)->str);
+}
+
+char *String::toChars()
+{
+    return str;
+}
+
+void String::print()
+{
+    printf("String '%s'\n",str);
+}
+
+
+/****************************** FileName ********************************/
+
+FileName::FileName(char *str, int ref)
+    : String(str,ref)
+{
+}
+
+char *FileName::combine(const char *path, const char *name)
+{   char *f;
+    size_t pathlen;
+    size_t namelen;
+
+    if (!path || !*path)
+	return (char *)name;
+    pathlen = strlen(path);
+    namelen = strlen(name);
+    f = (char *)mem.malloc(pathlen + 1 + namelen + 1);
+    memcpy(f, path, pathlen);
+
+    if (
+	path[pathlen - 1] != '/'
+#if _WIN32
+	&& path[pathlen - 1] != '\\' && path[pathlen - 1] != ':'
+#endif
+    )
+    {	f[pathlen] = '/';
+	pathlen++;
+    }
+
+    memcpy(f + pathlen, name, namelen + 1);
+    return f;
+}
+
+FileName::FileName(char *path, char *name)
+    : String(combine(path,name),1)
+{
+}
+
+// Split a path into an Array of paths
+Array *FileName::splitPath(const char *path)
+{
+    char c = 0;				// unnecessary initializer is for VC /W4
+    const char *p;
+    OutBuffer buf;
+    Array *array;
+
+    array = new Array();
+    if (path)
+    {
+	p = path;
+	do
+	{   char instring = 0;
+
+	    while (isspace(*p))		// skip leading whitespace
+		p++;
+	    buf.reserve(strlen(p) + 1);	// guess size of path
+            // LDC remember first character
+            const char* start = p;
+	    for (; ; p++)
+	    {
+		c = *p;
+		switch (c)
+		{
+		    case '"':
+			instring ^= 1;	// toggle inside/outside of string
+			continue;
+
+#if MACINTOSH
+		    case ',':
+#endif
+#if _WIN32
+		    case ';':
+#endif
+#if POSIX
+		    case ':':
+#endif
+			p++;
+			break;		// note that ; cannot appear as part
+					// of a path, quotes won't protect it
+
+		    case 0x1A:		// ^Z means end of file
+		    case 0:
+			break;
+
+		    case '\r':
+			continue;	// ignore carriage returns
+
+#if POSIX
+		    case '~':
+                        // LDC don't expand unless first character of path
+                        if (p != start)
+                            goto Ldefault;
+			buf.writestring(getenv("HOME"));
+			continue;
+#endif
+
+		    case ' ':
+		    case '\t':		// tabs in filenames?
+			if (!instring)	// if not in string
+			    break;	// treat as end of path
+		    default:
+                    Ldefault:
+			buf.writeByte(c);
+			continue;
+		}
+		break;
+	    }
+	    if (buf.offset)		// if path is not empty
+	    {
+		buf.writeByte(0);	// to asciiz
+		array->push(buf.extractData());
+	    }
+	} while (c);
+    }
+    return array;
+}
+
+hash_t FileName::hashCode()
+{
+#if _WIN32
+    // We need a different hashCode because it must be case-insensitive
+    size_t len = strlen(str);
+    hash_t hash = 0;
+    unsigned char *s = (unsigned char *)str;
+
+    for (;;)
+    {
+	switch (len)
+	{
+	    case 0:
+		return hash;
+
+	    case 1:
+		hash *= 37;
+		hash += *(uint8_t *)s | 0x20;
+		return hash;
+
+	    case 2:
+		hash *= 37;
+		hash += *(uint16_t *)s | 0x2020;
+		return hash;
+
+	    case 3:
+		hash *= 37;
+		hash += ((*(uint16_t *)s << 8) +
+			 ((uint8_t *)s)[2]) | 0x202020;
+		break;
+
+	    default:
+		hash *= 37;
+		hash += *(uint32_t *)s | 0x20202020;
+		s += 4;
+		len -= 4;
+		break;
+	}
+    }
+#else
+    // darwin HFS is case insensitive, though...
+    return String::hashCode();
+#endif
+}
+
+int FileName::compare(Object *obj)
+{
+#if _WIN32
+    return stricmp(str,((FileName *)obj)->str);
+#else
+    return String::compare(obj);
+#endif
+}
+
+int FileName::equals(Object *obj)
+{
+#if _WIN32
+    return stricmp(str,((FileName *)obj)->str) == 0;
+#else
+    return String::equals(obj);
+#endif
+}
+
+/************************************
+ * Return !=0 if absolute path name.
+ */
+
+int FileName::absolute(const char *name)
+{
+    return
+#if _WIN32
+	(*name == '\\') ||
+	(*name == '/')  ||
+	(*name && name[1] == ':') ||
+#endif
+	(*name == '/');
+}
+
+/********************************
+ * Return filename extension (read-only).
+ * Points past '.' of extension.
+ * If there isn't one, return NULL.
+ */
+
+char *FileName::ext(const char *str)
+{
+    char *e;
+    size_t len = strlen(str);
+
+    e = (char *)str + len;
+    for (;;)
+    {
+	switch (*e)
+	{   case '.':
+		return e + 1;
+
+	    case '/':
+	        break;
+
+#if _WIN32
+	    case '\\':
+	    case ':':
+		break;
+#endif
+	    default:
+		if (e == str)
+		    break;
+		e--;
+		continue;
+	}
+	return NULL;
+    }
+}
+
+char *FileName::ext()
+{
+    return ext(str);
+}
+
+/********************************
+ * Return mem.malloc'd filename with extension removed.
+ */
+
+char *FileName::removeExt(const char *str)
+{
+    const char *e = ext(str);
+    if (e)
+    {	size_t len = (e - str) - 1;
+	char *n = (char *)mem.malloc(len + 1);
+	memcpy(n, str, len);
+	n[len] = 0;
+	return n;
+    }
+    return mem.strdup(str);
+}
+
+/********************************
+ * Return filename name excluding path (read-only).
+ */
+
+char *FileName::name(const char *str)
+{
+    char *e;
+    size_t len = strlen(str);
+
+    e = (char *)str + len;
+    for (;;)
+    {
+	switch (*e)
+	{
+
+	    case '/':
+	       return e + 1;
+
+#if _WIN32
+	    case '\\':
+	    case ':':
+		return e + 1;
+#endif
+	    default:
+		if (e == str)
+		    break;
+		e--;
+		continue;
+	}
+	return e;
+    }
+}
+
+char *FileName::name()
+{
+    return name(str);
+}
+
+/**************************************
+ * Return path portion of str.
+ * Path will does not include trailing path separator.
+ */
+
+char *FileName::path(const char *str)
+{
+    char *n = name(str);
+    char *path;
+    size_t pathlen;
+
+    if (n > str)
+    {
+
+	if (n[-1] == '/')
+	    n--;
+
+#if _WIN32
+	if (n[-1] == '\\')
+	    n--;
+#endif
+    }
+    pathlen = n - str;
+    path = (char *)mem.malloc(pathlen + 1);
+    memcpy(path, str, pathlen);
+    path[pathlen] = 0;
+    return path;
+}
+
+/**************************************
+ * Replace filename portion of path.
+ */
+
+char *FileName::replaceName(char *path, char *name)
+{   char *f;
+    char *n;
+    size_t pathlen;
+    size_t namelen;
+
+    if (absolute(name))
+	return name;
+
+    n = FileName::name(path);
+    if (n == path)
+	return name;
+    pathlen = n - path;
+    namelen = strlen(name);
+    f = (char *)mem.malloc(pathlen + 1 + namelen + 1);
+    memcpy(f, path, pathlen);
+
+    if  (
+	path[pathlen - 1] != '/'
+#if _WIN32
+	&& path[pathlen - 1] != '\\' && path[pathlen - 1] != ':'
+#endif
+	)
+    {	f[pathlen] = '/';
+	pathlen++;
+    }
+
+    memcpy(f + pathlen, name, namelen + 1);
+    return f;
+}
+
+/***************************
+ */
+
+FileName *FileName::defaultExt(const char *name, const char *ext)
+{
+    char *e;
+    char *s;
+    size_t len;
+    size_t extlen;
+
+    e = FileName::ext(name);
+    if (e)				// if already has an extension
+	return new FileName((char *)name, 0);
+
+    len = strlen(name);
+    extlen = strlen(ext);
+    s = (char *)alloca(len + 1 + extlen + 1);
+    memcpy(s,name,len);
+    s[len] = '.';
+    memcpy(s + len + 1, ext, extlen + 1);
+    return new FileName(s, 0);
+}
+
+/***************************
+ */
+
+FileName *FileName::forceExt(const char *name, const char *ext)
+{
+    char *e;
+    char *s;
+    size_t len;
+    size_t extlen;
+
+    e = FileName::ext(name);
+    if (e)				// if already has an extension
+    {
+	len = e - name;
+	extlen = strlen(ext);
+
+	s = (char *)alloca(len + extlen + 1);
+	memcpy(s,name,len);
+	memcpy(s + len, ext, extlen + 1);
+	return new FileName(s, 0);
+    }
+    else
+	return defaultExt(name, ext);	// doesn't have one
+}
+
+/******************************
+ * Return !=0 if extensions match.
+ */
+
+int FileName::equalsExt(const char *ext)
+{   const char *e;
+
+    e = FileName::ext();
+    if (!e && !ext)
+	return 1;
+    if (!e || !ext)
+	return 0;
+#if POSIX
+    return strcmp(e,ext) == 0;
+#endif
+#if _WIN32
+    return stricmp(e,ext) == 0;
+#endif
+}
+
+/*************************************
+ * Copy file from this to to.
+ */
+
+void FileName::CopyTo(FileName *to)
+{
+    File file(this);
+
+#if _WIN32
+    file.touchtime = mem.malloc(sizeof(WIN32_FIND_DATAA));	// keep same file time
+#endif
+#if POSIX
+    file.touchtime = mem.malloc(sizeof(struct stat)); // keep same file time
+#endif
+    file.readv();
+    file.name = to;
+    file.writev();
+}
+
+/*************************************
+ * Search Path for file.
+ * Input:
+ *	cwd	if !=0, search current directory before searching path
+ */
+
+char *FileName::searchPath(Array *path, const char *name, int cwd)
+{
+    if (absolute(name))
+    {
+	return exists(name) ? (char *)name : NULL;
+    }
+    if (cwd)
+    {
+	if (exists(name))
+	    return (char *)name;
+    }
+    if (path)
+    {	unsigned i;
+
+	for (i = 0; i < path->dim; i++)
+	{
+	    char *p = (char *)path->data[i];
+	    char *n = combine(p, name);
+
+	    if (exists(n))
+		return n;
+	}
+    }
+    return NULL;
+}
+
+int FileName::exists(const char *name)
+{
+#if POSIX
+    struct stat st;
+
+    if (stat(name, &st) < 0)
+	return 0;
+    if (S_ISDIR(st.st_mode))
+	return 2;
+    return 1;
+#endif
+#if _WIN32
+    DWORD dw;
+    int result;
+
+    dw = GetFileAttributesA(name);
+    if (dw == -1L)
+	result = 0;
+    else if (dw & FILE_ATTRIBUTE_DIRECTORY)
+	result = 2;
+    else
+	result = 1;
+    return result;
+#endif
+}
+
+void FileName::ensurePathExists(const char *path)
+{
+    //printf("FileName::ensurePathExists(%s)\n", path ? path : "");
+    if (path && *path)
+    {
+	if (!exists(path))
+	{
+	    char *p = FileName::path(path);
+	    if (*p)
+	    {
+#if _WIN32
+		size_t len = strlen(p);
+		if (len > 2 && p[-1] == ':')
+		{   mem.free(p);
+		    return;
+		}
+#endif
+		ensurePathExists(p);
+		mem.free(p);
+	    }
+#if _WIN32
+	    if (path[strlen(path) - 1] != '\\')
+#endif
+#if POSIX
+	    if (path[strlen(path) - 1] != '\\')
+#endif
+	    {
+		//printf("mkdir(%s)\n", path);
+#if _WIN32
+		if (mkdir(path))
+#endif
+#if POSIX
+		if (mkdir(path, 0777))
+#endif
+		    error("cannot create directory %s", path);
+	    }
+	}
+    }
+}
+
+/****************************** File ********************************/
+
+File::File(FileName *n)
+{
+    ref = 0;
+    buffer = NULL;
+    len = 0;
+    touchtime = NULL;
+    name = n;
+}
+
+File::File(char *n)
+{
+    ref = 0;
+    buffer = NULL;
+    len = 0;
+    touchtime = NULL;
+    name = new FileName(n, 0);
+}
+
+File::~File()
+{
+    if (buffer)
+    {
+	if (ref == 0)
+	    mem.free(buffer);
+#if _WIN32
+	else if (ref == 2)
+	    UnmapViewOfFile(buffer);
+#endif
+    }
+    if (touchtime)
+	mem.free(touchtime);
+}
+
+void File::mark()
+{
+    mem.mark(buffer);
+    mem.mark(touchtime);
+    mem.mark(name);
+}
+
+/*************************************
+ */
+
+int File::read()
+{
+#if POSIX
+    off_t size;
+    ssize_t numread;
+    int fd;
+    struct stat buf;
+    int result = 0;
+    char *name;
+
+    name = this->name->toChars();
+    //printf("File::read('%s')\n",name);
+    fd = open(name, O_RDONLY);
+    if (fd == -1)
+    {	result = errno;
+	//printf("\topen error, errno = %d\n",errno);
+	goto err1;
+    }
+
+    if (!ref)
+	mem.free(buffer);
+    ref = 0;       // we own the buffer now
+
+    //printf("\tfile opened\n");
+    if (fstat(fd, &buf))
+    {
+	printf("\tfstat error, errno = %d\n",errno);
+        goto err2;
+    }
+    size = buf.st_size;
+    buffer = (unsigned char *) mem.malloc(size + 2);
+    if (!buffer)
+    {
+	printf("\tmalloc error, errno = %d\n",errno);
+	goto err2;
+    }
+
+    numread = ::read(fd, buffer, size);
+    if (numread != size)
+    {
+	printf("\tread error, errno = %d\n",errno);
+	goto err2;
+    }
+
+    if (touchtime)
+        memcpy(touchtime, &buf, sizeof(buf));
+
+    if (close(fd) == -1)
+    {
+	printf("\tclose error, errno = %d\n",errno);
+	goto err;
+    }
+
+    len = size;
+
+    // Always store a wchar ^Z past end of buffer so scanner has a sentinel
+    buffer[size] = 0;		// ^Z is obsolete, use 0
+    buffer[size + 1] = 0;
+    return 0;
+
+err2:
+    close(fd);
+err:
+    mem.free(buffer);
+    buffer = NULL;
+    len = 0;
+
+err1:
+    result = 1;
+    return result;
+#endif
+#if _WIN32
+    DWORD size;
+    DWORD numread;
+    HANDLE h;
+    int result = 0;
+    char *name;
+
+    name = this->name->toChars();
+    h = CreateFileA(name,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,
+	FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,0);
+    if (h == INVALID_HANDLE_VALUE)
+	goto err1;
+
+    if (!ref)
+	mem.free(buffer);
+    ref = 0;
+
+    size = GetFileSize(h,NULL);
+    buffer = (unsigned char *) mem.malloc(size + 2);
+    if (!buffer)
+	goto err2;
+
+    if (ReadFile(h,buffer,size,&numread,NULL) != TRUE)
+	goto err2;
+
+    if (numread != size)
+	goto err2;
+
+    if (touchtime)
+    {
+	if (!GetFileTime(h, NULL, NULL, &((WIN32_FIND_DATAA *)touchtime)->ftLastWriteTime))
+	    goto err2;
+    }
+
+    if (!CloseHandle(h))
+	goto err;
+
+    len = size;
+
+    // Always store a wchar ^Z past end of buffer so scanner has a sentinel
+    buffer[size] = 0;		// ^Z is obsolete, use 0
+    buffer[size + 1] = 0;
+    return 0;
+
+err2:
+    CloseHandle(h);
+err:
+    mem.free(buffer);
+    buffer = NULL;
+    len = 0;
+
+err1:
+    result = 1;
+    return result;
+#endif
+}
+
+/*****************************
+ * Read a file with memory mapped file I/O.
+ */
+
+int File::mmread()
+{
+#if POSIX
+    return read();
+#endif
+#if _WIN32
+    HANDLE hFile;
+    HANDLE hFileMap;
+    DWORD size;
+    char *name;
+
+    name = this->name->toChars();
+    hFile = CreateFile(name, GENERIC_READ,
+			FILE_SHARE_READ, NULL,
+			OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+    if (hFile == INVALID_HANDLE_VALUE)
+	goto Lerr;
+    size = GetFileSize(hFile, NULL);
+    //printf(" file created, size %d\n", size);
+
+    hFileMap = CreateFileMapping(hFile,NULL,PAGE_READONLY,0,size,NULL);
+    if (CloseHandle(hFile) != TRUE)
+	goto Lerr;
+
+    if (hFileMap == NULL)
+	goto Lerr;
+
+    //printf(" mapping created\n");
+
+    if (!ref)
+	mem.free(buffer);
+    ref = 2;
+    buffer = (unsigned char *)MapViewOfFileEx(hFileMap, FILE_MAP_READ,0,0,size,NULL);
+    if (CloseHandle(hFileMap) != TRUE)
+	goto Lerr;
+    if (buffer == NULL)			// mapping view failed
+	goto Lerr;
+
+    len = size;
+    //printf(" buffer = %p\n", buffer);
+
+    return 0;
+
+Lerr:
+    return GetLastError();			// failure
+#endif
+}
+
+/*********************************************
+ * Write a file.
+ * Returns:
+ *	0	success
+ */
+
+int File::write()
+{
+#if POSIX
+    int fd;
+    ssize_t numwritten;
+    char *name;
+
+    name = this->name->toChars();
+    fd = open(name, O_CREAT | O_WRONLY | O_TRUNC, 0644);
+    if (fd == -1)
+	goto err;
+
+    numwritten = ::write(fd, buffer, len);
+    if (len != numwritten)
+	goto err2;
+    
+    if (close(fd) == -1)
+	goto err;
+
+    if (touchtime)
+    {   struct utimbuf ubuf;
+
+        ubuf.actime = ((struct stat *)touchtime)->st_atime;
+        ubuf.modtime = ((struct stat *)touchtime)->st_mtime;
+	if (utime(name, &ubuf))
+	    goto err;
+    }
+    return 0;
+
+err2:
+    close(fd);
+    ::remove(name);
+err:
+    return 1;
+#endif
+#if _WIN32
+    HANDLE h;
+    DWORD numwritten;
+    char *name;
+
+    name = this->name->toChars();
+    h = CreateFileA(name,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,
+	FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,NULL);
+    if (h == INVALID_HANDLE_VALUE)
+	goto err;
+
+    if (WriteFile(h,buffer,len,&numwritten,NULL) != TRUE)
+	goto err2;
+
+    if (len != numwritten)
+	goto err2;
+    
+    if (touchtime) {
+        SetFileTime(h, NULL, NULL, &((WIN32_FIND_DATAA *)touchtime)->ftLastWriteTime);
+    }
+    if (!CloseHandle(h))
+	goto err;
+    return 0;
+
+err2:
+    CloseHandle(h);
+    DeleteFileA(name);
+err:
+    return 1;
+#endif
+}
+
+/*********************************************
+ * Append to a file.
+ * Returns:
+ *	0	success
+ */
+
+int File::append()
+{
+#if POSIX
+    return 1;
+#endif
+#if _WIN32
+    HANDLE h;
+    DWORD numwritten;
+    char *name;
+
+    name = this->name->toChars();
+    h = CreateFileA(name,GENERIC_WRITE,0,NULL,OPEN_ALWAYS,
+	FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,NULL);
+    if (h == INVALID_HANDLE_VALUE)
+	goto err;
+
+#if 1
+    SetFilePointer(h, 0, NULL, FILE_END);
+#else // INVALID_SET_FILE_POINTER doesn't seem to have a definition
+    if (SetFilePointer(h, 0, NULL, FILE_END) == INVALID_SET_FILE_POINTER)
+	goto err;
+#endif
+
+    if (WriteFile(h,buffer,len,&numwritten,NULL) != TRUE)
+	goto err2;
+
+    if (len != numwritten)
+	goto err2;
+    
+    if (touchtime) {
+        SetFileTime(h, NULL, NULL, &((WIN32_FIND_DATAA *)touchtime)->ftLastWriteTime);
+    }
+    if (!CloseHandle(h))
+	goto err;
+    return 0;
+
+err2:
+    CloseHandle(h);
+err:
+    return 1;
+#endif
+}
+
+/**************************************
+ */
+
+void File::readv()
+{
+    if (read())
+	error("Error reading file '%s'\n",name->toChars());
+}
+
+/**************************************
+ */
+
+void File::mmreadv()
+{
+    if (mmread())
+	readv();
+}
+
+void File::writev()
+{
+    if (write())
+	error("Error writing file '%s'\n",name->toChars());
+}
+
+void File::appendv()
+{
+    if (write())
+	error("Error appending to file '%s'\n",name->toChars());
+}
+
+/*******************************************
+ * Return !=0 if file exists.
+ *	0:	file doesn't exist
+ *	1:	normal file
+ *	2:	directory
+ */
+
+int File::exists()
+{
+#if POSIX
+    return 0;
+#endif
+#if _WIN32
+    DWORD dw;
+    int result;
+    char *name;
+
+    name = this->name->toChars();
+    if (touchtime)
+	dw = ((WIN32_FIND_DATAA *)touchtime)->dwFileAttributes;
+    else
+	dw = GetFileAttributesA(name);
+    if (dw == -1L)
+	result = 0;
+    else if (dw & FILE_ATTRIBUTE_DIRECTORY)
+	result = 2;
+    else
+	result = 1;
+    return result;
+#endif
+}
+
+void File::remove()
+{
+#if POSIX
+    ::remove(this->name->toChars());
+#endif
+#if _WIN32
+    DeleteFileA(this->name->toChars());
+#endif
+}
+
+Array *File::match(char *n)
+{
+    return match(new FileName(n, 0));
+}
+
+Array *File::match(FileName *n)
+{
+#if POSIX
+    return NULL;
+#endif
+#if _WIN32
+    HANDLE h;
+    WIN32_FIND_DATAA fileinfo;
+    Array *a;
+    char *c;
+    char *name;
+
+    a = new Array();
+    c = n->toChars();
+    name = n->name();
+    h = FindFirstFileA(c,&fileinfo);
+    if (h != INVALID_HANDLE_VALUE)
+    {
+	do
+	{
+	    // Glue path together with name
+	    char *fn;
+	    File *f;
+
+	    fn = (char *)mem.malloc(name - c + strlen(fileinfo.cFileName) + 1);
+	    memcpy(fn, c, name - c);
+	    strcpy(fn + (name - c), fileinfo.cFileName);
+	    f = new File(fn);
+	    f->touchtime = mem.malloc(sizeof(WIN32_FIND_DATAA));
+	    memcpy(f->touchtime, &fileinfo, sizeof(fileinfo));
+	    a->push(f);
+	} while (FindNextFileA(h,&fileinfo) != FALSE);
+	FindClose(h);
+    }
+    return a;
+#endif
+}
+
+int File::compareTime(File *f)
+{
+#if POSIX
+    return 0;
+#endif
+#if _WIN32
+    if (!touchtime)
+	stat();
+    if (!f->touchtime)
+	f->stat();
+    return CompareFileTime(&((WIN32_FIND_DATAA *)touchtime)->ftLastWriteTime, &((WIN32_FIND_DATAA *)f->touchtime)->ftLastWriteTime);
+#endif
+}
+
+void File::stat()
+{
+#if POSIX
+    if (!touchtime)
+    {
+	touchtime = mem.calloc(1, sizeof(struct stat));
+    }
+#endif
+#if _WIN32
+    HANDLE h;
+
+    if (!touchtime)
+    {
+	touchtime = mem.calloc(1, sizeof(WIN32_FIND_DATAA));
+    }
+    h = FindFirstFileA(name->toChars(),(WIN32_FIND_DATAA *)touchtime);
+    if (h != INVALID_HANDLE_VALUE)
+    {
+	FindClose(h);
+    }
+#endif
+}
+
+void File::checkoffset(size_t offset, size_t nbytes)
+{
+    if (offset > len || offset + nbytes > len)
+	error("Corrupt file '%s': offset x%zx off end of file",toChars(),offset);
+}
+
+char *File::toChars()
+{
+    return name->toChars();
+}
+
+
+/************************* OutBuffer *************************/
+
+OutBuffer::OutBuffer()
+{
+    data = NULL;
+    offset = 0;
+    size = 0;
+}
+
+OutBuffer::~OutBuffer()
+{
+    mem.free(data);
+}
+
+void *OutBuffer::extractData()
+{
+    void *p;
+
+    p = (void *)data;
+    data = NULL;
+    offset = 0;
+    size = 0;
+    return p;
+}
+
+void OutBuffer::mark()
+{
+    mem.mark(data);
+}
+
+void OutBuffer::reserve(unsigned nbytes)
+{
+    //printf("OutBuffer::reserve: size = %d, offset = %d, nbytes = %d\n", size, offset, nbytes);
+    if (size - offset < nbytes)
+    {
+#if defined (__x86_64__)
+	size = (offset + nbytes) * 2 + 2;
+#else
+	size = (offset + nbytes) * 2;
+#endif
+	data = (unsigned char *)mem.realloc(data, size);
+    }
+}
+
+void OutBuffer::reset()
+{
+    offset = 0;
+}
+
+void OutBuffer::setsize(unsigned size)
+{
+    offset = size;
+}
+
+void OutBuffer::write(const void *data, unsigned nbytes)
+{
+    reserve(nbytes);
+    memcpy(this->data + offset, data, nbytes);
+    offset += nbytes;
+}
+
+void OutBuffer::writebstring(unsigned char *string)
+{
+    write(string,*string + 1);
+}
+
+void OutBuffer::writestring(const char *string)
+{
+    write(string,strlen(string));
+}
+
+void OutBuffer::writedstring(const char *string)
+{
+#if M_UNICODE
+    for (; *string; string++)
+    {
+	writedchar(*string);
+    }
+#else
+    write(string,strlen(string));
+#endif
+}
+
+void OutBuffer::writedstring(const wchar_t *string)
+{
+#if M_UNICODE
+    write(string,wcslen(string) * sizeof(wchar_t));
+#else
+    for (; *string; string++)
+    {
+	writedchar(*string);
+    }
+#endif
+}
+
+void OutBuffer::prependstring(const char *string)
+{   unsigned len;
+
+    len = strlen(string);
+    reserve(len);
+    memmove(data + len, data, offset);
+    memcpy(data, string, len);
+    offset += len;
+}
+
+void OutBuffer::writenl()
+{
+#if _WIN32
+#if M_UNICODE
+    write4(0x000A000D);		// newline is CR,LF on Microsoft OS's
+#else
+    writeword(0x0A0D);		// newline is CR,LF on Microsoft OS's
+#endif
+#else
+#if M_UNICODE
+    writeword('\n');
+#else
+    writeByte('\n');
+#endif
+#endif
+}
+
+void OutBuffer::writeByte(unsigned b)
+{
+    reserve(1);
+    this->data[offset] = (unsigned char)b;
+    offset++;
+}
+
+void OutBuffer::writeUTF8(unsigned b)
+{
+    reserve(6);
+    if (b <= 0x7F)
+    {
+	this->data[offset] = (unsigned char)b;
+	offset++;
+    }
+    else if (b <= 0x7FF)
+    {
+	this->data[offset + 0] = (unsigned char)((b >> 6) | 0xC0);
+	this->data[offset + 1] = (unsigned char)((b & 0x3F) | 0x80);
+	offset += 2;
+    }
+    else if (b <= 0xFFFF)
+    {
+	this->data[offset + 0] = (unsigned char)((b >> 12) | 0xE0);
+	this->data[offset + 1] = (unsigned char)(((b >> 6) & 0x3F) | 0x80);
+	this->data[offset + 2] = (unsigned char)((b & 0x3F) | 0x80);
+	offset += 3;
+    }
+    else if (b <= 0x1FFFFF)
+    {
+	this->data[offset + 0] = (unsigned char)((b >> 18) | 0xF0);
+	this->data[offset + 1] = (unsigned char)(((b >> 12) & 0x3F) | 0x80);
+	this->data[offset + 2] = (unsigned char)(((b >> 6) & 0x3F) | 0x80);
+	this->data[offset + 3] = (unsigned char)((b & 0x3F) | 0x80);
+	offset += 4;
+    }
+    else if (b <= 0x3FFFFFF)
+    {
+	this->data[offset + 0] = (unsigned char)((b >> 24) | 0xF8);
+	this->data[offset + 1] = (unsigned char)(((b >> 18) & 0x3F) | 0x80);
+	this->data[offset + 2] = (unsigned char)(((b >> 12) & 0x3F) | 0x80);
+	this->data[offset + 3] = (unsigned char)(((b >> 6) & 0x3F) | 0x80);
+	this->data[offset + 4] = (unsigned char)((b & 0x3F) | 0x80);
+	offset += 5;
+    }
+    else if (b <= 0x7FFFFFFF)
+    {
+	this->data[offset + 0] = (unsigned char)((b >> 30) | 0xFC);
+	this->data[offset + 1] = (unsigned char)(((b >> 24) & 0x3F) | 0x80);
+	this->data[offset + 2] = (unsigned char)(((b >> 18) & 0x3F) | 0x80);
+	this->data[offset + 3] = (unsigned char)(((b >> 12) & 0x3F) | 0x80);
+	this->data[offset + 4] = (unsigned char)(((b >> 6) & 0x3F) | 0x80);
+	this->data[offset + 5] = (unsigned char)((b & 0x3F) | 0x80);
+	offset += 6;
+    }
+    else
+	assert(0);
+}
+
+void OutBuffer::writedchar(unsigned b)
+{
+    reserve(Dchar_mbmax * sizeof(dchar));
+    offset = (unsigned char *)Dchar::put((dchar *)(this->data + offset), (dchar)b) -
+		this->data;
+}
+
+void OutBuffer::prependbyte(unsigned b)
+{
+    reserve(1);
+    memmove(data + 1, data, offset);
+    data[0] = (unsigned char)b;
+    offset++;
+}
+
+void OutBuffer::writeword(unsigned w)
+{
+    reserve(2);
+    *(unsigned short *)(this->data + offset) = (unsigned short)w;
+    offset += 2;
+}
+
+void OutBuffer::writeUTF16(unsigned w)
+{
+    reserve(4);
+    if (w <= 0xFFFF)
+    {
+	*(unsigned short *)(this->data + offset) = (unsigned short)w;
+	offset += 2;
+    }
+    else if (w <= 0x10FFFF)
+    {
+	*(unsigned short *)(this->data + offset) = (unsigned short)((w >> 10) + 0xD7C0);
+	*(unsigned short *)(this->data + offset + 2) = (unsigned short)((w & 0x3FF) | 0xDC00);
+	offset += 4;
+    }
+    else
+	assert(0);
+}
+
+void OutBuffer::write4(unsigned w)
+{
+    reserve(4);
+    *(unsigned long *)(this->data + offset) = w;
+    offset += 4;
+}
+
+void OutBuffer::write(OutBuffer *buf)
+{
+    if (buf)
+    {	reserve(buf->offset);
+	memcpy(data + offset, buf->data, buf->offset);
+	offset += buf->offset;
+    }
+}
+
+void OutBuffer::write(Object *obj)
+{
+    if (obj)
+    {
+	writestring(obj->toChars());
+    }
+}
+
+void OutBuffer::fill0(unsigned nbytes)
+{
+    reserve(nbytes);
+    memset(data + offset,0,nbytes);
+    offset += nbytes;
+}
+
+void OutBuffer::align(unsigned size)
+{   unsigned nbytes;
+
+    nbytes = ((offset + size - 1) & ~(size - 1)) - offset;
+    fill0(nbytes);
+}
+
+
+////////////////////////////////////////////////////////////////
+// The compiler shipped with Visual Studio 2005 (and possible
+// other versions) does not support C99 printf format specfiers
+// such as %z and %j
+#if _MSC_VER
+using std::string;
+using std::wstring;
+
+template<typename S>
+inline void 
+search_and_replace(S& str, const S& what, const S& replacement)
+{
+    assert(!what.empty());
+    size_t pos = str.find(what);
+    while (pos != S::npos) 
+    {
+        str.replace(pos, what.size(), replacement);
+        pos = str.find(what, pos + replacement.size());
+    }
+}
+#define WORKAROUND_C99_SPECIFIERS_BUG(S,tmp,f) \
+    S tmp = f;                                 \
+    search_and_replace(fmt, S("%z"), S("%l")); \
+    search_and_replace(fmt, S("%j"), S("%i")); \
+    f = tmp.c_str();
+#else
+#define WORKAROUND_C99_SPECIFIERS_BUG(S,tmp,f)
+#endif
+
+void OutBuffer::vprintf(const char *format, va_list args)
+{
+    char buffer[128];
+    char *p;
+    unsigned psize;
+    int count;
+
+    WORKAROUND_C99_SPECIFIERS_BUG(string, fmt, format);
+
+    p = buffer;
+    psize = sizeof(buffer);
+    for (;;)
+    {
+#if _WIN32
+	count = _vsnprintf(p,psize,format,args);
+	if (count != -1)
+	    break;
+	psize *= 2;
+#elif POSIX
+        va_list va;
+        va_copy(va, args);
+/*
+  The functions vprintf(), vfprintf(), vsprintf(), vsnprintf()
+  are equivalent to the functions printf(), fprintf(), sprintf(),
+  snprintf(), respectively, except that they are called with a
+  va_list instead of a variable number of arguments. These
+  functions do not call the va_end macro. Consequently, the value
+  of ap is undefined after the call. The application should call
+  va_end(ap) itself afterwards.
+ */
+	count = vsnprintf(p,psize,format,va);
+        va_end(va);
+	if (count == -1)
+	    psize *= 2;
+	else if (count >= psize)
+	    psize = count + 1;
+	else
+	    break;
+#endif
+	p = (char *) alloca(psize);	// buffer too small, try again with larger size
+    }
+    write(p,count);
+}
+
+#if M_UNICODE
+void OutBuffer::vprintf(const wchar_t *format, va_list args)
+{
+    dchar buffer[128];
+    dchar *p;
+    unsigned psize;
+    int count;
+
+    WORKAROUND_C99_SPECIFIERS_BUG(wstring, fmt, format);
+
+    p = buffer;
+    psize = sizeof(buffer) / sizeof(buffer[0]);
+    for (;;)
+    {
+#if _WIN32
+	count = _vsnwprintf(p,psize,format,args);
+	if (count != -1)
+	    break;
+	psize *= 2;
+#endif
+#if POSIX
+        va_list va;
+        va_copy(va, args);
+	count = vsnwprintf(p,psize,format,va);
+        va_end(va); 
+
+	if (count == -1)
+	    psize *= 2;
+	else if (count >= psize)
+	    psize = count + 1;
+	else
+	    break;
+#endif
+	p = (dchar *) alloca(psize * 2);	// buffer too small, try again with larger size
+    }
+    write(p,count * 2);
+}
+#endif
+
+void OutBuffer::printf(const char *format, ...)
+{
+    va_list ap;
+    va_start(ap, format);
+    vprintf(format,ap);
+    va_end(ap);
+}
+
+#if M_UNICODE
+void OutBuffer::printf(const wchar_t *format, ...)
+{
+    va_list ap;
+    va_start(ap, format);
+    vprintf(format,ap);
+    va_end(ap);
+}
+#endif
+
+void OutBuffer::bracket(char left, char right)
+{
+    reserve(2);
+    memmove(data + 1, data, offset);
+    data[0] = left;
+    data[offset + 1] = right;
+    offset += 2;
+}
+
+/******************
+ * Insert left at i, and right at j.
+ * Return index just past right.
+ */
+
+unsigned OutBuffer::bracket(unsigned i, const char *left, unsigned j, const char *right)
+{
+    size_t leftlen = strlen(left);
+    size_t rightlen = strlen(right);
+    reserve(leftlen + rightlen);
+    insert(i, left, leftlen);
+    insert(j + leftlen, right, rightlen);
+    return j + leftlen + rightlen;
+}
+
+void OutBuffer::spread(unsigned offset, unsigned nbytes)
+{
+    reserve(nbytes);
+    memmove(data + offset + nbytes, data + offset,
+	this->offset - offset);
+    this->offset += nbytes;
+}
+
+/****************************************
+ * Returns: offset + nbytes
+ */
+
+unsigned OutBuffer::insert(unsigned offset, const void *p, unsigned nbytes)
+{
+    spread(offset, nbytes);
+    memmove(data + offset, p, nbytes);
+    return offset + nbytes;
+}
+
+void OutBuffer::remove(unsigned offset, unsigned nbytes)
+{
+    memmove(data + offset, data + offset + nbytes, this->offset - (offset + nbytes));
+    this->offset -= nbytes;
+}
+
+char *OutBuffer::toChars()
+{
+    writeByte(0);
+    return (char *)data;
+}
+
+/********************************* Bits ****************************/
+
+Bits::Bits()
+{
+    data = NULL;
+    bitdim = 0;
+    allocdim = 0;
+}
+
+Bits::~Bits()
+{
+    mem.free(data);
+}
+
+void Bits::mark()
+{
+    mem.mark(data);
+}
+
+void Bits::resize(unsigned bitdim)
+{
+    unsigned allocdim;
+    unsigned mask;
+
+    allocdim = (bitdim + 31) / 32;
+    data = (unsigned *)mem.realloc(data, allocdim * sizeof(data[0]));
+    if (this->allocdim < allocdim)
+	memset(data + this->allocdim, 0, (allocdim - this->allocdim) * sizeof(data[0]));
+
+    // Clear other bits in last word
+    mask = (1 << (bitdim & 31)) - 1;
+    if (mask)
+	data[allocdim - 1] &= ~mask;
+
+    this->bitdim = bitdim;
+    this->allocdim = allocdim;
+}
+
+void Bits::set(unsigned bitnum)
+{
+    data[bitnum / 32] |= 1 << (bitnum & 31);
+}
+
+void Bits::clear(unsigned bitnum)
+{
+    data[bitnum / 32] &= ~(1 << (bitnum & 31));
+}
+
+int Bits::test(unsigned bitnum)
+{
+    return data[bitnum / 32] & (1 << (bitnum & 31));
+}
+
+void Bits::set()
+{   unsigned mask;
+
+    memset(data, ~0, allocdim * sizeof(data[0]));
+
+    // Clear other bits in last word
+    mask = (1 << (bitdim & 31)) - 1;
+    if (mask)
+	data[allocdim - 1] &= mask;
+}
+
+void Bits::clear()
+{
+    memset(data, 0, allocdim * sizeof(data[0]));
+}
+
+void Bits::copy(Bits *from)
+{
+    assert(bitdim == from->bitdim);
+    memcpy(data, from->data, allocdim * sizeof(data[0]));
+}
+
+Bits *Bits::clone()
+{
+    Bits *b;
+
+    b = new Bits();
+    b->resize(bitdim);
+    b->copy(this);
+    return b;
+}
+
+void Bits::sub(Bits *b)
+{
+    unsigned u;
+
+    for (u = 0; u < allocdim; u++)
+	data[u] &= ~b->data[u];
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/root/root.h	Fri Apr 03 17:02:52 2009 +0200
@@ -0,0 +1,357 @@
+
+
+// Copyright (c) 1999-2006 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+#ifndef ROOT_H
+#define ROOT_H
+
+#include <stdlib.h>
+#include <stdarg.h>
+
+#if __DMC__
+#pragma once
+#endif
+
+typedef size_t hash_t;
+
+#include "dchar.h"
+
+char *wchar2ascii(wchar_t *);
+int wcharIsAscii(wchar_t *);
+char *wchar2ascii(wchar_t *, unsigned len);
+int wcharIsAscii(wchar_t *, unsigned len);
+
+int bstrcmp(unsigned char *s1, unsigned char *s2);
+char *bstr2str(unsigned char *b);
+void error(const char *format, ...);
+void error(const wchar_t *format, ...);
+void warning(const char *format, ...);
+
+#ifndef TYPEDEFS
+#define TYPEDEFS
+
+#if _MSC_VER
+#include <float.h>  // for _isnan
+#include <malloc.h> // for alloca
+// According to VC 8.0 docs, long double is the same as double
+#define strtold strtod
+#define strtof  strtod
+#define isnan   _isnan
+
+typedef __int64 longlong;
+typedef unsigned __int64 ulonglong;
+#else
+typedef long long longlong;
+typedef unsigned long long ulonglong;
+#endif
+
+#endif
+
+longlong randomx();
+
+/*
+ * Root of our class library.
+ */
+
+struct OutBuffer;
+struct Array;
+
+struct Object
+{
+    Object() { }
+    virtual ~Object() { }
+
+    virtual int equals(Object *o);
+
+    /**
+     * Returns a hash code, useful for things like building hash tables of Objects.
+     */
+    virtual hash_t hashCode();
+
+    /**
+     * Return <0, ==0, or >0 if this is less than, equal to, or greater than obj.
+     * Useful for sorting Objects.
+     */
+    virtual int compare(Object *obj);
+
+    /**
+     * Pretty-print an Object. Useful for debugging the old-fashioned way.
+     */
+    virtual void print();
+
+    virtual char *toChars();
+    virtual dchar *toDchars();
+    virtual void toBuffer(OutBuffer *buf);
+
+    /**
+     * Used as a replacement for dynamic_cast. Returns a unique number
+     * defined by the library user. For Object, the return value is 0.
+     */
+    virtual int dyncast();
+
+    /**
+     * Marks pointers for garbage collector by calling mem.mark() for all pointers into heap.
+     */
+    /*virtual*/		// not used, disable for now
+	void mark();
+};
+
+struct String : Object
+{
+    int ref;			// != 0 if this is a reference to someone else's string
+    char *str;			// the string itself
+
+    String(char *str, int ref = 1);
+
+    ~String();
+
+    static hash_t calcHash(const char *str, size_t len);
+    static hash_t calcHash(const char *str);
+    hash_t hashCode();
+    unsigned len();
+    int equals(Object *obj);
+    int compare(Object *obj);
+    char *toChars();
+    void print();
+    void mark();
+};
+
+struct FileName : String
+{
+    FileName(char *str, int ref);
+    FileName(char *path, char *name);
+    hash_t hashCode();
+    int equals(Object *obj);
+    int compare(Object *obj);
+    static int absolute(const char *name);
+    static char *ext(const char *);
+    char *ext();
+    static char *removeExt(const char *str);
+    static char *name(const char *);
+    char *name();
+    static char *path(const char *);
+    static char *replaceName(char *path, char *name);
+
+    static char *combine(const char *path, const char *name);
+    static Array *splitPath(const char *path);
+    static FileName *defaultExt(const char *name, const char *ext);
+    static FileName *forceExt(const char *name, const char *ext);
+    int equalsExt(const char *ext);
+
+    void CopyTo(FileName *to);
+    static char *searchPath(Array *path, const char *name, int cwd);
+    static int exists(const char *name);
+    static void ensurePathExists(const char *path);
+};
+
+struct File : Object
+{
+    int ref;			// != 0 if this is a reference to someone else's buffer
+    unsigned char *buffer;	// data for our file
+    unsigned len;		// amount of data in buffer[]
+    void *touchtime;		// system time to use for file
+
+    FileName *name;		// name of our file
+
+    File(char *);
+    File(FileName *);
+    ~File();
+
+    void mark();
+
+    char *toChars();
+
+    /* Read file, return !=0 if error
+     */
+
+    int read();
+
+    /* Write file, either succeed or fail
+     * with error message & exit.
+     */
+
+    void readv();
+
+    /* Read file, return !=0 if error
+     */
+
+    int mmread();
+
+    /* Write file, either succeed or fail
+     * with error message & exit.
+     */
+
+    void mmreadv();
+
+    /* Write file, return !=0 if error
+     */
+
+    int write();
+
+    /* Write file, either succeed or fail
+     * with error message & exit.
+     */
+
+    void writev();
+
+    /* Return !=0 if file exists.
+     *	0:	file doesn't exist
+     *	1:	normal file
+     *	2:	directory
+     */
+
+    /* Append to file, return !=0 if error
+     */
+
+    int append();
+
+    /* Append to file, either succeed or fail
+     * with error message & exit.
+     */
+
+    void appendv();
+
+    /* Return !=0 if file exists.
+     *	0:	file doesn't exist
+     *	1:	normal file
+     *	2:	directory
+     */
+
+    int exists();
+
+    /* Given wildcard filespec, return an array of
+     * matching File's.
+     */
+
+    static Array *match(char *);
+    static Array *match(FileName *);
+
+    // Compare file times.
+    // Return	<0	this < f
+    //		=0	this == f
+    //		>0	this > f
+    int compareTime(File *f);
+
+    // Read system file statistics
+    void stat();
+
+    /* Set buffer
+     */
+
+    void setbuffer(void *buffer, unsigned len)
+    {
+	this->buffer = (unsigned char *)buffer;
+	this->len = len;
+    }
+
+    void checkoffset(size_t offset, size_t nbytes);
+
+    void remove();		// delete file
+};
+
+struct OutBuffer : Object
+{
+    unsigned char *data;
+    unsigned offset;
+    unsigned size;
+
+    OutBuffer();
+    ~OutBuffer();
+    void *extractData();
+    void mark();
+
+    void reserve(unsigned nbytes);
+    void setsize(unsigned size);
+    void reset();
+    void write(const void *data, unsigned nbytes);
+    void writebstring(unsigned char *string);
+    void writestring(const char *string);
+    void writedstring(const char *string);
+    void writedstring(const wchar_t *string);
+    void prependstring(const char *string);
+    void writenl();			// write newline
+    void writeByte(unsigned b);
+    void writebyte(unsigned b) { writeByte(b); }
+    void writeUTF8(unsigned b);
+    void writedchar(unsigned b);
+    void prependbyte(unsigned b);
+    void writeword(unsigned w);
+    void writeUTF16(unsigned w);
+    void write4(unsigned w);
+    void write(OutBuffer *buf);
+    void write(Object *obj);
+    void fill0(unsigned nbytes);
+    void align(unsigned size);
+    void vprintf(const char *format, va_list args);
+    void printf(const char *format, ...);
+#if M_UNICODE
+    void vprintf(const unsigned short *format, va_list args);
+    void printf(const unsigned short *format, ...);
+#endif
+    void bracket(char left, char right);
+    unsigned bracket(unsigned i, const char *left, unsigned j, const char *right);
+    void spread(unsigned offset, unsigned nbytes);
+    unsigned insert(unsigned offset, const void *data, unsigned nbytes);
+    void remove(unsigned offset, unsigned nbytes);
+    char *toChars();
+    char *extractString();
+};
+
+struct Array : Object
+{
+    unsigned dim;
+    unsigned allocdim;
+    void **data;
+
+    Array();
+    ~Array();
+    void mark();
+    char *toChars();
+
+    void reserve(unsigned nentries);
+    void setDim(unsigned newdim);
+    void fixDim();
+    void push(void *ptr);
+    void *pop();
+    void shift(void *ptr);
+    void insert(unsigned index, void *ptr);
+    void insert(unsigned index, Array *a);
+    void append(Array *a);
+    void remove(unsigned i);
+    void zero();
+    void *tos();
+    void sort();
+    Array *copy();
+};
+
+struct Bits : Object
+{
+    unsigned bitdim;
+    unsigned allocdim;
+    unsigned *data;
+
+    Bits();
+    ~Bits();
+    void mark();
+
+    void resize(unsigned bitdim);
+
+    void set(unsigned bitnum);
+    void clear(unsigned bitnum);
+    int test(unsigned bitnum);
+
+    void set();
+    void clear();
+    void copy(Bits *from);
+    Bits *clone();
+
+    void sub(Bits *b);
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/root/stringtable.c	Fri Apr 03 17:02:52 2009 +0200
@@ -0,0 +1,139 @@
+
+// Copyright (c) 1999-2008 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// http://www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "root.h"
+#include "rmem.h"
+#include "dchar.h"
+#include "lstring.h"
+#include "stringtable.h"
+
+StringTable::StringTable(unsigned size)
+{
+    table = (void **)mem.calloc(size, sizeof(void *));
+    tabledim = size;
+    count = 0;
+}
+
+StringTable::~StringTable()
+{
+    unsigned i;
+
+    // Zero out dangling pointers to help garbage collector.
+    // Should zero out StringEntry's too.
+    for (i = 0; i < count; i++)
+	table[i] = NULL;
+
+    mem.free(table);
+    table = NULL;
+}
+
+struct StringEntry
+{
+    StringEntry *left;
+    StringEntry *right;
+    hash_t hash;
+
+    StringValue value;
+
+    static StringEntry *alloc(const dchar *s, unsigned len);
+};
+
+StringEntry *StringEntry::alloc(const dchar *s, unsigned len)
+{
+    StringEntry *se;
+
+    se = (StringEntry *) mem.calloc(1,sizeof(StringEntry) - sizeof(Lstring) + Lstring::size(len));
+    se->value.lstring.length = len;
+    se->hash = Dchar::calcHash(s,len);
+    memcpy(se->value.lstring.string, s, len * sizeof(dchar));
+    return se;
+}
+
+void **StringTable::search(const dchar *s, unsigned len)
+{
+    hash_t hash;
+    unsigned u;
+    int cmp;
+    StringEntry **se;
+
+    //printf("StringTable::search(%p,%d)\n",s,len);
+    hash = Dchar::calcHash(s,len);
+    u = hash % tabledim;
+    se = (StringEntry **)&table[u];
+    //printf("\thash = %d, u = %d\n",hash,u);
+    while (*se)
+    {
+	cmp = (*se)->hash - hash;
+	if (cmp == 0)
+	{
+	    cmp = (*se)->value.lstring.len() - len;
+	    if (cmp == 0)
+	    {
+		cmp = Dchar::memcmp(s,(*se)->value.lstring.toDchars(),len);
+		if (cmp == 0)
+		    break;
+	    }
+	}
+	if (cmp < 0)
+	    se = &(*se)->left;
+	else
+	    se = &(*se)->right;
+    }
+    //printf("\treturn %p, %p\n",se, (*se));
+    return (void **)se;
+}
+
+StringValue *StringTable::lookup(const dchar *s, unsigned len)
+{   StringEntry *se;
+
+    se = *(StringEntry **)search(s,len);
+    if (se)
+	return &se->value;
+    else
+	return NULL;
+}
+
+StringValue *StringTable::update(const dchar *s, unsigned len)
+{   StringEntry **pse;
+    StringEntry *se;
+
+    pse = (StringEntry **)search(s,len);
+    se = *pse;
+    if (!se)			// not in table: so create new entry
+    {
+	se = StringEntry::alloc(s, len);
+	*pse = se;
+    }
+    return &se->value;
+}
+
+StringValue *StringTable::insert(const dchar *s, unsigned len)
+{   StringEntry **pse;
+    StringEntry *se;
+
+    pse = (StringEntry **)search(s,len);
+    se = *pse;
+    if (se)
+	return NULL;		// error: already in table
+    else
+    {
+	se = StringEntry::alloc(s, len);
+	*pse = se;
+    }
+    return &se->value;
+}
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/root/stringtable.h	Fri Apr 03 17:02:52 2009 +0200
@@ -0,0 +1,48 @@
+// Copyright (c) 1999-2008 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// http://www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+
+#ifndef STRINGTABLE_H
+#define STRINGTABLE_H
+
+#if __SC__
+#pragma once
+#endif
+
+#include "root.h"
+#include "dchar.h"
+#include "lstring.h"
+
+struct StringValue
+{
+    union
+    {	int intvalue;
+	void *ptrvalue;
+	dchar *string;
+    };
+    Lstring lstring;
+};
+
+struct StringTable : Object
+{
+    void **table;
+    unsigned count;
+    unsigned tabledim;
+
+    StringTable(unsigned size = 37);
+    ~StringTable();
+
+    StringValue *lookup(const dchar *s, unsigned len);
+    StringValue *insert(const dchar *s, unsigned len);
+    StringValue *update(const dchar *s, unsigned len);
+
+private:
+    void **search(const dchar *s, unsigned len);
+};
+
+#endif
--- a/dmd/stringtable.c	Fri Apr 03 16:35:47 2009 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,139 +0,0 @@
-
-// Copyright (c) 1999-2008 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// http://www.digitalmars.com
-// License for redistribution is by either the Artistic License
-// in artistic.txt, or the GNU General Public License in gnu.txt.
-// See the included readme.txt for details.
-
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include "root.h"
-#include "rmem.h"
-#include "dchar.h"
-#include "lstring.h"
-#include "stringtable.h"
-
-StringTable::StringTable(unsigned size)
-{
-    table = (void **)mem.calloc(size, sizeof(void *));
-    tabledim = size;
-    count = 0;
-}
-
-StringTable::~StringTable()
-{
-    unsigned i;
-
-    // Zero out dangling pointers to help garbage collector.
-    // Should zero out StringEntry's too.
-    for (i = 0; i < count; i++)
-	table[i] = NULL;
-
-    mem.free(table);
-    table = NULL;
-}
-
-struct StringEntry
-{
-    StringEntry *left;
-    StringEntry *right;
-    hash_t hash;
-
-    StringValue value;
-
-    static StringEntry *alloc(const dchar *s, unsigned len);
-};
-
-StringEntry *StringEntry::alloc(const dchar *s, unsigned len)
-{
-    StringEntry *se;
-
-    se = (StringEntry *) mem.calloc(1,sizeof(StringEntry) - sizeof(Lstring) + Lstring::size(len));
-    se->value.lstring.length = len;
-    se->hash = Dchar::calcHash(s,len);
-    memcpy(se->value.lstring.string, s, len * sizeof(dchar));
-    return se;
-}
-
-void **StringTable::search(const dchar *s, unsigned len)
-{
-    hash_t hash;
-    unsigned u;
-    int cmp;
-    StringEntry **se;
-
-    //printf("StringTable::search(%p,%d)\n",s,len);
-    hash = Dchar::calcHash(s,len);
-    u = hash % tabledim;
-    se = (StringEntry **)&table[u];
-    //printf("\thash = %d, u = %d\n",hash,u);
-    while (*se)
-    {
-	cmp = (*se)->hash - hash;
-	if (cmp == 0)
-	{
-	    cmp = (*se)->value.lstring.len() - len;
-	    if (cmp == 0)
-	    {
-		cmp = Dchar::memcmp(s,(*se)->value.lstring.toDchars(),len);
-		if (cmp == 0)
-		    break;
-	    }
-	}
-	if (cmp < 0)
-	    se = &(*se)->left;
-	else
-	    se = &(*se)->right;
-    }
-    //printf("\treturn %p, %p\n",se, (*se));
-    return (void **)se;
-}
-
-StringValue *StringTable::lookup(const dchar *s, unsigned len)
-{   StringEntry *se;
-
-    se = *(StringEntry **)search(s,len);
-    if (se)
-	return &se->value;
-    else
-	return NULL;
-}
-
-StringValue *StringTable::update(const dchar *s, unsigned len)
-{   StringEntry **pse;
-    StringEntry *se;
-
-    pse = (StringEntry **)search(s,len);
-    se = *pse;
-    if (!se)			// not in table: so create new entry
-    {
-	se = StringEntry::alloc(s, len);
-	*pse = se;
-    }
-    return &se->value;
-}
-
-StringValue *StringTable::insert(const dchar *s, unsigned len)
-{   StringEntry **pse;
-    StringEntry *se;
-
-    pse = (StringEntry **)search(s,len);
-    se = *pse;
-    if (se)
-	return NULL;		// error: already in table
-    else
-    {
-	se = StringEntry::alloc(s, len);
-	*pse = se;
-    }
-    return &se->value;
-}
-
-
-
-
--- a/dmd/stringtable.h	Fri Apr 03 16:35:47 2009 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-// Copyright (c) 1999-2008 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// http://www.digitalmars.com
-// License for redistribution is by either the Artistic License
-// in artistic.txt, or the GNU General Public License in gnu.txt.
-// See the included readme.txt for details.
-
-
-#ifndef STRINGTABLE_H
-#define STRINGTABLE_H
-
-#if __SC__
-#pragma once
-#endif
-
-#include "root.h"
-#include "dchar.h"
-#include "lstring.h"
-
-struct StringValue
-{
-    union
-    {	int intvalue;
-	void *ptrvalue;
-	dchar *string;
-    };
-    Lstring lstring;
-};
-
-struct StringTable : Object
-{
-    void **table;
-    unsigned count;
-    unsigned tabledim;
-
-    StringTable(unsigned size = 37);
-    ~StringTable();
-
-    StringValue *lookup(const dchar *s, unsigned len);
-    StringValue *insert(const dchar *s, unsigned len);
-    StringValue *update(const dchar *s, unsigned len);
-
-private:
-    void **search(const dchar *s, unsigned len);
-};
-
-#endif