changeset 473:373489eeaf90

Applied downs' lphobos update
author Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
date Mon, 04 Aug 2008 19:28:49 +0200
parents 15c804b6ce77
children 074e74c1a72b
files lphobos/build.sh lphobos/etc/c/zlib.d lphobos/gc/gc.d lphobos/gc/gc_guess_stack.d lphobos/gc/gcbits.d lphobos/gc/gcx.d lphobos/gc/win32.d lphobos/hello.d lphobos/internal/aaA.d lphobos/internal/adi.d lphobos/internal/contract.d lphobos/internal/critical.d lphobos/internal/dmain2.d lphobos/internal/eh.d lphobos/internal/objectimpl.d lphobos/internal/qsort2.d lphobos/internal/switch.d lphobos/llvm/intrinsic.d lphobos/object.d lphobos/phobos.d lphobos/std/bitarray.d lphobos/std/c/stdarg.d lphobos/std/c/stdlib.d lphobos/std/c/windows/com.d lphobos/std/c/windows/stat.d lphobos/std/c/windows/windows.d lphobos/std/c/windows/winsock.d lphobos/std/cstream.d lphobos/std/date.d lphobos/std/date.d~ lphobos/std/dateparse.d lphobos/std/file.d lphobos/std/intrinsic.d lphobos/std/math.d lphobos/std/md5.d lphobos/std/mmfile.d lphobos/std/moduleinit.d lphobos/std/outbuffer.d lphobos/std/path.d lphobos/std/process.d lphobos/std/random.d lphobos/std/regexp.d lphobos/std/socket.d lphobos/std/stream.d lphobos/std/string.d lphobos/std/system.d lphobos/std/thread.d lphobos/std/traits.d lphobos/std/zip.d lphobos/std/zlib.d lphobos/typeinfo1/ti_float.d
diffstat 51 files changed, 27282 insertions(+), 421 deletions(-) [+]
line wrap: on
line diff
--- a/lphobos/build.sh	Mon Aug 04 19:08:39 2008 +0200
+++ b/lphobos/build.sh	Mon Aug 04 19:28:49 2008 +0200
@@ -5,69 +5,96 @@
 rm -f obj/*.bc
 rm -f ../lib/*.bc
 
-LLVMDCFLAGS="-c -odobj -g"
-REBUILDFLAGS="-dc=llvmdc-posix-internal -c -oqobj -g"
+LLVMDCFLAGS="-c -odobj -oq -gc -noasm"
+LLVMDCFLAGS_ASM="-c -odobj -oq -gc"
 
 echo "compiling contract runtime"
-llvmdc internal/contract.d -c -of../lib/llvmdcore.bc -noruntime || exit 1
+llvmdc internal/contract.d -c -of../lib/llvmdcore.bc || exit 1 #-noruntime || exit 1
 
 echo "compiling common runtime"
-rebuild internal/arrays.d \
+llvmdc-build internal/arrays.d \
         internal/mem.d \
-        $REBUILDFLAGS || exit 1
+        internal/critical.d \
+        internal/dmain2.d \
+        $LLVMDCFLAGS_ASM || exit 1
+mv *.bc obj
 
 echo "compiling module init backend"
 llvm-as -f -o=obj/moduleinit_backend.bc internal/moduleinit_backend.ll || exit 1
 llvm-link -f -o=../lib/llvmdcore.bc `ls obj/internal.*.bc` ../lib/llvmdcore.bc obj/moduleinit_backend.bc || exit 1
 
 echo "compiling typeinfo 1"
-rebuild typeinfos1.d $REBUILDFLAGS || exit 1
+llvmdc-build typeinfos1.d $LLVMDCFLAGS || exit 1
+mv *.bc obj
 llvm-link -f -o=../lib/llvmdcore.bc `ls obj/typeinfo1.*.bc` ../lib/llvmdcore.bc || exit 1
 
 echo "compiling typeinfo 2"
-rebuild typeinfos2.d $REBUILDFLAGS || exit 1
+llvmdc-build typeinfos2.d $LLVMDCFLAGS || exit 1
+mv *.bc obj
 llvm-link -f -o=../lib/llvmdcore.bc `ls obj/typeinfo2.*.bc` ../lib/llvmdcore.bc || exit 1
 
+echo "compiling exceptions"
+llvmdc-build internal/eh.d $LLVMDCFLAGS -debug || exit 1
+mv *.bc obj
+llvm-link -f -o=../lib/llvmdcore.bc obj/*eh.bc ../lib/llvmdcore.bc || exit 1
+
 echo "compiling object/interface casting runtime support"
 llvmdc internal/cast.d $LLVMDCFLAGS || exit 1
+mv *.bc obj
 llvm-link -f -o=../lib/llvmdcore.bc obj/cast.bc ../lib/llvmdcore.bc || exit 1
 
 echo "compiling string foreach/switch runtime support"
 llvmdc internal/aApply.d $LLVMDCFLAGS || exit 1
 llvmdc internal/aApplyR.d $LLVMDCFLAGS || exit 1
 llvmdc internal/switch.d $LLVMDCFLAGS || exit 1
+mv *.bc obj
 llvm-link -f -o=../lib/llvmdcore.bc obj/aApply.bc obj/aApplyR.bc obj/switch.bc ../lib/llvmdcore.bc || exit 1
 
 echo "compiling array runtime support"
 llvmdc internal/qsort2.d $LLVMDCFLAGS || exit 1
+mv *.bc obj
 llvm-link -f -o=../lib/llvmdcore.bc obj/qsort2.bc ../lib/llvmdcore.bc || exit 1
 llvmdc internal/adi.d $LLVMDCFLAGS || exit 1
+mv *.bc obj
 llvm-link -f -o=../lib/llvmdcore.bc obj/adi.bc ../lib/llvmdcore.bc || exit 1
 llvmdc internal/aaA.d $LLVMDCFLAGS || exit 1
+mv *.bc obj
 llvm-link -f -o=../lib/llvmdcore.bc obj/aaA.bc ../lib/llvmdcore.bc || exit 1
 
 echo "compiling object implementation"
-llvmdc internal/objectimpl.d $LLVMDCFLAGS || exit 1
+llvmdc internal/objectimpl.d -c -odobj -g || exit 1
 llvm-link -f -o=../lib/llvmdcore.bc obj/objectimpl.bc ../lib/llvmdcore.bc || exit 1
 
 echo "compiling llvm runtime support"
-rebuild llvmsupport.d $REBUILDFLAGS || exit 1
+llvmdc-build llvmsupport.d $LLVMDCFLAGS || exit 1
+mv *.bc obj
 llvm-link -f -o=../lib/llvmdcore.bc `ls obj/llvm.*.bc` ../lib/llvmdcore.bc || exit 1
 
 echo "compiling garbage collector"
-llvmdc gc/gclinux.d $LLVMDCFLAGS || exit 1
-llvmdc gc/gcx.d $LLVMDCFLAGS -Igc || exit 1
-llvmdc gc/gcbits.d $LLVMDCFLAGS -Igc || exit 1
-llvmdc gc/gc.d $LLVMDCFLAGS -Igc || exit 1
+cd gc
+llvmdc $(ls *.d |grep -v win32) $LLVMDCFLAGS_ASM -I.. ||exit 1
+# llvmdc gclinux.d $LLVMDCFLAGS -I.. || exit 1
+# llvmdc gcx.d $LLVMDCFLAGS -I.. || exit 1
+# llvmdc gcbits.d $LLVMDCFLAGS -I.. || exit 1
+# llvmdc gc.d $LLVMDCFLAGS -I.. || exit 1
+mv std.gc.bc gc.bc
+mv *.bc ../obj
+cd ..
 llvm-link -f -o=../lib/llvmdcore.bc obj/gclinux.bc obj/gcx.bc obj/gcbits.bc obj/gc.bc ../lib/llvmdcore.bc || exit 1
 
 echo "compiling phobos"
-rebuild phobos.d $REBUILDFLAGS || exit 1
+llvmdc-build phobos.d $LLVMDCFLAGS || exit 1
+mv *.bc obj
 echo "linking phobos"
 llvm-link -f -o=../lib/llvmdcore.bc `ls obj/std.*.bc` ../lib/llvmdcore.bc || exit 1
 
+echo "Compiling auxiliary"
+llvmdc-build etc/c/zlib.d $LLVMDCFLAGS || exit 1
+mv *.bc obj
+llvm-link -f -o=../lib/llvmdcore.bc `ls obj/etc.*.bc` ../lib/llvmdcore.bc || exit 1
+
 echo "optimizing"
-opt -f -std-compile-opts -o=../lib/llvmdcore.bc ../lib/llvmdcore.bc || exit 1
+opt -stats -p -f -std-compile-opts -disable-inlining -o=../lib/llvmdcore.bc ../lib/llvmdcore.bc || exit 1
 
 
 echo "SUCCESS"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lphobos/etc/c/zlib.d	Mon Aug 04 19:28:49 2008 +0200
@@ -0,0 +1,1215 @@
+/* zlib.d: modified from zlib.h by Walter Bright */
+/* NOTE: This file has been patched from the original DMD distribution to
+   work with the GDC compiler.
+
+   Modified by David Friedman, February 2007
+*/
+
+module etc.c.zlib;
+
+/* zlib.h -- interface of the 'zlib' general purpose compression library
+  version 1.2.1, November 17th, 2003
+
+  Copyright (C) 1995-2003 Jean-loup Gailly and Mark Adler
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jean-loup Gailly        Mark Adler
+  jloup@gzip.org          madler@alumni.caltech.edu
+
+
+  The data format used by the zlib library is described by RFCs (Request for
+  Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt
+  (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format).
+*/
+
+private import std.stdint;
+
+extern (C):
+alias uint Culong_t;
+alias int Clong_t;
+
+char[] ZLIB_VERSION = "1.2.1";
+
+/*
+     The 'zlib' compression library provides in-memory compression and
+  decompression functions, including integrity checks of the uncompressed
+  data.  This version of the library supports only one compression method
+  (deflation) but other algorithms will be added later and will have the same
+  stream interface.
+
+     Compression can be done in a single step if the buffers are large
+  enough (for example if an input file is mmap'ed), or can be done by
+  repeated calls of the compression function.  In the latter case, the
+  application must provide more input and/or consume the output
+  (providing more output space) before each call.
+
+     The compressed data format used by the in-memory functions is the zlib
+  format, which is a zlib wrapper documented in RFC 1950, wrapped around a
+  deflate stream, which is itself documented in RFC 1951.
+
+     The library also supports reading and writing files in gzip (.gz) format
+  with an interface similar to that of stdio using the functions that start
+  with "gz".  The gzip format is different from the zlib format.  gzip is a
+  gzip wrapper, documented in RFC 1952, wrapped around a deflate stream.
+
+     The zlib format was designed to be compact and fast for use in memory
+  and on communications channels.  The gzip format was designed for single-
+  file compression on file systems, has a larger header than zlib to maintain
+  directory information, and uses a different, slower check method than zlib.
+
+     This library does not provide any functions to write gzip files in memory.
+  However such functions could be easily written using zlib's deflate function,
+  the documentation in the gzip RFC, and the examples in gzio.c.
+
+     The library does not install any signal handler. The decoder checks
+  the consistency of the compressed data, so the library should never
+  crash even in case of corrupted input.
+*/
+
+alias void* (*alloc_func) (void* opaque, uint items, uint size);
+alias void   (*free_func)  (void* opaque, void* address);
+
+struct z_stream
+{
+    ubyte    *next_in;  /* next input byte */
+    uint     avail_in;  /* number of bytes available at next_in */
+    Culong_t total_in;  /* total nb of input bytes read so far */
+
+    ubyte    *next_out; /* next output byte should be put there */
+    uint     avail_out; /* remaining free space at next_out */
+    Culong_t total_out; /* total nb of bytes output so far */
+
+    char     *msg;      /* last error message, NULL if no error */
+    void*    state;     /* not visible by applications */
+
+    alloc_func zalloc;  /* used to allocate the internal state */
+    free_func  zfree;   /* used to free the internal state */
+    void*      opaque;  /* private data object passed to zalloc and zfree */
+
+    int      data_type;  /* best guess about the data type: ascii or binary */
+    Culong_t adler;      /* adler32 value of the uncompressed data */
+    Culong_t reserved;   /* reserved for future use */
+}
+
+alias z_stream* z_streamp;
+
+/*
+   The application must update next_in and avail_in when avail_in has
+   dropped to zero. It must update next_out and avail_out when avail_out
+   has dropped to zero. The application must initialize zalloc, zfree and
+   opaque before calling the init function. All other fields are set by the
+   compression library and must not be updated by the application.
+
+   The opaque value provided by the application will be passed as the first
+   parameter for calls of zalloc and zfree. This can be useful for custom
+   memory management. The compression library attaches no meaning to the
+   opaque value.
+
+   zalloc must return Z_NULL if there is not enough memory for the object.
+   If zlib is used in a multi-threaded application, zalloc and zfree must be
+   thread safe.
+
+   On 16-bit systems, the functions zalloc and zfree must be able to allocate
+   exactly 65536 bytes, but will not be required to allocate more than this
+   if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS,
+   pointers returned by zalloc for objects of exactly 65536 bytes *must*
+   have their offset normalized to zero. The default allocation function
+   provided by this library ensures this (see zutil.c). To reduce memory
+   requirements and avoid any allocation of 64K objects, at the expense of
+   compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h).
+
+   The fields total_in and total_out can be used for statistics or
+   progress reports. After compression, total_in holds the total size of
+   the uncompressed data and may be saved for use in the decompressor
+   (particularly if the decompressor wants to decompress everything in
+   a single step).
+*/
+
+                        /* constants */
+
+enum
+{
+	Z_NO_FLUSH      = 0,
+	Z_PARTIAL_FLUSH = 1, /* will be removed, use Z_SYNC_FLUSH instead */
+	Z_SYNC_FLUSH    = 2,
+	Z_FULL_FLUSH    = 3,
+	Z_FINISH        = 4,
+	Z_BLOCK         = 5
+}
+/* Allowed flush values; see deflate() and inflate() below for details */
+
+enum
+{
+	Z_OK            = 0,
+	Z_STREAM_END    = 1,
+	Z_NEED_DICT     = 2,
+	Z_ERRNO         = -1,
+	Z_STREAM_ERROR  = -2,
+	Z_DATA_ERROR    = -3,
+	Z_MEM_ERROR     = -4,
+	Z_BUF_ERROR     = -5,
+	Z_VERSION_ERROR = -6,
+}
+/* Return codes for the compression/decompression functions. Negative
+ * values are errors, positive values are used for special but normal events.
+ */
+
+enum
+{
+	Z_NO_COMPRESSION         = 0,
+	Z_BEST_SPEED             = 1,
+	Z_BEST_COMPRESSION       = 9,
+	Z_DEFAULT_COMPRESSION    = -1,
+}
+/* compression levels */
+
+enum
+{
+	Z_FILTERED            = 1,
+	Z_HUFFMAN_ONLY        = 2,
+	Z_RLE                 = 3,
+	Z_DEFAULT_STRATEGY    = 0,
+}
+/* compression strategy; see deflateInit2() below for details */
+
+enum
+{
+	Z_BINARY   = 0,
+	Z_ASCII    = 1,
+	Z_UNKNOWN  = 2,
+}
+/* Possible values of the data_type field (though see inflate()) */
+
+enum
+{
+	Z_DEFLATED   = 8,
+}
+/* The deflate compression method (the only one supported in this version) */
+
+const int Z_NULL = 0;  /* for initializing zalloc, zfree, opaque */
+
+                        /* basic functions */
+
+char* zlibVersion();
+/* The application can compare zlibVersion and ZLIB_VERSION for consistency.
+   If the first character differs, the library code actually used is
+   not compatible with the zlib.h header file used by the application.
+   This check is automatically made by deflateInit and inflateInit.
+ */
+
+int deflateInit(z_streamp strm, int level)
+{
+    return deflateInit_(strm, level, ZLIB_VERSION.ptr, z_stream.sizeof);
+}
+/* 
+     Initializes the internal stream state for compression. The fields
+   zalloc, zfree and opaque must be initialized before by the caller.
+   If zalloc and zfree are set to Z_NULL, deflateInit updates them to
+   use default allocation functions.
+
+     The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9:
+   1 gives best speed, 9 gives best compression, 0 gives no compression at
+   all (the input data is simply copied a block at a time).
+   Z_DEFAULT_COMPRESSION requests a default compromise between speed and
+   compression (currently equivalent to level 6).
+
+     deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_STREAM_ERROR if level is not a valid compression level,
+   Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible
+   with the version assumed by the caller (ZLIB_VERSION).
+   msg is set to null if there is no error message.  deflateInit does not
+   perform any compression: this will be done by deflate().
+*/
+
+
+int deflate(z_streamp strm, int flush);
+/*
+    deflate compresses as much data as possible, and stops when the input
+  buffer becomes empty or the output buffer becomes full. It may introduce some
+  output latency (reading input without producing any output) except when
+  forced to flush.
+
+    The detailed semantics are as follows. deflate performs one or both of the
+  following actions:
+
+  - Compress more input starting at next_in and update next_in and avail_in
+    accordingly. If not all input can be processed (because there is not
+    enough room in the output buffer), next_in and avail_in are updated and
+    processing will resume at this point for the next call of deflate().
+
+  - Provide more output starting at next_out and update next_out and avail_out
+    accordingly. This action is forced if the parameter flush is non zero.
+    Forcing flush frequently degrades the compression ratio, so this parameter
+    should be set only when necessary (in interactive applications).
+    Some output may be provided even if flush is not set.
+
+  Before the call of deflate(), the application should ensure that at least
+  one of the actions is possible, by providing more input and/or consuming
+  more output, and updating avail_in or avail_out accordingly; avail_out
+  should never be zero before the call. The application can consume the
+  compressed output when it wants, for example when the output buffer is full
+  (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK
+  and with zero avail_out, it must be called again after making room in the
+  output buffer because there might be more output pending.
+
+    If the parameter flush is set to Z_SYNC_FLUSH, all pending output is
+  flushed to the output buffer and the output is aligned on a byte boundary, so
+  that the decompressor can get all input data available so far. (In particular
+  avail_in is zero after the call if enough output space has been provided
+  before the call.)  Flushing may degrade compression for some compression
+  algorithms and so it should be used only when necessary.
+
+    If flush is set to Z_FULL_FLUSH, all output is flushed as with
+  Z_SYNC_FLUSH, and the compression state is reset so that decompression can
+  restart from this point if previous compressed data has been damaged or if
+  random access is desired. Using Z_FULL_FLUSH too often can seriously degrade
+  the compression.
+
+    If deflate returns with avail_out == 0, this function must be called again
+  with the same value of the flush parameter and more output space (updated
+  avail_out), until the flush is complete (deflate returns with non-zero
+  avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that
+  avail_out is greater than six to avoid repeated flush markers due to
+  avail_out == 0 on return.
+
+    If the parameter flush is set to Z_FINISH, pending input is processed,
+  pending output is flushed and deflate returns with Z_STREAM_END if there
+  was enough output space; if deflate returns with Z_OK, this function must be
+  called again with Z_FINISH and more output space (updated avail_out) but no
+  more input data, until it returns with Z_STREAM_END or an error. After
+  deflate has returned Z_STREAM_END, the only possible operations on the
+  stream are deflateReset or deflateEnd.
+
+    Z_FINISH can be used immediately after deflateInit if all the compression
+  is to be done in a single step. In this case, avail_out must be at least
+  the value returned by deflateBound (see below). If deflate does not return
+  Z_STREAM_END, then it must be called again as described above.
+
+    deflate() sets strm->adler to the adler32 checksum of all input read
+  so far (that is, total_in bytes).
+
+    deflate() may update data_type if it can make a good guess about
+  the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered
+  binary. This field is only for information purposes and does not affect
+  the compression algorithm in any manner.
+
+    deflate() returns Z_OK if some progress has been made (more input
+  processed or more output produced), Z_STREAM_END if all input has been
+  consumed and all output has been produced (only when flush is set to
+  Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example
+  if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible
+  (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not
+  fatal, and deflate() can be called again with more input and more output
+  space to continue compressing.
+*/
+
+
+int deflateEnd(z_streamp strm);
+/*
+     All dynamically allocated data structures for this stream are freed.
+   This function discards any unprocessed input and does not flush any
+   pending output.
+
+     deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the
+   stream state was inconsistent, Z_DATA_ERROR if the stream was freed
+   prematurely (some input or output was discarded). In the error case,
+   msg may be set but then points to a static string (which must not be
+   deallocated).
+*/
+
+
+int inflateInit(z_streamp strm)
+{
+    return inflateInit_(strm, ZLIB_VERSION.ptr, z_stream.sizeof);
+}
+/* 
+     Initializes the internal stream state for decompression. The fields
+   next_in, avail_in, zalloc, zfree and opaque must be initialized before by
+   the caller. If next_in is not Z_NULL and avail_in is large enough (the exact
+   value depends on the compression method), inflateInit determines the
+   compression method from the zlib header and allocates all data structures
+   accordingly; otherwise the allocation will be deferred to the first call of
+   inflate.  If zalloc and zfree are set to Z_NULL, inflateInit updates them to
+   use default allocation functions.
+
+     inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
+   version assumed by the caller.  msg is set to null if there is no error
+   message. inflateInit does not perform any decompression apart from reading
+   the zlib header if present: this will be done by inflate().  (So next_in and
+   avail_in may be modified, but next_out and avail_out are unchanged.)
+*/
+
+
+int inflate(z_streamp strm, int flush);
+/*
+    inflate decompresses as much data as possible, and stops when the input
+  buffer becomes empty or the output buffer becomes full. It may introduce
+  some output latency (reading input without producing any output) except when
+  forced to flush.
+
+  The detailed semantics are as follows. inflate performs one or both of the
+  following actions:
+
+  - Decompress more input starting at next_in and update next_in and avail_in
+    accordingly. If not all input can be processed (because there is not
+    enough room in the output buffer), next_in is updated and processing
+    will resume at this point for the next call of inflate().
+
+  - Provide more output starting at next_out and update next_out and avail_out
+    accordingly.  inflate() provides as much output as possible, until there
+    is no more input data or no more space in the output buffer (see below
+    about the flush parameter).
+
+  Before the call of inflate(), the application should ensure that at least
+  one of the actions is possible, by providing more input and/or consuming
+  more output, and updating the next_* and avail_* values accordingly.
+  The application can consume the uncompressed output when it wants, for
+  example when the output buffer is full (avail_out == 0), or after each
+  call of inflate(). If inflate returns Z_OK and with zero avail_out, it
+  must be called again after making room in the output buffer because there
+  might be more output pending.
+
+    The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH,
+  Z_FINISH, or Z_BLOCK. Z_SYNC_FLUSH requests that inflate() flush as much
+  output as possible to the output buffer. Z_BLOCK requests that inflate() stop
+  if and when it get to the next deflate block boundary. When decoding the zlib
+  or gzip format, this will cause inflate() to return immediately after the
+  header and before the first block. When doing a raw inflate, inflate() will
+  go ahead and process the first block, and will return when it gets to the end
+  of that block, or when it runs out of data.
+
+    The Z_BLOCK option assists in appending to or combining deflate streams.
+  Also to assist in this, on return inflate() will set strm->data_type to the
+  number of unused bits in the last byte taken from strm->next_in, plus 64
+  if inflate() is currently decoding the last block in the deflate stream,
+  plus 128 if inflate() returned immediately after decoding an end-of-block
+  code or decoding the complete header up to just before the first byte of the
+  deflate stream. The end-of-block will not be indicated until all of the
+  uncompressed data from that block has been written to strm->next_out.  The
+  number of unused bits may in general be greater than seven, except when
+  bit 7 of data_type is set, in which case the number of unused bits will be
+  less than eight.
+
+    inflate() should normally be called until it returns Z_STREAM_END or an
+  error. However if all decompression is to be performed in a single step
+  (a single call of inflate), the parameter flush should be set to
+  Z_FINISH. In this case all pending input is processed and all pending
+  output is flushed; avail_out must be large enough to hold all the
+  uncompressed data. (The size of the uncompressed data may have been saved
+  by the compressor for this purpose.) The next operation on this stream must
+  be inflateEnd to deallocate the decompression state. The use of Z_FINISH
+  is never required, but can be used to inform inflate that a faster approach
+  may be used for the single inflate() call.
+
+     In this implementation, inflate() always flushes as much output as
+  possible to the output buffer, and always uses the faster approach on the
+  first call. So the only effect of the flush parameter in this implementation
+  is on the return value of inflate(), as noted below, or when it returns early
+  because Z_BLOCK is used.
+
+     If a preset dictionary is needed after this call (see inflateSetDictionary
+  below), inflate sets strm-adler to the adler32 checksum of the dictionary
+  chosen by the compressor and returns Z_NEED_DICT; otherwise it sets
+  strm->adler to the adler32 checksum of all output produced so far (that is,
+  total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described
+  below. At the end of the stream, inflate() checks that its computed adler32
+  checksum is equal to that saved by the compressor and returns Z_STREAM_END
+  only if the checksum is correct.
+
+    inflate() will decompress and check either zlib-wrapped or gzip-wrapped
+  deflate data.  The header type is detected automatically.  Any information
+  contained in the gzip header is not retained, so applications that need that
+  information should instead use raw inflate, see inflateInit2() below, or
+  inflateBack() and perform their own processing of the gzip header and
+  trailer.
+
+    inflate() returns Z_OK if some progress has been made (more input processed
+  or more output produced), Z_STREAM_END if the end of the compressed data has
+  been reached and all uncompressed output has been produced, Z_NEED_DICT if a
+  preset dictionary is needed at this point, Z_DATA_ERROR if the input data was
+  corrupted (input stream not conforming to the zlib format or incorrect check
+  value), Z_STREAM_ERROR if the stream structure was inconsistent (for example
+  if next_in or next_out was NULL), Z_MEM_ERROR if there was not enough memory,
+  Z_BUF_ERROR if no progress is possible or if there was not enough room in the
+  output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and
+  inflate() can be called again with more input and more output space to
+  continue decompressing. If Z_DATA_ERROR is returned, the application may then
+  call inflateSync() to look for a good compression block if a partial recovery
+  of the data is desired.
+*/
+
+
+int inflateEnd(z_streamp strm);
+/*
+     All dynamically allocated data structures for this stream are freed.
+   This function discards any unprocessed input and does not flush any
+   pending output.
+
+     inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state
+   was inconsistent. In the error case, msg may be set but then points to a
+   static string (which must not be deallocated).
+*/
+
+                        /* Advanced functions */
+
+/*
+    The following functions are needed only in some special applications.
+*/
+
+int deflateInit2(z_streamp strm,
+                 int  level,
+                 int  method,
+                 int  windowBits,
+                 int  memLevel,
+                 int  strategy)
+{
+    return deflateInit2_(strm, level, method, windowBits, memLevel,
+                         strategy, ZLIB_VERSION.ptr, z_stream.sizeof);
+}
+/*
+     This is another version of deflateInit with more compression options. The
+   fields next_in, zalloc, zfree and opaque must be initialized before by
+   the caller.
+
+     The method parameter is the compression method. It must be Z_DEFLATED in
+   this version of the library.
+
+     The windowBits parameter is the base two logarithm of the window size
+   (the size of the history buffer). It should be in the range 8..15 for this
+   version of the library. Larger values of this parameter result in better
+   compression at the expense of memory usage. The default value is 15 if
+   deflateInit is used instead.
+
+     windowBits can also be -8..-15 for raw deflate. In this case, -windowBits
+   determines the window size. deflate() will then generate raw deflate data
+   with no zlib header or trailer, and will not compute an adler32 check value.
+
+     windowBits can also be greater than 15 for optional gzip encoding. Add
+   16 to windowBits to write a simple gzip header and trailer around the
+   compressed data instead of a zlib wrapper. The gzip header will have no
+   file name, no extra data, no comment, no modification time (set to zero),
+   no header crc, and the operating system will be set to 255 (unknown).
+
+     The memLevel parameter specifies how much memory should be allocated
+   for the internal compression state. memLevel=1 uses minimum memory but
+   is slow and reduces compression ratio; memLevel=9 uses maximum memory
+   for optimal speed. The default value is 8. See zconf.h for total memory
+   usage as a function of windowBits and memLevel.
+
+     The strategy parameter is used to tune the compression algorithm. Use the
+   value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a
+   filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no
+   string match), or Z_RLE to limit match distances to one (run-length
+   encoding). Filtered data consists mostly of small values with a somewhat
+   random distribution. In this case, the compression algorithm is tuned to
+   compress them better. The effect of Z_FILTERED is to force more Huffman
+   coding and less string matching; it is somewhat intermediate between
+   Z_DEFAULT and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as fast as
+   Z_HUFFMAN_ONLY, but give better compression for PNG image data. The strategy
+   parameter only affects the compression ratio but not the correctness of the
+   compressed output even if it is not set appropriately.
+
+      deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid
+   method). msg is set to null if there is no error message.  deflateInit2 does
+   not perform any compression: this will be done by deflate().
+*/
+                            
+int deflateSetDictionary(z_streamp strm, ubyte* dictionary, uint  dictLength);
+/*
+     Initializes the compression dictionary from the given byte sequence
+   without producing any compressed output. This function must be called
+   immediately after deflateInit, deflateInit2 or deflateReset, before any
+   call of deflate. The compressor and decompressor must use exactly the same
+   dictionary (see inflateSetDictionary).
+
+     The dictionary should consist of strings (byte sequences) that are likely
+   to be encountered later in the data to be compressed, with the most commonly
+   used strings preferably put towards the end of the dictionary. Using a
+   dictionary is most useful when the data to be compressed is short and can be
+   predicted with good accuracy; the data can then be compressed better than
+   with the default empty dictionary.
+
+     Depending on the size of the compression data structures selected by
+   deflateInit or deflateInit2, a part of the dictionary may in effect be
+   discarded, for example if the dictionary is larger than the window size in
+   deflate or deflate2. Thus the strings most likely to be useful should be
+   put at the end of the dictionary, not at the front.
+
+     Upon return of this function, strm->adler is set to the adler32 value
+   of the dictionary; the decompressor may later use this value to determine
+   which dictionary has been used by the compressor. (The adler32 value
+   applies to the whole dictionary even if only a subset of the dictionary is
+   actually used by the compressor.) If a raw deflate was requested, then the
+   adler32 value is not computed and strm->adler is not set.
+
+     deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a
+   parameter is invalid (such as NULL dictionary) or the stream state is
+   inconsistent (for example if deflate has already been called for this stream
+   or if the compression method is bsort). deflateSetDictionary does not
+   perform any compression: this will be done by deflate().
+*/
+
+int deflateCopy(z_streamp dest, z_streamp source);
+/*
+     Sets the destination stream as a complete copy of the source stream.
+
+     This function can be useful when several compression strategies will be
+   tried, for example when there are several ways of pre-processing the input
+   data with a filter. The streams that will be discarded should then be freed
+   by calling deflateEnd.  Note that deflateCopy duplicates the internal
+   compression state which can be quite large, so this strategy is slow and
+   can consume lots of memory.
+
+     deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
+   (such as zalloc being NULL). msg is left unchanged in both source and
+   destination.
+*/
+
+int deflateReset(z_streamp strm);
+/*
+     This function is equivalent to deflateEnd followed by deflateInit,
+   but does not free and reallocate all the internal compression state.
+   The stream will keep the same compression level and any other attributes
+   that may have been set by deflateInit2.
+
+      deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent (such as zalloc or state being NULL).
+*/
+
+int deflateParams(z_streamp strm, int level, int strategy);
+/*
+     Dynamically update the compression level and compression strategy.  The
+   interpretation of level and strategy is as in deflateInit2.  This can be
+   used to switch between compression and straight copy of the input data, or
+   to switch to a different kind of input data requiring a different
+   strategy. If the compression level is changed, the input available so far
+   is compressed with the old level (and may be flushed); the new level will
+   take effect only at the next call of deflate().
+
+     Before the call of deflateParams, the stream state must be set as for
+   a call of deflate(), since the currently available input may have to
+   be compressed and flushed. In particular, strm->avail_out must be non-zero.
+
+     deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source
+   stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR
+   if strm->avail_out was zero.
+*/
+
+uint deflateBound(z_streamp strm, uint Culong_t);
+/*
+     deflateBound() returns an upper bound on the compressed size after
+   deflation of sourceLen bytes.  It must be called after deflateInit()
+   or deflateInit2().  This would be used to allocate an output buffer
+   for deflation in a single pass, and so would be called before deflate().
+*/
+
+int deflatePrime(z_streamp strm, int bits, int value);
+/*
+     deflatePrime() inserts bits in the deflate output stream.  The intent
+  is that this function is used to start off the deflate output with the
+  bits leftover from a previous deflate stream when appending to it.  As such,
+  this function can only be used for raw deflate, and must be used before the
+  first deflate() call after a deflateInit2() or deflateReset().  bits must be
+  less than or equal to 16, and that many of the least significant bits of
+  value will be inserted in the output.
+
+      deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent.
+*/
+
+int inflateInit2(z_streamp strm, int windowBits)
+{
+    return inflateInit2_(strm, windowBits, ZLIB_VERSION.ptr, z_stream.sizeof);
+}
+/*   
+     This is another version of inflateInit with an extra parameter. The
+   fields next_in, avail_in, zalloc, zfree and opaque must be initialized
+   before by the caller.
+
+     The windowBits parameter is the base two logarithm of the maximum window
+   size (the size of the history buffer).  It should be in the range 8..15 for
+   this version of the library. The default value is 15 if inflateInit is used
+   instead. windowBits must be greater than or equal to the windowBits value
+   provided to deflateInit2() while compressing, or it must be equal to 15 if
+   deflateInit2() was not used. If a compressed stream with a larger window
+   size is given as input, inflate() will return with the error code
+   Z_DATA_ERROR instead of trying to allocate a larger window.
+
+     windowBits can also be -8..-15 for raw inflate. In this case, -windowBits
+   determines the window size. inflate() will then process raw deflate data,
+   not looking for a zlib or gzip header, not generating a check value, and not
+   looking for any check values for comparison at the end of the stream. This
+   is for use with other formats that use the deflate compressed data format
+   such as zip.  Those formats provide their own check values. If a custom
+   format is developed using the raw deflate format for compressed data, it is
+   recommended that a check value such as an adler32 or a crc32 be applied to
+   the uncompressed data as is done in the zlib, gzip, and zip formats.  For
+   most applications, the zlib format should be used as is. Note that comments
+   above on the use in deflateInit2() applies to the magnitude of windowBits.
+
+     windowBits can also be greater than 15 for optional gzip decoding. Add
+   32 to windowBits to enable zlib and gzip decoding with automatic header
+   detection, or add 16 to decode only the gzip format (the zlib format will
+   return a Z_DATA_ERROR).
+
+     inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative
+   memLevel). msg is set to null if there is no error message.  inflateInit2
+   does not perform any decompression apart from reading the zlib header if
+   present: this will be done by inflate(). (So next_in and avail_in may be
+   modified, but next_out and avail_out are unchanged.)
+*/
+
+int inflateSetDictionary(z_streamp strm, ubyte* dictionary, uint  dictLength);
+/*
+     Initializes the decompression dictionary from the given uncompressed byte
+   sequence. This function must be called immediately after a call of inflate
+   if this call returned Z_NEED_DICT. The dictionary chosen by the compressor
+   can be determined from the adler32 value returned by this call of
+   inflate. The compressor and decompressor must use exactly the same
+   dictionary (see deflateSetDictionary).
+
+     inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a
+   parameter is invalid (such as NULL dictionary) or the stream state is
+   inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the
+   expected one (incorrect adler32 value). inflateSetDictionary does not
+   perform any decompression: this will be done by subsequent calls of
+   inflate().
+*/
+
+int inflateSync(z_streamp strm);
+/* 
+    Skips invalid compressed data until a full flush point (see above the
+  description of deflate with Z_FULL_FLUSH) can be found, or until all
+  available input is skipped. No output is provided.
+
+    inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR
+  if no more input was provided, Z_DATA_ERROR if no flush point has been found,
+  or Z_STREAM_ERROR if the stream structure was inconsistent. In the success
+  case, the application may save the current current value of total_in which
+  indicates where valid compressed data was found. In the error case, the
+  application may repeatedly call inflateSync, providing more input each time,
+  until success or end of the input data.
+*/
+
+int inflateCopy (z_streamp dest, z_streamp source);
+/*
+     Sets the destination stream as a complete copy of the source stream.
+
+     This function can be useful when randomly accessing a large stream.  The
+   first pass through the stream can periodically record the inflate state,
+   allowing restarting inflate at those points when randomly accessing the
+   stream.
+
+     inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
+   (such as zalloc being NULL). msg is left unchanged in both source and
+   destination.
+*/
+
+int inflateReset(z_streamp strm);
+/*
+     This function is equivalent to inflateEnd followed by inflateInit,
+   but does not free and reallocate all the internal decompression state.
+   The stream will keep attributes that may have been set by inflateInit2.
+
+      inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent (such as zalloc or state being NULL).
+*/
+
+
+int inflateBackInit(z_stream* strm, int windowBits, ubyte* window)
+{
+    return inflateBackInit_(strm, windowBits, window, ZLIB_VERSION.ptr, z_stream.sizeof);   
+}
+/*
+     Initialize the internal stream state for decompression using inflateBack()
+   calls.  The fields zalloc, zfree and opaque in strm must be initialized
+   before the call.  If zalloc and zfree are Z_NULL, then the default library-
+   derived memory allocation routines are used.  windowBits is the base two
+   logarithm of the window size, in the range 8..15.  window is a caller
+   supplied buffer of that size.  Except for special applications where it is
+   assured that deflate was used with small window sizes, windowBits must be 15
+   and a 32K byte window must be supplied to be able to decompress general
+   deflate streams.
+
+     See inflateBack() for the usage of these routines.
+
+     inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of
+   the paramaters are invalid, Z_MEM_ERROR if the internal state could not
+   be allocated, or Z_VERSION_ERROR if the version of the library does not
+   match the version of the header file.
+*/
+
+alias uint function(void*, ubyte**) in_func;
+alias int function(void*, ubyte*, uint) out_func;
+
+int inflateBack(z_stream* strm,
+                in_func f_in,
+                void* in_desc,
+                out_func f_out,
+                void* out_desc);
+/*
+     inflateBack() does a raw inflate with a single call using a call-back
+   interface for input and output.  This is more efficient than inflate() for
+   file i/o applications in that it avoids copying between the output and the
+   sliding window by simply making the window itself the output buffer.  This
+   function trusts the application to not change the output buffer passed by
+   the output function, at least until inflateBack() returns.
+
+     inflateBackInit() must be called first to allocate the internal state
+   and to initialize the state with the user-provided window buffer.
+   inflateBack() may then be used multiple times to inflate a complete, raw
+   deflate stream with each call.  inflateBackEnd() is then called to free
+   the allocated state.
+
+     A raw deflate stream is one with no zlib or gzip header or trailer.
+   This routine would normally be used in a utility that reads zip or gzip
+   files and writes out uncompressed files.  The utility would decode the
+   header and process the trailer on its own, hence this routine expects
+   only the raw deflate stream to decompress.  This is different from the
+   normal behavior of inflate(), which expects either a zlib or gzip header and
+   trailer around the deflate stream.
+
+     inflateBack() uses two subroutines supplied by the caller that are then
+   called by inflateBack() for input and output.  inflateBack() calls those
+   routines until it reads a complete deflate stream and writes out all of the
+   uncompressed data, or until it encounters an error.  The function's
+   parameters and return types are defined above in the in_func and out_func
+   typedefs.  inflateBack() will call in(in_desc, &buf) which should return the
+   number of bytes of provided input, and a pointer to that input in buf.  If
+   there is no input available, in() must return zero--buf is ignored in that
+   case--and inflateBack() will return a buffer error.  inflateBack() will call
+   out(out_desc, buf, len) to write the uncompressed data buf[0..len-1].  out()
+   should return zero on success, or non-zero on failure.  If out() returns
+   non-zero, inflateBack() will return with an error.  Neither in() nor out()
+   are permitted to change the contents of the window provided to
+   inflateBackInit(), which is also the buffer that out() uses to write from.
+   The length written by out() will be at most the window size.  Any non-zero
+   amount of input may be provided by in().
+
+     For convenience, inflateBack() can be provided input on the first call by
+   setting strm->next_in and strm->avail_in.  If that input is exhausted, then
+   in() will be called.  Therefore strm->next_in must be initialized before
+   calling inflateBack().  If strm->next_in is Z_NULL, then in() will be called
+   immediately for input.  If strm->next_in is not Z_NULL, then strm->avail_in
+   must also be initialized, and then if strm->avail_in is not zero, input will
+   initially be taken from strm->next_in[0 .. strm->avail_in - 1].
+
+     The in_desc and out_desc parameters of inflateBack() is passed as the
+   first parameter of in() and out() respectively when they are called.  These
+   descriptors can be optionally used to pass any information that the caller-
+   supplied in() and out() functions need to do their job.
+
+     On return, inflateBack() will set strm->next_in and strm->avail_in to
+   pass back any unused input that was provided by the last in() call.  The
+   return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR
+   if in() or out() returned an error, Z_DATA_ERROR if there was a format
+   error in the deflate stream (in which case strm->msg is set to indicate the
+   nature of the error), or Z_STREAM_ERROR if the stream was not properly
+   initialized.  In the case of Z_BUF_ERROR, an input or output error can be
+   distinguished using strm->next_in which will be Z_NULL only if in() returned
+   an error.  If strm->next is not Z_NULL, then the Z_BUF_ERROR was due to
+   out() returning non-zero.  (in() will always be called before out(), so
+   strm->next_in is assured to be defined if out() returns non-zero.)  Note
+   that inflateBack() cannot return Z_OK.
+*/
+
+int inflateBackEnd(z_stream* strm);
+/*
+     All memory allocated by inflateBackInit() is freed.
+
+     inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream
+   state was inconsistent.
+*/
+
+uint zlibCompileFlags();
+/* Return flags indicating compile-time options.
+
+    Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other:
+     1.0: size of uInt
+     3.2: size of uLong
+     5.4: size of voidpf (pointer)
+     7.6: size of z_off_t
+
+    Compiler, assembler, and debug options:
+     8: DEBUG
+     9: ASMV or ASMINF -- use ASM code
+     10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention
+     11: 0 (reserved)
+
+    One-time table building (smaller code, but not thread-safe if true):
+     12: BUILDFIXED -- build static block decoding tables when needed
+     13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed
+     14,15: 0 (reserved)
+
+    Library content (indicates missing functionality):
+     16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking
+                          deflate code when not needed)
+     17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect
+                    and decode gzip streams (to avoid linking crc code)
+     18-19: 0 (reserved)
+
+    Operation variations (changes in library functionality):
+     20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate
+     21: FASTEST -- deflate algorithm with only one, lowest compression level
+     22,23: 0 (reserved)
+
+    The sprintf variant used by gzprintf (zero is best):
+     24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format
+     25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure!
+     26: 0 = returns value, 1 = void -- 1 means inferred string length returned
+
+    Remainder:
+     27-31: 0 (reserved)
+ */
+
+                        /* utility functions */
+
+/*
+     The following utility functions are implemented on top of the
+   basic stream-oriented functions. To simplify the interface, some
+   default options are assumed (compression level and memory usage,
+   standard memory allocation functions). The source code of these
+   utility functions can easily be modified if you need special options.
+*/
+
+int compress(ubyte* dest,
+             Culong_t* destLen,
+             ubyte* source,
+             Culong_t sourceLen);
+/*
+     Compresses the source buffer into the destination buffer.  sourceLen is
+   the byte length of the source buffer. Upon entry, destLen is the total
+   size of the destination buffer, which must be at least the value returned
+   by compressBound(sourceLen). Upon exit, destLen is the actual size of the
+   compressed buffer.
+     This function can be used to compress a whole file at once if the
+   input file is mmap'ed.
+     compress returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_BUF_ERROR if there was not enough room in the output
+   buffer.
+*/
+
+int compress2(ubyte* dest,
+              Culong_t* destLen,
+              ubyte* source,
+              Culong_t sourceLen,
+              int level);
+/*
+     Compresses the source buffer into the destination buffer. The level
+   parameter has the same meaning as in deflateInit.  sourceLen is the byte
+   length of the source buffer. Upon entry, destLen is the total size of the
+   destination buffer, which must be at least the value returned by
+   compressBound(sourceLen). Upon exit, destLen is the actual size of the
+   compressed buffer.
+
+     compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_BUF_ERROR if there was not enough room in the output buffer,
+   Z_STREAM_ERROR if the level parameter is invalid.
+*/
+
+uint compressBound(Culong_t sourceLen);
+/*
+     compressBound() returns an upper bound on the compressed size after
+   compress() or compress2() on sourceLen bytes.  It would be used before
+   a compress() or compress2() call to allocate the destination buffer.
+*/
+
+int uncompress(ubyte* dest,
+               uint* Culong_t,
+               ubyte* source,
+               uint Culong_t);
+/*
+     Decompresses the source buffer into the destination buffer.  sourceLen is
+   the byte length of the source buffer. Upon entry, destLen is the total
+   size of the destination buffer, which must be large enough to hold the
+   entire uncompressed data. (The size of the uncompressed data must have
+   been saved previously by the compressor and transmitted to the decompressor
+   by some mechanism outside the scope of this compression library.)
+   Upon exit, destLen is the actual size of the compressed buffer.
+     This function can be used to decompress a whole file at once if the
+   input file is mmap'ed.
+
+     uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_BUF_ERROR if there was not enough room in the output
+   buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete.
+*/
+
+
+typedef void* gzFile;
+alias int z_off_t;		// file offset
+
+gzFile gzopen(char* path, char* mode);
+/*
+     Opens a gzip (.gz) file for reading or writing. The mode parameter
+   is as in fopen ("rb" or "wb") but can also include a compression level
+   ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for
+   Huffman only compression as in "wb1h", or 'R' for run-length encoding
+   as in "wb1R". (See the description of deflateInit2 for more information
+   about the strategy parameter.)
+
+     gzopen can be used to read a file which is not in gzip format; in this
+   case gzread will directly read from the file without decompression.
+
+     gzopen returns NULL if the file could not be opened or if there was
+   insufficient memory to allocate the (de)compression state; errno
+   can be checked to distinguish the two cases (if errno is zero, the
+   zlib error is Z_MEM_ERROR).  */
+
+gzFile gzdopen(int fd, char* mode);
+/*
+     gzdopen() associates a gzFile with the file descriptor fd.  File
+   descriptors are obtained from calls like open, dup, creat, pipe or
+   fileno (in the file has been previously opened with fopen).
+   The mode parameter is as in gzopen.
+     The next call of gzclose on the returned gzFile will also close the
+   file descriptor fd, just like fclose(fdopen(fd), mode) closes the file
+   descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode).
+     gzdopen returns NULL if there was insufficient memory to allocate
+   the (de)compression state.
+*/
+
+int gzsetparams(gzFile file, int level, int strategy);
+/*
+     Dynamically update the compression level or strategy. See the description
+   of deflateInit2 for the meaning of these parameters.
+     gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not
+   opened for writing.
+*/
+
+int gzread(gzFile file, void* buf, uint len);
+/*
+     Reads the given number of uncompressed bytes from the compressed file.
+   If the input file was not in gzip format, gzread copies the given number
+   of bytes into the buffer.
+     gzread returns the number of uncompressed bytes actually read (0 for
+   end of file, -1 for error). */
+
+int gzwrite(gzFile file, void* buf, uint len);
+/*
+     Writes the given number of uncompressed bytes into the compressed file.
+   gzwrite returns the number of uncompressed bytes actually written
+   (0 in case of error).
+*/
+
+int gzprintf(gzFile file, char* format, ...);
+/*
+     Converts, formats, and writes the args to the compressed file under
+   control of the format string, as in fprintf. gzprintf returns the number of
+   uncompressed bytes actually written (0 in case of error).  The number of
+   uncompressed bytes written is limited to 4095. The caller should assure that
+   this limit is not exceeded. If it is exceeded, then gzprintf() will return
+   return an error (0) with nothing written. In this case, there may also be a
+   buffer overflow with unpredictable consequences, which is possible only if
+   zlib was compiled with the insecure functions sprintf() or vsprintf()
+   because the secure snprintf() or vsnprintf() functions were not available.
+*/
+
+int gzputs(gzFile file, char* s);
+/*
+      Writes the given null-terminated string to the compressed file, excluding
+   the terminating null character.
+      gzputs returns the number of characters written, or -1 in case of error.
+*/
+
+char* gzgets(gzFile file, char* buf, int len);
+/*
+      Reads bytes from the compressed file until len-1 characters are read, or
+   a newline character is read and transferred to buf, or an end-of-file
+   condition is encountered.  The string is then terminated with a null
+   character.
+      gzgets returns buf, or Z_NULL in case of error.
+*/
+
+int gzputc(gzFile file, int c);
+/*
+      Writes c, converted to an unsigned char, into the compressed file.
+   gzputc returns the value that was written, or -1 in case of error.
+*/
+
+int    gzgetc(gzFile file);
+/*
+      Reads one byte from the compressed file. gzgetc returns this byte
+   or -1 in case of end of file or error.
+*/
+
+int gzungetc(int c, gzFile file);
+/*
+      Push one character back onto the stream to be read again later.
+   Only one character of push-back is allowed.  gzungetc() returns the
+   character pushed, or -1 on failure.  gzungetc() will fail if a
+   character has been pushed but not read yet, or if c is -1. The pushed
+   character will be discarded if the stream is repositioned with gzseek()
+   or gzrewind().
+*/
+
+int gzflush(gzFile file, int flush);
+/*
+     Flushes all pending output into the compressed file. The parameter
+   flush is as in the deflate() function. The return value is the zlib
+   error number (see function gzerror below). gzflush returns Z_OK if
+   the flush parameter is Z_FINISH and all output could be flushed.
+     gzflush should be called only when strictly necessary because it can
+   degrade compression.
+*/
+
+z_off_t gzseek(gzFile file, z_off_t offset, int whence);
+/* 
+      Sets the starting position for the next gzread or gzwrite on the
+   given compressed file. The offset represents a number of bytes in the
+   uncompressed data stream. The whence parameter is defined as in lseek(2);
+   the value SEEK_END is not supported.
+     If the file is opened for reading, this function is emulated but can be
+   extremely slow. If the file is opened for writing, only forward seeks are
+   supported; gzseek then compresses a sequence of zeroes up to the new
+   starting position.
+
+      gzseek returns the resulting offset location as measured in bytes from
+   the beginning of the uncompressed stream, or -1 in case of error, in
+   particular if the file is opened for writing and the new starting position
+   would be before the current position.
+*/
+
+int gzrewind(gzFile file);
+/*
+     Rewinds the given file. This function is supported only for reading.
+
+   gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET)
+*/
+
+z_off_t  gztell(gzFile file);
+/*
+     Returns the starting position for the next gzread or gzwrite on the
+   given compressed file. This position represents a number of bytes in the
+   uncompressed data stream.
+
+   gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR)
+*/
+
+int gzeof(gzFile file);
+/*
+     Returns 1 when EOF has previously been detected reading the given
+   input stream, otherwise zero.
+*/
+
+int gzclose(gzFile file);
+/*
+     Flushes all pending output if necessary, closes the compressed file
+   and deallocates all the (de)compression state. The return value is the zlib
+   error number (see function gzerror below).
+*/
+
+char* gzerror(gzFile file, int *errnum);
+/*
+     Returns the error message for the last error which occurred on the
+   given compressed file. errnum is set to zlib error number. If an
+   error occurred in the file system and not in the compression library,
+   errnum is set to Z_ERRNO and the application may consult errno
+   to get the exact error code.
+*/
+
+void gzclearerr (gzFile file);
+/*
+     Clears the error and end-of-file flags for file. This is analogous to the
+   clearerr() function in stdio. This is useful for continuing to read a gzip
+   file that is being written concurrently.
+*/
+
+                        /* checksum functions */
+
+/*
+     These functions are not related to compression but are exported
+   anyway because they might be useful in applications using the
+   compression library.
+*/
+
+ Culong_t adler32  (Culong_t adler, ubyte *buf, uint len);
+
+/*
+     Update a running Adler-32 checksum with the bytes buf[0..len-1] and
+   return the updated checksum. If buf is NULL, this function returns
+   the required initial value for the checksum.
+   An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
+   much faster. Usage example:
+
+     uint adler = adler32(0L, Z_NULL, 0);
+
+     while (read_buffer(buffer, length) != EOF) {
+       adler = adler32(adler, buffer, length);
+     }
+     if (adler != original_adler) error();
+*/
+
+Culong_t crc32(Culong_t crc, ubyte *buf, uint len);
+/*
+     Update a running crc with the bytes buf[0..len-1] and return the updated
+   crc. If buf is NULL, this function returns the required initial value
+   for the crc. Pre- and post-conditioning (one's complement) is performed
+   within this function so it shouldn't be done by the application.
+   Usage example:
+
+     uint crc = crc32(0L, Z_NULL, 0);
+
+     while (read_buffer(buffer, length) != EOF) {
+       crc = crc32(crc, buffer, length);
+     }
+     if (crc != original_crc) error();
+*/
+
+
+                        /* various hacks, don't look :) */
+
+/* deflateInit and inflateInit are macros to allow checking the zlib version
+ * and the compiler's view of z_stream:
+ */
+int deflateInit_(z_streamp strm,
+                 int level,
+                 char* versionx,
+                 int stream_size);
+                 
+int inflateInit_(z_streamp strm,
+                 char* versionx,
+                 int stream_size);
+                 
+int deflateInit2_(z_streamp strm,
+                  int level,
+                  int method,
+                  int windowBits,
+                  int memLevel,
+                  int strategy,
+                  char* versionx,
+                  int stream_size);
+                  
+int inflateBackInit_(z_stream* strm,
+                     int windowBits,
+                     ubyte* window,
+                     char* z_version,
+                     int stream_size);
+                     
+int inflateInit2_(z_streamp strm,
+                  int windowBits,
+                  char* versionx,
+                  int stream_size);
+                  
+char* zError(int err);
+int inflateSyncPoint(z_streamp z);
+Culong_t* get_crc_table();
--- a/lphobos/gc/gc.d	Mon Aug 04 19:08:39 2008 +0200
+++ b/lphobos/gc/gc.d	Mon Aug 04 19:28:49 2008 +0200
@@ -1,151 +1,1028 @@
-/**
- * Part of the D programming language runtime library.
- */
-
-/*
- *  Copyright (C) 2004-2007 by Digital Mars, www.digitalmars.com
- *  Written by Walter Bright
- *
- *  This software is provided 'as-is', without any express or implied
- *  warranty. In no event will the authors be held liable for any damages
- *  arising from the use of this software.
- *
- *  Permission is granted to anyone to use this software for any purpose,
- *  including commercial applications, and to alter it and redistribute it
- *  freely, subject to the following restrictions:
- *
- *  o  The origin of this software must not be misrepresented; you must not
- *     claim that you wrote the original software. If you use this software
- *     in a product, an acknowledgment in the product documentation would be
- *     appreciated but is not required.
- *  o  Altered source versions must be plainly marked as such, and must not
- *     be misrepresented as being the original software.
- *  o  This notice may not be removed or altered from any source
- *     distribution.
- */
-
-
-// Storage allocation
-
-module std.gc;
-
-//debug = PRINTF;
-
-public import std.c.stdarg;
-public import std.c.stdlib;
-public import std.c.string;
-public import gcx;
-public import std.outofmemory;
-public import gcstats;
-public import std.thread;
-
-version=GCCLASS;
-
-version (GCCLASS)
-    alias GC gc_t;
-else
-    alias GC* gc_t;
-
-gc_t _gc;
-
-void addRoot(void *p)		      { _gc.addRoot(p); }
-void removeRoot(void *p)	      { _gc.removeRoot(p); }
-void addRange(void *pbot, void *ptop) { _gc.addRange(pbot, ptop); }
-void removeRange(void *pbot)	      { _gc.removeRange(pbot); }
-void fullCollect()		      { _gc.fullCollect(); }
-void fullCollectNoStack()	      { _gc.fullCollectNoStack(); }
-void genCollect()		      { _gc.genCollect(); }
-void minimize()			      { _gc.minimize(); }
-void disable()			      { _gc.disable(); }
-void enable()			      { _gc.enable(); }
-void getStats(out GCStats stats)      { _gc.getStats(stats); }
-void hasPointers(void* p)	      { _gc.hasPointers(p); }
-void hasNoPointers(void* p)	      { _gc.hasNoPointers(p); }
-void setV1_0()			      { _gc.setV1_0(); }
-
-void[] malloc(size_t nbytes)
-{
-    void* p = _gc.malloc(nbytes);
-    return p[0 .. nbytes];
-}
-
-void[] realloc(void* p, size_t nbytes)
-{
-    void* q = _gc.realloc(p, nbytes);
-    return q[0 .. nbytes];
-}
-
-size_t extend(void* p, size_t minbytes, size_t maxbytes)
-{
-    return _gc.extend(p, minbytes, maxbytes);
-}
-
-size_t capacity(void* p)
-{
-    return _gc.capacity(p);
-}
-
-void setTypeInfo(TypeInfo ti, void* p)
-{
-    if (ti.flags() & 1)
-	hasNoPointers(p);
-    else
-	hasPointers(p);
-}
-
-void* getGCHandle()
-{
-    return cast(void*)_gc;
-}
-
-void setGCHandle(void* p)
-{
-    void* oldp = getGCHandle();
-    gc_t g = cast(gc_t)p;
-    if (g.gcversion != gcx.GCVERSION)
-	throw new Error("incompatible gc versions");
-
-    // Add our static data to the new gc
-    GC.scanStaticData(g);
-
-    _gc = g;
-//    return oldp;
-}
-
-void endGCHandle()
-{
-    GC.unscanStaticData(_gc);
-}
-
-extern (C)
-{
-
-void _d_monitorrelease(Object h);
-
-
-void gc_init()
-{
-    version (GCCLASS)
-    {	void* p;
-	ClassInfo ci = GC.classinfo;
-
-	p = std.c.stdlib.malloc(ci.init.length);
-	(cast(byte*)p)[0 .. ci.init.length] = ci.init[];
-	_gc = cast(GC)p;
-    }
-    else
-    {
-	_gc = cast(GC *) std.c.stdlib.calloc(1, GC.sizeof);
-    }
-    _gc.initialize();
-    GC.scanStaticData(_gc);
-    std.thread.Thread.thread_init();
-}
-
-void gc_term()
-{
-    _gc.fullCollectNoStack();
-    _gc.Dtor();
-}
-
-}
+/**
+ * Part of the D programming language runtime library.
+ */
+
+/*
+ *  Copyright (C) 2004-2008 by Digital Mars, www.digitalmars.com
+ *  Written by Walter Bright
+ *
+ *  This software is provided 'as-is', without any express or implied
+ *  warranty. In no event will the authors be held liable for any damages
+ *  arising from the use of this software.
+ *
+ *  Permission is granted to anyone to use this software for any purpose,
+ *  including commercial applications, and to alter it and redistribute it
+ *  freely, subject to the following restrictions:
+ *
+ *  o  The origin of this software must not be misrepresented; you must not
+ *     claim that you wrote the original software. If you use this software
+ *     in a product, an acknowledgment in the product documentation would be
+ *     appreciated but is not required.
+ *  o  Altered source versions must be plainly marked as such, and must not
+ *     be misrepresented as being the original software.
+ *  o  This notice may not be removed or altered from any source
+ *     distribution.
+ */
+
+/* NOTE: This file has been patched from the original DMD distribution to
+   work with the GDC compiler.
+
+   Modified by David Friedman, February 2007
+*/
+
+
+// Storage allocation
+
+module std.gc;
+
+//debug = PRINTF;
+
+public import std.c.stdarg;
+public import std.c.stdlib;
+public import std.c.string;
+public import gcx;
+public import std.outofmemory;
+public import gcstats;
+public import std.thread;
+
+version=GCCLASS;
+
+version (GCCLASS)
+    alias GC gc_t;
+else
+    alias GC* gc_t;
+
+gc_t _gc;
+
+void addRoot(void *p)		      { _gc.addRoot(p); }
+void removeRoot(void *p)	      { _gc.removeRoot(p); }
+void addRange(void *pbot, void *ptop) { _gc.addRange(pbot, ptop); }
+void removeRange(void *pbot)	      { _gc.removeRange(pbot); }
+void fullCollect()		      { _gc.fullCollect(); }
+void fullCollectNoStack()	      { _gc.fullCollectNoStack(); }
+void genCollect()		      { _gc.genCollect(); }
+void minimize()			      { _gc.minimize(); }
+void disable()			      { _gc.disable(); }
+void enable()			      { _gc.enable(); }
+void getStats(out GCStats stats)      { _gc.getStats(stats); }
+void hasPointers(void* p)	      { _gc.hasPointers(p); }
+void hasNoPointers(void* p)	      { _gc.hasNoPointers(p); }
+void setV1_0()			      { _gc.setV1_0(); }
+
+void[] malloc(size_t nbytes)
+{
+    void* p = _gc.malloc(nbytes);
+    return p[0 .. nbytes];
+}
+
+void[] realloc(void* p, size_t nbytes)
+{
+    void* q = _gc.realloc(p, nbytes);
+    return q[0 .. nbytes];
+}
+
+size_t extend(void* p, size_t minbytes, size_t maxbytes)
+{
+    return _gc.extend(p, minbytes, maxbytes);
+}
+
+size_t capacity(void* p)
+{
+    return _gc.capacity(p);
+}
+
+void setTypeInfo(TypeInfo ti, void* p)
+{
+    if (ti.flags() & 1)
+	hasNoPointers(p);
+    else
+	hasPointers(p);
+}
+
+void* getGCHandle()
+{
+    return cast(void*)_gc;
+}
+
+void setGCHandle(void* p)
+{
+    void* oldp = getGCHandle();
+    gc_t g = cast(gc_t)p;
+    if (g.gcversion != gcx.GCVERSION)
+	throw new Error("incompatible gc versions");
+
+    // Add our static data to the new gc
+    GC.scanStaticData(g);
+
+    _gc = g;
+//    return oldp;
+}
+
+void endGCHandle()
+{
+    GC.unscanStaticData(_gc);
+}
+
+extern (C)
+{
+
+void _d_monitorexit(Object h);
+
+
+void gc_init()
+{
+    version (GCCLASS)
+    {	void* p;
+	ClassInfo ci = GC.classinfo;
+
+	p = std.c.stdlib.malloc(ci.init.length);
+	(cast(byte*)p)[0 .. ci.init.length] = ci.init[];
+	_gc = cast(GC)p;
+    }
+    else
+    {
+	_gc = cast(GC *) std.c.stdlib.calloc(1, GC.sizeof);
+    }
+    _gc.initialize();
+    GC.scanStaticData(_gc);
+    std.thread.Thread.thread_init();
+}
+
+void gc_term()
+{
+    _gc.fullCollectNoStack();
+    _gc.Dtor();
+}
+
+Object _d_newclass(ClassInfo ci)
+{
+    void *p;
+
+    debug(PRINTF) printf("_d_newclass(ci = %p, %s)\n", ci, cast(char *)ci.name);
+    if (ci.flags & 1)			// if COM object
+    {
+	p = std.c.stdlib.malloc(ci.init.length);
+	if (!p)
+	    _d_OutOfMemory();
+	debug(PRINTF) printf(" COM object p = %p\n", p);
+    }
+    else
+    {
+	p = _gc.malloc(ci.init.length);
+	debug(PRINTF) printf(" p = %p\n", p);
+	_gc.setFinalizer(p, &new_finalizer);
+	if (ci.flags & 2)
+	    _gc.hasNoPointers(p);
+    }
+
+    debug (PRINTF)
+    {
+	printf("p = %p\n", p);
+	printf("ci = %p, ci.init = %p, len = %d\n", ci, ci.init, ci.init.length);
+	printf("vptr = %p\n", *cast(void **)ci.init);
+	printf("vtbl[0] = %p\n", (*cast(void ***)ci.init)[0]);
+	printf("vtbl[1] = %p\n", (*cast(void ***)ci.init)[1]);
+	printf("init[0] = %x\n", (cast(uint *)ci.init)[0]);
+	printf("init[1] = %x\n", (cast(uint *)ci.init)[1]);
+	printf("init[2] = %x\n", (cast(uint *)ci.init)[2]);
+	printf("init[3] = %x\n", (cast(uint *)ci.init)[3]);
+	printf("init[4] = %x\n", (cast(uint *)ci.init)[4]);
+    }
+
+
+    // Initialize it
+    (cast(byte*)p)[0 .. ci.init.length] = ci.init[];
+
+    //printf("initialization done\n");
+    return cast(Object)p;
+}
+
+extern (D) alias void (*fp_t)(Object);		// generic function pointer
+
+void _d_delinterface(void** p)
+{
+    if (*p)
+    {
+	Interface *pi = **cast(Interface ***)*p;
+	Object o;
+
+	o = cast(Object)(*p - pi.offset);
+	_d_delclass(&o);
+	*p = null;
+    }
+}
+
+void _d_delclass(Object *p)
+{
+    if (*p)
+    {
+	debug (PRINTF) printf("_d_delclass(%p)\n", *p);
+	version(0)
+	{
+	    ClassInfo **pc = cast(ClassInfo **)*p;
+	    if (*pc)
+	    {
+		ClassInfo c = **pc;
+
+		if (c.deallocator)
+		{
+		    _d_callfinalizer(cast(void *)(*p));
+		    fp_t fp = cast(fp_t)c.deallocator;
+		    (*fp)(*p);			// call deallocator
+		    *p = null;
+		    return;
+		}
+	    }
+	}
+	_gc.free(cast(void*)(*p));
+	*p = null;
+    }
+}
+
+/******************************************
+ * Allocate a new array of length elements.
+ * ti is the type of the resulting array, or pointer to element.
+ */
+
+/* For when the array is initialized to 0 */
+void* _d_newarrayT(TypeInfo ti, size_t length)
+{
+    void* result;
+    auto size = ti.next.tsize();		// array element size
+
+    debug(PRINTF) printf("_d_newarrayT(length = x%x, size = %d)\n", length, size);
+    if (length && size)
+    {
+	/*version (D_InlineAsm_X86)
+	{
+	    asm
+	    {
+		mov	EAX,size	;
+		mul	EAX,length	;
+		mov	size,EAX	;
+		jc	Loverflow	;
+	    }
+	}
+	else*/
+	    size *= length;
+	result = cast(byte*) _gc.malloc(size + 1);
+	if (!(ti.next.flags() & 1))
+	    _gc.hasNoPointers(result);
+	memset(result, 0, size);
+    }
+    return result;
+
+Loverflow:
+    _d_OutOfMemory();
+}
+
+/* For when the array has a non-zero initializer.
+ */
+void* _d_newarrayiT(TypeInfo ti, size_t length)
+{
+    void* result;
+    auto size = ti.next.tsize();		// array element size
+
+    debug(PRINTF)
+	 printf("_d_newarrayiT(length = %d, size = %d)\n", length, size);
+    if (length == 0 || size == 0)
+	{ }
+    else
+    {
+	auto initializer = ti.next.init();
+	auto isize = initializer.length;
+	auto q = initializer.ptr;
+	/*version (D_InlineAsm_X86)
+	{
+	    asm
+	    {
+		mov	EAX,size	;
+		mul	EAX,length	;
+		mov	size,EAX	;
+		jc	Loverflow	;
+	    }
+	}
+	else*/
+	    size *= length;
+	auto p = _gc.malloc(size + 1);
+	debug(PRINTF) printf(" p = %p\n", p);
+	if (!(ti.next.flags() & 1))
+	    _gc.hasNoPointers(p);
+	if (isize == 1)
+	    memset(p, *cast(ubyte*)q, size);
+	else if (isize == int.sizeof)
+	{
+	    int init = *cast(int*)q;
+	    size /= int.sizeof;
+	    for (size_t u = 0; u < size; u++)
+	    {
+		(cast(int*)p)[u] = init;
+	    }
+	}
+	else
+	{
+	    for (size_t u = 0; u < size; u += isize)
+	    {
+		memcpy(p + u, q, isize);
+	    }
+	}
+	result = cast(byte*) p
;
+    }
+    return result;
+
+Loverflow:
+    _d_OutOfMemory();
+}
+
+void[] _d_newarraymTp(TypeInfo ti, int ndims, size_t* pdim)
+{
+    void[] result = void;
+
+    //debug(PRINTF)
+	//printf("_d_newarraymT(ndims = %d)\n", ndims);
+    if (ndims == 0)
+	result = null;
+    else
+    {
+
+	void[] foo(TypeInfo ti, size_t* pdim, int ndims)
+	{
+	    size_t dim = *pdim;
+	    void[] p;
+
+	    //printf("foo(ti = %p, ti.next = %p, dim = %d, ndims = %d\n", ti, ti.next, dim, ndims);
+	    if (ndims == 1)
+	    {
+		auto r = _d_newarrayT(ti, dim);
+		p = *cast(void[]*)(&r);
+	    }
+	    else
+	    {
+		p = _gc.malloc(dim * (void[]).sizeof + 1)[0 .. dim];
+		for (int i = 0; i < dim; i++)
+		{
+		    (cast(void[]*)p.ptr)[i] = foo(ti.next, pdim + 1, ndims - 1);
+		}
+	    }
+	    return p;
+	}
+
+	result = foo(ti, pdim, ndims);
+	//printf("result = %llx\n", result);
+
+	version (none)
+	{
+	    for (int i = 0; i < ndims; i++)
+	    {
+		printf("index %d: %d\n", i, pdim[i]);
+	    }
+	}
+    }
+    return result;
+}
+
+void[] _d_newarraymiTp(TypeInfo ti, int ndims, size_t* pdim)
+{
+    void[] result = void;
+
+    //debug(PRINTF)
+	//printf("_d_newarraymi(size = %d, ndims = %d)\n", size, ndims);
+    if (ndims == 0)
+	result = null;
+    else
+    {
+
+	void[] foo(TypeInfo ti, size_t* pdim, int ndims)
+	{
+	    size_t dim = *pdim;
+	    void[] p;
+
+	    if (ndims == 1)
+	    {
+		auto r = _d_newarrayiT(ti, dim);
+		p = *cast(void[]*)(&r);
+	    }
+	    else
+	    {
+		p = _gc.malloc(dim * (void[]).sizeof + 1)[0 .. dim];
+		for (int i = 0; i < dim; i++)
+		{
+		    (cast(void[]*)p.ptr)[i] = foo(ti.next, pdim + 1, ndims - 1);
+		}
+	    }
+	    return p;
+	}
+
+	result = foo(ti, pdim, ndims);
+	//printf("result = %llx\n", result);
+
+	version (none)
+	{
+	    for (int i = 0; i < ndims; i++)
+	    {
+		printf("index %d: %d\n", i, pdim[i]);
+		printf("init = %d\n", *cast(int*)pinit);
+	    }
+	}
+    }
+    return result;
+}
+
+struct Array
+{
+    size_t length;
+    byte *data;
+};
+
+// Perhaps we should get a a size argument like _d_new(), so we
+// can zero out the array?
+
+void _d_delarray(size_t plength, void* pdata)
+{
+    assert(!plength || pdata);
+    if (pdata) _gc.free(pdata);
+}
+
+
+void _d_delmemory(void* *p)
+{
+    if (*p)
+    {
+	_gc.free(*p);
+	*p = null;
+    }
+}
+
+
+}
+
+void new_finalizer(void *p, bool dummy)
+{
+    //printf("new_finalizer(p = %p)\n", p);
+    _d_callfinalizer(p);
+}
+
+extern (C)
+void _d_callinterfacefinalizer(void *p)
+{
+    //printf("_d_callinterfacefinalizer(p = %p)\n", p);
+    if (p)
+    {
+	Interface *pi = **cast(Interface ***)p;
+	Object o = cast(Object)(p - pi.offset);
+	_d_callfinalizer(cast(void*)o);
+    }
+}
+
+extern (C)
+void _d_callfinalizer(void *p)
+{
+    //printf("_d_callfinalizer(p = %p)\n", p);
+    if (p)	// not necessary if called from gc
+    {
+	ClassInfo **pc = cast(ClassInfo **)p;
+	if (*pc)
+	{
+	    ClassInfo c = **pc;
+
+	    try
+	    {
+		do
+		{
+		    if (c.destructor)
+		    {
+			fp_t fp = cast(fp_t)c.destructor;
+			(*fp)(cast(Object)p);		// call destructor
+		    }
+		    c = c.base;
+		} while (c);
+		if ((cast(void**)p)[1])	// if monitor is not null
+		    _d_monitorexit(cast(Object)p);
+	    }
+	    finally
+	    {
+		*pc = null;			// zero vptr
+	    }
+	}
+    }
+}
+
+/+ ------------------------------------------------ +/
+
+
+/******************************
+ * Resize dynamic arrays with 0 initializers.
+ */
+
+extern (C)
+byte* _d_arraysetlengthT(TypeInfo ti, size_t newlength, size_t plength, byte* pdata)
+in
+{
+    assert(ti);
+}
+body
+{
+    byte* newdata;
+    size_t sizeelem = ti.next.tsize();
+
+    debug(PRINTF)
+    {
+	printf("_d_arraysetlengthT(p = %p, sizeelem = %d, newlength = %d)\n", p, sizeelem, newlength);
+	if (p)
+	    printf("\tpdata = %p, plength = %d\n", pdata, plength);
+    }
+
+    if (newlength)
+    {
+	version (GNU)
+	{
+	    // required to output the label;
+	    static char x = 0;
+	    if (x)
+		goto Loverflow;
+	}
+
+	version (D_InlineAsm_X86)
+	{
+	    size_t newsize = void;
+
+	    asm
+	    {
+		mov	EAX,newlength	;
+		mul	EAX,sizeelem	;
+		mov	newsize,EAX	;
+		jc	Loverflow	;
+	    }
+	}
+	else
+	{
+	    size_t newsize = sizeelem * newlength;
+
+	    if (newsize / newlength != sizeelem)
+		goto Loverflow;
+	}
+	//printf("newsize = %x, newlength = %x\n", newsize, newlength);
+
+	if (pdata)
+	{
+	    newdata = pdata;
+	    if (newlength > plength)
+	    {
+		size_t size = plength * sizeelem;
+		size_t cap = _gc.capacity(pdata);
+
+		if (cap <= newsize)
+		{
+		    if (cap >= 4096)
+		    {	// Try to extend in-place
+			auto u = _gc.extend(pdata, (newsize + 1) - cap, (newsize + 1) - cap);
+			if (u)
+			{
+			    goto L1;
+			}
+		    }
+		    newdata = cast(byte *)_gc.malloc(newsize + 1);
+		    newdata[0 .. size] = pdata[0 .. size];
+		    if (!(ti.next.flags() & 1))
+			_gc.hasNoPointers(newdata);
+		}
+	     L1:
+		newdata[size .. newsize] = 0;
+	    }
+	}
+	else
+	{
+	    newdata = cast(byte *)_gc.calloc(newsize + 1, 1);
+	    if (!(ti.next.flags() & 1))
+		_gc.hasNoPointers(newdata);
+	}
+    }
+    else
+    {
+	newdata = pdata;
+    }
+
+    pdata = newdata;
+    plength = newlength;
+    return newdata;
+
+Loverflow:
+    _d_OutOfMemory();
+}
+
+/**
+ * Resize arrays for non-zero initializers.
+ *	p		pointer to array lvalue to be updated
+ *	newlength	new .length property of array
+ *	sizeelem	size of each element of array
+ *	initsize	size of initializer
+ *	...		initializer
+ */
+extern (C)
+byte* _d_arraysetlengthiT(TypeInfo ti, size_t newlength, size_t plength, byte* pdata)
+in
+{
+    assert(!plength || pdata);
+}
+body
+{
+    byte* newdata;
+    size_t sizeelem = ti.next.tsize();
+    void[] initializer = ti.next.init();
+    size_t initsize = initializer.length;
+
+    assert(sizeelem);
+    assert(initsize);
+    assert(initsize <= sizeelem);
+    assert((sizeelem / initsize) * initsize == sizeelem);
+
+    debug(PRINTF)
+    {
+	printf("_d_arraysetlengthiT(p = %p, sizeelem = %d, newlength = %d, initsize = %d)\n", p, sizeelem, newlength, initsize);
+	if (p)
+	    printf("\tpdata = %p, plength = %d\n", pdata, plength);
+    }
+
+    if (newlength)
+    {
+	version (GNU)
+	{
+	    // required to output the label;
+	    static char x = 0;
+	    if (x)
+		goto Loverflow;
+	}
+
+	version (D_InlineAsm_X86)
+	{
+	    size_t newsize = void;
+
+	    asm
+	    {
+		mov	EAX,newlength	;
+		mul	EAX,sizeelem	;
+		mov	newsize,EAX	;
+		jc	Loverflow	;
+	    }
+	}
+	else
+	{
+	    size_t newsize = sizeelem * newlength;
+
+	    if (newsize / newlength != sizeelem)
+		goto Loverflow;
+	}
+	//printf("newsize = %x, newlength = %x\n", newsize, newlength);
+
+	size_t size = plength * sizeelem;
+	if (pdata)
+	{
+	    newdata = pdata;
+	    if (newlength > plength)
+	    {
+		size_t cap = _gc.capacity(pdata);
+
+		if (cap <= newsize)
+		{
+		    if (cap >= 4096)
+		    {	// Try to extend in-place
+			auto u = _gc.extend(pdata, (newsize + 1) - cap, (newsize + 1) - cap);
+			if (u)
+			{
+			    goto L1;
+			}
+		    }
+		    newdata = cast(byte *)_gc.malloc(newsize + 1);
+		    newdata[0 .. size] = pdata[0 .. size];
+		L1: ;
+		}
+	    }
+	}
+	else
+	{
+	    newdata = cast(byte *)_gc.malloc(newsize + 1);
+	    if (!(ti.next.flags() & 1))
+		_gc.hasNoPointers(newdata);
+	}
+
+	auto q = initializer.ptr;	// pointer to initializer
+
+	if (newsize > size)
+	{
+	    if (initsize == 1)
+	    {
+		//printf("newdata = %p, size = %d, newsize = %d, *q = %d\n", newdata, size, newsize, *cast(byte*)q);
+		newdata[size .. newsize] = *(cast(byte*)q);
+	    }
+	    else
+	    {
+		for (size_t u = size; u < newsize; u += initsize)
+		{
+		    memcpy(newdata + u, q, initsize);
+		}
+	    }
+	}
+    }
+    else
+    {
+	newdata = pdata;
+    }
+
+    pdata = newdata;
+    plength = newlength;
+    return newdata;
+
+Loverflow:
+    _d_OutOfMemory();
+}
+
+/****************************************
+ * Append y[] to array x[].
+ * size is size of each array element.
+ */
+
+extern (C)
+Array _d_arrayappendT(TypeInfo ti, Array *px, byte[] y)
+{
+    auto sizeelem = ti.next.tsize();		// array element size
+    auto cap = _gc.capacity(px.data);
+    auto length = px.length;
+    auto newlength = length + y.length;
+    auto newsize = newlength * sizeelem;
+    if (newsize > cap)
+    {   byte* newdata;
+
+	if (cap >= 4096)
+	{   // Try to extend in-place
+	    auto u = _gc.extend(px.data, (newsize + 1) - cap, (newsize + 1) - cap);
+	    if (u)
+	    {
+		goto L1;
+	    }
+	}
+
+	newdata = cast(byte *)_gc.malloc(newCapacity(newlength, sizeelem) + 1);
+	if (!(ti.next.flags() & 1))
+	    _gc.hasNoPointers(newdata);
+	memcpy(newdata, px.data, length * sizeelem);
+	px.data = newdata;
+    }
+  L1:
+    px.length = newlength;
+    memcpy(px.data + length * sizeelem, y.ptr, y.length * sizeelem);
+    return *px;
+}
+
+size_t newCapacity(size_t newlength, size_t size)
+{
+    version(none)
+    {
+	size_t newcap = newlength * size;
+    }
+    else
+    {
+	/*
+	 * Better version by Dave Fladebo:
+	 * This uses an inverse logorithmic algorithm to pre-allocate a bit more
+	 * space for larger arrays.
+	 * - Arrays smaller than 4096 bytes are left as-is, so for the most
+	 * common cases, memory allocation is 1 to 1. The small overhead added
+	 * doesn't effect small array perf. (it's virtually the same as
+	 * current).
+	 * - Larger arrays have some space pre-allocated.
+	 * - As the arrays grow, the relative pre-allocated space shrinks.
+	 * - The logorithmic algorithm allocates relatively more space for
+	 * mid-size arrays, making it very fast for medium arrays (for
+	 * mid-to-large arrays, this turns out to be quite a bit faster than the
+	 * equivalent realloc() code in C, on Linux at least. Small arrays are
+	 * just as fast as GCC).
+	 * - Perhaps most importantly, overall memory usage and stress on the GC
+	 * is decreased significantly for demanding environments.
+	 */
+	size_t newcap = newlength * size;
+	size_t newext = 0;
+
+	if (newcap > 4096)
+	{
+	    //double mult2 = 1.0 + (size / log10(pow(newcap * 2.0,2.0)));
+
+	    // Redo above line using only integer math
+
+	    static int log2plus1(size_t c)
+	    {   int i;
+
+		if (c == 0)
+		    i = -1;
+		else
+		    for (i = 1; c >>= 1; i++)
+			{   }
+		return i;
+	    }
+
+	    /* The following setting for mult sets how much bigger
+	     * the new size will be over what is actually needed.
+	     * 100 means the same size, more means proportionally more.
+	     * More means faster but more memory consumption.
+	     */
+	    //long mult = 100 + (1000L * size) / (6 * log2plus1(newcap));
+	    long mult = 100 + (1000L * size) / log2plus1(newcap);
+
+	    // testing shows 1.02 for large arrays is about the point of diminishing return
+	    if (mult < 102)
+		mult = 102;
+	    newext = cast(size_t)((newcap * mult) / 100);
+	    newext -= newext % size;
+	    //printf("mult: %2.2f, mult2: %2.2f, alloc: %2.2f\n",mult/100.0,mult2,newext / cast(double)size);
+	}
+	newcap = newext > newcap ? newext : newcap;
+	//printf("newcap = %d, newlength = %d, size = %d\n", newcap, newlength, size);
+    }
+    return newcap;
+}
+
+extern (C)
+byte[] _d_arrayappendcTp(TypeInfo ti, inout byte[] x, byte *argp)
+{
+    auto sizeelem = ti.next.tsize();		// array element size
+    auto cap = _gc.capacity(x.ptr);
+    auto length = x.length;
+    auto newlength = length + 1;
+    auto newsize = newlength * sizeelem;
+
+    assert(cap == 0 || length * sizeelem <= cap);
+
+    //printf("_d_arrayappendc(sizeelem = %d, ptr = %p, length = %d, cap = %d)\n", sizeelem, x.ptr, x.length, cap);
+
+    if (newsize >= cap)
+    {   byte* newdata;
+
+	if (cap >= 4096)
+	{   // Try to extend in-place
+	    auto u = _gc.extend(x.ptr, (newsize + 1) - cap, (newsize + 1) - cap);
+	    if (u)
+	    {
+		goto L1;
+	    }
+	}
+
+	//printf("_d_arrayappendc(sizeelem = %d, newlength = %d, cap = %d)\n", sizeelem, newlength, cap);
+	cap = newCapacity(newlength, sizeelem);
+	assert(cap >= newlength * sizeelem);
+	newdata = cast(byte *)_gc.malloc(cap + 1);
+	if (!(ti.next.flags() & 1))
+	    _gc.hasNoPointers(newdata);
+	memcpy(newdata, x.ptr, length * sizeelem);
+	(cast(void **)(&x))[1] = newdata;
+    }
+  L1:
+
+    *cast(size_t *)&x = newlength;
+    x.ptr[length * sizeelem .. newsize] = argp[0 .. sizeelem];
+    assert((cast(size_t)x.ptr & 15) == 0);
+    assert(_gc.capacity(x.ptr) >= x.length * sizeelem);
+    return x;
+}
+
+extern (C)
+byte[] _d_arraycatT(TypeInfo ti, byte[] x, byte[] y)
+out (result)
+{
+    auto sizeelem = ti.next.tsize();		// array element size
+    //printf("_d_arraycatT(%d,%p ~ %d,%p sizeelem = %d => %d,%p)\n", x.length, x.ptr, y.length, y.ptr, sizeelem, result.length, result.ptr);
+    assert(result.length == x.length + y.length);
+    for (size_t i = 0; i < x.length * sizeelem; i++)
+	assert((cast(byte*)result)[i] == (cast(byte*)x)[i]);
+    for (size_t i = 0; i < y.length * sizeelem; i++)
+	assert((cast(byte*)result)[x.length * sizeelem + i] == (cast(byte*)y)[i]);
+
+    size_t cap = _gc.capacity(result.ptr);
+    assert(!cap || cap > result.length * sizeelem);
+}
+body
+{
+    version (none)
+    {
+	/* Cannot use this optimization because:
+	 *  char[] a, b;
+	 *  char c = 'a';
+	 *	b = a ~ c;
+	 *	c = 'b';
+	 * will change the contents of b.
+	 */
+	if (!y.length)
+	    return x;
+	if (!x.length)
+	    return y;
+    }
+
+    //printf("_d_arraycatT(%d,%p ~ %d,%p)\n", x.length, x.ptr, y.length, y.ptr);
+    auto sizeelem = ti.next.tsize();		// array element size
+    //printf("_d_arraycatT(%d,%p ~ %d,%p sizeelem = %d)\n", x.length, x.ptr, y.length, y.ptr, sizeelem);
+    size_t xlen = x.length * sizeelem;
+    size_t ylen = y.length * sizeelem;
+    size_t len = xlen + ylen;
+    if (!len)
+	return null;
+
+    byte* p = cast(byte*)_gc.malloc(len + 1);
+    if (!(ti.next.flags() & 1))
+	_gc.hasNoPointers(p);
+    memcpy(p, x.ptr, xlen);
+    memcpy(p + xlen, y.ptr, ylen);
+    p[len] = 0;
+
+    return p[0 .. x.length + y.length];
+}
+
+
+extern (C)
+byte[] _d_arraycatnT(TypeInfo ti, uint n, ...)
+{   void* a;
+    size_t length;
+    byte[]* p;
+    uint i;
+    byte[] b;
+    va_list va;
+    auto sizeelem = ti.next.tsize();		// array element size
+
+    va_start!(typeof(n))(va, n);
+
+    for (i = 0; i < n; i++)
+    {
+	b = va_arg!(typeof(b))(va);
+	length += b.length;
+    }
+    if (!length)
+	return null;
+
+    a = _gc.malloc(length * sizeelem);
+    if (!(ti.next.flags() & 1))
+	_gc.hasNoPointers(a);
+    va_start!(typeof(n))(va, n);
+
+    uint j = 0;
+    for (i = 0; i < n; i++)
+    {
+	b = va_arg!(typeof(b))(va);
+	if (b.length)
+	{
+	    memcpy(a + j, b.ptr, b.length * sizeelem);
+	    j += b.length * sizeelem;
+	}
+    }
+
+    return (cast(byte*)a)[0..length];
+}
+
+version (GNU) { } else
+extern (C)
+void* _d_arrayliteralT(TypeInfo ti, size_t length, ...)
+{
+    auto sizeelem = ti.next.tsize();		// array element size
+    void* result;
+
+    //printf("_d_arrayliteralT(sizeelem = %d, length = %d)\n", sizeelem, length);
+    if (length == 0 || sizeelem == 0)
+	result = null;
+    else
+    {
+	result = _gc.malloc(length * sizeelem);
+	if (!(ti.next.flags() & 1))
+	{
+	    _gc.hasNoPointers(result);
+	}
+
+	va_list q;
+	va_start!(size_t)(q, length);
+
+	size_t stacksize = (sizeelem + int.sizeof - 1) & ~(int.sizeof - 1);
+
+	if (stacksize == sizeelem)
+	{
+	    memcpy(result, q, length * sizeelem);
+	}
+	else
+	{
+	    for (size_t i = 0; i < length; i++)
+	    {
+		memcpy(result + i * sizeelem, q, sizeelem);
+		q += stacksize;
+	    }
+	}
+
+	va_end(q);
+    }
+    return result;
+}
+
+/**********************************
+ * Support for array.dup property.
+ */
+
+/*struct Array2
+{
+    size_t length;
+    void* ptr;
+}*/
+
+extern(C) void* _d_allocmemoryT(size_t foo) { return malloc(foo).ptr; }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lphobos/gc/gc_guess_stack.d	Mon Aug 04 19:28:49 2008 +0200
@@ -0,0 +1,3 @@
+module gcc.gc_guess_stack;
+void * stackOriginGuess;
+
--- a/lphobos/gc/gcbits.d	Mon Aug 04 19:08:39 2008 +0200
+++ b/lphobos/gc/gcbits.d	Mon Aug 04 19:28:49 2008 +0200
@@ -4,13 +4,24 @@
 // www.digitalmars.com
 // Written by Walter Bright
 
+/* NOTE: This file has been patched from the original DMD distribution to
+   work with the GDC compiler.
+
+   Modified by David Friedman, September 2004
+*/
+
 import std.c.string;
 import std.c.stdlib;
 import std.outofmemory;
 import std.intrinsic;
 
 //version = Asm86;
-version = bitops;
+version (GNU) {
+    // bitop intrinsics not implemented yet
+} else {
+    version = bitops;
+}
+
 
 struct GCBits
 {
--- a/lphobos/gc/gcx.d	Mon Aug 04 19:08:39 2008 +0200
+++ b/lphobos/gc/gcx.d	Mon Aug 04 19:28:49 2008 +0200
@@ -1,14 +1,17 @@
-/*
- *  Copyright (C) 2004 by Digital Mars, www.digitalmars.com
- *  Written by Walter Bright
+/**
+ * This module contains the garbage collector implementation.
  *
+ * Copyright: Copyright (C) 2001-2007 Digital Mars, www.digitalmars.com.
+ *            All rights reserved.
+ * License:
  *  This software is provided 'as-is', without any express or implied
  *  warranty. In no event will the authors be held liable for any damages
  *  arising from the use of this software.
  *
  *  Permission is granted to anyone to use this software for any purpose,
  *  including commercial applications, and to alter it and redistribute it
- *  freely, subject to the following restrictions:
+ *  freely, in both source and binary form, subject to the following
+ *  restrictions:
  *
  *  o  The origin of this software must not be misrepresented; you must not
  *     claim that you wrote the original software. If you use this software
@@ -18,226 +21,2661 @@
  *     be misrepresented as being the original software.
  *  o  This notice may not be removed or altered from any source
  *     distribution.
+ * Authors:   Walter Bright, David Friedman, Sean Kelly
  */
 
-// D Garbage Collector stub to prevent linking in gc
-
-/*
- * Modified for use as the preliminary GC for LLVMDC (LLVM D Compiler)
- * by Tomas Lindquist Olsen, Dec 2007
- */
+/* NOTE: This file has been patched from the original DMD distribution to
+   work with the GDC compiler.
+
+   Modified by David Friedman, July 2006
+*/
 
 module gcx;
 
-debug=PRINTF;
+// D Garbage Collector implementation
+
+/************** Debugging ***************************/
+
+//debug = PRINTF;			// turn on printf's
+//debug = COLLECT_PRINTF;		// turn on printf's
+//debug = THREADINVARIANT;	// check thread integrity
+//debug = LOGGING;		// log allocations / frees
+//debug = MEMSTOMP;		// stomp on memory
+//debug = SENTINEL;		// add underrun/overrrun protection
+//debug = PTRCHECK;		// more pointer checking
+//debug = PTRCHECK2;		// thorough but slow pointer checking
+
+/*************** Configuration *********************/
+
+version = STACKGROWSDOWN;	// growing the stack means subtracting from the stack pointer
+				// (use for Intel X86 CPUs)
+				// else growing the stack means adding to the stack pointer
+version = MULTI_THREADED;	// produce multithreaded version
 
 /***************************************************/
 
+private import gcbits;
+private import gcstats;
+
+private import cstdlib = std.c.stdlib : calloc, free, malloc, realloc;
+private import cstring = std.c.string : memcpy, memmove, memset;
+
+debug private import std.c.stdio;
+
+import std.outofmemory;
+import std.gc;
+
+version (GNU)
+{
+    private import gcc.builtins;
+}
 
 version (Win32)
 {
     import win32;
+    import std.c.windows.windows;
 }
-
-version (linux)
+else version (GNU)
+{
+    private import gcgcc;
+}
+else version (linux)
 {
     import gclinux;
 }
 
-import gcstats;
-import stdc = std.c.stdlib;
-
-
-//alias GC* gc_t;
+/*version (BigEndian)
+  private import std.intrinsic;*/
+
+
+
+version (MULTI_THREADED)
+{
+    import std.thread;
+}
+
+
+private void onOutOfMemoryError()
+{
+    _d_OutOfMemory();
+}
+
+private void* rt_stackBottom()
+{
+    version (Win32)
+    {
+        return win32.os_query_stackBottom();
+    }
+    else version (GNU)
+    {
+	return gcgcc.os_query_stackBottom();
+    }
+    else version (linux)
+    {
+        return gclinux.os_query_stackBottom();
+    }
+}
+
+private bool thread_needLock()
+{
+    return std.thread.Thread.nthreads != 1;
+}
+
+
 alias GC gc_t;
 
-//struct GCStats { }
+version (X86) version (D_InlineAsm) { version = Asm86; }
+
+
+/* ======================= Leak Detector =========================== */
+
+
+debug (LOGGING)
+{
+    struct Log
+    {
+	void*  p;
+	size_t size;
+	uint   line;
+	char*  file;
+	void*  parent;
+
+	void print()
+	{
+	    printf("    p = %x, size = %d, parent = %x ", p, size, parent);
+	    if (file)
+	    {
+		printf("%s(%u)", file, line);
+	    }
+	    printf("\n");
+	}
+    }
+
+
+    struct LogArray
+    {
+	size_t dim;
+	size_t allocdim;
+	Log *data;
+
+	void Dtor()
+	{
+	    if (data)
+		cstdlib.free(data);
+	    data = null;
+	}
+
+	void reserve(size_t nentries)
+	{
+	    assert(dim <= allocdim);
+	    if (allocdim - dim < nentries)
+	    {
+		allocdim = (dim + nentries) * 2;
+		assert(dim + nentries <= allocdim);
+		if (!data)
+		{
+		    data = cast(Log *)cstdlib.malloc(allocdim * Log.sizeof);
+		    if (!data && allocdim)
+			onOutOfMemoryError();
+		}
+		else
+		{   Log *newdata;
+
+		    newdata = cast(Log *)cstdlib.malloc(allocdim * Log.sizeof);
+		    if (!newdata && allocdim)
+			onOutOfMemoryError();
+		    cstring.memcpy(newdata, data, dim * Log.sizeof);
+		    cstdlib.free(data);
+		    data = newdata;
+		}
+	    }
+	}
+
+
+	void push(Log log)
+	{
+	    reserve(1);
+	    data[dim++] = log;
+	}
+
+	void remove(size_t i)
+	{
+	    cstring.memmove(data + i, data + i + 1, (dim - i) * Log.sizeof);
+	    dim--;
+	}
+
+
+	size_t find(void *p)
+	{
+	    for (size_t i = 0; i < dim; i++)
+	    {
+		if (data[i].p == p)
+		    return i;
+	    }
+	    return ~0u;		// not found
+	}
+
+
+	void copy(LogArray *from)
+	{
+	    reserve(from.dim - dim);
+	    assert(from.dim <= allocdim);
+	    cstring.memcpy(data, from.data, from.dim * Log.sizeof);
+	    dim = from.dim;
+	}
+    }
+}
+
 
 /* ============================ GC =============================== */
 
 
-//alias int size_t;
 alias void (*GC_FINALIZER)(void *p, bool dummy);
 
-const uint GCVERSION = 1;   // increment every time we change interface
-                // to GC.
+class GCLock { }		// just a dummy so we can get a global lock
+
+
+const uint GCVERSION = 1;	// increment every time we change interface
+				// to GC.
 
 class GC
 {
+    // For passing to debug code
+    static size_t line;
+    static char*  file;
+
     uint gcversion = GCVERSION;
 
-    void *gcx;          // implementation
+    Gcx *gcx;			// implementation
+    static ClassInfo gcLock;	// global lock
+
 
     void initialize()
     {
-    debug(PRINTF) printf("GC initialize()\n");
+	gcLock = GCLock.classinfo;
+	gcx = cast(Gcx *)cstdlib.calloc(1, Gcx.sizeof);
+	if (!gcx)
+	    onOutOfMemoryError();
+        printf("GCX set to %p\n", gcx);
+	gcx.initialize();
+        setStackBottom(rt_stackBottom());
     }
 
 
     void Dtor()
     {
-    debug(PRINTF) printf("GC Dtor()\n");
+	version (linux)
+	{
+	    //debug(PRINTF) printf("Thread %x ", pthread_self());
+	    //debug(PRINTF) printf("GC.Dtor()\n");
+	}
+
+	if (gcx)
+	{
+	    gcx.Dtor();
+	    cstdlib.free(gcx);
+	    gcx = null;
+	}
     }
 
-    invariant
+
+    invariant()
     {
-    debug(PRINTF) printf("GC invariant()\n");
+	if (gcx)
+        {
+	    gcx.thread_Invariant();
+        }
     }
 
+
+    /**
+     *
+     */
+    void enable()
+    {
+        if (!thread_needLock())
+        {
+	    assert(gcx.disabled > 0);
+	    gcx.disabled--;
+        }
+        else synchronized (gcLock)
+	{
+	    assert(gcx.disabled > 0);
+	    gcx.disabled--;
+	}
+    }
+
+
+    /**
+     *
+     */
+    void disable()
+    {
+        if (!thread_needLock())
+        {
+	    gcx.disabled++;
+        }
+        else synchronized (gcLock)
+	{
+	    gcx.disabled++;
+	}
+    }
+
+
+    /**
+     *
+     */
     void *malloc(size_t size)
     {
-    debug(PRINTF) printf("GC malloc()\n");
-    return malloc(size);
+        if (!size)
+        {
+            return null;
+        }
+
+	if (!thread_needLock())
+	{
+	    return mallocNoSync(size);
+	}
+	else synchronized (gcLock)
+	{
+	    return mallocNoSync(size);
+	}
     }
 
-    void *mallocNoSync(size_t size)
+
+    //
+    //
+    //
+    private void *mallocNoSync(size_t size)
     {
-    debug(PRINTF) printf("GC mallocNoSync()\n");
-    return malloc(size);
+        assert(size != 0);
+
+        void *p = null;
+	Bins bin;
+
+	//debug(PRINTF) printf("GC::malloc(size = %d, gcx = %p)\n", size, gcx);
+	assert(gcx);
+	//debug(PRINTF) printf("gcx.self = %x, pthread_self() = %x\n", gcx.self, pthread_self());
+        size += SENTINEL_EXTRA;
+
+        // Compute size bin
+        // Cache previous binsize lookup - Dave Fladebo.
+        static size_t lastsize = -1;
+        static Bins lastbin;
+        if (size == lastsize)
+            bin = lastbin;
+        else
+        {
+            bin = gcx.findBin(size);
+            lastsize = size;
+            lastbin = bin;
+        }
+
+        if (bin < B_PAGE)
+        {
+            p = gcx.bucket[bin];
+            if (p == null)
+            {
+                if (!gcx.allocPage(bin) && !gcx.disabled)	// try to find a new page
+                {
+                    if (!thread_needLock())
+                    {
+                        /* Then we haven't locked it yet. Be sure
+                         * and lock for a collection, since a finalizer
+                         * may start a new thread.
+                         */
+                        synchronized (gcLock)
+                        {
+                            gcx.fullcollectshell();
+                        }
+                    }
+                    else if (!gcx.fullcollectshell())	// collect to find a new page
+                    {
+                        //gcx.newPool(1);
+                    }
+                }
+                if (!gcx.bucket[bin] && !gcx.allocPage(bin))
+                {   int result;
+
+                    gcx.newPool(1);		// allocate new pool to find a new page
+                    result = gcx.allocPage(bin);
+                    if (!result)
+                        return null;
+                }
+                p = gcx.bucket[bin];
+            }
+
+            // Return next item from free list
+            gcx.bucket[bin] = (cast(List *)p).next;
+            cstring.memset(p + size, 0, binsize[bin] - size);
+            //debug(PRINTF) printf("\tmalloc => %x\n", p);
+            debug (MEMSTOMP) cstring.memset(p, 0xF0, size);
+        }
+        else
+        {
+            p = gcx.bigAlloc(size);
+            if (!p)
+                return null;
+        }
+        size -= SENTINEL_EXTRA;
+        p = sentinel_add(p);
+        sentinel_init(p, size);
+        gcx.log_malloc(p, size);
+	return p;
     }
 
 
+    /**
+     *
+     */
     void *calloc(size_t size, size_t n)
     {
-    debug(PRINTF) printf("GC calloc()\n");
-    return calloc(n, size);
+        size_t len = size * n;
+
+        if (!len)
+        {
+            return null;
+        }
+
+        if (!thread_needLock())
+        {
+            return callocNoSync(len);
+        }
+        else synchronized (gcLock)
+        {
+            return callocNoSync(len);
+        }
     }
 
 
+    //
+    //
+    //
+    private void *callocNoSync(size_t size)
+    {
+        assert(size != 0);
+
+	void *p = mallocNoSync(size);
+	if (p)
+	{   //debug(PRINTF) printf("calloc: %x len %d\n", p, len);
+	    cstring.memset(p, 0, size);
+	}
+	return p;
+    }
+
+
+    /**
+     *
+     */
     void *realloc(void *p, size_t size)
     {
-    debug(PRINTF) printf("GC realloc()\n");
-    return realloc(p, size);
+        if (!thread_needLock())
+        {
+            return reallocNoSync(p, size);
+        }
+        else synchronized (gcLock)
+        {
+            return reallocNoSync(p, size);
+        }
     }
 
 
+    //
+    //
+    //
+    private void *reallocNoSync(void *p, size_t size)
+    {
+	gcx.p_cache = null;
+	if (!size)
+	{   if (p)
+	    {   freeNoSync(p);
+		p = null;
+	    }
+	}
+	else if (!p)
+	{
+	    p = mallocNoSync(size);
+	}
+	else
+	{   void *p2;
+	    size_t psize;
+
+	    //debug(PRINTF) printf("GC::realloc(p = %x, size = %u)\n", p, size);
+	    version (SENTINEL)
+	    {
+		sentinel_Invariant(p);
+		psize = *sentinel_size(p);
+		if (psize != size)
+		{
+		    p2 = mallocNoSync(size);
+		    if (psize < size)
+			size = psize;
+		    //debug(PRINTF) printf("\tcopying %d bytes\n",size);
+		    cstring.memcpy(p2, p, size);
+		    p = p2;
+		}
+	    }
+	    else
+	    {
+		psize = gcx.findSize(p);	// find allocated size
+		if (psize >= PAGESIZE && size >= PAGESIZE)
+		{
+		    auto psz = psize / PAGESIZE;
+		    auto newsz = (size + PAGESIZE - 1) / PAGESIZE;
+		    if (newsz == psz)
+			return p;
+
+		    auto pool = gcx.findPool(p);
+		    auto pagenum = (p - pool.baseAddr) / PAGESIZE;
+
+		    if (newsz < psz)
+		    {	// Shrink in place
+			synchronized (gcLock)
+			{
+			    debug (MEMSTOMP) cstring.memset(p + size, 0xF2, psize - size);
+			    pool.freePages(pagenum + newsz, psz - newsz);
+			}
+			return p;
+		    }
+		    else if (pagenum + newsz <= pool.npages)
+		    {
+			// Attempt to expand in place
+			synchronized (gcLock)
+			{
+			    for (size_t i = pagenum + psz; 1;)
+			    {
+				if (i == pagenum + newsz)
+				{
+				    debug (MEMSTOMP) cstring.memset(p + psize, 0xF0, size - psize);
+				    cstring.memset(&pool.pagetable[pagenum + psz], B_PAGEPLUS, newsz - psz);
+				    return p;
+				}
+				if (i == pool.ncommitted)
+				{
+				    auto u = pool.extendPages(pagenum + newsz - pool.ncommitted);
+				    if (u == ~0u)
+					break;
+				    i = pagenum + newsz;
+				    continue;
+				}
+				if (pool.pagetable[i] != B_FREE)
+				    break;
+				i++;
+			    }
+			}
+		    }
+		}
+		if (psize < size ||		// if new size is bigger
+		    psize > size * 2)		// or less than half
+		{
+		    p2 = mallocNoSync(size);
+		    if (psize < size)
+			size = psize;
+		    //debug(PRINTF) printf("\tcopying %d bytes\n",size);
+		    cstring.memcpy(p2, p, size);
+		    p = p2;
+		}
+	    }
+	}
+	return p;
+    }
+
+
+    /**
+     * Attempt to in-place enlarge the memory block pointed to by p by at least
+     * minbytes beyond its current capacity, up to a maximum of maxsize.  This
+     * does not attempt to move the memory block (like realloc() does).
+     *
+     * Returns:
+     *	0 if could not extend p,
+     *	total size of entire memory block if successful.
+     */
+    size_t extend(void* p, size_t minsize, size_t maxsize)
+    {
+        if (!thread_needLock())
+        {
+            return extendNoSync(p, minsize, maxsize);
+        }
+        else synchronized (gcLock)
+        {
+            return extendNoSync(p, minsize, maxsize);
+        }
+    }
+
+
+    //
+    //
+    //
+    private size_t extendNoSync(void* p, size_t minsize, size_t maxsize)
+    in
+    {
+        assert( minsize <= maxsize );
+    }
+    body
+    {
+	//debug(PRINTF) printf("GC::extend(p = %x, minsize = %u, maxsize = %u)\n", p, minsize, maxsize);
+	version (SENTINEL)
+	{
+	    return 0;
+	}
+	auto psize = gcx.findSize(p);	// find allocated size
+	if (psize < PAGESIZE)
+	    return 0;			// cannot extend buckets
+
+	auto psz = psize / PAGESIZE;
+	auto minsz = (minsize + PAGESIZE - 1) / PAGESIZE;
+	auto maxsz = (maxsize + PAGESIZE - 1) / PAGESIZE;
+
+	auto pool = gcx.findPool(p);
+	auto pagenum = (p - pool.baseAddr) / PAGESIZE;
+
+        size_t sz;
+        for (sz = 0; sz < maxsz; sz++)
+        {
+            auto i = pagenum + psz + sz;
+            if (i == pool.ncommitted)
+                break;
+            if (pool.pagetable[i] != B_FREE)
+            {   if (sz < minsz)
+                    return 0;
+                break;
+            }
+        }
+        if (sz >= minsz)
+        {
+        }
+        else if (pagenum + psz + sz == pool.ncommitted)
+        {
+            auto u = pool.extendPages(minsz - sz);
+            if (u == ~0u)
+                return 0;
+            sz = minsz;
+        }
+        else
+            return 0;
+        debug (MEMSTOMP) cstring.memset(p + psize, 0xF0, (psz + sz) * PAGESIZE - psize);
+        cstring.memset(pool.pagetable + pagenum + psz, B_PAGEPLUS, sz);
+        gcx.p_cache = null;
+        gcx.size_cache = 0;
+        return (psz + sz) * PAGESIZE;
+    }
+
+
+    /**
+     *
+     */
     void free(void *p)
     {
-    debug(PRINTF) printf("GC free()\n");
-    stdc.free(p);
+	if (!p)
+        {
+	    return;
+        }
+
+        if (!thread_needLock())
+        {
+            return freeNoSync(p);
+        }
+        else synchronized (gcLock)
+        {
+            return freeNoSync(p);
+        }
     }
 
+
+    //
+    //
+    //
+    private void freeNoSync(void *p)
+    {
+        assert (p);
+
+	Pool *pool;
+	uint pagenum;
+	Bins bin;
+	uint biti;
+
+	// Find which page it is in
+	pool = gcx.findPool(p);
+	if (!pool)				// if not one of ours
+	    return;				// ignore
+	sentinel_Invariant(p);
+	p = sentinel_sub(p);
+	pagenum = (p - pool.baseAddr) / PAGESIZE;
+	biti = cast(uint)(p - pool.baseAddr) / 16;
+	pool.noscan.clear(biti);
+	if (pool.finals.nbits && pool.finals.testClear(biti))
+	    gcx.rt_finalize(sentinel_add(p), false);
+
+	gcx.p_cache = null;
+	bin = cast(Bins)pool.pagetable[pagenum];
+	if (bin == B_PAGE)		// if large alloc
+	{   int npages;
+	    uint n;
+
+	    // Free pages
+	    npages = 1;
+	    n = pagenum;
+	    while (++n < pool.ncommitted && pool.pagetable[n] == B_PAGEPLUS)
+		npages++;
+	    debug (MEMSTOMP) cstring.memset(p, 0xF2, npages * PAGESIZE);
+	    pool.freePages(pagenum, npages);
+	}
+	else
+	{   // Add to free list
+	    List *list = cast(List *)p;
+
+	    debug (MEMSTOMP) cstring.memset(p, 0xF2, binsize[bin]);
+
+	    list.next = gcx.bucket[bin];
+	    gcx.bucket[bin] = list;
+	}
+	gcx.log_free(sentinel_add(p));
+    }
+
+
+    /**
+     * Determine the allocated size of pointer p.  If p is an interior pointer
+     * or not a gc allocated pointer, return 0.
+     */
     size_t capacity(void *p)
     {
-    debug(PRINTF) printf("GC capacity()\n");
-    return 0;
+        if (!p)
+        {
+            return 0;
+        }
+
+        if (!thread_needLock())
+        {
+            return sizeOfNoSync(p);
+        }
+        else synchronized (gcLock)
+        {
+            return sizeOfNoSync(p);
+        }
     }
 
+
+    //
+    //
+    //
+    private size_t sizeOfNoSync(void *p)
+    {
+        assert (p);
+
+	version (SENTINEL)
+	{
+	    p = sentinel_sub(p);
+	    size_t size = gcx.findSize(p);
+
+	    // Check for interior pointer
+	    // This depends on:
+	    // 1) size is a power of 2 for less than PAGESIZE values
+	    // 2) base of memory pool is aligned on PAGESIZE boundary
+	    if (cast(size_t)p & (size - 1) & (PAGESIZE - 1))
+		size = 0;
+	    return size ? size - SENTINAL_EXTRA : 0;
+	}
+	else
+	{
+	    if (p !is null && p == gcx.p_cache)
+		return gcx.size_cache;
+
+	    size_t size = gcx.findSize(p);
+
+	    // Check for interior pointer
+	    // This depends on:
+	    // 1) size is a power of 2 for less than PAGESIZE values
+	    // 2) base of memory pool is aligned on PAGESIZE boundary
+	    if (cast(size_t)p & (size - 1) & (PAGESIZE - 1))
+		size = 0;
+	    else
+	    {
+		gcx.p_cache = p;
+		gcx.size_cache = size;
+	    }
+
+	    return size;
+	}
+    }
+
+
+    /**
+     * Verify that pointer p:
+     *	1) belongs to this memory pool
+     *	2) points to the start of an allocated piece of memory
+     *	3) is not on a free list
+     */
     void check(void *p)
     {
-    debug(PRINTF) printf("GC check()\n");
+        if (!p)
+        {
+            return;
+        }
+
+        if (!thread_needLock())
+        {
+            checkNoSync(p);
+        }
+        else synchronized (gcLock)
+        {
+            checkNoSync(p);
+        }
     }
 
-
-    void setStackBottom(void *p)
+    //
+    //
+    //
+    private void checkNoSync(void *p)
     {
-    debug(PRINTF) printf("GC setStackBottom()\n");
+        assert(p);
+
+        sentinel_Invariant(p);
+        debug (PTRCHECK)
+        {
+            Pool* pool;
+            uint pagenum;
+            Bins bin;
+            size_t size;
+
+            p = sentinel_sub(p);
+            pool = gcx.findPool(p);
+            assert(pool);
+            pagenum = (p - pool.baseAddr) / PAGESIZE;
+            bin = cast(Bins)pool.pagetable[pagenum];
+            assert(bin <= B_PAGE);
+            size = binsize[bin];
+            assert((cast(size_t)p & (size - 1)) == 0);
+
+            debug (PTRCHECK2)
+            {
+                if (bin < B_PAGE)
+                {
+                    // Check that p is not on a free list
+                    List *list;
+
+                    for (list = gcx.bucket[bin]; list; list = list.next)
+                    {
+                        assert(cast(void *)list != p);
+                    }
+                }
+            }
+        }
     }
 
+
+    //
+    //
+    //
+    private void setStackBottom(void *p)
+    {
+	version (STACKGROWSDOWN)
+	{
+	    //p = (void *)((uint *)p + 4);
+	    if (p > gcx.stackBottom)
+	    {
+		//debug(PRINTF) printf("setStackBottom(%x)\n", p);
+		gcx.stackBottom = p;
+	    }
+	}
+	else
+	{
+	    //p = (void *)((uint *)p - 4);
+	    if (p < gcx.stackBottom)
+	    {
+		//debug(PRINTF) printf("setStackBottom(%x)\n", p);
+		gcx.stackBottom = cast(char *)p;
+	    }
+	}
+    }
+
+
     static void scanStaticData(gc_t g)
     {
+	void *pbot;
+	void *ptop;
+	size_t nbytes;
+
+	//debug(PRINTF) printf("+GC.scanStaticData()\n");
+	os_query_staticdataseg(&pbot, &nbytes);
+	ptop = pbot + nbytes;
+	version (GNU) {
+	    if (pbot) {
+		g.addRange(pbot, ptop);
+	    }
+	} else {
+	    g.addRange(pbot, ptop);
+	}
+	//debug(PRINTF) printf("-GC.scanStaticData()\n");
+    }
+
+    static void unscanStaticData(gc_t g)
+    {
+	void *pbot;
+	size_t nbytes;
+
+	os_query_staticdataseg(&pbot, &nbytes);
+	version (GNU) {
+	    if (pbot) {
+		g.removeRange(pbot);
+	    }
+	} else {
+	    g.removeRange(pbot);
+	}
+    }
+
+
+    /**
+     * add p to list of roots
+     */
+    void addRoot(void *p)
+    {
+        if (!p)
+        {
+            return;
+        }
+
+        if (!thread_needLock())
+        {
+	    gcx.addRoot(p);
+        }
+        else synchronized (gcLock)
+	{
+	    gcx.addRoot(p);
+	}
+    }
+
+
+    /**
+     * remove p from list of roots
+     */
+    void removeRoot(void *p)
+    {
+        if (!p)
+        {
+            return;
+        }
+
+        if (!thread_needLock())
+        {
+	    gcx.removeRoot(p);
+        }
+        else synchronized (gcLock)
+	{
+	    gcx.removeRoot(p);
+	}
+    }
+
+
+    /**
+     * add range to scan for roots
+     */
+    void addRange(void *pbot, void *ptop)
+    {
+        if (!pbot || !ptop)
+        {
+            return;
+        }
+
+	//debug(PRINTF) printf("+GC.addRange(pbot = x%x, ptop = x%x)\n", pbot, ptop);
+        if (!thread_needLock())
+        {
+	    gcx.addRange(pbot, ptop);
+        }
+        else synchronized (gcLock)
+	{
+	    gcx.addRange(pbot, ptop);
+	}
+	//debug(PRINTF) printf("-GC.addRange()\n");
+    }
+
+
+    /**
+     * remove range
+     */
+    void removeRange(void *p)
+    {
+        if (!p)
+        {
+            return;
+        }
+
+        if (!thread_needLock())
+        {
+	    gcx.removeRange(p);
+        }
+        else synchronized (gcLock)
+	{
+	    gcx.removeRange(p);
+	}
+    }
+
+
+    /**
+     * do full garbage collection
+     */
+    void fullCollect()
+    {
+	debug(PRINTF) printf("GC.fullCollect()\n");
+
+        if (!thread_needLock())
+        {
+	    gcx.fullcollectshell();
+        }
+        else synchronized (gcLock)
+	{
+	    gcx.fullcollectshell();
+	}
+
+	version (none)
+	{
+	    GCStats stats;
+
+	    getStats(stats);
+	    debug(PRINTF) printf("poolsize = %x, usedsize = %x, freelistsize = %x\n",
+		    stats.poolsize, stats.usedsize, stats.freelistsize);
+	}
+
+	gcx.log_collect();
+    }
+
+
+    /**
+     * do full garbage collection ignoring roots
+     */
+    void fullCollectNoStack()
+    {
+        if (!thread_needLock())
+        {
+            gcx.noStack++;
+            gcx.fullcollectshell();
+            gcx.noStack--;
+        }
+        else synchronized (gcLock)
+        {
+            gcx.noStack++;
+            gcx.fullcollectshell();
+            gcx.noStack--;
+        }
+    }
+
+
+    /**
+     * do generational garbage collection
+     */
+    void genCollect()
+    {
+	synchronized (gcLock)
+	{
+	    gcx.fullcollectshell();
+	}
+    }
+
+    void minimize()	// minimize physical memory usage
+    {
+	// Not implemented, ignore
+    }
+
+    void setFinalizer(void *p, GC_FINALIZER pFn)
+    {
+	synchronized (gcLock)
+	{
+	    gcx.finalizer = pFn;
+	    gcx.doFinalize(p);
+	}
+    }
+
+
+    void hasPointers(void *p)
+    {
+	synchronized (gcLock)
+	{
+	    gcx.HasPointers(p);
+	}
+    }
+
+
+    void hasNoPointers(void *p)
+    {
+	if (!gcx.conservative)
+	{   synchronized (gcLock)
+	    {
+		gcx.HasNoPointers(p);
+	    }
+	}
+    }
+
+
+    void setV1_0()
+    {
+	gcx.conservative = 1;
+    }
+
+    /**
+     * Retrieve statistics about garbage collection.
+     * Useful for debugging and tuning.
+     */
+    void getStats(out GCStats stats)
+    {
+        if (!thread_needLock())
+        {
+            getStatsNoSync(stats);
+        }
+        else synchronized (gcLock)
+        {
+            getStatsNoSync(stats);
+        }
+    }
+
+    //
+    //
+    //
+    private void getStatsNoSync(out GCStats stats)
+    {
+	size_t psize = 0;
+	size_t usize = 0;
+	size_t flsize = 0;
+
+	size_t n;
+	size_t bsize = 0;
+
+	//debug(PRINTF) printf("getStats()\n");
+	cstring.memset(&stats, 0, GCStats.sizeof);
+
+        for (n = 0; n < gcx.npools; n++)
+        {   Pool *pool = gcx.pooltable[n];
+
+            psize += pool.ncommitted * PAGESIZE;
+            for (uint j = 0; j < pool.ncommitted; j++)
+            {
+                Bins bin = cast(Bins)pool.pagetable[j];
+                if (bin == B_FREE)
+                    stats.freeblocks++;
+                else if (bin == B_PAGE)
+                    stats.pageblocks++;
+                else if (bin < B_PAGE)
+                    bsize += PAGESIZE;
+            }
+        }
+
+        for (n = 0; n < B_PAGE; n++)
+        {
+            //debug(PRINTF) printf("bin %d\n", n);
+            for (List *list = gcx.bucket[n]; list; list = list.next)
+            {
+                //debug(PRINTF) printf("\tlist %x\n", list);
+                flsize += binsize[n];
+            }
+        }
+
+	usize = bsize - flsize;
+
+	stats.poolsize = psize;
+	stats.usedsize = bsize - flsize;
+	stats.freelistsize = flsize;
+    }
+}
+
+
+/* ============================ Gcx =============================== */
+
+enum
+{   PAGESIZE =	  4096,
+    COMMITSIZE = (4096*16),
+    POOLSIZE =   (4096*256),
+}
+
+
+enum
+{
+    B_16,
+    B_32,
+    B_64,
+    B_128,
+    B_256,
+    B_512,
+    B_1024,
+    B_2048,
+    B_PAGE,		// start of large alloc
+    B_PAGEPLUS,		// continuation of large alloc
+    B_FREE,		// free page
+    B_UNCOMMITTED,	// memory not committed for this page
+    B_MAX
+}
+
+
+alias ubyte Bins;
+
+
+struct List
+{
+    List *next;
+}
+
+
+struct Range
+{
     void *pbot;
     void *ptop;
-    uint nbytes;
-
-    debug(PRINTF) printf("GC scanStaticData()\n");
-    //debug(PRINTF) printf("+GC.scanStaticData()\n");
-    os_query_staticdataseg(&pbot, &nbytes);
-    ptop = pbot + nbytes;
-    g.addRange(pbot, ptop);
-    //debug(PRINTF) printf("-GC.scanStaticData()\n");
+}
+
+
+const uint binsize[B_MAX] = [ 16,32,64,128,256,512,1024,2048,4096 ];
+const uint notbinsize[B_MAX] = [ ~(16u-1),~(32u-1),~(64u-1),~(128u-1),~(256u-1),
+				~(512u-1),~(1024u-1),~(2048u-1),~(4096u-1) ];
+
+/* ============================ Gcx =============================== */
+
+
+struct Gcx
+{
+    debug (THREADINVARIANT)
+    {
+	pthread_t self;
+	void thread_Invariant()
+	{
+	    if (self != pthread_self())
+		printf("thread_Invariant(): gcx = %x, self = %x, pthread_self() = %x\n", this, self, pthread_self());
+	    assert(self == pthread_self());
+	}
     }
-
-    static void unscanStaticData(gc_t g)
+    else
     {
-    void *pbot;
-    uint nbytes;
-
-    debug(PRINTF) printf("GC unscanStaticData()\n");
-    os_query_staticdataseg(&pbot, &nbytes);
-    g.removeRange(pbot);
+	void thread_Invariant() { }
     }
 
-
-    void addRoot(void *p)   // add p to list of roots
+    void *p_cache;
+    size_t size_cache;
+
+    size_t nroots;
+    size_t rootdim;
+    void **roots;
+
+    size_t nranges;
+    size_t rangedim;
+    Range *ranges;
+
+    uint conservative;	// !=0 means conservative behavior
+    uint noStack;	// !=0 means don't scan stack
+    uint log;		// turn on logging
+    uint anychanges;
+    void *stackBottom;
+    uint inited;
+    int disabled;	// turn off collections if >0
+
+    byte *minAddr;	// min(baseAddr)
+    byte *maxAddr;	// max(topAddr)
+
+    uint npools;
+    Pool **pooltable;
+
+    List *bucket[B_MAX];	// free list for each size
+
+    GC_FINALIZER finalizer;	// finalizer function (one per GC)
+
+    private void rt_finalize( void* p, bool dummy )
     {
-    debug(PRINTF) printf("GC addRoot()\n");
+        if (finalizer)
+            (*finalizer)(p, dummy);
     }
 
-    void removeRoot(void *p)    // remove p from list of roots
+
+    void initialize()
+    {   int dummy;
+
+	(cast(byte *)this)[0 .. Gcx.sizeof] = 0;
+	stackBottom = cast(char *)&dummy;
+	log_init();
+	debug (THREADINVARIANT)
+	    self = pthread_self();
+	//printf("gcx = %p, self = %x\n", this, self);
+	inited = 1;
+    }
+
+
+    void Dtor()
     {
-    debug(PRINTF) printf("GC removeRoot()\n");
+	inited = 0;
+
+	for (uint i = 0; i < npools; i++)
+	{   Pool *pool = pooltable[i];
+
+	    pool.Dtor();
+	    cstdlib.free(pool);
+	}
+	if (pooltable)
+	    cstdlib.free(pooltable);
+
+	if (roots)
+	    cstdlib.free(roots);
+
+	if (ranges)
+	    cstdlib.free(ranges);
     }
 
-    void addRange(void *pbot, void *ptop)   // add range to scan for roots
+
+    void Invariant() { }
+
+
+    invariant()
     {
-    debug(PRINTF) printf("GC addRange()\n");
+	if (inited)
+	{
+	//printf("Gcx.invariant(): this = %p\n", this);
+	    uint i;
+
+	    // Assure we're called on the right thread
+	    debug (THREADINVARIANT) assert(self == pthread_self());
+
+	    for (i = 0; i < npools; i++)
+	    {   Pool *pool = pooltable[i];
+
+		pool.Invariant();
+		if (i == 0)
+		{
+		    assert(minAddr == pool.baseAddr);
+		}
+		if (i + 1 < npools)
+		{
+		    assert(pool.opCmp(pooltable[i + 1]) < 0);
+		}
+		else if (i + 1 == npools)
+		{
+		    assert(maxAddr == pool.topAddr);
+		}
+	    }
+
+	    if (roots)
+	    {
+		assert(rootdim != 0);
+		assert(nroots <= rootdim);
+	    }
+
+	    if (ranges)
+	    {
+		assert(rangedim != 0);
+		assert(nranges <= rangedim);
+
+		for (i = 0; i < nranges; i++)
+		{
+		    assert(ranges[i].pbot);
+		    assert(ranges[i].ptop);
+		    assert(ranges[i].pbot <= ranges[i].ptop);
+		}
+	    }
+
+	    for (i = 0; i < B_PAGE; i++)
+	    {
+		for (List *list = bucket[i]; list; list = list.next)
+		{
+		}
+	    }
+	}
     }
 
-    void removeRange(void *pbot)        // remove range
+
+    /**
+     *
+     */
+
+    void addRoot(void *p)
     {
-    debug(PRINTF) printf("GC removeRange()\n");
+	if (nroots == rootdim)
+	{
+	    size_t newdim = rootdim * 2 + 16;
+	    void** newroots;
+
+	    newroots = cast(void **)cstdlib.malloc(newdim * newroots[0].sizeof);
+	    if (!newroots)
+		onOutOfMemoryError();
+	    if (roots)
+	    {   cstring.memcpy(newroots, roots, nroots * newroots[0].sizeof);
+		cstdlib.free(roots);
+	    }
+	    roots = newroots;
+	    rootdim = newdim;
+	}
+	roots[nroots] = p;
+	nroots++;
     }
 
-    void fullCollect()      // do full garbage collection
+
+    /**
+     *
+     */
+    void removeRoot(void *p)
     {
-    debug(PRINTF) printf("GC fullCollect()\n");
+	for (size_t i = nroots; i--;)
+	{
+	    if (roots[i] == p)
+	    {
+		nroots--;
+		cstring.memmove(roots + i, roots + i + 1, (nroots - i) * roots[0].sizeof);
+		return;
+	    }
+	}
+	assert(0);
     }
 
-    void fullCollectNoStack()       // do full garbage collection
+
+    /**
+     *
+     */
+    void addRange(void *pbot, void *ptop)
     {
-    debug(PRINTF) printf("GC fullCollectNoStack()\n");
+	debug(THREADINVARIANT) { debug(PRINTF) printf("Thread %x ", pthread_self()); }
+	debug(PRINTF) printf("%x.Gcx::addRange(%x, %x), nranges = %d\n", this, pbot, ptop, nranges);
+	if (nranges == rangedim)
+	{
+	    size_t newdim = rangedim * 2 + 16;
+	    Range *newranges;
+
+	    newranges = cast(Range *)cstdlib.malloc(newdim * newranges[0].sizeof);
+	    if (!newranges)
+		onOutOfMemoryError();
+	    if (ranges)
+	    {   cstring.memcpy(newranges, ranges, nranges * newranges[0].sizeof);
+		cstdlib.free(ranges);
+	    }
+	    ranges = newranges;
+	    rangedim = newdim;
+	}
+	ranges[nranges].pbot = pbot;
+	ranges[nranges].ptop = ptop;
+	nranges++;
     }
 
-    void genCollect()   // do generational garbage collection
+
+    /**
+     *
+     */
+    void removeRange(void *pbot)
     {
-    debug(PRINTF) printf("GC genCollect()\n");
+	debug(THREADINVARIANT) { debug(PRINTF) printf("Thread %x ", pthread_self()); }
+	debug(PRINTF) printf("%x.Gcx.removeRange(%x), nranges = %d\n", this, pbot, nranges);
+	for (size_t i = nranges; i--;)
+	{
+	    if (ranges[i].pbot == pbot)
+	    {
+		nranges--;
+		cstring.memmove(ranges + i, ranges + i + 1, (nranges - i) * ranges[0].sizeof);
+		return;
+	    }
+	}
+	debug(PRINTF) printf("Wrong thread\n");
+
+	// This is a fatal error, but ignore it.
+	// The problem is that we can get a Close() call on a thread
+	// other than the one the range was allocated on.
+	//assert(zero);
     }
 
-    void minimize() // minimize physical memory usage
+
+    /**
+     * Find Pool that pointer is in.
+     * Return null if not in a Pool.
+     * Assume pooltable[] is sorted.
+     */
+    Pool *findPool(void *p)
     {
-    debug(PRINTF) printf("GC minimize()\n");
+	if (p >= minAddr && p < maxAddr)
+	{
+	    if (npools == 1)
+	    {
+		return pooltable[0];
+	    }
+
+	    for (uint i = 0; i < npools; i++)
+	    {   Pool *pool;
+
+		pool = pooltable[i];
+		if (p < pool.topAddr)
+		{   if (pool.baseAddr <= p)
+			return pool;
+		    break;
+		}
+	    }
+	}
+	return null;
     }
 
-    void setFinalizer(void *p, GC_FINALIZER pFn)
+
+    /**
+     * Find size of pointer p.
+     * Returns 0 if not a gc'd pointer
+     */
+    size_t findSize(void *p)
     {
-    debug(PRINTF) printf("GC setFinalizer()\n");
+	Pool *pool;
+	size_t size = 0;
+
+	pool = findPool(p);
+	if (pool)
+	{
+	    uint pagenum;
+	    Bins bin;
+
+	    pagenum = (cast(uint)(p - pool.baseAddr)) / PAGESIZE;
+	    bin = cast(Bins)pool.pagetable[pagenum];
+	    size = binsize[bin];
+	    if (bin == B_PAGE)
+	    {   uint npages = pool.ncommitted;
+		ubyte* pt;
+		uint i;
+
+		pt = &pool.pagetable[0];
+		for (i = pagenum + 1; i < npages; i++)
+		{
+		    if (pt[i] != B_PAGEPLUS)
+			break;
+		}
+		size = (i - pagenum) * PAGESIZE;
+	    }
+	}
+	return size;
     }
 
-    void enable()
+
+    /**
+     * Compute bin for size.
+     */
+    static Bins findBin(size_t size)
+    {   Bins bin;
+
+	if (size <= 256)
+	{
+	    if (size <= 64)
+	    {
+		if (size <= 16)
+		    bin = B_16;
+		else if (size <= 32)
+		    bin = B_32;
+		else
+		    bin = B_64;
+	    }
+	    else
+	    {
+		if (size <= 128)
+		    bin = B_128;
+		else
+		    bin = B_256;
+	    }
+	}
+	else
+	{
+	    if (size <= 1024)
+	    {
+		if (size <= 512)
+		    bin = B_512;
+		else
+		    bin = B_1024;
+	    }
+	    else
+	    {
+		if (size <= 2048)
+		    bin = B_2048;
+		else
+		    bin = B_PAGE;
+	    }
+	}
+	return bin;
+    }
+
+
+    /**
+     * Allocate a chunk of memory that is larger than a page.
+     * Return null if out of memory.
+     */
+    void *bigAlloc(size_t size)
     {
-    debug(PRINTF) printf("GC enable()\n");
+	Pool *pool;
+	uint npages;
+	uint n;
+	uint pn;
+	uint freedpages;
+	void *p;
+	int state;
+
+	npages = (size + PAGESIZE - 1) / PAGESIZE;
+
+	for (state = 0; ; )
+	{
+	    // This code could use some refinement when repeatedly
+	    // allocating very large arrays.
+
+	    for (n = 0; n < npools; n++)
+	    {
+		pool = pooltable[n];
+		pn = pool.allocPages(npages);
+		if (pn != ~0u)
+		    goto L1;
+	    }
+
+	    // Failed
+	    switch (state)
+	    {
+		case 0:
+		    if (disabled)
+		    {	state = 1;
+			continue;
+		    }
+		    // Try collecting
+		    freedpages = fullcollectshell();
+		    if (freedpages >= npools * ((POOLSIZE / PAGESIZE) / 4))
+		    {   state = 1;
+			continue;
+		    }
+		    // Allocate new pool
+		    pool = newPool(npages);
+		    if (!pool)
+		    {   state = 2;
+			continue;
+		    }
+		    pn = pool.allocPages(npages);
+		    assert(pn != ~0u);
+		    goto L1;
+
+		case 1:
+		    // Allocate new pool
+		    pool = newPool(npages);
+		    if (!pool)
+			goto Lnomemory;
+		    pn = pool.allocPages(npages);
+		    assert(pn != ~0u);
+		    goto L1;
+
+		case 2:
+		    goto Lnomemory;
+	    }
+	}
+
+      L1:
+	pool.pagetable[pn] = B_PAGE;
+	if (npages > 1)
+	    cstring.memset(&pool.pagetable[pn + 1], B_PAGEPLUS, npages - 1);
+	p = pool.baseAddr + pn * PAGESIZE;
+	cstring.memset(cast(char *)p + size, 0, npages * PAGESIZE - size);
+	debug (MEMSTOMP) cstring.memset(p, 0xF1, size);
+	//debug(PRINTF) printf("\tp = %x\n", p);
+	return p;
+
+      Lnomemory:
+	onOutOfMemoryError();
+	return null;
     }
 
-    void disable()
+
+    /**
+     * Allocate a new pool with at least npages in it.
+     * Sort it into pooltable[].
+     * Return null if failed.
+     */
+    Pool *newPool(uint npages)
     {
-    debug(PRINTF) printf("GC disable()\n");
+	Pool *pool;
+	Pool **newpooltable;
+	uint newnpools;
+	uint i;
+
+	//debug(PRINTF) printf("************Gcx::newPool(npages = %d)****************\n", npages);
+
+	// Round up to COMMITSIZE pages
+	npages = (npages + (COMMITSIZE/PAGESIZE) - 1) & ~(COMMITSIZE/PAGESIZE - 1);
+
+	// Minimum of POOLSIZE
+	if (npages < POOLSIZE/PAGESIZE)
+	    npages = POOLSIZE/PAGESIZE;
+	else if (npages > POOLSIZE/PAGESIZE)
+	{   // Give us 150% of requested size, so there's room to extend
+	    auto n = npages + (npages >> 1);
+	    if (n < size_t.max/PAGESIZE)
+		npages = n;
+	}
+
+	// Allocate successively larger pools up to 8 megs
+	if (npools)
+	{   uint n;
+
+	    n = npools;
+	    if (n > 8)
+		n = 8;			// cap pool size at 8 megs
+	    n *= (POOLSIZE / PAGESIZE);
+	    if (npages < n)
+		npages = n;
+	}
+
+	pool = cast(Pool *)cstdlib.calloc(1, Pool.sizeof);
+	if (pool)
+	{
+	    pool.initialize(npages);
+	    if (!pool.baseAddr)
+		goto Lerr;
+
+	    newnpools = npools + 1;
+	    newpooltable = cast(Pool **)cstdlib.realloc(pooltable, newnpools * (Pool *).sizeof);
+	    if (!newpooltable)
+		goto Lerr;
+
+	    // Sort pool into newpooltable[]
+	    for (i = 0; i < npools; i++)
+	    {
+		if (pool.opCmp(newpooltable[i]) < 0)
+		     break;
+	    }
+	    cstring.memmove(newpooltable + i + 1, newpooltable + i, (npools - i) * (Pool *).sizeof);
+	    newpooltable[i] = pool;
+
+	    pooltable = newpooltable;
+	    npools = newnpools;
+
+	    minAddr = pooltable[0].baseAddr;
+	    maxAddr = pooltable[npools - 1].topAddr;
+	}
+	return pool;
+
+      Lerr:
+	pool.Dtor();
+	cstdlib.free(pool);
+	return null;
     }
 
-    void getStats(out GCStats stats)
+
+    /**
+     * Allocate a page of bin's.
+     * Returns:
+     *	0	failed
+     */
+    int allocPage(Bins bin)
     {
-    debug(PRINTF) printf("GC getStats()\n");
+	Pool *pool;
+	uint n;
+	uint pn;
+	byte *p;
+	byte *ptop;
+
+	//debug(PRINTF) printf("Gcx::allocPage(bin = %d)\n", bin);
+	for (n = 0; n < npools; n++)
+	{
+	    pool = pooltable[n];
+	    pn = pool.allocPages(1);
+	    if (pn != ~0u)
+		goto L1;
+	}
+	return 0;		// failed
+
+      L1:
+	pool.pagetable[pn] = cast(ubyte)bin;
+
+	// Convert page to free list
+	size_t size = binsize[bin];
+	List **b = &bucket[bin];
+
+	p = pool.baseAddr + pn * PAGESIZE;
+	ptop = p + PAGESIZE;
+	for (; p < ptop; p += size)
+	{
+	    (cast(List *)p).next = *b;
+	    *b = cast(List *)p;
+	}
+	return 1;
     }
 
-    void hasPointers(void* p)
+
+    /**
+     * Search a range of memory values and mark any pointers into the GC pool.
+     */
+    void mark(void *pbot, void *ptop)
     {
-    debug(PRINTF) printf("GC hasPointers()\n");
+	void **p1 = cast(void **)pbot;
+	void **p2 = cast(void **)ptop;
+	uint changes = 0;
+
+        //printf("marking range: %p -> %p\n", pbot, ptop);
+	for (; p1 < p2; p1++)
+	{
+	    Pool *pool;
+	    byte *p = cast(byte *)(*p1);
+
+	    //if (log) debug(PRINTF) printf("\tmark %x\n", p);
+	    if (p >= minAddr)
+	    {
+		pool = findPool(p);
+		if (pool)
+		{
+		    size_t offset = cast(size_t)(p - pool.baseAddr);
+		    uint biti;
+		    uint pn = offset / PAGESIZE;
+		    Bins bin = cast(Bins)pool.pagetable[pn];
+
+		    //debug(PRINTF) printf("\t\tfound pool %x, base=%x, pn = %d, bin = %d, biti = x%x\n", pool, pool.baseAddr, pn, bin, biti);
+
+		    // Adjust bit to be at start of allocated memory block
+		    if (bin <= B_PAGE)
+		    {
+			biti = (offset & notbinsize[bin]) >> 4;
+			//debug(PRINTF) printf("\t\tbiti = x%x\n", biti);
+		    }
+		    else if (bin == B_PAGEPLUS)
+		    {
+			do
+			{   --pn;
+			} while (cast(Bins)pool.pagetable[pn] == B_PAGEPLUS);
+			biti = pn * (PAGESIZE / 16);
+		    }
+		    else
+		    {
+			// Don't mark bits in B_FREE or B_UNCOMMITTED pages
+			continue;
+		    }
+
+		    //debug(PRINTF) printf("\t\tmark(x%x) = %d\n", biti, pool.mark.test(biti));
+		    if (!pool.mark.test(biti))
+		    {
+			//if (log) debug(PRINTF) printf("\t\tmarking %x\n", p);
+			pool.mark.set(biti);
+			if (!pool.noscan.test(biti))
+			{
+                            pool.scan.set(biti);
+			    changes = 1;
+			}
+			log_parent(sentinel_add(pool.baseAddr + biti * 16), sentinel_add(pbot));
+		    }
+		}
+	    }
+	}
+	anychanges |= changes;
     }
 
-    void hasNoPointers(void* p)
+
+    /**
+     * Return number of full pages free'd.
+     */
+    size_t fullcollectshell()
     {
-    debug(PRINTF) printf("GC hasNoPointers()\n");
+	// The purpose of the 'shell' is to ensure all the registers
+	// get put on the stack so they'll be scanned
+	void *sp;
+	size_t result;
+	version (GNU)
+	{
+	    __builtin_unwind_init();
+	    sp = & sp;
+	}
+	else
+	{
+	    /*asm
+	    {
+		pushad		;
+		mov	sp[EBP],ESP	;
+	    }*/
+	}
+	result = fullcollect(sp);
+	version (GNU)
+	{
+	    // nothing to do
+	}
+	else
+	{
+	    /*asm
+	    {
+		popad		;
+	    }*/
+	}
+	return result;
     }
 
-    void setV1_0()
+
+    /**
+     *
+     */
+    size_t fullcollect(void *stackTop)
     {
-    debug(PRINTF) printf("GC setV1_0()\n");
-    assert(0);
+	uint n;
+	Pool *pool;
+
+	debug(COLLECT_PRINTF) printf("Gcx.fullcollect()\n");
+
+	Thread.pauseAll();
+
+	p_cache = null;
+	size_cache = 0;
+
+	anychanges = 0;
+	for (n = 0; n < npools; n++)
+	{
+	    pool = pooltable[n];
+	    pool.mark.zero();
+	    pool.scan.zero();
+	    pool.freebits.zero();
+	}
+
+	// Mark each free entry, so it doesn't get scanned
+	for (n = 0; n < B_PAGE; n++)
+	{
+	    for (List *list = bucket[n]; list; list = list.next)
+	    {
+		pool = findPool(list);
+		assert(pool);
+		pool.freebits.set(cast(uint)(cast(byte *)list - pool.baseAddr) / 16);
+	    }
+	}
+
+	for (n = 0; n < npools; n++)
+	{
+	    pool = pooltable[n];
+	    pool.mark.copy(&pool.freebits);
+	}
+
+	version (MULTI_THREADED)
+	{
+	    // Scan stacks and registers for each paused thread
+	    Thread[] threads = Thread.getAll();
+	    //thread_id id = cast(thread_id) GetCurrentThread();
+	    for (n = 0; n < threads.length; n++)
+	    {   Thread t = threads[n];
+
+		if (t && t.getState() == Thread.TS.RUNNING)
+		{
+		    if (noStack && threads.length == 1)
+			break;
+
+		    version (Win32)
+		    {
+			CONTEXT context;
+
+			context.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL;
+			if (!GetThreadContext(t.hdl, &context))
+			{
+			    assert(0);
+			}
+			debug (PRINTF) printf("mt scan stack bot = %x, top = %x\n", context.Esp, t.stackBottom);
+			mark(cast(void *)context.Esp, t.stackBottom);
+			mark(&context.Edi, &context.Eip);
+		    }
+		    else version (GNU)
+		    {
+			if (t.isSelf())
+			    t.stackTop = Thread.getESP();
+
+			//%%fry printf("top=%08x bot=%08x ext=%08x\n", t.stackTop, t.stackBottom, Thread.getESP());//%%try
+			version (STACKGROWSDOWN)
+			    mark(t.stackTop, t.stackBottom);
+			else
+			    mark(t.stackBottom, t.stackTop);
+		    }
+		    else version (linux)
+		    {
+			// The registers are already stored in the stack
+			//printf("Thread: ESP = x%x, stackBottom = x%x, isSelf = %d\n", Thread.getESP(), t.stackBottom, t.isSelf());
+			if (t.isSelf())
+			    t.stackTop = Thread.getESP();
+
+			version (STACKGROWSDOWN)
+			    mark(t.stackTop, t.stackBottom);
+			else
+			    mark(t.stackBottom, t.stackTop);
+		    }
+		}
+	    }
+	}
+	else
+	{
+	    if (!noStack)
+	    {
+		// Scan stack for main thread
+		debug(PRINTF) printf(" scan stack bot = %x, top = %x\n", stackTop, stackBottom);
+		version (STACKGROWSDOWN)
+		    mark(stackTop, stackBottom);
+		else
+		    mark(stackBottom, stackTop);
+	    }
+	}
+
+	// Scan roots[]
+	debug(COLLECT_PRINTF) printf("scan roots[]\n");
+	mark(roots, roots + nroots);
+
+	// Scan ranges[]
+	debug(COLLECT_PRINTF) printf("scan ranges[]\n");
+	//log++;
+	for (n = 0; n < nranges; n++)
+	{
+	    debug(COLLECT_PRINTF) printf("\t%x .. %x\n", ranges[n].pbot, ranges[n].ptop);
+	    mark(ranges[n].pbot, ranges[n].ptop);
+	}
+	//log--;
+
+	debug(COLLECT_PRINTF) printf("\tscan heap\n");
+	while (anychanges)
+	{
+	    anychanges = 0;
+	    for (n = 0; n < npools; n++)
+	    {
+		uint *bbase;
+		uint *b;
+		uint *btop;
+
+		pool = pooltable[n];
+
+		bbase = pool.scan.base();
+		btop = bbase + pool.scan.nwords;
+		for (b = bbase; b < btop;)
+		{   Bins bin;
+		    uint pn;
+		    uint u;
+		    uint bitm;
+		    byte *o;
+
+		    bitm = *b;
+		    if (!bitm)
+		    {   b++;
+			continue;
+		    }
+		    *b = 0;
+
+		    o = pool.baseAddr + (b - bbase) * 32 * 16;
+		    /*		    version (BigEndian)
+			bitm = bswap(bitm);
+		    */
+		    if (!(bitm & 0xFFFF))
+		    {
+			bitm >>= 16;
+			o += 16 * 16;
+		    }
+		    for (; bitm; o += 16, bitm >>= 1)
+		    {
+			if (!(bitm & 1))
+			    continue;
+
+			pn = (o - pool.baseAddr) / PAGESIZE;
+			bin = cast(Bins)pool.pagetable[pn];
+			if (bin < B_PAGE)
+			{
+			    mark(o, o + binsize[bin]);
+			}
+			else if (bin == B_PAGE || bin == B_PAGEPLUS)
+			{
+			    if (bin == B_PAGEPLUS)
+			    {
+				while (pool.pagetable[pn - 1] != B_PAGE)
+				    pn--;
+			    }
+			    u = 1;
+			    while (pn + u < pool.ncommitted && pool.pagetable[pn + u] == B_PAGEPLUS)
+				u++;
+			    mark(o, o + u * PAGESIZE);
+			}
+		    }
+		}
+	    }
+	}
+
+	// Free up everything not marked
+	debug(COLLECT_PRINTF) printf("\tfree'ing\n");
+	size_t freedpages = 0;
+	size_t freed = 0;
+	for (n = 0; n < npools; n++)
+	{   uint pn;
+	    uint ncommitted;
+	    uint *bbase;
+
+	    pool = pooltable[n];
+	    bbase = pool.mark.base();
+	    ncommitted = pool.ncommitted;
+	    for (pn = 0; pn < ncommitted; pn++, bbase += PAGESIZE / (32 * 16))
+	    {
+		Bins bin = cast(Bins)pool.pagetable[pn];
+
+		if (bin < B_PAGE)
+		{   byte *p;
+		    byte *ptop;
+		    uint biti;
+		    uint bitstride;
+		    uint size = binsize[bin];
+
+		    p = pool.baseAddr + pn * PAGESIZE;
+		    ptop = p + PAGESIZE;
+		    biti = pn * (PAGESIZE/16);
+		    bitstride = size / 16;
+
+    version(none) // BUG: doesn't work because freebits() must also be cleared
+    {
+		    // If free'd entire page
+		    if (bbase[0] == 0 && bbase[1] == 0 && bbase[2] == 0 && bbase[3] == 0 &&
+			bbase[4] == 0 && bbase[5] == 0 && bbase[6] == 0 && bbase[7] == 0)
+		    {
+			for (; p < ptop; p += size, biti += bitstride)
+			{
+			    if (pool.finals.nbits && pool.finals.testClear(biti))
+				rt_finalize(cast(List *)sentinel_add(p), false);
+
+			    List *list = cast(List *)p;
+			    //debug(PRINTF) printf("\tcollecting %x\n", list);
+			    log_free(sentinel_add(list));
+
+			    debug (MEMSTOMP) cstring.memset(p, 0xF3, size);
+			}
+			pool.pagetable[pn] = B_FREE;
+			freed += PAGESIZE;
+			//debug(PRINTF) printf("freeing entire page %d\n", pn);
+			continue;
+		    }
     }
-
-    size_t extend(void* p, size_t minsize, size_t maxsize)
+		    for (; p < ptop; p += size, biti += bitstride)
+		    {
+			if (!pool.mark.test(biti))
+			{
+			    sentinel_Invariant(sentinel_add(p));
+
+			    pool.freebits.set(biti);
+			    pool.noscan.clear(biti);
+			    if (pool.finals.nbits && pool.finals.testClear(biti))
+				rt_finalize(cast(List *)sentinel_add(p), false);
+
+			    List *list = cast(List *)p;
+			    debug(PRINTF) printf("\tcollecting %x\n", list);
+			    log_free(sentinel_add(list));
+
+			    debug (MEMSTOMP) cstring.memset(p, 0xF3, size);
+
+			    freed += size;
+			}
+		    }
+		}
+		else if (bin == B_PAGE)
+		{   uint biti = pn * (PAGESIZE / 16);
+
+		    if (!pool.mark.test(biti))
+		    {   byte *p = pool.baseAddr + pn * PAGESIZE;
+
+			sentinel_Invariant(sentinel_add(p));
+			pool.noscan.clear(biti);
+			if (pool.finals.nbits && pool.finals.testClear(biti))
+			    rt_finalize(sentinel_add(p), false);
+
+			debug(COLLECT_PRINTF) printf("\tcollecting big %x\n", p);
+			log_free(sentinel_add(p));
+			pool.pagetable[pn] = B_FREE;
+			freedpages++;
+			debug (MEMSTOMP) cstring.memset(p, 0xF3, PAGESIZE);
+			while (pn + 1 < ncommitted && pool.pagetable[pn + 1] == B_PAGEPLUS)
+			{
+			    pn++;
+			    pool.pagetable[pn] = B_FREE;
+			    freedpages++;
+
+			    debug (MEMSTOMP)
+			    {   p += PAGESIZE;
+				cstring.memset(p, 0xF3, PAGESIZE);
+			    }
+			}
+		    }
+		}
+	    }
+	}
+
+	// Zero buckets
+	bucket[] = null;
+
+	// Free complete pages, rebuild free list
+	debug(COLLECT_PRINTF) printf("\tfree complete pages\n");
+	size_t recoveredpages = 0;
+	for (n = 0; n < npools; n++)
+	{   uint pn;
+	    uint ncommitted;
+
+	    pool = pooltable[n];
+	    ncommitted = pool.ncommitted;
+	    for (pn = 0; pn < ncommitted; pn++)
+	    {
+		Bins bin = cast(Bins)pool.pagetable[pn];
+		uint biti;
+		uint u;
+
+		if (bin < B_PAGE)
+		{
+		    uint size = binsize[bin];
+		    uint bitstride = size / 16;
+		    uint bitbase = pn * (PAGESIZE / 16);
+		    uint bittop = bitbase + (PAGESIZE / 16);
+		    byte *p;
+
+		    biti = bitbase;
+		    for (biti = bitbase; biti < bittop; biti += bitstride)
+		    {   if (!pool.freebits.test(biti))
+			    goto Lnotfree;
+		    }
+		    pool.pagetable[pn] = B_FREE;
+		    recoveredpages++;
+		    continue;
+
+		 Lnotfree:
+		    p = pool.baseAddr + pn * PAGESIZE;
+		    for (u = 0; u < PAGESIZE; u += size)
+		    {   biti = bitbase + u / 16;
+			if (pool.freebits.test(biti))
+			{   List *list;
+
+			    list = cast(List *)(p + u);
+			    if (list.next != bucket[bin])	// avoid unnecessary writes
+				list.next = bucket[bin];
+			    bucket[bin] = list;
+			}
+		    }
+		}
+	    }
+	}
+
+	debug(COLLECT_PRINTF) printf("recovered pages = %d\n", recoveredpages);
+	debug(COLLECT_PRINTF) printf("\tfree'd %u bytes, %u pages from %u pools\n", freed, freedpages, npools);
+
+	Thread.resumeAll();
+
+	return freedpages + recoveredpages;
+    }
+
+
+    /**
+     * Run finalizer on p when it is free'd.
+     */
+    void doFinalize(void *p)
     {
-    debug(PRINTF) printf("GC extend()\n");
-    assert(0);
+	Pool *pool = findPool(p);
+	assert(pool);
+
+	// Only allocate finals[] if we actually need it
+	if (!pool.finals.nbits)
+	    pool.finals.alloc(pool.mark.nbits);
+
+	pool.finals.set((p - pool.baseAddr) / 16);
+    }
+
+
+    /**
+     * Indicate that block pointed to by p has possible pointers
+     * to GC allocated memory in it.
+     */
+
+    void HasPointers(void *p)
+    {
+	Pool *pool = findPool(p);
+	assert(pool);
+
+	pool.noscan.clear((p - pool.baseAddr) / 16);
+    }
+
+
+    /**
+     * Indicate that block pointed to by p has no possible pointers
+     * to GC allocated memory in it.
+     */
+    void HasNoPointers(void *p)
+    {
+	//printf("HasNoPointers(%p)\n", p);
+	Pool *pool = findPool(p);
+	assert(pool);
+
+	pool.noscan.set((p - pool.baseAddr) / 16);
+    }
+
+
+    /***** Leak Detector ******/
+
+
+    debug (LOGGING)
+    {
+	LogArray current;
+	LogArray prev;
+
+
+	void log_init()
+	{
+	    //debug(PRINTF) printf("+log_init()\n");
+	    current.reserve(1000);
+	    prev.reserve(1000);
+	    //debug(PRINTF) printf("-log_init()\n");
+	}
+
+
+	void log_malloc(void *p, size_t size)
+	{
+	    //debug(PRINTF) printf("+log_malloc(p = %x, size = %d)\n", p, size);
+	    Log log;
+
+	    log.p = p;
+	    log.size = size;
+	    log.line = GC.line;
+	    log.file = GC.file;
+	    log.parent = null;
+
+	    GC.line = 0;
+	    GC.file = null;
+
+	    current.push(log);
+	    //debug(PRINTF) printf("-log_malloc()\n");
+	}
+
+
+	void log_free(void *p)
+	{
+	    //debug(PRINTF) printf("+log_free(%x)\n", p);
+	    size_t i;
+
+	    i = current.find(p);
+	    if (i == ~0u)
+	    {
+		debug(PRINTF) printf("free'ing unallocated memory %x\n", p);
+	    }
+	    else
+		current.remove(i);
+	    //debug(PRINTF) printf("-log_free()\n");
+	}
+
+	void log_collect()
+	{
+	    //debug(PRINTF) printf("+log_collect()\n");
+	    // Print everything in current that is not in prev
+
+	    debug(PRINTF) printf("New pointers this cycle: --------------------------------\n");
+	    size_t used = 0;
+	    for (size_t i = 0; i < current.dim; i++)
+	    {
+		size_t j;
+
+		j = prev.find(current.data[i].p);
+		if (j == ~0u)
+		    current.data[i].print();
+		else
+		    used++;
+	    }
+
+	    debug(PRINTF) printf("All roots this cycle: --------------------------------\n");
+	    for (size_t i = 0; i < current.dim; i++)
+	    {
+		void *p;
+		size_t j;
+
+		p = current.data[i].p;
+		if (!findPool(current.data[i].parent))
+		{
+		    j = prev.find(current.data[i].p);
+		    if (j == ~0u)
+			debug(PRINTF) printf("N");
+		    else
+			debug(PRINTF) printf(" ");;
+		    current.data[i].print();
+		}
+	    }
+
+	    debug(PRINTF) printf("Used = %d-------------------------------------------------\n", used);
+	    prev.copy(&current);
+
+	    debug(PRINTF) printf("-log_collect()\n");
+	}
+
+
+	void log_parent(void *p, void *parent)
+	{
+	    //debug(PRINTF) printf("+log_parent()\n");
+	    size_t i;
+
+	    i = current.find(p);
+	    if (i == ~0u)
+	    {
+		debug(PRINTF) printf("parent'ing unallocated memory %x, parent = %x\n", p, parent);
+		Pool *pool;
+		pool = findPool(p);
+		assert(pool);
+		size_t offset = cast(uint)(p - pool.baseAddr);
+		size_t biti;
+		uint pn = offset / PAGESIZE;
+		Bins bin = cast(Bins)pool.pagetable[pn];
+		biti = (offset & notbinsize[bin]);
+		debug(PRINTF) printf("\tbin = %d, offset = x%x, biti = x%x\n", bin, offset, biti);
+	    }
+	    else
+	    {
+		current.data[i].parent = parent;
+	    }
+	    //debug(PRINTF) printf("-log_parent()\n");
+	}
+
+    }
+    else
+    {
+	void log_init() { }
+	void log_malloc(void *p, size_t size) { }
+	void log_free(void *p) { }
+	void log_collect() { }
+	void log_parent(void *p, void *parent) { }
     }
 }
+
+
+/* ============================ Pool  =============================== */
+
+
+struct Pool
+{
+    byte* baseAddr;
+    byte* topAddr;
+    GCBits mark;	// entries already scanned, or should not be scanned
+    GCBits scan;	// entries that need to be scanned
+    GCBits freebits;	// entries that are on the free list
+    GCBits finals;	// entries that need finalizer run on them
+    GCBits noscan;	// entries that should not be scanned
+
+    uint npages;
+    uint ncommitted;	// ncommitted <= npages
+    ubyte* pagetable;
+
+
+    void initialize(uint npages)
+    {
+	size_t poolsize;
+
+	//debug(PRINTF) printf("Pool::Pool(%u)\n", npages);
+	poolsize = npages * PAGESIZE;
+	assert(poolsize >= POOLSIZE);
+	baseAddr = cast(byte *)os_mem_map(poolsize);
+
+	// Some of the code depends on page alignment of memory pools
+	assert((cast(uint)baseAddr & (PAGESIZE - 1)) == 0);
+
+	if (!baseAddr)
+	{
+	    //debug(PRINTF) printf("GC fail: poolsize = x%x, errno = %d\n", poolsize, errno);
+	    //debug(PRINTF) printf("message = '%s'\n", sys_errlist[errno]);
+
+	    npages = 0;
+	    poolsize = 0;
+	}
+	//assert(baseAddr);
+	topAddr = baseAddr + poolsize;
+
+	mark.alloc(poolsize / 16);
+	scan.alloc(poolsize / 16);
+	freebits.alloc(poolsize / 16);
+	noscan.alloc(poolsize / 16);
+
+	pagetable = cast(ubyte*)cstdlib.malloc(npages);
+	if (!pagetable)
+	    onOutOfMemoryError();
+	cstring.memset(pagetable, B_UNCOMMITTED, npages);
+
+	this.npages = npages;
+	ncommitted = 0;
+    }
+
+
+    void Dtor()
+    {
+	if (baseAddr)
+	{
+	    int result;
+
+	    if (ncommitted)
+	    {
+		result = os_mem_decommit(baseAddr, 0, ncommitted * PAGESIZE);
+		assert(result == 0);
+		ncommitted = 0;
+	    }
+
+	    if (npages)
+	    {
+		result = os_mem_unmap(baseAddr, npages * PAGESIZE);
+		assert(result == 0);
+		npages = 0;
+	    }
+
+	    baseAddr = null;
+	    topAddr = null;
+	}
+	if (pagetable)
+	    cstdlib.free(pagetable);
+
+	mark.Dtor();
+	scan.Dtor();
+	freebits.Dtor();
+	finals.Dtor();
+        noscan.Dtor();
+    }
+
+
+    void Invariant() { }
+
+
+    invariant()
+    {
+	//mark.Invariant();
+	//scan.Invariant();
+	//freebits.Invariant();
+	//finals.Invariant();
+	//noscan.Invariant();
+
+	if (baseAddr)
+	{
+	    //if (baseAddr + npages * PAGESIZE != topAddr)
+		//printf("baseAddr = %p, npages = %d, topAddr = %p\n", baseAddr, npages, topAddr);
+	    assert(baseAddr + npages * PAGESIZE == topAddr);
+	    assert(ncommitted <= npages);
+	}
+
+	for (uint i = 0; i < npages; i++)
+	{   Bins bin = cast(Bins)pagetable[i];
+
+	    assert(bin < B_MAX);
+	}
+    }
+
+
+    /**
+     * Allocate n pages from Pool.
+     * Returns ~0u on failure.
+     */
+    uint allocPages(uint n)
+    {
+	uint i;
+	uint n2;
+
+	//debug(PRINTF) printf("Pool::allocPages(n = %d)\n", n);
+	n2 = n;
+	for (i = 0; i < ncommitted; i++)
+	{
+	    if (pagetable[i] == B_FREE)
+	    {
+		if (--n2 == 0)
+		{   //debug(PRINTF) printf("\texisting pn = %d\n", i - n + 1);
+		    return i - n + 1;
+		}
+	    }
+	    else
+		n2 = n;
+	}
+	return extendPages(n);
+    }
+
+    /**
+     * Extend Pool by n pages.
+     * Returns ~0u on failure.
+     */
+    uint extendPages(uint n)
+    {
+	//debug(PRINTF) printf("Pool::extendPages(n = %d)\n", n);
+	if (ncommitted + n <= npages)
+	{
+	    uint tocommit;
+
+	    tocommit = (n + (COMMITSIZE/PAGESIZE) - 1) & ~(COMMITSIZE/PAGESIZE - 1);
+	    if (ncommitted + tocommit > npages)
+		tocommit = npages - ncommitted;
+	    //debug(PRINTF) printf("\tlooking to commit %d more pages\n", tocommit);
+	    //fflush(stdout);
+	    if (os_mem_commit(baseAddr, ncommitted * PAGESIZE, tocommit * PAGESIZE) == 0)
+	    {
+		cstring.memset(pagetable + ncommitted, B_FREE, tocommit);
+		auto i = ncommitted;
+		ncommitted += tocommit;
+
+		while (i && pagetable[i - 1] == B_FREE)
+		    i--;
+
+		return i;
+	    }
+	    //debug(PRINTF) printf("\tfailed to commit %d pages\n", tocommit);
+	}
+
+	return ~0u;
+    }
+
+
+    /**
+     * Free npages pages starting with pagenum.
+     */
+    void freePages(uint pagenum, uint npages)
+    {
+	cstring.memset(&pagetable[pagenum], B_FREE, npages);
+    }
+
+
+    /**
+     * Used for sorting pooltable[]
+     */
+    int opCmp(Pool *p2)
+    {
+	if (baseAddr < p2.baseAddr)
+	    return -1;
+	else
+	    return cast(int)(baseAddr > p2.baseAddr);
+    }
+}
+
+
+/* ============================ SENTINEL =============================== */
+
+
+version (SENTINEL)
+{
+    const size_t SENTINEL_PRE = cast(size_t) 0xF4F4F4F4F4F4F4F4UL;	// 32 or 64 bits
+    const ubyte SENTINEL_POST = 0xF5;		// 8 bits
+    const uint SENTINEL_EXTRA = 2 * size_t.sizeof + 1;
+
+
+    size_t* sentinel_size(void *p)  { return &(cast(size_t *)p)[-2]; }
+    size_t* sentinel_pre(void *p)   { return &(cast(size_t *)p)[-1]; }
+    ubyte* sentinel_post(void *p) { return &(cast(ubyte *)p)[sentinel_size(p)]; }
+
+
+    void sentinel_init(void *p, size_t size)
+    {
+	*sentinel_size(p) = size;
+	*sentinel_pre(p) = SENTINEL_PRE;
+	*sentinel_post(p) = SENTINEL_POST;
+    }
+
+
+    void sentinel_Invariant(void *p)
+    {
+	assert(*sentinel_pre(p) == SENTINEL_PRE);
+	assert(*sentinel_post(p) == SENTINEL_POST);
+    }
+
+
+    void *sentinel_add(void *p)
+    {
+	return p + 2 * size_t.sizeof;
+    }
+
+
+    void *sentinel_sub(void *p)
+    {
+	return p - 2 * size_t.sizeof;
+    }
+}
+else
+{
+    const uint SENTINEL_EXTRA = 0;
+
+
+    void sentinel_init(void *p, size_t size)
+    {
+    }
+
+
+    void sentinel_Invariant(void *p)
+    {
+    }
+
+
+    void *sentinel_add(void *p)
+    {
+	return p;
+    }
+
+
+    void *sentinel_sub(void *p)
+    {
+	return p;
+    }
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lphobos/gc/win32.d	Mon Aug 04 19:28:49 2008 +0200
@@ -0,0 +1,168 @@
+
+// Copyright (C) 2001-2002 by Digital Mars
+// All Rights Reserved
+// www.digitalmars.com
+// Written by Walter Bright
+
+import std.c.windows.windows;
+
+alias int pthread_t;
+
+/***********************************
+ * Map memory.
+ */
+
+void *os_mem_map(uint nbytes)
+{
+    return VirtualAlloc(null, nbytes, MEM_RESERVE, PAGE_READWRITE);
+}
+
+/***********************************
+ * Commit memory.
+ * Returns:
+ *	0	success
+ *	!=0	failure
+ */
+
+int os_mem_commit(void *base, uint offset, uint nbytes)
+{
+    void *p;
+
+    p = VirtualAlloc(base + offset, nbytes, MEM_COMMIT, PAGE_READWRITE);
+    return cast(int)(p == null);
+}
+
+
+/***********************************
+ * Decommit memory.
+ * Returns:
+ *	0	success
+ *	!=0	failure
+ */
+
+int os_mem_decommit(void *base, uint offset, uint nbytes)
+{
+    return cast(int)VirtualFree(base + offset, nbytes, MEM_DECOMMIT) == 0; 
+}
+
+/***********************************
+ * Unmap memory allocated with os_mem_map().
+ * Memory must have already been decommitted.
+ * Returns:
+ *	0	success
+ *	!=0	failure
+ */
+
+int os_mem_unmap(void *base, uint nbytes)
+{
+    return cast(int)VirtualFree(base, 0, MEM_RELEASE) == 0; 
+}
+
+
+/********************************************
+ */
+
+pthread_t pthread_self()
+{
+    //printf("pthread_self() = %x\n", GetCurrentThreadId());
+    return cast(pthread_t) GetCurrentThreadId();
+}
+
+/**********************************************
+ * Determine "bottom" of stack (actually the top on Win32 systems).
+ */
+
+void *os_query_stackBottom()
+{
+    asm
+    {
+	naked			;
+	mov	EAX,FS:4	;
+	ret			;
+    }
+}
+
+/**********************************************
+ * Determine base address and size of static data segment.
+ */
+
+version (GNU)
+{
+// This is MinGW specific
+extern (C)
+{
+    // TODO: skip the .rdata between .data and .bss?
+    extern int _data_start__;
+    extern int _bss_end__;
+}
+
+void os_query_staticdataseg(void **base, uint *nbytes)
+{
+    *base = cast(void *)&_data_start__;
+    *nbytes = cast(uint)(cast(char *)&_bss_end__ - cast(char *)&_data_start__);
+}
+
+}
+else
+{
+    
+extern (C)
+{
+    extern int _xi_a;	// &_xi_a just happens to be start of data segment
+    extern int _edata;	// &_edata is start of BSS segment
+    extern int _end;	// &_end is past end of BSS
+}
+
+void os_query_staticdataseg(void **base, uint *nbytes)
+{
+    *base = cast(void *)&_xi_a;
+    *nbytes = cast(uint)(cast(char *)&_end - cast(char *)&_xi_a);
+}
+
+}
+/++++
+
+void os_query_staticdataseg(void **base, uint *nbytes)
+{
+    static char dummy = 6;
+    SYSTEM_INFO si;
+    MEMORY_BASIC_INFORMATION mbi;
+    char *p;
+    void *bottom = null;
+    uint size = 0;
+
+    // Tests show the following does not work reliably.
+    // The reason is that the data segment is arbitrarily divided
+    // up into PAGE_READWRITE and PAGE_WRITECOPY.
+    // This means there are multiple regions to query, and
+    // can even wind up including the code segment.
+    assert(0);				// fix implementation
+
+    GetSystemInfo(&si);
+    p = (char *)((uint)(&dummy) & ~(si.dwPageSize - 1));
+    while (VirtualQuery(p, &mbi, sizeof(mbi)) == sizeof(mbi) &&
+        mbi.Protect & (PAGE_READWRITE | PAGE_WRITECOPY) &&
+        !(mbi.Protect & PAGE_GUARD) &&
+        mbi.AllocationBase != 0)
+    {
+	bottom = (void *)mbi.BaseAddress;
+	size = (uint)mbi.RegionSize;
+
+	printf("dwPageSize        = x%x\n", si.dwPageSize);
+	printf("&dummy            = %p\n", &dummy);
+	printf("BaseAddress       = %p\n", mbi.BaseAddress);
+	printf("AllocationBase    = %p\n", mbi.AllocationBase);
+	printf("AllocationProtect = x%x\n", mbi.AllocationProtect);
+	printf("RegionSize        = x%x\n", mbi.RegionSize);
+	printf("State             = x%x\n", mbi.State);
+	printf("Protect           = x%x\n", mbi.Protect);
+	printf("Type              = x%x\n\n", mbi.Type);
+
+	p -= si.dwPageSize;
+    }
+
+    *base = bottom;
+    *nbytes = size;
+}
+
+++++/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lphobos/hello.d	Mon Aug 04 19:28:49 2008 +0200
@@ -0,0 +1,5 @@
+module hello;
+
+import std.stdio;
+
+void main() { writefln("Hello World"); }
--- a/lphobos/internal/aaA.d	Mon Aug 04 19:08:39 2008 +0200
+++ b/lphobos/internal/aaA.d	Mon Aug 04 19:28:49 2008 +0200
@@ -60,14 +60,14 @@
  */
 alias Array ArrayRet_t;
 
-pragma(LLVM_internal, "notypeinfo")
+pragma(no_typeinfo)
 struct Array
 {
     size_t length;
     void* ptr;
 }
 
-pragma(LLVM_internal, "notypeinfo")
+pragma(no_typeinfo)
 struct aaA
 {
     aaA *left;
@@ -77,7 +77,7 @@
     /* value */
 }
 
-pragma(LLVM_internal, "notypeinfo")
+pragma(no_typeinfo)
 struct BB
 {
     aaA*[] b;
@@ -226,7 +226,7 @@
  * Add entry for key if it is not already there.
  */
 
-void* _aaGet(AA* aa, TypeInfo keyti, void* pkey, size_t valuesize)
+void* _aaGet(AA* aa, TypeInfo keyti, size_t valuesize, void* pkey)
     in
     {
 	assert(aa);
--- a/lphobos/internal/adi.d	Mon Aug 04 19:08:39 2008 +0200
+++ b/lphobos/internal/adi.d	Mon Aug 04 19:28:49 2008 +0200
@@ -38,7 +38,7 @@
 import std.outofmemory;
 import std.utf;
 
-pragma(LLVM_internal, "notypeinfo")
+pragma(no_typeinfo)
 struct Array
 {
     size_t length;
@@ -462,13 +462,13 @@
 
 extern (C) int _adEq(Array a1, Array a2, TypeInfo ti)
 {
-    //printf("_adEq(a1.length = %d, a2.length = %d)\n", a1.length, a2.length);
+    // printf("_adEq(a1.length = %d, a2.length = %d)\n", a1.length, a2.length);
     if (a1.length != a2.length)
     return 0;       // not equal
-    auto sz = ti.tsize();
+    auto sz = ti.next.tsize();
     auto p1 = a1.ptr;
     auto p2 = a2.ptr;
-
+    
 /+
     for (int i = 0; i < a1.length; i++)
     {
@@ -480,10 +480,10 @@
     if (sz == 1)
     // We should really have a ti.isPOD() check for this
     return (memcmp(p1, p2, a1.length) == 0);
-
+    
     for (size_t i = 0; i < a1.length; i++)
     {
-    if (!ti.equals(p1 + i * sz, p2 + i * sz))
+    if (!ti.next.equals(p1 + i * sz, p2 + i * sz))
         return 0;       // not equal
     }
     return 1;           // equal
--- a/lphobos/internal/contract.d	Mon Aug 04 19:08:39 2008 +0200
+++ b/lphobos/internal/contract.d	Mon Aug 04 19:28:49 2008 +0200
@@ -1,13 +1,21 @@
 module internal.contract;
 
+import std.string: toString;
 extern(C):
 
 void exit(int);
 
-void _d_assert(bool cond, uint line, char[] msg)
+/*void _d_assert(bool cond, uint line, char[] msg)
 {
     if (!cond) {
         printf("Aborted(%u): %.*s\n", line, msg.length, msg.ptr);
         exit(1);
     }
+}*/
+void _d_assert(string file, uint line) {
+  throw new Exception(file~":"~.toString(line)~": Assertion failed!");
 }
+
+void _d_assert_msg(string msg, string file, uint line) {
+  throw new Exception(file~": "~.toString(line)~": Assertion failed: \""~msg~"\"");
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lphobos/internal/critical.d	Mon Aug 04 19:28:49 2008 +0200
@@ -0,0 +1,49 @@
+module internal.critical;
+extern(C):
+
+import std.c.linux.linux, std.c.stdlib:ccalloc=calloc, cmalloc=malloc, cfree=free;
+
+struct CritSec {
+  pthread_mutex_t* p;
+}
+
+const PTHREAD_MUTEX_RECURSIVE = 1, PTHREAD_MUTEX_ERRORCHECK=2;
+
+extern(C) int pthread_self();
+
+void _d_criticalenter(CritSec* cs) {
+  if (!cs.p) {
+    auto newp = cast(pthread_mutex_t*) cmalloc(pthread_mutex_t.sizeof);
+    auto cspp = &cs.p;
+    pthread_mutexattr_t mt; pthread_mutexattr_init(&mt);
+    pthread_mutexattr_settype(&mt, PTHREAD_MUTEX_RECURSIVE);
+    printf("Create -> %i\n", pthread_mutex_init(newp, &mt));
+    asm { xor EAX, EAX; mov ECX, newp; mov EDX, cspp; lock; cmpxchg int ptr [EDX], ECX; }
+    if (cs.p != newp) pthread_mutex_destroy(newp);
+  }
+  auto count = (cast(uint*) cs.p)[1];
+  // printf("%i ::%u\n", pthread_self(), count);
+  //printf("%i: Lock %p -> %i\n", pthread_self(), cs.p,
+    pthread_mutex_lock(cs.p);//);
+}
+
+void _d_criticalexit(CritSec* cs) {
+  //printf("%i: Unlock %p -> %i\n", pthread_self(), cs.p,
+    pthread_mutex_unlock(cs.p);//);
+}
+
+void _d_monitorenter(Object h)
+{
+    _d_criticalenter(cast(CritSec*) &h.__monitor);
+}
+
+void _d_monitorexit(Object h)
+{
+    _d_criticalexit(cast(CritSec*) &h.__monitor);
+}
+
+void _STI_monitor_staticctor() { }
+void _STI_critical_init() { }
+void _STI_critical_term() { }
+void _STD_monitor_staticdtor() { }
+void _STD_critical_term() { }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lphobos/internal/dmain2.d	Mon Aug 04 19:28:49 2008 +0200
@@ -0,0 +1,122 @@
+/*
+ * Placed into the Public Domain.
+ * written by Walter Bright
+ * www.digitalmars.com
+ */
+
+module internal.dmain2;
+import object;
+import std.c.stdio;
+import std.c.string;
+import std.c.stdlib;
+import std.string;
+
+extern (C) void _STI_monitor_staticctor();
+extern (C) void _STD_monitor_staticdtor();
+extern (C) void _STI_critical_init();
+extern (C) void _STD_critical_term();
+extern (C) void gc_init();
+extern (C) void gc_term();
+extern (C) void _minit();
+extern (C) void _moduleCtor();
+extern (C) void _moduleDtor();
+extern (C) void _moduleUnitTests();
+
+extern (C) bool no_catch_exceptions;
+
+/***********************************
+ * The D main() function supplied by the user's program
+ */
+int main(char[][] args);
+
+/***********************************
+ * Substitutes for the C main() function.
+ * It's purpose is to wrap the call to the D main()
+ * function and catch any unhandled exceptions.
+ */
+
+extern (C) int main(size_t argc, char **argv)
+{
+    char[] *am;
+    char[][] args;
+    int result;
+    int myesp;
+    int myebx;
+
+    version (linux)
+    {
+	_STI_monitor_staticctor();
+	_STI_critical_init();
+	gc_init();
+	am = cast(char[] *) malloc(argc * (char[]).sizeof);
+	// BUG: alloca() conflicts with try-catch-finally stack unwinding
+	//am = (char[] *) alloca(argc * (char[]).sizeof);
+    }
+    version (Win32)
+    {
+	gc_init();
+	_minit();
+	am = cast(char[] *) alloca(argc * (char[]).sizeof);
+    }
+
+    if (no_catch_exceptions)
+    {
+	_moduleCtor();
+	_moduleUnitTests();
+
+	for (size_t i = 0; i < argc; i++)
+	{
+	    auto len = strlen(argv[i]);
+	    am[i] = argv[i][0 .. len];
+	}
+
+	args = am[0 .. argc];
+
+	result = main(args);
+	_moduleDtor();
+	gc_term();
+    }
+    else
+    {
+	try
+	{
+	    _moduleCtor();
+	    _moduleUnitTests();
+
+	    for (size_t i = 0; i < argc; i++)
+	    {
+		auto len = strlen(argv[i]);
+		am[i] = argv[i][0 .. len];
+	    }
+
+	    args = am[0 .. argc];
+
+	    result = main(args);
+	    _moduleDtor();
+	    gc_term();
+	}
+	catch (Object o)
+	{
+	    version (none)
+	    {
+		printf("Error: ");
+		o.print();
+	    }
+	    else
+	    {
+		auto foo = o.toString();
+		fprintf(stderr, "Error: %.*s\n", foo.length, foo.ptr);
+	    }
+	    exit(EXIT_FAILURE);
+	}
+    }
+
+    version (linux)
+    {
+	free(am);
+	_STD_critical_term();
+	_STD_monitor_staticdtor();
+    }
+    return result;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lphobos/internal/eh.d	Mon Aug 04 19:28:49 2008 +0200
@@ -0,0 +1,374 @@
+/**
+ * This module contains functions and structures required for
+ * exception handling.
+ */
+module eh;
+
+// debug = EH_personality;
+// debug = EH_personality_verbose;
+
+// current EH implementation works on x86 linux only
+version(X86) version(linux) version=X86_LINUX;
+
+private extern(C) void abort();
+private extern(C) int printf(char*, ...);
+
+// D runtime functions
+extern(C) {
+    int _d_isbaseof(ClassInfo oc, ClassInfo c);
+}
+
+// libunwind headers
+extern(C)
+{
+    enum _Unwind_Reason_Code
+    {
+        NO_REASON = 0,
+        FOREIGN_EXCEPTION_CAUGHT = 1,
+        FATAL_PHASE2_ERROR = 2,
+        FATAL_PHASE1_ERROR = 3,
+        NORMAL_STOP = 4,
+        END_OF_STACK = 5,
+        HANDLER_FOUND = 6,
+        INSTALL_CONTEXT = 7,
+        CONTINUE_UNWIND = 8
+    }
+
+    enum _Unwind_Action
+    {
+        SEARCH_PHASE = 1,
+        CLEANUP_PHASE = 2,
+        HANDLER_PHASE = 3,
+        FORCE_UNWIND = 4
+    }
+
+    alias void* _Unwind_Context_Ptr;
+
+    alias void function(_Unwind_Reason_Code, _Unwind_Exception*) _Unwind_Exception_Cleanup_Fn;
+
+    struct _Unwind_Exception
+    {
+        char[8] exception_class;
+        _Unwind_Exception_Cleanup_Fn exception_cleanup;
+        int private_1;
+        int private_2;
+    }
+
+version(X86_LINUX) 
+{
+    void _Unwind_Resume(_Unwind_Exception*);
+    _Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Exception*);
+    ulong _Unwind_GetLanguageSpecificData(_Unwind_Context_Ptr context);
+    ulong _Unwind_GetIP(_Unwind_Context_Ptr context);
+    ulong _Unwind_SetIP(_Unwind_Context_Ptr context, ulong new_value);
+    ulong _Unwind_SetGR(_Unwind_Context_Ptr context, int index, ulong new_value);
+    ulong _Unwind_GetRegionStart(_Unwind_Context_Ptr context);
+}
+else
+{
+    // runtime calls these directly
+    void _Unwind_Resume(_Unwind_Exception*)
+    {
+        printf("_Unwind_Resume is not implemented on this platform.\n");
+    }
+    _Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Exception*)
+    {
+        printf("_Unwind_RaiseException is not implemented on this platform.\n");
+        return _Unwind_Reason_Code.FATAL_PHASE1_ERROR;
+    }
+}
+
+}
+
+
+// helpers for reading certain DWARF data
+//TODO: It may not be a good idea to use exceptions for error handling within exception handling code
+private ubyte* get_uleb128(ubyte* addr, ref size_t res)
+{
+  res = 0;
+  size_t bitsize = 0;
+
+  // read as long as high bit is set
+  while(*addr & 0x80) {
+    res |= (*addr & 0x7f) << bitsize;
+    bitsize += 7;
+    addr += 1;
+    if(bitsize >= size_t.sizeof*8)
+       throw new Exception("tried to read uleb128 that exceeded size of size_t");
+  }
+  // read last
+  if(bitsize != 0 && *addr >= 1 << size_t.sizeof*8 - bitsize)
+    throw new Exception("tried to read uleb128 that exceeded size of size_t");
+  res |= (*addr) << bitsize;
+
+  return addr + 1;
+}
+
+private ubyte* get_sleb128(ubyte* addr, ref ptrdiff_t res)
+{
+  res = 0;
+  size_t bitsize = 0;
+
+  // read as long as high bit is set
+  while(*addr & 0x80) {
+    res |= (*addr & 0x7f) << bitsize;
+    bitsize += 7;
+    addr += 1;
+    if(bitsize >= size_t.sizeof*8)
+       throw new Exception("tried to read sleb128 that exceeded size of size_t");
+  }
+  // read last
+  if(bitsize != 0 && *addr >= 1 << size_t.sizeof*8 - bitsize)
+    throw new Exception("tried to read sleb128 that exceeded size of size_t");
+  res |= (*addr) << bitsize;
+
+  // take care of sign
+  if(bitsize < size_t.sizeof*8 && ((*addr) & 0x40))
+    res |= cast(ptrdiff_t)(-1) ^ ((1 << (bitsize+7)) - 1);
+
+  return addr + 1;
+}
+
+
+// exception struct used by the runtime.
+// _d_throw allocates a new instance and passes the address of its
+// _Unwind_Exception member to the unwind call. The personality
+// routine is then able to get the whole struct by looking at the data
+// surrounding the unwind info.
+struct _d_exception
+{
+  Object exception_object;
+  _Unwind_Exception unwind_info;
+}
+
+// the 8-byte string identifying the type of exception
+// the first 4 are for vendor, the second 4 for language
+//TODO: This may be the wrong way around
+char[8] _d_exception_class = "LLDCD1\0\0";
+
+
+//
+// x86 Linux specific implementation of personality function
+// and helpers
+//
+version(X86_LINUX) 
+{
+
+// the personality routine gets called by the unwind handler and is responsible for
+// reading the EH tables and deciding what to do
+extern(C) _Unwind_Reason_Code _d_eh_personality(int ver, _Unwind_Action actions, ulong exception_class, _Unwind_Exception* exception_info, _Unwind_Context_Ptr context)
+{
+  printf("eh_personality is running\n");
+  // check ver: the C++ Itanium ABI only allows ver == 1
+  if(ver != 1) {
+    printf("Fatal Phase1 #1\n");
+    return _Unwind_Reason_Code.FATAL_PHASE1_ERROR;
+  }
+  
+  // check exceptionClass
+  //TODO: Treat foreign exceptions with more respect
+  if((cast(char*)&exception_class)[0..8] != _d_exception_class) {
+    printf("Fatal Phase1 #2: %s != %s\n", cast(char*)&exception_class, cast(char*) _d_exception_class);
+    return _Unwind_Reason_Code.FATAL_PHASE1_ERROR;
+  }
+
+  // find call site table, action table and classinfo table
+  // Note: callsite and action tables do not contain static-length
+  // data and will be parsed as needed
+  // Note: classinfo_table points past the end of the table
+  ubyte* callsite_table;
+  ubyte* action_table;
+  ClassInfo* classinfo_table;
+  _d_getLanguageSpecificTables(context, callsite_table, action_table, classinfo_table);
+
+
+  /*
+    find landing pad and action table index belonging to ip by walking
+    the callsite_table
+  */
+  ubyte* callsite_walker = callsite_table;
+
+  // get the instruction pointer
+  // will be used to find the right entry in the callsite_table
+  // -1 because it will point past the last instruction
+  ulong ip = _Unwind_GetIP(context) - 1;
+    
+  // address block_start is relative to
+  ulong region_start = _Unwind_GetRegionStart(context);
+
+  // table entries
+  uint block_start_offset, block_size;
+  ulong landing_pad;
+  size_t action_offset;
+
+  while(true) {
+    // if we've gone through the list and found nothing...
+    if(callsite_walker >= action_table) {
+      printf("Continue unwind #3\n");
+      return _Unwind_Reason_Code.CONTINUE_UNWIND;
+    }
+
+    block_start_offset = *cast(uint*)callsite_walker;
+    block_size = *(cast(uint*)callsite_walker + 1);
+    landing_pad = *(cast(uint*)callsite_walker + 2);
+    if(landing_pad)
+      landing_pad += region_start;
+    callsite_walker = get_uleb128(callsite_walker + 3*uint.sizeof, action_offset);
+
+    /*debug(EH_personality_verbose) */printf("%d %d %d\n", block_start_offset, block_size, landing_pad);
+
+    // since the list is sorted, as soon as we're past the ip
+    // there's no handler to be found
+    if(ip < region_start + block_start_offset) {
+      printf("Continue unwind #4\n");
+      return _Unwind_Reason_Code.CONTINUE_UNWIND;
+    }
+
+    // if we've found our block, exit
+    if(ip < region_start + block_start_offset + block_size)
+      break;
+  }
+
+  /*debug(EH_personality) */printf("Found correct landing pad and actionOffset %d\n", action_offset);
+
+  // now we need the exception's classinfo to find a handler
+  // the exception_info is actually a member of a larger _d_exception struct
+  // the runtime allocated. get that now
+  _d_exception* exception_struct = cast(_d_exception*)(cast(ubyte*)exception_info - _d_exception.unwind_info.offsetof);
+
+  // if there's no action offset and no landing pad, continue unwinding
+  if(!action_offset && !landing_pad) {
+    printf("Continue unwind #5\n");
+    return _Unwind_Reason_Code.CONTINUE_UNWIND;
+  }
+
+  // if there's no action offset but a landing pad, this is a cleanup handler
+  else if(!action_offset && landing_pad) {
+    printf("Install cleanup handler #6\n");
+    return _d_eh_install_finally_context(actions, landing_pad, exception_struct, context);
+  }
+
+  /*
+   walk action table chain, comparing classinfos using _d_isbaseof
+  */
+  ubyte* action_walker = action_table + action_offset - 1;
+
+  ptrdiff_t ti_offset, next_action_offset;
+  while(true) {
+    action_walker = get_sleb128(action_walker, ti_offset);
+    // it is intentional that we not modify action_walker here
+    // next_action_offset is from current action_walker position
+    get_sleb128(action_walker, next_action_offset);
+
+    // negative are 'filters' which we don't use
+    assert(ti_offset >= 0 && "Filter actions are unsupported");
+
+    // zero means cleanup, which we require to be the last action
+    if(ti_offset == 0) {
+      assert(next_action_offset == 0 && "Cleanup action must be last in chain");
+      printf("Cleanup handler #7\n");
+      return _d_eh_install_finally_context(actions, landing_pad, exception_struct, context);
+    }
+
+    // get classinfo for action and check if the one in the
+    // exception structure is a base
+    ClassInfo catch_ci = classinfo_table[-ti_offset];
+    /*debug(EH_personality) */printf("Comparing catch %s to exception %s\n", catch_ci.name.ptr, exception_struct.exception_object.classinfo.name.ptr);
+    if(_d_isbaseof(exception_struct.exception_object.classinfo, catch_ci)) {
+      printf("Install catch context #8\n");
+      return _d_eh_install_catch_context(actions, ti_offset, landing_pad, exception_struct, context);
+    }
+
+    // we've walked through all actions and found nothing...
+    if(next_action_offset == 0) {
+      printf("Continue unwind #9\n");
+      return _Unwind_Reason_Code.CONTINUE_UNWIND;
+    } else
+      action_walker += next_action_offset;
+  }
+  
+  printf("Assertion failure ;_;\n");
+  assert(false);
+}
+
+// These are the register numbers for SetGR that
+// llvm's eh.exception and eh.selector intrinsics
+// will pick up.
+// Found by trial-and-error and probably platform dependent!
+private int eh_exception_regno = 0;
+private int eh_selector_regno = 2;
+
+private _Unwind_Reason_Code _d_eh_install_catch_context(_Unwind_Action actions, ptrdiff_t switchval, ulong landing_pad, _d_exception* exception_struct, _Unwind_Context_Ptr context)
+{
+  debug(EH_personality) printf("Found catch clause!\n");
+
+  if(actions & _Unwind_Action.SEARCH_PHASE)
+    return _Unwind_Reason_Code.HANDLER_FOUND;
+
+  else if(actions & _Unwind_Action.HANDLER_PHASE)
+  {
+    debug(EH_personality) printf("Setting switch value to: %d!\n", switchval);
+    _Unwind_SetGR(context, eh_exception_regno, cast(ulong)cast(void*)(exception_struct.exception_object));
+    _Unwind_SetGR(context, eh_selector_regno, switchval);
+    _Unwind_SetIP(context, landing_pad);
+    return _Unwind_Reason_Code.INSTALL_CONTEXT;
+  }
+
+  assert(false);
+}
+
+private _Unwind_Reason_Code _d_eh_install_finally_context(_Unwind_Action actions, ulong landing_pad, _d_exception* exception_struct, _Unwind_Context_Ptr context)
+{
+  // if we're merely in search phase, continue
+  if(actions & _Unwind_Action.SEARCH_PHASE)
+    return _Unwind_Reason_Code.CONTINUE_UNWIND;
+
+  debug(EH_personality) printf("Calling cleanup routine...\n");
+
+  _Unwind_SetGR(context, eh_exception_regno, cast(ulong)exception_struct);
+  _Unwind_SetGR(context, eh_selector_regno, 0);
+  _Unwind_SetIP(context, landing_pad);
+  return _Unwind_Reason_Code.INSTALL_CONTEXT;
+}
+
+private void _d_getLanguageSpecificTables(_Unwind_Context_Ptr context, ref ubyte* callsite, ref ubyte* action, ref ClassInfo* ci)
+{
+  ubyte* data = cast(ubyte*)_Unwind_GetLanguageSpecificData(context);
+
+  //TODO: Do proper DWARF reading here
+  assert(*data++ == 0xff);
+
+  assert(*data++ == 0x00);
+  size_t cioffset;
+  data = get_uleb128(data, cioffset);
+  ci = cast(ClassInfo*)(data + cioffset);
+
+  assert(*data++ == 0x03);
+  size_t callsitelength;
+  data = get_uleb128(data, callsitelength);
+  action = data + callsitelength;
+
+  callsite = data;
+}
+
+} // end of x86 Linux specific implementation
+
+
+extern(C) void _d_throw_exception(Object e)
+{
+    if (e !is null)
+    {
+        _d_exception* exc_struct = new _d_exception;
+        exc_struct.unwind_info.exception_class[] = _d_exception_class;
+        exc_struct.exception_object = e;
+        printf("Raising exception\n");
+        _Unwind_Reason_Code ret = _Unwind_RaiseException(&exc_struct.unwind_info);
+        printf("_Unwind_RaiseException failed with reason code: %i\n", ret);
+    }
+    abort();
+}
+
+extern(C) void _d_eh_resume_unwind(_d_exception* exception_struct)
+{
+  _Unwind_Resume(&exception_struct.unwind_info);
+}
--- a/lphobos/internal/objectimpl.d	Mon Aug 04 19:08:39 2008 +0200
+++ b/lphobos/internal/objectimpl.d	Mon Aug 04 19:28:49 2008 +0200
@@ -1132,16 +1132,27 @@
     void function() ctor;
     void function() dtor;
     void function() unitTest;
+    
+    void* xgetMembers;
+    void function() ictor;
 
     /******************
      * Return collection of all modules in the program.
      */
-    static ModuleInfo[] modules()
-    {
-    return std.moduleinit._moduleinfo_array;
+    static int opApply(int delegate(ref ModuleInfo) dg) {
+      foreach (ref mod; std.moduleinit._moduleinfo_array)
+        if (auto i = dg(mod)) return i;
+      return 0;
     }
 }
 
+struct ModuleReference
+{
+    ModuleReference* next;
+    ModuleInfo mod;
+}
+extern(C) ModuleReference* _Dmodule_ref;
+
 /**
  * All recoverable exceptions should be derived from class Exception.
  */
@@ -1189,4 +1200,3 @@
 }
 
 //extern (C) int nullext = 0;
-
--- a/lphobos/internal/qsort2.d	Mon Aug 04 19:08:39 2008 +0200
+++ b/lphobos/internal/qsort2.d	Mon Aug 04 19:28:49 2008 +0200
@@ -14,7 +14,7 @@
 
 import std.c.stdlib;
 
-pragma(LLVM_internal, "notypeinfo")
+pragma(no_typeinfo)
 struct Array
 {
     size_t length;
--- a/lphobos/internal/switch.d	Mon Aug 04 19:08:39 2008 +0200
+++ b/lphobos/internal/switch.d	Mon Aug 04 19:28:49 2008 +0200
@@ -422,5 +422,7 @@
     }
 }
 
-
-
+void _d_switch_error(string fn, int line)
+{
+    throw new Exception(fn~toString(line)~": switch missing default");
+}
--- a/lphobos/llvm/intrinsic.d	Mon Aug 04 19:08:39 2008 +0200
+++ b/lphobos/llvm/intrinsic.d	Mon Aug 04 19:28:49 2008 +0200
@@ -2,110 +2,110 @@
 
 // code generator intrinsics
 /*
-pragma(LLVM_internal, "intrinsic", "llvm.returnaddress")
+pragma(intrinsic, "llvm.returnaddress")
     void* llvm_returnaddress(uint level);
 */
-pragma(LLVM_internal, "intrinsic", "llvm.frameaddress")
+pragma(intrinsic, "llvm.frameaddress")
     void* llvm_frameaddress(uint level);
 /*
-pragma(LLVM_internal, "intrinsic", "llvm.stacksave")
+pragma(intrinsic, "llvm.stacksave")
     void* llvm_stacksave();
 
-pragma(LLVM_internal, "intrinsic", "llvm.stackrestore")
+pragma(intrinsic, "llvm.stackrestore")
     void llvm_stackrestore(void* ptr);
 
-pragma(LLVM_internal, "intrinsic", "llvm.pcmarker")
+pragma(intrinsic, "llvm.pcmarker")
     void llvm_pcmarker(uint id);
 
-pragma(LLVM_internal, "intrinsic", "llvm.prefetch")
+pragma(intrinsic, "llvm.prefetch")
     void llvm_prefetch(void* ptr, uint rw, uint locality);
 */
 
-pragma(LLVM_internal, "intrinsic", "llvm.readcyclecounter")
+pragma(intrinsic, "llvm.readcyclecounter")
     ulong readcyclecounter();
 
 // standard C intrinsics
-pragma(LLVM_internal, "intrinsic", "llvm.memcpy.i32")
+pragma(intrinsic, "llvm.memcpy.i32")
     void llvm_memcpy_i32(void* dst, void* src, uint len, uint alignment);
 
-pragma(LLVM_internal, "intrinsic", "llvm.memcpy.i64")
+pragma(intrinsic, "llvm.memcpy.i64")
     void llvm_memcpy_i64(void* dst, void* src, ulong len, uint alignment);
 
-pragma(LLVM_internal, "intrinsic", "llvm.memmove.i32")
+pragma(intrinsic, "llvm.memmove.i32")
     void llvm_memmove_i32(void* dst, void* src, uint len, uint alignment);
 
-pragma(LLVM_internal, "intrinsic", "llvm.memmove.i64")
+pragma(intrinsic, "llvm.memmove.i64")
     void llvm_memmove_i64(void* dst, void* src, ulong len, int alignment);
 
-pragma(LLVM_internal, "intrinsic", "llvm.memset.i32")
+pragma(intrinsic, "llvm.memset.i32")
     void llvm_memset_i32(void* dst, ubyte val, uint len, uint alignment);
 
-pragma(LLVM_internal, "intrinsic", "llvm.memset.i64")
+pragma(intrinsic, "llvm.memset.i64")
     void llvm_memset_i64(void* dst, ubyte val, ulong len, uint alignment);
 
-pragma(LLVM_internal, "intrinsic", "llvm.sqrt.f32")
+pragma(intrinsic, "llvm.sqrt.f32")
     float llvm_sqrt(float val);
 
-pragma(LLVM_internal, "intrinsic", "llvm.sqrt.f64")
+pragma(intrinsic, "llvm.sqrt.f64")
 {
     double llvm_sqrt(double val);
-    real llvm_sqrt(real val);
+    // real llvm_sqrt(real val);
 }
 
-pragma(LLVM_internal, "intrinsic", "llvm.powi.f32")
+pragma(intrinsic, "llvm.powi.f32")
     float llvm_powi(float val, int power);
 
-pragma(LLVM_internal, "intrinsic", "llvm.powi.f64")
+pragma(intrinsic, "llvm.powi.f64")
 {
     double llvm_powi(double val, int power);
-    real llvm_powi(real val, int power);
+    // real llvm_powi(real val, int power);
 }
 
 // bit manipulation intrinsics
-pragma(LLVM_internal, "intrinsic", "llvm.bswap.i16.i16")
+pragma(intrinsic, "llvm.bswap.i16.i16")
     ushort llvm_bswap(ushort val);
 
-pragma(LLVM_internal, "intrinsic", "llvm.bswap.i32.i32")
+pragma(intrinsic, "llvm.bswap.i32.i32")
     uint llvm_bswap(uint val);
 
-pragma(LLVM_internal, "intrinsic", "llvm.bswap.i64.i64")
+pragma(intrinsic, "llvm.bswap.i64.i64")
     ulong llvm_bswap(ulong val);
 
 /*
-pragma(LLVM_internal, "intrinsic", "llvm.ctpop.i8")
+pragma(intrinsic, "llvm.ctpop.i8")
     uint llvm_ctpop_i8(ubyte src);
 
-pragma(LLVM_internal, "intrinsic", "llvm.ctpop.i16")
+pragma(intrinsic, "llvm.ctpop.i16")
     uint llvm_ctpop_i16(ushort src);
 
-pragma(LLVM_internal, "intrinsic", "llvm.ctpop.i32")
+pragma(intrinsic, "llvm.ctpop.i32")
     uint llvm_ctpop_i32(uint src);
 
-pragma(LLVM_internal, "intrinsic", "llvm.ctpop.i64")
+pragma(intrinsic, "llvm.ctpop.i64")
     uint llvm_ctpop_i64(ulong src);
 
-pragma(LLVM_internal, "intrinsic", "llvm.ctlz.i8")
+pragma(intrinsic, "llvm.ctlz.i8")
     uint llvm_ctlz_i8(ubyte src);
 
-pragma(LLVM_internal, "intrinsic", "llvm.ctlz.i16")
+pragma(intrinsic, "llvm.ctlz.i16")
     uint llvm_ctlz_i16(ushort src);
 
-pragma(LLVM_internal, "intrinsic", "llvm.ctlz.i32")
+pragma(intrinsic, "llvm.ctlz.i32")
     uint llvm_ctlz_i32(uint src);
 
-pragma(LLVM_internal, "intrinsic", "llvm.ctlz.i64")
+pragma(intrinsic, "llvm.ctlz.i64")
     uint llvm_ctlz_i64(ulong src);
 
-pragma(LLVM_internal, "intrinsic", "llvm.cttz.i8")
+pragma(intrinsic, "llvm.cttz.i8")
     uint llvm_cttz_i8(ubyte src);
 
-pragma(LLVM_internal, "intrinsic", "llvm.cttz.i16")
+pragma(intrinsic, "llvm.cttz.i16")
     uint llvm_cttz_i16(ushort src);
 
-pragma(LLVM_internal, "intrinsic", "llvm.cttz.i32")
+pragma(intrinsic, "llvm.cttz.i32")
     uint llvm_cttz_i32(uint src);
 
-pragma(LLVM_internal, "intrinsic", "llvm.cttz.i64")
+pragma(intrinsic, "llvm.cttz.i64")
     uint llvm_cttz_i64(ulong src);
 */
 
@@ -114,7 +114,7 @@
 /*
 
 //declare i8 @llvm.atomic.lcs.i8.i8p.i8.i8( i8* <ptr>, i8 <cmp>, i8 <val> )
-pragma(LLVM_internal, "intrinsic", "llvm.atomic.lcs.i8.i8p.i8.i8")
+pragma(intrinsic, "llvm.atomic.lcs.i8.i8p.i8.i8")
     ubyte llvm_atomic_lcs_i8(void* ptr, ubyte cmp, ubyte val);
 
 declare i16 @llvm.atomic.lcs.i16.i16p.i16.i16( i16* <ptr>, i16 <cmp>, i16 <val> )
--- a/lphobos/object.d	Mon Aug 04 19:08:39 2008 +0200
+++ b/lphobos/object.d	Mon Aug 04 19:28:49 2008 +0200
@@ -1,4 +1,3 @@
-
 // Implementation is in internal\object.d
 
 module object;
@@ -173,11 +172,19 @@
     void function() ctor;
     void function() dtor;
     void function() unitTest;
+    void* xgetMembers;
+    void function() ictor;
 
     // Return collection of all modules in the program.
-    static ModuleInfo[] modules();
+    static int opApply(int delegate(ref ModuleInfo));
 }
 
+struct ModuleReference {
+    ModuleReference* next;
+    ModuleInfo mod;
+}
+extern(C) extern ModuleReference* _Dmodule_ref;
+
 // Recoverable errors
 
 class Exception : Object
@@ -198,4 +205,3 @@
     this(string msg);
     this(string msg, Error next);
 }
-
--- a/lphobos/phobos.d	Mon Aug 04 19:08:39 2008 +0200
+++ b/lphobos/phobos.d	Mon Aug 04 19:28:49 2008 +0200
@@ -27,7 +27,12 @@
 std.c.stdio,
 std.c.stdlib,
 std.c.string,
-std.c.time;
+std.c.time,
+std.file,
+std.date,
+std.socket,
+std.zlib,
+std.cstream;
 
 version(linux) {
     import
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lphobos/std/bitarray.d	Mon Aug 04 19:28:49 2008 +0200
@@ -0,0 +1,955 @@
+/***********************
+ * Macros:
+ *	WIKI = StdBitarray
+ */
+
+module std.bitarray;
+
+//debug = bitarray;		// uncomment to turn on debugging printf's
+
+private import std.intrinsic;
+
+/**
+ * An array of bits.
+ */
+
+struct BitArray
+{
+    size_t len;
+    uint* ptr;
+
+    size_t dim()
+    {
+	return (len + 31) / 32;
+    }
+
+    size_t length()
+    {
+	return len;
+    }
+
+    void length(size_t newlen)
+    {
+	if (newlen != len)
+	{
+	    size_t olddim = dim();
+	    size_t newdim = (newlen + 31) / 32;
+
+	    if (newdim != olddim)
+	    {
+		// Create a fake array so we can use D's realloc machinery
+		uint[] b = ptr[0 .. olddim];
+		b.length = newdim;		// realloc
+		ptr = b.ptr;
+		if (newdim & 31)
+		{   // Set any pad bits to 0
+		    ptr[newdim - 1] &= ~(~0 << (newdim & 31));
+		}
+	    }
+
+	    len = newlen;
+	}
+    }
+
+    /**********************************************
+     * Support for [$(I index)] operation for BitArray.
+     */
+    bool opIndex(size_t i)
+    in
+    {
+	assert(i < len);
+    }
+    body
+    {
+	return cast(bool)bt(ptr, i);
+    }
+
+    /** ditto */
+    bool opIndexAssign(bool b, size_t i)
+    in
+    {
+	assert(i < len);
+    }
+    body
+    {
+	if (b)
+	    bts(ptr, i);
+	else
+	    btr(ptr, i);
+	return b;
+    }
+
+    /**********************************************
+     * Support for array.dup property for BitArray.
+     */
+    BitArray dup()
+    {
+	BitArray ba;
+
+	uint[] b = ptr[0 .. dim].dup;
+	ba.len = len;
+	ba.ptr = b.ptr;
+	return ba;
+    }
+
+    unittest
+    {
+	BitArray a;
+	BitArray b;
+	int i;
+
+	debug(bitarray) printf("BitArray.dup.unittest\n");
+
+	a.length = 3;
+	a[0] = 1; a[1] = 0; a[2] = 1;
+	b = a.dup;
+	assert(b.length == 3);
+	for (i = 0; i < 3; i++)
+	{   debug(bitarray) printf("b[%d] = %d\n", i, b[i]);
+	    assert(b[i] == (((i ^ 1) & 1) ? true : false));
+	}
+    }
+
+    /**********************************************
+     * Support for foreach loops for BitArray.
+     */
+    int opApply(int delegate(inout bool) dg)
+    {
+	int result;
+
+	for (size_t i = 0; i < len; i++)
+	{   bool b = opIndex(i);
+	    result = dg(b);
+	    (*this)[i] = b;
+	    if (result)
+		break;
+	}
+	return result;
+    }
+
+    /** ditto */
+    int opApply(int delegate(inout size_t, inout bool) dg)
+    {
+	int result;
+
+	for (size_t i = 0; i < len; i++)
+	{   bool b = opIndex(i);
+	    result = dg(i, b);
+	    (*this)[i] = b;
+	    if (result)
+		break;
+	}
+	return result;
+    }
+
+    unittest
+    {
+	debug(bitarray) printf("BitArray.opApply unittest\n");
+
+	static bool[] ba = [1,0,1];
+
+	BitArray a; a.init(ba);
+
+	int i;
+	foreach (b;a)
+	{
+	    switch (i)
+	    {	case 0: assert(b == true); break;
+		case 1: assert(b == false); break;
+		case 2: assert(b == true); break;
+		default: assert(0);
+	    }
+	    i++;
+	}
+
+	foreach (j,b;a)
+	{
+	    switch (j)
+	    {	case 0: assert(b == true); break;
+		case 1: assert(b == false); break;
+		case 2: assert(b == true); break;
+		default: assert(0);
+	    }
+	}
+    }
+
+
+    /**********************************************
+     * Support for array.reverse property for BitArray.
+     */
+
+    BitArray reverse()
+	out (result)
+	{
+	    assert(result == *this);
+	}
+	body
+	{
+	    if (len >= 2)
+	    {
+		bool t;
+		size_t lo, hi;
+
+		lo = 0;
+		hi = len - 1;
+		for (; lo < hi; lo++, hi--)
+		{
+		    t = (*this)[lo];
+		    (*this)[lo] = (*this)[hi];
+		    (*this)[hi] = t;
+		}
+	    }
+	    return *this;
+	}
+
+    unittest
+    {
+	debug(bitarray) printf("BitArray.reverse.unittest\n");
+
+	BitArray b;
+	static bool[5] data = [1,0,1,1,0];
+	int i;
+
+	b.init(data);
+	b.reverse;
+	for (i = 0; i < data.length; i++)
+	{
+	    assert(b[i] == data[4 - i]);
+	}
+    }
+
+
+    /**********************************************
+     * Support for array.sort property for BitArray.
+     */
+
+    BitArray sort()
+	out (result)
+	{
+	    assert(result == *this);
+	}
+	body
+	{
+	    if (len >= 2)
+	    {
+		size_t lo, hi;
+
+		lo = 0;
+		hi = len - 1;
+		while (1)
+		{
+		    while (1)
+		    {
+			if (lo >= hi)
+			    goto Ldone;
+			if ((*this)[lo] == true)
+			    break;
+			lo++;
+		    }
+
+		    while (1)
+		    {
+			if (lo >= hi)
+			    goto Ldone;
+			if ((*this)[hi] == false)
+			    break;
+			hi--;
+		    }
+
+		    (*this)[lo] = false;
+		    (*this)[hi] = true;
+
+		    lo++;
+		    hi--;
+		}
+	    Ldone:
+		;
+	    }
+	    return *this;
+	}
+
+    unittest
+    {
+	debug(bitarray) printf("BitArray.sort.unittest\n");
+
+	static uint x = 0b1100011000;
+	static BitArray ba = { 10, &x };
+	ba.sort;
+	for (size_t i = 0; i < 6; i++)
+	    assert(ba[i] == false);
+	for (size_t i = 6; i < 10; i++)
+	    assert(ba[i] == true);
+    }
+
+
+    /***************************************
+     * Support for operators == and != for bit arrays.
+     */
+
+    int opEquals(BitArray a2)
+    {   size_t i;
+
+	if (this.length != a2.length)
+	    return 0;		// not equal
+	uint *p1 = cast(uint*)this.ptr;
+	uint *p2 = cast(uint*)a2.ptr;
+	size_t n = this.length / (8 * uint.sizeof);
+	for (i = 0; i < n; i++)
+	{
+	    if (p1[i] != p2[i])
+		return 0;		// not equal
+	}
+
+	uint mask;
+
+	n = this.length & ((8 * uint.sizeof) - 1);
+	mask = (1 << n) - 1;
+	//printf("i = %d, n = %d, mask = %x, %x, %x\n", i, n, mask, p1[i], p2[i]);
+	return (mask == 0) || (p1[i] & mask) == (p2[i] & mask);
+    }
+
+    unittest
+    {
+	debug(bitarray) printf("BitArray.opEquals unittest\n");
+
+	static bool[] ba = [1,0,1,0,1];
+	static bool[] bb = [1,0,1];
+	static bool[] bc = [1,0,1,0,1,0,1];
+	static bool[] bd = [1,0,1,1,1];
+	static bool[] be = [1,0,1,0,1];
+
+	BitArray a; a.init(ba);
+	BitArray b; b.init(bb);
+	BitArray c; c.init(bc);
+	BitArray d; d.init(bd);
+	BitArray e; e.init(be);
+
+	assert(a != b);
+	assert(a != c);
+	assert(a != d);
+	assert(a == e);
+    }
+
+    /***************************************
+     * Implement comparison operators.
+     */
+
+    int opCmp(BitArray a2)
+    {
+	size_t len;
+	size_t i;
+
+	len = this.length;
+	if (a2.length < len)
+	    len = a2.length;
+	uint* p1 = cast(uint*)this.ptr;
+	uint* p2 = cast(uint*)a2.ptr;
+	size_t n = len / (8 * uint.sizeof);
+	for (i = 0; i < n; i++)
+	{
+	    if (p1[i] != p2[i])
+		break;		// not equal
+	}
+	/*	
+	for (uint j = i * 8; j < len; j++)
+	{   ubyte mask = cast(ubyte)(1 << j);
+	    int c;
+
+	    c = cast(int)(p1[i] & mask) - cast(int)(p2[i] & mask);
+	    if (c)
+		return c;
+	}
+	*/
+	uint mask = 1;
+	for (size_t j = i * (8 * uint.sizeof); j < len; j++)
+	{   int c;
+
+	    c = cast(int)(p1[i] & mask) - cast(int)(p2[i] & mask);
+	    if (c)
+		return c;
+	    mask <<= 1;
+	}
+	ptrdiff_t c = cast(ptrdiff_t)this.len - cast(ptrdiff_t)a2.length;
+	if (c < 0)
+	    return -1;
+	else if (c > 0)
+	    return 1;
+	return 0;
+    }
+
+    unittest
+    {
+	debug(bitarray) printf("BitArray.opCmp unittest\n");
+
+	static bool[] ba = [1,0,1,0,1];
+	static bool[] bb = [1,0,1];
+	static bool[] bc = [1,0,1,0,1,0,1];
+	static bool[] bd = [1,0,1,1,1];
+	static bool[] be = [1,0,1,0,1];
+
+	BitArray a; a.init(ba);
+	BitArray b; b.init(bb);
+	BitArray c; c.init(bc);
+	BitArray d; d.init(bd);
+	BitArray e; e.init(be);
+
+	assert(a >  b);
+	assert(a >= b);
+	assert(a <  c);
+	assert(a <= c);
+	assert(a <  d);
+	assert(a <= d);
+	assert(a == e);
+	assert(a <= e);
+	assert(a >= e);
+    }
+
+    /***************************************
+     * Set BitArray to contents of ba[]
+     */
+
+    void init(bool[] ba)
+    {
+	length = ba.length;
+	foreach (i, b; ba)
+	{
+	    (*this)[i] = b;
+	}
+    }
+
+
+    /***************************************
+     * Map BitArray onto v[], with numbits being the number of bits
+     * in the array. Does not copy the data.
+     *
+     * This is the inverse of opCast.
+     */
+    void init(void[] v, size_t numbits)
+    in
+    {
+	assert(numbits <= v.length * 8);
+	assert((v.length & 3) == 0);
+    }
+    body
+    {
+	ptr = cast(uint*)v.ptr;
+	len = numbits;
+    }
+
+    unittest
+    {
+	debug(bitarray) printf("BitArray.init unittest\n");
+
+	static bool[] ba = [1,0,1,0,1];
+
+	BitArray a; a.init(ba);
+	BitArray b;
+	void[] v;
+
+	v = cast(void[])a;
+	b.init(v, a.length);
+
+	assert(b[0] == 1);
+	assert(b[1] == 0);
+	assert(b[2] == 1);
+	assert(b[3] == 0);
+	assert(b[4] == 1);
+
+	a[0] = 0;
+	assert(b[0] == 0);
+
+	assert(a == b);
+    }
+
+    /***************************************
+     * Convert to void[].
+     */
+    void[] opCast()
+    {
+	return cast(void[])ptr[0 .. dim];
+    }
+
+    unittest
+    {
+	debug(bitarray) printf("BitArray.opCast unittest\n");
+
+	static bool[] ba = [1,0,1,0,1];
+
+	BitArray a; a.init(ba);
+	void[] v = cast(void[])a;
+
+	assert(v.length == a.dim * uint.sizeof);
+    }
+
+    /***************************************
+     * Support for unary operator ~ for bit arrays.
+     */
+    BitArray opCom()
+    {
+	auto dim = this.dim();
+
+	BitArray result;
+
+	result.length = len;
+	for (size_t i = 0; i < dim; i++)
+	    result.ptr[i] = ~this.ptr[i];
+	if (len & 31)
+	    result.ptr[dim - 1] &= ~(~0 << (len & 31));
+	return result;
+    }
+
+    unittest
+    {
+	debug(bitarray) printf("BitArray.opCom unittest\n");
+
+	static bool[] ba = [1,0,1,0,1];
+
+	BitArray a; a.init(ba);
+	BitArray b = ~a;
+
+	assert(b[0] == 0);
+	assert(b[1] == 1);
+	assert(b[2] == 0);
+	assert(b[3] == 1);
+	assert(b[4] == 0);
+    }
+
+
+    /***************************************
+     * Support for binary operator & for bit arrays.
+     */
+    BitArray opAnd(BitArray e2)
+    in
+    {
+	assert(len == e2.length);
+    }
+    body
+    {
+	auto dim = this.dim();
+
+	BitArray result;
+
+	result.length = len;
+	for (size_t i = 0; i < dim; i++)
+	    result.ptr[i] = this.ptr[i] & e2.ptr[i];
+	return result;
+    }
+
+    unittest
+    {
+	debug(bitarray) printf("BitArray.opAnd unittest\n");
+
+	static bool[] ba = [1,0,1,0,1];
+	static bool[] bb = [1,0,1,1,0];
+
+	BitArray a; a.init(ba);
+	BitArray b; b.init(bb);
+
+	BitArray c = a & b;
+
+	assert(c[0] == 1);
+	assert(c[1] == 0);
+	assert(c[2] == 1);
+	assert(c[3] == 0);
+	assert(c[4] == 0);
+    }
+
+
+    /***************************************
+     * Support for binary operator | for bit arrays.
+     */
+    BitArray opOr(BitArray e2)
+    in
+    {
+	assert(len == e2.length);
+    }
+    body
+    {
+	auto dim = this.dim();
+
+	BitArray result;
+
+	result.length = len;
+	for (size_t i = 0; i < dim; i++)
+	    result.ptr[i] = this.ptr[i] | e2.ptr[i];
+	return result;
+    }
+
+    unittest
+    {
+	debug(bitarray) printf("BitArray.opOr unittest\n");
+
+	static bool[] ba = [1,0,1,0,1];
+	static bool[] bb = [1,0,1,1,0];
+
+	BitArray a; a.init(ba);
+	BitArray b; b.init(bb);
+
+	BitArray c = a | b;
+
+	assert(c[0] == 1);
+	assert(c[1] == 0);
+	assert(c[2] == 1);
+	assert(c[3] == 1);
+	assert(c[4] == 1);
+    }
+
+
+    /***************************************
+     * Support for binary operator ^ for bit arrays.
+     */
+    BitArray opXor(BitArray e2)
+    in
+    {
+	assert(len == e2.length);
+    }
+    body
+    {
+	auto dim = this.dim();
+
+	BitArray result;
+
+	result.length = len;
+	for (size_t i = 0; i < dim; i++)
+	    result.ptr[i] = this.ptr[i] ^ e2.ptr[i];
+	return result;
+    }
+
+    unittest
+    {
+	debug(bitarray) printf("BitArray.opXor unittest\n");
+
+	static bool[] ba = [1,0,1,0,1];
+	static bool[] bb = [1,0,1,1,0];
+
+	BitArray a; a.init(ba);
+	BitArray b; b.init(bb);
+
+	BitArray c = a ^ b;
+
+	assert(c[0] == 0);
+	assert(c[1] == 0);
+	assert(c[2] == 0);
+	assert(c[3] == 1);
+	assert(c[4] == 1);
+    }
+
+
+    /***************************************
+     * Support for binary operator - for bit arrays.
+     *
+     * $(I a - b) for BitArrays means the same thing as $(I a &amp; ~b).
+     */
+    BitArray opSub(BitArray e2)
+    in
+    {
+	assert(len == e2.length);
+    }
+    body
+    {
+	auto dim = this.dim();
+
+	BitArray result;
+
+	result.length = len;
+	for (size_t i = 0; i < dim; i++)
+	    result.ptr[i] = this.ptr[i] & ~e2.ptr[i];
+	return result;
+    }
+
+    unittest
+    {
+	debug(bitarray) printf("BitArray.opSub unittest\n");
+
+	static bool[] ba = [1,0,1,0,1];
+	static bool[] bb = [1,0,1,1,0];
+
+	BitArray a; a.init(ba);
+	BitArray b; b.init(bb);
+
+	BitArray c = a - b;
+
+	assert(c[0] == 0);
+	assert(c[1] == 0);
+	assert(c[2] == 0);
+	assert(c[3] == 0);
+	assert(c[4] == 1);
+    }
+
+
+    /***************************************
+     * Support for operator &= bit arrays.
+     */
+    BitArray opAndAssign(BitArray e2)
+    in
+    {
+	assert(len == e2.length);
+    }
+    body
+    {
+	auto dim = this.dim();
+
+	for (size_t i = 0; i < dim; i++)
+	    ptr[i] &= e2.ptr[i];
+	return *this;
+    }
+
+    unittest
+    {
+	debug(bitarray) printf("BitArray.opAndAssign unittest\n");
+
+	static bool[] ba = [1,0,1,0,1];
+	static bool[] bb = [1,0,1,1,0];
+
+	BitArray a; a.init(ba);
+	BitArray b; b.init(bb);
+
+	a &= b;
+	assert(a[0] == 1);
+	assert(a[1] == 0);
+	assert(a[2] == 1);
+	assert(a[3] == 0);
+	assert(a[4] == 0);
+    }
+
+
+    /***************************************
+     * Support for operator |= for bit arrays.
+     */
+    BitArray opOrAssign(BitArray e2)
+    in
+    {
+	assert(len == e2.length);
+    }
+    body
+    {
+	auto dim = this.dim();
+
+	for (size_t i = 0; i < dim; i++)
+	    ptr[i] |= e2.ptr[i];
+	return *this;
+    }
+
+    unittest
+    {
+	debug(bitarray) printf("BitArray.opOrAssign unittest\n");
+
+	static bool[] ba = [1,0,1,0,1];
+	static bool[] bb = [1,0,1,1,0];
+
+	BitArray a; a.init(ba);
+	BitArray b; b.init(bb);
+
+	a |= b;
+	assert(a[0] == 1);
+	assert(a[1] == 0);
+	assert(a[2] == 1);
+	assert(a[3] == 1);
+	assert(a[4] == 1);
+    }
+
+    /***************************************
+     * Support for operator ^= for bit arrays.
+     */
+    BitArray opXorAssign(BitArray e2)
+    in
+    {
+	assert(len == e2.length);
+    }
+    body
+    {
+	auto dim = this.dim();
+
+	for (size_t i = 0; i < dim; i++)
+	    ptr[i] ^= e2.ptr[i];
+	return *this;
+    }
+
+    unittest
+    {
+	debug(bitarray) printf("BitArray.opXorAssign unittest\n");
+
+	static bool[] ba = [1,0,1,0,1];
+	static bool[] bb = [1,0,1,1,0];
+
+	BitArray a; a.init(ba);
+	BitArray b; b.init(bb);
+
+	a ^= b;
+	assert(a[0] == 0);
+	assert(a[1] == 0);
+	assert(a[2] == 0);
+	assert(a[3] == 1);
+	assert(a[4] == 1);
+    }
+
+    /***************************************
+     * Support for operator -= for bit arrays.
+     *
+     * $(I a -= b) for BitArrays means the same thing as $(I a &amp;= ~b).
+     */
+    BitArray opSubAssign(BitArray e2)
+    in
+    {
+	assert(len == e2.length);
+    }
+    body
+    {
+	auto dim = this.dim();
+
+	for (size_t i = 0; i < dim; i++)
+	    ptr[i] &= ~e2.ptr[i];
+	return *this;
+    }
+
+    unittest
+    {
+	debug(bitarray) printf("BitArray.opSubAssign unittest\n");
+
+	static bool[] ba = [1,0,1,0,1];
+	static bool[] bb = [1,0,1,1,0];
+
+	BitArray a; a.init(ba);
+	BitArray b; b.init(bb);
+
+	a -= b;
+	assert(a[0] == 0);
+	assert(a[1] == 0);
+	assert(a[2] == 0);
+	assert(a[3] == 0);
+	assert(a[4] == 1);
+    }
+
+    /***************************************
+     * Support for operator ~= for bit arrays.
+     */
+
+    BitArray opCatAssign(bool b)
+    {
+	length = len + 1;
+	(*this)[len - 1] = b;
+	return *this;
+    }
+
+    unittest
+    {
+	debug(bitarray) printf("BitArray.opCatAssign unittest\n");
+
+	static bool[] ba = [1,0,1,0,1];
+
+	BitArray a; a.init(ba);
+	BitArray b;
+
+	b = (a ~= true);
+	assert(a[0] == 1);
+	assert(a[1] == 0);
+	assert(a[2] == 1);
+	assert(a[3] == 0);
+	assert(a[4] == 1);
+	assert(a[5] == 1);
+
+	assert(b == a);
+    }
+
+    /***************************************
+     * ditto
+     */
+
+    BitArray opCatAssign(BitArray b)
+    {
+	auto istart = len;
+	length = len + b.length;
+	for (auto i = istart; i < len; i++)
+	    (*this)[i] = b[i - istart];
+	return *this;
+    }
+
+    unittest
+    {
+	debug(bitarray) printf("BitArray.opCatAssign unittest\n");
+
+	static bool[] ba = [1,0];
+	static bool[] bb = [0,1,0];
+
+	BitArray a; a.init(ba);
+	BitArray b; b.init(bb);
+	BitArray c;
+
+	c = (a ~= b);
+	assert(a.length == 5);
+	assert(a[0] == 1);
+	assert(a[1] == 0);
+	assert(a[2] == 0);
+	assert(a[3] == 1);
+	assert(a[4] == 0);
+
+	assert(c == a);
+    }
+
+    /***************************************
+     * Support for binary operator ~ for bit arrays.
+     */
+    BitArray opCat(bool b)
+    {
+	BitArray r;
+
+	r = this.dup;
+	r.length = len + 1;
+	r[len] = b;
+	return r;
+    }
+
+    /** ditto */
+    BitArray opCat_r(bool b)
+    {
+	BitArray r;
+
+	r.length = len + 1;
+	r[0] = b;
+	for (size_t i = 0; i < len; i++)
+	    r[1 + i] = (*this)[i];
+	return r;
+    }
+
+    /** ditto */
+    BitArray opCat(BitArray b)
+    {
+	BitArray r;
+
+	r = this.dup();
+	r ~= b;
+	return r;
+    }
+
+    unittest
+    {
+	debug(bitarray) printf("BitArray.opCat unittest\n");
+
+	static bool[] ba = [1,0];
+	static bool[] bb = [0,1,0];
+
+	BitArray a; a.init(ba);
+	BitArray b; b.init(bb);
+	BitArray c;
+
+	c = (a ~ b);
+	assert(c.length == 5);
+	assert(c[0] == 1);
+	assert(c[1] == 0);
+	assert(c[2] == 0);
+	assert(c[3] == 1);
+	assert(c[4] == 0);
+
+	c = (a ~ true);
+	assert(c.length == 3);
+	assert(c[0] == 1);
+	assert(c[1] == 0);
+	assert(c[2] == 1);
+
+	c = (false ~ a);
+	assert(c.length == 3);
+	assert(c[0] == 0);
+	assert(c[1] == 1);
+	assert(c[2] == 0);
+    }
+}
--- a/lphobos/std/c/stdarg.d	Mon Aug 04 19:08:39 2008 +0200
+++ b/lphobos/std/c/stdarg.d	Mon Aug 04 19:28:49 2008 +0200
@@ -13,14 +13,14 @@
 
 public import llvm.va_list;
 
-pragma(LLVM_internal, "va_start")
+pragma(va_start)
     void va_start(T)(va_list ap, ref T);
 
-pragma(LLVM_internal, "va_arg")
+pragma(va_arg)
     T va_arg(T)(va_list ap);
 
-pragma(LLVM_internal, "va_intrinsic", "llvm.va_end")
+pragma(va_end)
     void va_end(va_list args);
 
-pragma(LLVM_internal, "va_intrinsic", "llvm.va_copy")
+pragma(va_copy)
     void va_copy(va_list dst, va_list src);
--- a/lphobos/std/c/stdlib.d	Mon Aug 04 19:08:39 2008 +0200
+++ b/lphobos/std/c/stdlib.d	Mon Aug 04 19:28:49 2008 +0200
@@ -42,7 +42,7 @@
 
     int system(char *);
 
-    pragma(LLVM_internal, "alloca")
+    pragma(alloca)
     void *alloca(uint);	///
 
     void *calloc(size_t, size_t);	///
@@ -64,8 +64,11 @@
     int    random(int num);	/// ditto
     void   randomize();	/// ditto
 
-    int getErrno();	/// ditto
-    int setErrno(int);	/// ditto
+    int* __errno_location();
+    int getErrno() { return *__errno_location(); }
+    int setErrno(int i) { return *__errno_location = i; }
+    //int getErrno();	/// ditto
+    //int setErrno(int);	/// ditto
 
 const int ERANGE = 34;	// on both Windows and linux
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lphobos/std/c/windows/com.d	Mon Aug 04 19:28:49 2008 +0200
@@ -0,0 +1,246 @@
+
+module std.c.windows.com;
+
+private import std.c.windows.windows;
+private import std.string;
+
+alias WCHAR OLECHAR;
+alias OLECHAR *LPOLESTR;
+alias OLECHAR *LPCOLESTR;
+
+enum
+{
+	rmm = 23,	// OLE 2 version number info
+	rup = 639,
+}
+
+enum : int
+{
+	S_OK = 0,
+	S_FALSE = 0x00000001,
+	NOERROR = 0,
+	E_NOTIMPL     = cast(int)0x80004001,
+	E_NOINTERFACE = cast(int)0x80004002,
+	E_POINTER     = cast(int)0x80004003,
+	E_ABORT       = cast(int)0x80004004,
+	E_FAIL        = cast(int)0x80004005,
+	E_HANDLE      = cast(int)0x80070006,
+	CLASS_E_NOAGGREGATION = cast(int)0x80040110,
+	E_OUTOFMEMORY = cast(int)0x8007000E,
+	E_INVALIDARG  = cast(int)0x80070057,
+	E_UNEXPECTED  = cast(int)0x8000FFFF,
+}
+
+struct GUID {          // size is 16
+    align(1):
+	DWORD Data1;
+	WORD  Data2;
+	WORD  Data3;
+	BYTE  Data4[8];
+}
+
+enum
+{
+	CLSCTX_INPROC_SERVER	= 0x1,
+	CLSCTX_INPROC_HANDLER	= 0x2,
+	CLSCTX_LOCAL_SERVER	= 0x4,
+	CLSCTX_INPROC_SERVER16	= 0x8,
+	CLSCTX_REMOTE_SERVER	= 0x10,
+	CLSCTX_INPROC_HANDLER16	= 0x20,
+	CLSCTX_INPROC_SERVERX86	= 0x40,
+	CLSCTX_INPROC_HANDLERX86 = 0x80,
+
+	CLSCTX_INPROC = (CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER),
+	CLSCTX_ALL = (CLSCTX_INPROC_SERVER| CLSCTX_INPROC_HANDLER| CLSCTX_LOCAL_SERVER),
+	CLSCTX_SERVER = (CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER),
+}
+
+alias GUID IID;
+alias GUID CLSID;
+
+extern (C)
+{
+    extern IID IID_IUnknown;
+    extern IID IID_IClassFactory;
+    extern IID IID_IMarshal;
+    extern IID IID_IMallocSpy;
+    extern IID IID_IStdMarshalInfo;
+    extern IID IID_IExternalConnection;
+    extern IID IID_IMultiQI;
+    extern IID IID_IEnumUnknown;
+    extern IID IID_IBindCtx;
+    extern IID IID_IEnumMoniker;
+    extern IID IID_IRunnableObject;
+    extern IID IID_IRunningObjectTable;
+    extern IID IID_IPersist;
+    extern IID IID_IPersistStream;
+    extern IID IID_IMoniker;
+    extern IID IID_IROTData;
+    extern IID IID_IEnumString;
+    extern IID IID_ISequentialStream;
+    extern IID IID_IStream;
+    extern IID IID_IEnumSTATSTG;
+    extern IID IID_IStorage;
+    extern IID IID_IPersistFile;
+    extern IID IID_IPersistStorage;
+    extern IID IID_ILockBytes;
+    extern IID IID_IEnumFORMATETC;
+    extern IID IID_IEnumSTATDATA;
+    extern IID IID_IRootStorage;
+    extern IID IID_IAdviseSink;
+    extern IID IID_IAdviseSink2;
+    extern IID IID_IDataObject;
+    extern IID IID_IDataAdviseHolder;
+    extern IID IID_IMessageFilter;
+    extern IID IID_IRpcChannelBuffer;
+    extern IID IID_IRpcProxyBuffer;
+    extern IID IID_IRpcStubBuffer;
+    extern IID IID_IPSFactoryBuffer;
+    extern IID IID_IPropertyStorage;
+    extern IID IID_IPropertySetStorage;
+    extern IID IID_IEnumSTATPROPSTG;
+    extern IID IID_IEnumSTATPROPSETSTG;
+    extern IID IID_IFillLockBytes;
+    extern IID IID_IProgressNotify;
+    extern IID IID_ILayoutStorage;
+    extern IID GUID_NULL;
+    extern IID IID_IRpcChannel;
+    extern IID IID_IRpcStub;
+    extern IID IID_IStubManager;
+    extern IID IID_IRpcProxy;
+    extern IID IID_IProxyManager;
+    extern IID IID_IPSFactory;
+    extern IID IID_IInternalMoniker;
+    extern IID IID_IDfReserved1;
+    extern IID IID_IDfReserved2;
+    extern IID IID_IDfReserved3;
+    extern IID IID_IStub;
+    extern IID IID_IProxy;
+    extern IID IID_IEnumGeneric;
+    extern IID IID_IEnumHolder;
+    extern IID IID_IEnumCallback;
+    extern IID IID_IOleManager;
+    extern IID IID_IOlePresObj;
+    extern IID IID_IDebug;
+    extern IID IID_IDebugStream;
+    extern IID IID_StdOle;
+    extern IID IID_ICreateTypeInfo;
+    extern IID IID_ICreateTypeInfo2;
+    extern IID IID_ICreateTypeLib;
+    extern IID IID_ICreateTypeLib2;
+    extern IID IID_IDispatch;
+    extern IID IID_IEnumVARIANT;
+    extern IID IID_ITypeComp;
+    extern IID IID_ITypeInfo;
+    extern IID IID_ITypeInfo2;
+    extern IID IID_ITypeLib;
+    extern IID IID_ITypeLib2;
+    extern IID IID_ITypeChangeEvents;
+    extern IID IID_IErrorInfo;
+    extern IID IID_ICreateErrorInfo;
+    extern IID IID_ISupportErrorInfo;
+    extern IID IID_IOleAdviseHolder;
+    extern IID IID_IOleCache;
+    extern IID IID_IOleCache2;
+    extern IID IID_IOleCacheControl;
+    extern IID IID_IParseDisplayName;
+    extern IID IID_IOleContainer;
+    extern IID IID_IOleClientSite;
+    extern IID IID_IOleObject;
+    extern IID IID_IOleWindow;
+    extern IID IID_IOleLink;
+    extern IID IID_IOleItemContainer;
+    extern IID IID_IOleInPlaceUIWindow;
+    extern IID IID_IOleInPlaceActiveObject;
+    extern IID IID_IOleInPlaceFrame;
+    extern IID IID_IOleInPlaceObject;
+    extern IID IID_IOleInPlaceSite;
+    extern IID IID_IContinue;
+    extern IID IID_IViewObject;
+    extern IID IID_IViewObject2;
+    extern IID IID_IDropSource;
+    extern IID IID_IDropTarget;
+    extern IID IID_IEnumOLEVERB;
+}
+
+extern (Windows)
+{
+
+export
+{
+DWORD   CoBuildVersion();
+
+int StringFromGUID2(GUID *rguid, LPOLESTR lpsz, int cbMax);
+
+/* init/uninit */
+
+HRESULT CoInitialize(LPVOID pvReserved);
+void    CoUninitialize();
+DWORD   CoGetCurrentProcess();
+
+
+HRESULT CoCreateInstance(CLSID *rclsid, IUnknown UnkOuter,
+                    DWORD dwClsContext, IID* riid, void* ppv);
+
+//HINSTANCE CoLoadLibrary(LPOLESTR lpszLibName, BOOL bAutoFree);
+void    CoFreeLibrary(HINSTANCE hInst);
+void    CoFreeAllLibraries();
+void    CoFreeUnusedLibraries();
+}
+
+interface IUnknown
+{
+    HRESULT QueryInterface(IID* riid, void** pvObject);
+    ULONG AddRef();
+    ULONG Release();
+}
+
+interface IClassFactory : IUnknown
+{
+    HRESULT CreateInstance(IUnknown UnkOuter, IID* riid, void** pvObject);
+    HRESULT LockServer(BOOL fLock);
+}
+
+class ComObject : IUnknown
+{
+extern (Windows):
+    HRESULT QueryInterface(IID* riid, void** ppv)
+    {
+	if (*riid == IID_IUnknown)
+	{
+	    *ppv = cast(void*)cast(IUnknown)this;
+	    AddRef();
+	    return S_OK;
+	}
+	else
+	{   *ppv = null;
+	    return E_NOINTERFACE;
+	}
+    }
+
+    ULONG AddRef()
+    {
+	return InterlockedIncrement(&count);
+    }
+
+    ULONG Release()
+    {
+	LONG lRef = InterlockedDecrement(&count);
+	if (lRef == 0)
+	{
+	    // free object
+
+	    // If we delete this object, then the postinvariant called upon
+	    // return from Release() will fail.
+	    // Just let the GC reap it.
+	    //delete this;
+
+	    return 0;
+	}
+	return cast(ULONG)lRef;
+    }
+
+    LONG count = 0;		// object reference count
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lphobos/std/c/windows/stat.d	Mon Aug 04 19:28:49 2008 +0200
@@ -0,0 +1,49 @@
+
+/// Placed into public domain
+/// Author: Walter Bright
+
+module std.c.windows.stat;
+
+extern (C):
+
+// linux version is in std.c.linux.linux
+
+version (Windows)
+{
+const S_IFMT   = 0xF000;
+const S_IFDIR  = 0x4000;
+const S_IFCHR  = 0x2000;
+const S_IFIFO  = 0x1000;
+const S_IFREG  = 0x8000;
+const S_IREAD  = 0x0100;
+const S_IWRITE = 0x0080;
+const S_IEXEC  = 0x0040;
+const S_IFBLK  = 0x6000;
+const S_IFNAM  = 0x5000;
+
+int S_ISREG(int m)  { return (m & S_IFMT) == S_IFREG; }
+int S_ISBLK(int m)  { return (m & S_IFMT) == S_IFBLK; }
+int S_ISNAM(int m)  { return (m & S_IFMT) == S_IFNAM; }
+int S_ISDIR(int m)  { return (m & S_IFMT) == S_IFDIR; }
+int S_ISCHR(int m)  { return (m & S_IFMT) == S_IFCHR; }
+
+struct struct_stat
+{
+    short st_dev;
+    ushort st_ino;
+    ushort st_mode;
+    short st_nlink;
+    ushort st_uid;
+    ushort st_gid;
+    short st_rdev;
+    short dummy;
+    int st_size;
+    int st_atime;
+    int st_mtime;
+    int st_ctime;
+}
+
+int  stat(char *, struct_stat *);
+int  fstat(int, struct_stat *);
+int  _wstat(wchar *, struct_stat *);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lphobos/std/c/windows/windows.d	Mon Aug 04 19:28:49 2008 +0200
@@ -0,0 +1,2722 @@
+
+/* Windows is a registered trademark of Microsoft Corporation in the United
+States and other countries. */
+
+module std.c.windows.windows;
+
+version (Windows)
+{
+}
+else
+{
+    static assert(0);		// Windows only
+}
+
+extern (Windows)
+{
+    alias uint ULONG;
+    alias ULONG *PULONG;
+    alias ushort USHORT;
+    alias USHORT *PUSHORT;
+    alias ubyte UCHAR;
+    alias UCHAR *PUCHAR;
+    alias char *PSZ;
+    alias wchar WCHAR;
+
+    alias void VOID;
+    alias char CHAR;
+    alias short SHORT;
+    alias int LONG;
+    alias CHAR *LPSTR;
+    alias CHAR *PSTR;
+    alias CHAR *LPCSTR;
+    alias CHAR *PCSTR;
+    alias LPSTR LPTCH, PTCH;
+    alias LPSTR PTSTR, LPTSTR;
+    alias LPCSTR LPCTSTR;
+
+    alias WCHAR* LPWSTR, LPCWSTR, PCWSTR;
+
+    alias uint DWORD;
+    alias int BOOL;
+    alias ubyte BYTE;
+    alias ushort WORD;
+    alias float FLOAT;
+    alias FLOAT *PFLOAT;
+    alias BOOL *PBOOL;
+    alias BOOL *LPBOOL;
+    alias BYTE *PBYTE;
+    alias BYTE *LPBYTE;
+    alias int *PINT;
+    alias int *LPINT;
+    alias WORD *PWORD;
+    alias WORD *LPWORD;
+    alias int *LPLONG;
+    alias DWORD *PDWORD;
+    alias DWORD *LPDWORD;
+    alias void *LPVOID;
+    alias void *LPCVOID;
+
+    alias int INT;
+    alias uint UINT;
+    alias uint *PUINT;
+
+    typedef void *HANDLE;
+    alias void *PVOID;
+    alias HANDLE HGLOBAL;
+    alias HANDLE HLOCAL;
+    alias LONG HRESULT;
+    alias LONG SCODE;
+    alias HANDLE HINSTANCE;
+    alias HINSTANCE HMODULE;
+    alias HANDLE HWND;
+
+    alias HANDLE HGDIOBJ;
+    alias HANDLE HACCEL;
+    alias HANDLE HBITMAP;
+    alias HANDLE HBRUSH;
+    alias HANDLE HCOLORSPACE;
+    alias HANDLE HDC;
+    alias HANDLE HGLRC;
+    alias HANDLE HDESK;
+    alias HANDLE HENHMETAFILE;
+    alias HANDLE HFONT;
+    alias HANDLE HICON;
+    alias HANDLE HMENU;
+    alias HANDLE HMETAFILE;
+    alias HANDLE HPALETTE;
+    alias HANDLE HPEN;
+    alias HANDLE HRGN;
+    alias HANDLE HRSRC;
+    alias HANDLE HSTR;
+    alias HANDLE HTASK;
+    alias HANDLE HWINSTA;
+    alias HANDLE HKL;
+    alias HICON HCURSOR;
+
+    alias HANDLE HKEY;
+    alias HKEY *PHKEY;
+    alias DWORD ACCESS_MASK;
+    alias ACCESS_MASK *PACCESS_MASK;
+    alias ACCESS_MASK REGSAM;
+
+    alias int (*FARPROC)();
+
+    alias UINT WPARAM;
+    alias LONG LPARAM;
+    alias LONG LRESULT;
+
+    alias DWORD   COLORREF;
+    alias DWORD   *LPCOLORREF;
+    alias WORD    ATOM;
+
+version (0)
+{   // Properly prototyped versions
+    alias BOOL function(HWND, UINT, WPARAM, LPARAM) DLGPROC;
+    alias VOID function(HWND, UINT, UINT, DWORD) TIMERPROC;
+    alias BOOL function(HDC, LPARAM, int) GRAYSTRINGPROC;
+    alias BOOL function(HWND, LPARAM) WNDENUMPROC;
+    alias LRESULT function(int code, WPARAM wParam, LPARAM lParam) HOOKPROC;
+    alias VOID function(HWND, UINT, DWORD, LRESULT) SENDASYNCPROC;
+    alias BOOL function(HWND, LPCSTR, HANDLE) PROPENUMPROCA;
+    alias BOOL function(HWND, LPCWSTR, HANDLE) PROPENUMPROCW;
+    alias BOOL function(HWND, LPSTR, HANDLE, DWORD) PROPENUMPROCEXA;
+    alias BOOL function(HWND, LPWSTR, HANDLE, DWORD) PROPENUMPROCEXW;
+    alias int function(LPSTR lpch, int ichCurrent, int cch, int code)
+       EDITWORDBREAKPROCA;
+    alias int function(LPWSTR lpch, int ichCurrent, int cch, int code)
+       EDITWORDBREAKPROCW;
+    alias BOOL function(HDC hdc, LPARAM lData, WPARAM wData, int cx, int cy)
+       DRAWSTATEPROC;
+}
+else
+{
+    alias FARPROC DLGPROC;
+    alias FARPROC TIMERPROC;
+    alias FARPROC GRAYSTRINGPROC;
+    alias FARPROC WNDENUMPROC;
+    alias FARPROC HOOKPROC;
+    alias FARPROC SENDASYNCPROC;
+    alias FARPROC EDITWORDBREAKPROCA;
+    alias FARPROC EDITWORDBREAKPROCW;
+    alias FARPROC PROPENUMPROCA;
+    alias FARPROC PROPENUMPROCW;
+    alias FARPROC PROPENUMPROCEXA;
+    alias FARPROC PROPENUMPROCEXW;
+    alias FARPROC DRAWSTATEPROC;
+}
+
+WORD HIWORD(int l) { return cast(WORD)((l >> 16) & 0xFFFF); }
+WORD LOWORD(int l) { return cast(WORD)l; }
+bool FAILED(int status) { return status < 0; }
+bool SUCCEEDED(int Status) { return Status >= 0; }
+
+enum : int
+{
+    FALSE = 0,
+    TRUE = 1,
+}
+
+enum : uint
+{
+    MAX_PATH = 260,
+    HINSTANCE_ERROR = 32,
+}
+
+enum
+{
+	ERROR_SUCCESS =                    0,
+	ERROR_INVALID_FUNCTION =           1,
+	ERROR_FILE_NOT_FOUND =             2,
+	ERROR_PATH_NOT_FOUND =             3,
+	ERROR_TOO_MANY_OPEN_FILES =        4,
+	ERROR_ACCESS_DENIED =              5,
+	ERROR_INVALID_HANDLE =             6,
+	ERROR_NO_MORE_FILES =              18,
+	ERROR_MORE_DATA =		   234,
+	ERROR_NO_MORE_ITEMS =		   259,
+}
+
+enum
+{
+	DLL_PROCESS_ATTACH = 1,
+	DLL_THREAD_ATTACH =  2,
+	DLL_THREAD_DETACH =  3,
+	DLL_PROCESS_DETACH = 0,
+}
+
+enum
+{
+    FILE_BEGIN           = 0,
+    FILE_CURRENT         = 1,
+    FILE_END             = 2,
+}
+
+enum : uint
+{
+    DELETE =                           0x00010000,
+    READ_CONTROL =                     0x00020000,
+    WRITE_DAC =                        0x00040000,
+    WRITE_OWNER =                      0x00080000,
+    SYNCHRONIZE =                      0x00100000,
+
+    STANDARD_RIGHTS_REQUIRED =         0x000F0000,
+    STANDARD_RIGHTS_READ =             READ_CONTROL,
+    STANDARD_RIGHTS_WRITE =            READ_CONTROL,
+    STANDARD_RIGHTS_EXECUTE =          READ_CONTROL,
+    STANDARD_RIGHTS_ALL =              0x001F0000,
+    SPECIFIC_RIGHTS_ALL =              0x0000FFFF,
+    ACCESS_SYSTEM_SECURITY =           0x01000000,
+    MAXIMUM_ALLOWED =                  0x02000000,
+
+    GENERIC_READ                     = 0x80000000,
+    GENERIC_WRITE                    = 0x40000000,
+    GENERIC_EXECUTE                  = 0x20000000,
+    GENERIC_ALL                      = 0x10000000,
+}
+
+enum
+{
+    FILE_SHARE_READ                 = 0x00000001,
+    FILE_SHARE_WRITE                = 0x00000002,
+    FILE_SHARE_DELETE               = 0x00000004,  
+    FILE_ATTRIBUTE_READONLY         = 0x00000001,  
+    FILE_ATTRIBUTE_HIDDEN           = 0x00000002,  
+    FILE_ATTRIBUTE_SYSTEM           = 0x00000004,  
+    FILE_ATTRIBUTE_DIRECTORY        = 0x00000010,  
+    FILE_ATTRIBUTE_ARCHIVE          = 0x00000020,  
+    FILE_ATTRIBUTE_NORMAL           = 0x00000080,  
+    FILE_ATTRIBUTE_TEMPORARY        = 0x00000100,  
+    FILE_ATTRIBUTE_COMPRESSED       = 0x00000800,  
+    FILE_ATTRIBUTE_OFFLINE          = 0x00001000,  
+    FILE_NOTIFY_CHANGE_FILE_NAME    = 0x00000001,   
+    FILE_NOTIFY_CHANGE_DIR_NAME     = 0x00000002,   
+    FILE_NOTIFY_CHANGE_ATTRIBUTES   = 0x00000004,   
+    FILE_NOTIFY_CHANGE_SIZE         = 0x00000008,   
+    FILE_NOTIFY_CHANGE_LAST_WRITE   = 0x00000010,   
+    FILE_NOTIFY_CHANGE_LAST_ACCESS  = 0x00000020,   
+    FILE_NOTIFY_CHANGE_CREATION     = 0x00000040,   
+    FILE_NOTIFY_CHANGE_SECURITY     = 0x00000100,   
+    FILE_ACTION_ADDED               = 0x00000001,   
+    FILE_ACTION_REMOVED             = 0x00000002,   
+    FILE_ACTION_MODIFIED            = 0x00000003,   
+    FILE_ACTION_RENAMED_OLD_NAME    = 0x00000004,   
+    FILE_ACTION_RENAMED_NEW_NAME    = 0x00000005,   
+    FILE_CASE_SENSITIVE_SEARCH      = 0x00000001,  
+    FILE_CASE_PRESERVED_NAMES       = 0x00000002,  
+    FILE_UNICODE_ON_DISK            = 0x00000004,  
+    FILE_PERSISTENT_ACLS            = 0x00000008,  
+    FILE_FILE_COMPRESSION           = 0x00000010,  
+    FILE_VOLUME_IS_COMPRESSED       = 0x00008000,  
+}
+
+const DWORD MAILSLOT_NO_MESSAGE = cast(DWORD)-1;
+const DWORD MAILSLOT_WAIT_FOREVER = cast(DWORD)-1; 
+
+enum : uint
+{
+    FILE_FLAG_WRITE_THROUGH         = 0x80000000,
+    FILE_FLAG_OVERLAPPED            = 0x40000000,
+    FILE_FLAG_NO_BUFFERING          = 0x20000000,
+    FILE_FLAG_RANDOM_ACCESS         = 0x10000000,
+    FILE_FLAG_SEQUENTIAL_SCAN       = 0x08000000,
+    FILE_FLAG_DELETE_ON_CLOSE       = 0x04000000,
+    FILE_FLAG_BACKUP_SEMANTICS      = 0x02000000,
+    FILE_FLAG_POSIX_SEMANTICS       = 0x01000000,
+}
+
+enum
+{
+    CREATE_NEW          = 1,
+    CREATE_ALWAYS       = 2,
+    OPEN_EXISTING       = 3,
+    OPEN_ALWAYS         = 4,
+    TRUNCATE_EXISTING   = 5,
+}
+
+const HANDLE INVALID_HANDLE_VALUE = cast(HANDLE)-1;
+const DWORD INVALID_SET_FILE_POINTER = cast(DWORD)-1;
+const DWORD INVALID_FILE_SIZE = cast(DWORD)0xFFFFFFFF;
+
+struct OVERLAPPED {
+    DWORD   Internal;
+    DWORD   InternalHigh;
+    DWORD   Offset;
+    DWORD   OffsetHigh;
+    HANDLE  hEvent;
+}
+
+struct SECURITY_ATTRIBUTES {
+    DWORD nLength;
+    void *lpSecurityDescriptor;
+    BOOL bInheritHandle;
+}
+
+alias SECURITY_ATTRIBUTES* PSECURITY_ATTRIBUTES, LPSECURITY_ATTRIBUTES;
+
+struct FILETIME {
+    DWORD dwLowDateTime;
+    DWORD dwHighDateTime;
+}
+alias FILETIME* PFILETIME, LPFILETIME;
+
+struct WIN32_FIND_DATA {
+    DWORD dwFileAttributes;
+    FILETIME ftCreationTime;
+    FILETIME ftLastAccessTime;
+    FILETIME ftLastWriteTime;
+    DWORD nFileSizeHigh;
+    DWORD nFileSizeLow;
+    DWORD dwReserved0;
+    DWORD dwReserved1;
+    char   cFileName[MAX_PATH];
+    char   cAlternateFileName[ 14 ];
+}
+
+struct WIN32_FIND_DATAW {
+    DWORD dwFileAttributes;
+    FILETIME ftCreationTime;
+    FILETIME ftLastAccessTime;
+    FILETIME ftLastWriteTime;
+    DWORD nFileSizeHigh;
+    DWORD nFileSizeLow;
+    DWORD dwReserved0;
+    DWORD dwReserved1;
+    wchar  cFileName[ 260  ];
+    wchar  cAlternateFileName[ 14 ];
+}
+
+export
+{
+BOOL SetCurrentDirectoryA(LPCSTR lpPathName);
+BOOL SetCurrentDirectoryW(LPCWSTR lpPathName);
+DWORD GetCurrentDirectoryA(DWORD nBufferLength, LPSTR lpBuffer);
+DWORD GetCurrentDirectoryW(DWORD nBufferLength, LPWSTR lpBuffer);
+BOOL CreateDirectoryA(LPCSTR lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes);
+BOOL CreateDirectoryW(LPCWSTR lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes);
+BOOL CreateDirectoryExA(LPCSTR lpTemplateDirectory, LPCSTR lpNewDirectory, LPSECURITY_ATTRIBUTES lpSecurityAttributes);
+BOOL CreateDirectoryExW(LPCWSTR lpTemplateDirectory, LPCWSTR lpNewDirectory, LPSECURITY_ATTRIBUTES lpSecurityAttributes);
+BOOL RemoveDirectoryA(LPCSTR lpPathName);
+BOOL RemoveDirectoryW(LPCWSTR lpPathName);
+
+BOOL   CloseHandle(HANDLE hObject);
+
+HANDLE CreateFileA(char *lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
+	SECURITY_ATTRIBUTES *lpSecurityAttributes, DWORD dwCreationDisposition,
+	DWORD dwFlagsAndAttributes, HANDLE hTemplateFile);
+HANDLE CreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
+	SECURITY_ATTRIBUTES *lpSecurityAttributes, DWORD dwCreationDisposition,
+	DWORD dwFlagsAndAttributes, HANDLE hTemplateFile);
+
+BOOL   DeleteFileA(char *lpFileName);
+BOOL   DeleteFileW(LPCWSTR lpFileName);
+
+BOOL   FindClose(HANDLE hFindFile);
+HANDLE FindFirstFileA(char *lpFileName, WIN32_FIND_DATA* lpFindFileData);
+HANDLE FindFirstFileW(LPCWSTR lpFileName, WIN32_FIND_DATAW* lpFindFileData);
+BOOL   FindNextFileA(HANDLE hFindFile, WIN32_FIND_DATA* lpFindFileData);
+BOOL   FindNextFileW(HANDLE hFindFile, WIN32_FIND_DATAW* lpFindFileData);
+BOOL   GetExitCodeThread(HANDLE hThread, DWORD *lpExitCode);
+DWORD  GetLastError();
+DWORD  GetFileAttributesA(char *lpFileName);
+DWORD  GetFileAttributesW(wchar *lpFileName);
+DWORD  GetFileSize(HANDLE hFile, DWORD *lpFileSizeHigh);
+BOOL   CopyFileA(LPCSTR lpExistingFileName, LPCSTR lpNewFileName, BOOL bFailIfExists);
+BOOL   CopyFileW(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName, BOOL bFailIfExists);
+BOOL   MoveFileA(char *from, char *to);
+BOOL   MoveFileW(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName);
+BOOL   ReadFile(HANDLE hFile, void *lpBuffer, DWORD nNumberOfBytesToRead,
+	DWORD *lpNumberOfBytesRead, OVERLAPPED *lpOverlapped);
+DWORD  SetFilePointer(HANDLE hFile, LONG lDistanceToMove,
+	LONG *lpDistanceToMoveHigh, DWORD dwMoveMethod);
+BOOL   WriteFile(HANDLE hFile, void *lpBuffer, DWORD nNumberOfBytesToWrite,
+	DWORD *lpNumberOfBytesWritten, OVERLAPPED *lpOverlapped);
+DWORD  GetModuleFileNameA(HMODULE hModule, LPSTR lpFilename, DWORD nSize);
+}
+
+struct MEMORYSTATUS {
+    DWORD dwLength;
+    DWORD dwMemoryLoad;
+    DWORD dwTotalPhys;
+    DWORD dwAvailPhys;
+    DWORD dwTotalPageFile;
+    DWORD dwAvailPageFile;
+    DWORD dwTotalVirtual;
+    DWORD dwAvailVirtual;
+};
+alias MEMORYSTATUS *LPMEMORYSTATUS;
+
+
+export
+{
+ LONG  InterlockedIncrement(LPLONG lpAddend);
+ LONG  InterlockedDecrement(LPLONG lpAddend);
+ LONG  InterlockedExchange(LPLONG Target, LONG Value);
+ LONG  InterlockedExchangeAdd(LPLONG Addend, LONG Value);
+ PVOID InterlockedCompareExchange(PVOID *Destination, PVOID Exchange, PVOID Comperand);
+ BOOL  FreeResource(HGLOBAL hResData);
+ LPVOID LockResource(HGLOBAL hResData);
+}
+
+HMODULE LoadLibraryA(LPCSTR lpLibFileName);
+FARPROC GetProcAddress(HMODULE hModule, LPCSTR lpProcName);
+DWORD GetVersion();
+BOOL FreeLibrary(HMODULE hLibModule);
+void FreeLibraryAndExitThread(HMODULE hLibModule, DWORD dwExitCode);
+BOOL DisableThreadLibraryCalls(HMODULE hLibModule);
+
+//
+// Registry Specific Access Rights.
+//
+
+enum
+{
+	KEY_QUERY_VALUE =         0x0001,
+	KEY_SET_VALUE =           0x0002,
+	KEY_CREATE_SUB_KEY =      0x0004,
+	KEY_ENUMERATE_SUB_KEYS =  0x0008,
+	KEY_NOTIFY =              0x0010,
+	KEY_CREATE_LINK =         0x0020,
+
+	KEY_READ =       cast(int)((STANDARD_RIGHTS_READ | KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS | KEY_NOTIFY)   & ~SYNCHRONIZE),
+	KEY_WRITE =      cast(int)((STANDARD_RIGHTS_WRITE | KEY_SET_VALUE | KEY_CREATE_SUB_KEY) & ~SYNCHRONIZE),
+	KEY_EXECUTE =    cast(int)(KEY_READ & ~SYNCHRONIZE),
+	KEY_ALL_ACCESS = cast(int)((STANDARD_RIGHTS_ALL | KEY_QUERY_VALUE | KEY_SET_VALUE | KEY_CREATE_SUB_KEY | KEY_ENUMERATE_SUB_KEYS | KEY_NOTIFY | KEY_CREATE_LINK) & ~SYNCHRONIZE),
+}
+
+//
+// Key creation/open disposition
+//
+
+const int REG_CREATED_NEW_KEY =         0x00000001;   // New Registry Key created
+const int REG_OPENED_EXISTING_KEY =     0x00000002;   // Existing Key opened
+
+
+//
+//
+// Predefined Value Types.
+//
+enum
+{
+	REG_NONE =                    0,   // No value type
+	REG_SZ =                      1,   // Unicode nul terminated string
+	REG_EXPAND_SZ =               2,   // Unicode nul terminated string
+                                            // (with environment variable references)
+	REG_BINARY =                  3,   // Free form binary
+	REG_DWORD =                   4,   // 32-bit number
+	REG_DWORD_LITTLE_ENDIAN =     4,   // 32-bit number (same as REG_DWORD)
+	REG_DWORD_BIG_ENDIAN =        5,   // 32-bit number
+	REG_LINK =                    6,   // Symbolic Link (unicode)
+	REG_MULTI_SZ =                7,   // Multiple Unicode strings
+	REG_RESOURCE_LIST =           8,   // Resource list in the resource map
+	REG_FULL_RESOURCE_DESCRIPTOR = 9,  // Resource list in the hardware description
+	REG_RESOURCE_REQUIREMENTS_LIST = 10,
+	REG_QWORD =			11,
+	REG_QWORD_LITTLE_ENDIAN =	11,
+}
+
+/*
+ * MessageBox() Flags
+ */
+enum
+{
+	MB_OK =                       0x00000000,
+	MB_OKCANCEL =                 0x00000001,
+	MB_ABORTRETRYIGNORE =         0x00000002,
+	MB_YESNOCANCEL =              0x00000003,
+	MB_YESNO =                    0x00000004,
+	MB_RETRYCANCEL =              0x00000005,
+
+
+	MB_ICONHAND =                 0x00000010,
+	MB_ICONQUESTION =             0x00000020,
+	MB_ICONEXCLAMATION =          0x00000030,
+	MB_ICONASTERISK =             0x00000040,
+
+
+	MB_USERICON =                 0x00000080,
+	MB_ICONWARNING =              MB_ICONEXCLAMATION,
+	MB_ICONERROR =                MB_ICONHAND,
+
+
+	MB_ICONINFORMATION =          MB_ICONASTERISK,
+	MB_ICONSTOP =                 MB_ICONHAND,
+
+	MB_DEFBUTTON1 =               0x00000000,
+	MB_DEFBUTTON2 =               0x00000100,
+	MB_DEFBUTTON3 =               0x00000200,
+
+	MB_DEFBUTTON4 =               0x00000300,
+
+
+	MB_APPLMODAL =                0x00000000,
+	MB_SYSTEMMODAL =              0x00001000,
+	MB_TASKMODAL =                0x00002000,
+
+	MB_HELP =                     0x00004000, // Help Button
+
+
+	MB_NOFOCUS =                  0x00008000,
+	MB_SETFOREGROUND =            0x00010000,
+	MB_DEFAULT_DESKTOP_ONLY =     0x00020000,
+
+
+	MB_TOPMOST =                  0x00040000,
+	MB_RIGHT =                    0x00080000,
+	MB_RTLREADING =               0x00100000,
+
+
+	MB_TYPEMASK =                 0x0000000F,
+	MB_ICONMASK =                 0x000000F0,
+	MB_DEFMASK =                  0x00000F00,
+	MB_MODEMASK =                 0x00003000,
+	MB_MISCMASK =                 0x0000C000,
+}
+
+
+int MessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType);
+int MessageBoxExA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType, WORD wLanguageId);
+
+const HKEY HKEY_CLASSES_ROOT =           cast(HKEY)(0x80000000);
+const HKEY HKEY_CURRENT_USER =           cast(HKEY)(0x80000001);
+const HKEY HKEY_LOCAL_MACHINE =          cast(HKEY)(0x80000002);
+const HKEY HKEY_USERS =                  cast(HKEY)(0x80000003);
+const HKEY HKEY_PERFORMANCE_DATA =       cast(HKEY)(0x80000004);
+const HKEY HKEY_PERFORMANCE_TEXT =       cast(HKEY)(0x80000050);
+const HKEY HKEY_PERFORMANCE_NLSTEXT =    cast(HKEY)(0x80000060);
+const HKEY HKEY_CURRENT_CONFIG =         cast(HKEY)(0x80000005);
+const HKEY HKEY_DYN_DATA =               cast(HKEY)(0x80000006);
+
+enum
+{
+	REG_OPTION_RESERVED =         (0x00000000),   // Parameter is reserved
+
+	REG_OPTION_NON_VOLATILE =     (0x00000000),   // Key is preserved
+                                                    // when system is rebooted
+
+	REG_OPTION_VOLATILE =         (0x00000001),   // Key is not preserved
+                                                    // when system is rebooted
+
+	REG_OPTION_CREATE_LINK =      (0x00000002),   // Created key is a
+                                                    // symbolic link
+
+	REG_OPTION_BACKUP_RESTORE =   (0x00000004),   // open for backup or restore
+                                                    // special access rules
+                                                    // privilege required
+
+	REG_OPTION_OPEN_LINK =        (0x00000008),   // Open symbolic link
+
+	REG_LEGAL_OPTION = (REG_OPTION_RESERVED | REG_OPTION_NON_VOLATILE | REG_OPTION_VOLATILE | REG_OPTION_CREATE_LINK | REG_OPTION_BACKUP_RESTORE | REG_OPTION_OPEN_LINK),
+}
+
+export LONG RegDeleteKeyA(HKEY hKey, LPCSTR lpSubKey);
+export LONG RegDeleteValueA(HKEY hKey, LPCSTR lpValueName);
+
+export LONG  RegEnumKeyExA(HKEY hKey, DWORD dwIndex, LPSTR lpName, LPDWORD lpcbName, LPDWORD lpReserved, LPSTR lpClass, LPDWORD lpcbClass, FILETIME* lpftLastWriteTime);
+export LONG RegEnumValueA(HKEY hKey, DWORD dwIndex, LPSTR lpValueName, LPDWORD lpcbValueName, LPDWORD lpReserved,
+    LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData);
+
+export LONG RegCloseKey(HKEY hKey);
+export LONG RegFlushKey(HKEY hKey);
+
+export LONG RegOpenKeyA(HKEY hKey, LPCSTR lpSubKey, PHKEY phkResult);
+export LONG RegOpenKeyExA(HKEY hKey, LPCSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult);
+
+export LONG RegQueryInfoKeyA(HKEY hKey, LPSTR lpClass, LPDWORD lpcbClass,
+    LPDWORD lpReserved, LPDWORD lpcSubKeys, LPDWORD lpcbMaxSubKeyLen, LPDWORD lpcbMaxClassLen,
+    LPDWORD lpcValues, LPDWORD lpcbMaxValueNameLen, LPDWORD lpcbMaxValueLen, LPDWORD lpcbSecurityDescriptor,
+    PFILETIME lpftLastWriteTime);
+
+export LONG RegQueryValueA(HKEY hKey, LPCSTR lpSubKey, LPSTR lpValue,
+    LPLONG lpcbValue);
+
+export LONG RegCreateKeyExA(HKEY hKey, LPCSTR lpSubKey, DWORD Reserved, LPSTR lpClass,
+   DWORD dwOptions, REGSAM samDesired, SECURITY_ATTRIBUTES* lpSecurityAttributes,
+    PHKEY phkResult, LPDWORD lpdwDisposition);
+
+export LONG RegSetValueExA(HKEY hKey, LPCSTR lpValueName, DWORD Reserved, DWORD dwType, BYTE* lpData, DWORD cbData);
+
+struct MEMORY_BASIC_INFORMATION {
+    PVOID BaseAddress;
+    PVOID AllocationBase;
+    DWORD AllocationProtect;
+    DWORD RegionSize;
+    DWORD State;
+    DWORD Protect;
+    DWORD Type;
+}
+alias MEMORY_BASIC_INFORMATION* PMEMORY_BASIC_INFORMATION;
+
+enum
+{
+	SECTION_QUERY       = 0x0001,
+	SECTION_MAP_WRITE   = 0x0002,
+	SECTION_MAP_READ    = 0x0004,
+	SECTION_MAP_EXECUTE = 0x0008,
+	SECTION_EXTEND_SIZE = 0x0010,
+
+	SECTION_ALL_ACCESS = cast(int)(STANDARD_RIGHTS_REQUIRED|SECTION_QUERY| SECTION_MAP_WRITE | SECTION_MAP_READ | SECTION_MAP_EXECUTE | SECTION_EXTEND_SIZE),
+	PAGE_NOACCESS          = 0x01,
+	PAGE_READONLY          = 0x02,
+	PAGE_READWRITE         = 0x04,
+	PAGE_WRITECOPY         = 0x08,
+	PAGE_EXECUTE           = 0x10,
+	PAGE_EXECUTE_READ      = 0x20,
+	PAGE_EXECUTE_READWRITE = 0x40,
+	PAGE_EXECUTE_WRITECOPY = 0x80,
+	PAGE_GUARD            = 0x100,
+	PAGE_NOCACHE          = 0x200,
+	MEM_COMMIT           = 0x1000,
+	MEM_RESERVE          = 0x2000,
+	MEM_DECOMMIT         = 0x4000,
+	MEM_RELEASE          = 0x8000,
+	MEM_FREE            = 0x10000,
+	MEM_PRIVATE         = 0x20000,
+	MEM_MAPPED          = 0x40000,
+	MEM_RESET           = 0x80000,
+	MEM_TOP_DOWN       = 0x100000,
+	SEC_FILE           = 0x800000,
+	SEC_IMAGE         = 0x1000000,
+	SEC_RESERVE       = 0x4000000,
+	SEC_COMMIT        = 0x8000000,
+	SEC_NOCACHE      = 0x10000000,
+	MEM_IMAGE        = SEC_IMAGE,
+}
+
+enum
+{
+	FILE_MAP_COPY =       SECTION_QUERY,
+	FILE_MAP_WRITE =      SECTION_MAP_WRITE,
+	FILE_MAP_READ =       SECTION_MAP_READ,
+	FILE_MAP_ALL_ACCESS = SECTION_ALL_ACCESS,
+}
+
+
+//
+// Define access rights to files and directories
+//
+
+//
+// The FILE_READ_DATA and FILE_WRITE_DATA constants are also defined in
+// devioctl.h as FILE_READ_ACCESS and FILE_WRITE_ACCESS. The values for these
+// constants *MUST* always be in sync.
+// The values are redefined in devioctl.h because they must be available to
+// both DOS and NT.
+//
+
+enum
+{
+	FILE_READ_DATA =            ( 0x0001 ),   // file & pipe
+	FILE_LIST_DIRECTORY =       ( 0x0001 ),    // directory
+
+	FILE_WRITE_DATA =           ( 0x0002 ),    // file & pipe
+	FILE_ADD_FILE =             ( 0x0002 ),    // directory
+
+	FILE_APPEND_DATA =          ( 0x0004 ),    // file
+	FILE_ADD_SUBDIRECTORY =     ( 0x0004 ),    // directory
+	FILE_CREATE_PIPE_INSTANCE = ( 0x0004 ),    // named pipe
+
+	FILE_READ_EA =              ( 0x0008 ),    // file & directory
+
+	FILE_WRITE_EA =             ( 0x0010 ),    // file & directory
+
+	FILE_EXECUTE =              ( 0x0020 ),    // file
+	FILE_TRAVERSE =             ( 0x0020 ),    // directory
+
+	FILE_DELETE_CHILD =         ( 0x0040 ),    // directory
+
+	FILE_READ_ATTRIBUTES =      ( 0x0080 ),    // all
+
+	FILE_WRITE_ATTRIBUTES =     ( 0x0100 ),    // all
+
+	FILE_ALL_ACCESS =	    cast(int)(STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x1FF),
+
+	FILE_GENERIC_READ =         cast(int)(STANDARD_RIGHTS_READ  | FILE_READ_DATA |  FILE_READ_ATTRIBUTES |                 FILE_READ_EA |  SYNCHRONIZE),
+
+	FILE_GENERIC_WRITE =        cast(int)(STANDARD_RIGHTS_WRITE | FILE_WRITE_DATA |  FILE_WRITE_ATTRIBUTES |                      FILE_WRITE_EA  |  FILE_APPEND_DATA |  SYNCHRONIZE),
+
+	FILE_GENERIC_EXECUTE =      cast(int)(STANDARD_RIGHTS_EXECUTE | FILE_READ_ATTRIBUTES |                 FILE_EXECUTE |  SYNCHRONIZE),
+}
+
+export
+{
+ BOOL GlobalUnlock(HGLOBAL hMem);
+ HGLOBAL GlobalFree(HGLOBAL hMem);
+ UINT GlobalCompact(DWORD dwMinFree);
+ void GlobalFix(HGLOBAL hMem);
+ void GlobalUnfix(HGLOBAL hMem);
+ LPVOID GlobalWire(HGLOBAL hMem);
+ BOOL GlobalUnWire(HGLOBAL hMem);
+ void GlobalMemoryStatus(LPMEMORYSTATUS lpBuffer);
+ HLOCAL LocalAlloc(UINT uFlags, UINT uBytes);
+ HLOCAL LocalReAlloc(HLOCAL hMem, UINT uBytes, UINT uFlags);
+ LPVOID LocalLock(HLOCAL hMem);
+ HLOCAL LocalHandle(LPCVOID pMem);
+ BOOL LocalUnlock(HLOCAL hMem);
+ UINT LocalSize(HLOCAL hMem);
+ UINT LocalFlags(HLOCAL hMem);
+ HLOCAL LocalFree(HLOCAL hMem);
+ UINT LocalShrink(HLOCAL hMem, UINT cbNewSize);
+ UINT LocalCompact(UINT uMinFree);
+ BOOL FlushInstructionCache(HANDLE hProcess, LPCVOID lpBaseAddress, DWORD dwSize);
+ LPVOID VirtualAlloc(LPVOID lpAddress, DWORD dwSize, DWORD flAllocationType, DWORD flProtect);
+ BOOL VirtualFree(LPVOID lpAddress, DWORD dwSize, DWORD dwFreeType);
+ BOOL VirtualProtect(LPVOID lpAddress, DWORD dwSize, DWORD flNewProtect, PDWORD lpflOldProtect);
+ DWORD VirtualQuery(LPCVOID lpAddress, PMEMORY_BASIC_INFORMATION lpBuffer, DWORD dwLength);
+ LPVOID VirtualAllocEx(HANDLE hProcess, LPVOID lpAddress, DWORD dwSize, DWORD flAllocationType, DWORD flProtect);
+ BOOL VirtualFreeEx(HANDLE hProcess, LPVOID lpAddress, DWORD dwSize, DWORD dwFreeType);
+ BOOL VirtualProtectEx(HANDLE hProcess, LPVOID lpAddress, DWORD dwSize, DWORD flNewProtect, PDWORD lpflOldProtect);
+ DWORD VirtualQueryEx(HANDLE hProcess, LPCVOID lpAddress, PMEMORY_BASIC_INFORMATION lpBuffer, DWORD dwLength);
+}
+
+struct SYSTEMTIME
+{
+    WORD wYear;
+    WORD wMonth;
+    WORD wDayOfWeek;
+    WORD wDay;
+    WORD wHour;
+    WORD wMinute;
+    WORD wSecond;
+    WORD wMilliseconds;
+}
+
+struct TIME_ZONE_INFORMATION {
+    LONG Bias;
+    WCHAR StandardName[ 32 ];
+    SYSTEMTIME StandardDate;
+    LONG StandardBias;
+    WCHAR DaylightName[ 32 ];
+    SYSTEMTIME DaylightDate;
+    LONG DaylightBias;
+}
+
+enum
+{
+	TIME_ZONE_ID_UNKNOWN =  0,
+	TIME_ZONE_ID_STANDARD = 1,
+	TIME_ZONE_ID_DAYLIGHT = 2,
+}
+
+export void GetSystemTime(SYSTEMTIME* lpSystemTime);
+export void GetSystemTimeAsFileTime(FILETIME* lpSystemTimeAsFileTime);
+export BOOL SetSystemTime(SYSTEMTIME* lpSystemTime);
+export void GetLocalTime(SYSTEMTIME* lpSystemTime);
+export BOOL SetLocalTime(SYSTEMTIME* lpSystemTime);
+export BOOL SystemTimeToTzSpecificLocalTime(TIME_ZONE_INFORMATION* lpTimeZoneInformation, SYSTEMTIME* lpUniversalTime, SYSTEMTIME* lpLocalTime);
+export DWORD GetTimeZoneInformation(TIME_ZONE_INFORMATION* lpTimeZoneInformation);
+export BOOL SetTimeZoneInformation(TIME_ZONE_INFORMATION* lpTimeZoneInformation);
+
+export BOOL SystemTimeToFileTime(SYSTEMTIME *lpSystemTime, FILETIME* lpFileTime);
+export BOOL FileTimeToLocalFileTime(FILETIME *lpFileTime, FILETIME* lpLocalFileTime);
+export BOOL LocalFileTimeToFileTime(FILETIME *lpLocalFileTime, FILETIME* lpFileTime);
+export BOOL FileTimeToSystemTime(FILETIME *lpFileTime, SYSTEMTIME* lpSystemTime);
+export LONG CompareFileTime(FILETIME *lpFileTime1, FILETIME *lpFileTime2);
+export BOOL FileTimeToDosDateTime(FILETIME *lpFileTime, WORD* lpFatDate, WORD* lpFatTime);
+export BOOL DosDateTimeToFileTime(WORD wFatDate, WORD wFatTime, FILETIME* lpFileTime);
+export DWORD GetTickCount();
+export BOOL SetSystemTimeAdjustment(DWORD dwTimeAdjustment, BOOL bTimeAdjustmentDisabled);
+export BOOL GetSystemTimeAdjustment(DWORD* lpTimeAdjustment, DWORD* lpTimeIncrement, BOOL* lpTimeAdjustmentDisabled);
+export DWORD FormatMessageA(DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId, DWORD dwLanguageId, LPSTR lpBuffer, DWORD nSize, void* *Arguments);export DWORD FormatMessageW(DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId, DWORD dwLanguageId, LPWSTR lpBuffer, DWORD nSize, void* *Arguments);
+
+enum
+{
+	FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x00000100,
+	FORMAT_MESSAGE_IGNORE_INSERTS =  0x00000200,
+	FORMAT_MESSAGE_FROM_STRING =     0x00000400,
+	FORMAT_MESSAGE_FROM_HMODULE =    0x00000800,
+	FORMAT_MESSAGE_FROM_SYSTEM =     0x00001000,
+	FORMAT_MESSAGE_ARGUMENT_ARRAY =  0x00002000,
+	FORMAT_MESSAGE_MAX_WIDTH_MASK =  0x000000FF,
+};
+
+
+//
+//  Language IDs.
+//
+//  The following two combinations of primary language ID and
+//  sublanguage ID have special semantics:
+//
+//    Primary Language ID   Sublanguage ID      Result
+//    -------------------   ---------------     ------------------------
+//    LANG_NEUTRAL          SUBLANG_NEUTRAL     Language neutral
+//    LANG_NEUTRAL          SUBLANG_DEFAULT     User default language
+//    LANG_NEUTRAL          SUBLANG_SYS_DEFAULT System default language
+//
+
+//
+//  Primary language IDs.
+//
+
+enum
+{
+	LANG_NEUTRAL                     = 0x00,
+
+	LANG_AFRIKAANS                   = 0x36,
+	LANG_ALBANIAN                    = 0x1c,
+	LANG_ARABIC                      = 0x01,
+	LANG_BASQUE                      = 0x2d,
+	LANG_BELARUSIAN                  = 0x23,
+	LANG_BULGARIAN                   = 0x02,
+	LANG_CATALAN                     = 0x03,
+	LANG_CHINESE                     = 0x04,
+	LANG_CROATIAN                    = 0x1a,
+	LANG_CZECH                       = 0x05,
+	LANG_DANISH                      = 0x06,
+	LANG_DUTCH                       = 0x13,
+	LANG_ENGLISH                     = 0x09,
+	LANG_ESTONIAN                    = 0x25,
+	LANG_FAEROESE                    = 0x38,
+	LANG_FARSI                       = 0x29,
+	LANG_FINNISH                     = 0x0b,
+	LANG_FRENCH                      = 0x0c,
+	LANG_GERMAN                      = 0x07,
+	LANG_GREEK                       = 0x08,
+	LANG_HEBREW                      = 0x0d,
+	LANG_HUNGARIAN                   = 0x0e,
+	LANG_ICELANDIC                   = 0x0f,
+	LANG_INDONESIAN                  = 0x21,
+	LANG_ITALIAN                     = 0x10,
+	LANG_JAPANESE                    = 0x11,
+	LANG_KOREAN                      = 0x12,
+	LANG_LATVIAN                     = 0x26,
+	LANG_LITHUANIAN                  = 0x27,
+	LANG_NORWEGIAN                   = 0x14,
+	LANG_POLISH                      = 0x15,
+	LANG_PORTUGUESE                  = 0x16,
+	LANG_ROMANIAN                    = 0x18,
+	LANG_RUSSIAN                     = 0x19,
+	LANG_SERBIAN                     = 0x1a,
+	LANG_SLOVAK                      = 0x1b,
+	LANG_SLOVENIAN                   = 0x24,
+	LANG_SPANISH                     = 0x0a,
+	LANG_SWEDISH                     = 0x1d,
+	LANG_THAI                        = 0x1e,
+	LANG_TURKISH                     = 0x1f,
+	LANG_UKRAINIAN                   = 0x22,
+	LANG_VIETNAMESE                  = 0x2a,
+}
+//
+//  Sublanguage IDs.
+//
+//  The name immediately following SUBLANG_ dictates which primary
+//  language ID that sublanguage ID can be combined with to form a
+//  valid language ID.
+//
+enum
+{
+	SUBLANG_NEUTRAL =                  0x00,    // language neutral
+	SUBLANG_DEFAULT =                  0x01,    // user default
+	SUBLANG_SYS_DEFAULT =              0x02,    // system default
+
+	SUBLANG_ARABIC_SAUDI_ARABIA =      0x01,    // Arabic (Saudi Arabia)
+	SUBLANG_ARABIC_IRAQ =              0x02,    // Arabic (Iraq)
+	SUBLANG_ARABIC_EGYPT =             0x03,    // Arabic (Egypt)
+	SUBLANG_ARABIC_LIBYA =             0x04,    // Arabic (Libya)
+	SUBLANG_ARABIC_ALGERIA =           0x05,    // Arabic (Algeria)
+	SUBLANG_ARABIC_MOROCCO =           0x06,    // Arabic (Morocco)
+	SUBLANG_ARABIC_TUNISIA =           0x07,    // Arabic (Tunisia)
+	SUBLANG_ARABIC_OMAN =              0x08,    // Arabic (Oman)
+	SUBLANG_ARABIC_YEMEN =             0x09,    // Arabic (Yemen)
+	SUBLANG_ARABIC_SYRIA =             0x0a,    // Arabic (Syria)
+	SUBLANG_ARABIC_JORDAN =            0x0b,    // Arabic (Jordan)
+	SUBLANG_ARABIC_LEBANON =           0x0c,    // Arabic (Lebanon)
+	SUBLANG_ARABIC_KUWAIT =            0x0d,    // Arabic (Kuwait)
+	SUBLANG_ARABIC_UAE =               0x0e,    // Arabic (U.A.E)
+	SUBLANG_ARABIC_BAHRAIN =           0x0f,    // Arabic (Bahrain)
+	SUBLANG_ARABIC_QATAR =             0x10,    // Arabic (Qatar)
+	SUBLANG_CHINESE_TRADITIONAL =      0x01,    // Chinese (Taiwan)
+	SUBLANG_CHINESE_SIMPLIFIED =       0x02,    // Chinese (PR China)
+	SUBLANG_CHINESE_HONGKONG =         0x03,    // Chinese (Hong Kong)
+	SUBLANG_CHINESE_SINGAPORE =        0x04,    // Chinese (Singapore)
+	SUBLANG_DUTCH =                    0x01,    // Dutch
+	SUBLANG_DUTCH_BELGIAN =            0x02,    // Dutch (Belgian)
+	SUBLANG_ENGLISH_US =               0x01,    // English (USA)
+	SUBLANG_ENGLISH_UK =               0x02,    // English (UK)
+	SUBLANG_ENGLISH_AUS =              0x03,    // English (Australian)
+	SUBLANG_ENGLISH_CAN =              0x04,    // English (Canadian)
+	SUBLANG_ENGLISH_NZ =               0x05,    // English (New Zealand)
+	SUBLANG_ENGLISH_EIRE =             0x06,    // English (Irish)
+	SUBLANG_ENGLISH_SOUTH_AFRICA =     0x07,    // English (South Africa)
+	SUBLANG_ENGLISH_JAMAICA =          0x08,    // English (Jamaica)
+	SUBLANG_ENGLISH_CARIBBEAN =        0x09,    // English (Caribbean)
+	SUBLANG_ENGLISH_BELIZE =           0x0a,    // English (Belize)
+	SUBLANG_ENGLISH_TRINIDAD =         0x0b,    // English (Trinidad)
+	SUBLANG_FRENCH =                   0x01,    // French
+	SUBLANG_FRENCH_BELGIAN =           0x02,    // French (Belgian)
+	SUBLANG_FRENCH_CANADIAN =          0x03,    // French (Canadian)
+	SUBLANG_FRENCH_SWISS =             0x04,    // French (Swiss)
+	SUBLANG_FRENCH_LUXEMBOURG =        0x05,    // French (Luxembourg)
+	SUBLANG_GERMAN =                   0x01,    // German
+	SUBLANG_GERMAN_SWISS =             0x02,    // German (Swiss)
+	SUBLANG_GERMAN_AUSTRIAN =          0x03,    // German (Austrian)
+	SUBLANG_GERMAN_LUXEMBOURG =        0x04,    // German (Luxembourg)
+	SUBLANG_GERMAN_LIECHTENSTEIN =     0x05,    // German (Liechtenstein)
+	SUBLANG_ITALIAN =                  0x01,    // Italian
+	SUBLANG_ITALIAN_SWISS =            0x02,    // Italian (Swiss)
+	SUBLANG_KOREAN =                   0x01,    // Korean (Extended Wansung)
+	SUBLANG_KOREAN_JOHAB =             0x02,    // Korean (Johab)
+	SUBLANG_NORWEGIAN_BOKMAL =         0x01,    // Norwegian (Bokmal)
+	SUBLANG_NORWEGIAN_NYNORSK =        0x02,    // Norwegian (Nynorsk)
+	SUBLANG_PORTUGUESE =               0x02,    // Portuguese
+	SUBLANG_PORTUGUESE_BRAZILIAN =     0x01,    // Portuguese (Brazilian)
+	SUBLANG_SERBIAN_LATIN =            0x02,    // Serbian (Latin)
+	SUBLANG_SERBIAN_CYRILLIC =         0x03,    // Serbian (Cyrillic)
+	SUBLANG_SPANISH =                  0x01,    // Spanish (Castilian)
+	SUBLANG_SPANISH_MEXICAN =          0x02,    // Spanish (Mexican)
+	SUBLANG_SPANISH_MODERN =           0x03,    // Spanish (Modern)
+	SUBLANG_SPANISH_GUATEMALA =        0x04,    // Spanish (Guatemala)
+	SUBLANG_SPANISH_COSTA_RICA =       0x05,    // Spanish (Costa Rica)
+	SUBLANG_SPANISH_PANAMA =           0x06,    // Spanish (Panama)
+	SUBLANG_SPANISH_DOMINICAN_REPUBLIC = 0x07,  // Spanish (Dominican Republic)
+	SUBLANG_SPANISH_VENEZUELA =        0x08,    // Spanish (Venezuela)
+	SUBLANG_SPANISH_COLOMBIA =         0x09,    // Spanish (Colombia)
+	SUBLANG_SPANISH_PERU =             0x0a,    // Spanish (Peru)
+	SUBLANG_SPANISH_ARGENTINA =        0x0b,    // Spanish (Argentina)
+	SUBLANG_SPANISH_ECUADOR =          0x0c,    // Spanish (Ecuador)
+	SUBLANG_SPANISH_CHILE =            0x0d,    // Spanish (Chile)
+	SUBLANG_SPANISH_URUGUAY =          0x0e,    // Spanish (Uruguay)
+	SUBLANG_SPANISH_PARAGUAY =         0x0f,    // Spanish (Paraguay)
+	SUBLANG_SPANISH_BOLIVIA =          0x10,    // Spanish (Bolivia)
+	SUBLANG_SPANISH_EL_SALVADOR =      0x11,    // Spanish (El Salvador)
+	SUBLANG_SPANISH_HONDURAS =         0x12,    // Spanish (Honduras)
+	SUBLANG_SPANISH_NICARAGUA =        0x13,    // Spanish (Nicaragua)
+	SUBLANG_SPANISH_PUERTO_RICO =      0x14,    // Spanish (Puerto Rico)
+	SUBLANG_SWEDISH =                  0x01,    // Swedish
+	SUBLANG_SWEDISH_FINLAND =          0x02,    // Swedish (Finland)
+}
+//
+//  Sorting IDs.
+//
+
+enum
+{
+	SORT_DEFAULT                   = 0x0,    // sorting default
+
+	SORT_JAPANESE_XJIS             = 0x0,    // Japanese XJIS order
+	SORT_JAPANESE_UNICODE          = 0x1,    // Japanese Unicode order
+
+	SORT_CHINESE_BIG5              = 0x0,    // Chinese BIG5 order
+	SORT_CHINESE_PRCP              = 0x0,    // PRC Chinese Phonetic order
+	SORT_CHINESE_UNICODE           = 0x1,    // Chinese Unicode order
+	SORT_CHINESE_PRC               = 0x2,    // PRC Chinese Stroke Count order
+
+	SORT_KOREAN_KSC                = 0x0,    // Korean KSC order
+	SORT_KOREAN_UNICODE            = 0x1,    // Korean Unicode order
+
+	SORT_GERMAN_PHONE_BOOK         = 0x1,    // German Phone Book order
+}
+
+// end_r_winnt
+
+//
+//  A language ID is a 16 bit value which is the combination of a
+//  primary language ID and a secondary language ID.  The bits are
+//  allocated as follows:
+//
+//       +-----------------------+-------------------------+
+//       |     Sublanguage ID    |   Primary Language ID   |
+//       +-----------------------+-------------------------+
+//        15                   10 9                       0   bit
+//
+//
+//  Language ID creation/extraction macros:
+//
+//    MAKELANGID    - construct language id from a primary language id and
+//                    a sublanguage id.
+//    PRIMARYLANGID - extract primary language id from a language id.
+//    SUBLANGID     - extract sublanguage id from a language id.
+//
+
+int MAKELANGID(int p, int s) { return ((cast(WORD)s) << 10) | cast(WORD)p; }
+WORD PRIMARYLANGID(int lgid) { return cast(WORD)(lgid & 0x3ff); }
+WORD SUBLANGID(int lgid)     { return cast(WORD)(lgid >> 10); }
+
+
+struct FLOATING_SAVE_AREA {
+    DWORD   ControlWord;
+    DWORD   StatusWord;
+    DWORD   TagWord;
+    DWORD   ErrorOffset;
+    DWORD   ErrorSelector;
+    DWORD   DataOffset;
+    DWORD   DataSelector;
+    BYTE    RegisterArea[80 ];
+    DWORD   Cr0NpxState;
+}
+
+enum
+{
+	SIZE_OF_80387_REGISTERS =      80,
+//
+// The following flags control the contents of the CONTEXT structure.
+//
+	CONTEXT_i386 =    0x00010000,    // this assumes that i386 and
+	CONTEXT_i486 =    0x00010000,    // i486 have identical context records
+
+	CONTEXT_CONTROL =         (CONTEXT_i386 | 0x00000001), // SS:SP, CS:IP, FLAGS, BP
+	CONTEXT_INTEGER =         (CONTEXT_i386 | 0x00000002), // AX, BX, CX, DX, SI, DI
+	CONTEXT_SEGMENTS =        (CONTEXT_i386 | 0x00000004), // DS, ES, FS, GS
+	CONTEXT_FLOATING_POINT =  (CONTEXT_i386 | 0x00000008), // 387 state
+	CONTEXT_DEBUG_REGISTERS = (CONTEXT_i386 | 0x00000010), // DB 0-3,6,7
+
+	CONTEXT_FULL = (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS),
+}
+
+struct CONTEXT
+{
+
+    //
+    // The flags values within this flag control the contents of
+    // a CONTEXT record.
+    //
+    // If the context record is used as an input parameter, then
+    // for each portion of the context record controlled by a flag
+    // whose value is set, it is assumed that that portion of the
+    // context record contains valid context. If the context record
+    // is being used to modify a threads context, then only that
+    // portion of the threads context will be modified.
+    //
+    // If the context record is used as an IN OUT parameter to capture
+    // the context of a thread, then only those portions of the thread's
+    // context corresponding to set flags will be returned.
+    //
+    // The context record is never used as an OUT only parameter.
+    //
+
+    DWORD ContextFlags;
+
+    //
+    // This section is specified/returned if CONTEXT_DEBUG_REGISTERS is
+    // set in ContextFlags.  Note that CONTEXT_DEBUG_REGISTERS is NOT
+    // included in CONTEXT_FULL.
+    //
+
+    DWORD   Dr0;
+    DWORD   Dr1;
+    DWORD   Dr2;
+    DWORD   Dr3;
+    DWORD   Dr6;
+    DWORD   Dr7;
+
+    //
+    // This section is specified/returned if the
+    // ContextFlags word contians the flag CONTEXT_FLOATING_POINT.
+    //
+
+    FLOATING_SAVE_AREA FloatSave;
+
+    //
+    // This section is specified/returned if the
+    // ContextFlags word contians the flag CONTEXT_SEGMENTS.
+    //
+
+    DWORD   SegGs;
+    DWORD   SegFs;
+    DWORD   SegEs;
+    DWORD   SegDs;
+
+    //
+    // This section is specified/returned if the
+    // ContextFlags word contians the flag CONTEXT_INTEGER.
+    //
+
+    DWORD   Edi;
+    DWORD   Esi;
+    DWORD   Ebx;
+    DWORD   Edx;
+    DWORD   Ecx;
+    DWORD   Eax;
+
+    //
+    // This section is specified/returned if the
+    // ContextFlags word contians the flag CONTEXT_CONTROL.
+    //
+
+    DWORD   Ebp;
+    DWORD   Eip;
+    DWORD   SegCs;              // MUST BE SANITIZED
+    DWORD   EFlags;             // MUST BE SANITIZED
+    DWORD   Esp;
+    DWORD   SegSs;
+}
+
+enum
+{
+	THREAD_BASE_PRIORITY_LOWRT =  15,  // value that gets a thread to LowRealtime-1
+	THREAD_BASE_PRIORITY_MAX =    2,   // maximum thread base priority boost
+	THREAD_BASE_PRIORITY_MIN =    -2,  // minimum thread base priority boost
+	THREAD_BASE_PRIORITY_IDLE =   -15, // value that gets a thread to idle
+
+	THREAD_PRIORITY_LOWEST =          THREAD_BASE_PRIORITY_MIN,
+	THREAD_PRIORITY_BELOW_NORMAL =    (THREAD_PRIORITY_LOWEST+1),
+	THREAD_PRIORITY_NORMAL =          0,
+	THREAD_PRIORITY_HIGHEST =         THREAD_BASE_PRIORITY_MAX,
+	THREAD_PRIORITY_ABOVE_NORMAL =    (THREAD_PRIORITY_HIGHEST-1),
+	THREAD_PRIORITY_ERROR_RETURN =    int.max,
+
+	THREAD_PRIORITY_TIME_CRITICAL =   THREAD_BASE_PRIORITY_LOWRT,
+	THREAD_PRIORITY_IDLE =            THREAD_BASE_PRIORITY_IDLE,
+}
+
+export HANDLE GetCurrentThread();
+export BOOL GetProcessTimes(HANDLE hProcess, LPFILETIME lpCreationTime, LPFILETIME lpExitTime, LPFILETIME lpKernelTime, LPFILETIME lpUserTime);
+export HANDLE GetCurrentProcess();
+export BOOL DuplicateHandle (HANDLE sourceProcess, HANDLE sourceThread,
+        HANDLE targetProcessHandle, HANDLE *targetHandle, DWORD access, 
+        BOOL inheritHandle, DWORD options);
+export DWORD GetCurrentThreadId();
+export BOOL SetThreadPriority(HANDLE hThread, int nPriority);
+export BOOL SetThreadPriorityBoost(HANDLE hThread, BOOL bDisablePriorityBoost);
+export BOOL GetThreadPriorityBoost(HANDLE hThread, PBOOL pDisablePriorityBoost);
+export BOOL GetThreadTimes(HANDLE hThread, LPFILETIME lpCreationTime, LPFILETIME lpExitTime, LPFILETIME lpKernelTime, LPFILETIME lpUserTime);
+export int GetThreadPriority(HANDLE hThread);
+export BOOL GetThreadContext(HANDLE hThread, CONTEXT* lpContext);
+export BOOL SetThreadContext(HANDLE hThread, CONTEXT* lpContext);
+export DWORD SuspendThread(HANDLE hThread);
+export DWORD ResumeThread(HANDLE hThread);
+export DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds);
+export DWORD WaitForMultipleObjects(DWORD nCount, HANDLE *lpHandles, BOOL bWaitAll, DWORD dwMilliseconds);
+export void Sleep(DWORD dwMilliseconds);
+
+export BOOL QueryPerformanceCounter(long* lpPerformanceCount);
+export BOOL QueryPerformanceFrequency(long* lpFrequency);
+
+enum
+{
+	WM_NOTIFY =                       0x004E,
+	WM_INPUTLANGCHANGEREQUEST =       0x0050,
+	WM_INPUTLANGCHANGE =              0x0051,
+	WM_TCARD =                        0x0052,
+	WM_HELP =                         0x0053,
+	WM_USERCHANGED =                  0x0054,
+	WM_NOTIFYFORMAT =                 0x0055,
+
+	NFR_ANSI =                             1,
+	NFR_UNICODE =                          2,
+	NF_QUERY =                             3,
+	NF_REQUERY =                           4,
+
+	WM_CONTEXTMENU =                  0x007B,
+	WM_STYLECHANGING =                0x007C,
+	WM_STYLECHANGED =                 0x007D,
+	WM_DISPLAYCHANGE =                0x007E,
+	WM_GETICON =                      0x007F,
+	WM_SETICON =                      0x0080,
+
+
+
+	WM_NCCREATE =                     0x0081,
+	WM_NCDESTROY =                    0x0082,
+	WM_NCCALCSIZE =                   0x0083,
+	WM_NCHITTEST =                    0x0084,
+	WM_NCPAINT =                      0x0085,
+	WM_NCACTIVATE =                   0x0086,
+	WM_GETDLGCODE =                   0x0087,
+
+	WM_NCMOUSEMOVE =                  0x00A0,
+	WM_NCLBUTTONDOWN =                0x00A1,
+	WM_NCLBUTTONUP =                  0x00A2,
+	WM_NCLBUTTONDBLCLK =              0x00A3,
+	WM_NCRBUTTONDOWN =                0x00A4,
+	WM_NCRBUTTONUP =                  0x00A5,
+	WM_NCRBUTTONDBLCLK =              0x00A6,
+	WM_NCMBUTTONDOWN =                0x00A7,
+	WM_NCMBUTTONUP =                  0x00A8,
+	WM_NCMBUTTONDBLCLK =              0x00A9,
+
+	WM_KEYFIRST =                     0x0100,
+	WM_KEYDOWN =                      0x0100,
+	WM_KEYUP =                        0x0101,
+	WM_CHAR =                         0x0102,
+	WM_DEADCHAR =                     0x0103,
+	WM_SYSKEYDOWN =                   0x0104,
+	WM_SYSKEYUP =                     0x0105,
+	WM_SYSCHAR =                      0x0106,
+	WM_SYSDEADCHAR =                  0x0107,
+	WM_KEYLAST =                      0x0108,
+
+
+	WM_IME_STARTCOMPOSITION =         0x010D,
+	WM_IME_ENDCOMPOSITION =           0x010E,
+	WM_IME_COMPOSITION =              0x010F,
+	WM_IME_KEYLAST =                  0x010F,
+
+
+	WM_INITDIALOG =                   0x0110,
+	WM_COMMAND =                      0x0111,
+	WM_SYSCOMMAND =                   0x0112,
+	WM_TIMER =                        0x0113,
+	WM_HSCROLL =                      0x0114,
+	WM_VSCROLL =                      0x0115,
+	WM_INITMENU =                     0x0116,
+	WM_INITMENUPOPUP =                0x0117,
+	WM_MENUSELECT =                   0x011F,
+	WM_MENUCHAR =                     0x0120,
+	WM_ENTERIDLE =                    0x0121,
+
+	WM_CTLCOLORMSGBOX =               0x0132,
+	WM_CTLCOLOREDIT =                 0x0133,
+	WM_CTLCOLORLISTBOX =              0x0134,
+	WM_CTLCOLORBTN =                  0x0135,
+	WM_CTLCOLORDLG =                  0x0136,
+	WM_CTLCOLORSCROLLBAR =            0x0137,
+	WM_CTLCOLORSTATIC =               0x0138,
+
+
+
+	WM_MOUSEFIRST =                   0x0200,
+	WM_MOUSEMOVE =                    0x0200,
+	WM_LBUTTONDOWN =                  0x0201,
+	WM_LBUTTONUP =                    0x0202,
+	WM_LBUTTONDBLCLK =                0x0203,
+	WM_RBUTTONDOWN =                  0x0204,
+	WM_RBUTTONUP =                    0x0205,
+	WM_RBUTTONDBLCLK =                0x0206,
+	WM_MBUTTONDOWN =                  0x0207,
+	WM_MBUTTONUP =                    0x0208,
+	WM_MBUTTONDBLCLK =                0x0209,
+
+
+
+	WM_MOUSELAST =                    0x0209,
+
+
+
+
+
+
+
+
+	WM_PARENTNOTIFY =                 0x0210,
+	MENULOOP_WINDOW =                 0,
+	MENULOOP_POPUP =                  1,
+	WM_ENTERMENULOOP =                0x0211,
+	WM_EXITMENULOOP =                 0x0212,
+
+
+	WM_NEXTMENU =                     0x0213,
+}
+
+enum
+{
+/*
+ * Dialog Box Command IDs
+ */
+	IDOK =                1,
+	IDCANCEL =            2,
+	IDABORT =             3,
+	IDRETRY =             4,
+	IDIGNORE =            5,
+	IDYES =               6,
+	IDNO =                7,
+
+	IDCLOSE =         8,
+	IDHELP =          9,
+
+
+// end_r_winuser
+
+
+
+/*
+ * Control Manager Structures and Definitions
+ */
+
+
+
+// begin_r_winuser
+
+/*
+ * Edit Control Styles
+ */
+	ES_LEFT =             0x0000,
+	ES_CENTER =           0x0001,
+	ES_RIGHT =            0x0002,
+	ES_MULTILINE =        0x0004,
+	ES_UPPERCASE =        0x0008,
+	ES_LOWERCASE =        0x0010,
+	ES_PASSWORD =         0x0020,
+	ES_AUTOVSCROLL =      0x0040,
+	ES_AUTOHSCROLL =      0x0080,
+	ES_NOHIDESEL =        0x0100,
+	ES_OEMCONVERT =       0x0400,
+	ES_READONLY =         0x0800,
+	ES_WANTRETURN =       0x1000,
+
+	ES_NUMBER =           0x2000,
+
+
+// end_r_winuser
+
+
+
+/*
+ * Edit Control Notification Codes
+ */
+	EN_SETFOCUS =         0x0100,
+	EN_KILLFOCUS =        0x0200,
+	EN_CHANGE =           0x0300,
+	EN_UPDATE =           0x0400,
+	EN_ERRSPACE =         0x0500,
+	EN_MAXTEXT =          0x0501,
+	EN_HSCROLL =          0x0601,
+	EN_VSCROLL =          0x0602,
+
+
+/* Edit control EM_SETMARGIN parameters */
+	EC_LEFTMARGIN =       0x0001,
+	EC_RIGHTMARGIN =      0x0002,
+	EC_USEFONTINFO =      0xffff,
+
+
+
+
+// begin_r_winuser
+
+/*
+ * Edit Control Messages
+ */
+	EM_GETSEL =               0x00B0,
+	EM_SETSEL =               0x00B1,
+	EM_GETRECT =              0x00B2,
+	EM_SETRECT =              0x00B3,
+	EM_SETRECTNP =            0x00B4,
+	EM_SCROLL =               0x00B5,
+	EM_LINESCROLL =           0x00B6,
+	EM_SCROLLCARET =          0x00B7,
+	EM_GETMODIFY =            0x00B8,
+	EM_SETMODIFY =            0x00B9,
+	EM_GETLINECOUNT =         0x00BA,
+	EM_LINEINDEX =            0x00BB,
+	EM_SETHANDLE =            0x00BC,
+	EM_GETHANDLE =            0x00BD,
+	EM_GETTHUMB =             0x00BE,
+	EM_LINELENGTH =           0x00C1,
+	EM_REPLACESEL =           0x00C2,
+	EM_GETLINE =              0x00C4,
+	EM_LIMITTEXT =            0x00C5,
+	EM_CANUNDO =              0x00C6,
+	EM_UNDO =                 0x00C7,
+	EM_FMTLINES =             0x00C8,
+	EM_LINEFROMCHAR =         0x00C9,
+	EM_SETTABSTOPS =          0x00CB,
+	EM_SETPASSWORDCHAR =      0x00CC,
+	EM_EMPTYUNDOBUFFER =      0x00CD,
+	EM_GETFIRSTVISIBLELINE =  0x00CE,
+	EM_SETREADONLY =          0x00CF,
+	EM_SETWORDBREAKPROC =     0x00D0,
+	EM_GETWORDBREAKPROC =     0x00D1,
+	EM_GETPASSWORDCHAR =      0x00D2,
+
+	EM_SETMARGINS =           0x00D3,
+	EM_GETMARGINS =           0x00D4,
+	EM_SETLIMITTEXT =         EM_LIMITTEXT, /* ;win40 Name change */
+	EM_GETLIMITTEXT =         0x00D5,
+	EM_POSFROMCHAR =          0x00D6,
+	EM_CHARFROMPOS =          0x00D7,
+
+
+
+// end_r_winuser
+
+
+/*
+ * EDITWORDBREAKPROC code values
+ */
+	WB_LEFT =            0,
+	WB_RIGHT =           1,
+	WB_ISDELIMITER =     2,
+
+// begin_r_winuser
+
+/*
+ * Button Control Styles
+ */
+	BS_PUSHBUTTON =       0x00000000,
+	BS_DEFPUSHBUTTON =    0x00000001,
+	BS_CHECKBOX =         0x00000002,
+	BS_AUTOCHECKBOX =     0x00000003,
+	BS_RADIOBUTTON =      0x00000004,
+	BS_3STATE =           0x00000005,
+	BS_AUTO3STATE =       0x00000006,
+	BS_GROUPBOX =         0x00000007,
+	BS_USERBUTTON =       0x00000008,
+	BS_AUTORADIOBUTTON =  0x00000009,
+	BS_OWNERDRAW =        0x0000000B,
+	BS_LEFTTEXT =         0x00000020,
+
+	BS_TEXT =             0x00000000,
+	BS_ICON =             0x00000040,
+	BS_BITMAP =           0x00000080,
+	BS_LEFT =             0x00000100,
+	BS_RIGHT =            0x00000200,
+	BS_CENTER =           0x00000300,
+	BS_TOP =              0x00000400,
+	BS_BOTTOM =           0x00000800,
+	BS_VCENTER =          0x00000C00,
+	BS_PUSHLIKE =         0x00001000,
+	BS_MULTILINE =        0x00002000,
+	BS_NOTIFY =           0x00004000,
+	BS_FLAT =             0x00008000,
+	BS_RIGHTBUTTON =      BS_LEFTTEXT,
+
+
+
+/*
+ * User Button Notification Codes
+ */
+	BN_CLICKED =          0,
+	BN_PAINT =            1,
+	BN_HILITE =           2,
+	BN_UNHILITE =         3,
+	BN_DISABLE =          4,
+	BN_DOUBLECLICKED =    5,
+
+	BN_PUSHED =           BN_HILITE,
+	BN_UNPUSHED =         BN_UNHILITE,
+	BN_DBLCLK =           BN_DOUBLECLICKED,
+	BN_SETFOCUS =         6,
+	BN_KILLFOCUS =        7,
+
+/*
+ * Button Control Messages
+ */
+	BM_GETCHECK =        0x00F0,
+	BM_SETCHECK =        0x00F1,
+	BM_GETSTATE =        0x00F2,
+	BM_SETSTATE =        0x00F3,
+	BM_SETSTYLE =        0x00F4,
+
+	BM_CLICK =           0x00F5,
+	BM_GETIMAGE =        0x00F6,
+	BM_SETIMAGE =        0x00F7,
+
+	BST_UNCHECKED =      0x0000,
+	BST_CHECKED =        0x0001,
+	BST_INDETERMINATE =  0x0002,
+	BST_PUSHED =         0x0004,
+	BST_FOCUS =          0x0008,
+
+
+/*
+ * Static Control Constants
+ */
+	SS_LEFT =             0x00000000,
+	SS_CENTER =           0x00000001,
+	SS_RIGHT =            0x00000002,
+	SS_ICON =             0x00000003,
+	SS_BLACKRECT =        0x00000004,
+	SS_GRAYRECT =         0x00000005,
+	SS_WHITERECT =        0x00000006,
+	SS_BLACKFRAME =       0x00000007,
+	SS_GRAYFRAME =        0x00000008,
+	SS_WHITEFRAME =       0x00000009,
+	SS_USERITEM =         0x0000000A,
+	SS_SIMPLE =           0x0000000B,
+	SS_LEFTNOWORDWRAP =   0x0000000C,
+
+	SS_OWNERDRAW =        0x0000000D,
+	SS_BITMAP =           0x0000000E,
+	SS_ENHMETAFILE =      0x0000000F,
+	SS_ETCHEDHORZ =       0x00000010,
+	SS_ETCHEDVERT =       0x00000011,
+	SS_ETCHEDFRAME =      0x00000012,
+	SS_TYPEMASK =         0x0000001F,
+
+	SS_NOPREFIX =         0x00000080, /* Don't do "&" character translation */
+
+	SS_NOTIFY =           0x00000100,
+	SS_CENTERIMAGE =      0x00000200,
+	SS_RIGHTJUST =        0x00000400,
+	SS_REALSIZEIMAGE =    0x00000800,
+	SS_SUNKEN =           0x00001000,
+	SS_ENDELLIPSIS =      0x00004000,
+	SS_PATHELLIPSIS =     0x00008000,
+	SS_WORDELLIPSIS =     0x0000C000,
+	SS_ELLIPSISMASK =     0x0000C000,
+
+
+// end_r_winuser
+
+
+/*
+ * Static Control Mesages
+ */
+	STM_SETICON =         0x0170,
+	STM_GETICON =         0x0171,
+
+	STM_SETIMAGE =        0x0172,
+	STM_GETIMAGE =        0x0173,
+	STN_CLICKED =         0,
+	STN_DBLCLK =          1,
+	STN_ENABLE =          2,
+	STN_DISABLE =         3,
+
+	STM_MSGMAX =          0x0174,
+}
+
+
+enum
+{
+/*
+ * Window Messages
+ */
+
+	WM_NULL =                         0x0000,
+	WM_CREATE =                       0x0001,
+	WM_DESTROY =                      0x0002,
+	WM_MOVE =                         0x0003,
+	WM_SIZE =                         0x0005,
+
+	WM_ACTIVATE =                     0x0006,
+/*
+ * WM_ACTIVATE state values
+ */
+	WA_INACTIVE =     0,
+	WA_ACTIVE =       1,
+	WA_CLICKACTIVE =  2,
+
+	WM_SETFOCUS =                     0x0007,
+	WM_KILLFOCUS =                    0x0008,
+	WM_ENABLE =                       0x000A,
+	WM_SETREDRAW =                    0x000B,
+	WM_SETTEXT =                      0x000C,
+	WM_GETTEXT =                      0x000D,
+	WM_GETTEXTLENGTH =                0x000E,
+	WM_PAINT =                        0x000F,
+	WM_CLOSE =                        0x0010,
+	WM_QUERYENDSESSION =              0x0011,
+	WM_QUIT =                         0x0012,
+	WM_QUERYOPEN =                    0x0013,
+	WM_ERASEBKGND =                   0x0014,
+	WM_SYSCOLORCHANGE =               0x0015,
+	WM_ENDSESSION =                   0x0016,
+	WM_SHOWWINDOW =                   0x0018,
+	WM_WININICHANGE =                 0x001A,
+
+	WM_SETTINGCHANGE =                WM_WININICHANGE,
+
+
+
+	WM_DEVMODECHANGE =                0x001B,
+	WM_ACTIVATEAPP =                  0x001C,
+	WM_FONTCHANGE =                   0x001D,
+	WM_TIMECHANGE =                   0x001E,
+	WM_CANCELMODE =                   0x001F,
+	WM_SETCURSOR =                    0x0020,
+	WM_MOUSEACTIVATE =                0x0021,
+	WM_CHILDACTIVATE =                0x0022,
+	WM_QUEUESYNC =                    0x0023,
+
+	WM_GETMINMAXINFO =                0x0024,
+}
+
+struct RECT
+{
+    LONG    left;
+    LONG    top;
+    LONG    right;
+    LONG    bottom;
+}
+alias RECT* PRECT, NPRECT, LPRECT;
+
+struct PAINTSTRUCT {
+    HDC         hdc;
+    BOOL        fErase;
+    RECT        rcPaint;
+    BOOL        fRestore;
+    BOOL        fIncUpdate;
+    BYTE        rgbReserved[32];
+}
+alias PAINTSTRUCT* PPAINTSTRUCT, NPPAINTSTRUCT, LPPAINTSTRUCT;
+
+// flags for GetDCEx()
+
+enum
+{
+	DCX_WINDOW =           0x00000001,
+	DCX_CACHE =            0x00000002,
+	DCX_NORESETATTRS =     0x00000004,
+	DCX_CLIPCHILDREN =     0x00000008,
+	DCX_CLIPSIBLINGS =     0x00000010,
+	DCX_PARENTCLIP =       0x00000020,
+	DCX_EXCLUDERGN =       0x00000040,
+	DCX_INTERSECTRGN =     0x00000080,
+	DCX_EXCLUDEUPDATE =    0x00000100,
+	DCX_INTERSECTUPDATE =  0x00000200,
+	DCX_LOCKWINDOWUPDATE = 0x00000400,
+	DCX_VALIDATE =         0x00200000,
+}
+
+export
+{
+ BOOL UpdateWindow(HWND hWnd);
+ HWND SetActiveWindow(HWND hWnd);
+ HWND GetForegroundWindow();
+ BOOL PaintDesktop(HDC hdc);
+ BOOL SetForegroundWindow(HWND hWnd);
+ HWND WindowFromDC(HDC hDC);
+ HDC GetDC(HWND hWnd);
+ HDC GetDCEx(HWND hWnd, HRGN hrgnClip, DWORD flags);
+ HDC GetWindowDC(HWND hWnd);
+ int ReleaseDC(HWND hWnd, HDC hDC);
+ HDC BeginPaint(HWND hWnd, LPPAINTSTRUCT lpPaint);
+ BOOL EndPaint(HWND hWnd, PAINTSTRUCT *lpPaint);
+ BOOL GetUpdateRect(HWND hWnd, LPRECT lpRect, BOOL bErase);
+ int GetUpdateRgn(HWND hWnd, HRGN hRgn, BOOL bErase);
+ int SetWindowRgn(HWND hWnd, HRGN hRgn, BOOL bRedraw);
+ int GetWindowRgn(HWND hWnd, HRGN hRgn);
+ int ExcludeUpdateRgn(HDC hDC, HWND hWnd);
+ BOOL InvalidateRect(HWND hWnd, RECT *lpRect, BOOL bErase);
+ BOOL ValidateRect(HWND hWnd, RECT *lpRect);
+ BOOL InvalidateRgn(HWND hWnd, HRGN hRgn, BOOL bErase);
+ BOOL ValidateRgn(HWND hWnd, HRGN hRgn);
+ BOOL RedrawWindow(HWND hWnd, RECT *lprcUpdate, HRGN hrgnUpdate, UINT flags);
+}
+
+// flags for RedrawWindow()
+enum
+{
+	RDW_INVALIDATE =          0x0001,
+	RDW_INTERNALPAINT =       0x0002,
+	RDW_ERASE =               0x0004,
+	RDW_VALIDATE =            0x0008,
+	RDW_NOINTERNALPAINT =     0x0010,
+	RDW_NOERASE =             0x0020,
+	RDW_NOCHILDREN =          0x0040,
+	RDW_ALLCHILDREN =         0x0080,
+	RDW_UPDATENOW =           0x0100,
+	RDW_ERASENOW =            0x0200,
+	RDW_FRAME =               0x0400,
+	RDW_NOFRAME =             0x0800,
+}
+
+export
+{
+ BOOL GetClientRect(HWND hWnd, LPRECT lpRect);
+ BOOL GetWindowRect(HWND hWnd, LPRECT lpRect);
+ BOOL AdjustWindowRect(LPRECT lpRect, DWORD dwStyle, BOOL bMenu);
+ BOOL AdjustWindowRectEx(LPRECT lpRect, DWORD dwStyle, BOOL bMenu, DWORD dwExStyle);
+ HFONT CreateFontA(int, int, int, int, int, DWORD,
+                             DWORD, DWORD, DWORD, DWORD, DWORD,
+                             DWORD, DWORD, LPCSTR);
+ HFONT CreateFontW(int, int, int, int, int, DWORD,
+                             DWORD, DWORD, DWORD, DWORD, DWORD,
+                             DWORD, DWORD, LPCWSTR);
+}
+
+enum
+{
+	OUT_DEFAULT_PRECIS =          0,
+	OUT_STRING_PRECIS =           1,
+	OUT_CHARACTER_PRECIS =        2,
+	OUT_STROKE_PRECIS =           3,
+	OUT_TT_PRECIS =               4,
+	OUT_DEVICE_PRECIS =           5,
+	OUT_RASTER_PRECIS =           6,
+	OUT_TT_ONLY_PRECIS =          7,
+	OUT_OUTLINE_PRECIS =          8,
+	OUT_SCREEN_OUTLINE_PRECIS =   9,
+
+	CLIP_DEFAULT_PRECIS =     0,
+	CLIP_CHARACTER_PRECIS =   1,
+	CLIP_STROKE_PRECIS =      2,
+	CLIP_MASK =               0xf,
+	CLIP_LH_ANGLES =          (1<<4),
+	CLIP_TT_ALWAYS =          (2<<4),
+	CLIP_EMBEDDED =           (8<<4),
+
+	DEFAULT_QUALITY =         0,
+	DRAFT_QUALITY =           1,
+	PROOF_QUALITY =           2,
+
+	NONANTIALIASED_QUALITY =  3,
+	ANTIALIASED_QUALITY =     4,
+
+
+	DEFAULT_PITCH =           0,
+	FIXED_PITCH =             1,
+	VARIABLE_PITCH =          2,
+
+	MONO_FONT =               8,
+
+
+	ANSI_CHARSET =            0,
+	DEFAULT_CHARSET =         1,
+	SYMBOL_CHARSET =          2,
+	SHIFTJIS_CHARSET =        128,
+	HANGEUL_CHARSET =         129,
+	GB2312_CHARSET =          134,
+	CHINESEBIG5_CHARSET =     136,
+	OEM_CHARSET =             255,
+
+	JOHAB_CHARSET =           130,
+	HEBREW_CHARSET =          177,
+	ARABIC_CHARSET =          178,
+	GREEK_CHARSET =           161,
+	TURKISH_CHARSET =         162,
+	VIETNAMESE_CHARSET =      163,
+	THAI_CHARSET =            222,
+	EASTEUROPE_CHARSET =      238,
+	RUSSIAN_CHARSET =         204,
+
+	MAC_CHARSET =             77,
+	BALTIC_CHARSET =          186,
+
+	FS_LATIN1 =               0x00000001L,
+	FS_LATIN2 =               0x00000002L,
+	FS_CYRILLIC =             0x00000004L,
+	FS_GREEK =                0x00000008L,
+	FS_TURKISH =              0x00000010L,
+	FS_HEBREW =               0x00000020L,
+	FS_ARABIC =               0x00000040L,
+	FS_BALTIC =               0x00000080L,
+	FS_VIETNAMESE =           0x00000100L,
+	FS_THAI =                 0x00010000L,
+	FS_JISJAPAN =             0x00020000L,
+	FS_CHINESESIMP =          0x00040000L,
+	FS_WANSUNG =              0x00080000L,
+	FS_CHINESETRAD =          0x00100000L,
+	FS_JOHAB =                0x00200000L,
+	FS_SYMBOL =               cast(int)0x80000000L,
+
+
+/* Font Families */
+	FF_DONTCARE =         (0<<4), /* Don't care or don't know. */
+	FF_ROMAN =            (1<<4), /* Variable stroke width, serifed. */
+                                    /* Times Roman, Century Schoolbook, etc. */
+	FF_SWISS =            (2<<4), /* Variable stroke width, sans-serifed. */
+                                    /* Helvetica, Swiss, etc. */
+	FF_MODERN =           (3<<4), /* Constant stroke width, serifed or sans-serifed. */
+                                    /* Pica, Elite, Courier, etc. */
+	FF_SCRIPT =           (4<<4), /* Cursive, etc. */
+	FF_DECORATIVE =       (5<<4), /* Old English, etc. */
+
+/* Font Weights */
+	FW_DONTCARE =         0,
+	FW_THIN =             100,
+	FW_EXTRALIGHT =       200,
+	FW_LIGHT =            300,
+	FW_NORMAL =           400,
+	FW_MEDIUM =           500,
+	FW_SEMIBOLD =         600,
+	FW_BOLD =             700,
+	FW_EXTRABOLD =        800,
+	FW_HEAVY =            900,
+
+	FW_ULTRALIGHT =       FW_EXTRALIGHT,
+	FW_REGULAR =          FW_NORMAL,
+	FW_DEMIBOLD =         FW_SEMIBOLD,
+	FW_ULTRABOLD =        FW_EXTRABOLD,
+	FW_BLACK =            FW_HEAVY,
+
+	PANOSE_COUNT =               10,
+	PAN_FAMILYTYPE_INDEX =        0,
+	PAN_SERIFSTYLE_INDEX =        1,
+	PAN_WEIGHT_INDEX =            2,
+	PAN_PROPORTION_INDEX =        3,
+	PAN_CONTRAST_INDEX =          4,
+	PAN_STROKEVARIATION_INDEX =   5,
+	PAN_ARMSTYLE_INDEX =          6,
+	PAN_LETTERFORM_INDEX =        7,
+	PAN_MIDLINE_INDEX =           8,
+	PAN_XHEIGHT_INDEX =           9,
+
+	PAN_CULTURE_LATIN =           0,
+}
+
+struct RGBQUAD {
+        BYTE    rgbBlue;
+        BYTE    rgbGreen;
+        BYTE    rgbRed;
+        BYTE    rgbReserved;
+}
+alias RGBQUAD* LPRGBQUAD;
+
+struct BITMAPINFOHEADER
+{
+        DWORD      biSize;
+        LONG       biWidth;
+        LONG       biHeight;
+        WORD       biPlanes;
+        WORD       biBitCount;
+        DWORD      biCompression;
+        DWORD      biSizeImage;
+        LONG       biXPelsPerMeter;
+        LONG       biYPelsPerMeter;
+        DWORD      biClrUsed;
+        DWORD      biClrImportant;
+}
+alias BITMAPINFOHEADER* LPBITMAPINFOHEADER, PBITMAPINFOHEADER;
+
+struct BITMAPINFO {
+    BITMAPINFOHEADER    bmiHeader;
+    RGBQUAD             bmiColors[1];
+}
+alias BITMAPINFO* LPBITMAPINFO, PBITMAPINFO;
+
+struct PALETTEENTRY {
+    BYTE        peRed;
+    BYTE        peGreen;
+    BYTE        peBlue;
+    BYTE        peFlags;
+}
+alias PALETTEENTRY* PPALETTEENTRY, LPPALETTEENTRY;
+
+struct LOGPALETTE {
+    WORD        palVersion;
+    WORD        palNumEntries;
+    PALETTEENTRY        palPalEntry[1];
+}
+alias LOGPALETTE* PLOGPALETTE, NPLOGPALETTE, LPLOGPALETTE;
+
+/* Pixel format descriptor */
+struct PIXELFORMATDESCRIPTOR
+{
+    WORD  nSize;
+    WORD  nVersion;
+    DWORD dwFlags;
+    BYTE  iPixelType;
+    BYTE  cColorBits;
+    BYTE  cRedBits;
+    BYTE  cRedShift;
+    BYTE  cGreenBits;
+    BYTE  cGreenShift;
+    BYTE  cBlueBits;
+    BYTE  cBlueShift;
+    BYTE  cAlphaBits;
+    BYTE  cAlphaShift;
+    BYTE  cAccumBits;
+    BYTE  cAccumRedBits;
+    BYTE  cAccumGreenBits;
+    BYTE  cAccumBlueBits;
+    BYTE  cAccumAlphaBits;
+    BYTE  cDepthBits;
+    BYTE  cStencilBits;
+    BYTE  cAuxBuffers;
+    BYTE  iLayerType;
+    BYTE  bReserved;
+    DWORD dwLayerMask;
+    DWORD dwVisibleMask;
+    DWORD dwDamageMask;
+}
+alias PIXELFORMATDESCRIPTOR* PPIXELFORMATDESCRIPTOR, LPPIXELFORMATDESCRIPTOR;
+
+
+export
+{
+ BOOL   RoundRect(HDC, int, int, int, int, int, int);
+ BOOL   ResizePalette(HPALETTE, UINT);
+ int    SaveDC(HDC);
+ int    SelectClipRgn(HDC, HRGN);
+ int    ExtSelectClipRgn(HDC, HRGN, int);
+ int    SetMetaRgn(HDC);
+ HGDIOBJ   SelectObject(HDC, HGDIOBJ);
+ HPALETTE   SelectPalette(HDC, HPALETTE, BOOL);
+ COLORREF   SetBkColor(HDC, COLORREF);
+ int     SetBkMode(HDC, int);
+ LONG    SetBitmapBits(HBITMAP, DWORD, void *);
+ UINT    SetBoundsRect(HDC,   RECT *, UINT);
+ int     SetDIBits(HDC, HBITMAP, UINT, UINT, void *, BITMAPINFO *, UINT);
+ int     SetDIBitsToDevice(HDC, int, int, DWORD, DWORD, int,
+        int, UINT, UINT, void *, BITMAPINFO *, UINT);
+ DWORD   SetMapperFlags(HDC, DWORD);
+ int     SetGraphicsMode(HDC hdc, int iMode);
+ int     SetMapMode(HDC, int);
+ HMETAFILE     SetMetaFileBitsEx(UINT, BYTE *);
+ UINT    SetPaletteEntries(HPALETTE, UINT, UINT, PALETTEENTRY *);
+ COLORREF   SetPixel(HDC, int, int, COLORREF);
+ BOOL     SetPixelV(HDC, int, int, COLORREF);
+ BOOL    SetPixelFormat(HDC, int, PIXELFORMATDESCRIPTOR *);
+ int     SetPolyFillMode(HDC, int);
+ BOOL    StretchBlt(HDC, int, int, int, int, HDC, int, int, int, int, DWORD);
+ BOOL    SetRectRgn(HRGN, int, int, int, int);
+ int     StretchDIBits(HDC, int, int, int, int, int, int, int, int,
+         void *, BITMAPINFO *, UINT, DWORD);
+ int     SetROP2(HDC, int);
+ int     SetStretchBltMode(HDC, int);
+ UINT    SetSystemPaletteUse(HDC, UINT);
+ int     SetTextCharacterExtra(HDC, int);
+ COLORREF   SetTextColor(HDC, COLORREF);
+ UINT    SetTextAlign(HDC, UINT);
+ BOOL    SetTextJustification(HDC, int, int);
+ BOOL    UpdateColors(HDC);
+}
+
+/* Text Alignment Options */
+enum
+{
+	TA_NOUPDATECP =                0,
+	TA_UPDATECP =                  1,
+
+	TA_LEFT =                      0,
+	TA_RIGHT =                     2,
+	TA_CENTER =                    6,
+
+	TA_TOP =                       0,
+	TA_BOTTOM =                    8,
+	TA_BASELINE =                  24,
+
+	TA_RTLREADING =                256,
+	TA_MASK =       (TA_BASELINE+TA_CENTER+TA_UPDATECP+TA_RTLREADING),
+}
+
+struct POINT
+{
+    LONG  x;
+    LONG  y;
+}
+alias POINT* PPOINT, NPPOINT, LPPOINT;
+
+
+export
+{
+ BOOL    MoveToEx(HDC, int, int, LPPOINT);
+ BOOL    TextOutA(HDC, int, int, LPCSTR, int);
+ BOOL    TextOutW(HDC, int, int, LPCWSTR, int);
+}
+
+export void PostQuitMessage(int nExitCode);
+export LRESULT DefWindowProcA(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
+export HMODULE GetModuleHandleA(LPCSTR lpModuleName);
+
+alias LRESULT (* WNDPROC)(HWND, UINT, WPARAM, LPARAM);
+
+struct WNDCLASSEXA {
+    UINT        cbSize;
+    /* Win 3.x */
+    UINT        style;
+    WNDPROC     lpfnWndProc;
+    int         cbClsExtra;
+    int         cbWndExtra;
+    HINSTANCE   hInstance;
+    HICON       hIcon;
+    HCURSOR     hCursor;
+    HBRUSH      hbrBackground;
+    LPCSTR      lpszMenuName;
+    LPCSTR      lpszClassName;
+    /* Win 4.0 */
+    HICON       hIconSm;
+}
+alias WNDCLASSEXA* PWNDCLASSEXA, NPWNDCLASSEXA, LPWNDCLASSEXA;
+
+
+struct WNDCLASSA {
+    UINT        style;
+    WNDPROC     lpfnWndProc;
+    int         cbClsExtra;
+    int         cbWndExtra;
+    HINSTANCE   hInstance;
+    HICON       hIcon;
+    HCURSOR     hCursor;
+    HBRUSH      hbrBackground;
+    LPCSTR      lpszMenuName;
+    LPCSTR      lpszClassName;
+}
+alias WNDCLASSA* PWNDCLASSA, NPWNDCLASSA, LPWNDCLASSA;
+alias WNDCLASSA WNDCLASS;
+
+/*
+ * Window Styles
+ */
+enum : uint
+{
+	WS_OVERLAPPED =       0x00000000,
+	WS_POPUP =            0x80000000,
+	WS_CHILD =            0x40000000,
+	WS_MINIMIZE =         0x20000000,
+	WS_VISIBLE =          0x10000000,
+	WS_DISABLED =         0x08000000,
+	WS_CLIPSIBLINGS =     0x04000000,
+	WS_CLIPCHILDREN =     0x02000000,
+	WS_MAXIMIZE =         0x01000000,
+	WS_CAPTION =          0x00C00000,  /* WS_BORDER | WS_DLGFRAME  */
+	WS_BORDER =           0x00800000,
+	WS_DLGFRAME =         0x00400000,
+	WS_VSCROLL =          0x00200000,
+	WS_HSCROLL =          0x00100000,
+	WS_SYSMENU =          0x00080000,
+	WS_THICKFRAME =       0x00040000,
+	WS_GROUP =            0x00020000,
+	WS_TABSTOP =          0x00010000,
+
+	WS_MINIMIZEBOX =      0x00020000,
+	WS_MAXIMIZEBOX =      0x00010000,
+
+	WS_TILED =            WS_OVERLAPPED,
+	WS_ICONIC =           WS_MINIMIZE,
+	WS_SIZEBOX =          WS_THICKFRAME,
+
+/*
+ * Common Window Styles
+ */
+	WS_OVERLAPPEDWINDOW = (WS_OVERLAPPED |            WS_CAPTION |  WS_SYSMENU |  WS_THICKFRAME |            WS_MINIMIZEBOX |                 WS_MAXIMIZEBOX),
+	WS_TILEDWINDOW =      WS_OVERLAPPEDWINDOW,
+	WS_POPUPWINDOW =      (WS_POPUP |  WS_BORDER |  WS_SYSMENU),
+	WS_CHILDWINDOW =      (WS_CHILD),
+}
+
+/*
+ * Class styles
+ */
+enum
+{
+	CS_VREDRAW =          0x0001,
+	CS_HREDRAW =          0x0002,
+	CS_KEYCVTWINDOW =     0x0004,
+	CS_DBLCLKS =          0x0008,
+	CS_OWNDC =            0x0020,
+	CS_CLASSDC =          0x0040,
+	CS_PARENTDC =         0x0080,
+	CS_NOKEYCVT =         0x0100,
+	CS_NOCLOSE =          0x0200,
+	CS_SAVEBITS =         0x0800,
+	CS_BYTEALIGNCLIENT =  0x1000,
+	CS_BYTEALIGNWINDOW =  0x2000,
+	CS_GLOBALCLASS =      0x4000,
+
+
+	CS_IME =              0x00010000,
+}
+
+export
+{
+ HICON LoadIconA(HINSTANCE hInstance, LPCSTR lpIconName);
+ HICON LoadIconW(HINSTANCE hInstance, LPCWSTR lpIconName);
+ HCURSOR LoadCursorA(HINSTANCE hInstance, LPCSTR lpCursorName);
+ HCURSOR LoadCursorW(HINSTANCE hInstance, LPCWSTR lpCursorName);
+}
+
+const LPSTR IDI_APPLICATION =     cast(LPSTR)(32512);
+
+const LPSTR IDC_ARROW =           cast(LPSTR)(32512);
+const LPSTR IDC_CROSS =           cast(LPSTR)(32515);
+
+/*
+ * Color Types
+ */
+enum
+{
+	CTLCOLOR_MSGBOX =         0,
+	CTLCOLOR_EDIT =           1,
+	CTLCOLOR_LISTBOX =        2,
+	CTLCOLOR_BTN =            3,
+	CTLCOLOR_DLG =            4,
+	CTLCOLOR_SCROLLBAR =      5,
+	CTLCOLOR_STATIC =         6,
+	CTLCOLOR_MAX =            7,
+
+	COLOR_SCROLLBAR =         0,
+	COLOR_BACKGROUND =        1,
+	COLOR_ACTIVECAPTION =     2,
+	COLOR_INACTIVECAPTION =   3,
+	COLOR_MENU =              4,
+	COLOR_WINDOW =            5,
+	COLOR_WINDOWFRAME =       6,
+	COLOR_MENUTEXT =          7,
+	COLOR_WINDOWTEXT =        8,
+	COLOR_CAPTIONTEXT =       9,
+	COLOR_ACTIVEBORDER =      10,
+	COLOR_INACTIVEBORDER =    11,
+	COLOR_APPWORKSPACE =      12,
+	COLOR_HIGHLIGHT =         13,
+	COLOR_HIGHLIGHTTEXT =     14,
+	COLOR_BTNFACE =           15,
+	COLOR_BTNSHADOW =         16,
+	COLOR_GRAYTEXT =          17,
+	COLOR_BTNTEXT =           18,
+	COLOR_INACTIVECAPTIONTEXT = 19,
+	COLOR_BTNHIGHLIGHT =      20,
+
+
+	COLOR_3DDKSHADOW =        21,
+	COLOR_3DLIGHT =           22,
+	COLOR_INFOTEXT =          23,
+	COLOR_INFOBK =            24,
+
+	COLOR_DESKTOP =           COLOR_BACKGROUND,
+	COLOR_3DFACE =            COLOR_BTNFACE,
+	COLOR_3DSHADOW =          COLOR_BTNSHADOW,
+	COLOR_3DHIGHLIGHT =       COLOR_BTNHIGHLIGHT,
+	COLOR_3DHILIGHT =         COLOR_BTNHIGHLIGHT,
+	COLOR_BTNHILIGHT =        COLOR_BTNHIGHLIGHT,
+}
+
+const int CW_USEDEFAULT = cast(int)0x80000000;
+/*
+ * Special value for CreateWindow, et al.
+ */
+const HWND HWND_DESKTOP = (cast(HWND)0);
+
+
+export ATOM RegisterClassA(WNDCLASSA *lpWndClass);
+
+export HWND CreateWindowExA(
+    DWORD dwExStyle,
+    LPCSTR lpClassName,
+    LPCSTR lpWindowName,
+    DWORD dwStyle,
+    int X,
+    int Y,
+    int nWidth,
+    int nHeight,
+    HWND hWndParent ,
+    HMENU hMenu,
+    HINSTANCE hInstance,
+    LPVOID lpParam);
+
+
+HWND CreateWindowA(
+    LPCSTR lpClassName,
+    LPCSTR lpWindowName,
+    DWORD dwStyle,
+    int X,
+    int Y,
+    int nWidth,
+    int nHeight,
+    HWND hWndParent ,
+    HMENU hMenu,
+    HINSTANCE hInstance,
+    LPVOID lpParam)
+{
+    return CreateWindowExA(0, lpClassName, lpWindowName, dwStyle, X, Y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam);
+}
+
+/*
+ * Message structure
+ */
+struct MSG {
+    HWND        hwnd;
+    UINT        message;
+    WPARAM      wParam;
+    LPARAM      lParam;
+    DWORD       time;
+    POINT       pt;
+}
+alias MSG* PMSG, NPMSG, LPMSG;
+
+export
+{
+ BOOL GetMessageA(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax);
+ BOOL TranslateMessage(MSG *lpMsg);
+ LONG DispatchMessageA(MSG *lpMsg);
+ BOOL PeekMessageA(MSG *lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax, UINT wRemoveMsg);
+ HWND GetFocus();
+}
+
+export DWORD ExpandEnvironmentStringsA(LPCSTR lpSrc, LPSTR lpDst, DWORD nSize);
+
+export
+{
+ BOOL IsValidCodePage(UINT CodePage);
+ UINT GetACP();
+ UINT GetOEMCP();
+ //BOOL GetCPInfo(UINT CodePage, LPCPINFO lpCPInfo);
+ BOOL IsDBCSLeadByte(BYTE TestChar);
+ BOOL IsDBCSLeadByteEx(UINT CodePage, BYTE TestChar);
+ int MultiByteToWideChar(UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr, int cchMultiByte, LPWSTR lpWideCharStr, int cchWideChar);
+ int WideCharToMultiByte(UINT CodePage, DWORD dwFlags, LPCWSTR lpWideCharStr, int cchWideChar, LPSTR lpMultiByteStr, int cchMultiByte, LPCSTR lpDefaultChar, LPBOOL lpUsedDefaultChar);
+}
+
+export HANDLE CreateFileMappingA(HANDLE hFile, LPSECURITY_ATTRIBUTES lpFileMappingAttributes, DWORD flProtect, DWORD dwMaximumSizeHigh, DWORD dwMaximumSizeLow, LPCSTR lpName);
+export HANDLE CreateFileMappingW(HANDLE hFile, LPSECURITY_ATTRIBUTES lpFileMappingAttributes, DWORD flProtect, DWORD dwMaximumSizeHigh, DWORD dwMaximumSizeLow, LPCWSTR lpName);
+
+export BOOL GetMailslotInfo(HANDLE hMailslot, LPDWORD lpMaxMessageSize, LPDWORD lpNextSize, LPDWORD lpMessageCount, LPDWORD lpReadTimeout);
+export BOOL SetMailslotInfo(HANDLE hMailslot, DWORD lReadTimeout);
+export LPVOID MapViewOfFile(HANDLE hFileMappingObject, DWORD dwDesiredAccess, DWORD dwFileOffsetHigh, DWORD dwFileOffsetLow, DWORD dwNumberOfBytesToMap);
+export LPVOID MapViewOfFileEx(HANDLE hFileMappingObject, DWORD dwDesiredAccess, DWORD dwFileOffsetHigh, DWORD dwFileOffsetLow, DWORD dwNumberOfBytesToMap, LPVOID lpBaseAddress);
+export BOOL FlushViewOfFile(LPCVOID lpBaseAddress, DWORD dwNumberOfBytesToFlush);
+export BOOL UnmapViewOfFile(LPCVOID lpBaseAddress);
+
+export  HGDIOBJ   GetStockObject(int);
+export BOOL ShowWindow(HWND hWnd, int nCmdShow);
+
+/* Stock Logical Objects */
+enum
+{	WHITE_BRUSH =         0,
+	LTGRAY_BRUSH =        1,
+	GRAY_BRUSH =          2,
+	DKGRAY_BRUSH =        3,
+	BLACK_BRUSH =         4,
+	NULL_BRUSH =          5,
+	HOLLOW_BRUSH =        NULL_BRUSH,
+	WHITE_PEN =           6,
+	BLACK_PEN =           7,
+	NULL_PEN =            8,
+	OEM_FIXED_FONT =      10,
+	ANSI_FIXED_FONT =     11,
+	ANSI_VAR_FONT =       12,
+	SYSTEM_FONT =         13,
+	DEVICE_DEFAULT_FONT = 14,
+	DEFAULT_PALETTE =     15,
+	SYSTEM_FIXED_FONT =   16,
+	DEFAULT_GUI_FONT =    17,
+	STOCK_LAST =          17,
+}
+
+/*
+ * ShowWindow() Commands
+ */
+enum
+{	SW_HIDE =             0,
+	SW_SHOWNORMAL =       1,
+	SW_NORMAL =           1,
+	SW_SHOWMINIMIZED =    2,
+	SW_SHOWMAXIMIZED =    3,
+	SW_MAXIMIZE =         3,
+	SW_SHOWNOACTIVATE =   4,
+	SW_SHOW =             5,
+	SW_MINIMIZE =         6,
+	SW_SHOWMINNOACTIVE =  7,
+	SW_SHOWNA =           8,
+	SW_RESTORE =          9,
+	SW_SHOWDEFAULT =      10,
+	SW_MAX =              10,
+}
+
+struct TEXTMETRICA
+{
+    LONG        tmHeight;
+    LONG        tmAscent;
+    LONG        tmDescent;
+    LONG        tmInternalLeading;
+    LONG        tmExternalLeading;
+    LONG        tmAveCharWidth;
+    LONG        tmMaxCharWidth;
+    LONG        tmWeight;
+    LONG        tmOverhang;
+    LONG        tmDigitizedAspectX;
+    LONG        tmDigitizedAspectY;
+    BYTE        tmFirstChar;
+    BYTE        tmLastChar;
+    BYTE        tmDefaultChar;
+    BYTE        tmBreakChar;
+    BYTE        tmItalic;
+    BYTE        tmUnderlined;
+    BYTE        tmStruckOut;
+    BYTE        tmPitchAndFamily;
+    BYTE        tmCharSet;
+}
+
+export  BOOL   GetTextMetricsA(HDC, TEXTMETRICA*);
+
+/*
+ * Scroll Bar Constants
+ */
+enum
+{	SB_HORZ =             0,
+	SB_VERT =             1,
+	SB_CTL =              2,
+	SB_BOTH =             3,
+}
+
+/*
+ * Scroll Bar Commands
+ */
+enum
+{	SB_LINEUP =           0,
+	SB_LINELEFT =         0,
+	SB_LINEDOWN =         1,
+	SB_LINERIGHT =        1,
+	SB_PAGEUP =           2,
+	SB_PAGELEFT =         2,
+	SB_PAGEDOWN =         3,
+	SB_PAGERIGHT =        3,
+	SB_THUMBPOSITION =    4,
+	SB_THUMBTRACK =       5,
+	SB_TOP =              6,
+	SB_LEFT =             6,
+	SB_BOTTOM =           7,
+	SB_RIGHT =            7,
+	SB_ENDSCROLL =        8,
+}
+
+export int SetScrollPos(HWND hWnd, int nBar, int nPos, BOOL bRedraw);
+export int GetScrollPos(HWND hWnd, int nBar);
+export BOOL SetScrollRange(HWND hWnd, int nBar, int nMinPos, int nMaxPos, BOOL bRedraw);
+export BOOL GetScrollRange(HWND hWnd, int nBar, LPINT lpMinPos, LPINT lpMaxPos);
+export BOOL ShowScrollBar(HWND hWnd, int wBar, BOOL bShow);
+export BOOL EnableScrollBar(HWND hWnd, UINT wSBflags, UINT wArrows);
+
+/*
+ * LockWindowUpdate API
+ */
+
+export BOOL LockWindowUpdate(HWND hWndLock);
+export BOOL ScrollWindow(HWND hWnd, int XAmount, int YAmount, RECT* lpRect, RECT* lpClipRect);
+export BOOL ScrollDC(HDC hDC, int dx, int dy, RECT* lprcScroll, RECT* lprcClip, HRGN hrgnUpdate, LPRECT lprcUpdate);
+export int ScrollWindowEx(HWND hWnd, int dx, int dy, RECT* prcScroll, RECT* prcClip, HRGN hrgnUpdate, LPRECT prcUpdate, UINT flags);
+
+/*
+ * Virtual Keys, Standard Set
+ */
+enum
+{	VK_LBUTTON =        0x01,
+	VK_RBUTTON =        0x02,
+	VK_CANCEL =         0x03,
+	VK_MBUTTON =        0x04, /* NOT contiguous with L & RBUTTON */
+
+	VK_BACK =           0x08,
+	VK_TAB =            0x09,
+
+	VK_CLEAR =          0x0C,
+	VK_RETURN =         0x0D,
+
+	VK_SHIFT =          0x10,
+	VK_CONTROL =        0x11,
+	VK_MENU =           0x12,
+	VK_PAUSE =          0x13,
+	VK_CAPITAL =        0x14,
+
+
+	VK_ESCAPE =         0x1B,
+
+	VK_SPACE =          0x20,
+	VK_PRIOR =          0x21,
+	VK_NEXT =           0x22,
+	VK_END =            0x23,
+	VK_HOME =           0x24,
+	VK_LEFT =           0x25,
+	VK_UP =             0x26,
+	VK_RIGHT =          0x27,
+	VK_DOWN =           0x28,
+	VK_SELECT =         0x29,
+	VK_PRINT =          0x2A,
+	VK_EXECUTE =        0x2B,
+	VK_SNAPSHOT =       0x2C,
+	VK_INSERT =         0x2D,
+	VK_DELETE =         0x2E,
+	VK_HELP =           0x2F,
+
+/* VK_0 thru VK_9 are the same as ASCII '0' thru '9' (0x30 - 0x39) */
+/* VK_A thru VK_Z are the same as ASCII 'A' thru 'Z' (0x41 - 0x5A) */
+
+	VK_LWIN =           0x5B,
+	VK_RWIN =           0x5C,
+	VK_APPS =           0x5D,
+
+	VK_NUMPAD0 =        0x60,
+	VK_NUMPAD1 =        0x61,
+	VK_NUMPAD2 =        0x62,
+	VK_NUMPAD3 =        0x63,
+	VK_NUMPAD4 =        0x64,
+	VK_NUMPAD5 =        0x65,
+	VK_NUMPAD6 =        0x66,
+	VK_NUMPAD7 =        0x67,
+	VK_NUMPAD8 =        0x68,
+	VK_NUMPAD9 =        0x69,
+	VK_MULTIPLY =       0x6A,
+	VK_ADD =            0x6B,
+	VK_SEPARATOR =      0x6C,
+	VK_SUBTRACT =       0x6D,
+	VK_DECIMAL =        0x6E,
+	VK_DIVIDE =         0x6F,
+	VK_F1 =             0x70,
+	VK_F2 =             0x71,
+	VK_F3 =             0x72,
+	VK_F4 =             0x73,
+	VK_F5 =             0x74,
+	VK_F6 =             0x75,
+	VK_F7 =             0x76,
+	VK_F8 =             0x77,
+	VK_F9 =             0x78,
+	VK_F10 =            0x79,
+	VK_F11 =            0x7A,
+	VK_F12 =            0x7B,
+	VK_F13 =            0x7C,
+	VK_F14 =            0x7D,
+	VK_F15 =            0x7E,
+	VK_F16 =            0x7F,
+	VK_F17 =            0x80,
+	VK_F18 =            0x81,
+	VK_F19 =            0x82,
+	VK_F20 =            0x83,
+	VK_F21 =            0x84,
+	VK_F22 =            0x85,
+	VK_F23 =            0x86,
+	VK_F24 =            0x87,
+
+	VK_NUMLOCK =        0x90,
+	VK_SCROLL =         0x91,
+
+/*
+ * VK_L* & VK_R* - left and right Alt, Ctrl and Shift virtual keys.
+ * Used only as parameters to GetAsyncKeyState() and GetKeyState().
+ * No other API or message will distinguish left and right keys in this way.
+ */
+	VK_LSHIFT =         0xA0,
+	VK_RSHIFT =         0xA1,
+	VK_LCONTROL =       0xA2,
+	VK_RCONTROL =       0xA3,
+	VK_LMENU =          0xA4,
+	VK_RMENU =          0xA5,
+
+
+	VK_PROCESSKEY =     0xE5,
+
+
+	VK_ATTN =           0xF6,
+	VK_CRSEL =          0xF7,
+	VK_EXSEL =          0xF8,
+	VK_EREOF =          0xF9,
+	VK_PLAY =           0xFA,
+	VK_ZOOM =           0xFB,
+	VK_NONAME =         0xFC,
+	VK_PA1 =            0xFD,
+	VK_OEM_CLEAR =      0xFE,
+}
+
+export LRESULT SendMessageA(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
+
+alias UINT (*LPOFNHOOKPROC) (HWND, UINT, WPARAM, LPARAM);
+
+struct OPENFILENAMEA {
+   DWORD        lStructSize;
+   HWND         hwndOwner;
+   HINSTANCE    hInstance;
+   LPCSTR       lpstrFilter;
+   LPSTR        lpstrCustomFilter;
+   DWORD        nMaxCustFilter;
+   DWORD        nFilterIndex;
+   LPSTR        lpstrFile;
+   DWORD        nMaxFile;
+   LPSTR        lpstrFileTitle;
+   DWORD        nMaxFileTitle;
+   LPCSTR       lpstrInitialDir;
+   LPCSTR       lpstrTitle;
+   DWORD        Flags;
+   WORD         nFileOffset;
+   WORD         nFileExtension;
+   LPCSTR       lpstrDefExt;
+   LPARAM       lCustData;
+   LPOFNHOOKPROC lpfnHook;
+   LPCSTR       lpTemplateName;
+}
+alias OPENFILENAMEA *LPOPENFILENAMEA;
+
+struct OPENFILENAMEW {
+   DWORD        lStructSize;
+   HWND         hwndOwner;
+   HINSTANCE    hInstance;
+   LPCWSTR      lpstrFilter;
+   LPWSTR       lpstrCustomFilter;
+   DWORD        nMaxCustFilter;
+   DWORD        nFilterIndex;
+   LPWSTR       lpstrFile;
+   DWORD        nMaxFile;
+   LPWSTR       lpstrFileTitle;
+   DWORD        nMaxFileTitle;
+   LPCWSTR      lpstrInitialDir;
+   LPCWSTR      lpstrTitle;
+   DWORD        Flags;
+   WORD         nFileOffset;
+   WORD         nFileExtension;
+   LPCWSTR      lpstrDefExt;
+   LPARAM       lCustData;
+   LPOFNHOOKPROC lpfnHook;
+   LPCWSTR      lpTemplateName;
+}
+alias OPENFILENAMEW *LPOPENFILENAMEW;
+
+BOOL          GetOpenFileNameA(LPOPENFILENAMEA);
+BOOL          GetOpenFileNameW(LPOPENFILENAMEW);
+
+BOOL          GetSaveFileNameA(LPOPENFILENAMEA);
+BOOL          GetSaveFileNameW(LPOPENFILENAMEW);
+
+short         GetFileTitleA(LPCSTR, LPSTR, WORD);
+short         GetFileTitleW(LPCWSTR, LPWSTR, WORD);
+
+enum
+{
+	PM_NOREMOVE =         0x0000,
+	PM_REMOVE =           0x0001,
+	PM_NOYIELD =          0x0002,
+}
+
+/* Bitmap Header Definition */
+struct BITMAP
+{
+    LONG        bmType;
+    LONG        bmWidth;
+    LONG        bmHeight;
+    LONG        bmWidthBytes;
+    WORD        bmPlanes;
+    WORD        bmBitsPixel;
+    LPVOID      bmBits;
+}
+alias BITMAP* PBITMAP, NPBITMAP, LPBITMAP;
+
+
+export  HDC       CreateCompatibleDC(HDC);
+
+export  int     GetObjectA(HGDIOBJ, int, LPVOID);
+export  int     GetObjectW(HGDIOBJ, int, LPVOID);
+export  BOOL   DeleteDC(HDC);
+
+struct LOGFONTA
+{
+    LONG      lfHeight;
+    LONG      lfWidth;
+    LONG      lfEscapement;
+    LONG      lfOrientation;
+    LONG      lfWeight;
+    BYTE      lfItalic;
+    BYTE      lfUnderline;
+    BYTE      lfStrikeOut;
+    BYTE      lfCharSet;
+    BYTE      lfOutPrecision;
+    BYTE      lfClipPrecision;
+    BYTE      lfQuality;
+    BYTE      lfPitchAndFamily;
+    CHAR      lfFaceName[32 ];
+}
+alias LOGFONTA* PLOGFONTA, NPLOGFONTA, LPLOGFONTA;
+
+export HMENU LoadMenuA(HINSTANCE hInstance, LPCSTR lpMenuName);
+export HMENU LoadMenuW(HINSTANCE hInstance, LPCWSTR lpMenuName);
+
+export HMENU GetSubMenu(HMENU hMenu, int nPos);
+
+export HBITMAP LoadBitmapA(HINSTANCE hInstance, LPCSTR lpBitmapName);
+export HBITMAP LoadBitmapW(HINSTANCE hInstance, LPCWSTR lpBitmapName);
+
+LPSTR MAKEINTRESOURCEA(int i) { return cast(LPSTR)(cast(DWORD)(cast(WORD)(i))); }
+
+export  HFONT     CreateFontIndirectA(LOGFONTA *);
+
+export BOOL MessageBeep(UINT uType);
+export int ShowCursor(BOOL bShow);
+export BOOL SetCursorPos(int X, int Y);
+export HCURSOR SetCursor(HCURSOR hCursor);
+export BOOL GetCursorPos(LPPOINT lpPoint);
+export BOOL ClipCursor( RECT *lpRect);
+export BOOL GetClipCursor(LPRECT lpRect);
+export HCURSOR GetCursor();
+export BOOL CreateCaret(HWND hWnd, HBITMAP hBitmap , int nWidth, int nHeight);
+export UINT GetCaretBlinkTime();
+export BOOL SetCaretBlinkTime(UINT uMSeconds);
+export BOOL DestroyCaret();
+export BOOL HideCaret(HWND hWnd);
+export BOOL ShowCaret(HWND hWnd);
+export BOOL SetCaretPos(int X, int Y);
+export BOOL GetCaretPos(LPPOINT lpPoint);
+export BOOL ClientToScreen(HWND hWnd, LPPOINT lpPoint);
+export BOOL ScreenToClient(HWND hWnd, LPPOINT lpPoint);
+export int MapWindowPoints(HWND hWndFrom, HWND hWndTo, LPPOINT lpPoints, UINT cPoints);
+export HWND WindowFromPoint(POINT Point);
+export HWND ChildWindowFromPoint(HWND hWndParent, POINT Point);
+
+
+export BOOL TrackPopupMenu(HMENU hMenu, UINT uFlags, int x, int y,
+	int nReserved, HWND hWnd, RECT *prcRect);
+
+align (2) struct DLGTEMPLATE {
+    DWORD style;
+    DWORD dwExtendedStyle;
+    WORD cdit;
+    short x;
+    short y;
+    short cx;
+    short cy;
+}
+alias DLGTEMPLATE *LPDLGTEMPLATEA;
+alias DLGTEMPLATE *LPDLGTEMPLATEW;
+
+
+alias LPDLGTEMPLATEA LPDLGTEMPLATE;
+
+alias  DLGTEMPLATE *LPCDLGTEMPLATEA;
+alias  DLGTEMPLATE *LPCDLGTEMPLATEW;
+
+
+alias LPCDLGTEMPLATEA LPCDLGTEMPLATE;
+
+
+export int DialogBoxParamA(HINSTANCE hInstance, LPCSTR lpTemplateName,
+	HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam);
+export int DialogBoxIndirectParamA(HINSTANCE hInstance,
+	LPCDLGTEMPLATEA hDialogTemplate, HWND hWndParent, DLGPROC lpDialogFunc,
+	LPARAM dwInitParam);
+
+enum : DWORD
+{
+	SRCCOPY =             cast(DWORD)0x00CC0020, /* dest = source                   */
+	SRCPAINT =            cast(DWORD)0x00EE0086, /* dest = source OR dest           */
+	SRCAND =              cast(DWORD)0x008800C6, /* dest = source AND dest          */
+	SRCINVERT =           cast(DWORD)0x00660046, /* dest = source XOR dest          */
+	SRCERASE =            cast(DWORD)0x00440328, /* dest = source AND (NOT dest)   */
+	NOTSRCCOPY =          cast(DWORD)0x00330008, /* dest = (NOT source)             */
+	NOTSRCERASE =         cast(DWORD)0x001100A6, /* dest = (NOT src) AND (NOT dest) */
+	MERGECOPY =           cast(DWORD)0x00C000CA, /* dest = (source AND pattern)     */
+	MERGEPAINT =          cast(DWORD)0x00BB0226, /* dest = (NOT source) OR dest     */
+	PATCOPY =             cast(DWORD)0x00F00021, /* dest = pattern                  */
+	PATPAINT =            cast(DWORD)0x00FB0A09, /* dest = DPSnoo                   */
+	PATINVERT =           cast(DWORD)0x005A0049, /* dest = pattern XOR dest         */
+	DSTINVERT =           cast(DWORD)0x00550009, /* dest = (NOT dest)               */
+	BLACKNESS =           cast(DWORD)0x00000042, /* dest = BLACK                    */
+	WHITENESS =           cast(DWORD)0x00FF0062, /* dest = WHITE                    */
+}
+
+enum
+{
+	SND_SYNC =            0x0000, /* play synchronously (default) */
+	SND_ASYNC =           0x0001, /* play asynchronously */
+	SND_NODEFAULT =       0x0002, /* silence (!default) if sound not found */
+	SND_MEMORY =          0x0004, /* pszSound points to a memory file */
+	SND_LOOP =            0x0008, /* loop the sound until next sndPlaySound */
+	SND_NOSTOP =          0x0010, /* don't stop any currently playing sound */
+
+	SND_NOWAIT =	0x00002000, /* don't wait if the driver is busy */
+	SND_ALIAS =       0x00010000, /* name is a registry alias */
+	SND_ALIAS_ID =	0x00110000, /* alias is a predefined ID */
+	SND_FILENAME =    0x00020000, /* name is file name */
+	SND_RESOURCE =    0x00040004, /* name is resource name or atom */
+
+	SND_PURGE =           0x0040, /* purge non-static events for task */
+	SND_APPLICATION =     0x0080, /* look for application specific association */
+
+
+	SND_ALIAS_START =	0,     /* alias base */
+}
+
+export  BOOL   PlaySoundA(LPCSTR pszSound, HMODULE hmod, DWORD fdwSound);
+export  BOOL   PlaySoundW(LPCWSTR pszSound, HMODULE hmod, DWORD fdwSound);
+
+export  int     GetClipBox(HDC, LPRECT);
+export  int     GetClipRgn(HDC, HRGN);
+export  int     GetMetaRgn(HDC, HRGN);
+export  HGDIOBJ   GetCurrentObject(HDC, UINT);
+export  BOOL    GetCurrentPositionEx(HDC, LPPOINT);
+export  int     GetDeviceCaps(HDC, int);
+
+struct LOGPEN
+  {
+    UINT        lopnStyle;
+    POINT       lopnWidth;
+    COLORREF    lopnColor;
+}
+alias LOGPEN* PLOGPEN, NPLOGPEN, LPLOGPEN;
+
+enum
+{
+	PS_SOLID =            0,
+	PS_DASH =             1, /* -------  */
+	PS_DOT =              2, /* .......  */
+	PS_DASHDOT =          3, /* _._._._  */
+	PS_DASHDOTDOT =       4, /* _.._.._  */
+	PS_NULL =             5,
+	PS_INSIDEFRAME =      6,
+	PS_USERSTYLE =        7,
+	PS_ALTERNATE =        8,
+	PS_STYLE_MASK =       0x0000000F,
+
+	PS_ENDCAP_ROUND =     0x00000000,
+	PS_ENDCAP_SQUARE =    0x00000100,
+	PS_ENDCAP_FLAT =      0x00000200,
+	PS_ENDCAP_MASK =      0x00000F00,
+
+	PS_JOIN_ROUND =       0x00000000,
+	PS_JOIN_BEVEL =       0x00001000,
+	PS_JOIN_MITER =       0x00002000,
+	PS_JOIN_MASK =        0x0000F000,
+
+	PS_COSMETIC =         0x00000000,
+	PS_GEOMETRIC =        0x00010000,
+	PS_TYPE_MASK =        0x000F0000,
+}
+
+export  HPALETTE   CreatePalette(LOGPALETTE *);
+export  HPEN      CreatePen(int, int, COLORREF);
+export  HPEN      CreatePenIndirect(LOGPEN *);
+export  HRGN      CreatePolyPolygonRgn(POINT *, INT *, int, int);
+export  HBRUSH    CreatePatternBrush(HBITMAP);
+export  HRGN      CreateRectRgn(int, int, int, int);
+export  HRGN      CreateRectRgnIndirect(RECT *);
+export  HRGN      CreateRoundRectRgn(int, int, int, int, int, int);
+export  BOOL      CreateScalableFontResourceA(DWORD, LPCSTR, LPCSTR, LPCSTR);
+export  BOOL      CreateScalableFontResourceW(DWORD, LPCWSTR, LPCWSTR, LPCWSTR);
+
+COLORREF RGB(int r, int g, int b)
+{
+    return cast(COLORREF)
+	((cast(BYTE)r|(cast(WORD)(cast(BYTE)g)<<8))|((cast(DWORD)cast(BYTE)b)<<16));
+}
+
+export  BOOL   LineTo(HDC, int, int);
+export  BOOL   DeleteObject(HGDIOBJ);
+export int FillRect(HDC hDC,  RECT *lprc, HBRUSH hbr);
+
+
+export BOOL EndDialog(HWND hDlg, int nResult);
+export HWND GetDlgItem(HWND hDlg, int nIDDlgItem);
+
+export BOOL SetDlgItemInt(HWND hDlg, int nIDDlgItem, UINT uValue, BOOL bSigned);
+export UINT GetDlgItemInt(HWND hDlg, int nIDDlgItem, BOOL *lpTranslated,
+    BOOL bSigned);
+
+export BOOL SetDlgItemTextA(HWND hDlg, int nIDDlgItem, LPCSTR lpString);
+export BOOL SetDlgItemTextW(HWND hDlg, int nIDDlgItem, LPCWSTR lpString);
+
+export UINT GetDlgItemTextA(HWND hDlg, int nIDDlgItem, LPSTR lpString, int nMaxCount);
+export UINT GetDlgItemTextW(HWND hDlg, int nIDDlgItem, LPWSTR lpString, int nMaxCount);
+
+export BOOL CheckDlgButton(HWND hDlg, int nIDButton, UINT uCheck);
+export BOOL CheckRadioButton(HWND hDlg, int nIDFirstButton, int nIDLastButton,
+    int nIDCheckButton);
+
+export UINT IsDlgButtonChecked(HWND hDlg, int nIDButton);
+
+export HWND SetFocus(HWND hWnd);
+
+export int wsprintfA(LPSTR, LPCSTR, ...);
+export int wsprintfW(LPWSTR, LPCWSTR, ...);
+
+const uint INFINITE = uint.max;
+const uint WAIT_OBJECT_0 = 0;
+
+export HANDLE CreateSemaphoreA(LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, LONG lInitialCount, LONG lMaximumCount, LPCTSTR lpName);
+export HANDLE OpenSemaphoreA(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCTSTR lpName);
+export BOOL ReleaseSemaphore(HANDLE hSemaphore, LONG lReleaseCount, LPLONG lpPreviousCount);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lphobos/std/c/windows/winsock.d	Mon Aug 04 19:28:49 2008 +0200
@@ -0,0 +1,540 @@
+/*
+	Written by Christopher E. Miller
+	Placed into public domain.
+*/
+
+
+module std.c.windows.winsock;
+
+private import std.stdint;
+private import std.c.windows.windows;
+
+
+extern(Windows):
+
+alias UINT SOCKET;
+alias int socklen_t;
+
+const SOCKET INVALID_SOCKET = cast(SOCKET)~0;
+const int SOCKET_ERROR = -1;
+
+const int WSADESCRIPTION_LEN = 256;
+const int WSASYS_STATUS_LEN = 128;
+
+struct WSADATA
+{
+	WORD wVersion;
+	WORD wHighVersion;
+	char szDescription[WSADESCRIPTION_LEN + 1];
+	char szSystemStatus[WSASYS_STATUS_LEN + 1];
+	USHORT iMaxSockets;
+	USHORT iMaxUdpDg;
+	char* lpVendorInfo;
+}
+alias WSADATA* LPWSADATA;
+
+
+const int IOCPARM_MASK =  0x7F;
+const int IOC_IN =        cast(int)0x80000000;
+const int FIONBIO =       cast(int)(IOC_IN | ((UINT.sizeof & IOCPARM_MASK) << 16) | (102 << 8) | 126);
+
+
+int WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData);
+int WSACleanup();
+SOCKET socket(int af, int type, int protocol);
+int ioctlsocket(SOCKET s, int cmd, uint* argp);
+int bind(SOCKET s, sockaddr* name, int namelen);
+int connect(SOCKET s, sockaddr* name, int namelen);
+int listen(SOCKET s, int backlog);
+SOCKET accept(SOCKET s, sockaddr* addr, int* addrlen);
+int closesocket(SOCKET s);
+int shutdown(SOCKET s, int how);
+int getpeername(SOCKET s, sockaddr* name, int* namelen);
+int getsockname(SOCKET s, sockaddr* name, int* namelen);
+int send(SOCKET s, void* buf, int len, int flags);
+int sendto(SOCKET s, void* buf, int len, int flags, sockaddr* to, int tolen);
+int recv(SOCKET s, void* buf, int len, int flags);
+int recvfrom(SOCKET s, void* buf, int len, int flags, sockaddr* from, int* fromlen);
+int getsockopt(SOCKET s, int level, int optname, void* optval, int* optlen);
+int setsockopt(SOCKET s, int level, int optname, void* optval, int optlen);
+uint inet_addr(char* cp);
+int select(int nfds, fd_set* readfds, fd_set* writefds, fd_set* errorfds, timeval* timeout);
+char* inet_ntoa(in_addr ina);
+hostent* gethostbyname(char* name);
+hostent* gethostbyaddr(void* addr, int len, int type);
+protoent* getprotobyname(char* name);
+protoent* getprotobynumber(int number);
+servent* getservbyname(char* name, char* proto);
+servent* getservbyport(int port, char* proto);
+int gethostname(char* name, int namelen);
+int getaddrinfo(char* nodename, char* servname, addrinfo* hints, addrinfo** res);
+void freeaddrinfo(addrinfo* ai);
+int getnameinfo(sockaddr* sa, socklen_t salen, char* host, DWORD hostlen, char* serv, DWORD servlen, int flags);
+
+enum: int
+{
+	WSAEWOULDBLOCK =     10035,
+	WSAEINTR =           10004,
+	WSAHOST_NOT_FOUND =  11001,
+}
+
+int WSAGetLastError();
+
+
+enum: int
+{
+	AF_UNSPEC =     0,
+	
+	AF_UNIX =       1,
+	AF_INET =       2,
+	AF_IMPLINK =    3,
+	AF_PUP =        4,
+	AF_CHAOS =      5,
+	AF_NS =         6,
+	AF_IPX =        AF_NS,
+	AF_ISO =        7,
+	AF_OSI =        AF_ISO,
+	AF_ECMA =       8,
+	AF_DATAKIT =    9,
+	AF_CCITT =      10,
+	AF_SNA =        11,
+	AF_DECnet =     12,
+	AF_DLI =        13,
+	AF_LAT =        14,
+	AF_HYLINK =     15,
+	AF_APPLETALK =  16,
+	AF_NETBIOS =    17,
+	AF_VOICEVIEW =  18,
+	AF_FIREFOX =    19,
+	AF_UNKNOWN1 =   20,
+	AF_BAN =        21,
+	AF_ATM =        22,
+	AF_INET6 =      23,
+	AF_CLUSTER =    24,
+	AF_12844 =      25,
+	AF_IRDA =       26,
+	AF_NETDES =     28,
+	
+	AF_MAX =        29,
+	
+	
+	PF_UNSPEC     = AF_UNSPEC,
+	
+	PF_UNIX =       AF_UNIX,
+	PF_INET =       AF_INET,
+	PF_IMPLINK =    AF_IMPLINK,
+	PF_PUP =        AF_PUP,
+	PF_CHAOS =      AF_CHAOS,
+	PF_NS =         AF_NS,
+	PF_IPX =        AF_IPX,
+	PF_ISO =        AF_ISO,
+	PF_OSI =        AF_OSI,
+	PF_ECMA =       AF_ECMA,
+	PF_DATAKIT =    AF_DATAKIT,
+	PF_CCITT =      AF_CCITT,
+	PF_SNA =        AF_SNA,
+	PF_DECnet =     AF_DECnet,
+	PF_DLI =        AF_DLI,
+	PF_LAT =        AF_LAT,
+	PF_HYLINK =     AF_HYLINK,
+	PF_APPLETALK =  AF_APPLETALK,
+	PF_VOICEVIEW =  AF_VOICEVIEW,
+	PF_FIREFOX =    AF_FIREFOX,
+	PF_UNKNOWN1 =   AF_UNKNOWN1,
+	PF_BAN =        AF_BAN,
+	PF_INET6 =      AF_INET6,
+	
+	PF_MAX        = AF_MAX,
+}
+
+
+enum: int
+{
+	SOL_SOCKET = 0xFFFF,
+}
+
+
+enum: int
+{
+	SO_DEBUG =        0x0001,
+	SO_ACCEPTCONN =   0x0002,
+	SO_REUSEADDR =    0x0004,
+	SO_KEEPALIVE =    0x0008,
+	SO_DONTROUTE =    0x0010,
+	SO_BROADCAST =    0x0020,
+	SO_USELOOPBACK =  0x0040,
+	SO_LINGER =       0x0080,
+	SO_DONTLINGER =   ~SO_LINGER,
+	SO_OOBINLINE =    0x0100,
+	SO_SNDBUF =       0x1001,
+	SO_RCVBUF =       0x1002,
+	SO_SNDLOWAT =     0x1003,
+	SO_RCVLOWAT =     0x1004,
+	SO_SNDTIMEO =     0x1005,
+	SO_RCVTIMEO =     0x1006,
+	SO_ERROR =        0x1007,
+	SO_TYPE =         0x1008,
+	SO_EXCLUSIVEADDRUSE = ~SO_REUSEADDR,
+	
+	TCP_NODELAY =    1,
+	
+	IP_MULTICAST_LOOP =  0x4,
+	IP_ADD_MEMBERSHIP =  0x5,
+	IP_DROP_MEMBERSHIP = 0x6,
+	
+	IPV6_UNICAST_HOPS =    4,
+	IPV6_MULTICAST_IF =    9,
+	IPV6_MULTICAST_HOPS =  10,
+	IPV6_MULTICAST_LOOP =  11,
+	IPV6_ADD_MEMBERSHIP =  12,
+	IPV6_DROP_MEMBERSHIP = 13,
+	IPV6_JOIN_GROUP =      IPV6_ADD_MEMBERSHIP,
+	IPV6_LEAVE_GROUP =     IPV6_DROP_MEMBERSHIP,
+}
+
+
+const uint FD_SETSIZE = 64;
+
+
+struct fd_set
+{
+	UINT fd_count;
+	SOCKET[FD_SETSIZE] fd_array;
+}
+
+
+// Removes.
+void FD_CLR(SOCKET fd, fd_set* set)
+{
+	uint c = set.fd_count;
+	SOCKET* start = set.fd_array.ptr;
+	SOCKET* stop = start + c;
+	
+	for(; start != stop; start++)
+	{
+		if(*start == fd)
+			goto found;
+	}
+	return; //not found
+	
+	found:
+	for(++start; start != stop; start++)
+	{
+		*(start - 1) = *start;
+	}
+	
+	set.fd_count = c - 1;
+}
+
+
+// Tests.
+int FD_ISSET(SOCKET fd, fd_set* set)
+{
+	SOCKET* start = set.fd_array.ptr;
+	SOCKET* stop = start + set.fd_count;
+	
+	for(; start != stop; start++)
+	{
+		if(*start == fd)
+			return true;
+	}
+	return false;
+}
+
+
+// Adds.
+void FD_SET(SOCKET fd, fd_set* set)
+{
+	uint c = set.fd_count;
+	set.fd_array.ptr[c] = fd;
+	set.fd_count = c + 1;
+}
+
+
+// Resets to zero.
+void FD_ZERO(fd_set* set)
+{
+	set.fd_count = 0;
+}
+
+
+struct linger
+{
+	USHORT l_onoff;
+	USHORT l_linger;
+}
+
+
+struct protoent
+{
+	char* p_name;
+	char** p_aliases;
+	SHORT p_proto;
+}
+
+
+struct servent
+{
+	char* s_name;
+	char** s_aliases;
+	SHORT s_port;
+	char* s_proto;
+}
+
+
+/+
+union in6_addr
+{
+	private union _u_t
+	{
+		BYTE[16] Byte;
+		WORD[8] Word;
+	}
+	_u_t u;
+}
+
+
+struct in_addr6
+{
+	BYTE[16] s6_addr;
+}
++/
+
+
+version(BigEndian)
+{
+	uint16_t htons(uint16_t x)
+	{
+		return x;
+	}
+	
+	
+	uint32_t htonl(uint32_t x)
+	{
+		return x;
+	}
+}
+else version(LittleEndian)
+{
+	private import std.intrinsic;
+	
+	
+	uint16_t htons(uint16_t x)
+	{
+		return cast(uint16_t)((x >> 8) | (x << 8));
+	}
+
+
+	uint32_t htonl(uint32_t x)
+	{
+		return bswap(x);
+	}
+}
+else
+{
+	static assert(0);
+}
+
+
+uint16_t ntohs(uint16_t x)
+{
+	return htons(x);
+}
+
+
+uint32_t ntohl(uint32_t x)
+{
+	return htonl(x);
+}
+
+
+enum: int
+{
+	SOCK_STREAM =     1,
+	SOCK_DGRAM =      2,
+	SOCK_RAW =        3,
+	SOCK_RDM =        4,
+	SOCK_SEQPACKET =  5,
+}
+
+
+enum: int
+{
+	IPPROTO_IP =    0,
+	IPPROTO_ICMP =  1,
+	IPPROTO_IGMP =  2,
+	IPPROTO_GGP =   3,
+	IPPROTO_TCP =   6,
+	IPPROTO_PUP =   12,
+	IPPROTO_UDP =   17,
+	IPPROTO_IDP =   22,
+	IPPROTO_IPV6 =  41,
+	IPPROTO_ND =    77,
+	IPPROTO_RAW =   255,
+	
+	IPPROTO_MAX =   256,
+}
+
+
+enum: int
+{
+	MSG_OOB =        0x1,
+	MSG_PEEK =       0x2,
+	MSG_DONTROUTE =  0x4,
+        MSG_NOSIGNAL =   0x0, /// not supported on win32, would be 0x4000 if it was
+}
+
+
+enum: int
+{
+	SD_RECEIVE =  0,
+	SD_SEND =     1,
+	SD_BOTH =     2,
+}
+
+
+enum: uint
+{
+	INADDR_ANY =        0,
+	INADDR_LOOPBACK =   0x7F000001,
+	INADDR_BROADCAST =  0xFFFFFFFF,
+	INADDR_NONE =       0xFFFFFFFF,
+	ADDR_ANY =          INADDR_ANY,
+}
+
+
+enum: int
+{
+	AI_PASSIVE = 0x1,
+	AI_CANONNAME = 0x2,
+	AI_NUMERICHOST = 0x4,
+}
+
+
+struct timeval
+{
+	int32_t tv_sec;
+	int32_t tv_usec;
+}
+
+
+union in_addr
+{
+	private union _S_un_t
+	{
+		private struct _S_un_b_t
+		{
+			uint8_t s_b1, s_b2, s_b3, s_b4;
+		}
+		_S_un_b_t S_un_b;
+		
+		private struct _S_un_w_t
+		{
+			uint16_t s_w1, s_w2;
+		}
+		_S_un_w_t S_un_w;
+		
+		uint32_t S_addr;
+	}
+	_S_un_t S_un;
+	
+	uint32_t s_addr;
+	
+	struct
+	{
+		uint8_t s_net, s_host;
+		
+		union
+		{
+			uint16_t s_imp;
+			
+			struct
+			{
+				uint8_t s_lh, s_impno;
+			}
+		}
+	}
+}
+
+
+union in6_addr
+{
+	private union _in6_u_t
+	{
+		uint8_t[16] u6_addr8;
+		uint16_t[8] u6_addr16;
+		uint32_t[4] u6_addr32;
+	}
+	_in6_u_t in6_u;
+	
+	uint8_t[16] s6_addr8;
+	uint16_t[8] s6_addr16;
+	uint32_t[4] s6_addr32;
+	
+	alias s6_addr8 s6_addr;
+}
+
+
+const in6_addr IN6ADDR_ANY = { s6_addr8: [0] };
+const in6_addr IN6ADDR_LOOPBACK = { s6_addr8: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1] };
+//alias IN6ADDR_ANY IN6ADDR_ANY_INIT;
+//alias IN6ADDR_LOOPBACK IN6ADDR_LOOPBACK_INIT;
+	
+const uint INET_ADDRSTRLEN = 16;
+const uint INET6_ADDRSTRLEN = 46;
+
+
+struct sockaddr
+{
+	int16_t sa_family;