summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAndreas Rumpf <rumpf_a@web.de>2009-06-08 08:06:25 +0200
committerAndreas Rumpf <rumpf_a@web.de>2009-06-08 08:06:25 +0200
commit4d4b3b1c04d41868ebb58bd9ccba7b303007e900 (patch)
tree909ed0aad0b145733521f4ac2bfb938dd4b43785
parentce88dc3e67436939b03f97e624c11ca6058fedce (diff)
downloadNim-4d4b3b1c04d41868ebb58bd9ccba7b303007e900.tar.gz
version0.7.10
-rw-r--r--.bzrignore3
-rw-r--r--config/nimdoc.cfg567
-rw-r--r--config/nimrod.cfg21
-rw-r--r--data/ast.yml9
-rw-r--r--data/keywords.txt4
-rw-r--r--data/magic.yml4
-rw-r--r--data/messages.yml5
-rw-r--r--doc/grammar.txt2
-rw-r--r--doc/lib.txt13
-rw-r--r--doc/manual.txt2
-rw-r--r--doc/theindex.txt722
-rw-r--r--doc/tut2.txt2
-rw-r--r--install.txt4
-rw-r--r--koch.py24
-rw-r--r--lib/amd64.asm.in38
-rw-r--r--lib/atomic.h2716
-rw-r--r--lib/base/x11/keysym.nim1900
-rw-r--r--lib/contnrs.nim11
-rw-r--r--lib/dlmalloc.c5076
-rw-r--r--lib/dlmalloc.h1143
-rw-r--r--lib/generics.nim169
-rw-r--r--lib/i386.asm.in70
-rw-r--r--lib/impure/dialogs.nim (renamed from lib/base/dialogs.nim)0
-rw-r--r--lib/impure/web.nim (renamed from lib/base/web.nim)0
-rw-r--r--lib/impure/zipfiles.nim (renamed from lib/base/zip/zipfiles.nim)0
-rw-r--r--lib/int64s.nim71
-rw-r--r--lib/locks.nim18
-rw-r--r--lib/posix/detect.nim824
-rw-r--r--lib/posix/linux_amd64_consts.nim620
-rw-r--r--lib/posix/linux_consts.nim620
-rw-r--r--lib/posix/posix.nim59
-rw-r--r--lib/powerpc.asm.in35
-rw-r--r--lib/pure/cgi.nim (renamed from lib/base/cgi.nim)0
-rw-r--r--lib/pure/complex.nim (renamed from lib/complex.nim)0
-rw-r--r--lib/pure/dynlib.nim84
-rw-r--r--lib/pure/hashes.nim (renamed from lib/hashes.nim)0
-rw-r--r--lib/pure/lexbase.nim (renamed from lib/lexbase.nim)0
-rw-r--r--lib/pure/macros.nim (renamed from lib/macros.nim)18
-rw-r--r--lib/pure/math.nim (renamed from lib/math.nim)2
-rw-r--r--lib/pure/md5.nim245
-rw-r--r--lib/pure/os.nim (renamed from lib/os.nim)998
-rw-r--r--lib/pure/osproc.nim (renamed from lib/osproc.nim)0
-rw-r--r--lib/pure/parsecfg.nim (renamed from lib/parsecfg.nim)3
-rw-r--r--lib/pure/parsecsv.nim (renamed from lib/parsecsv.nim)2
-rw-r--r--lib/pure/parseopt.nim (renamed from lib/parseopt.nim)0
-rw-r--r--lib/pure/parsesql.nim1333
-rw-r--r--lib/pure/parsexml.nim (renamed from lib/parsexml.nim)14
-rw-r--r--lib/pure/regexprs.nim (renamed from lib/base/regexprs.nim)0
-rw-r--r--lib/pure/streams.nim (renamed from lib/streams.nim)0
-rw-r--r--lib/pure/strtabs.nim (renamed from lib/strtabs.nim)0
-rw-r--r--lib/pure/strutils.nim (renamed from lib/strutils.nim)11
-rw-r--r--lib/pure/terminal.nim (renamed from lib/base/terminal.nim)0
-rw-r--r--lib/pure/times.nim (renamed from lib/times.nim)36
-rw-r--r--lib/pure/unicode.nim (renamed from lib/unicode.nim)2
-rw-r--r--lib/pure/xmlgen.nim (renamed from lib/xmlgen.nim)0
-rw-r--r--lib/system.nim57
-rw-r--r--lib/system/alloc.nim (renamed from lib/alloc.nim)0
-rw-r--r--lib/system/ansi_c.nim (renamed from lib/ansi_c.nim)17
-rw-r--r--lib/system/arithm.nim (renamed from lib/arithm.nim)0
-rw-r--r--lib/system/assign.nim (renamed from lib/assign.nim)0
-rw-r--r--lib/system/cellsets.nim (renamed from lib/cellsets.nim)0
-rw-r--r--lib/system/cntbits.nim (renamed from lib/cntbits.nim)0
-rw-r--r--lib/system/debugger.nim (renamed from lib/debugger.nim)0
-rw-r--r--lib/system/dyncalls.nim (renamed from lib/dyncalls.nim)23
-rw-r--r--lib/system/ecmasys.nim (renamed from lib/ecmasys.nim)2
-rw-r--r--lib/system/excpt.nim (renamed from lib/excpt.nim)0
-rw-r--r--lib/system/gc.nim (renamed from lib/gc.nim)0
-rw-r--r--lib/system/hti.nim (renamed from lib/hti.nim)39
-rw-r--r--lib/system/mm.nim (renamed from lib/mm.nim)10
-rw-r--r--lib/system/profiler.nim (renamed from lib/profiler.nim)0
-rw-r--r--lib/system/repr.nim (renamed from lib/repr.nim)0
-rw-r--r--lib/system/sets.nim (renamed from lib/sets.nim)2
-rw-r--r--lib/system/sysio.nim (renamed from lib/sysio.nim)6
-rw-r--r--lib/system/sysstr.nim (renamed from lib/sysstr.nim)0
-rw-r--r--lib/target.h12
-rw-r--r--lib/tlsf.c1005
-rw-r--r--lib/tlsf.h39
-rw-r--r--lib/tlsfnim.nim698
-rw-r--r--lib/windows/winlean.nim (renamed from lib/winlean.nim)80
-rw-r--r--lib/wrappers/cairo/cairo.nim (renamed from lib/base/cairo/cairo.nim)0
-rw-r--r--lib/wrappers/cairo/cairoft.nim (renamed from lib/base/cairo/cairoft.nim)0
-rw-r--r--lib/wrappers/cairo/cairowin32.nim (renamed from lib/base/cairo/cairowin32.nim)0
-rw-r--r--lib/wrappers/cairo/cairoxlib.nim (renamed from lib/base/cairo/cairoxlib.nim)0
-rw-r--r--lib/wrappers/gtk/atk.nim (renamed from lib/base/gtk/atk.nim)0
-rw-r--r--lib/wrappers/gtk/gdk2.nim (renamed from lib/base/gtk/gdk2.nim)0
-rw-r--r--lib/wrappers/gtk/gdk2pixbuf.nim (renamed from lib/base/gtk/gdk2pixbuf.nim)0
-rw-r--r--lib/wrappers/gtk/gdkglext.nim (renamed from lib/base/gtk/gdkglext.nim)0
-rw-r--r--lib/wrappers/gtk/glib2.nim (renamed from lib/base/gtk/glib2.nim)0
-rw-r--r--lib/wrappers/gtk/gtk2.nim (renamed from lib/base/gtk/gtk2.nim)0
-rw-r--r--lib/wrappers/gtk/gtkglext.nim (renamed from lib/base/gtk/gtkglext.nim)0
-rw-r--r--lib/wrappers/gtk/gtkhtml.nim (renamed from lib/base/gtk/gtkhtml.nim)0
-rw-r--r--lib/wrappers/gtk/libglade2.nim (renamed from lib/base/gtk/libglade2.nim)0
-rw-r--r--lib/wrappers/gtk/pango.nim (renamed from lib/base/gtk/pango.nim)0
-rw-r--r--lib/wrappers/gtk/pangoutils.nim (renamed from lib/base/gtk/pangoutils.nim)0
-rw-r--r--lib/wrappers/libcurl.nim (renamed from lib/base/libcurl.nim)0
-rw-r--r--lib/wrappers/lua/lauxlib.nim (renamed from lib/base/lua/lauxlib.nim)2
-rw-r--r--lib/wrappers/lua/lua.nim (renamed from lib/base/lua/lua.nim)12
-rw-r--r--lib/wrappers/lua/lualib.nim (renamed from lib/base/lua/lualib.nim)2
-rw-r--r--lib/wrappers/mysql.nim (renamed from lib/base/mysql.nim)0
-rw-r--r--lib/wrappers/odbcsql.nim (renamed from lib/base/odbcsql.nim)0
-rw-r--r--lib/wrappers/opengl/gl.nim (renamed from lib/base/opengl/gl.nim)0
-rw-r--r--lib/wrappers/opengl/gl.pp (renamed from lib/base/opengl/gl.pp)0
-rw-r--r--lib/wrappers/opengl/glext.nim (renamed from lib/base/opengl/glext.nim)0
-rw-r--r--lib/wrappers/opengl/glext.pp (renamed from lib/base/opengl/glext.pp)0
-rw-r--r--lib/wrappers/opengl/glu.nim (renamed from lib/base/opengl/glu.nim)0
-rw-r--r--lib/wrappers/opengl/glu.pp (renamed from lib/base/opengl/glu.pp)0
-rw-r--r--lib/wrappers/opengl/glut.nim (renamed from lib/base/opengl/glut.nim)0
-rw-r--r--lib/wrappers/opengl/glut.pp (renamed from lib/base/opengl/glut.pp)0
-rw-r--r--lib/wrappers/opengl/glx.nim (renamed from lib/base/opengl/glx.nim)0
-rw-r--r--lib/wrappers/opengl/glx.pp (renamed from lib/base/opengl/glx.pp)0
-rw-r--r--lib/wrappers/opengl/wingl.nim (renamed from lib/base/opengl/wingl.nim)0
-rw-r--r--lib/wrappers/opengl/wingl.pp (renamed from lib/base/opengl/wingl.pp)0
-rw-r--r--lib/wrappers/pcre/pcre.nim (renamed from lib/base/pcre.nim)2
-rw-r--r--lib/wrappers/pcre/pcre_all.c (renamed from lib/base/pcre_all.c)0
-rw-r--r--lib/wrappers/postgres.nim (renamed from lib/base/postgres.nim)4
-rw-r--r--lib/wrappers/python.nim1581
-rw-r--r--lib/wrappers/sdl/sdl.nim (renamed from lib/base/sdl/sdl.nim)0
-rw-r--r--lib/wrappers/sdl/sdl_gfx.nim (renamed from lib/base/sdl/sdl_gfx.nim)0
-rw-r--r--lib/wrappers/sdl/sdl_image.nim (renamed from lib/base/sdl/sdl_image.nim)0
-rw-r--r--lib/wrappers/sdl/sdl_mixer.nim (renamed from lib/base/sdl/sdl_mixer.nim)0
-rw-r--r--lib/wrappers/sdl/sdl_mixer_nosmpeg.nim (renamed from lib/base/sdl/sdl_mixer_nosmpeg.nim)0
-rw-r--r--lib/wrappers/sdl/sdl_net.nim (renamed from lib/base/sdl/sdl_net.nim)0
-rw-r--r--lib/wrappers/sdl/sdl_ttf.nim (renamed from lib/base/sdl/sdl_ttf.nim)0
-rw-r--r--lib/wrappers/sdl/sdlutils.pas (renamed from lib/base/sdl/sdlutils.pas)0
-rw-r--r--lib/wrappers/sdl/smpeg.nim (renamed from lib/base/sdl/smpeg.nim)0
-rw-r--r--lib/wrappers/sqlite3.nim (renamed from lib/base/sqlite3.nim)0
-rw-r--r--lib/wrappers/tcl.nim855
-rw-r--r--lib/wrappers/x11/cursorfont.nim (renamed from lib/base/x11/cursorfont.nim)0
-rw-r--r--lib/wrappers/x11/keysym.nim1925
-rw-r--r--lib/wrappers/x11/x.nim (renamed from lib/base/x11/x.nim)0
-rw-r--r--lib/wrappers/x11/xatom.nim (renamed from lib/base/x11/xatom.nim)0
-rw-r--r--lib/wrappers/x11/xcms.nim (renamed from lib/base/x11/xcms.nim)0
-rw-r--r--lib/wrappers/x11/xf86dga.nim (renamed from lib/base/x11/xf86dga.nim)0
-rw-r--r--lib/wrappers/x11/xf86vmode.nim (renamed from lib/base/x11/xf86vmode.nim)0
-rw-r--r--lib/wrappers/x11/xi.nim (renamed from lib/base/x11/xi.nim)0
-rw-r--r--lib/wrappers/x11/xinerama.nim (renamed from lib/base/x11/xinerama.nim)0
-rw-r--r--lib/wrappers/x11/xkb.nim (renamed from lib/base/x11/xkb.nim)0
-rw-r--r--lib/wrappers/x11/xkblib.nim (renamed from lib/base/x11/xkblib.nim)0
-rw-r--r--lib/wrappers/x11/xlib.nim (renamed from lib/base/x11/xlib.nim)0
-rw-r--r--lib/wrappers/x11/xrandr.nim (renamed from lib/base/x11/xrandr.nim)0
-rw-r--r--lib/wrappers/x11/xrender.nim (renamed from lib/base/x11/xrender.nim)0
-rw-r--r--lib/wrappers/x11/xresource.nim (renamed from lib/base/x11/xresource.nim)0
-rw-r--r--lib/wrappers/x11/xshm.nim (renamed from lib/base/x11/xshm.nim)0
-rw-r--r--lib/wrappers/x11/xutil.nim (renamed from lib/base/x11/xutil.nim)0
-rw-r--r--lib/wrappers/x11/xv.nim (renamed from lib/base/x11/xv.nim)0
-rw-r--r--lib/wrappers/x11/xvlib.nim (renamed from lib/base/x11/xvlib.nim)0
-rw-r--r--lib/wrappers/zip/libzip.nim (renamed from lib/base/zip/libzip.nim)0
-rw-r--r--lib/wrappers/zip/libzip_all.c (renamed from lib/base/zip/libzip_all.c)0
-rw-r--r--lib/wrappers/zip/zlib.nim (renamed from lib/base/zip/zlib.nim)0
-rw-r--r--lib/wrappers/zip/zzip.nim (renamed from lib/base/zip/zzip.nim)0
-rw-r--r--nim/ast.pas154
-rw-r--r--nim/ccgexprs.pas161
-rw-r--r--nim/ccgstmts.pas6
-rw-r--r--nim/ccgtypes.pas20
-rw-r--r--nim/ccgutils.pas9
-rw-r--r--nim/cgen.pas70
-rw-r--r--nim/commands.pas3
-rw-r--r--nim/condsyms.pas3
-rw-r--r--nim/docgen.pas10
-rw-r--r--nim/ecmasgen.pas43
-rw-r--r--nim/evals.pas53
-rw-r--r--nim/extccomp.pas6
-rw-r--r--nim/magicsys.pas1
-rw-r--r--nim/msgs.pas1102
-rw-r--r--nim/nimconf.pas13
-rw-r--r--nim/nversion.pas4
-rw-r--r--nim/parsecfg.pas9
-rw-r--r--nim/paslex.pas10
-rw-r--r--nim/pnimsyn.pas11
-rw-r--r--nim/pragmas.pas9
-rw-r--r--nim/procfind.pas48
-rw-r--r--nim/rnimsyn.pas7
-rw-r--r--nim/rst.pas2
-rw-r--r--nim/scanner.pas60
-rw-r--r--nim/sem.pas4
-rw-r--r--nim/semexprs.pas126
-rw-r--r--nim/semfold.pas25
-rw-r--r--nim/semstmts.pas36
-rw-r--r--nim/semtypes.pas35
-rw-r--r--nim/sigmatch.pas42
-rw-r--r--nim/transf.pas58
-rw-r--r--nim/transtmp.pas2
-rw-r--r--nim/trees.pas4
-rw-r--r--nim/types.pas125
-rw-r--r--nim/wordrecg.pas60
-rw-r--r--rod/nimrod.dot60
-rw-r--r--rod/nimrod.ini70
-rw-r--r--tests/thallo.nim2
-rw-r--r--tests/tlibs.nim6
-rw-r--r--tests/ttempl3.nim10
-rw-r--r--tools/inno.tmpl9
-rw-r--r--tools/install.tmpl186
-rw-r--r--tools/niminst.nim155
193 files changed, 9082 insertions, 17620 deletions
diff --git a/.bzrignore b/.bzrignore
index 9876e6433..a638ed4bd 100644
--- a/.bzrignore
+++ b/.bzrignore
@@ -14,4 +14,5 @@ web
 misc
 lib/base/devel
 lib/base/devel/*
-
+lib/devel
+lib/devel/*
diff --git a/config/nimdoc.cfg b/config/nimdoc.cfg
index 73886ceee..489aa0b9f 100644
--- a/config/nimdoc.cfg
+++ b/config/nimdoc.cfg
@@ -1,297 +1,278 @@
-# This is the config file for the documentation generator.

-# (c) 2009 Andreas Rumpf

-# Feel free to edit the templates as you need.

-

-split.item.toc = "20"  

-# too long entries in the table of contents wrap around

-# after this number of characters

-

-doc.section = """

-<div class="section" id="$sectionID">

-<h1><a class="toc-backref" href="#$sectionTitleID">$sectionTitle</a></h1>

-<dl class="item">

-$content

-</dl></div>

-"""

-

-doc.section.toc = """

-<li>

-  <a class="reference" href="#$sectionID" id="$sectionTitleID">$sectionTitle</a>

-  <ul class="simple">

-    $content

-  </ul>

-</li>

-"""

-

-doc.item = """

-<dt id="$itemID"><pre>$header</pre></dt>

-<dd>

-$desc

-</dd>

-"""

-

-doc.item.toc = """

-  <li><a class="reference" href="#$itemID">$name</a></li>

-"""

-

-doc.toc = """

-<div class="navigation">

-<p class="topic-title first">Navigation</p>

-<ul class="simple">

-$content

-</ul>

-</div>"""

-

-doc.body_toc = """

-$tableofcontents

-<div class="content">

-$moduledesc

-$content

-</div>

-"""

-

-doc.body_no_toc = """

-$moduledesc

-$content

-"""

-

-doc.file = """<?xml version="1.0" encoding="utf-8" ?>

-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"

-  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

-<!--  This file is generated by Nimrod. -->

-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">

-<head>

-<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

-<title>$title</title>

-<style type="text/css">

-

-span.DecNumber {color: blue}

-span.BinNumber {color: blue}

-span.HexNumber {color: blue}

-span.OctNumber {color: blue}

-span.FloatNumber {color: blue}

-span.Identifier  {color: black}

-span.Keyword {font-weight: bold}

-span.StringLit {color: blue}

-span.LongStringLit {color: blue}

-span.CharLit {color: blue}

-span.EscapeSequence {color: black}

-span.Operator {color: black}

-span.Punctation {color: black}

-span.Comment, span.LongComment {font-style:italic; color: green}

-span.RegularExpression  {color: pink}

-span.TagStart {color: yellow}

-span.TagEnd {color: yellow}

-span.Key  {color: blue}

-span.Value  {color: black}

-span.RawData {color: blue}

-span.Assembler  {color: blue}

-span.Preprocessor {color: yellow}

-span.Directive  {color: yellow}

-span.Command, span.Rule, span.Hyperlink, span.Label, span.Reference, 

-span.Other  {color: black}

-

-div.navigation {

-  float: left; 

-  width: 27%;  //25em;

-  margin: 0; padding: 0; /*

-  border: 1px dashed gold; */

-  outline: 3px outset #7F7F7F; //#99ff99; //gold;

-  background-color: #7F7F7F;

-}

-

-div.navigation ul {list-style-type: none;}

-div.navigation ul li a, div.navigation ul li a:visited {

-  font-weight: bold;

-  color: #FFFFFF; // #CC0000;

-  text-decoration: none;

-}

-div.navigation ul li a:hover {

-  font-weight: bold;

-  text-decoration: none;

-  /*outline: 2px outset #7F7F7F;*/

-  color: gold;

-  /* background-color: #FFFFFF; // #1A1A1A; // #779977;*/

-}

-

-div.content {

-  margin-left: 27%; // 25em;

-  padding: 0 1em; 

-  /*border: 1px dashed #1A1A1A;*/

-  min-width: 16em;

-}

-

-dl.item dd, dl.item dd p {

-  margin-top:3px;

-}

-dl.item dd pre {

-  margin-left: 15pt;

-  border: 0px;

-}

-dl.item dt, dl.item dt pre {

-  margin:  20pt 0 0 0;

-}

-

-pre, span.tok {

-  background-color:#F9F9F9;

-  border:1px dotted #2F6FAB;

-  color:black;

+# This is the config file for the documentation generator.
+# (c) 2009 Andreas Rumpf
+# Feel free to edit the templates as you need.
+
+split.item.toc = "20"  
+# too long entries in the table of contents wrap around
+# after this number of characters
+
+doc.section = """
+<div class="section" id="$sectionID">
+<h1><a class="toc-backref" href="#$sectionTitleID">$sectionTitle</a></h1>
+<dl class="item">
+$content
+</dl></div>
+"""
+
+doc.section.toc = """
+<li>
+  <a class="reference" href="#$sectionID" id="$sectionTitleID">$sectionTitle</a>
+  <ul class="simple">
+    $content
+  </ul>
+</li>
+"""
+
+doc.item = """
+<dt id="$itemID"><pre>$header</pre></dt>
+<dd>
+$desc
+</dd>
+"""
+
+doc.item.toc = """
+  <li><a class="reference" href="#$itemID">$name</a></li>
+"""
+
+doc.toc = """
+<div class="navigation" id="navigation">
+<p class="topic-title first">Navigation</p>
+<ul class="simple">
+$content
+</ul>
+</div>"""
+
+doc.body_toc = """
+$tableofcontents
+<div class="content" id="content">
+$moduledesc
+$content
+</div>
+"""
+
+doc.body_no_toc = """
+$moduledesc
+$content
+"""
+
+doc.file = """<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<!--  This file is generated by Nimrod. -->
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<title>$title</title>
+<style type="text/css">
+
+span.DecNumber {color: blue}
+span.BinNumber {color: blue}
+span.HexNumber {color: blue}
+span.OctNumber {color: blue}
+span.FloatNumber {color: blue}
+span.Identifier  {color: black}
+span.Keyword {font-weight: bold}
+span.StringLit {color: blue}
+span.LongStringLit {color: blue}
+span.CharLit {color: blue}
+span.EscapeSequence {color: black}
+span.Operator {color: black}
+span.Punctation {color: black}
+span.Comment, span.LongComment {font-style:italic; color: green}
+span.RegularExpression  {color: pink}
+span.TagStart {color: yellow}
+span.TagEnd {color: yellow}
+span.Key  {color: blue}
+span.Value  {color: black}
+span.RawData {color: blue}
+span.Assembler  {color: blue}
+span.Preprocessor {color: yellow}
+span.Directive  {color: yellow}
+span.Command, span.Rule, span.Hyperlink, span.Label, span.Reference, 
+span.Other  {color: black}
+
+div.navigation {
+  float: left; 
+  width: 30%;
+  margin: 0; padding: 0;
+  border: 3px outset #7F7F7F;
+  background-color: #7F7F7F;
+  -moz-border-radius-bottomleft:5px;
+  -moz-border-radius-bottomright:5px;
+  -moz-border-radius-topleft:5px;
+  -moz-border-radius-topright:5px; 
+}
+
+div.navigation ul {
+  list-style-type: none;
+  padding-left: 1em;
+}
+div.navigation ul li a, div.navigation ul li a:visited {
+  font-weight: bold;
+  color: #FFFFFF;
+  text-decoration: none;
+}
+div.navigation ul li a:hover {
+  font-weight: bold;
+  text-decoration: none;
+  color: gold;
+}
+
+div.content {
+  margin-left: 30%;
+  padding: 0 1em;
+  border-left: 4em;
+}
+
+dl.item dd, dl.item dd p {
+  margin-top:3px;
+}
+dl.item dd pre {
+  margin-left: 15pt;
+  border: 0px;
+}
+dl.item dt, dl.item dt pre {
+  margin:  20pt 0 0 0;
+}
+
+pre, span.tok {
+  background-color:#F9F9F9;
+  border:1px dotted #2F6FAB;
+  color:black;
 }
 
 span.red {
   color: #A80000;
-}

-

-/*

-:Author: David Goodger

-:Contact: goodger@python.org

-:Date: Date: 2006-05-21 22:44:42 +0200 (Sun, 21 May 2006)

-:Revision: Revision: 4564

-:Copyright: This stylesheet has been placed in the public domain.

-

-Default cascading style sheet for the HTML output of Docutils.

-

-See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to

-customize this style sheet.

-*/

-/* used to remove borders from tables and images */

-.borderless, table.borderless td, table.borderless th { border: 0 }

-

-table.borderless td, table.borderless th {

-  /* Override padding for "table.docutils td" with "! important".

-     The right padding separates the table cells. */

-  padding: 0 0.5em 0 0 ! important }

-

-.first { margin-top: 0 ! important }

-.last, .with-subtitle { margin-bottom: 0 ! important }

-.hidden { display: none }

-a.toc-backref { text-decoration: none ; color: black }

-blockquote.epigraph { margin: 2em 5em ; }

-dl.docutils dd { margin-bottom: 0.5em }

-div.abstract { margin: 2em 5em }

-div.abstract p.topic-title { font-weight: bold ; text-align: center }

-div.admonition, div.attention, div.caution, div.danger, div.error,

-div.hint, div.important, div.note, div.tip, div.warning {

-  margin: 2em ; border: medium outset ; padding: 1em }

-div.admonition p.admonition-title, div.hint p.admonition-title,

-div.important p.admonition-title, div.note p.admonition-title,

-div.tip p.admonition-title { font-weight: bold ; font-family: sans-serif }

-

-div.attention p.admonition-title, div.caution p.admonition-title,

-div.danger p.admonition-title, div.error p.admonition-title,

-div.warning p.admonition-title { color: red ; font-weight: bold ;

-  font-family: sans-serif }

-

-/* Uncomment (and remove this text!) to get reduced vertical space in

-   compound paragraphs.

-div.compound .compound-first, div.compound .compound-middle {

-  margin-bottom: 0.5em }

-

-div.compound .compound-last, div.compound .compound-middle {

-  margin-top: 0.5em }

-*/

-

-div.dedication { margin: 2em 5em ; text-align: center ; font-style: italic }

-div.dedication p.topic-title { font-weight: bold ; font-style: normal }

-div.figure { margin-left: 2em ; margin-right: 2em }

-div.footer, div.header { clear: both; font-size: smaller }

-div.line-block { display: block ; margin-top: 1em ; margin-bottom: 1em }

-div.line-block div.line-block { margin-top: 0 ; margin-bottom: 0 ;

-  margin-left: 1.5em }

-div.sidebar { margin-left: 1em ; border: medium outset ;

-  padding: 1em ; background-color: #ffffee ; width: 40% ; float: right ;

-  clear: right }

-

-div.sidebar p.rubric { font-family: sans-serif ; font-size: medium }

-div.system-messages { margin: 5em }

-div.system-messages h1 { color: red }

-div.system-message { border: medium outset ; padding: 1em }

-div.system-message p.system-message-title { color: red ; font-weight: bold }

-div.topic { margin: 2em;}

-h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,

-h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {

-  margin-top: 0.4em }

-h1.title { text-align: center }

-h2.subtitle { text-align: center }

-hr.docutils { width: 75% }

-img.align-left { clear: left }

-img.align-right { clear: right }

-ol.simple, ul.simple { margin-bottom: 1em }

-ol.arabic { list-style: decimal }

-ol.loweralpha { list-style: lower-alpha }

-ol.upperalpha { list-style: upper-alpha }

-ol.lowerroman { list-style: lower-roman }

-ol.upperroman { list-style: upper-roman }

-p.attribution { text-align: right ; margin-left: 50% }

-p.caption { font-style: italic }

-p.credits { font-style: italic ; font-size: smaller }

-p.label { white-space: nowrap }

-p.rubric { font-weight:bold;font-size:larger;color:maroon;text-align:center}

-p.sidebar-title {font-family: sans-serif ;font-weight: bold ;font-size: larger }

-p.sidebar-subtitle {font-family: sans-serif ; font-weight: bold }

-p.topic-title { font-weight: bold }

-pre.address { margin-bottom: 0;margin-top:0;font-family:serif;font-size:100% }

-pre.literal-block, pre.doctest-block {margin-left: 2em ;margin-right: 2em }

-span.classifier {font-family: sans-serif;font-style: oblique }

-span.classifier-delimiter {font-family: sans-serif;font-weight: bold }

-span.interpreted {font-family: sans-serif }

-span.option {white-space: nowrap }

-span.pre {white-space: pre }

-span.problematic {color: red }

-span.section-subtitle {

-  /* font-size relative to parent (h1..h6 element) */

-  font-size: 80% }

-

-table.citation { border-left: solid 1px gray; margin-left: 1px }

-table.docinfo {margin: 2em 4em }

-table.docutils {margin-top: 0.5em;margin-bottom: 0.5em }

-table.footnote {border-left: solid 1px black;margin-left: 1px }

-

-table.docutils td, table.docutils th,

-table.docinfo td, table.docinfo th {padding-left: 0.5em;padding-right: 0.5em;

-  vertical-align: top}

-

-table.docutils th.field-name, table.docinfo th.docinfo-name {

-  font-weight: bold;text-align: left;white-space: nowrap;padding-left: 0 }

-h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,

-h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {font-size: 100% }

-ul.auto-toc { list-style-type: none }

-/*a.reference { color: #E00000; font-weight:bold;}

-a.reference:hover {color: #E00000;background-color: #ffff00;display: margin;

-  font-weight:bold;}*/

-

-</style>

-<script type="text/javascript">

-  //<![CDATA[

-    function toggleElem(id) {

-      var e = document.getElementById(id);

-      e.style.display = e.style.display == 'none' ? 'block' : 'none';

-    }

-

-    var gOpen = 'none'

-    function toggleAll() {

-      gOpen = gOpen == 'none' ? 'block' : 'none';

-      var i = 1

-      while (1) {

-        var e = document.getElementById("m"+i)

-        if (!e) break;

-        e.style.display = gOpen

-        i++;

-      }

-      document.getElementById('toggleButton').value =

-        gOpen == 'none' ? 'Show Details' : 'Hide Details';

-    }

-  //]]>

-</script>

-

-</head>

-<body>

-<div class="document" id="documentId">

-<h1 class="title">$title</h1>

-$content

-<small>Generated: $date $time UTC</small>

-</div>

-</body>

-</html>

-"""

-

+}
+
+/*
+:Author: David Goodger
+:Contact: goodger@python.org
+:Date: Date: 2006-05-21 22:44:42 +0200 (Sun, 21 May 2006)
+:Revision: Revision: 4564
+:Copyright: This stylesheet has been placed in the public domain.
+
+Default cascading style sheet for the HTML output of Docutils.
+
+See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
+customize this style sheet.
+*/
+/* used to remove borders from tables and images */
+.borderless, table.borderless td, table.borderless th { border: 0 }
+
+table.borderless td, table.borderless th {
+  /* Override padding for "table.docutils td" with "! important".
+     The right padding separates the table cells. */
+  padding: 0 0.5em 0 0 ! important }
+
+.first { margin-top: 0 ! important }
+.last, .with-subtitle { margin-bottom: 0 ! important }
+.hidden { display: none }
+a.toc-backref { text-decoration: none ; color: black }
+blockquote.epigraph { margin: 2em 5em ; }
+dl.docutils dd { margin-bottom: 0.5em }
+div.abstract { margin: 2em 5em }
+div.abstract p.topic-title { font-weight: bold ; text-align: center }
+div.admonition, div.attention, div.caution, div.danger, div.error,
+div.hint, div.important, div.note, div.tip, div.warning {
+  margin: 2em ; border: medium outset ; padding: 1em }
+div.admonition p.admonition-title, div.hint p.admonition-title,
+div.important p.admonition-title, div.note p.admonition-title,
+div.tip p.admonition-title { font-weight: bold ; font-family: sans-serif }
+
+div.attention p.admonition-title, div.caution p.admonition-title,
+div.danger p.admonition-title, div.error p.admonition-title,
+div.warning p.admonition-title { color: red ; font-weight: bold ;
+  font-family: sans-serif }
+
+/* Uncomment (and remove this text!) to get reduced vertical space in
+   compound paragraphs.
+div.compound .compound-first, div.compound .compound-middle {
+  margin-bottom: 0.5em }
+
+div.compound .compound-last, div.compound .compound-middle {
+  margin-top: 0.5em }
+*/
+
+div.dedication { margin: 2em 5em ; text-align: center ; font-style: italic }
+div.dedication p.topic-title { font-weight: bold ; font-style: normal }
+div.figure { margin-left: 2em ; margin-right: 2em }
+div.footer, div.header { clear: both; font-size: smaller }
+div.line-block { display: block ; margin-top: 1em ; margin-bottom: 1em }
+div.line-block div.line-block { margin-top: 0 ; margin-bottom: 0 ;
+  margin-left: 1.5em }
+div.sidebar { margin-left: 1em ; border: medium outset ;
+  padding: 1em ; background-color: #ffffee ; /*width: 40% ;*/ float: right ;
+  clear: right }
+
+div.sidebar p.rubric { font-family: sans-serif ; font-size: medium }
+div.system-messages { margin: 5em }
+div.system-messages h1 { color: red }
+div.system-message { border: medium outset ; padding: 1em }
+div.system-message p.system-message-title { color: red ; font-weight: bold }
+div.topic { margin: 2em;}
+h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
+h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
+  margin-top: 0.4em }
+h1.title { text-align: center }
+h2.subtitle { text-align: center }
+/* hr.docutils { width: 75% } */
+img.align-left { clear: left }
+img.align-right { clear: right }
+ol.simple, ul.simple { margin-bottom: 1em }
+ol.arabic { list-style: decimal }
+ol.loweralpha { list-style: lower-alpha }
+ol.upperalpha { list-style: upper-alpha }
+ol.lowerroman { list-style: lower-roman }
+ol.upperroman { list-style: upper-roman }
+p.attribution { text-align: right ; margin-left: 50% }
+p.caption { font-style: italic }
+p.credits { font-style: italic ; font-size: smaller }
+p.label { white-space: nowrap }
+p.rubric { font-weight:bold;font-size:larger;color:maroon;text-align:center}
+p.sidebar-title {font-family: sans-serif ;font-weight: bold ;font-size: larger }
+p.sidebar-subtitle {font-family: sans-serif ; font-weight: bold }
+p.topic-title { font-weight: bold }
+pre.address { margin-bottom: 0;margin-top:0;font-family:serif;font-size:100% }
+pre.literal-block, pre.doctest-block {margin-left: 2em ;margin-right: 2em }
+span.classifier {font-family: sans-serif;font-style: oblique }
+span.classifier-delimiter {font-family: sans-serif;font-weight: bold }
+span.interpreted {font-family: sans-serif }
+span.option {white-space: nowrap }
+span.pre {white-space: pre }
+span.problematic {color: red }
+span.section-subtitle {
+  /* font-size relative to parent (h1..h6 element) */
+  font-size: 80% }
+
+table.citation { border-left: solid 1px gray; margin-left: 1px }
+table.docinfo {margin: 2em 4em }
+table.docutils {margin-top: 0.5em;margin-bottom: 0.5em }
+table.footnote {border-left: solid 1px black;margin-left: 1px }
+
+table.docutils td, table.docutils th,
+table.docinfo td, table.docinfo th {padding-left: 0.5em;padding-right: 0.5em;
+  vertical-align: top}
+
+table.docutils th.field-name, table.docinfo th.docinfo-name {
+  font-weight: bold;text-align: left;white-space: nowrap;padding-left: 0 }
+h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
+h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {font-size: 100% }
+ul.auto-toc { list-style-type: none }
+/*a.reference { color: #E00000; font-weight:bold;}
+a.reference:hover {color: #E00000;background-color: #ffff00;display: margin;
+  font-weight:bold;}*/
+
+</style>
+
+</head>
+<body>
+<div class="document" id="documentId">
+<h1 class="title">$title</h1>
+$content
+<small>Generated: $date $time UTC</small>
+</div>
+</body>
+</html>
+"""
+
diff --git a/config/nimrod.cfg b/config/nimrod.cfg
index 4eb7b785b..8ff1b1d86 100644
--- a/config/nimrod.cfg
+++ b/config/nimrod.cfg
@@ -8,18 +8,21 @@
 # Environment variables cannot be used in the options, however!

 

 cc = gcc

-lib="$nimrod/lib"

-path="$lib/base"

-path="$lib/base/gtk"

-path="$lib/base/cairo"

-path="$lib/base/x11"

-path="$lib/base/sdl"

-path="$lib/base/opengl"

-path="$lib/base/zip"

+#lib="" # default can be overridden here

+path="$lib/pure"

+path="$lib/impure"

+path="$lib/wrappers"

+path="$lib/wrappers/cairo"

+path="$lib/wrappers/gtk"

+path="$lib/wrappers/lua"

+path="$lib/wrappers/opengl"

+path="$lib/wrappers/pcre"

+path="$lib/wrappers/sdl"

+path="$lib/wrappers/x11"

+path="$lib/wrappers/zip"

 path="$lib/windows"

 path="$lib/posix"

 path="$lib/ecmas"

-path="$lib/extra"

 

 @if release:

   obj_checks:off

diff --git a/data/ast.yml b/data/ast.yml
index c4b261bba..82776a8f9 100644
--- a/data/ast.yml
+++ b/data/ast.yml
@@ -1,14 +1,14 @@
 #
 #
 #           The Nimrod Compiler
-#        (c) Copyright 2008 Andreas Rumpf
+#        (c) Copyright 2009 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
 #
 
 {
-'SymFlag': [          # already 26 flags!
+'SymFlag': [          # already 28 flags!
   'sfUsed',           # read access of sym (for warnings) or simply used
   'sfStar',           # symbol has * visibility
   'sfMinus',          # symbol has - visibility
@@ -42,6 +42,7 @@
   'sfThreadVar',      # variable is a thread variable
   'sfMerge',          # proc can be merged with itself
   'sfDeadCodeElim',   # dead code elimination for the module is turned on
+  'sfBorrow'          # proc is borrowed
 ],
 
 'TypeFlag': [
@@ -58,8 +59,9 @@
   'tyGeneric',
   'tyGenericInst', # instantiated generic type
   'tyGenericParam',
+  'tyAbstract',    # abstract type
   'tyEnum',
-  'tyAnyEnum',
+  'tyOrdinal',
   'tyArray',
   'tyObject',
   'tyTuple',
@@ -233,6 +235,7 @@
   'nkRefTy',
   'nkPtrTy',
   'nkVarTy',
+  'nkAbstractTy',         # abstract type
   'nkProcTy',
   'nkEnumTy',
   'nkEnumFieldDef',       # `ident = expr` in an enumeration
diff --git a/data/keywords.txt b/data/keywords.txt
index 5915bab05..d6cba0635 100644
--- a/data/keywords.txt
+++ b/data/keywords.txt
@@ -1,4 +1,4 @@
-addr and as asm
+abstract addr and as asm
 block break
 case cast const continue converter
 discard div
@@ -14,6 +14,6 @@ raise ref return
 shl shr
 template try tuple type
 var
-when where while with without
+when while with without
 xor
 yield
diff --git a/data/magic.yml b/data/magic.yml
index 19013ccc4..d0aeb378f 100644
--- a/data/magic.yml
+++ b/data/magic.yml
@@ -7,6 +7,7 @@
 'High',
 'SizeOf',
 'Is',
+'Echo',
 'Succ',
 'Pred',
 'Inc',
@@ -167,7 +168,6 @@
 'AppendSeqSeq',
 'InRange',
 'InSet',
-'Asgn',
 'Repr',
 'Exit',
 'SetLengthStr',
@@ -186,6 +186,7 @@
 'Range',
 'Set',
 'Seq',
+'Ordinal',
 'Int',
 'Int8',
 'Int16',
@@ -199,7 +200,6 @@
 'String',
 'Cstring',
 'Pointer', 
-'AnyEnum',
 'EmptySet',
 'IntSetBaseType',
 'Nil',
diff --git a/data/messages.yml b/data/messages.yml
index 271fadfe4..5cbfe60a7 100644
--- a/data/messages.yml
+++ b/data/messages.yml
@@ -172,10 +172,9 @@
 {'errXCannotBeInParamDecl': '$1 cannot be declared in parameter declaration'},
 {'errPragmaOnlyInHeaderOfProc':
   'pragmas are only in the header of a proc allowed'},
-{'errImportedProcCannotHaveImpl':
-  'an imported proc cannot have an implementation'},
-{'errImplOfXNotAllowed': "implementation of '$1' is not allowed here"},
+{'errImplOfXNotAllowed': "implementation of '$1' is not allowed"},
 {'errImplOfXexpected': "implementation of '$1' expected"},
+{'errNoSymbolToBorrowFromFound': "no symbol to borrow from found"},
 {'errDiscardValue': 'value returned by statement has to be discarded'},
 {'errInvalidDiscard': 'statement returns no value that can be discarded'},
 {'errUnknownPrecedence':
diff --git a/doc/grammar.txt b/doc/grammar.txt
index 11e26e33f..91ce6a911 100644
--- a/doc/grammar.txt
+++ b/doc/grammar.txt
@@ -155,7 +155,7 @@ colonAndEquals ::= [':' typeDesc] '=' expr
 constDecl ::= symbol ['*'] [pragma] colonAndEquals [COMMENT | IND COMMENT]
             | COMMENT
 constSection ::= 'const' indPush constDecl (SAD constDecl)* DED indPop
-typeDef ::= typeDesc | objectDef | enumDef
+typeDef ::= typeDesc | objectDef | enumDef | 'abstract' typeDesc
 
 objectField ::= symbol ['*'] [pragma]
 objectIdentPart ::=
diff --git a/doc/lib.txt b/doc/lib.txt
index 0b11c28cc..ec861b4c1 100644
--- a/doc/lib.txt
+++ b/doc/lib.txt
@@ -48,6 +48,9 @@ Pure libraries
 * `times <times.html>`_
   The ``times`` module contains basic support for working with time.
 
+* `dynlib <dynlib.html>`_
+  This module implements the ability to access symbols from shared libraries.
+
 * `parseopt <parseopt.html>`_
   The ``parseopt`` module implements a command line option parser. This
   supports long and short command options with optional values and command line
@@ -202,9 +205,13 @@ not contained in the distribution. You can then find them on the website.
   Part of the wrapper for Lua.
 * `lauxlib <lauxlib.html>`_
   Part of the wrapper for Lua.
-* `odbcsql <odbcsql.nim>`_
-  interface to the ODBC driver. 
-* `zlib <zlib.nim>`_
+* `tcl <tcl.html>`_ 
+  Wrapper for the TCL programming language.
+* `python <python.html>`_
+  Wrapper for the Python programming language.
+* `odbcsql <odbcsql.html>`_
+  interface to the ODBC driver.
+* `zlib <zlib.html>`_
   Wrapper for the zlib library. 
 * `sdl <sdl.html>`_
   Part of the wrapper for SDL.
diff --git a/doc/manual.txt b/doc/manual.txt
index 393363a47..8b7e264ad 100644
--- a/doc/manual.txt
+++ b/doc/manual.txt
@@ -1649,7 +1649,7 @@ possible within a single ``type`` section.
 Generics
 ~~~~~~~~
 
-`Version 0.7.8: Generic types like in the example do not work.`:red:
+`Version 0.7.10: Generic types like in the example do not work.`:red:
 
 Example:
 
diff --git a/doc/theindex.txt b/doc/theindex.txt
index 24d58ec68..b5650e1be 100644
--- a/doc/theindex.txt
+++ b/doc/theindex.txt
@@ -10,17 +10,17 @@ Index
      `macros.html#115 <macros.html#115>`_
 
    `!=`:idx:
-     `system.html#353 <system.html#353>`_
+     `system.html#355 <system.html#355>`_
 
    `$`:idx:
-     * `system.html#424 <system.html#424>`_
-     * `system.html#425 <system.html#425>`_
      * `system.html#426 <system.html#426>`_
      * `system.html#427 <system.html#427>`_
      * `system.html#428 <system.html#428>`_
      * `system.html#429 <system.html#429>`_
      * `system.html#430 <system.html#430>`_
      * `system.html#431 <system.html#431>`_
+     * `system.html#432 <system.html#432>`_
+     * `system.html#433 <system.html#433>`_
      * `times.html#109 <times.html#109>`_
      * `times.html#110 <times.html#110>`_
      * `macros.html#116 <macros.html#116>`_
@@ -31,164 +31,162 @@ Index
      * `strtabs.html#112 <strtabs.html#112>`_
 
    `%%`:idx:
-     * `system.html#298 <system.html#298>`_
-     * `system.html#299 <system.html#299>`_
      * `system.html#300 <system.html#300>`_
      * `system.html#301 <system.html#301>`_
      * `system.html#302 <system.html#302>`_
+     * `system.html#303 <system.html#303>`_
+     * `system.html#304 <system.html#304>`_
 
    `&`:idx:
-     * `system.html#364 <system.html#364>`_
-     * `system.html#365 <system.html#365>`_
      * `system.html#366 <system.html#366>`_
      * `system.html#367 <system.html#367>`_
-     * `system.html#455 <system.html#455>`_
-     * `system.html#456 <system.html#456>`_
+     * `system.html#368 <system.html#368>`_
+     * `system.html#369 <system.html#369>`_
      * `system.html#457 <system.html#457>`_
      * `system.html#458 <system.html#458>`_
+     * `system.html#459 <system.html#459>`_
+     * `system.html#460 <system.html#460>`_
 
    `*`:idx:
-     * `system.html#206 <system.html#206>`_
-     * `system.html#207 <system.html#207>`_
      * `system.html#208 <system.html#208>`_
      * `system.html#209 <system.html#209>`_
      * `system.html#210 <system.html#210>`_
-     * `system.html#317 <system.html#317>`_
-     * `system.html#325 <system.html#325>`_
+     * `system.html#211 <system.html#211>`_
+     * `system.html#212 <system.html#212>`_
+     * `system.html#319 <system.html#319>`_
+     * `system.html#327 <system.html#327>`_
      * `complex.html#107 <complex.html#107>`_
 
    `*%`:idx:
-     * `system.html#288 <system.html#288>`_
-     * `system.html#289 <system.html#289>`_
      * `system.html#290 <system.html#290>`_
      * `system.html#291 <system.html#291>`_
      * `system.html#292 <system.html#292>`_
+     * `system.html#293 <system.html#293>`_
+     * `system.html#294 <system.html#294>`_
 
    `+`:idx:
-     * `system.html#181 <system.html#181>`_
-     * `system.html#182 <system.html#182>`_
      * `system.html#183 <system.html#183>`_
      * `system.html#184 <system.html#184>`_
      * `system.html#185 <system.html#185>`_
-     * `system.html#196 <system.html#196>`_
-     * `system.html#197 <system.html#197>`_
+     * `system.html#186 <system.html#186>`_
+     * `system.html#187 <system.html#187>`_
      * `system.html#198 <system.html#198>`_
      * `system.html#199 <system.html#199>`_
      * `system.html#200 <system.html#200>`_
-     * `system.html#313 <system.html#313>`_
+     * `system.html#201 <system.html#201>`_
+     * `system.html#202 <system.html#202>`_
      * `system.html#315 <system.html#315>`_
-     * `system.html#326 <system.html#326>`_
+     * `system.html#317 <system.html#317>`_
+     * `system.html#328 <system.html#328>`_
      * `complex.html#103 <complex.html#103>`_
 
    `+%`:idx:
-     * `system.html#278 <system.html#278>`_
-     * `system.html#279 <system.html#279>`_
      * `system.html#280 <system.html#280>`_
      * `system.html#281 <system.html#281>`_
      * `system.html#282 <system.html#282>`_
+     * `system.html#283 <system.html#283>`_
+     * `system.html#284 <system.html#284>`_
 
    `-`:idx:
-     * `system.html#186 <system.html#186>`_
-     * `system.html#187 <system.html#187>`_
      * `system.html#188 <system.html#188>`_
      * `system.html#189 <system.html#189>`_
      * `system.html#190 <system.html#190>`_
-     * `system.html#201 <system.html#201>`_
-     * `system.html#202 <system.html#202>`_
+     * `system.html#191 <system.html#191>`_
+     * `system.html#192 <system.html#192>`_
      * `system.html#203 <system.html#203>`_
      * `system.html#204 <system.html#204>`_
      * `system.html#205 <system.html#205>`_
-     * `system.html#314 <system.html#314>`_
+     * `system.html#206 <system.html#206>`_
+     * `system.html#207 <system.html#207>`_
      * `system.html#316 <system.html#316>`_
-     * `system.html#327 <system.html#327>`_
+     * `system.html#318 <system.html#318>`_
+     * `system.html#329 <system.html#329>`_
      * `complex.html#104 <complex.html#104>`_
      * `complex.html#105 <complex.html#105>`_
      * `times.html#113 <times.html#113>`_
 
    `-%`:idx:
-     * `system.html#283 <system.html#283>`_
-     * `system.html#284 <system.html#284>`_
      * `system.html#285 <system.html#285>`_
      * `system.html#286 <system.html#286>`_
      * `system.html#287 <system.html#287>`_
+     * `system.html#288 <system.html#288>`_
+     * `system.html#289 <system.html#289>`_
 
    `-+-`:idx:
-     `system.html#328 <system.html#328>`_
+     `system.html#330 <system.html#330>`_
 
    `/`:idx:
-     * `system.html#318 <system.html#318>`_
-     * `os.html#119 <os.html#119>`_
+     * `system.html#320 <system.html#320>`_
+     * `os.html#124 <os.html#124>`_
      * `complex.html#106 <complex.html#106>`_
 
    `/%`:idx:
-     * `system.html#293 <system.html#293>`_
-     * `system.html#294 <system.html#294>`_
      * `system.html#295 <system.html#295>`_
      * `system.html#296 <system.html#296>`_
      * `system.html#297 <system.html#297>`_
+     * `system.html#298 <system.html#298>`_
+     * `system.html#299 <system.html#299>`_
 
    `/../`:idx:
-     `os.html#123 <os.html#123>`_
+     `os.html#127 <os.html#127>`_
 
    `<`:idx:
-     * `system.html#256 <system.html#256>`_
-     * `system.html#257 <system.html#257>`_
      * `system.html#258 <system.html#258>`_
      * `system.html#259 <system.html#259>`_
      * `system.html#260 <system.html#260>`_
-     * `system.html#321 <system.html#321>`_
-     * `system.html#345 <system.html#345>`_
-     * `system.html#346 <system.html#346>`_
+     * `system.html#261 <system.html#261>`_
+     * `system.html#262 <system.html#262>`_
+     * `system.html#323 <system.html#323>`_
      * `system.html#347 <system.html#347>`_
      * `system.html#348 <system.html#348>`_
      * `system.html#349 <system.html#349>`_
      * `system.html#350 <system.html#350>`_
      * `system.html#351 <system.html#351>`_
      * `system.html#352 <system.html#352>`_
+     * `system.html#353 <system.html#353>`_
+     * `system.html#354 <system.html#354>`_
      * `times.html#114 <times.html#114>`_
 
    `<%`:idx:
-     * `system.html#308 <system.html#308>`_
-     * `system.html#309 <system.html#309>`_
      * `system.html#310 <system.html#310>`_
      * `system.html#311 <system.html#311>`_
      * `system.html#312 <system.html#312>`_
+     * `system.html#313 <system.html#313>`_
+     * `system.html#314 <system.html#314>`_
 
    `<=`:idx:
-     `times.html#115 <times.html#115>`_
-
-   `<=`:idx:
-     * `system.html#251 <system.html#251>`_
-     * `system.html#252 <system.html#252>`_
      * `system.html#253 <system.html#253>`_
      * `system.html#254 <system.html#254>`_
      * `system.html#255 <system.html#255>`_
-     * `system.html#320 <system.html#320>`_
-     * `system.html#338 <system.html#338>`_
-     * `system.html#339 <system.html#339>`_
+     * `system.html#256 <system.html#256>`_
+     * `system.html#257 <system.html#257>`_
+     * `system.html#322 <system.html#322>`_
      * `system.html#340 <system.html#340>`_
      * `system.html#341 <system.html#341>`_
      * `system.html#342 <system.html#342>`_
      * `system.html#343 <system.html#343>`_
      * `system.html#344 <system.html#344>`_
+     * `system.html#345 <system.html#345>`_
+     * `system.html#346 <system.html#346>`_
+
+   `<=`:idx:
+     `times.html#115 <times.html#115>`_
 
    `<=%`:idx:
-     * `system.html#303 <system.html#303>`_
-     * `system.html#304 <system.html#304>`_
      * `system.html#305 <system.html#305>`_
      * `system.html#306 <system.html#306>`_
      * `system.html#307 <system.html#307>`_
+     * `system.html#308 <system.html#308>`_
+     * `system.html#309 <system.html#309>`_
 
    `==`:idx:
      * `md5.html#107 <md5.html#107>`_
-     * `system.html#246 <system.html#246>`_
-     * `system.html#247 <system.html#247>`_
      * `system.html#248 <system.html#248>`_
      * `system.html#249 <system.html#249>`_
      * `system.html#250 <system.html#250>`_
-     * `system.html#319 <system.html#319>`_
-     * `system.html#329 <system.html#329>`_
-     * `system.html#330 <system.html#330>`_
+     * `system.html#251 <system.html#251>`_
+     * `system.html#252 <system.html#252>`_
+     * `system.html#321 <system.html#321>`_
      * `system.html#331 <system.html#331>`_
      * `system.html#332 <system.html#332>`_
      * `system.html#333 <system.html#333>`_
@@ -196,7 +194,9 @@ Index
      * `system.html#335 <system.html#335>`_
      * `system.html#336 <system.html#336>`_
      * `system.html#337 <system.html#337>`_
-     * `system.html#460 <system.html#460>`_
+     * `system.html#338 <system.html#338>`_
+     * `system.html#339 <system.html#339>`_
+     * `system.html#462 <system.html#462>`_
      * `complex.html#102 <complex.html#102>`_
      * `macros.html#117 <macros.html#117>`_
 
@@ -204,31 +204,31 @@ Index
      `regexprs.html#111 <regexprs.html#111>`_
 
    `>`:idx:
-     `system.html#355 <system.html#355>`_
+     `system.html#357 <system.html#357>`_
 
    `>%`:idx:
-     `system.html#423 <system.html#423>`_
+     `system.html#425 <system.html#425>`_
 
    `>=`:idx:
-     `system.html#354 <system.html#354>`_
+     `system.html#356 <system.html#356>`_
 
    `>=%`:idx:
-     `system.html#422 <system.html#422>`_
+     `system.html#424 <system.html#424>`_
 
    `@`:idx:
-     `system.html#363 <system.html#363>`_
+     `system.html#365 <system.html#365>`_
 
    `[]`:idx:
-     `macros.html#113 <macros.html#113>`_
+     `strtabs.html#107 <strtabs.html#107>`_
 
    `[]`:idx:
-     `strtabs.html#107 <strtabs.html#107>`_
+     `macros.html#113 <macros.html#113>`_
 
    `[]=`:idx:
-     `strtabs.html#106 <strtabs.html#106>`_
+     `macros.html#114 <macros.html#114>`_
 
    `[]=`:idx:
-     `macros.html#114 <macros.html#114>`_
+     `strtabs.html#106 <strtabs.html#106>`_
 
    `[ESC]`:idx:
      `manual.html#134 <manual.html#134>`_
@@ -237,12 +237,12 @@ Index
      `xmlgen.html#107 <xmlgen.html#107>`_
 
    `abs`:idx:
-     * `system.html#261 <system.html#261>`_
-     * `system.html#262 <system.html#262>`_
      * `system.html#263 <system.html#263>`_
      * `system.html#264 <system.html#264>`_
      * `system.html#265 <system.html#265>`_
-     * `system.html#322 <system.html#322>`_
+     * `system.html#266 <system.html#266>`_
+     * `system.html#267 <system.html#267>`_
+     * `system.html#324 <system.html#324>`_
      * `complex.html#108 <complex.html#108>`_
 
    `acronym`:idx:
@@ -252,11 +252,11 @@ Index
      `nimrodc.html#113 <nimrodc.html#113>`_
 
    `add`:idx:
-     * `system.html#368 <system.html#368>`_
-     * `system.html#369 <system.html#369>`_
      * `system.html#370 <system.html#370>`_
      * `system.html#371 <system.html#371>`_
      * `system.html#372 <system.html#372>`_
+     * `system.html#373 <system.html#373>`_
+     * `system.html#374 <system.html#374>`_
      * `macros.html#119 <macros.html#119>`_
      * `macros.html#120 <macros.html#120>`_
 
@@ -269,7 +269,7 @@ Index
      * `zipfiles.html#107 <zipfiles.html#107>`_
 
    `addQuitProc`:idx:
-     `system.html#406 <system.html#406>`_
+     `system.html#408 <system.html#408>`_
 
    `address`:idx:
      `xmlgen.html#109 <xmlgen.html#109>`_
@@ -284,10 +284,10 @@ Index
      `strutils.html#152 <strutils.html#152>`_
 
    `alloc`:idx:
-     `system.html#415 <system.html#415>`_
+     `system.html#417 <system.html#417>`_
 
    `alloc0`:idx:
-     `system.html#416 <system.html#416>`_
+     `system.html#418 <system.html#418>`_
 
    `ALLOC_MAX_BLOCK_TO_DROP`:idx:
      `mysql.html#317 <mysql.html#317>`_
@@ -299,18 +299,18 @@ Index
      `os.html#104 <os.html#104>`_
 
    `and`:idx:
-     * `system.html#116 <system.html#116>`_
-     * `system.html#231 <system.html#231>`_
-     * `system.html#232 <system.html#232>`_
+     * `system.html#117 <system.html#117>`_
      * `system.html#233 <system.html#233>`_
      * `system.html#234 <system.html#234>`_
      * `system.html#235 <system.html#235>`_
+     * `system.html#236 <system.html#236>`_
+     * `system.html#237 <system.html#237>`_
 
    `apostrophe`:idx:
      `manual.html#129 <manual.html#129>`_
 
    `AppendFileExt`:idx:
-     `os.html#131 <os.html#131>`_
+     `os.html#135 <os.html#135>`_
 
    `arccos`:idx:
      `math.html#122 <math.html#122>`_
@@ -332,7 +332,7 @@ Index
 
    `array`:idx:
      * `tut1.html#117 <tut1.html#117>`_
-     * `system.html#124 <system.html#124>`_
+     * `system.html#125 <system.html#125>`_
 
    `array properties`:idx:
      `tut2.html#105 <tut2.html#105>`_
@@ -344,7 +344,7 @@ Index
      `manual.html#196 <manual.html#196>`_
 
    `assert`:idx:
-     `system.html#420 <system.html#420>`_
+     `system.html#422 <system.html#422>`_
 
    `AST`:idx:
      `macros.html#101 <macros.html#101>`_
@@ -379,10 +379,10 @@ Index
      `xmlgen.html#113 <xmlgen.html#113>`_
 
    `BiggestFloat`:idx:
-     `system.html#376 <system.html#376>`_
+     `system.html#378 <system.html#378>`_
 
    `BiggestInt`:idx:
-     `system.html#375 <system.html#375>`_
+     `system.html#377 <system.html#377>`_
 
    `BINARY_FLAG`:idx:
      `mysql.html#131 <mysql.html#131>`_
@@ -425,7 +425,7 @@ Index
      `xmlgen.html#117 <xmlgen.html#117>`_
 
    `Byte`:idx:
-     `system.html#128 <system.html#128>`_
+     `system.html#129 <system.html#129>`_
 
    `calling conventions`:idx:
      `manual.html#163 <manual.html#163>`_
@@ -437,7 +437,7 @@ Index
      `xmlgen.html#118 <xmlgen.html#118>`_
 
    `card`:idx:
-     `system.html#169 <system.html#169>`_
+     `system.html#171 <system.html#171>`_
 
    `carriage return`:idx:
      `manual.html#122 <manual.html#122>`_
@@ -446,22 +446,22 @@ Index
      `manual.html#181 <manual.html#181>`_
 
    `cchar`:idx:
-     `system.html#377 <system.html#377>`_
+     `system.html#379 <system.html#379>`_
 
    `cdecl`:idx:
      `manual.html#165 <manual.html#165>`_
 
    `cdouble`:idx:
-     `system.html#384 <system.html#384>`_
+     `system.html#386 <system.html#386>`_
 
    `cfloat`:idx:
-     `system.html#383 <system.html#383>`_
+     `system.html#385 <system.html#385>`_
 
    `cgiError`:idx:
      `cgi.html#106 <cgi.html#106>`_
 
    `ChangeFileExt`:idx:
-     `os.html#132 <os.html#132>`_
+     `os.html#134 <os.html#134>`_
 
    `char`:idx:
      `system.html#110 <system.html#110>`_
@@ -497,10 +497,10 @@ Index
      `mysql.html#273 <mysql.html#273>`_
 
    `chr`:idx:
-     `system.html#171 <system.html#171>`_
+     `system.html#173 <system.html#173>`_
 
    `cint`:idx:
-     `system.html#380 <system.html#380>`_
+     `system.html#382 <system.html#382>`_
 
    `cite`:idx:
      `xmlgen.html#119 <xmlgen.html#119>`_
@@ -575,13 +575,13 @@ Index
      `mysql.html#169 <mysql.html#169>`_
 
    `clong`:idx:
-     `system.html#381 <system.html#381>`_
+     `system.html#383 <system.html#383>`_
 
    `clongdouble`:idx:
-     `system.html#385 <system.html#385>`_
+     `system.html#387 <system.html#387>`_
 
    `clonglong`:idx:
-     `system.html#382 <system.html#382>`_
+     `system.html#384 <system.html#384>`_
 
    `close`:idx:
      * `lexbase.html#105 <lexbase.html#105>`_
@@ -591,14 +591,14 @@ Index
      * `zipfiles.html#103 <zipfiles.html#103>`_
 
    `CloseFile`:idx:
-     `system.html#492 <system.html#492>`_
+     `system.html#493 <system.html#493>`_
 
    `closure`:idx:
      `manual.html#170 <manual.html#170>`_
 
    `cmp`:idx:
-     * `system.html#361 <system.html#361>`_
-     * `system.html#362 <system.html#362>`_
+     * `system.html#363 <system.html#363>`_
+     * `system.html#364 <system.html#364>`_
 
    `cmpIgnoreCase`:idx:
      `strutils.html#137 <strutils.html#137>`_
@@ -607,7 +607,7 @@ Index
      `strutils.html#138 <strutils.html#138>`_
 
    `cmpPaths`:idx:
-     `os.html#130 <os.html#130>`_
+     `os.html#136 <os.html#136>`_
 
    `cmpRunesIgnoreCase`:idx:
      `unicode.html#115 <unicode.html#115>`_
@@ -639,10 +639,10 @@ Index
      `mysql.html#266 <mysql.html#266>`_
 
    `CompileDate`:idx:
-     `system.html#393 <system.html#393>`_
+     `system.html#395 <system.html#395>`_
 
    `CompileTime`:idx:
-     `system.html#394 <system.html#394>`_
+     `system.html#396 <system.html#396>`_
 
    `complex statements`:idx:
      `manual.html#175 <manual.html#175>`_
@@ -658,7 +658,7 @@ Index
      * `tut1.html#104 <tut1.html#104>`_
 
    `contains`:idx:
-     * `system.html#356 <system.html#356>`_
+     * `system.html#358 <system.html#358>`_
      * `strutils.html#139 <strutils.html#139>`_
      * `strutils.html#140 <strutils.html#140>`_
      * `strutils.html#141 <strutils.html#141>`_
@@ -667,14 +667,14 @@ Index
      `manual.html#195 <manual.html#195>`_
 
    `copy`:idx:
-     * `system.html#407 <system.html#407>`_
-     * `system.html#408 <system.html#408>`_
+     * `system.html#409 <system.html#409>`_
+     * `system.html#410 <system.html#410>`_
 
    `copyFile`:idx:
-     `os.html#134 <os.html#134>`_
+     `os.html#139 <os.html#139>`_
 
    `copyMem`:idx:
-     `system.html#412 <system.html#412>`_
+     `system.html#414 <system.html#414>`_
 
    `copyNimNode`:idx:
      `macros.html#136 <macros.html#136>`_
@@ -695,32 +695,32 @@ Index
      `math.html#109 <math.html#109>`_
 
    `countdown`:idx:
-     `system.html#441 <system.html#441>`_
+     `system.html#443 <system.html#443>`_
 
    `countup`:idx:
-     `system.html#442 <system.html#442>`_
+     `system.html#444 <system.html#444>`_
 
    `cpuEndian`:idx:
-     `system.html#399 <system.html#399>`_
+     `system.html#401 <system.html#401>`_
 
    `createDir`:idx:
-     * `os.html#138 <os.html#138>`_
+     * `os.html#151 <os.html#151>`_
      * `zipfiles.html#104 <zipfiles.html#104>`_
 
    `create_random_string`:idx:
      `mysql.html#269 <mysql.html#269>`_
 
    `cschar`:idx:
-     `system.html#378 <system.html#378>`_
+     `system.html#380 <system.html#380>`_
 
    `cshort`:idx:
-     `system.html#379 <system.html#379>`_
+     `system.html#381 <system.html#381>`_
 
    `cstring`:idx:
      `system.html#112 <system.html#112>`_
 
    `cstringArray`:idx:
-     `system.html#386 <system.html#386>`_
+     `system.html#388 <system.html#388>`_
 
    `CSV`:idx:
      `parsecsv.html#101 <parsecsv.html#101>`_
@@ -1095,7 +1095,7 @@ Index
      `manual.html#176 <manual.html#176>`_
 
    `dbgLineHook`:idx:
-     `system.html#437 <system.html#437>`_
+     `system.html#439 <system.html#439>`_
 
    `dd`:idx:
      `xmlgen.html#123 <xmlgen.html#123>`_
@@ -1104,13 +1104,13 @@ Index
      `nimrodc.html#114 <nimrodc.html#114>`_
 
    `dealloc`:idx:
-     `system.html#418 <system.html#418>`_
+     `system.html#420 <system.html#420>`_
 
    `debugger`:idx:
      `nimrodc.html#110 <nimrodc.html#110>`_
 
    `dec`:idx:
-     `system.html#160 <system.html#160>`_
+     `system.html#162 <system.html#162>`_
 
    `decodeData`:idx:
      `cgi.html#107 <cgi.html#107>`_
@@ -1119,7 +1119,7 @@ Index
      `manual.html#222 <manual.html#222>`_
 
    `defined`:idx:
-     `system.html#114 <system.html#114>`_
+     `system.html#115 <system.html#115>`_
 
    `del`:idx:
      * `xmlgen.html#124 <xmlgen.html#124>`_
@@ -1141,11 +1141,11 @@ Index
      `manual.html#177 <manual.html#177>`_
 
    `div`:idx:
-     * `system.html#211 <system.html#211>`_
-     * `system.html#212 <system.html#212>`_
      * `system.html#213 <system.html#213>`_
      * `system.html#214 <system.html#214>`_
      * `system.html#215 <system.html#215>`_
+     * `system.html#216 <system.html#216>`_
+     * `system.html#217 <system.html#217>`_
      * `xmlgen.html#126 <xmlgen.html#126>`_
 
    `dl`:idx:
@@ -1174,65 +1174,67 @@ Index
      `math.html#102 <math.html#102>`_
 
    `EAccessViolation`:idx:
-     `system.html#143 <system.html#143>`_
+     `system.html#145 <system.html#145>`_
 
    `each`:idx:
-     `system.html#463 <system.html#463>`_
+     `system.html#465 <system.html#465>`_
 
    `EArithmetic`:idx:
-     `system.html#140 <system.html#140>`_
+     `system.html#142 <system.html#142>`_
 
    `EAssertionFailed`:idx:
-     `system.html#144 <system.html#144>`_
+     `system.html#146 <system.html#146>`_
 
    `EAsynch`:idx:
-     `system.html#134 <system.html#134>`_
+     `system.html#135 <system.html#135>`_
 
    `E_Base`:idx:
-     `system.html#133 <system.html#133>`_
+     `system.html#134 <system.html#134>`_
 
    `ECgi`:idx:
      `cgi.html#104 <cgi.html#104>`_
 
    `echo`:idx:
-     * `system.html#478 <system.html#478>`_
-     * `system.html#479 <system.html#479>`_
+     `system.html#480 <system.html#480>`_
 
    `ECMAScript`:idx:
      `nimrodc.html#115 <nimrodc.html#115>`_
 
    `EControlC`:idx:
-     `system.html#145 <system.html#145>`_
+     `system.html#147 <system.html#147>`_
 
    `editDistance`:idx:
      `strutils.html#159 <strutils.html#159>`_
 
    `EDivByZero`:idx:
-     `system.html#141 <system.html#141>`_
+     `system.html#143 <system.html#143>`_
 
    `EInvalidCsv`:idx:
      `parsecsv.html#105 <parsecsv.html#105>`_
 
    `EInvalidField`:idx:
-     `system.html#149 <system.html#149>`_
+     `system.html#151 <system.html#151>`_
 
    `EInvalidIndex`:idx:
-     `system.html#148 <system.html#148>`_
+     `system.html#150 <system.html#150>`_
+
+   `EInvalidLibrary`:idx:
+     `system.html#140 <system.html#140>`_
 
    `EInvalidObjectAssignment`:idx:
-     `system.html#153 <system.html#153>`_
+     `system.html#155 <system.html#155>`_
 
    `EInvalidObjectConversion`:idx:
-     `system.html#154 <system.html#154>`_
+     `system.html#156 <system.html#156>`_
 
    `EInvalidRegEx`:idx:
      `regexprs.html#104 <regexprs.html#104>`_
 
    `EInvalidValue`:idx:
-     `system.html#146 <system.html#146>`_
+     `system.html#148 <system.html#148>`_
 
    `EIO`:idx:
-     `system.html#137 <system.html#137>`_
+     `system.html#138 <system.html#138>`_
 
    `elementName`:idx:
      `parsexml.html#111 <parsexml.html#111>`_
@@ -1247,7 +1249,7 @@ Index
      `endb.html#102 <endb.html#102>`_
 
    `EndOfFile`:idx:
-     * `system.html#493 <system.html#493>`_
+     * `system.html#494 <system.html#494>`_
      * `lexbase.html#101 <lexbase.html#101>`_
 
    `endsWith`:idx:
@@ -1255,7 +1257,7 @@ Index
 
    `ENoExceptionToReraise`:idx:
      * `manual.html#184 <manual.html#184>`_
-     * `system.html#152 <system.html#152>`_
+     * `system.html#154 <system.html#154>`_
 
    `entityName`:idx:
      `parsexml.html#112 <parsexml.html#112>`_
@@ -1263,12 +1265,12 @@ Index
    `enum_cursor_type`:idx:
      `mysql.html#237 <mysql.html#237>`_
 
-   `enumeration`:idx:
-     `tut1.html#113 <tut1.html#113>`_
-
    `Enumeration`:idx:
      `manual.html#148 <manual.html#148>`_
 
+   `enumeration`:idx:
+     `tut1.html#113 <tut1.html#113>`_
+
    `enum_field_types`:idx:
      `mysql.html#202 <mysql.html#202>`_
 
@@ -1288,21 +1290,21 @@ Index
      `mysql.html#383 <mysql.html#383>`_
 
    `EOS`:idx:
-     `system.html#138 <system.html#138>`_
+     `system.html#139 <system.html#139>`_
 
    `EOutOfMemory`:idx:
-     `system.html#147 <system.html#147>`_
+     `system.html#149 <system.html#149>`_
 
    `EOutOfRange`:idx:
      * `manual.html#145 <manual.html#145>`_
      * `tut1.html#112 <tut1.html#112>`_
-     * `system.html#150 <system.html#150>`_
+     * `system.html#152 <system.html#152>`_
 
    `EOverflow`:idx:
-     `system.html#142 <system.html#142>`_
+     `system.html#144 <system.html#144>`_
 
    `equalMem`:idx:
-     `system.html#414 <system.html#414>`_
+     `system.html#416 <system.html#416>`_
 
    `EraseLine`:idx:
      `terminal.html#108 <terminal.html#108>`_
@@ -1311,7 +1313,7 @@ Index
      `terminal.html#109 <terminal.html#109>`_
 
    `ERessourceExhausted`:idx:
-     `system.html#139 <system.html#139>`_
+     `system.html#141 <system.html#141>`_
 
    `error`:idx:
      * `manual.html#221 <manual.html#221>`_
@@ -1327,6 +1329,9 @@ Index
    `errorStr`:idx:
      `parsecfg.html#110 <parsecfg.html#110>`_
 
+   `errorStream`:idx:
+     `osproc.html#114 <osproc.html#114>`_
+
    `escape`:idx:
      * `manual.html#133 <manual.html#133>`_
      * `strutils.html#156 <strutils.html#156>`_
@@ -1335,13 +1340,13 @@ Index
      `manual.html#120 <manual.html#120>`_
 
    `EStackOverflow`:idx:
-     `system.html#151 <system.html#151>`_
+     `system.html#153 <system.html#153>`_
 
    `ESynch`:idx:
-     `system.html#135 <system.html#135>`_
+     `system.html#136 <system.html#136>`_
 
    `ESystem`:idx:
-     `system.html#136 <system.html#136>`_
+     `system.html#137 <system.html#137>`_
 
    `eventAttr`:idx:
      `xmlgen.html#104 <xmlgen.html#104>`_
@@ -1356,28 +1361,38 @@ Index
      `tut2.html#106 <tut2.html#106>`_
 
    `excl`:idx:
-     `system.html#168 <system.html#168>`_
+     `system.html#170 <system.html#170>`_
+
+   `exclFilePermissions`:idx:
+     `os.html#157 <os.html#157>`_
+
+   `executeCommand`:idx:
+     `osproc.html#104 <osproc.html#104>`_
+
+   `executeProcess`:idx:
+     * `osproc.html#103 <osproc.html#103>`_
+     * `osproc.html#115 <osproc.html#115>`_
 
    `executeShellCommand`:idx:
-     `os.html#133 <os.html#133>`_
+     `os.html#142 <os.html#142>`_
 
    `ExeExt`:idx:
      `os.html#107 <os.html#107>`_
 
    `existsDir`:idx:
-     `os.html#139 <os.html#139>`_
+     `os.html#115 <os.html#115>`_
 
    `existsEnv`:idx:
      `os.html#144 <os.html#144>`_
 
-   `ExistsFile`:idx:
-     `os.html#117 <os.html#117>`_
+   `existsFile`:idx:
+     `os.html#114 <os.html#114>`_
 
    `exp`:idx:
      `math.html#119 <math.html#119>`_
 
    `expandFilename`:idx:
-     `os.html#116 <os.html#116>`_
+     `os.html#130 <os.html#130>`_
 
    `expectKind`:idx:
      `macros.html#147 <macros.html#147>`_
@@ -1398,16 +1413,16 @@ Index
      `tut2.html#112 <tut2.html#112>`_
 
    `extractDir`:idx:
-     `os.html#126 <os.html#126>`_
+     `os.html#128 <os.html#128>`_
 
    `extractFileExt`:idx:
-     `os.html#128 <os.html#128>`_
+     `os.html#132 <os.html#132>`_
 
    `extractFilename`:idx:
-     `os.html#127 <os.html#127>`_
+     `os.html#129 <os.html#129>`_
 
    `extractFileTrunk`:idx:
-     `os.html#129 <os.html#129>`_
+     `os.html#133 <os.html#133>`_
 
    `ExtSep`:idx:
      `os.html#109 <os.html#109>`_
@@ -1509,10 +1524,10 @@ Index
      `mysql.html#218 <mysql.html#218>`_
 
    `fileHandle`:idx:
-     `system.html#517 <system.html#517>`_
+     `system.html#518 <system.html#518>`_
 
    `fileNewer`:idx:
-     `os.html#141 <os.html#141>`_
+     `os.html#119 <os.html#119>`_
 
    `FILE_OFFSET_BITS`:idx:
      `libcurl.html#263 <libcurl.html#263>`_
@@ -1527,7 +1542,7 @@ Index
      `manual.html#188 <manual.html#188>`_
 
    `find`:idx:
-     * `system.html#461 <system.html#461>`_
+     * `system.html#463 <system.html#463>`_
      * `strutils.html#124 <strutils.html#124>`_
      * `strutils.html#125 <strutils.html#125>`_
      * `strutils.html#126 <strutils.html#126>`_
@@ -1557,7 +1572,7 @@ Index
      `macros.html#130 <macros.html#130>`_
 
    `FlushFile`:idx:
-     `system.html#495 <system.html#495>`_
+     `system.html#496 <system.html#496>`_
 
    `for`:idx:
      * `manual.html#203 <manual.html#203>`_
@@ -1586,35 +1601,35 @@ Index
      `manual.html#198 <manual.html#198>`_
 
    `GC_disable`:idx:
-     `system.html#464 <system.html#464>`_
+     `system.html#466 <system.html#466>`_
 
    `GC_disableMarkAndSweep`:idx:
-     `system.html#470 <system.html#470>`_
+     `system.html#472 <system.html#472>`_
 
    `GC_enable`:idx:
-     `system.html#465 <system.html#465>`_
+     `system.html#467 <system.html#467>`_
 
    `GC_enableMarkAndSweep`:idx:
-     `system.html#469 <system.html#469>`_
+     `system.html#471 <system.html#471>`_
 
    `GC_fullCollect`:idx:
-     `system.html#466 <system.html#466>`_
+     `system.html#468 <system.html#468>`_
 
    `GC_getStatistics`:idx:
-     `system.html#471 <system.html#471>`_
+     `system.html#473 <system.html#473>`_
 
    `GC_ref`:idx:
-     * `system.html#472 <system.html#472>`_
-     * `system.html#473 <system.html#473>`_
      * `system.html#474 <system.html#474>`_
+     * `system.html#475 <system.html#475>`_
+     * `system.html#476 <system.html#476>`_
 
    `GC_setStrategy`:idx:
-     `system.html#468 <system.html#468>`_
+     `system.html#470 <system.html#470>`_
 
    `GC_unref`:idx:
-     * `system.html#475 <system.html#475>`_
-     * `system.html#476 <system.html#476>`_
      * `system.html#477 <system.html#477>`_
+     * `system.html#478 <system.html#478>`_
+     * `system.html#479 <system.html#479>`_
 
    `generic character types`:idx:
      `regexprs.html#102 <regexprs.html#102>`_
@@ -1624,10 +1639,10 @@ Index
      * `tut2.html#108 <tut2.html#108>`_
 
    `getApplicationDir`:idx:
-     `os.html#110 <os.html#110>`_
+     `os.html#161 <os.html#161>`_
 
    `getApplicationFilename`:idx:
-     `os.html#111 <os.html#111>`_
+     `os.html#160 <os.html#160>`_
 
    `getClockStr`:idx:
      `times.html#112 <times.html#112>`_
@@ -1640,7 +1655,7 @@ Index
      * `parsexml.html#117 <parsexml.html#117>`_
 
    `getConfigDir`:idx:
-     `os.html#115 <os.html#115>`_
+     `os.html#159 <os.html#159>`_
 
    `getContentLength`:idx:
      `cgi.html#110 <cgi.html#110>`_
@@ -1648,11 +1663,14 @@ Index
    `getContentType`:idx:
      `cgi.html#111 <cgi.html#111>`_
 
+   `getCreationTime`:idx:
+     `os.html#118 <os.html#118>`_
+
    `getCurrentDir`:idx:
-     `os.html#112 <os.html#112>`_
+     `os.html#120 <os.html#120>`_
 
    `getCurrentExceptionMsg`:idx:
-     `system.html#433 <system.html#433>`_
+     `system.html#435 <system.html#435>`_
 
    `getCurrentLine`:idx:
      `lexbase.html#106 <lexbase.html#106>`_
@@ -1670,14 +1688,17 @@ Index
      * `parsecfg.html#109 <parsecfg.html#109>`_
      * `parsexml.html#119 <parsexml.html#119>`_
 
+   `getFilePermissions`:idx:
+     `os.html#154 <os.html#154>`_
+
    `getFilePos`:idx:
-     `system.html#515 <system.html#515>`_
+     `system.html#516 <system.html#516>`_
 
    `getFileSize`:idx:
-     `system.html#507 <system.html#507>`_
+     `system.html#508 <system.html#508>`_
 
    `getFreeMem`:idx:
-     `system.html#439 <system.html#439>`_
+     `system.html#441 <system.html#441>`_
 
    `getGatewayInterface`:idx:
      `cgi.html#113 <cgi.html#113>`_
@@ -1686,7 +1707,7 @@ Index
      `times.html#107 <times.html#107>`_
 
    `getHomeDir`:idx:
-     `os.html#114 <os.html#114>`_
+     `os.html#158 <os.html#158>`_
 
    `getHttpAccept`:idx:
      `cgi.html#114 <cgi.html#114>`_
@@ -1715,8 +1736,11 @@ Index
    `getHttpUserAgent`:idx:
      `cgi.html#122 <cgi.html#122>`_
 
+   `getLastAccessTime`:idx:
+     `os.html#117 <os.html#117>`_
+
    `getLastModificationTime`:idx:
-     `os.html#140 <os.html#140>`_
+     `os.html#116 <os.html#116>`_
 
    `getLine`:idx:
      * `parsecfg.html#108 <parsecfg.html#108>`_
@@ -1729,7 +1753,7 @@ Index
      `md5.html#106 <md5.html#106>`_
 
    `getOccupiedMem`:idx:
-     `system.html#438 <system.html#438>`_
+     `system.html#440 <system.html#440>`_
 
    `getopt`:idx:
      `parseopt.html#106 <parseopt.html#106>`_
@@ -1744,7 +1768,7 @@ Index
      `cgi.html#125 <cgi.html#125>`_
 
    `getRefcount`:idx:
-     `system.html#432 <system.html#432>`_
+     `system.html#434 <system.html#434>`_
 
    `getRemoteAddr`:idx:
      `cgi.html#126 <cgi.html#126>`_
@@ -1813,7 +1837,7 @@ Index
      `times.html#105 <times.html#105>`_
 
    `getTotalMem`:idx:
-     `system.html#440 <system.html#440>`_
+     `system.html#442 <system.html#442>`_
 
    `get_tty_password`:idx:
      `mysql.html#282 <mysql.html#282>`_
@@ -1877,7 +1901,7 @@ Index
      `nimrodc.html#105 <nimrodc.html#105>`_
 
    `high`:idx:
-     `system.html#121 <system.html#121>`_
+     `system.html#122 <system.html#122>`_
 
    `hint`:idx:
      * `manual.html#219 <manual.html#219>`_
@@ -1885,13 +1909,13 @@ Index
      * `macros.html#140 <macros.html#140>`_
 
    `hostCPU`:idx:
-     `system.html#401 <system.html#401>`_
+     `system.html#403 <system.html#403>`_
 
    `HOSTNAME_LENGTH`:idx:
      `mysql.html#111 <mysql.html#111>`_
 
    `hostOS`:idx:
-     `system.html#400 <system.html#400>`_
+     `system.html#402 <system.html#402>`_
 
    `hr`:idx:
      `xmlgen.html#140 <xmlgen.html#140>`_
@@ -1962,13 +1986,16 @@ Index
      `nimrodc.html#101 <nimrodc.html#101>`_
 
    `in`:idx:
-     `system.html#357 <system.html#357>`_
+     `system.html#359 <system.html#359>`_
 
    `inc`:idx:
-     `system.html#159 <system.html#159>`_
+     `system.html#161 <system.html#161>`_
 
    `incl`:idx:
-     `system.html#167 <system.html#167>`_
+     `system.html#169 <system.html#169>`_
+
+   `inclFilePermissions`:idx:
+     `os.html#156 <os.html#156>`_
 
    `include`:idx:
      `tut1.html#129 <tut1.html#129>`_
@@ -1977,7 +2004,7 @@ Index
      `manual.html#113 <manual.html#113>`_
 
    `inf`:idx:
-     `system.html#434 <system.html#434>`_
+     `system.html#436 <system.html#436>`_
 
    `information hiding`:idx:
      * `manual.html#213 <manual.html#213>`_
@@ -1992,6 +2019,9 @@ Index
    `input`:idx:
      `xmlgen.html#143 <xmlgen.html#143>`_
 
+   `inputStream`:idx:
+     `osproc.html#112 <osproc.html#112>`_
+
    `ins`:idx:
      `xmlgen.html#144 <xmlgen.html#144>`_
 
@@ -2023,7 +2053,7 @@ Index
      `macros.html#129 <macros.html#129>`_
 
    `is`:idx:
-     `system.html#359 <system.html#359>`_
+     `system.html#361 <system.html#361>`_
 
    `isAlpha`:idx:
      `unicode.html#111 <unicode.html#111>`_
@@ -2035,18 +2065,18 @@ Index
      `unicode.html#109 <unicode.html#109>`_
 
    `isMainModule`:idx:
-     `system.html#392 <system.html#392>`_
+     `system.html#394 <system.html#394>`_
 
    `isNil`:idx:
-     * `system.html#449 <system.html#449>`_
-     * `system.html#450 <system.html#450>`_
      * `system.html#451 <system.html#451>`_
      * `system.html#452 <system.html#452>`_
      * `system.html#453 <system.html#453>`_
      * `system.html#454 <system.html#454>`_
+     * `system.html#455 <system.html#455>`_
+     * `system.html#456 <system.html#456>`_
 
    `is_not`:idx:
-     `system.html#360 <system.html#360>`_
+     `system.html#362 <system.html#362>`_
 
    `IS_NOT_NULL`:idx:
      `mysql.html#303 <mysql.html#303>`_
@@ -2076,25 +2106,25 @@ Index
      `mysql.html#255 <mysql.html#255>`_
 
    `items`:idx:
-     * `system.html#443 <system.html#443>`_
-     * `system.html#444 <system.html#444>`_
      * `system.html#445 <system.html#445>`_
      * `system.html#446 <system.html#446>`_
      * `system.html#447 <system.html#447>`_
      * `system.html#448 <system.html#448>`_
+     * `system.html#449 <system.html#449>`_
+     * `system.html#450 <system.html#450>`_
 
    `iterator`:idx:
      `manual.html#204 <manual.html#204>`_
 
    `iterOverEnvironment`:idx:
-     `os.html#150 <os.html#150>`_
+     `os.html#146 <os.html#146>`_
 
    `JavaScript`:idx:
      `nimrodc.html#116 <nimrodc.html#116>`_
 
    `JoinPath`:idx:
-     * `os.html#118 <os.html#118>`_
-     * `os.html#120 <os.html#120>`_
+     * `os.html#122 <os.html#122>`_
+     * `os.html#123 <os.html#123>`_
 
    `kbd`:idx:
      `xmlgen.html#145 <xmlgen.html#145>`_
@@ -2116,11 +2146,11 @@ Index
      `xmlgen.html#147 <xmlgen.html#147>`_
 
    `len`:idx:
-     * `system.html#162 <system.html#162>`_
-     * `system.html#163 <system.html#163>`_
      * `system.html#164 <system.html#164>`_
      * `system.html#165 <system.html#165>`_
      * `system.html#166 <system.html#166>`_
+     * `system.html#167 <system.html#167>`_
+     * `system.html#168 <system.html#168>`_
      * `strtabs.html#109 <strtabs.html#109>`_
      * `macros.html#118 <macros.html#118>`_
 
@@ -2152,7 +2182,7 @@ Index
      `nimrodc.html#107 <nimrodc.html#107>`_
 
    `lines`:idx:
-     `system.html#516 <system.html#516>`_
+     `system.html#517 <system.html#517>`_
 
    `line_trace`:idx:
      `nimrodc.html#109 <nimrodc.html#109>`_
@@ -2191,7 +2221,7 @@ Index
      `math.html#118 <math.html#118>`_
 
    `low`:idx:
-     `system.html#122 <system.html#122>`_
+     `system.html#123 <system.html#123>`_
 
    `Macros`:idx:
      * `manual.html#210 <manual.html#210>`_
@@ -2238,13 +2268,13 @@ Index
      `nimrodc.html#118 <nimrodc.html#118>`_
 
    `max`:idx:
-     * `system.html#272 <system.html#272>`_
-     * `system.html#273 <system.html#273>`_
      * `system.html#274 <system.html#274>`_
      * `system.html#275 <system.html#275>`_
      * `system.html#276 <system.html#276>`_
      * `system.html#277 <system.html#277>`_
-     * `system.html#324 <system.html#324>`_
+     * `system.html#278 <system.html#278>`_
+     * `system.html#279 <system.html#279>`_
+     * `system.html#326 <system.html#326>`_
 
    `MAX_BIGINT_WIDTH`:idx:
      `mysql.html#194 <mysql.html#194>`_
@@ -2307,20 +2337,20 @@ Index
      `manual.html#197 <manual.html#197>`_
 
    `min`:idx:
-     * `system.html#266 <system.html#266>`_
-     * `system.html#267 <system.html#267>`_
      * `system.html#268 <system.html#268>`_
      * `system.html#269 <system.html#269>`_
      * `system.html#270 <system.html#270>`_
      * `system.html#271 <system.html#271>`_
-     * `system.html#323 <system.html#323>`_
+     * `system.html#272 <system.html#272>`_
+     * `system.html#273 <system.html#273>`_
+     * `system.html#325 <system.html#325>`_
 
    `mod`:idx:
-     * `system.html#216 <system.html#216>`_
-     * `system.html#217 <system.html#217>`_
      * `system.html#218 <system.html#218>`_
      * `system.html#219 <system.html#219>`_
      * `system.html#220 <system.html#220>`_
+     * `system.html#221 <system.html#221>`_
+     * `system.html#222 <system.html#222>`_
 
    `modify_defaults_file`:idx:
      `mysql.html#284 <mysql.html#284>`_
@@ -2330,10 +2360,10 @@ Index
      * `tut1.html#125 <tut1.html#125>`_
 
    `moveFile`:idx:
-     `os.html#135 <os.html#135>`_
+     `os.html#140 <os.html#140>`_
 
    `moveMem`:idx:
-     `system.html#413 <system.html#413>`_
+     `system.html#415 <system.html#415>`_
 
    `MULTIPLE_KEY_FLAG`:idx:
      `mysql.html#127 <mysql.html#127>`_
@@ -2853,13 +2883,13 @@ Index
      `mysql.html#110 <mysql.html#110>`_
 
    `nan`:idx:
-     `system.html#436 <system.html#436>`_
+     `system.html#438 <system.html#438>`_
 
    `Natural`:idx:
-     `system.html#129 <system.html#129>`_
+     `system.html#130 <system.html#130>`_
 
    `neginf`:idx:
-     `system.html#435 <system.html#435>`_
+     `system.html#437 <system.html#437>`_
 
    `nestList`:idx:
      `macros.html#152 <macros.html#152>`_
@@ -2904,8 +2934,8 @@ Index
      `mysql.html#187 <mysql.html#187>`_
 
    `new`:idx:
-     * `system.html#119 <system.html#119>`_
      * `system.html#120 <system.html#120>`_
+     * `system.html#121 <system.html#121>`_
 
    `newCall`:idx:
      * `macros.html#150 <macros.html#150>`_
@@ -2935,10 +2965,10 @@ Index
      `macros.html#135 <macros.html#135>`_
 
    `newSeq`:idx:
-     `system.html#161 <system.html#161>`_
+     `system.html#163 <system.html#163>`_
 
    `newString`:idx:
-     `system.html#410 <system.html#410>`_
+     `system.html#412 <system.html#412>`_
 
    `newStringStream`:idx:
      `streams.html#117 <streams.html#117>`_
@@ -2962,16 +2992,16 @@ Index
      `manual.html#169 <manual.html#169>`_
 
    `NimrodMajor`:idx:
-     `system.html#396 <system.html#396>`_
+     `system.html#398 <system.html#398>`_
 
    `NimrodMinor`:idx:
-     `system.html#397 <system.html#397>`_
+     `system.html#399 <system.html#399>`_
 
    `NimrodPatch`:idx:
-     `system.html#398 <system.html#398>`_
+     `system.html#400 <system.html#400>`_
 
    `NimrodVersion`:idx:
-     `system.html#395 <system.html#395>`_
+     `system.html#397 <system.html#397>`_
 
    `nl`:idx:
      `strutils.html#108 <strutils.html#108>`_
@@ -2992,15 +3022,15 @@ Index
      `xmlgen.html#152 <xmlgen.html#152>`_
 
    `not`:idx:
-     * `system.html#115 <system.html#115>`_
-     * `system.html#191 <system.html#191>`_
-     * `system.html#192 <system.html#192>`_
+     * `system.html#116 <system.html#116>`_
      * `system.html#193 <system.html#193>`_
      * `system.html#194 <system.html#194>`_
      * `system.html#195 <system.html#195>`_
+     * `system.html#196 <system.html#196>`_
+     * `system.html#197 <system.html#197>`_
 
    `not_in`:idx:
-     `system.html#358 <system.html#358>`_
+     `system.html#360 <system.html#360>`_
 
    `NOT_NULL_FLAG`:idx:
      `mysql.html#124 <mysql.html#124>`_
@@ -3036,11 +3066,11 @@ Index
 
    `openarray`:idx:
      * `tut1.html#119 <tut1.html#119>`_
-     * `system.html#125 <system.html#125>`_
+     * `system.html#126 <system.html#126>`_
 
    `OpenFile`:idx:
-     * `system.html#490 <system.html#490>`_
      * `system.html#491 <system.html#491>`_
+     * `system.html#492 <system.html#492>`_
 
    `operator`:idx:
      `manual.html#138 <manual.html#138>`_
@@ -3055,24 +3085,30 @@ Index
      `xmlgen.html#156 <xmlgen.html#156>`_
 
    `or`:idx:
-     * `system.html#117 <system.html#117>`_
-     * `system.html#236 <system.html#236>`_
-     * `system.html#237 <system.html#237>`_
+     * `system.html#118 <system.html#118>`_
      * `system.html#238 <system.html#238>`_
      * `system.html#239 <system.html#239>`_
      * `system.html#240 <system.html#240>`_
+     * `system.html#241 <system.html#241>`_
+     * `system.html#242 <system.html#242>`_
 
    `ord`:idx:
-     `system.html#170 <system.html#170>`_
+     `system.html#172 <system.html#172>`_
 
    `ordinal`:idx:
      `tut1.html#114 <tut1.html#114>`_
 
+   `Ordinal`:idx:
+     `system.html#114 <system.html#114>`_
+
    `Ordinal types`:idx:
      `manual.html#141 <manual.html#141>`_
 
    `OSError`:idx:
-     `os.html#147 <os.html#147>`_
+     `os.html#112 <os.html#112>`_
+
+   `outputStream`:idx:
+     `osproc.html#113 <osproc.html#113>`_
 
    `p`:idx:
      `xmlgen.html#157 <xmlgen.html#157>`_
@@ -3087,22 +3123,22 @@ Index
      `xmlgen.html#158 <xmlgen.html#158>`_
 
    `paramCount`:idx:
-     `os.html#145 <os.html#145>`_
+     `os.html#110 <os.html#110>`_
 
    `paramStr`:idx:
-     `os.html#146 <os.html#146>`_
+     `os.html#111 <os.html#111>`_
 
    `ParDir`:idx:
      `os.html#102 <os.html#102>`_
 
    `parentDir`:idx:
-     `os.html#122 <os.html#122>`_
+     `os.html#126 <os.html#126>`_
 
    `ParseBiggestInt`:idx:
      `strutils.html#145 <strutils.html#145>`_
 
    `parseCmdLine`:idx:
-     `os.html#154 <os.html#154>`_
+     `os.html#152 <os.html#152>`_
 
    `ParseFloat`:idx:
      `strutils.html#146 <strutils.html#146>`_
@@ -3240,10 +3276,10 @@ Index
      `streams.html#118 <streams.html#118>`_
 
    `PFloat32`:idx:
-     `system.html#388 <system.html#388>`_
+     `system.html#390 <system.html#390>`_
 
    `PFloat64`:idx:
-     `system.html#389 <system.html#389>`_
+     `system.html#391 <system.html#391>`_
 
    `Pgptr`:idx:
      `mysql.html#104 <mysql.html#104>`_
@@ -3255,10 +3291,10 @@ Index
      `parsexml.html#115 <parsexml.html#115>`_
 
    `PInt32`:idx:
-     `system.html#391 <system.html#391>`_
+     `system.html#393 <system.html#393>`_
 
    `PInt64`:idx:
-     `system.html#390 <system.html#390>`_
+     `system.html#392 <system.html#392>`_
 
    `PIRest`:idx:
      `parsexml.html#116 <parsexml.html#116>`_
@@ -3333,7 +3369,7 @@ Index
      `macros.html#108 <macros.html#108>`_
 
    `PObject`:idx:
-     `system.html#132 <system.html#132>`_
+     `system.html#133 <system.html#133>`_
 
    `pointer`:idx:
      `system.html#113 <system.html#113>`_
@@ -3343,10 +3379,10 @@ Index
      * `tut1.html#120 <tut1.html#120>`_
 
    `pop`:idx:
-     `system.html#462 <system.html#462>`_
+     `system.html#464 <system.html#464>`_
 
    `Positive`:idx:
-     `system.html#130 <system.html#130>`_
+     `system.html#131 <system.html#131>`_
 
    `pow`:idx:
      `math.html#132 <math.html#132>`_
@@ -3360,6 +3396,9 @@ Index
    `PPPChar`:idx:
      `sqlite3.html#174 <sqlite3.html#174>`_
 
+   `PProcess`:idx:
+     `osproc.html#101 <osproc.html#101>`_
+
    `PPSqlite3`:idx:
      `sqlite3.html#176 <sqlite3.html#176>`_
 
@@ -3376,7 +3415,7 @@ Index
      `xmlgen.html#159 <xmlgen.html#159>`_
 
    `pred`:idx:
-     `system.html#158 <system.html#158>`_
+     `system.html#160 <system.html#160>`_
 
    `PRI_KEY_FLAG`:idx:
      `mysql.html#125 <mysql.html#125>`_
@@ -3391,6 +3430,9 @@ Index
    `processedRows`:idx:
      `parsecsv.html#107 <parsecsv.html#107>`_
 
+   `processID`:idx:
+     `osproc.html#110 <osproc.html#110>`_
+
    `Psockaddr`:idx:
      `mysql.html#250 <mysql.html#250>`_
 
@@ -3482,7 +3524,7 @@ Index
      `manual.html#228 <manual.html#228>`_
 
    `putEnv`:idx:
-     `os.html#142 <os.html#142>`_
+     `os.html#145 <os.html#145>`_
 
    `PVIO`:idx:
      `mysql.html#103 <mysql.html#103>`_
@@ -3494,14 +3536,14 @@ Index
      `xmlgen.html#160 <xmlgen.html#160>`_
 
    `quit`:idx:
-     * `system.html#482 <system.html#482>`_
      * `system.html#483 <system.html#483>`_
+     * `system.html#484 <system.html#484>`_
 
    `QuitFailure`:idx:
-     `system.html#481 <system.html#481>`_
+     `system.html#482 <system.html#482>`_
 
    `QuitSuccess`:idx:
-     `system.html#480 <system.html#480>`_
+     `system.html#481 <system.html#481>`_
 
    `quotation mark`:idx:
      `manual.html#128 <manual.html#128>`_
@@ -3522,7 +3564,7 @@ Index
      `mysql.html#254 <mysql.html#254>`_
 
    `range`:idx:
-     `system.html#123 <system.html#123>`_
+     `system.html#124 <system.html#124>`_
 
    `re-raised`:idx:
      `manual.html#183 <manual.html#183>`_
@@ -3531,23 +3573,23 @@ Index
      `streams.html#106 <streams.html#106>`_
 
    `readBuffer`:idx:
-     `system.html#510 <system.html#510>`_
+     `system.html#511 <system.html#511>`_
 
    `ReadBytes`:idx:
-     `system.html#508 <system.html#508>`_
+     `system.html#509 <system.html#509>`_
 
    `readChar`:idx:
-     * `system.html#494 <system.html#494>`_
+     * `system.html#495 <system.html#495>`_
      * `streams.html#105 <streams.html#105>`_
 
    `ReadChars`:idx:
-     `system.html#509 <system.html#509>`_
+     `system.html#510 <system.html#510>`_
 
    `readData`:idx:
      `cgi.html#108 <cgi.html#108>`_
 
    `readFile`:idx:
-     `system.html#496 <system.html#496>`_
+     `system.html#497 <system.html#497>`_
 
    `readFloat32`:idx:
      `streams.html#111 <streams.html#111>`_
@@ -3568,7 +3610,7 @@ Index
      `streams.html#107 <streams.html#107>`_
 
    `readLine`:idx:
-     * `system.html#504 <system.html#504>`_
+     * `system.html#505 <system.html#505>`_
      * `streams.html#114 <streams.html#114>`_
 
    `readRow`:idx:
@@ -3578,7 +3620,7 @@ Index
      `streams.html#113 <streams.html#113>`_
 
    `realloc`:idx:
-     `system.html#417 <system.html#417>`_
+     `system.html#419 <system.html#419>`_
 
    `reBinary`:idx:
      `regexprs.html#116 <regexprs.html#116>`_
@@ -3647,10 +3689,10 @@ Index
      `regexprs.html#114 <regexprs.html#114>`_
 
    `removeDir`:idx:
-     `os.html#137 <os.html#137>`_
+     `os.html#150 <os.html#150>`_
 
    `removeFile`:idx:
-     `os.html#136 <os.html#136>`_
+     `os.html#141 <os.html#141>`_
 
    `reNatural`:idx:
      `regexprs.html#113 <regexprs.html#113>`_
@@ -3666,7 +3708,7 @@ Index
      * `strutils.html#128 <strutils.html#128>`_
 
    `repr`:idx:
-     `system.html#373 <system.html#373>`_
+     `system.html#375 <system.html#375>`_
 
    `ResetAttributes`:idx:
      `terminal.html#110 <terminal.html#110>`_
@@ -3675,6 +3717,9 @@ Index
      * `manual.html#190 <manual.html#190>`_
      * `manual.html#201 <manual.html#201>`_
 
+   `resume`:idx:
+     `osproc.html#107 <osproc.html#107>`_
+
    `return`:idx:
      `manual.html#189 <manual.html#189>`_
 
@@ -3693,6 +3738,9 @@ Index
    `runes`:idx:
      `unicode.html#114 <unicode.html#114>`_
 
+   `running`:idx:
+     `osproc.html#109 <osproc.html#109>`_
+
    `safe`:idx:
      `manual.html#112 <manual.html#112>`_
 
@@ -3700,10 +3748,10 @@ Index
      `manual.html#166 <manual.html#166>`_
 
    `sameFile`:idx:
-     `os.html#148 <os.html#148>`_
+     `os.html#137 <os.html#137>`_
 
    `sameFileContent`:idx:
-     `os.html#149 <os.html#149>`_
+     `os.html#138 <os.html#138>`_
 
    `samp`:idx:
      `xmlgen.html#161 <xmlgen.html#161>`_
@@ -3744,10 +3792,10 @@ Index
      * `tut1.html#127 <tut1.html#127>`_
 
    `seq`:idx:
-     `system.html#126 <system.html#126>`_
+     `system.html#127 <system.html#127>`_
 
    `seqToPtr`:idx:
-     `system.html#459 <system.html#459>`_
+     `system.html#461 <system.html#461>`_
 
    `Sequences`:idx:
      * `manual.html#153 <manual.html#153>`_
@@ -3787,7 +3835,7 @@ Index
      `mysql.html#113 <mysql.html#113>`_
 
    `set`:idx:
-     `system.html#127 <system.html#127>`_
+     `system.html#128 <system.html#128>`_
 
    `set type`:idx:
      * `manual.html#157 <manual.html#157>`_
@@ -3797,7 +3845,7 @@ Index
      `terminal.html#116 <terminal.html#116>`_
 
    `setCurrentDir`:idx:
-     `os.html#113 <os.html#113>`_
+     `os.html#121 <os.html#121>`_
 
    `setCursorPos`:idx:
      `terminal.html#101 <terminal.html#101>`_
@@ -3808,8 +3856,11 @@ Index
    `setCursorYPos`:idx:
      `terminal.html#103 <terminal.html#103>`_
 
+   `setFilePermissions`:idx:
+     `os.html#155 <os.html#155>`_
+
    `setFilePos`:idx:
-     `system.html#514 <system.html#514>`_
+     `system.html#515 <system.html#515>`_
 
    `SET_FLAG`:idx:
      `mysql.html#135 <mysql.html#135>`_
@@ -3818,25 +3869,25 @@ Index
      `terminal.html#115 <terminal.html#115>`_
 
    `setLen`:idx:
-     * `system.html#409 <system.html#409>`_
-     * `system.html#419 <system.html#419>`_
+     * `system.html#411 <system.html#411>`_
+     * `system.html#421 <system.html#421>`_
 
    `setTestData`:idx:
      `cgi.html#142 <cgi.html#142>`_
 
    `shl`:idx:
-     * `system.html#226 <system.html#226>`_
-     * `system.html#227 <system.html#227>`_
      * `system.html#228 <system.html#228>`_
      * `system.html#229 <system.html#229>`_
      * `system.html#230 <system.html#230>`_
+     * `system.html#231 <system.html#231>`_
+     * `system.html#232 <system.html#232>`_
 
    `shr`:idx:
-     * `system.html#221 <system.html#221>`_
-     * `system.html#222 <system.html#222>`_
      * `system.html#223 <system.html#223>`_
      * `system.html#224 <system.html#224>`_
      * `system.html#225 <system.html#225>`_
+     * `system.html#226 <system.html#226>`_
+     * `system.html#227 <system.html#227>`_
 
    `simple assertions`:idx:
      `regexprs.html#103 <regexprs.html#103>`_
@@ -3848,7 +3899,7 @@ Index
      `math.html#129 <math.html#129>`_
 
    `sizeof`:idx:
-     `system.html#156 <system.html#156>`_
+     `system.html#158 <system.html#158>`_
 
    `small`:idx:
      `xmlgen.html#164 <xmlgen.html#164>`_
@@ -3864,7 +3915,7 @@ Index
      * `strutils.html#132 <strutils.html#132>`_
 
    `SplitFilename`:idx:
-     `os.html#125 <os.html#125>`_
+     `os.html#131 <os.html#131>`_
 
    `splitLines`:idx:
      `strutils.html#133 <strutils.html#133>`_
@@ -3873,7 +3924,7 @@ Index
      `strutils.html#134 <strutils.html#134>`_
 
    `SplitPath`:idx:
-     `os.html#121 <os.html#121>`_
+     `os.html#125 <os.html#125>`_
 
    `splitSeq`:idx:
      * `strutils.html#135 <strutils.html#135>`_
@@ -4387,6 +4438,10 @@ Index
    `standardDeviation`:idx:
      `math.html#136 <math.html#136>`_
 
+   `startProcess`:idx:
+     * `osproc.html#105 <osproc.html#105>`_
+     * `osproc.html#116 <osproc.html#116>`_
+
    `startsWith`:idx:
      `strutils.html#149 <strutils.html#149>`_
 
@@ -4406,13 +4461,13 @@ Index
      `manual.html#164 <manual.html#164>`_
 
    `stderr`:idx:
-     `system.html#489 <system.html#489>`_
+     `system.html#490 <system.html#490>`_
 
    `stdin`:idx:
-     `system.html#487 <system.html#487>`_
+     `system.html#488 <system.html#488>`_
 
    `stdout`:idx:
-     `system.html#488 <system.html#488>`_
+     `system.html#489 <system.html#489>`_
 
    `st_dynamic_array`:idx:
      `mysql.html#339 <mysql.html#339>`_
@@ -4513,7 +4568,7 @@ Index
      `strutils.html#109 <strutils.html#109>`_
 
    `succ`:idx:
-     `system.html#157 <system.html#157>`_
+     `system.html#159 <system.html#159>`_
 
    `sum`:idx:
      `math.html#110 <math.html#110>`_
@@ -4521,8 +4576,11 @@ Index
    `sup`:idx:
      `xmlgen.html#169 <xmlgen.html#169>`_
 
+   `suspend`:idx:
+     `osproc.html#106 <osproc.html#106>`_
+
    `swap`:idx:
-     `system.html#421 <system.html#421>`_
+     `system.html#423 <system.html#423>`_
 
    `symbol`:idx:
      `macros.html#125 <macros.html#125>`_
@@ -4543,7 +4601,7 @@ Index
      `manual.html#125 <manual.html#125>`_
 
    `TAddress`:idx:
-     `system.html#374 <system.html#374>`_
+     `system.html#376 <system.html#376>`_
 
    `tan`:idx:
      `math.html#130 <math.html#130>`_
@@ -4756,19 +4814,25 @@ Index
      `manual.html#209 <manual.html#209>`_
 
    `TEndian`:idx:
-     `system.html#387 <system.html#387>`_
+     `system.html#389 <system.html#389>`_
+
+   `terminate`:idx:
+     `osproc.html#108 <osproc.html#108>`_
 
    `textarea`:idx:
      `xmlgen.html#173 <xmlgen.html#173>`_
 
    `TFile`:idx:
-     `system.html#484 <system.html#484>`_
+     `system.html#485 <system.html#485>`_
 
    `TFileHandle`:idx:
-     `system.html#486 <system.html#486>`_
+     `system.html#487 <system.html#487>`_
 
    `TFileMode`:idx:
-     `system.html#485 <system.html#485>`_
+     `system.html#486 <system.html#486>`_
+
+   `TFilePermission`:idx:
+     `os.html#153 <os.html#153>`_
 
    `TFileStream`:idx:
      `streams.html#119 <streams.html#119>`_
@@ -4786,7 +4850,7 @@ Index
      `strtabs.html#111 <strtabs.html#111>`_
 
    `TGC_Strategy`:idx:
-     `system.html#467 <system.html#467>`_
+     `system.html#469 <system.html#469>`_
 
    `th`:idx:
      `xmlgen.html#175 <xmlgen.html#175>`_
@@ -4831,25 +4895,25 @@ Index
      `macros.html#105 <macros.html#105>`_
 
    `toBiggestFloat`:idx:
-     `system.html#403 <system.html#403>`_
+     `system.html#405 <system.html#405>`_
 
    `toBiggestInt`:idx:
-     `system.html#405 <system.html#405>`_
+     `system.html#407 <system.html#407>`_
 
    `toBin`:idx:
      `strutils.html#155 <strutils.html#155>`_
 
    `TObject`:idx:
-     `system.html#131 <system.html#131>`_
+     `system.html#132 <system.html#132>`_
 
    `toFloat`:idx:
-     `system.html#402 <system.html#402>`_
+     `system.html#404 <system.html#404>`_
 
    `toHex`:idx:
      `strutils.html#142 <strutils.html#142>`_
 
    `toInt`:idx:
-     `system.html#404 <system.html#404>`_
+     `system.html#406 <system.html#406>`_
 
    `toLower`:idx:
      * `strutils.html#115 <strutils.html#115>`_
@@ -4875,13 +4939,13 @@ Index
      `unicode.html#108 <unicode.html#108>`_
 
    `toU16`:idx:
-     `system.html#179 <system.html#179>`_
+     `system.html#181 <system.html#181>`_
 
    `toU32`:idx:
-     `system.html#180 <system.html#180>`_
+     `system.html#182 <system.html#182>`_
 
    `toU8`:idx:
-     `system.html#178 <system.html#178>`_
+     `system.html#180 <system.html#180>`_
 
    `toUpper`:idx:
      * `strutils.html#117 <strutils.html#117>`_
@@ -4892,7 +4956,10 @@ Index
      `unicode.html#105 <unicode.html#105>`_
 
    `TPathComponent`:idx:
-     `os.html#152 <os.html#152>`_
+     `os.html#148 <os.html#148>`_
+
+   `TProcessOption`:idx:
+     `osproc.html#102 <osproc.html#102>`_
 
    `tr`:idx:
      `xmlgen.html#178 <xmlgen.html#178>`_
@@ -4905,7 +4972,7 @@ Index
      `cgi.html#105 <cgi.html#105>`_
 
    `TResult`:idx:
-     `system.html#155 <system.html#155>`_
+     `system.html#157 <system.html#157>`_
 
    `TRune`:idx:
      `unicode.html#101 <unicode.html#101>`_
@@ -5022,8 +5089,11 @@ Index
    `UNIQUE_KEY_FLAG`:idx:
      `mysql.html#126 <mysql.html#126>`_
 
+   `unixTimeToWinTime`:idx:
+     `times.html#117 <times.html#117>`_
+
    `UnixToNativePath`:idx:
-     `os.html#124 <os.html#124>`_
+     `os.html#113 <os.html#113>`_
 
    `unsigned integer`:idx:
      * `manual.html#142 <manual.html#142>`_
@@ -5067,12 +5137,12 @@ Index
    `validIdentifier`:idx:
      `strutils.html#158 <strutils.html#158>`_
 
-   `var`:idx:
-     `xmlgen.html#181 <xmlgen.html#181>`_
-
    `Var`:idx:
      `manual.html#178 <manual.html#178>`_
 
+   `var`:idx:
+     `xmlgen.html#181 <xmlgen.html#181>`_
+
    `varargs`:idx:
      `nimrodc.html#106 <nimrodc.html#106>`_
 
@@ -5090,11 +5160,14 @@ Index
    `volatile`:idx:
      `nimrodc.html#111 <nimrodc.html#111>`_
 
+   `waitForExit`:idx:
+     `osproc.html#111 <osproc.html#111>`_
+
    `walkDir`:idx:
-     `os.html#153 <os.html#153>`_
+     `os.html#149 <os.html#149>`_
 
    `walkFiles`:idx:
-     * `os.html#151 <os.html#151>`_
+     * `os.html#147 <os.html#147>`_
      * `zipfiles.html#110 <zipfiles.html#110>`_
 
    `warning`:idx:
@@ -5112,32 +5185,35 @@ Index
    `Whitespace`:idx:
      `strutils.html#102 <strutils.html#102>`_
 
+   `winTimeToUnixTime`:idx:
+     `times.html#118 <times.html#118>`_
+
    `write`:idx:
-     * `system.html#497 <system.html#497>`_
      * `system.html#498 <system.html#498>`_
      * `system.html#499 <system.html#499>`_
      * `system.html#500 <system.html#500>`_
      * `system.html#501 <system.html#501>`_
      * `system.html#502 <system.html#502>`_
      * `system.html#503 <system.html#503>`_
+     * `system.html#504 <system.html#504>`_
      * `streams.html#103 <streams.html#103>`_
      * `streams.html#104 <streams.html#104>`_
 
    `writeBuffer`:idx:
-     `system.html#513 <system.html#513>`_
+     `system.html#514 <system.html#514>`_
 
    `writeBytes`:idx:
-     `system.html#511 <system.html#511>`_
+     `system.html#512 <system.html#512>`_
 
    `writeChars`:idx:
-     `system.html#512 <system.html#512>`_
+     `system.html#513 <system.html#513>`_
 
    `writeContentType`:idx:
      `cgi.html#143 <cgi.html#143>`_
 
    `writeln`:idx:
-     * `system.html#505 <system.html#505>`_
      * `system.html#506 <system.html#506>`_
+     * `system.html#507 <system.html#507>`_
 
    `WriteStyled`:idx:
      `terminal.html#112 <terminal.html#112>`_
@@ -5153,28 +5229,28 @@ Index
      `cgi.html#103 <cgi.html#103>`_
 
    `xor`:idx:
-     * `system.html#118 <system.html#118>`_
-     * `system.html#241 <system.html#241>`_
-     * `system.html#242 <system.html#242>`_
+     * `system.html#119 <system.html#119>`_
      * `system.html#243 <system.html#243>`_
      * `system.html#244 <system.html#244>`_
      * `system.html#245 <system.html#245>`_
+     * `system.html#246 <system.html#246>`_
+     * `system.html#247 <system.html#247>`_
 
    `yield`:idx:
      `manual.html#191 <manual.html#191>`_
 
    `ze`:idx:
-     * `system.html#172 <system.html#172>`_
-     * `system.html#173 <system.html#173>`_
-
-   `ze64`:idx:
      * `system.html#174 <system.html#174>`_
      * `system.html#175 <system.html#175>`_
+
+   `ze64`:idx:
      * `system.html#176 <system.html#176>`_
      * `system.html#177 <system.html#177>`_
+     * `system.html#178 <system.html#178>`_
+     * `system.html#179 <system.html#179>`_
 
    `ZEROFILL_FLAG`:idx:
      `mysql.html#130 <mysql.html#130>`_
 
    `zeroMem`:idx:
-     `system.html#411 <system.html#411>`_
\ No newline at end of file
+     `system.html#413 <system.html#413>`_
\ No newline at end of file
diff --git a/doc/tut2.txt b/doc/tut2.txt
index 114039887..bb0949659 100644
--- a/doc/tut2.txt
+++ b/doc/tut2.txt
@@ -396,7 +396,7 @@ is not executed (if an exception occurs).
 Generics
 ========
 
-`Version 0.7.8: Complex generic types like in the example do not work.`:red:
+`Version 0.7.10: Complex generic types like in the example do not work.`:red:
 
 `Generics`:idx: are Nimrod's means to parametrize procs, iterators or types 
 with `type parameters`:idx:. They are most useful for efficient type safe
diff --git a/install.txt b/install.txt
index a5aef4cbe..520b39935 100644
--- a/install.txt
+++ b/install.txt
@@ -30,6 +30,10 @@ manually. An alternative is to create a symbolic link in ``/usr/bin``::
 
   [sudo] ln -s $your_install_dir/bin/nimrod  /usr/bin/nimrod
 
+From version 0.7.10 onwards ``install.sh`` and ``deinstall.sh`` scripts are
+provided for distributing the files over the UNIX hierarchy. However, this
+makes updating your Nimrod installation more cumbersome. 
+
 
 Installation on the Macintosh
 -----------------------------
diff --git a/koch.py b/koch.py
index 6fcb1336d..364a71d8a 100644
--- a/koch.py
+++ b/koch.py
@@ -12,7 +12,7 @@ from pycompab import *
 
 # --------------------- constants  ----------------------------------------
 
-NIMROD_VERSION = '0.7.8'
+NIMROD_VERSION = '0.7.10'
 # This string contains Nimrod's version. It is the only place
 # where the version needs to be updated. The rest is done by
 # the build process automatically. It is replaced **everywhere**!
@@ -244,9 +244,9 @@ def MakeExecutable(file):
   os.chmod(file, 493)
 
 class Changed:
-  """ Returns a Changed object. This object evals to true if one of the
-      given files has changed, false otherwise in a boolean context. You have
-      to call the object's success() method if the building has been a success.
+  """ Returns a Changed object. check() returns true iff one of the
+      given files has changed. You have to call the object's success() 
+      method if the build has been a success.
 
       Example:
 
@@ -342,7 +342,7 @@ def cmd_nim():
   CogRule("wordrecg", "nim/wordrecg.pas", "data/keywords.txt")
   CogRule("commands", "nim/commands.pas",
           "data/basicopt.txt data/advopt.txt")
-  CogRule("macros", "lib/macros.nim", "koch.py data/ast.yml")
+  CogRule("macros", "lib/pure/macros.nim", "koch.py data/ast.yml")
   c = Changed("nim", Glob("nim/*.pas"), EXPLAIN)
   if c.check() or force:
     Exec(FPC_CMD)
@@ -353,8 +353,7 @@ def cmd_nim():
 
 def cmd_rod(options):
   prereqs = Glob("lib/*.nim") + Glob("rod/*.nim") + [
-    "lib/nimbase.h", "lib/dlmalloc.c", "lib/dlmalloc.h",
-    "config/nimrod.cfg"]
+    "lib/nimbase.h", "config/nimrod.cfg"]
   c = Changed("rod", prereqs, EXPLAIN)
   if c.check() or cmd_nim() or force:
     buildRod(options)
@@ -386,7 +385,7 @@ Possible Commands:
   rodsrc                   generates Nimrod version from Pascal version
   web                      generates the website
   profile                  profile the Nimrod compiler
-  csource                  build the C sources for installation
+  csource [options]        build the C sources for installation
   zip                      build the installation ZIP package
   inno                     build the Inno Setup installer
 """, NIMROD_VERSION + ' ' * (44-len(NIMROD_VERSION)), sys.version)
@@ -423,13 +422,14 @@ def main(args):
     elif cmd == "profile": cmd_profile()
     elif cmd == "zip": cmd_zip()
     elif cmd == "inno": cmd_inno()
-    elif cmd == "csource": cmd_csource()
+    elif cmd == "csource": cmd_csource(join(args[i+1:]))
     elif cmd == "install": cmd_install() # for backwards compability
     else: Error("illegal command: " + cmd)
     
-def cmd_csource():
-  Exec(Subs("nimrod cc -r tools/niminst --var:version=$1 csource rod/nimrod",
-       NIMROD_VERSION))
+def cmd_csource(args):
+  Exec(Subs(
+    "nimrod cc $2 -r tools/niminst --var:version=$1 csource rod/nimrod $2",
+    NIMROD_VERSION, args))
 
 def cmd_zip():
   Exec(Subs("nimrod cc -r tools/niminst --var:version=$1 zip rod/nimrod",
diff --git a/lib/amd64.asm.in b/lib/amd64.asm.in
deleted file mode 100644
index 0fa66fa7d..000000000
--- a/lib/amd64.asm.in
+++ /dev/null
@@ -1,38 +0,0 @@
-; This contains the CPU-dependant variants of some routines.

-; (C) 2005 Andreas Rumpf

-; This code was inspired by the Freepascal compiler's sources

-; All routines here have the _cdecl calling convention because

-; that is the only convention any C compiler supports.

-

-\python{

-import os

-

-def c(name): 

-  if os.name == 'posix':

-    return name

-  else:

-    return "_" + name

-    

-def arg:

-  if os.name == 'posix':

-    return 'rdi'

-  else:

-    return 'rcx' # on win64 uses its own calling convention; this sucks!

-}

-

-segment code

-

-global \c{cpu_inc_locked}

-global \c{cpu_dec_locked}

-

-\c{cpu_dec_locked}: 

-     lock

-     dec       [\arg]

-     setz      al

-     ret

-     

-\c{cpu_inc_locked}:

-     lock

-     inc       [\arg]

-     setz      al

-     ret

diff --git a/lib/atomic.h b/lib/atomic.h
deleted file mode 100644
index afab4843f..000000000
--- a/lib/atomic.h
+++ /dev/null
@@ -1,2716 +0,0 @@
-/* Atomic operations for Nimrod */
-
-#if defined(_MSCVER)
-__declspec(naked) int __fastcall Xadd (volatile int* pNum, int val)
-{
-    __asm
-    {
-        lock xadd dword ptr [ECX], EDX
-        mov EAX, EDX
-        ret
-    }
-}
-
-
-
-#endif
-
-
-#define ATOMIC_ASM(type,op)     \
-    __asm __volatile ("lock; " op : "=m" (*(type *)p) : "ir" (v), "0" (*(type *)p))
-
-#define ATOMIC_ASM_NOLOCK(type,op)     \
-    __asm __volatile (op : "=m" (*(type *)p) : "ir" (v), "0" (*(type *)p))
-
-static __inline void
-atomic_add_int(void *p, u_int v)
-{
-        ATOMIC_ASM(int, "addl %1,%0");
-}
-
-static __inline void
-atomic_add_int_nolock(void *p, u_int v)
-{
-        ATOMIC_ASM_NOLOCK(int, "addl %1,%0");
-}
-
-
-
-/*
-Atomic.h
-
-Joshua Scholar
-May 26, 2003
-
-This header contains:
-
-a multiprocessor nonblocking FIFO,  
-
-a multiprocessor nonblocking LIFO
-
-multiprocessor nonblocking reference counting (including volatile pointers 
-that can be safely shared between processors)
-
-nonblocking memory allocation routines
-
-template types that encapsulate variables meant to be shared between 
-processors - all changes to these variables are atomic and globally visible
-
-All kinds of atomic operations that are useful in a multiprocessor context.
-
-The philosophy behind this code is that I created templates that encapsulate
-atomic access so that while the templates themselves may not be the easiest
-code to read, code that uses these templates can be simple, abstract and
-reliable.
-
-I also created regular C style functions, overloaded by type for some of
-the more basic operations.  If you have regular variables or memory 
-locations that you want to use in a globally visible way you have two 
-choices.
-
-If the operation you want is one of the basic building blocks you can
-call one of the overloaded functions like InterlockedSetIfEqual().
-
-Otherwise it's perfectly safe to cast a pointer to your data to be a pointer
-to one of the atomic types so that you can use their methods.  For instance:
-if (((AtomicInt *)foo)->CompareSomeBitsAndExchangeSomeOtherBits(exchange, 
-        bitsToExchange,
-        comperand, 
-        bitsToCompare))
-    ...
-or even
-
-//atomically allocate n bytes out of the pool
- data = ((*(AtomicPtr<char> *)curPool)+= n) - n;
-
-
-
-State of code:
-
-Unlike other libraries of similar routines that I wrote in the past, this
-has not been thoroughly tested. In fact I don't remember how much of it has
-been tested at this point.
-
-It would take an 8 way machine for me to really pound on the routines.
-
-
-
-Overview
-
-Some basic types are:
-typedef Atomic<int> AtomicInt;
-typedef Atomic<unsigned int> AtomicUInt;
-typedef Atomic<__int64> AtomicInt64;
-typedef Atomic<unsigned __int64> AtomicUInt64;
-
-Fancier types include
-template <typename T> struct AtomicPtr;
-This is a pointer that has the same semantics as the above integer types
-
-template <typename T>struct AtomicPtrWithCount;
-
-AtomicPtrWithCount<T> is a very important type.  It has 32 bits of pointer
-and 32 bits of counter.  There are a number of algorithms that are possible
-when a pointer and a counter can be changed atomically together including a
-lock free pushdown stack and reference counted garbage collection where
-multiple processors can share pointers as well as sharing the data that's
-pointed at.
-
-template <typename T> struct AtomicPtrWithMark;
-
-This is similar to AtomicPtrWithCount<T> but the extra 32 bits are accessed
-as individual bits instead of being accessed as a counter.  It's not as
-important.  I was playing with algorithms before I realized that the
-important ones I was afraid of using had been published independently of my
-former employer.
-
-
-
-The atomic number types act as integer variables, but all changes to these
-variable happen through interlocked atomic instructions.
-All changes are therefor "globally visible" in Intel's parlance.
-
-Note that incrementing (or decrementing or adding to) one of these uses
-InterlockedExchangeAdd, which for 64 bit numbers ends up relying on "lock
-CMPXCHG8B"
-
-There's an Exchange method.
-
-There are also special methods that use compare exchange in some forms that
-I've found useful:
-
-T CompareExchange(T exchange, T comperand)
-bool SetIfEqual(T exchange, T comperand)
-
-and fancier ones I found some uses for
-
- inline bool SetIfSomeBitsAreEqual(T exchange, T comperand, T bitsToCompare)
- inline bool SetSomeBitsIfThoseBitsAreEqual(T exchange, 
-                                             T comperand, 
-                                             T bitsToCompare)
- inline bool SetSomeBitsIfSomeOtherBitsAreEqual(T exchange,
-              T bitsToExchange,
-              T comperand,
-              T bitsToCompare
-              )
-
- inline T CompareSomeBitsAndExchange(T exchange, 
-                                     T comperand, 
-                                     T bitsToCompare)
- inline T CompareSomeBitsAndExchangeThoseBits(T exchange, 
-                                             T comperand, 
-                                             T bitsToCompare)
- inline T CompareSomeBitsAndExchangeSomeOtherBits(T exchange,
-              T bitsToExchange,
-              T comperand,
-              T bitsToCompare
-              )
-
-There are also atomic bit test, bit test and set etc. methods:
-
- inline bool BTS(int bit)
- inline bool BTC(int bit)
- inline bool BTR(int bit)
- inline bool BT(int bit)
-
-ALGORITHMS and their classes:
-
-The important ones are:
-
-struct Counted
-Use this as the base type for any object you want to be reference counted
-
-template <typename T> class CountedPtr;
-Safely acts as pointer to a reference counted type.  This pointer can not be
-shared between threads safely.
-
-template <typename T> class AtomicCountedPtr;
-Like CountedPtr<T> but this pointer CAN be shared between threads/processors
-safely.
-
-template <typename T> class MPQueue;
-Multiprocessor queue.  This is the nonblocking shared FIFO.
-
-Note, for the sake of convenience there is a Fifo that has the same
-semantics but can only be used single threaded:
-template <typename T> class Queue ;
-
-class MPCountStack;
-This is the multiprocessor nonblocking LIFO stack.  Note that what gets
-pushed on the stack are pointers to MPStackElement. Your data must be
-objects derived from MPStackElements.  Note that it is not legal to push a
-NULL onto the stack - NULL is used to signal an empty stack.
-
-Note that for the sake of convienience there is, once again, a single
-threaded version of the stack:
-class SimpleStack.
-
-There are also classes for allocators that use the MPCountStack as a
-freelist.
-template <typename T, typename BLOCK_ALLOCATOR>
-struct MPCountFreeListAllocator;
-
-This template is recursive in the sense that each allocator gets new blocks
-from a shared allocatorn passed in the constructor (of type
-BLOCK_ALLOCATOR).  You can build a tree of allocators this way.  The root of
-the tree should be of type SimpleAllocator<T> which just calls new and
-delete.
-
-Once again, for the sake of simplicity, there is a single threaded version
-of the block allocator called
-template <typename T, typename BLOCK_ALLOCATOR> struct SimpleBlockAllocator
-
-*/
-#ifndef ATOMIC_H
-#define ATOMIC_H
-#include <windows.h>
-#include <assert.h>
-#include <new>
-using namespace std;
-/* 
-    windows defines the following interlocked routines
-    we need to define the equivalent for volatiles (which 
-    they should have been in the first place, and the following 
-    types voltatile long, volatile int, volatile unsigned long, 
-    volatile unsigned int,  volatile T*, volatile __int64, 
-    volatile unsigned __int64.
-
-    Note: I use the platform SDK which has different header files 
-    for interlocked instructions than the Windows includes in Visual 
-    C
-
-    If you have the platform SDK and the code doesn't compile then
-    you need to make sure that 
-    "C:\Program Files\Microsoft Platform SDK\include"
-    is the first directory listed under menus "Tools" -> menu item
-    "Options" -> tab "Directories" (of course if you installed the 
-    platform SDK in a different directory than 
-    "C:\Program Files\Microsoft Platform SDK" then you should use 
-    YOUR path.
-
-    If you don't have the plaform SDK then InterlockedCompareExchange 
-    is defined for void * instead of being defined for longs...  and 
-    there is no InterlockedCompareExchangePointer
-
-    The whole point of Microsoft having different headers was an update
-    to support 64 bit platforms which doesn't matter here at all (some 
-    of the code here relies on CMPXCHG8B swaping out both a pointer AND
-    a counter - a trick that won't work on the current 64 bit platforms).
-
-    In any case, if you don't have the platform SDK then just 
-    appropriate casts to make the code compile.  Keep in mind that 
-    casting from 64 bit types to 32 bit types is wrong - where there's 
-    a 64 bit type I meant it to call one of my assembly language
-    routines that uses CMPXCHG8B.
-
-    LONG
-    InterlockedIncrement(
-    LPLONG lpAddend
-    );
-
-    LONG
-    InterlockedDecrement(
-    LPLONG lpAddend
-    );
-
-    LONG
-    InterlockedExchange(
-    LPLONG Target,
-    LONG Value
-    );
-
-    LONG
-    InterlockedExchangeAdd(
-    LPLONG Addend,
-    LONG Value
-    );
-
-    LONG
-    InterlockedCompareExchange (
-    PLONG Destination,
-    LONG ExChange,
-    LONG Comperand
-    );
-
-    PVOID
-    InterlockedExchangePointer (
-    PVOID *Target,
-    PVOID Value
-    );
-
-    PVOID
-    InterlockedCompareExchangePointer (
-    PVOID *Destination,
-    PVOID ExChange,
-    PVOID Comperand
-    );
-*/
-
-//we'll need a special cases for volatile __int64 and 
-//volatile unsigned __int64
-
-template <typename T>
-inline T InterlockedIncrement(volatile T * ptr)
-{
-    return (T)InterlockedIncrement((LPLONG)ptr);
-}
-
-template <typename T>
-inline T InterlockedDecrement(volatile T * ptr)
-{
-    return (T)InterlockedDecrement((LPLONG)ptr);
-}
-
-template <typename T>
-inline T InterlockedExchange(volatile T * target,T value)
-{
-    return (T)InterlockedExchange((LPLONG)target,(LONG)value);
-}
-
-template <typename T>
-inline T InterlockedExchangeAdd(volatile T *addend,T value)
-{
-    return (T)InterlockedExchangeAdd((LPLONG)addend,(LONG)value);
-}
-
-template <typename T>
-T InterlockedCompareExchange (volatile T * dest,T exchange,T comperand)
-{
-    return (T)InterlockedCompareExchange ((LPLONG)dest,
-                                        (LONG)exchange,
-                                        (LONG)comperand);
-}
-//most common use of InterlockedCompareExchange
-template <typename T>
-bool InterlockedSetIfEqual (volatile T * dest,T exchange,T comperand)
-{
-    return comperand==InterlockedCompareExchange(dest,exchange,comperand);
-}
-
-//disable the no return value warning, because the assembly language
-//routines load the appropriate registers directly
-#pragma warning(disable:4035)
-
-inline unsigned __int64 
-InterlockedCompareExchange(volatile unsigned __int64 *dest
-                           ,unsigned __int64 exchange
-                           ,unsigned __int64 comperand) 
-{
-    //value returned in eax::edx
-    __asm {
-        lea esi,comperand;
-        lea edi,exchange;
-        
-        mov eax,[esi];
-        mov edx,4[esi];
-        mov ebx,[edi];
-        mov ecx,4[edi];
-        mov esi,dest;
-        //lock CMPXCHG8B [esi] is equivalent to the following except
-        //that it's atomic:
-        //ZeroFlag = (edx:eax == *esi);
-        //if (ZeroFlag) *esi = ecx:ebx;
-        //else edx:eax = *esi;
-        lock CMPXCHG8B [esi];			
-    }
-}
-
-//most common use of InterlockedCompareExchange
-//It's more efficient to use the z flag than to do another compare
-inline bool 
-InterlockedSetIfEqual(volatile unsigned __int64 *dest
-                      ,unsigned __int64 exchange
-                      ,unsigned __int64 comperand) 
-{
-    //value returned in eax
-    __asm {
-        lea esi,comperand;
-        lea edi,exchange;
-        
-        mov eax,[esi];
-        mov edx,4[esi];
-        mov ebx,[edi];
-        mov ecx,4[edi];
-        mov esi,dest;
-        //lock CMPXCHG8B [esi] is equivalent to the following except
-        //that it's atomic:
-        //ZeroFlag = (edx:eax == *esi);
-        //if (ZeroFlag) *esi = ecx:ebx;
-        //else edx:eax = *esi;
-        lock CMPXCHG8B [esi];			
-        mov eax,0;
-        setz al;
-    }
-}
-#pragma warning(default:4035)
-
-inline unsigned __int64 InterlockedIncrement(volatile unsigned __int64 * ptr)
-{
-    unsigned __int64 comperand;
-    unsigned __int64 exchange;
-    do {
-        comperand = *ptr;
-        exchange = comperand+1;
-    }while(!InterlockedSetIfEqual(ptr,exchange,comperand));
-    return exchange;
-}
-
-inline unsigned __int64 InterlockedDecrement(volatile unsigned __int64 * ptr)
-{
-    unsigned __int64 comperand;
-    unsigned __int64 exchange;
-    do {
-        comperand = *ptr;
-        exchange = comperand-1;
-    }while(!InterlockedSetIfEqual(ptr,exchange,comperand));
-    return exchange;
-}
-
-inline unsigned __int64 InterlockedExchange(volatile unsigned __int64 * target,
-                                            unsigned __int64 value)
-{
-    unsigned __int64 comperand;
-    do {
-        comperand = *target;
-    }while(!InterlockedSetIfEqual(target,value,comperand));
-    return comperand;
-}
-
-inline unsigned __int64 InterlockedExchangeAdd(volatile unsigned __int64 *addend,
-                                               unsigned __int64 value)
-{
-    unsigned __int64 comperand;
-    do {
-        comperand = *addend;
-    }while(!InterlockedSetIfEqual(addend,comperand+value,comperand));
-    return comperand;
-}
-
-#pragma warning(disable:4035)
-inline __int64 
-InterlockedCompareExchange(volatile __int64 *dest
-                           ,__int64 exchange
-                           ,__int64 comperand) 
-{
-    //value returned in eax::edx
-    __asm {
-        lea esi,comperand;
-        lea edi,exchange;
-        
-        mov eax,[esi];
-        mov edx,4[esi];
-        mov ebx,[edi];
-        mov ecx,4[edi];
-        mov esi,dest;
-        //lock CMPXCHG8B [esi] is equivalent to the following except
-        //that it's atomic:
-        //ZeroFlag = (edx:eax == *esi);
-        //if (ZeroFlag) *esi = ecx:ebx;
-        //else edx:eax = *esi;
-        lock CMPXCHG8B [esi];			
-    }
-}
-
-//most common use of InterlockedCompareExchange
-//It's more efficient to use the z flag than to do another compare
-inline bool 
-InterlockedSetIfEqual(volatile __int64 *dest
-                      ,__int64 exchange
-                      ,__int64 comperand) 
-{
-    //value returned in eax
-    __asm {
-        lea esi,comperand;
-        lea edi,exchange;
-        
-        mov eax,[esi];
-        mov edx,4[esi];
-        mov ebx,[edi];
-        mov ecx,4[edi];
-        mov esi,dest;
-        //lock CMPXCHG8B [esi] is equivalent to the following except
-        //that it's atomic:
-        //ZeroFlag = (edx:eax == *esi);
-        //if (ZeroFlag) *esi = ecx:ebx;
-        //else edx:eax = *esi;
-        lock CMPXCHG8B [esi];			
-        mov eax,0;
-        setz al;
-    }
-}
-#pragma warning(default:4035)
-
-inline __int64 InterlockedIncrement(volatile __int64 * dest)
-{
-    __int64 comperand;
-    __int64 exchange;
-    do {
-        comperand = *dest;
-        exchange = comperand+1;
-    }while(!InterlockedSetIfEqual(dest,exchange,comperand));
-    return exchange;
-}
-
-inline __int64 InterlockedDecrement(volatile __int64 * dest)
-{
-    __int64 comperand;
-    __int64 exchange;
-    do {
-        comperand = *dest;
-        exchange = comperand-1;
-    }while(!InterlockedSetIfEqual(dest,exchange,comperand));
-    return exchange;
-}
-
-inline __int64 InterlockedExchange(volatile __int64 * target,__int64 value)
-{
-    __int64 comperand;
-    do {
-        comperand = *target;
-    }while(!InterlockedSetIfEqual(target,value,comperand));
-    return comperand;
-}
-
-inline __int64 InterlockedExchangeAdd(volatile __int64 *addend,
-                                      __int64 value)
-{
-    __int64 comperand;
-    do {
-        comperand = *addend;
-    }while(!InterlockedSetIfEqual(addend,comperand+value,comperand));
-    return comperand;
-}
-
-#pragma warning(disable:4035)
-//I've just thought of some algorithms that use BTS and all so I'm including them
-inline bool InterlockedBTS(volatile int *dest, int bit)
-{
-    //value returned in eax
-    __asm{
-        mov eax,bit;
-        mov ebx,dest;
-        lock bts [ebx],eax;
-        mov eax,0;
-        setc al;
-    }
-}
-inline bool InterlockedBTC(volatile int *dest, int bit)
-{
-    //value returned in eax
-    __asm{
-        mov eax,bit;
-        mov ebx,dest;
-        lock btc [ebx],eax;
-        mov eax,0;
-        setc al;
-    }
-}
-inline bool InterlockedBTR(volatile int *dest, int bit)
-{
-    //value returned in eax
-    __asm{
-        mov eax,bit;
-        mov ebx,dest;
-        lock btr [ebx],eax;
-        mov eax,0;
-        setc al;
-    }
-}
-//you can lock BT but since it doesn't change memory there isn't really any point
-inline bool BT(volatile int *dest, int bit)
-{
-    //value returned in eax
-    __asm{
-        mov eax,bit;
-        mov ebx,dest;
-        bt [ebx],eax;
-        mov eax,0;
-        setc al;
-    }
-}
-#pragma warning(default:4035)
-
-inline bool InterlockedBTS(volatile unsigned *dest, int bit)
-{
-    return InterlockedBTS((volatile int *)dest,bit);
-}
-inline bool InterlockedBTC(volatile unsigned *dest, int bit)
-{
-    return InterlockedBTC((volatile int *)dest,bit);
-}
-inline bool InterlockedBTR(volatile unsigned *dest, int bit)
-{
-    return InterlockedBTR((volatile int *)dest,bit);
-}
-inline bool BT(volatile unsigned *dest, int bit)
-{
-    return BT((volatile int *)dest,bit);
-}
-
-inline bool InterlockedBTS(volatile unsigned long *dest, int bit)
-{
-    return InterlockedBTS((volatile int *)dest,bit);
-}
-inline bool InterlockedBTC(volatile unsigned long *dest, int bit)
-{
-    return InterlockedBTC((volatile int *)dest,bit);
-}
-inline bool InterlockedBTR(volatile unsigned long *dest, int bit)
-{
-    return InterlockedBTR((volatile int *)dest,bit);
-}
-inline bool BT(volatile unsigned long *dest, int bit)
-{
-    return BT((volatile int *)dest,bit);
-}
-
-inline bool InterlockedBTS(volatile long *dest, int bit)
-{
-    return InterlockedBTS((volatile int *)dest,bit);
-}
-inline bool InterlockedBTC(volatile long *dest, int bit)
-{
-    return InterlockedBTC((volatile int *)dest,bit);
-}
-inline bool InterlockedBTR(volatile long *dest, int bit)
-{
-    return InterlockedBTR((volatile int *)dest,bit);
-}
-inline bool BT(volatile long *dest, int bit)
-{
-    return BT((volatile int *)dest,bit);
-}
-
-inline bool InterlockedBTS(volatile __int64 *dest, int bit)
-{
-    if (bit<32) return InterlockedBTS((volatile int *)&dest,bit);
-    return InterlockedBTS(1+(volatile int *)&dest,bit-32);
-}
-inline bool InterlockedBTC(volatile __int64 *dest, int bit)
-{
-    if (bit<32) return InterlockedBTC((volatile int *)&dest,bit);
-    return InterlockedBTC(1+(volatile int *)&dest,bit-32);
-}
-inline bool InterlockedBTR(volatile __int64 *dest, int bit)
-{
-    if (bit<32) return InterlockedBTR((volatile int *)&dest,bit);
-    return InterlockedBTR(1+(volatile int *)&dest,bit-32);
-}
-inline bool BT(volatile __int64 *dest, int bit)
-{
-    if (bit<32) return BT((volatile int *)&dest,bit);
-    return BT(1+(volatile int *)&dest,bit-32);
-}
-inline bool InterlockedBTS(volatile unsigned __int64 *dest, int bit)
-{
-    if (bit<32) return InterlockedBTS((volatile int *)&dest,bit);
-    return InterlockedBTS(1+(volatile int *)&dest,bit-32);
-}
-inline bool InterlockedBTC(volatile unsigned __int64 *dest, int bit)
-{
-    if (bit<32) return InterlockedBTC((volatile int *)&dest,bit);
-    return InterlockedBTC(1+(volatile int *)&dest,bit-32);
-}
-inline bool InterlockedBTR(volatile unsigned __int64 *dest, int bit)
-{
-    if (bit<32) return InterlockedBTR((volatile int *)&dest,bit);
-    return InterlockedBTR(1+(volatile int *)&dest,bit-32);
-}
-inline bool BT(volatile unsigned __int64 *dest, int bit)
-{
-    if (bit<32) return BT((volatile int *)&dest,bit);
-    return BT(1+(volatile int *)&dest,bit-32);
-}
-
-//T can be int, unsigned int, long, unsigned long
-//__int64 or unsigned __int64
-template <typename T>
-struct Atomic 
-{
-    volatile T value;
-    
-    inline Atomic(){}
-    
-    explicit inline Atomic(T n)
-    { //so that it's globally visible (to use intel's terminology)
-        InterlockedExchange(&value,n);
-    }
-    
-    //if you need an atomic load then use (*this += 0)
-    //but I haven't found any algorithms that
-    //require an atomic load
-    inline operator T() const
-    {
-        return value;
-    }
-    
-    inline T CompareExchange(T exchange, T comperand)
-    {
-        return InterlockedCompareExchange(&value,exchange,comperand);
-    }
-    
-    //useful - simulates having a compareexchange that ignores some bits in
-    //the compare
-    inline T CompareSomeBitsAndExchange(T exchange, T comperand, T bitsToCompare)
-    {
-        T returned;
-        T bitsToIgnore = ~bitsToCompare;
-        for (;;){
-            returned = InterlockedCompareExchange(&value,exchange,comperand);
-            if (returned == comperand) return returned;
-            if (0 != ((returned ^ comperand) & bitsToCompare)) break;
-            comparand = (comparand&bitsToCompare) | (bitsToIgnore&returned);
-        }
-        return returned;
-    }
-    
-    //useful - simulates having a compareexchange that ignores some bits in
-    //the compare and in the set
-    inline T CompareSomeBitsAndExchangeThoseBits(T exchange, T comperand, T bitsToCompare)
-    {
-        T returned = comperand;
-        T bitsToIgnore = ~bitsToCompare;
-        for (;;){
-            exchange = (exchange&bitsToCompare) | (bitsToIgnore&returned);
-            returned = InterlockedCompareExchange(&value,exchange,comperand);
-            if (returned == comperand) return returned;
-            if (0 != ((returned ^ comperand) & bitsToCompare)) break;
-            comparand = (comparand&bitsToCompare) | (bitsToIgnore&returned);
-        }
-        return returned;
-    }
-    
-    //useful - simulates having a compareexchange that ignores some bits in
-    //the compare and others in the set
-    inline T CompareSomeBitsAndExchangeSomeOtherBits(T exchange, 
-        T bitsToExchange,
-        T comperand, 
-        T bitsToCompare
-        )
-    {
-        T returned = value;
-        T bitsToIgnore = ~bitsToCompare;
-        T bitsToLeave = ~bitsToExchange;
-        for (;;){
-            exchange = (exchange&bitsToExchange) | (bitsToLeave&returned);
-            returned = InterlockedCompareExchange(&value,exchange,comperand);
-            if (returned == comperand) return returned;
-            if (0 != ((returned ^ comperand) & bitsToCompare)) break;
-            comparand = (comparand&bitsToCompare) | (bitsToIgnore&returned);
-        }
-        return returned;
-    }
-    
-    inline T Exchange(T exchange) 
-    {
-        return InterlockedExchange(&value,exchange);
-    }
-    
-    inline bool SetIfEqual(T exchange, T comperand)
-    {
-        return InterlockedSetIfEqual(&value,exchange,comperand);
-    }
-    
-    //useful - simulates having a compareexchange that ignores some bits in
-    //the compare
-    inline bool SetIfSomeBitsAreEqual(T exchange, T comperand, T bitsToCompare)
-    {
-        T returned;
-        T bitsToIgnore = ~bitsToCompare;
-        for (;;){
-            returned = InterlockedCompareExchange(&value,exchange,comperand);
-            if (returned == comperand) return true;
-            if (0 != ((returned ^ comperand) & bitsToCompare)) break;
-            comparand = (comparand&bitsToCompare) | (bitsToIgnore&returned);
-        }
-        return false;
-    }
-    
-    //useful - simulates having a compareexchange that ignores some bits in
-    //the compare and in the set
-    inline bool SetSomeBitsIfThoseBitsAreEqual(T exchange, T comperand, T bitsToCompare)
-    {
-        T returned = comperand;
-        T bitsToIgnore = ~bitsToCompare;
-        for (;;){
-            exchange = (exchange&bitsToCompare) | (bitsToIgnore&returned);
-            returned = InterlockedCompareExchange(&value,exchange,comperand);
-            if (returned == comperand) return true;
-            if (0 != ((returned ^ comperand) & bitsToCompare)) break;
-            comperand = (comperand&bitsToCompare) | (bitsToIgnore&returned);
-        }
-        return false;
-    }
-    //useful - simulates having a compareexchange that ignores some bits in
-    //the compare and others in the set
-    inline bool SetSomeBitsIfSomeOtherBitsAreEqual(T exchange, 
-        T bitsToExchange,
-        T comperand, 
-        T bitsToCompare
-        )
-    {
-        T returned = value;
-        T bitsToIgnore = ~bitsToCompare;
-        T bitsToLeave = ~bitsToExchange;
-        for (;;){
-            exchange = (exchange&bitsToExchange) | (bitsToLeave&returned);
-            returned = InterlockedCompareExchange(&value,exchange,comperand);
-            if (returned == comperand) return true;
-            if (0 != ((returned ^ comperand) & bitsToCompare)) break;
-            comperand = (comperand&bitsToCompare) | (bitsToIgnore&returned);
-        }
-        return false;
-    }
-    
-    inline T operator =(T exchange)
-    {
-        Exchange(exchange);
-        return exchange;
-    }
-    
-    inline T operator +=(T n)
-    {
-        return n + InterlockedExchangeAdd(&value, n);
-    }
-    
-    inline T operator -=(T n)
-    {
-        return InterlockedExchangeAdd(&value, -n) - n;
-    }
-    inline T operator ++()
-    {
-        return (*this += 1);
-    }
-    
-    inline T operator --() 
-    {
-        return (*this -= 1);
-    }
-    
-    inline T operator ++(int)
-    {
-        return InterlockedExchangeAdd(&value, (T)1);
-    }
-    
-    inline T operator --(int)
-    {
-        return InterlockedExchangeAdd(&value, (T)-1);
-    }
-    
-    inline T operator &=(T n)
-    {
-        T comperand;
-        T exchange;
-        do {
-            comperand = value; 
-            exchange = comperand & n;
-        }while(!SetIfEqual(exchange, comperand));
-        return exchange;
-    }
-    
-    inline T operator |= (T n) 
-    {
-        T comperand;
-        T exchange;
-        do {
-            comperand = value; 
-            exchange = comperand | n;
-        }while(!SetIfEqual(exchange, comperand));
-        return exchange;
-    }
-    
-    //yes this isn't standard, but it's useful
-    inline T Mask(T bitsToKeep, T bitsToSet) 
-    {
-        T comperand;
-        T exchange;
-        do {
-            comperand = value ; 
-            exchange = ((comperand & bitsToKeep) | bitsToSet);
-        }while(!SetIfEqual(exchange, comperand));
-        return exchange;
-    }
-    
-    inline T operator ^= (T n)
-    {
-        T comperand;
-        T exchange;
-        do {
-            comperand = value;  
-            exchange = comperand ^ n;
-        }while(!SetIfEqual(exchange, comperand));
-        return exchange;
-    }
-    inline T operator *= (T n) 
-    {
-        T comperand;
-        T exchange;
-        do {
-            comperand = value;  
-            exchange = comperand * n;
-        }while(!SetIfEqual(exchange, comperand));
-        return exchange;
-    }
-    
-    inline T operator /= (T n) 
-    {
-        T comperand;
-        T exchange;
-        do {
-            comperand = value;
-            exchange = comperand / n;
-        }while(!SetIfEqual(exchange, comperand));
-        return exchange;
-    }
-    
-    inline T operator >>= (unsigned n) 
-    {
-        T comperand;
-        T exchange;
-        do {
-            comperand = value;
-            exchange = comperand >> n;
-        }while(!SetIfEqual(exchange, comperand));
-        return exchange;
-    }
-    
-    inline T operator <<= (unsigned n)
-    {
-        T comperand;
-        T exchange;
-        do {
-            comperand = value;
-            exchange = comperand << n;
-        }while(!SetIfEqual(exchange, comperand));
-        return exchange;
-    }
-    inline bool BTS(int bit)
-    {
-        return InterlockedBTS(&value,bit);
-    }
-    inline bool BTC(int bit)
-    {
-        return InterlockedBTC(&value,bit);
-    }
-    inline bool BTR(int bit)
-    {
-        return InterlockedBTR(&value,bit);
-    }
-    inline bool BT(int bit)
-    {
-        return BT(&value,bit);
-    }
-}; 
-
-template <typename T>
-T * InterlockedCompareExchangePointer (
-                                       T *volatile *dest,
-                                       T * exchange,
-                                       T * comperand
-                                       )
-{
-    return (T*)InterlockedCompareExchangePointer((PVOID *)dest,(PVOID)exchange,(PVOID)comperand);
-}
-
-template <typename T>
-struct AtomicPtr 
-{
-    T * volatile value;
-    
-    inline AtomicPtr(){}
-    
-    explicit inline AtomicPtr(T *n)
-    { //so that it's globally visible (to use intel's terminology)
-        InterlockedExchange(&value,n);
-    }
-    explicit inline AtomicPtr(const T *n)
-    { //so that it's globally visible (to use intel's terminology)
-        InterlockedExchange(&value,(T *)n);
-    }
-    
-    inline operator T *() const
-    {
-        return value;
-    }
-    
-    inline operator const T *() const
-    {
-        return value;
-    }
-    
-    inline T *CompareExchange(T *exchange, T *comperand)
-    {
-        return InterlockedCompareExchangePointer(&value,exchange,comperand);
-    }
-    
-    //useful - simulates having a compareexchange that ignores some bits in
-    //the compare
-    inline T * CompareSomeBitsAndExchange(T * exchange, T * comperand, int bitsToCompare)
-    {
-        T  *returned;
-        int bitsToIgnore = ~bitsToCompare;
-        for (;;){
-            returned = InterlockedCompareExchangePointer(&value,exchange,comperand);
-            if (returned == comperand) return returned;
-            if (0 != ((returned ^ comperand) & bitsToCompare)) break;
-            comparand = (comparand&bitsToCompare) | (bitsToIgnore&returned);
-        }
-        return returned;
-    }
-    
-    //useful - simulates having a compareexchange that ignores some bits in
-    //the compare and in the set
-    inline T * CompareSomeBitsAndExchangeThoseBits(T * exchange, T * comperand, int bitsToCompare)
-    {
-        T *returned = comperand;
-        int bitsToIgnore = ~bitsToCompare;
-        for (;;){
-            exchange = (T*)((int)exchange&bitsToCompare) | (bitsToIgnore&(int)returned);
-            returned = InterlockedCompareExchangePointer(&value,exchange,comperand);
-            if (returned == comperand) return returned;
-            if (0 != ((returned ^ comperand) & bitsToCompare)) break;
-            comparand = (T*)((int)comparand&bitsToCompare) | (bitsToIgnore&(int)returned);
-        }
-        return returned;
-    }
-    //useful - simulates having a compareexchange that ignores some bits in
-    //the compare and others in the set
-    inline T* CompareSomeBitsAndExchangeSomeOtherBits(T *exchange, 
-        int bitsToExchange,
-        T * comperand, 
-        int bitsToCompare
-        )
-    {
-        T * returned = value;
-        int bitsToIgnore = ~bitsToCompare;
-        int bitsToLeave = ~bitsToExchange;
-        for (;;){
-            exchange = (T*)((int)exchange&bitsToExchange) | (bitsToLeave&(int)returned);
-            returned = InterlockedCompareExchange(&value,exchange,comperand);
-            if (returned == comperand) return returned;
-            if (0 != ((returned ^ comperand) & bitsToCompare)) break;
-            comparand = (T*)((int)comparand&bitsToCompare) | (bitsToIgnore&(int)returned);
-        }
-        return returned;
-    }
-    
-    inline T * operator ->() const
-    {
-        assert (value != NULL);
-        return value;
-    }
-    
-    inline T *Exchange(T *exchange) 
-    {
-        return InterlockedExchange(&value,exchange);
-    }
-    
-    inline bool SetIfEqual(T *exchange, T *comperand)
-    {
-        return comperand==InterlockedCompareExchangePointer(&value,exchange,comperand);
-    }
-    
-    //useful - simulates having a compareexchange that ignores some bits in
-    //the compare
-    inline bool SetIfSomeBitsAreEqual(T * exchange, T * comperand, int bitsToCompare)
-    {
-        T  *returned;
-        int bitsToIgnore = ~bitsToCompare;
-        for (;;){
-            returned = InterlockedCompareExchangePointer(&value,exchange,comperand);
-            if (returned == comperand) return true;
-            if (0 != ((returned ^ comperand) & bitsToCompare)) break;
-            comparand = (comparand&bitsToCompare) | (bitsToIgnore&returned);
-        }
-        return false;
-    }
-    
-    //useful - simulates having a compareexchange that ignores some bits in
-    //the compare and in the set
-    inline bool SetSomeBitsIfThoseBitsAreEqual(T * exchange, T * comperand, int bitsToCompare)
-    {
-        T *returned = comperand;
-        int bitsToIgnore = ~bitsToCompare;
-        for (;;){
-            exchange = (T*)((int)exchange&bitsToCompare) | (bitsToIgnore&(int)returned);
-            returned = InterlockedCompareExchangePointer(&value,exchange,comperand);
-            if (returned == comperand) return true;
-            if (0 != ((returned ^ comperand) & bitsToCompare)) break;
-            comparand = (T*)((int)comparand&bitsToCompare) | (bitsToIgnore&(int)returned);
-        }
-        return false;
-    }
-    
-    //useful - simulates having a compareexchange that ignores some bits in
-    //the compare and others in the set
-    inline bool SetSomeBitsIfSomeOtherBitsAreEqual(T *exchange, 
-        int bitsToExchange,
-        T * comperand, 
-        int bitsToCompare
-        )
-    {
-        T * returned = value;
-        int bitsToIgnore = ~bitsToCompare;
-        int bitsToLeave = ~bitsToExchange;
-        for (;;){
-            exchange = (T*)((int)exchange&bitsToExchange) | (bitsToLeave&(int)returned);
-            returned = InterlockedCompareExchange(&value,exchange,comperand);
-            if (returned == comperand) return true;
-            if (0 != ((returned ^ comperand) & bitsToCompare)) break;
-            comparand = (T*)((int)comparand&bitsToCompare) | (bitsToIgnore&(int)returned);
-        }
-        return false;
-    }
-    
-    inline T *operator =(T *exchange)
-    {
-        Exchange(exchange);
-        return exchange;
-    }
-    
-    template <typename INT_TYPE>
-        inline T *operator +=(INT_TYPE n)
-    {
-        return n + (T *)InterlockedExchangeAdd((LPLONG)&value, (LONG)(n * (LONG)sizeof(T)));
-    }
-    
-    template <typename INT_TYPE>
-        inline T *operator -=(INT_TYPE n)
-    {
-        return (T *)InterlockedExchangeAdd((LPLONG)&value, (LONG)(-n * (LONG)sizeof(T))) - n;
-    }
-    inline T *operator ++()
-    {
-        return (T *)InterlockedExchangeAdd((LPLONG)&value, (LONG)(sizeof(T))) + 1;
-    }
-    
-    inline T *operator --() 
-    {
-        return (T *)InterlockedExchangeAdd((LPLONG)&value, -(LONG)(sizeof(T))) - 1;
-    }
-    
-    inline T *operator ++(int)
-    {
-        return (T*)InterlockedExchangeAdd((LPLONG)&value, (LONG)sizeof(T));
-    }
-    
-    inline T *operator --(int)
-    {
-        return (T*)InterlockedExchangeAdd((LPLONG)&value, -(LONG)sizeof(T));
-    }
-    
-    //yes this isn't standard, but it's useful
-    template <typename INT_TYPE>
-        inline T *operator &=(INT_TYPE n)
-    {
-        T * comperand;
-        T * exchange;
-        do {
-            comperand = value; 
-            exchange = (T *)((LONG)comperand & n);
-        }while(!SetIfEqual(exchange, comperand));
-        return exchange;
-    }
-    
-    //yes this isn't standard, but it's useful
-    template <typename INT_TYPE>
-        inline T *operator |= (INT_TYPE n) 
-    {
-        T * comperand;
-        T * exchange;
-        do {
-            comperand = value; 
-            exchange = (T *)((LONG)comperand | n);
-        }while(!SetIfEqual(exchange, comperand));
-        return exchange;
-    }
-    
-    //yes this isn't standard, but it's useful
-    template <typename INT_TYPE>
-        inline T operator ^= (INT_TYPE n)
-    {
-        T * comperand;
-        T * exchange;
-        do {
-            comperand = value;  
-            exchange = (T *)((LONG)comperand ^ n);
-        }while(!SetIfEqual(exchange, comperand));
-        return exchange;
-    }
-    
-    //yes this isn't standard, but it's useful
-    template <typename INT_TYPE_A, typename INT_TYPE_B>
-        inline T * Mask(INT_TYPE_A bitsToKeep, INT_TYPE_B bitsToSet) 
-    {
-        T * comperand;
-        T * exchange;
-        do {
-            comperand = value ; 
-            exchange = (T *)(((LONG)comperand & bitsToKeep) | bitsToSet);
-        }while(!SetIfEqual(exchange, comperand));
-        return exchange;
-    }
-    
-    
-    inline bool BTS(int bit)
-    {
-        return InterlockedBTS((volatile int *)&value,bit);
-    }
-    inline bool BTC(int bit)
-    {
-        return InterlockedBTC((volatile int *)&value,bit);
-    }
-    inline bool BTR(int bit)
-    {
-        return InterlockedBTR((volatile int *)&value,bit);
-    }
-    inline bool BT(int bit)
-    {
-        return BT((volatile int *)&value,bit);
-    }
-};
-
-typedef Atomic<int> AtomicInt;
-typedef Atomic<unsigned int> AtomicUInt;
-typedef Atomic<__int64> AtomicInt64;
-typedef Atomic<unsigned __int64> AtomicUInt64;
-
-template
-<typename T, typename A = AtomicUInt64>
-struct AtomicUnion
-{
-    A whole;
-    
-    AtomicUnion()
-    {
-        assert(sizeof(T)<=sizeof(A));
-        new((void *)&whole) T();//in place new
-        
-    }
-    
-    ~AtomicUnion()
-    {
-        ((T *)&whole)->~T();
-    }
-    
-    T &Value() 
-    {
-        return *(T *)&whole;
-    }
-    const T &Value() const
-    {
-        return *(const T *)&whole;
-    }
-};
-
-
-template <typename T>
-struct AtomicPtrWithCountStruct
-{
-    AtomicPtr<T> ptr;
-    AtomicInt count;
-};
-
-
-template <typename T>
-struct PtrWithCountStruct
-{
-    T* ptr;
-    int count;
-};
-
-template <typename T, int MARKBITS=3>
-struct BitMarkedAtomicPtr : public AtomicPtr<T>
-{
-    const int MarkMask() const
-    {
-        return (1<<MARKBITS)-1;
-    }
-    
-    const int DataMask() const
-    {
-        return ~ThreadBitMask();
-    }
-    
-    static T * MaskPtr(T *data)
-    {
-        return (T*)((int)data & DataMask());
-    }
-    
-    static int MaskMark(T * data)
-    {
-        return ((int)data & MarkMask());
-    }
-    
-    static T* Mark(T * data, int bit)
-    {
-        return (T*)((int)data | 1<<bit);
-    }
-    
-    static T* Unmark(T * data, int bit)
-    {
-        return (T*)((int)data & ~(1<<bit));
-    }
-    
-    T * MaskPtr()
-    {
-        return MaskPtr(value);
-    }
-    
-    int MaskMark()
-    {
-        return MaskMark(value);
-    }
-    
-    //note new value has the marks in exchange not the original marks
-    inline bool SetIfMarked(T *exchange, int bit)
-    {
-        assert(bit<MARKBITS);
-        return SetIfSomeBitsAreEqual(exchange,DataMask(),(T*)(1<<bit),1<<bit);
-    }
-    
-    //note new value has the marks in exchange not the original marks
-    T * ExchangeIfMarked(T *exchange, int bit)
-    {
-        assert(bit<MARKBITS);
-        return CompareSomeBitsAndExchange(exchange,DataMask(),(T*)(1<<bit),1<<bit);
-    }
-    
-    inline bool SetAndClearMarksIfMarked(T *exchange, int bit)
-    {
-        return SetIfMarked(MaskPtr(exchange),bit);
-    }
-    
-    inline T * ExchangeAndClearMarksIfMarked(T *exchange, int bit)
-    {
-        return ExchangeIfMarked(MaskPtr(exchange),bit);
-    }
-    
-    inline bool SetAndClearOtherMarksIfMarked(T *exchange, int bit)
-    {
-        return SetIfMarked(Mark(MaskPtr(exchange),bit),
-            bit);
-    }
-    
-    //note new value has the marks in exchange not the original marks
-    T * ExchangeAndClearOtherMarksIfMarked(T *exchange, int bit)
-    {
-        return ExchangeIfMarked(Mark(MaskPtr(exchange),bit),
-            bit);
-    }
-    
-    inline bool SetAndMarkIfMarked(T *exchange, int bit)
-    {
-        return SetSomeBitsIfSomeOtherBitsAreEqual(
-            Mark(MaskPtr(exchange),bit),
-            DataMask() | 1<<bit,
-            (T*)(1<<bit),
-            1<<bit);
-    }
-    
-    inline T * ExchangeAndMarkIfMarked(T *exchange, int bit)
-    {
-        return CompareSomeBitsAndExchangeSomeOtherBits(
-            Mark(MaskPtr(exchange),bit),
-            DataMask() | 1<<bit,
-            (T*)(1<<bit),
-            1<<bit);
-    }	 
-    
-    bool Mark(int bit)
-    {
-        assert(bit<MARKBITS);
-        return BTS(bit);
-    }
-    
-    bool Unmark(int bit)
-    {
-        assert(bit<MARKBITS);
-        return BTC(bit);
-    }
-    
-    bool InvertMark(int bit)
-    {
-        assert(bit<MARKBITS);
-        return BTR(bit);
-    }
-    
-    bool IsMarked(int bit)
-    {
-        assert(bit<MARKBITS);
-        return BT(bit);
-    }
-};
-
-template <typename T>
-struct AtomicPtrWithCount : public AtomicUnion< AtomicPtrWithCountStruct<T> >
-{
-    typedef AtomicUnion< PtrWithCountStruct<T>, unsigned __int64 > SimpleUnionType;
-    AtomicPtrWithCount()
-    {
-        whole = 0;
-    }
-    AtomicPtrWithCount(unsigned __int64 o)
-    {
-        whole = o.whole;
-    }
-    AtomicPtrWithCount(T *ptr)
-    {
-        SimpleUnionType o;
-        o.Value().ptr = ptr;
-        o.Value().count = 0;
-        whole = o.whole;
-    }
-    
-    operator unsigned __int64() const
-    {
-        return whole;
-    }
-    T *Ptr() const
-    {
-        return Value().ptr;
-    }
-    int Count() const
-    {
-        return Value().count;
-    }
-    unsigned __int64 Whole() const
-    {
-        return whole;
-    }
-    
-    AtomicPtr<T> & Ptr()
-    {
-        return Value().ptr;
-    }
-    AtomicInt & Count()
-    {
-        return Value().count;
-    }
-    AtomicUInt64 & Whole()
-    {
-        return whole;
-    }
-    unsigned __int64 SetPtrAndIncCount(T *ptr)
-    {
-        SimpleUnionType was;
-        SimpleUnionType to;
-        to.Value().ptr = ptr;
-        do {
-            was.whole = whole;
-            to.Value().count = was.Value().count+1;
-        }while(!whole.SetIfEqual(to.whole,was.whole));
-        return to.whole;
-    }
-    bool SetIfPtrEqualAndIncCount(T *exchange, T *comperand)
-    {
-        SimpleUnionType was;
-        SimpleUnionType to;
-        to.ptr = exchange;
-        do {
-            was.whole = whole;
-            if (was.Value().ptr != comperand) return false;
-            to.Value().count = was.Value().count+1;
-        }while(!whole.SetIfEqual(to.whole,was.whole));
-        return true;
-    }
-    unsigned __int64 ExchangeIfPtrEqualAndIncCount(T *exchange, T *comperand)
-    {
-        SimpleUnionType was;
-        SimpleUnionType to;
-        to.ptr = exchange;
-        do {
-            was.whole = whole;
-            if (was.Value().ptr != comperand) return was.whole;
-            to.Value().count = was.Value().count+1;
-        }while(!whole.SetIfEqual(to.whole,was.whole));
-        return was.whole;
-    }
-    inline T *operator =(T *exchange)
-    {
-        SetPtrAndIncCount(exchange);
-        return exchange;
-    }
-    
-    template <typename INT_TYPE>
-        inline T *operator +=(INT_TYPE n)
-    {
-        T *was;
-        T *to;
-        do {
-            was = Ptr();
-            to = was + n;
-        }while (!SetIfPtrEqualAndIncCount(to,was));
-        return to;
-    }
-    
-    template <typename INT_TYPE>
-        inline T *operator -=(INT_TYPE n)
-    {
-        T *was;
-        T *to;
-        do {
-            was = Ptr();
-            to = was - n;
-        }while (!SetIfPtrEqualAndIncCount(to,was));
-        return to;
-    }
-    inline T *operator ++()
-    {
-        return (*this += 1);
-    }
-    
-    inline T *operator --() 
-    {
-        return (*this -= 1);
-    }
-    
-    inline T *operator ++(int)
-    {
-        return (++ *this) - 1;
-    }
-    
-    inline T *operator --(int)
-    {
-        return (-- *this) + 1;
-    }
-};
-
-template <typename T>
-struct AtomicPtrWithMarkStruct
-{
-    AtomicPtr<T> ptr;
-    AtomicUInt mark;
-};
-
-
-template <typename T>
-struct PtrWithMarkStruct
-{
-    T* ptr;
-    unsigned int mark;
-};
-
-template <typename T>
-struct AtomicPtrWithMark : public AtomicUnion< AtomicPtrWithMarkStruct<T> >
-{
-    typedef AtomicUnion< PtrWithMarkStruct<T>, unsigned __int64 > SimpleUnionType;
-    AtomicPtrWithMark()
-    {
-        whole = 0;
-    }
-    AtomicPtrWithMark(unsigned __int64 o)
-    {
-        whole = o.whole;
-    }
-    AtomicPtrWithMark(T *ptr)
-    {
-        SimpleUnionType o;
-        o.Value().ptr = ptr;
-        o.Value().mark = 0;
-        whole = o.whole;
-    }
-    
-    operator unsigned __int64() const
-    {
-        return whole;
-    }
-    T *Ptr() const
-    {
-        return Value().ptr;
-    }
-    int Mark() const
-    {
-        return Value().mark;
-    }
-    unsigned __int64 Whole() const
-    {
-        return whole;
-    }
-    
-    AtomicPtr<T> & Ptr()
-    {
-        return Value().ptr;
-    }
-    AtomicInt & Mark()
-    {
-        return Value().mark;
-    }
-    AtomicUInt64 & Whole()
-    {
-        return whole;
-    }
-    
-    inline bool SetAndClearOtherMarksIfMarked(T *exchange, int bit)
-    {
-        assert(bit<32);
-        SimpleUnionType compareMask;
-        compareMask.Value().ptr = NULL;
-        compareMask.Value().mark = 1u<<bit;
-        
-        SimpleUnionType exchangeValue;
-        exchangeValue.Value().ptr = exchange;
-        exchangeValue.Value().mark = compareMask.Value().mark;
-        
-        return whole.SetSomeBitsIfSomeOtherBitsAreEqual(exchangeValue.whole,
-            (unsigned __int64)-1i64,
-            compareMask.whole,
-            compareMask.whole);
-    }
-    inline bool SetAndClearMarksIfPtrEqual(T *exchange, T*comparend)
-    {
-        SimpleUnionType compareMask;
-        compareMask.Value().ptr = (T*)-1;
-        compareMask.Value().mark = 0;
-        
-        SimpleUnionType compareValue;
-        compareValue.Value().ptr = comparend;
-        compareValue.Value().mark = 0;
-        
-        SimpleUnionType exchangeValue;
-        exchangeValue.Value().ptr = exchange;
-        exchangeValue.Value().mark = 0;
-        
-        return whole.SetSomeBitsIfThoseBitsAreEqual(exchangeValue.whole,
-            compareValue.whole,
-            compareMask.whole);
-    }
-    
-    inline bool SetAndClearMarksIfMarked(T *exchange, int bit)
-    {
-        assert(bit<32);
-        SimpleUnionType compareMask;
-        compareMask.Value().ptr = NULL;
-        compareMask.Value().mark = 1u<<bit;
-        
-        SimpleUnionType exchangeValue;
-        exchangeValue.Value().ptr = exchange;
-        exchangeValue.Value().mark = 0;
-        
-        return whole.SetSomeBitsIfSomeOtherBitsAreEqual(exchangeValue.whole,
-            (unsigned __int64)-1i64,
-            compareMask.whole,
-            compareMask.whole);
-    }
-    //note new value has the marks in exchange not the original marks
-    unsigned __int64 ExchangeAndClearOtherMarksIfMarked(T *exchange, int bit)
-    {
-        assert(bit<32);
-        SimpleUnionType compareMask;
-        compareMask.Value().ptr = NULL;
-        compareMask.Value().mark = 1u<<bit;
-        
-        SimpleUnionType exchangeValue;
-        exchangeValue.Value().ptr = exchange;
-        exchangeValue.Value().mark = compareMask.Value().mark;
-        
-        return whole.CompareSomeBitsAndExchangeSomeOtherBits(exchangeValue.whole,
-            exchangeMask.whole,
-            compareMask.whole,
-            compareMask.whole);
-    }
-    
-    unsigned __int64 ExchangeAndClearMarksIfMarked(T *exchange, int bit)
-    {
-        assert(bit<32);
-        SimpleUnionType compareMask;
-        compareMask.Value().ptr = NULL;
-        compareMask.Value().mark = 1u<<bit;
-        
-        SimpleUnionType exchangeValue;
-        exchangeValue.Value().ptr = exchange;
-        exchangeValue.Value().mark = 0;
-        
-        return whole.CompareSomeBitsAndExchangeSomeOtherBits(exchangeValue.whole,
-            exchangeMask.whole,
-            compareMask.whole,
-            compareMask.whole);
-    }
-    
-    
-    bool Mark(int bit)
-    {
-        assert(bit<32);
-        return whole.BTS(bit);
-    }
-    
-    bool Unmark(int bit)
-    {
-        assert(bit<32);
-        return whole.BTC(bit);
-    }
-    
-    bool InvertMark(int bit)
-    {
-        assert(bit<32);
-        return whole.BTR(bit);
-    }
-    
-    bool IsMarked(int bit)
-    {
-        assert(bit<32);
-        return whole.BT(bit);
-    }
-};
-
-struct MPStackElement
-{
-    MPStackElement * next;
-};
-
-class MPMarkStack
-{
-protected:
-    AtomicPtrWithMark<MPStackElement> tos;
-    AtomicUInt availableThreadBits;
-    AtomicInt lastReserved;
-    
-public:
-    
-    MPStackElement* ExchangeStack(MPStackElement *newStack = NULL)
-    {
-        AtomicPtrWithMark<MPStackElement>::SimpleUnionType newWhole, ret;
-        newWhole.Value().mark = 0;
-        newWhole.Value().ptr = newStack;
-        ret.whole = tos.whole.Exchange(newWhole.whole);
-        return ret.Value().ptr;
-    }
-    
-    MPMarkStack()
-    {
-        lastReserved = 0;
-        tos.whole = 0;
-        availableThreadBits = (unsigned)-1;
-    }
-    
-    //expensive - call once per thread to reserve a bit
-    int ReserveThreadBit()
-    {
-        int offset = lastReserved;
-        //since locked operations are slow we only do
-        //bit tests on bits that look acceptable because
-        //of a nonlocked read.
-        unsigned readOnce = availableThreadBits;
-        for (int i=0; i< 32;++i){
-            const int bit = (31&(i+offset));
-            const unsigned mask = 1u<<bit;
-            if ((readOnce & mask)!=0){
-                if (availableThreadBits.BTR(bit)) {
-                    lastReserved = ((bit+1)&31);//try the next one
-                    return bit+1;
-                }
-                readOnce = availableThreadBits;
-            }
-        }
-        return 0;
-    }
-    int BlockingReserveThreadBit()
-    {
-        int i;
-        while (0==(i=ReserveThreadBit()));
-        return i;
-    }
-    int ReturnThreadBit(int i)
-    {
-        availableThreadBits.BTS(i-1);
-    }
-    
-    void PushElement(MPStackElement *element)
-    {
-        MPStackElement * next;
-        do {
-            next = tos.Value().ptr;
-            element->next = tos.Value().ptr;
-        }while(!tos.SetAndClearMarksIfPtrEqual(element,next));
-    }
-    
-    void PushList(MPStackElement *top, MPStackElement *bottom)
-    {
-        MPStackElement * next;
-        do {
-            next = tos.Value().ptr;
-            bottom->next = tos.Value().ptr;
-        }while(!tos.SetAndClearMarksIfPtrEqual(top,next));
-    }
-    
-    MPStackElement* PopElement(int i)
-    {
-        for(;;) {
-            tos.Value().mark.BTS(i-1);
-            MPStackElement * was = tos.Value().ptr;
-            if (was == NULL) return NULL;
-            if (tos.SetAndClearMarksIfMarked(was->next,i-1)) return was;
-        }
-    }
-    MPStackElement* PopElement()
-    {
-        int id = BlockingReserveThreadBit();
-        MPStackElement * ret = PopElement(id);
-        ReturnThreadBit(id);
-        return ret;
-    }
-};
-class MPCountStack
-{
-protected:
-    AtomicPtrWithCount<MPStackElement> tos;
-    
-public:
-    
-    MPStackElement* ExchangeStack(MPStackElement *newStack = NULL)
-    {
-        return tos.Value().ptr.Exchange(newStack);
-    }
-    
-    MPCountStack()
-    {
-        tos = 0;
-    }
-    
-    
-    void PushElement(MPStackElement *element)
-    {
-        MPStackElement * next;
-        do {
-            next = tos.Value().ptr;
-            element->next = tos.Value().ptr;
-        }while(!tos.Value().ptr.SetIfEqual(element,next));
-    }
-    
-    void PushList(MPStackElement *top, MPStackElement *bottom)
-    {
-        MPStackElement * next;
-        do {
-            next = tos.Value().ptr;
-            bottom->next = tos.Value().ptr;
-        }while(!tos.Value().ptr.SetIfEqual(top,next));
-    }
-    
-    MPStackElement* PopElement()
-    {
-        AtomicPtrWithCount<MPStackElement>::SimpleUnionType was;
-        AtomicPtrWithCount<MPStackElement>::SimpleUnionType to;
-        do {
-            was.whole = tos.whole;
-            if (was.Value().ptr == NULL) return NULL;
-            to.Value().count = was.Value().count + 1;
-            to.Value().ptr = was.Value().ptr->next;
-        }while(!tos.whole.SetIfEqual(was.whole,to.whole));
-        return was.Value().ptr;
-    }
-};
-
-class SimpleStack
-{
-protected:
-    MPStackElement * tos;
-    
-public:
-    
-    MPStackElement* ExchangeStack(MPStackElement *newStack = NULL)
-    {
-        MPStackElement* was = tos;
-        tos = newStack;
-        return was;
-    }
-    
-    SimpleStack()
-    {
-        tos = 0;
-    }
-    
-    
-    void PushElement(MPStackElement *element)
-    {
-        element->next = tos;
-        tos = element;
-    }
-    
-    void PushList(MPStackElement *top, MPStackElement *bottom)
-    {
-        bottom->next = tos;
-        tos = top;
-    }
-    
-    MPStackElement* PopElement()
-    {
-        MPStackElement* was = tos;
-        if (was) tos = was->next;
-        return was;
-    }
-};
-
-template <typename T>
-struct MPMemBlock : public MPStackElement
-{
-    T data;
-    char bottomOfBlock;
-};
-
-#define OFFSET_OF_MEMBER(type,member) ((int)&(((type *)0)->member))
-
-//put one of these in each thread object 
-//and you have thread local allocation
-template <typename T, typename BLOCK_ALLOCATOR>
-struct SimpleBlockAllocator
-{
-    SimpleStack data;
-    
-    typedef SimpleBlockAllocator<T,BLOCK_ALLOCATOR> AllocatorType;
-    
-    BLOCK_ALLOCATOR & MyAllocator;
-    
-    SimpleBlockAllocator(BLOCK_ALLOCATOR &source)
-        :MyAllocator(source)
-    {}
-    
-    int ReserveThreadBit(){return 1;}
-    int BlockingReserveThreadBit(){return 1;}
-    void ReturnThreadBit(int){  }
-    
-    int Size() const { return sizeof(T); }
-    void AddBlock()
-    {
-        int blockSize = MyAllocator.Size();
-        int elementSize = sizeof(MPMemBlock<T>);
-        assert( MyAllocator.Size() >= elementSize);
-        MPMemBlock<T> *bottom = (MPMemBlock<T> *)MyAllocator.Allocate();
-        void *prev = 0;
-        MPMemBlock<T> *top = bottom;  
-        do {
-            top->bottomOfBlock = 0;
-            top->next = prev;
-            prev = (void *)top;
-            ++top;
-        }while( (blockSize-=elementSize) >= elementSize);
-        bottom->bottomOfBlock = 1;
-        data.PushList(top-1,bottom);
-    }
-    void *Allocate(int) 
-    {	
-        return Allocate();
-    }
-    void *Allocate() 
-    {	
-        MPMemBlock<T> *ret;
-        for(;;) {
-            ret = (MPMemBlock<T> *)data.PopElement();
-            if (ret!=NULL) return &ret->data;
-            AddBlock();
-        }
-    }
-    void Deallocate(void *ob) 
-    {
-        if (!ob) return;
-        MPMemBlock<T> *ret = (MPMemBlock<T> *)
-            ((char *)data - OFFSET_OF_MEMBER(MPMemBlock<T>,ob));
-        data.PushElement(ret);
-    }
-    //all memory allocated must be Deallocated before Clear() or the destructor is called
-    void Clear() 
-    {
-        MPMemBlock<T> *stackWas = (MPMemBlock<T> *)data.ExchangeStack(NULL);
-        MPMemBlock<T> *blocks = NULL;
-        while(stackWas){
-            if (stackWas->bottomOfBlock){
-                if (blocks) {
-                    blocks->next = stackWas;
-                }
-                blocks = stackWas;
-            }
-            stackWas = (MPMemBlock<T> *)(stackWas->next);
-        }
-        while(blocks)
-        {
-            stackWas = (MPMemBlock<T> *)blocks->next;
-            MyAllocator.Deallocate(blocks);
-            blocks = stackWas;
-        }
-    }
-    //all memory allocated must be Deallocated before Clear() or the destructor is called
-    ~SimpleBlockAllocator()
-    {
-        Clear();
-    }
-};
-
-template<class T>
-struct SimpleAllocator
-{
-    void *Allocate() { return (void *)new char[sizeof(T)]; }
-    void *Allocate(int) { return Allocate(); }
-    
-    int ReserveThreadBit(){return 1;}
-    int BlockingReserveThreadBit(){return 1;}
-    void ReturnThreadBit(int){}
-    
-    void Deallocate(void *data) { delete[] (char[])data; }
-    int Size() const { return sizeof(T); }
-    typedef SimpleAllocator AllocatorType;
-};
-
-enum DontReserve{ DONT_RESERVE };
-
-template<class T>
-struct ThreadMarkedAllocator
-{
-    T& allocator;
-    int bit;
-    
-    ThreadMarkedAllocator(T &sourceAllocator)
-        :allocator(sourceAllocator)
-        ,bit(sourceAllocator.BlockingReserveThreadBit())
-    {}
-    
-    ThreadMarkedAllocator(T &sourceAllocator,DontReserve)
-        :allocator(sourceAllocator)
-        ,bit(0)
-    {}
-    
-    ~ThreadMarkedAllocator()
-    {
-        allocator.ReturnThreadBit(bit);
-    }
-    
-    bool ReserveThreadBit()
-    {
-        if (bit==0) bit=sourceAllocator.ReserveThreadBit();
-        return bit!=0;
-    }
-    void BlockingReserveThreadBit()
-    {
-        if (bit==0) bit=sourceAllocator.BlockingReserveThreadBit();
-    }
-    void ReturnThreadBit()
-    {
-        int was = bit;
-        bit = 0;
-        sourceAllocator.ReturnThreadBit(was);
-    }
-    
-    void *Allocate() 
-    { 
-        assert(bit!=0);
-        return allocator.Allocate(bit); 
-    }
-    
-    void Deallocate(void *data) { allocator.Deallocate(data); }
-    int Size() const { return Allocator.Size(); }
-    typedef ThreadMarkedAllocator<T> AllocatorType;
-};
-
-template <typename T, typename BLOCK_ALLOCATOR>
-struct MPMarkFreeListAllocator
-{
-    MPMarkStack data;
-    
-    typedef MPMarkFreeListAllocator<T,BLOCK_ALLOCATOR> AllocatorType;
-    
-    BLOCK_ALLOCATOR &MyAllocator;
-    
-    MPMarkFreeListAllocator(BLOCK_ALLOCATOR &source)
-        :MyAllocator(source)
-    {}
-    
-    int ReserveThreadBit(){return data.ReserveThreadBit();}
-    int BlockingReserveThreadBit(){return data.BlockingReserveThreadBit();}
-    void ReturnThreadBit(int bit){ data.ReturnThreadBit(bit); }
-    
-    int Size() const { return sizeof(T); }
-    void AddBlock()
-    {
-        int blockSize = MyAllocator.Size();
-        int elementSize = sizeof(MPMemBlock<T>);
-        assert( MyAllocator.Size() >= elementSize);
-        MPMemBlock<T> *bottom = (MPMemBlock<T> *)MyAllocator.Allocate();
-        void *prev = 0;
-        MPMemBlock<T> *top = bottom;  
-        do {
-            top->bottomOfBlock = 0;
-            top->next = prev;
-            prev = (void *)top;
-            ++top;
-        }while( (blockSize-=elementSize) >= elementSize);
-        bottom->bottomOfBlock = 1;
-        data.PushList(top-1,bottom);
-    }
-    void *Allocate(int mark) 
-    {	
-        MPMemBlock<T> *ret;
-        for(;;) {
-            ret = (MPMemBlock<T> *)data.PopElement(mark);
-            if (ret!=NULL) return ret;
-            AddBlock();
-        }
-    }
-    void *Allocate() 
-    {	
-        MPMemBlock<T> *ret;
-        for(;;) {
-            ret = (MPMemBlock<T> *)data.PopElement();
-            if (ret!=NULL) return &ret->data;
-            AddBlock();
-        }
-    }
-    void Deallocate(void *ob) 
-    {
-        if (!ob) return;
-        MPMemBlock<T> *ret = (MPMemBlock<T> *)
-            ((char *)data - OFFSET_OF_MEMBER(MPMemBlock<T>,ob));
-        data.PushElement(ret);
-    }
-    //all memory allocated must be Deallocated before Clear() or the destructor is called
-    void Clear()
-    {
-        MPMemBlock<T> *stackWas = (MPMemBlock<T> *)data.ExchangeStack(NULL);
-        MPMemBlock<T> *blocks = NULL;
-        while(stackWas){
-            if (stackWas->bottomOfBlock){
-                if (blocks) {
-                    blocks->next = stackWas;
-                }
-                blocks = stackWas;
-            }
-            stackWas = (MPMemBlock<T> *)(stackWas->next);
-        }
-        while(blocks)
-        {
-            stackWas = (MPMemBlock<T> *)blocks->next;
-            MyAllocator.Deallocate(blocks);
-            blocks = stackWas;
-        }
-    }
-    //all memory allocated must be Deallocated before Clear() or the destructor is called
-    ~MPMarkFreeListAllocator()
-    {
-        Clear();
-    }
-};
-template <typename T, typename BLOCK_ALLOCATOR>
-struct MPCountFreeListAllocator
-{
-    MPCountStack data;
-    
-    typedef MPCountFreeListAllocator<T,BLOCK_ALLOCATOR> AllocatorType;
-    
-    BLOCK_ALLOCATOR & MyAllocator;
-    
-    MPCountFreeListAllocator(BLOCK_ALLOCATOR &source)
-        :MyAllocator(source)
-    {}
-    
-    int ReserveThreadBit(){return 1;}
-    int BlockingReserveThreadBit(){return 1;}
-    void ReturnThreadBit(int){  }
-    
-    int Size() const { return sizeof(T); }
-    void AddBlock()
-    {
-        int blockSize = MyAllocator.Size();
-        int elementSize = sizeof(MPMemBlock<T>);
-        assert( MyAllocator.Size() >= elementSize);
-        MPMemBlock<T> *bottom = (MPMemBlock<T> *)MyAllocator.Allocate();
-        void *prev = 0;
-        MPMemBlock<T> *top = bottom;  
-        do {
-            top->bottomOfBlock = 0;
-            top->next = prev;
-            prev = (void *)top;
-            ++top;
-        }while( (blockSize-=elementSize) >= elementSize);
-        bottom->bottomOfBlock = 1;
-        data.PushList(top-1,bottom);
-    }
-    void *Allocate(int) 
-    {	
-        return Allocate();
-    }
-    void *Allocate() 
-    {	
-        MPMemBlock<T> *ret;
-        for(;;) {
-            ret = (MPMemBlock<T> *)data.PopElement();
-            if (ret!=NULL) return &ret->data;
-            AddBlock();
-        }
-    }
-    void Deallocate(void *ob) 
-    {
-        if (!ob) return;
-        MPMemBlock<T> *ret = (MPMemBlock<T> *)
-            ((char *)data - OFFSET_OF_MEMBER(MPMemBlock<T>,ob));
-        data.PushElement(ret);
-    }
-    //all memory allocated must be Deallocated before Clear() or the destructor is called
-    void Clear() 
-    {
-        MPMemBlock<T> *stackWas = (MPMemBlock<T> *)data.ExchangeStack(NULL);
-        MPMemBlock<T> *blocks = NULL;
-        while(stackWas){
-            if (stackWas->bottomOfBlock){
-                if (blocks) {
-                    blocks->next = stackWas;
-                }
-                blocks = stackWas;
-            }
-            stackWas = (MPMemBlock<T> *)(stackWas->next);
-        }
-        while(blocks)
-        {
-            stackWas = (MPMemBlock<T> *)blocks->next;
-            MyAllocator.Deallocate(blocks);
-            blocks = stackWas;
-        }
-    }
-    //all memory allocated must be Deallocated before Clear() or the destructor is called
-    ~MPCountFreeListAllocator()
-    {
-        Clear();
-    }
-};
-
-struct Counted
-{
-    mutable AtomicInt refCount;
-    Counted():refCount(0){}
-};
-
-//it is NOT safe to read or write from more than one thread at a time
-template <typename T> 
-class CountedPtr
-{
-    
-protected:
-    T *value;
-    void decRefCount()
-    {
-        decRefCount(value);
-    }
-public:
-    static void decRefCount(T *ptr)
-    {
-        if (ptr && 0 == --ptr->refCount){
-            delete ptr;
-        }
-    }
-    void SetValueIgnoringRefCounts(T *ptr) 
-    { 
-        value = ptr; 
-    }
-    CountedPtr():letter(NULL){}
-    
-    CountedPtr(T *ptr)
-    {
-        value = ptr;
-        if (value) ++value->refCount;
-    }
-    
-    operator const T *() const { return value; }
-    operator T *() { return value; }
-    
-    CountedPtr<T> & operator=(const T *ptr)
-    {
-        if (ptr) ++ptr->refCount;
-        decRefCount();
-        value = ptr;
-        return *this;
-    }
-    
-    operator bool() const
-    { return value!=NULL; }
-    
-    bool operator !() const
-    { return value==NULL; }
-    
-    
-    const T & operator*() const
-    { return *value; }
-    
-    T & operator*()
-    { return *value; }
-    
-    T * operator->()
-    { assert(value); return value; }
-    const T * operator->()const
-    { assert(value); return value; }
-    
-    ~CountedPtr()
-    {
-        decRefCount();
-    }
-};
-
-template <typename T>
-class AtomicCountedPtr
-{
-protected:
-    mutable AtomicPtrWithCount<T> value;
-public:
-    
-    
-    CountedPtr<T> & LoadValue(CountedPtr<T> &dest) const 
-    { 
-retry:
-    AtomicPtrWithCount<T>::SimpleUnionType inc;
-    inc.Value().ptr = 0;
-    inc.Value().count = 1;
-    AtomicPtrWithCount<T>::SimpleUnionType ret;
-    ret.whole = (value.whole+=inc.whole); //increment in ptr
-    dest = ret.Value().ptr ; //increment in object
-    AtomicPtrWithCount<T>::SimpleUnionType update;
-    update.Value().ptr = ret.Value().ptr;
-    for(;;){
-        update.Value().count = ret.Value().count-1;
-        AtomicPtrWithCount<T>::SimpleUnionType current;
-        current.whole = value.whole.SetIfEqual(update.whole,ret.whole);
-        if (current.whole == ret.whole) break; //successfully decremented in ptr
-        if (current.Value().ptr != ret.Value().ptr) || current.Value().count < 1){
-            //because of the line "dest = ret.Value().ptr" above
-            //the old value will decrement in the prev object as the next object is loaded
-            goto retry; 
-        }
-        ret.Value().count = current.Value().count;
-    }
-    return dest; 
-    }
-    
-    CountedPtr<T> & LoadValue(CountedPtr<T> &dest, int &count) const 
-    { 
-retry:
-    AtomicPtrWithCount<T>::SimpleUnionType inc;
-    inc.Value().ptr = 0;
-    inc.Value().count = 1;
-    AtomicPtrWithCount<T>::SimpleUnionType ret;
-    ret.whole = (value.whole+=inc.whole); //increment in ptr
-    dest = ret.Value().ptr ; //increment in object
-    AtomicPtrWithCount<T>::SimpleUnionType update;
-    update.Value().ptr = ret.Value().ptr;
-    for(;;){
-        update.Value().count = ret.Value().count-1;
-        AtomicPtrWithCount<T>::SimpleUnionType current;
-        current.whole = value.whole.SetIfEqual(update.whole,ret.whole);
-        if (current.whole == ret.whole) break; //successfully decremented in ptr
-        if (current.Value().ptr != ret.Value().ptr) || current.Value().count < 1){
-            //because of the line "dest = ret.Value().ptr" above
-            //the old value will decrement in the prev object as the next object is loaded
-            goto retry; 
-        }
-        ret.Value().count = current.Value().count;
-    }
-    count = ret.Value().count;
-    return dest; 
-    }
-    
-    CountedPtr<T> & ExchangeInPlace(CountedPtr<T> &dest)
-    { 
-        AtomicPtrWithCount<T>::SimpleUnionType destWhole;
-        destWhole.Value().ptr = dest;
-        destWhole.Value().count = 0;
-        destWhole.whole = value.whole.Exchange(destWhole.whole);
-        if (destWhole.Value().ptr != NULL && destWhole.Value().count != 0) 
-            destWhole.Value().ptr->refCount += destWhole.Value().count;
-        dest.SetValueIgnoringRefCounts(destWhole.Value().ptr);
-        return dest; 
-    }
-    
-    CountedPtr<T> & Exchange(CountedPtr<T> &dest, T *source)
-    { 
-        dest = source;
-        return ExchangeInPlace(dest);
-    }
-    
-    bool CompareExchange(CountedPtr<T> &dest, T *exchange, T * comparend)
-    { 
-        CountedPtr<T> holdExchange(exchange);
-retry:
-        AtomicPtrWithCount<T>::SimpleUnionType comp;
-        if (LoadValue(dest,comp.Value().count) != comparend) return false;
-        comp.Value().ptr = dest;
-        AtomicPtrWithCount<T>::SimpleUnionType exch;
-        exch.Value().ptr=exchange;
-        exch.Value().count = 0;
-        AtomicPtrWithCount<T>::SimpleUnionType ret;
-        for (;;){
-            ret.whole = value.whole.CompareExchange(exch.whole,comp.whole);
-            if (ret.whole == comp.whole) {
-                //transfer increment from holdExchange to this
-                holdExchange.SetValueIgnoringRefCounts(NULL);
-                //had inc from Load and the one from this 
-                if (dest) {
-                    const int dec = 1-comp.Value().count;
-                    if (dec!=0) dest->refCount -= dec;
-                }
-                return true;
-            }
-            if (ret.Value().ptr != comp.Value().ptr) {
-                //cant return the new pointer because there's no
-                //reason to think it hasn't been collected already
-                goto retry;
-            }
-            comp.Value().count = ret.Value().count;
-        }
-    }
-    
-    bool SetIfEqual(T *exchange, T * comparend)
-    { 
-        CountedPtr<T> holdExchange(exchange);
-retry:
-        AtomicPtrWithCount<T>::SimpleUnionType comp;
-        comp.whole = value.whole;
-        if (comp.Value().ptr != comparend) return false;
-        AtomicPtrWithCount<T>::SimpleUnionType exch;
-        exch.Value().ptr=exchange;
-        exch.Value().count = 0;
-        AtomicPtrWithCount<T>::SimpleUnionType ret;
-        for (;;){
-            ret.whole = value.whole.CompareExchange(exch.whole,comp.whole);
-            if (ret.whole == comp.whole) {
-                if (comp.Value().ptr) {
-                    const int dec = 1-comp.Value().count;
-                    if (dec!=0 && 0==(comp.Value().ptr->refCount -= dec)){
-                        delete comp.Value().ptr;
-                    };
-                }
-                //transfer increment from holdExchange to this
-                holdExchange.SetValueIgnoringRefCounts(NULL);
-                return true;
-            }
-            if (ret.Value().ptr != comp.Value().ptr) {
-                return false;
-            }
-            comp.Value().count = ret.Value().count;
-        }
-    }
-    
-    void operator = (const T *ptr)
-    {
-        CountedPtr<T> dest(ptr);
-        ExchangeInPlace(dest);
-    }
-    
-    //not recommended because value won't be consistant throughout 
-    //a given expression
-    operator bool() const
-    { return value.Value().ptr!=NULL; }
-    
-    //not recommended because value won't be consistant throughout 
-    //a given expression
-    bool operator !() const
-    { return value.Value().ptr==NULL; }
-    
-    
-    AtomicCountedPtr()
-    {}
-    
-    ~AtomicCountedPtr()
-    {
-        *this = (T*)NULL;
-    }
-};
-
-class MPQueueBase
-{
-    AtomicUInt * data;
-    int len;
-    
-    struct AtomicHeadAndTail{
-        AtomicInt head;
-        AtomicInt tail;
-    };
-    
-    AtomicUnion<AtomicHeadAndTail> headAndTail;
-    
-    struct HeadAndTailStruct{
-        int head;
-        int tail;
-    };
-    union HeadAndTailUnion
-    {
-        HeadAndTailStruct value;
-        unsigned __int64 whole;
-    };
-    
-    AtomicUInt & Index(int i)
-    {
-        return data[i & (len-1)];
-    }
-    bool IsNil(int i)
-    {
-        return (i & 1) != 0;
-    }
-    
-    public:
-        
-        int Used() const
-        {
-            HeadAndTailUnion ht;
-            ht.whole = headAndTail.whole;
-            return ht.value.head-ht.value.tail;
-            
-        }
-        bool Empty() const
-        {
-            HeadAndTailUnion ht;
-            ht.whole = headAndTail.whole;
-            return ht.value.head==ht.value.tail;
-        }
-        int Available() const
-        {
-            return MaxLen()-Used();
-            
-        }
-        int MaxLen() const
-        {
-            return len;
-        }
-        
-        MPQueueBase(int lenLn2)
-            :len(1<<lenLn2)
-        {
-            headAndTail.whole = 0;
-            data = new AtomicUInt[len];
-            for (int i=0;i<len;++i) data[i] = 1;
-        }
-        
-        ~MPQueueBase()
-        {
-            delete [] data;
-        }
-        
-        bool Put(int v)
-        {
-            assert((v&1)==0);
-            for(;;){
-                HeadAndTailUnion ht;
-                ht.whole = headAndTail.whole;
-                if (ht.value.head-ht.value.tail >= len) return false;
-                
-                int wasThere = Index(ht.value.head);
-                
-                if (IsNil(wasThere)){
-                    if (Index(ht.value.head).SetIfEqual(v,wasThere)){
-                        headAndTail.Value().head.SetIfEqual(1+ht.value.head,ht.value.head);
-                        return true;
-                    }
-                }
-                headAndTail.Value().head.SetIfEqual(1+ht.value.head,ht.value.head);
-            }
-        }
-        int Get()
-        {
-            for(;;){
-                HeadAndTailUnion ht;
-                ht.whole = headAndTail.whole;
-                if (ht.value.head-ht.value.tail < 1) return 0;
-                
-                int wasThere = Index(ht.value.tail);
-                int newNil = (ht.value.tail|1);
-                
-                if (!IsNil(wasThere)){
-                    if (Index(ht.value.tail).SetIfEqual(newNil,wasThere)){
-                        headAndTail.Value().tail.SetIfEqual(1+ht.value.tail,ht.value.tail);
-                        return wasThere;
-                    }
-                }
-                headAndTail.Value().tail.SetIfEqual(1+ht.value.tail,ht.value.tail);
-            }
-        }
-};
-
-template <typename T>
-class MPQueue 
-{
-    MPQueueBase queue;
-public:
-    MPQueue(int lenLn2)
-        :queue(lenLn2)
-    {}
-    T *Get()
-    {
-        return (T*)queue.Get();
-    }
-    bool Put(T * v)
-    {
-        return queue.Put((int)v);
-    }
-    bool Empty() const
-    {
-        return queue.Empty();
-    }
-    int Used() const
-    {
-        return queue.Used();
-        
-    }
-    int Available() const
-    {
-        return queue.Available();
-        
-    }
-    int MaxLen() const
-    {
-        return queue.MaxLen();
-    }
-};
-
-class QueueBase
-{
-    unsigned * data;
-    int len;
-    
-    int head;
-    int tail;
-    
-    unsigned & Index(int i)
-    {
-        return data[i & (len-1)];
-    }
-    
-public:
-    
-    int Used() const
-    {
-        return head-tail;
-        
-    }
-    bool Empty() const
-    {
-        return head==tail;
-        
-    }
-    
-    int Available() const
-    {
-        return MaxLen()-Used();
-        
-    }
-    int MaxLen() const
-    {
-        return len;
-    }
-    
-    QueueBase(int lenLn2)
-        :len(1<<lenLn2)
-        ,head(0)
-        ,tail(0)
-    {
-        data = new unsigned[len];
-        for (int i=0;i<len;++i) data[i] = 1;
-    }
-    
-    ~QueueBase()
-    {
-        delete [] data;
-    }
-    
-    bool Put(int v)
-    {
-        if (Available() < 1) return false;
-        Index(head++) = v;
-        return true;
-    }
-    
-    int Get()
-    {
-        if (Used() < 1) return 0;
-        return Index(tail++);
-    }
-};
-template <typename T>
-class Queue 
-{
-    QueueBase queue;
-public:
-    Queue(int lenLn2)
-        :queue(lenLn2)
-    {}
-    T *Get()
-    {
-        return (T*)queue.Get();
-    }
-    bool Put(T * v)
-    {
-        return queue.Put((int)v);
-    }
-    bool Empty() const
-    {
-        return queue.Empty();
-    }
-    int Used() const
-    {
-        return queue.Used();
-        
-    }
-    int Available() const
-    {
-        return queue.Available();
-        
-    }
-    int MaxLen() const
-    {
-        return queue.MaxLen();
-    }
-};
-
-
-#endif
diff --git a/lib/base/x11/keysym.nim b/lib/base/x11/keysym.nim
deleted file mode 100644
index 8958aabcb..000000000
--- a/lib/base/x11/keysym.nim
+++ /dev/null
@@ -1,1900 +0,0 @@
-#
-#Converted from X11/keysym.h and X11/keysymdef.h
-#
-#Capital letter consts renamed from XK_... to XKc_...
-# (since Pascal isn't case-sensitive)
-#
-#i.e.
-#C      Pascal
-#XK_a   XK_a
-#XK_A   XKc_A
-#
-
-#* default keysyms *
-
-const 
-  XK_VoidSymbol* = 0x00FFFFFF # void symbol 
-
-when defined(XK_MISCELLANY): 
-  #*
-  # * TTY Functions, cleverly chosen to map to ascii, for convenience of
-  # * programming, but could have been arbitrary (at the cost of lookup
-  # * tables in client code.
-  # *
-  XK_BackSpace == 0x0000FF08  # back space, back char 
-  XK_Tab == 0x0000FF09
-  XK_Linefeed == 0x0000FF0A   # Linefeed, LF 
-  XK_Clear == 0x0000FF0B
-  XK_Return == 0x0000FF0D     # Return, enter 
-  XK_Pause == 0x0000FF13      # Pause, hold 
-  XK_Scroll_Lock == 0x0000FF14
-  XK_Sys_Req == 0x0000FF15
-  XK_Escape == 0x0000FF1B
-  XK_Delete == 0x0000FFFF     # Delete, rubout 
-                              # International & multi-key character composition 
-  XK_Multi_key == 0x0000FF20  # Multi-key character compose 
-  XK_Codeinput == 0x0000FF37
-  XK_SingleCandidate == 0x0000FF3C
-  XK_MultipleCandidate == 0x0000FF3D
-  XK_PreviousCandidate == 0x0000FF3E # Japanese keyboard support 
-  XK_Kanji == 0x0000FF21      # Kanji, Kanji convert 
-  XK_Muhenkan == 0x0000FF22   # Cancel Conversion 
-  XK_Henkan_Mode == 0x0000FF23 # Start/Stop Conversion 
-  XK_Henkan == 0x0000FF23     # Alias for Henkan_Mode 
-  XK_Romaji == 0x0000FF24     # to Romaji 
-  XK_Hiragana == 0x0000FF25   # to Hiragana 
-  XK_Katakana == 0x0000FF26   # to Katakana 
-  XK_Hiragana_Katakana == 0x0000FF27 # Hiragana/Katakana toggle 
-  XK_Zenkaku == 0x0000FF28    # to Zenkaku 
-  XK_Hankaku == 0x0000FF29    # to Hankaku 
-  XK_Zenkaku_Hankaku == 0x0000FF2A # Zenkaku/Hankaku toggle 
-  XK_Touroku == 0x0000FF2B    # Add to Dictionary 
-  XK_Massyo == 0x0000FF2C     # Delete from Dictionary 
-  XK_Kana_Lock == 0x0000FF2D  # Kana Lock 
-  XK_Kana_Shift == 0x0000FF2E # Kana Shift 
-  XK_Eisu_Shift == 0x0000FF2F # Alphanumeric Shift 
-  XK_Eisu_toggle == 0x0000FF30 # Alphanumeric toggle 
-  XK_Kanji_Bangou == 0x0000FF37 # Codeinput 
-  XK_Zen_Koho == 0x0000FF3D   # Multiple/All Candidate(s) 
-  XK_Mae_Koho == 0x0000FF3E   # Previous Candidate 
-                              # = $FF31 thru = $FF3F are under XK_KOREAN 
-                              # Cursor control & motion 
-  XK_Home == 0x0000FF50
-  XK_Left == 0x0000FF51       # Move left, left arrow 
-  XK_Up == 0x0000FF52         # Move up, up arrow 
-  XK_Right == 0x0000FF53      # Move right, right arrow 
-  XK_Down == 0x0000FF54       # Move down, down arrow 
-  XK_Prior == 0x0000FF55      # Prior, previous 
-  XK_Page_Up == 0x0000FF55
-  XK_Next == 0x0000FF56       # Next 
-  XK_Page_Down == 0x0000FF56
-  XK_End == 0x0000FF57        # EOL 
-  XK_Begin == 0x0000FF58      # BOL 
-                              # Misc Functions 
-  XK_Select == 0x0000FF60     # Select, mark 
-  XK_Print == 0x0000FF61
-  XK_Execute == 0x0000FF62    # Execute, run, do 
-  XK_Insert == 0x0000FF63     # Insert, insert here 
-  XK_Undo == 0x0000FF65       # Undo, oops 
-  XK_Redo == 0x0000FF66       # redo, again 
-  XK_Menu == 0x0000FF67
-  XK_Find == 0x0000FF68       # Find, search 
-  XK_Cancel == 0x0000FF69     # Cancel, stop, abort, exit 
-  XK_Help == 0x0000FF6A       # Help 
-  XK_Break == 0x0000FF6B
-  XK_Mode_switch == 0x0000FF7E # Character set switch 
-  XK_script_switch == 0x0000FF7E # Alias for mode_switch 
-  XK_Num_Lock == 0x0000FF7F   # Keypad Functions, keypad numbers cleverly chosen to map to ascii 
-  XK_KP_Space == 0x0000FF80   # space 
-  XK_KP_Tab == 0x0000FF89
-  XK_KP_Enter == 0x0000FF8D   # enter 
-  XK_KP_F1 == 0x0000FF91      # PF1, KP_A, ... 
-  XK_KP_F2 == 0x0000FF92
-  XK_KP_F3 == 0x0000FF93
-  XK_KP_F4 == 0x0000FF94
-  XK_KP_Home == 0x0000FF95
-  XK_KP_Left == 0x0000FF96
-  XK_KP_Up == 0x0000FF97
-  XK_KP_Right == 0x0000FF98
-  XK_KP_Down == 0x0000FF99
-  XK_KP_Prior == 0x0000FF9A
-  XK_KP_Page_Up == 0x0000FF9A
-  XK_KP_Next == 0x0000FF9B
-  XK_KP_Page_Down == 0x0000FF9B
-  XK_KP_End == 0x0000FF9C
-  XK_KP_Begin == 0x0000FF9D
-  XK_KP_Insert == 0x0000FF9E
-  XK_KP_Delete == 0x0000FF9F
-  XK_KP_Equal == 0x0000FFBD   # equals 
-  XK_KP_Multiply == 0x0000FFAA
-  XK_KP_Add == 0x0000FFAB
-  XK_KP_Separator == 0x0000FFAC # separator, often comma 
-  XK_KP_Subtract == 0x0000FFAD
-  XK_KP_Decimal == 0x0000FFAE
-  XK_KP_Divide == 0x0000FFAF
-  XK_KP_0 == 0x0000FFB0
-  XK_KP_1 == 0x0000FFB1
-  XK_KP_2 == 0x0000FFB2
-  XK_KP_3 == 0x0000FFB3
-  XK_KP_4 == 0x0000FFB4
-  XK_KP_5 == 0x0000FFB5
-  XK_KP_6 == 0x0000FFB6
-  XK_KP_7 == 0x0000FFB7
-  XK_KP_8 == 0x0000FFB8
-  XK_KP_9 == 0x0000FFB9 #*
-                        # * Auxilliary Functions; note the duplicate definitions for left and right
-                        # * function keys;  Sun keyboards and a few other manufactures have such
-                        # * function key groups on the left and/or right sides of the keyboard.
-                        # * We've not found a keyboard with more than 35 function keys total.
-                        # *
-  XK_F1 == 0x0000FFBE
-  XK_F2 == 0x0000FFBF
-  XK_F3 == 0x0000FFC0
-  XK_F4 == 0x0000FFC1
-  XK_F5 == 0x0000FFC2
-  XK_F6 == 0x0000FFC3
-  XK_F7 == 0x0000FFC4
-  XK_F8 == 0x0000FFC5
-  XK_F9 == 0x0000FFC6
-  XK_F10 == 0x0000FFC7
-  XK_F11 == 0x0000FFC8
-  XK_L1 == 0x0000FFC8
-  XK_F12 == 0x0000FFC9
-  XK_L2 == 0x0000FFC9
-  XK_F13 == 0x0000FFCA
-  XK_L3 == 0x0000FFCA
-  XK_F14 == 0x0000FFCB
-  XK_L4 == 0x0000FFCB
-  XK_F15 == 0x0000FFCC
-  XK_L5 == 0x0000FFCC
-  XK_F16 == 0x0000FFCD
-  XK_L6 == 0x0000FFCD
-  XK_F17 == 0x0000FFCE
-  XK_L7 == 0x0000FFCE
-  XK_F18 == 0x0000FFCF
-  XK_L8 == 0x0000FFCF
-  XK_F19 == 0x0000FFD0
-  XK_L9 == 0x0000FFD0
-  XK_F20 == 0x0000FFD1
-  XK_L10 == 0x0000FFD1
-  XK_F21 == 0x0000FFD2
-  XK_R1 == 0x0000FFD2
-  XK_F22 == 0x0000FFD3
-  XK_R2 == 0x0000FFD3
-  XK_F23 == 0x0000FFD4
-  XK_R3 == 0x0000FFD4
-  XK_F24 == 0x0000FFD5
-  XK_R4 == 0x0000FFD5
-  XK_F25 == 0x0000FFD6
-  XK_R5 == 0x0000FFD6
-  XK_F26 == 0x0000FFD7
-  XK_R6 == 0x0000FFD7
-  XK_F27 == 0x0000FFD8
-  XK_R7 == 0x0000FFD8
-  XK_F28 == 0x0000FFD9
-  XK_R8 == 0x0000FFD9
-  XK_F29 == 0x0000FFDA
-  XK_R9 == 0x0000FFDA
-  XK_F30 == 0x0000FFDB
-  XK_R10 == 0x0000FFDB
-  XK_F31 == 0x0000FFDC
-  XK_R11 == 0x0000FFDC
-  XK_F32 == 0x0000FFDD
-  XK_R12 == 0x0000FFDD
-  XK_F33 == 0x0000FFDE
-  XK_R13 == 0x0000FFDE
-  XK_F34 == 0x0000FFDF
-  XK_R14 == 0x0000FFDF
-  XK_F35 == 0x0000FFE0
-  XK_R15 == 0x0000FFE0        # Modifiers 
-  XK_Shift_L == 0x0000FFE1    # Left shift 
-  XK_Shift_R == 0x0000FFE2    # Right shift 
-  XK_Control_L == 0x0000FFE3  # Left control 
-  XK_Control_R == 0x0000FFE4  # Right control 
-  XK_Caps_Lock == 0x0000FFE5  # Caps lock 
-  XK_Shift_Lock == 0x0000FFE6 # Shift lock 
-  XK_Meta_L == 0x0000FFE7     # Left meta 
-  XK_Meta_R == 0x0000FFE8     # Right meta 
-  XK_Alt_L == 0x0000FFE9      # Left alt 
-  XK_Alt_R == 0x0000FFEA      # Right alt 
-  XK_Super_L == 0x0000FFEB    # Left super 
-  XK_Super_R == 0x0000FFEC    # Right super 
-  XK_Hyper_L == 0x0000FFED    # Left hyper 
-  XK_Hyper_R == 0x0000FFEE    # Right hyper 
-# XK_MISCELLANY 
-#*
-# * ISO 9995 Function and Modifier Keys
-# * Byte 3 = = $FE
-# *
-
-when defined(XK_XKB_KEYS): 
-  XK_ISO_Lock == 0x0000FE01
-  XK_ISO_Level2_Latch == 0x0000FE02
-  XK_ISO_Level3_Shift == 0x0000FE03
-  XK_ISO_Level3_Latch == 0x0000FE04
-  XK_ISO_Level3_Lock == 0x0000FE05
-  XK_ISO_Group_Shift == 0x0000FF7E # Alias for mode_switch 
-  XK_ISO_Group_Latch == 0x0000FE06
-  XK_ISO_Group_Lock == 0x0000FE07
-  XK_ISO_Next_Group == 0x0000FE08
-  XK_ISO_Next_Group_Lock == 0x0000FE09
-  XK_ISO_Prev_Group == 0x0000FE0A
-  XK_ISO_Prev_Group_Lock == 0x0000FE0B
-  XK_ISO_First_Group == 0x0000FE0C
-  XK_ISO_First_Group_Lock == 0x0000FE0D
-  XK_ISO_Last_Group == 0x0000FE0E
-  XK_ISO_Last_Group_Lock == 0x0000FE0F
-  XK_ISO_Left_Tab == 0x0000FE20
-  XK_ISO_Move_Line_Up == 0x0000FE21
-  XK_ISO_Move_Line_Down == 0x0000FE22
-  XK_ISO_Partial_Line_Up == 0x0000FE23
-  XK_ISO_Partial_Line_Down == 0x0000FE24
-  XK_ISO_Partial_Space_Left == 0x0000FE25
-  XK_ISO_Partial_Space_Right == 0x0000FE26
-  XK_ISO_Set_Margin_Left == 0x0000FE27
-  XK_ISO_Set_Margin_Right == 0x0000FE28
-  XK_ISO_Release_Margin_Left == 0x0000FE29
-  XK_ISO_Release_Margin_Right == 0x0000FE2A
-  XK_ISO_Release_Both_Margins == 0x0000FE2B
-  XK_ISO_Fast_Cursor_Left == 0x0000FE2C
-  XK_ISO_Fast_Cursor_Right == 0x0000FE2D
-  XK_ISO_Fast_Cursor_Up == 0x0000FE2E
-  XK_ISO_Fast_Cursor_Down == 0x0000FE2F
-  XK_ISO_Continuous_Underline == 0x0000FE30
-  XK_ISO_Discontinuous_Underline == 0x0000FE31
-  XK_ISO_Emphasize == 0x0000FE32
-  XK_ISO_Center_Object == 0x0000FE33
-  XK_ISO_Enter == 0x0000FE34
-  XK_dead_grave == 0x0000FE50
-  XK_dead_acute == 0x0000FE51
-  XK_dead_circumflex == 0x0000FE52
-  XK_dead_tilde == 0x0000FE53
-  XK_dead_macron == 0x0000FE54
-  XK_dead_breve == 0x0000FE55
-  XK_dead_abovedot == 0x0000FE56
-  XK_dead_diaeresis == 0x0000FE57
-  XK_dead_abovering == 0x0000FE58
-  XK_dead_doubleacute == 0x0000FE59
-  XK_dead_caron == 0x0000FE5A
-  XK_dead_cedilla == 0x0000FE5B
-  XK_dead_ogonek == 0x0000FE5C
-  XK_dead_iota == 0x0000FE5D
-  XK_dead_voiced_sound == 0x0000FE5E
-  XK_dead_semivoiced_sound == 0x0000FE5F
-  XK_dead_belowdot == 0x0000FE60
-  XK_dead_hook == 0x0000FE61
-  XK_dead_horn == 0x0000FE62
-  XK_First_Virtual_Screen == 0x0000FED0
-  XK_Prev_Virtual_Screen == 0x0000FED1
-  XK_Next_Virtual_Screen == 0x0000FED2
-  XK_Last_Virtual_Screen == 0x0000FED4
-  XK_Terminate_Server == 0x0000FED5
-  XK_AccessX_Enable == 0x0000FE70
-  XK_AccessX_Feedback_Enable == 0x0000FE71
-  XK_RepeatKeys_Enable == 0x0000FE72
-  XK_SlowKeys_Enable == 0x0000FE73
-  XK_BounceKeys_Enable == 0x0000FE74
-  XK_StickyKeys_Enable == 0x0000FE75
-  XK_MouseKeys_Enable == 0x0000FE76
-  XK_MouseKeys_Accel_Enable == 0x0000FE77
-  XK_Overlay1_Enable == 0x0000FE78
-  XK_Overlay2_Enable == 0x0000FE79
-  XK_AudibleBell_Enable == 0x0000FE7A
-  XK_Pointer_Left == 0x0000FEE0
-  XK_Pointer_Right == 0x0000FEE1
-  XK_Pointer_Up == 0x0000FEE2
-  XK_Pointer_Down == 0x0000FEE3
-  XK_Pointer_UpLeft == 0x0000FEE4
-  XK_Pointer_UpRight == 0x0000FEE5
-  XK_Pointer_DownLeft == 0x0000FEE6
-  XK_Pointer_DownRight == 0x0000FEE7
-  XK_Pointer_Button_Dflt == 0x0000FEE8
-  XK_Pointer_Button1 == 0x0000FEE9
-  XK_Pointer_Button2 == 0x0000FEEA
-  XK_Pointer_Button3 == 0x0000FEEB
-  XK_Pointer_Button4 == 0x0000FEEC
-  XK_Pointer_Button5 == 0x0000FEED
-  XK_Pointer_DblClick_Dflt == 0x0000FEEE
-  XK_Pointer_DblClick1 == 0x0000FEEF
-  XK_Pointer_DblClick2 == 0x0000FEF0
-  XK_Pointer_DblClick3 == 0x0000FEF1
-  XK_Pointer_DblClick4 == 0x0000FEF2
-  XK_Pointer_DblClick5 == 0x0000FEF3
-  XK_Pointer_Drag_Dflt == 0x0000FEF4
-  XK_Pointer_Drag1 == 0x0000FEF5
-  XK_Pointer_Drag2 == 0x0000FEF6
-  XK_Pointer_Drag3 == 0x0000FEF7
-  XK_Pointer_Drag4 == 0x0000FEF8
-  XK_Pointer_Drag5 == 0x0000FEFD
-  XK_Pointer_EnableKeys == 0x0000FEF9
-  XK_Pointer_Accelerate == 0x0000FEFA
-  XK_Pointer_DfltBtnNext == 0x0000FEFB
-  XK_Pointer_DfltBtnPrev == 0x0000FEFC
-#*
-# * 3270 Terminal Keys
-# * Byte 3 = = $FD
-# *
-
-when defined(XK_3270): 
-  XK_3270_Duplicate == 0x0000FD01
-  XK_3270_FieldMark == 0x0000FD02
-  XK_3270_Right2 == 0x0000FD03
-  XK_3270_Left2 == 0x0000FD04
-  XK_3270_BackTab == 0x0000FD05
-  XK_3270_EraseEOF == 0x0000FD06
-  XK_3270_EraseInput == 0x0000FD07
-  XK_3270_Reset == 0x0000FD08
-  XK_3270_Quit == 0x0000FD09
-  XK_3270_PA1 == 0x0000FD0A
-  XK_3270_PA2 == 0x0000FD0B
-  XK_3270_PA3 == 0x0000FD0C
-  XK_3270_Test == 0x0000FD0D
-  XK_3270_Attn == 0x0000FD0E
-  XK_3270_CursorBlink == 0x0000FD0F
-  XK_3270_AltCursor == 0x0000FD10
-  XK_3270_KeyClick == 0x0000FD11
-  XK_3270_Jump == 0x0000FD12
-  XK_3270_Ident == 0x0000FD13
-  XK_3270_Rule == 0x0000FD14
-  XK_3270_Copy == 0x0000FD15
-  XK_3270_Play == 0x0000FD16
-  XK_3270_Setup == 0x0000FD17
-  XK_3270_Record == 0x0000FD18
-  XK_3270_ChangeScreen == 0x0000FD19
-  XK_3270_DeleteWord == 0x0000FD1A
-  XK_3270_ExSelect == 0x0000FD1B
-  XK_3270_CursorSelect == 0x0000FD1C
-  XK_3270_PrintScreen == 0x0000FD1D
-  XK_3270_Enter == 0x0000FD1E
-#*
-# *  Latin 1
-# *  Byte 3 = 0
-# *
-
-when defined(XK_LATIN1): 
-  XK_space == 0x00000020
-  XK_exclam == 0x00000021
-  XK_quotedbl == 0x00000022
-  XK_numbersign == 0x00000023
-  XK_dollar == 0x00000024
-  XK_percent == 0x00000025
-  XK_ampersand == 0x00000026
-  XK_apostrophe == 0x00000027
-  XK_quoteright == 0x00000027 # deprecated 
-  XK_parenleft == 0x00000028
-  XK_parenright == 0x00000029
-  XK_asterisk == 0x0000002A
-  XK_plus == 0x0000002B
-  XK_comma == 0x0000002C
-  XK_minus == 0x0000002D
-  XK_period == 0x0000002E
-  XK_slash == 0x0000002F
-  XK_0 == 0x00000030
-  XK_1 == 0x00000031
-  XK_2 == 0x00000032
-  XK_3 == 0x00000033
-  XK_4 == 0x00000034
-  XK_5 == 0x00000035
-  XK_6 == 0x00000036
-  XK_7 == 0x00000037
-  XK_8 == 0x00000038
-  XK_9 == 0x00000039
-  XK_colon == 0x0000003A
-  XK_semicolon == 0x0000003B
-  XK_less == 0x0000003C
-  XK_equal == 0x0000003D
-  XK_greater == 0x0000003E
-  XK_question == 0x0000003F
-  XK_at == 0x00000040
-  XKc_A == 0x00000041
-  XKc_B == 0x00000042
-  XKc_C == 0x00000043
-  XKc_D == 0x00000044
-  XKc_E == 0x00000045
-  XKc_F == 0x00000046
-  XKc_G == 0x00000047
-  XKc_H == 0x00000048
-  XKc_I == 0x00000049
-  XKc_J == 0x0000004A
-  XKc_K == 0x0000004B
-  XKc_L == 0x0000004C
-  XKc_M == 0x0000004D
-  XKc_N == 0x0000004E
-  XKc_O == 0x0000004F
-  XKc_P == 0x00000050
-  XKc_Q == 0x00000051
-  XKc_R == 0x00000052
-  XKc_S == 0x00000053
-  XKc_T == 0x00000054
-  XKc_U == 0x00000055
-  XKc_V == 0x00000056
-  XKc_W == 0x00000057
-  XKc_X == 0x00000058
-  XKc_Y == 0x00000059
-  XKc_Z == 0x0000005A
-  XK_bracketleft == 0x0000005B
-  XK_backslash == 0x0000005C
-  XK_bracketright == 0x0000005D
-  XK_asciicircum == 0x0000005E
-  XK_underscore == 0x0000005F
-  XK_grave == 0x00000060
-  XK_quoteleft == 0x00000060  # deprecated 
-  XK_a == 0x00000061
-  XK_b == 0x00000062
-  XK_c == 0x00000063
-  XK_d == 0x00000064
-  XK_e == 0x00000065
-  XK_f == 0x00000066
-  XK_g == 0x00000067
-  XK_h == 0x00000068
-  XK_i == 0x00000069
-  XK_j == 0x0000006A
-  XK_k == 0x0000006B
-  XK_l == 0x0000006C
-  XK_m == 0x0000006D
-  XK_n == 0x0000006E
-  XK_o == 0x0000006F
-  XK_p == 0x00000070
-  XK_q == 0x00000071
-  XK_r == 0x00000072
-  XK_s == 0x00000073
-  XK_t == 0x00000074
-  XK_u == 0x00000075
-  XK_v == 0x00000076
-  XK_w == 0x00000077
-  XK_x == 0x00000078
-  XK_y == 0x00000079
-  XK_z == 0x0000007A
-  XK_braceleft == 0x0000007B
-  XK_bar == 0x0000007C
-  XK_braceright == 0x0000007D
-  XK_asciitilde == 0x0000007E
-  XK_nobreakspace == 0x000000A0
-  XK_exclamdown == 0x000000A1
-  XK_cent == 0x000000A2
-  XK_sterling == 0x000000A3
-  XK_currency == 0x000000A4
-  XK_yen == 0x000000A5
-  XK_brokenbar == 0x000000A6
-  XK_section == 0x000000A7
-  XK_diaeresis == 0x000000A8
-  XK_copyright == 0x000000A9
-  XK_ordfeminine == 0x000000AA
-  XK_guillemotleft == 0x000000AB # left angle quotation mark 
-  XK_notsign == 0x000000AC
-  XK_hyphen == 0x000000AD
-  XK_registered == 0x000000AE
-  XK_macron == 0x000000AF
-  XK_degree == 0x000000B0
-  XK_plusminus == 0x000000B1
-  XK_twosuperior == 0x000000B2
-  XK_threesuperior == 0x000000B3
-  XK_acute == 0x000000B4
-  XK_mu == 0x000000B5
-  XK_paragraph == 0x000000B6
-  XK_periodcentered == 0x000000B7
-  XK_cedilla == 0x000000B8
-  XK_onesuperior == 0x000000B9
-  XK_masculine == 0x000000BA
-  XK_guillemotright == 0x000000BB # right angle quotation mark 
-  XK_onequarter == 0x000000BC
-  XK_onehalf == 0x000000BD
-  XK_threequarters == 0x000000BE
-  XK_questiondown == 0x000000BF
-  XKc_Agrave == 0x000000C0
-  XKc_Aacute == 0x000000C1
-  XKc_Acircumflex == 0x000000C2
-  XKc_Atilde == 0x000000C3
-  XKc_Adiaeresis == 0x000000C4
-  XKc_Aring == 0x000000C5
-  XKc_AE == 0x000000C6
-  XKc_Ccedilla == 0x000000C7
-  XKc_Egrave == 0x000000C8
-  XKc_Eacute == 0x000000C9
-  XKc_Ecircumflex == 0x000000CA
-  XKc_Ediaeresis == 0x000000CB
-  XKc_Igrave == 0x000000CC
-  XKc_Iacute == 0x000000CD
-  XKc_Icircumflex == 0x000000CE
-  XKc_Idiaeresis == 0x000000CF
-  XKc_ETH == 0x000000D0
-  XKc_Ntilde == 0x000000D1
-  XKc_Ograve == 0x000000D2
-  XKc_Oacute == 0x000000D3
-  XKc_Ocircumflex == 0x000000D4
-  XKc_Otilde == 0x000000D5
-  XKc_Odiaeresis == 0x000000D6
-  XK_multiply == 0x000000D7
-  XKc_Ooblique == 0x000000D8
-  XKc_Oslash == XKc_Ooblique
-  XKc_Ugrave == 0x000000D9
-  XKc_Uacute == 0x000000DA
-  XKc_Ucircumflex == 0x000000DB
-  XKc_Udiaeresis == 0x000000DC
-  XKc_Yacute == 0x000000DD
-  XKc_THORN == 0x000000DE
-  XK_ssharp == 0x000000DF
-  XK_agrave == 0x000000E0
-  XK_aacute == 0x000000E1
-  XK_acircumflex == 0x000000E2
-  XK_atilde == 0x000000E3
-  XK_adiaeresis == 0x000000E4
-  XK_aring == 0x000000E5
-  XK_ae == 0x000000E6
-  XK_ccedilla == 0x000000E7
-  XK_egrave == 0x000000E8
-  XK_eacute == 0x000000E9
-  XK_ecircumflex == 0x000000EA
-  XK_ediaeresis == 0x000000EB
-  XK_igrave == 0x000000EC
-  XK_iacute == 0x000000ED
-  XK_icircumflex == 0x000000EE
-  XK_idiaeresis == 0x000000EF
-  XK_eth == 0x000000F0
-  XK_ntilde == 0x000000F1
-  XK_ograve == 0x000000F2
-  XK_oacute == 0x000000F3
-  XK_ocircumflex == 0x000000F4
-  XK_otilde == 0x000000F5
-  XK_odiaeresis == 0x000000F6
-  XK_division == 0x000000F7
-  XK_oslash == 0x000000F8
-  XK_ooblique == XK_oslash
-  XK_ugrave == 0x000000F9
-  XK_uacute == 0x000000FA
-  XK_ucircumflex == 0x000000FB
-  XK_udiaeresis == 0x000000FC
-  XK_yacute == 0x000000FD
-  XK_thorn == 0x000000FE
-  XK_ydiaeresis == 0x000000FF
-# XK_LATIN1 
-#*
-# *   Latin 2
-# *   Byte 3 = 1
-# *
-
-when defined(XK_LATIN2): 
-  XKc_Aogonek == 0x000001A1
-  XK_breve == 0x000001A2
-  XKc_Lstroke == 0x000001A3
-  XKc_Lcaron == 0x000001A5
-  XKc_Sacute == 0x000001A6
-  XKc_Scaron == 0x000001A9
-  XKc_Scedilla == 0x000001AA
-  XKc_Tcaron == 0x000001AB
-  XKc_Zacute == 0x000001AC
-  XKc_Zcaron == 0x000001AE
-  XKc_Zabovedot == 0x000001AF
-  XK_aogonek == 0x000001B1
-  XK_ogonek == 0x000001B2
-  XK_lstroke == 0x000001B3
-  XK_lcaron == 0x000001B5
-  XK_sacute == 0x000001B6
-  XK_caron == 0x000001B7
-  XK_scaron == 0x000001B9
-  XK_scedilla == 0x000001BA
-  XK_tcaron == 0x000001BB
-  XK_zacute == 0x000001BC
-  XK_doubleacute == 0x000001BD
-  XK_zcaron == 0x000001BE
-  XK_zabovedot == 0x000001BF
-  XKc_Racute == 0x000001C0
-  XKc_Abreve == 0x000001C3
-  XKc_Lacute == 0x000001C5
-  XKc_Cacute == 0x000001C6
-  XKc_Ccaron == 0x000001C8
-  XKc_Eogonek == 0x000001CA
-  XKc_Ecaron == 0x000001CC
-  XKc_Dcaron == 0x000001CF
-  XKc_Dstroke == 0x000001D0
-  XKc_Nacute == 0x000001D1
-  XKc_Ncaron == 0x000001D2
-  XKc_Odoubleacute == 0x000001D5
-  XKc_Rcaron == 0x000001D8
-  XKc_Uring == 0x000001D9
-  XKc_Udoubleacute == 0x000001DB
-  XKc_Tcedilla == 0x000001DE
-  XK_racute == 0x000001E0
-  XK_abreve == 0x000001E3
-  XK_lacute == 0x000001E5
-  XK_cacute == 0x000001E6
-  XK_ccaron == 0x000001E8
-  XK_eogonek == 0x000001EA
-  XK_ecaron == 0x000001EC
-  XK_dcaron == 0x000001EF
-  XK_dstroke == 0x000001F0
-  XK_nacute == 0x000001F1
-  XK_ncaron == 0x000001F2
-  XK_odoubleacute == 0x000001F5
-  XK_udoubleacute == 0x000001FB
-  XK_rcaron == 0x000001F8
-  XK_uring == 0x000001F9
-  XK_tcedilla == 0x000001FE
-  XK_abovedot == 0x000001FF
-# XK_LATIN2 
-#*
-# *   Latin 3
-# *   Byte 3 = 2
-# *
-
-when defined(XK_LATIN3): 
-  XKc_Hstroke == 0x000002A1
-  XKc_Hcircumflex == 0x000002A6
-  XKc_Iabovedot == 0x000002A9
-  XKc_Gbreve == 0x000002AB
-  XKc_Jcircumflex == 0x000002AC
-  XK_hstroke == 0x000002B1
-  XK_hcircumflex == 0x000002B6
-  XK_idotless == 0x000002B9
-  XK_gbreve == 0x000002BB
-  XK_jcircumflex == 0x000002BC
-  XKc_Cabovedot == 0x000002C5
-  XKc_Ccircumflex == 0x000002C6
-  XKc_Gabovedot == 0x000002D5
-  XKc_Gcircumflex == 0x000002D8
-  XKc_Ubreve == 0x000002DD
-  XKc_Scircumflex == 0x000002DE
-  XK_cabovedot == 0x000002E5
-  XK_ccircumflex == 0x000002E6
-  XK_gabovedot == 0x000002F5
-  XK_gcircumflex == 0x000002F8
-  XK_ubreve == 0x000002FD
-  XK_scircumflex == 0x000002FE
-# XK_LATIN3 
-#*
-# *   Latin 4
-# *   Byte 3 = 3
-# *
-
-when defined(XK_LATIN4): 
-  XK_kra == 0x000003A2
-  XK_kappa == 0x000003A2      # deprecated 
-  XKc_Rcedilla == 0x000003A3
-  XKc_Itilde == 0x000003A5
-  XKc_Lcedilla == 0x000003A6
-  XKc_Emacron == 0x000003AA
-  XKc_Gcedilla == 0x000003AB
-  XKc_Tslash == 0x000003AC
-  XK_rcedilla == 0x000003B3
-  XK_itilde == 0x000003B5
-  XK_lcedilla == 0x000003B6
-  XK_emacron == 0x000003BA
-  XK_gcedilla == 0x000003BB
-  XK_tslash == 0x000003BC
-  XKc_ENG == 0x000003BD
-  XK_eng == 0x000003BF
-  XKc_Amacron == 0x000003C0
-  XKc_Iogonek == 0x000003C7
-  XKc_Eabovedot == 0x000003CC
-  XKc_Imacron == 0x000003CF
-  XKc_Ncedilla == 0x000003D1
-  XKc_Omacron == 0x000003D2
-  XKc_Kcedilla == 0x000003D3
-  XKc_Uogonek == 0x000003D9
-  XKc_Utilde == 0x000003DD
-  XKc_Umacron == 0x000003DE
-  XK_amacron == 0x000003E0
-  XK_iogonek == 0x000003E7
-  XK_eabovedot == 0x000003EC
-  XK_imacron == 0x000003EF
-  XK_ncedilla == 0x000003F1
-  XK_omacron == 0x000003F2
-  XK_kcedilla == 0x000003F3
-  XK_uogonek == 0x000003F9
-  XK_utilde == 0x000003FD
-  XK_umacron == 0x000003FE
-# XK_LATIN4 
-#*
-# * Latin-8
-# * Byte 3 = 18
-# *
-
-when defined(XK_LATIN8): 
-  XKc_Babovedot == 0x000012A1
-  XK_babovedot == 0x000012A2
-  XKc_Dabovedot == 0x000012A6
-  XKc_Wgrave == 0x000012A8
-  XKc_Wacute == 0x000012AA
-  XK_dabovedot == 0x000012AB
-  XKc_Ygrave == 0x000012AC
-  XKc_Fabovedot == 0x000012B0
-  XK_fabovedot == 0x000012B1
-  XKc_Mabovedot == 0x000012B4
-  XK_mabovedot == 0x000012B5
-  XKc_Pabovedot == 0x000012B7
-  XK_wgrave == 0x000012B8
-  XK_pabovedot == 0x000012B9
-  XK_wacute == 0x000012BA
-  XKc_Sabovedot == 0x000012BB
-  XK_ygrave == 0x000012BC
-  XKc_Wdiaeresis == 0x000012BD
-  XK_wdiaeresis == 0x000012BE
-  XK_sabovedot == 0x000012BF
-  XKc_Wcircumflex == 0x000012D0
-  XKc_Tabovedot == 0x000012D7
-  XKc_Ycircumflex == 0x000012DE
-  XK_wcircumflex == 0x000012F0
-  XK_tabovedot == 0x000012F7
-  XK_ycircumflex == 0x000012FE
-# XK_LATIN8 
-#*
-# * Latin-9 (a.k.a. Latin-0)
-# * Byte 3 = 19
-# *
-
-when defined(XK_LATIN9): 
-  XKc_OE == 0x000013BC
-  XK_oe == 0x000013BD
-  XKc_Ydiaeresis == 0x000013BE
-# XK_LATIN9 
-#*
-# * Katakana
-# * Byte 3 = 4
-# *
-
-when defined(XK_KATAKANA): 
-  XK_overline == 0x0000047E
-  XK_kana_fullstop == 0x000004A1
-  XK_kana_openingbracket == 0x000004A2
-  XK_kana_closingbracket == 0x000004A3
-  XK_kana_comma == 0x000004A4
-  XK_kana_conjunctive == 0x000004A5
-  XK_kana_middledot == 0x000004A5 # deprecated 
-  XKc_kana_WO == 0x000004A6
-  XK_kana_a == 0x000004A7
-  XK_kana_i == 0x000004A8
-  XK_kana_u == 0x000004A9
-  XK_kana_e == 0x000004AA
-  XK_kana_o == 0x000004AB
-  XK_kana_ya == 0x000004AC
-  XK_kana_yu == 0x000004AD
-  XK_kana_yo == 0x000004AE
-  XK_kana_tsu == 0x000004AF
-  XK_kana_tu == 0x000004AF    # deprecated 
-  XK_prolongedsound == 0x000004B0
-  XKc_kana_A == 0x000004B1
-  XKc_kana_I == 0x000004B2
-  XKc_kana_U == 0x000004B3
-  XKc_kana_E == 0x000004B4
-  XKc_kana_O == 0x000004B5
-  XKc_kana_KA == 0x000004B6
-  XKc_kana_KI == 0x000004B7
-  XKc_kana_KU == 0x000004B8
-  XKc_kana_KE == 0x000004B9
-  XKc_kana_KO == 0x000004BA
-  XKc_kana_SA == 0x000004BB
-  XKc_kana_SHI == 0x000004BC
-  XKc_kana_SU == 0x000004BD
-  XKc_kana_SE == 0x000004BE
-  XKc_kana_SO == 0x000004BF
-  XKc_kana_TA == 0x000004C0
-  XKc_kana_CHI == 0x000004C1
-  XKc_kana_TI == 0x000004C1   # deprecated 
-  XKc_kana_TSU == 0x000004C2
-  XKc_kana_TU == 0x000004C2   # deprecated 
-  XKc_kana_TE == 0x000004C3
-  XKc_kana_TO == 0x000004C4
-  XKc_kana_NA == 0x000004C5
-  XKc_kana_NI == 0x000004C6
-  XKc_kana_NU == 0x000004C7
-  XKc_kana_NE == 0x000004C8
-  XKc_kana_NO == 0x000004C9
-  XKc_kana_HA == 0x000004CA
-  XKc_kana_HI == 0x000004CB
-  XKc_kana_FU == 0x000004CC
-  XKc_kana_HU == 0x000004CC   # deprecated 
-  XKc_kana_HE == 0x000004CD
-  XKc_kana_HO == 0x000004CE
-  XKc_kana_MA == 0x000004CF
-  XKc_kana_MI == 0x000004D0
-  XKc_kana_MU == 0x000004D1
-  XKc_kana_ME == 0x000004D2
-  XKc_kana_MO == 0x000004D3
-  XKc_kana_YA == 0x000004D4
-  XKc_kana_YU == 0x000004D5
-  XKc_kana_YO == 0x000004D6
-  XKc_kana_RA == 0x000004D7
-  XKc_kana_RI == 0x000004D8
-  XKc_kana_RU == 0x000004D9
-  XKc_kana_RE == 0x000004DA
-  XKc_kana_RO == 0x000004DB
-  XKc_kana_WA == 0x000004DC
-  XKc_kana_N == 0x000004DD
-  XK_voicedsound == 0x000004DE
-  XK_semivoicedsound == 0x000004DF
-  XK_kana_switch == 0x0000FF7E # Alias for mode_switch 
-# XK_KATAKANA 
-#*
-# *  Arabic
-# *  Byte 3 = 5
-# *
-
-when defined(XK_ARABIC): 
-  XK_Farsi_0 == 0x00000590
-  XK_Farsi_1 == 0x00000591
-  XK_Farsi_2 == 0x00000592
-  XK_Farsi_3 == 0x00000593
-  XK_Farsi_4 == 0x00000594
-  XK_Farsi_5 == 0x00000595
-  XK_Farsi_6 == 0x00000596
-  XK_Farsi_7 == 0x00000597
-  XK_Farsi_8 == 0x00000598
-  XK_Farsi_9 == 0x00000599
-  XK_Arabic_percent == 0x000005A5
-  XK_Arabic_superscript_alef == 0x000005A6
-  XK_Arabic_tteh == 0x000005A7
-  XK_Arabic_peh == 0x000005A8
-  XK_Arabic_tcheh == 0x000005A9
-  XK_Arabic_ddal == 0x000005AA
-  XK_Arabic_rreh == 0x000005AB
-  XK_Arabic_comma == 0x000005AC
-  XK_Arabic_fullstop == 0x000005AE
-  XK_Arabic_0 == 0x000005B0
-  XK_Arabic_1 == 0x000005B1
-  XK_Arabic_2 == 0x000005B2
-  XK_Arabic_3 == 0x000005B3
-  XK_Arabic_4 == 0x000005B4
-  XK_Arabic_5 == 0x000005B5
-  XK_Arabic_6 == 0x000005B6
-  XK_Arabic_7 == 0x000005B7
-  XK_Arabic_8 == 0x000005B8
-  XK_Arabic_9 == 0x000005B9
-  XK_Arabic_semicolon == 0x000005BB
-  XK_Arabic_question_mark == 0x000005BF
-  XK_Arabic_hamza == 0x000005C1
-  XK_Arabic_maddaonalef == 0x000005C2
-  XK_Arabic_hamzaonalef == 0x000005C3
-  XK_Arabic_hamzaonwaw == 0x000005C4
-  XK_Arabic_hamzaunderalef == 0x000005C5
-  XK_Arabic_hamzaonyeh == 0x000005C6
-  XK_Arabic_alef == 0x000005C7
-  XK_Arabic_beh == 0x000005C8
-  XK_Arabic_tehmarbuta == 0x000005C9
-  XK_Arabic_teh == 0x000005CA
-  XK_Arabic_theh == 0x000005CB
-  XK_Arabic_jeem == 0x000005CC
-  XK_Arabic_hah == 0x000005CD
-  XK_Arabic_khah == 0x000005CE
-  XK_Arabic_dal == 0x000005CF
-  XK_Arabic_thal == 0x000005D0
-  XK_Arabic_ra == 0x000005D1
-  XK_Arabic_zain == 0x000005D2
-  XK_Arabic_seen == 0x000005D3
-  XK_Arabic_sheen == 0x000005D4
-  XK_Arabic_sad == 0x000005D5
-  XK_Arabic_dad == 0x000005D6
-  XK_Arabic_tah == 0x000005D7
-  XK_Arabic_zah == 0x000005D8
-  XK_Arabic_ain == 0x000005D9
-  XK_Arabic_ghain == 0x000005DA
-  XK_Arabic_tatweel == 0x000005E0
-  XK_Arabic_feh == 0x000005E1
-  XK_Arabic_qaf == 0x000005E2
-  XK_Arabic_kaf == 0x000005E3
-  XK_Arabic_lam == 0x000005E4
-  XK_Arabic_meem == 0x000005E5
-  XK_Arabic_noon == 0x000005E6
-  XK_Arabic_ha == 0x000005E7
-  XK_Arabic_heh == 0x000005E7 # deprecated 
-  XK_Arabic_waw == 0x000005E8
-  XK_Arabic_alefmaksura == 0x000005E9
-  XK_Arabic_yeh == 0x000005EA
-  XK_Arabic_fathatan == 0x000005EB
-  XK_Arabic_dammatan == 0x000005EC
-  XK_Arabic_kasratan == 0x000005ED
-  XK_Arabic_fatha == 0x000005EE
-  XK_Arabic_damma == 0x000005EF
-  XK_Arabic_kasra == 0x000005F0
-  XK_Arabic_shadda == 0x000005F1
-  XK_Arabic_sukun == 0x000005F2
-  XK_Arabic_madda_above == 0x000005F3
-  XK_Arabic_hamza_above == 0x000005F4
-  XK_Arabic_hamza_below == 0x000005F5
-  XK_Arabic_jeh == 0x000005F6
-  XK_Arabic_veh == 0x000005F7
-  XK_Arabic_keheh == 0x000005F8
-  XK_Arabic_gaf == 0x000005F9
-  XK_Arabic_noon_ghunna == 0x000005FA
-  XK_Arabic_heh_doachashmee == 0x000005FB
-  XK_Farsi_yeh == 0x000005FC
-  XK_Arabic_farsi_yeh == XK_Farsi_yeh
-  XK_Arabic_yeh_baree == 0x000005FD
-  XK_Arabic_heh_goal == 0x000005FE
-  XK_Arabic_switch == 0x0000FF7E # Alias for mode_switch 
-# XK_ARABIC 
-#*
-# * Cyrillic
-# * Byte 3 = 6
-# *
-
-when defined(XK_CYRILLIC): 
-  XKc_Cyrillic_GHE_bar == 0x00000680
-  XK_Cyrillic_ghe_bar == 0x00000690
-  XKc_Cyrillic_ZHE_descender == 0x00000681
-  XK_Cyrillic_zhe_descender == 0x00000691
-  XKc_Cyrillic_KA_descender == 0x00000682
-  XK_Cyrillic_ka_descender == 0x00000692
-  XKc_Cyrillic_KA_vertstroke == 0x00000683
-  XK_Cyrillic_ka_vertstroke == 0x00000693
-  XKc_Cyrillic_EN_descender == 0x00000684
-  XK_Cyrillic_en_descender == 0x00000694
-  XKc_Cyrillic_U_straight == 0x00000685
-  XK_Cyrillic_u_straight == 0x00000695
-  XKc_Cyrillic_U_straight_bar == 0x00000686
-  XK_Cyrillic_u_straight_bar == 0x00000696
-  XKc_Cyrillic_HA_descender == 0x00000687
-  XK_Cyrillic_ha_descender == 0x00000697
-  XKc_Cyrillic_CHE_descender == 0x00000688
-  XK_Cyrillic_che_descender == 0x00000698
-  XKc_Cyrillic_CHE_vertstroke == 0x00000689
-  XK_Cyrillic_che_vertstroke == 0x00000699
-  XKc_Cyrillic_SHHA == 0x0000068A
-  XK_Cyrillic_shha == 0x0000069A
-  XKc_Cyrillic_SCHWA == 0x0000068C
-  XK_Cyrillic_schwa == 0x0000069C
-  XKc_Cyrillic_I_macron == 0x0000068D
-  XK_Cyrillic_i_macron == 0x0000069D
-  XKc_Cyrillic_O_bar == 0x0000068E
-  XK_Cyrillic_o_bar == 0x0000069E
-  XKc_Cyrillic_U_macron == 0x0000068F
-  XK_Cyrillic_u_macron == 0x0000069F
-  XK_Serbian_dje == 0x000006A1
-  XK_Macedonia_gje == 0x000006A2
-  XK_Cyrillic_io == 0x000006A3
-  XK_Ukrainian_ie == 0x000006A4
-  XK_Ukranian_je == 0x000006A4 # deprecated 
-  XK_Macedonia_dse == 0x000006A5
-  XK_Ukrainian_i == 0x000006A6
-  XK_Ukranian_i == 0x000006A6 # deprecated 
-  XK_Ukrainian_yi == 0x000006A7
-  XK_Ukranian_yi == 0x000006A7 # deprecated 
-  XK_Cyrillic_je == 0x000006A8
-  XK_Serbian_je == 0x000006A8 # deprecated 
-  XK_Cyrillic_lje == 0x000006A9
-  XK_Serbian_lje == 0x000006A9 # deprecated 
-  XK_Cyrillic_nje == 0x000006AA
-  XK_Serbian_nje == 0x000006AA # deprecated 
-  XK_Serbian_tshe == 0x000006AB
-  XK_Macedonia_kje == 0x000006AC
-  XK_Ukrainian_ghe_with_upturn == 0x000006AD
-  XK_Byelorussian_shortu == 0x000006AE
-  XK_Cyrillic_dzhe == 0x000006AF
-  XK_Serbian_dze == 0x000006AF # deprecated 
-  XK_numerosign == 0x000006B0
-  XKc_Serbian_DJE == 0x000006B1
-  XKc_Macedonia_GJE == 0x000006B2
-  XKc_Cyrillic_IO == 0x000006B3
-  XKc_Ukrainian_IE == 0x000006B4
-  XKc_Ukranian_JE == 0x000006B4 # deprecated 
-  XKc_Macedonia_DSE == 0x000006B5
-  XKc_Ukrainian_I == 0x000006B6
-  XKc_Ukranian_I == 0x000006B6 # deprecated 
-  XKc_Ukrainian_YI == 0x000006B7
-  XKc_Ukranian_YI == 0x000006B7 # deprecated 
-  XKc_Cyrillic_JE == 0x000006B8
-  XKc_Serbian_JE == 0x000006B8 # deprecated 
-  XKc_Cyrillic_LJE == 0x000006B9
-  XKc_Serbian_LJE == 0x000006B9 # deprecated 
-  XKc_Cyrillic_NJE == 0x000006BA
-  XKc_Serbian_NJE == 0x000006BA # deprecated 
-  XKc_Serbian_TSHE == 0x000006BB
-  XKc_Macedonia_KJE == 0x000006BC
-  XKc_Ukrainian_GHE_WITH_UPTURN == 0x000006BD
-  XKc_Byelorussian_SHORTU == 0x000006BE
-  XKc_Cyrillic_DZHE == 0x000006BF
-  XKc_Serbian_DZE == 0x000006BF # deprecated 
-  XK_Cyrillic_yu == 0x000006C0
-  XK_Cyrillic_a == 0x000006C1
-  XK_Cyrillic_be == 0x000006C2
-  XK_Cyrillic_tse == 0x000006C3
-  XK_Cyrillic_de == 0x000006C4
-  XK_Cyrillic_ie == 0x000006C5
-  XK_Cyrillic_ef == 0x000006C6
-  XK_Cyrillic_ghe == 0x000006C7
-  XK_Cyrillic_ha == 0x000006C8
-  XK_Cyrillic_i == 0x000006C9
-  XK_Cyrillic_shorti == 0x000006CA
-  XK_Cyrillic_ka == 0x000006CB
-  XK_Cyrillic_el == 0x000006CC
-  XK_Cyrillic_em == 0x000006CD
-  XK_Cyrillic_en == 0x000006CE
-  XK_Cyrillic_o == 0x000006CF
-  XK_Cyrillic_pe == 0x000006D0
-  XK_Cyrillic_ya == 0x000006D1
-  XK_Cyrillic_er == 0x000006D2
-  XK_Cyrillic_es == 0x000006D3
-  XK_Cyrillic_te == 0x000006D4
-  XK_Cyrillic_u == 0x000006D5
-  XK_Cyrillic_zhe == 0x000006D6
-  XK_Cyrillic_ve == 0x000006D7
-  XK_Cyrillic_softsign == 0x000006D8
-  XK_Cyrillic_yeru == 0x000006D9
-  XK_Cyrillic_ze == 0x000006DA
-  XK_Cyrillic_sha == 0x000006DB
-  XK_Cyrillic_e == 0x000006DC
-  XK_Cyrillic_shcha == 0x000006DD
-  XK_Cyrillic_che == 0x000006DE
-  XK_Cyrillic_hardsign == 0x000006DF
-  XKc_Cyrillic_YU == 0x000006E0
-  XKc_Cyrillic_A == 0x000006E1
-  XKc_Cyrillic_BE == 0x000006E2
-  XKc_Cyrillic_TSE == 0x000006E3
-  XKc_Cyrillic_DE == 0x000006E4
-  XKc_Cyrillic_IE == 0x000006E5
-  XKc_Cyrillic_EF == 0x000006E6
-  XKc_Cyrillic_GHE == 0x000006E7
-  XKc_Cyrillic_HA == 0x000006E8
-  XKc_Cyrillic_I == 0x000006E9
-  XKc_Cyrillic_SHORTI == 0x000006EA
-  XKc_Cyrillic_KA == 0x000006EB
-  XKc_Cyrillic_EL == 0x000006EC
-  XKc_Cyrillic_EM == 0x000006ED
-  XKc_Cyrillic_EN == 0x000006EE
-  XKc_Cyrillic_O == 0x000006EF
-  XKc_Cyrillic_PE == 0x000006F0
-  XKc_Cyrillic_YA == 0x000006F1
-  XKc_Cyrillic_ER == 0x000006F2
-  XKc_Cyrillic_ES == 0x000006F3
-  XKc_Cyrillic_TE == 0x000006F4
-  XKc_Cyrillic_U == 0x000006F5
-  XKc_Cyrillic_ZHE == 0x000006F6
-  XKc_Cyrillic_VE == 0x000006F7
-  XKc_Cyrillic_SOFTSIGN == 0x000006F8
-  XKc_Cyrillic_YERU == 0x000006F9
-  XKc_Cyrillic_ZE == 0x000006FA
-  XKc_Cyrillic_SHA == 0x000006FB
-  XKc_Cyrillic_E == 0x000006FC
-  XKc_Cyrillic_SHCHA == 0x000006FD
-  XKc_Cyrillic_CHE == 0x000006FE
-  XKc_Cyrillic_HARDSIGN == 0x000006FF
-# XK_CYRILLIC 
-#*
-# * Greek
-# * Byte 3 = 7
-# *
-
-when defined(XK_GREEK): 
-  XKc_Greek_ALPHAaccent == 0x000007A1
-  XKc_Greek_EPSILONaccent == 0x000007A2
-  XKc_Greek_ETAaccent == 0x000007A3
-  XKc_Greek_IOTAaccent == 0x000007A4
-  XKc_Greek_IOTAdieresis == 0x000007A5
-  XKc_Greek_IOTAdiaeresis == XKc_Greek_IOTAdieresis # old typo 
-  XKc_Greek_OMICRONaccent == 0x000007A7
-  XKc_Greek_UPSILONaccent == 0x000007A8
-  XKc_Greek_UPSILONdieresis == 0x000007A9
-  XKc_Greek_OMEGAaccent == 0x000007AB
-  XK_Greek_accentdieresis == 0x000007AE
-  XK_Greek_horizbar == 0x000007AF
-  XK_Greek_alphaaccent == 0x000007B1
-  XK_Greek_epsilonaccent == 0x000007B2
-  XK_Greek_etaaccent == 0x000007B3
-  XK_Greek_iotaaccent == 0x000007B4
-  XK_Greek_iotadieresis == 0x000007B5
-  XK_Greek_iotaaccentdieresis == 0x000007B6
-  XK_Greek_omicronaccent == 0x000007B7
-  XK_Greek_upsilonaccent == 0x000007B8
-  XK_Greek_upsilondieresis == 0x000007B9
-  XK_Greek_upsilonaccentdieresis == 0x000007BA
-  XK_Greek_omegaaccent == 0x000007BB
-  XKc_Greek_ALPHA == 0x000007C1
-  XKc_Greek_BETA == 0x000007C2
-  XKc_Greek_GAMMA == 0x000007C3
-  XKc_Greek_DELTA == 0x000007C4
-  XKc_Greek_EPSILON == 0x000007C5
-  XKc_Greek_ZETA == 0x000007C6
-  XKc_Greek_ETA == 0x000007C7
-  XKc_Greek_THETA == 0x000007C8
-  XKc_Greek_IOTA == 0x000007C9
-  XKc_Greek_KAPPA == 0x000007CA
-  XKc_Greek_LAMDA == 0x000007CB
-  XKc_Greek_LAMBDA == 0x000007CB
-  XKc_Greek_MU == 0x000007CC
-  XKc_Greek_NU == 0x000007CD
-  XKc_Greek_XI == 0x000007CE
-  XKc_Greek_OMICRON == 0x000007CF
-  XKc_Greek_PI == 0x000007D0
-  XKc_Greek_RHO == 0x000007D1
-  XKc_Greek_SIGMA == 0x000007D2
-  XKc_Greek_TAU == 0x000007D4
-  XKc_Greek_UPSILON == 0x000007D5
-  XKc_Greek_PHI == 0x000007D6
-  XKc_Greek_CHI == 0x000007D7
-  XKc_Greek_PSI == 0x000007D8
-  XKc_Greek_OMEGA == 0x000007D9
-  XK_Greek_alpha == 0x000007E1
-  XK_Greek_beta == 0x000007E2
-  XK_Greek_gamma == 0x000007E3
-  XK_Greek_delta == 0x000007E4
-  XK_Greek_epsilon == 0x000007E5
-  XK_Greek_zeta == 0x000007E6
-  XK_Greek_eta == 0x000007E7
-  XK_Greek_theta == 0x000007E8
-  XK_Greek_iota == 0x000007E9
-  XK_Greek_kappa == 0x000007EA
-  XK_Greek_lamda == 0x000007EB
-  XK_Greek_lambda == 0x000007EB
-  XK_Greek_mu == 0x000007EC
-  XK_Greek_nu == 0x000007ED
-  XK_Greek_xi == 0x000007EE
-  XK_Greek_omicron == 0x000007EF
-  XK_Greek_pi == 0x000007F0
-  XK_Greek_rho == 0x000007F1
-  XK_Greek_sigma == 0x000007F2
-  XK_Greek_finalsmallsigma == 0x000007F3
-  XK_Greek_tau == 0x000007F4
-  XK_Greek_upsilon == 0x000007F5
-  XK_Greek_phi == 0x000007F6
-  XK_Greek_chi == 0x000007F7
-  XK_Greek_psi == 0x000007F8
-  XK_Greek_omega == 0x000007F9
-  XK_Greek_switch == 0x0000FF7E # Alias for mode_switch 
-# XK_GREEK 
-#*
-# * Technical
-# * Byte 3 = 8
-# *
-
-when defined(XK_TECHNICAL): 
-  XK_leftradical == 0x000008A1
-  XK_topleftradical == 0x000008A2
-  XK_horizconnector == 0x000008A3
-  XK_topintegral == 0x000008A4
-  XK_botintegral == 0x000008A5
-  XK_vertconnector == 0x000008A6
-  XK_topleftsqbracket == 0x000008A7
-  XK_botleftsqbracket == 0x000008A8
-  XK_toprightsqbracket == 0x000008A9
-  XK_botrightsqbracket == 0x000008AA
-  XK_topleftparens == 0x000008AB
-  XK_botleftparens == 0x000008AC
-  XK_toprightparens == 0x000008AD
-  XK_botrightparens == 0x000008AE
-  XK_leftmiddlecurlybrace == 0x000008AF
-  XK_rightmiddlecurlybrace == 0x000008B0
-  XK_topleftsummation == 0x000008B1
-  XK_botleftsummation == 0x000008B2
-  XK_topvertsummationconnector == 0x000008B3
-  XK_botvertsummationconnector == 0x000008B4
-  XK_toprightsummation == 0x000008B5
-  XK_botrightsummation == 0x000008B6
-  XK_rightmiddlesummation == 0x000008B7
-  XK_lessthanequal == 0x000008BC
-  XK_notequal == 0x000008BD
-  XK_greaterthanequal == 0x000008BE
-  XK_integral == 0x000008BF
-  XK_therefore == 0x000008C0
-  XK_variation == 0x000008C1
-  XK_infinity == 0x000008C2
-  XK_nabla == 0x000008C5
-  XK_approximate == 0x000008C8
-  XK_similarequal == 0x000008C9
-  XK_ifonlyif == 0x000008CD
-  XK_implies == 0x000008CE
-  XK_identical == 0x000008CF
-  XK_radical == 0x000008D6
-  XK_includedin == 0x000008DA
-  XK_includes == 0x000008DB
-  XK_intersection == 0x000008DC
-  XK_union == 0x000008DD
-  XK_logicaland == 0x000008DE
-  XK_logicalor == 0x000008DF
-  XK_partialderivative == 0x000008EF
-  XK_function == 0x000008F6
-  XK_leftarrow == 0x000008FB
-  XK_uparrow == 0x000008FC
-  XK_rightarrow == 0x000008FD
-  XK_downarrow == 0x000008FE
-# XK_TECHNICAL 
-#*
-# *  Special
-# *  Byte 3 = 9
-# *
-
-when defined(XK_SPECIAL): 
-  XK_blank == 0x000009DF
-  XK_soliddiamond == 0x000009E0
-  XK_checkerboard == 0x000009E1
-  XK_ht == 0x000009E2
-  XK_ff == 0x000009E3
-  XK_cr == 0x000009E4
-  XK_lf == 0x000009E5
-  XK_nl == 0x000009E8
-  XK_vt == 0x000009E9
-  XK_lowrightcorner == 0x000009EA
-  XK_uprightcorner == 0x000009EB
-  XK_upleftcorner == 0x000009EC
-  XK_lowleftcorner == 0x000009ED
-  XK_crossinglines == 0x000009EE
-  XK_horizlinescan1 == 0x000009EF
-  XK_horizlinescan3 == 0x000009F0
-  XK_horizlinescan5 == 0x000009F1
-  XK_horizlinescan7 == 0x000009F2
-  XK_horizlinescan9 == 0x000009F3
-  XK_leftt == 0x000009F4
-  XK_rightt == 0x000009F5
-  XK_bott == 0x000009F6
-  XK_topt == 0x000009F7
-  XK_vertbar == 0x000009F8
-# XK_SPECIAL 
-#*
-# *  Publishing
-# *  Byte 3 = a
-# *
-
-when defined(XK_PUBLISHING): 
-  XK_emspace == 0x00000AA1
-  XK_enspace == 0x00000AA2
-  XK_em3space == 0x00000AA3
-  XK_em4space == 0x00000AA4
-  XK_digitspace == 0x00000AA5
-  XK_punctspace == 0x00000AA6
-  XK_thinspace == 0x00000AA7
-  XK_hairspace == 0x00000AA8
-  XK_emdash == 0x00000AA9
-  XK_endash == 0x00000AAA
-  XK_signifblank == 0x00000AAC
-  XK_ellipsis == 0x00000AAE
-  XK_doubbaselinedot == 0x00000AAF
-  XK_onethird == 0x00000AB0
-  XK_twothirds == 0x00000AB1
-  XK_onefifth == 0x00000AB2
-  XK_twofifths == 0x00000AB3
-  XK_threefifths == 0x00000AB4
-  XK_fourfifths == 0x00000AB5
-  XK_onesixth == 0x00000AB6
-  XK_fivesixths == 0x00000AB7
-  XK_careof == 0x00000AB8
-  XK_figdash == 0x00000ABB
-  XK_leftanglebracket == 0x00000ABC
-  XK_decimalpoint == 0x00000ABD
-  XK_rightanglebracket == 0x00000ABE
-  XK_marker == 0x00000ABF
-  XK_oneeighth == 0x00000AC3
-  XK_threeeighths == 0x00000AC4
-  XK_fiveeighths == 0x00000AC5
-  XK_seveneighths == 0x00000AC6
-  XK_trademark == 0x00000AC9
-  XK_signaturemark == 0x00000ACA
-  XK_trademarkincircle == 0x00000ACB
-  XK_leftopentriangle == 0x00000ACC
-  XK_rightopentriangle == 0x00000ACD
-  XK_emopencircle == 0x00000ACE
-  XK_emopenrectangle == 0x00000ACF
-  XK_leftsinglequotemark == 0x00000AD0
-  XK_rightsinglequotemark == 0x00000AD1
-  XK_leftdoublequotemark == 0x00000AD2
-  XK_rightdoublequotemark == 0x00000AD3
-  XK_prescription == 0x00000AD4
-  XK_minutes == 0x00000AD6
-  XK_seconds == 0x00000AD7
-  XK_latincross == 0x00000AD9
-  XK_hexagram == 0x00000ADA
-  XK_filledrectbullet == 0x00000ADB
-  XK_filledlefttribullet == 0x00000ADC
-  XK_filledrighttribullet == 0x00000ADD
-  XK_emfilledcircle == 0x00000ADE
-  XK_emfilledrect == 0x00000ADF
-  XK_enopencircbullet == 0x00000AE0
-  XK_enopensquarebullet == 0x00000AE1
-  XK_openrectbullet == 0x00000AE2
-  XK_opentribulletup == 0x00000AE3
-  XK_opentribulletdown == 0x00000AE4
-  XK_openstar == 0x00000AE5
-  XK_enfilledcircbullet == 0x00000AE6
-  XK_enfilledsqbullet == 0x00000AE7
-  XK_filledtribulletup == 0x00000AE8
-  XK_filledtribulletdown == 0x00000AE9
-  XK_leftpointer == 0x00000AEA
-  XK_rightpointer == 0x00000AEB
-  XK_club == 0x00000AEC
-  XK_diamond == 0x00000AED
-  XK_heart == 0x00000AEE
-  XK_maltesecross == 0x00000AF0
-  XK_dagger == 0x00000AF1
-  XK_doubledagger == 0x00000AF2
-  XK_checkmark == 0x00000AF3
-  XK_ballotcross == 0x00000AF4
-  XK_musicalsharp == 0x00000AF5
-  XK_musicalflat == 0x00000AF6
-  XK_malesymbol == 0x00000AF7
-  XK_femalesymbol == 0x00000AF8
-  XK_telephone == 0x00000AF9
-  XK_telephonerecorder == 0x00000AFA
-  XK_phonographcopyright == 0x00000AFB
-  XK_caret == 0x00000AFC
-  XK_singlelowquotemark == 0x00000AFD
-  XK_doublelowquotemark == 0x00000AFE
-  XK_cursor == 0x00000AFF
-# XK_PUBLISHING 
-#*
-# *  APL
-# *  Byte 3 = b
-# *
-
-when defined(XK_APL): 
-  XK_leftcaret == 0x00000BA3
-  XK_rightcaret == 0x00000BA6
-  XK_downcaret == 0x00000BA8
-  XK_upcaret == 0x00000BA9
-  XK_overbar == 0x00000BC0
-  XK_downtack == 0x00000BC2
-  XK_upshoe == 0x00000BC3
-  XK_downstile == 0x00000BC4
-  XK_underbar == 0x00000BC6
-  XK_jot == 0x00000BCA
-  XK_quad == 0x00000BCC
-  XK_uptack == 0x00000BCE
-  XK_circle == 0x00000BCF
-  XK_upstile == 0x00000BD3
-  XK_downshoe == 0x00000BD6
-  XK_rightshoe == 0x00000BD8
-  XK_leftshoe == 0x00000BDA
-  XK_lefttack == 0x00000BDC
-  XK_righttack == 0x00000BFC
-# XK_APL 
-#*
-# * Hebrew
-# * Byte 3 = c
-# *
-
-when defined(XK_HEBREW): 
-  XK_hebrew_doublelowline == 0x00000CDF
-  XK_hebrew_aleph == 0x00000CE0
-  XK_hebrew_bet == 0x00000CE1
-  XK_hebrew_beth == 0x00000CE1 # deprecated 
-  XK_hebrew_gimel == 0x00000CE2
-  XK_hebrew_gimmel == 0x00000CE2 # deprecated 
-  XK_hebrew_dalet == 0x00000CE3
-  XK_hebrew_daleth == 0x00000CE3 # deprecated 
-  XK_hebrew_he == 0x00000CE4
-  XK_hebrew_waw == 0x00000CE5
-  XK_hebrew_zain == 0x00000CE6
-  XK_hebrew_zayin == 0x00000CE6 # deprecated 
-  XK_hebrew_chet == 0x00000CE7
-  XK_hebrew_het == 0x00000CE7 # deprecated 
-  XK_hebrew_tet == 0x00000CE8
-  XK_hebrew_teth == 0x00000CE8 # deprecated 
-  XK_hebrew_yod == 0x00000CE9
-  XK_hebrew_finalkaph == 0x00000CEA
-  XK_hebrew_kaph == 0x00000CEB
-  XK_hebrew_lamed == 0x00000CEC
-  XK_hebrew_finalmem == 0x00000CED
-  XK_hebrew_mem == 0x00000CEE
-  XK_hebrew_finalnun == 0x00000CEF
-  XK_hebrew_nun == 0x00000CF0
-  XK_hebrew_samech == 0x00000CF1
-  XK_hebrew_samekh == 0x00000CF1 # deprecated 
-  XK_hebrew_ayin == 0x00000CF2
-  XK_hebrew_finalpe == 0x00000CF3
-  XK_hebrew_pe == 0x00000CF4
-  XK_hebrew_finalzade == 0x00000CF5
-  XK_hebrew_finalzadi == 0x00000CF5 # deprecated 
-  XK_hebrew_zade == 0x00000CF6
-  XK_hebrew_zadi == 0x00000CF6 # deprecated 
-  XK_hebrew_qoph == 0x00000CF7
-  XK_hebrew_kuf == 0x00000CF7 # deprecated 
-  XK_hebrew_resh == 0x00000CF8
-  XK_hebrew_shin == 0x00000CF9
-  XK_hebrew_taw == 0x00000CFA
-  XK_hebrew_taf == 0x00000CFA # deprecated 
-  XK_Hebrew_switch == 0x0000FF7E # Alias for mode_switch 
-# XK_HEBREW 
-#*
-# * Thai
-# * Byte 3 = d
-# *
-
-when defined(XK_THAI): 
-  XK_Thai_kokai == 0x00000DA1
-  XK_Thai_khokhai == 0x00000DA2
-  XK_Thai_khokhuat == 0x00000DA3
-  XK_Thai_khokhwai == 0x00000DA4
-  XK_Thai_khokhon == 0x00000DA5
-  XK_Thai_khorakhang == 0x00000DA6
-  XK_Thai_ngongu == 0x00000DA7
-  XK_Thai_chochan == 0x00000DA8
-  XK_Thai_choching == 0x00000DA9
-  XK_Thai_chochang == 0x00000DAA
-  XK_Thai_soso == 0x00000DAB
-  XK_Thai_chochoe == 0x00000DAC
-  XK_Thai_yoying == 0x00000DAD
-  XK_Thai_dochada == 0x00000DAE
-  XK_Thai_topatak == 0x00000DAF
-  XK_Thai_thothan == 0x00000DB0
-  XK_Thai_thonangmontho == 0x00000DB1
-  XK_Thai_thophuthao == 0x00000DB2
-  XK_Thai_nonen == 0x00000DB3
-  XK_Thai_dodek == 0x00000DB4
-  XK_Thai_totao == 0x00000DB5
-  XK_Thai_thothung == 0x00000DB6
-  XK_Thai_thothahan == 0x00000DB7
-  XK_Thai_thothong == 0x00000DB8
-  XK_Thai_nonu == 0x00000DB9
-  XK_Thai_bobaimai == 0x00000DBA
-  XK_Thai_popla == 0x00000DBB
-  XK_Thai_phophung == 0x00000DBC
-  XK_Thai_fofa == 0x00000DBD
-  XK_Thai_phophan == 0x00000DBE
-  XK_Thai_fofan == 0x00000DBF
-  XK_Thai_phosamphao == 0x00000DC0
-  XK_Thai_moma == 0x00000DC1
-  XK_Thai_yoyak == 0x00000DC2
-  XK_Thai_rorua == 0x00000DC3
-  XK_Thai_ru == 0x00000DC4
-  XK_Thai_loling == 0x00000DC5
-  XK_Thai_lu == 0x00000DC6
-  XK_Thai_wowaen == 0x00000DC7
-  XK_Thai_sosala == 0x00000DC8
-  XK_Thai_sorusi == 0x00000DC9
-  XK_Thai_sosua == 0x00000DCA
-  XK_Thai_hohip == 0x00000DCB
-  XK_Thai_lochula == 0x00000DCC
-  XK_Thai_oang == 0x00000DCD
-  XK_Thai_honokhuk == 0x00000DCE
-  XK_Thai_paiyannoi == 0x00000DCF
-  XK_Thai_saraa == 0x00000DD0
-  XK_Thai_maihanakat == 0x00000DD1
-  XK_Thai_saraaa == 0x00000DD2
-  XK_Thai_saraam == 0x00000DD3
-  XK_Thai_sarai == 0x00000DD4
-  XK_Thai_saraii == 0x00000DD5
-  XK_Thai_saraue == 0x00000DD6
-  XK_Thai_sarauee == 0x00000DD7
-  XK_Thai_sarau == 0x00000DD8
-  XK_Thai_sarauu == 0x00000DD9
-  XK_Thai_phinthu == 0x00000DDA
-  XK_Thai_maihanakat_maitho == 0x00000DDE
-  XK_Thai_baht == 0x00000DDF
-  XK_Thai_sarae == 0x00000DE0
-  XK_Thai_saraae == 0x00000DE1
-  XK_Thai_sarao == 0x00000DE2
-  XK_Thai_saraaimaimuan == 0x00000DE3
-  XK_Thai_saraaimaimalai == 0x00000DE4
-  XK_Thai_lakkhangyao == 0x00000DE5
-  XK_Thai_maiyamok == 0x00000DE6
-  XK_Thai_maitaikhu == 0x00000DE7
-  XK_Thai_maiek == 0x00000DE8
-  XK_Thai_maitho == 0x00000DE9
-  XK_Thai_maitri == 0x00000DEA
-  XK_Thai_maichattawa == 0x00000DEB
-  XK_Thai_thanthakhat == 0x00000DEC
-  XK_Thai_nikhahit == 0x00000DED
-  XK_Thai_leksun == 0x00000DF0
-  XK_Thai_leknung == 0x00000DF1
-  XK_Thai_leksong == 0x00000DF2
-  XK_Thai_leksam == 0x00000DF3
-  XK_Thai_leksi == 0x00000DF4
-  XK_Thai_lekha == 0x00000DF5
-  XK_Thai_lekhok == 0x00000DF6
-  XK_Thai_lekchet == 0x00000DF7
-  XK_Thai_lekpaet == 0x00000DF8
-  XK_Thai_lekkao == 0x00000DF9
-# XK_THAI 
-#*
-# *   Korean
-# *   Byte 3 = e
-# *
-
-when defined(XK_KOREAN): 
-  XK_Hangul == 0x0000FF31     # Hangul start/stop(toggle) 
-  XK_Hangul_Start == 0x0000FF32 # Hangul start 
-  XK_Hangul_End == 0x0000FF33 # Hangul end, English start 
-  XK_Hangul_Hanja == 0x0000FF34 # Start Hangul->Hanja Conversion 
-  XK_Hangul_Jamo == 0x0000FF35 # Hangul Jamo mode 
-  XK_Hangul_Romaja == 0x0000FF36 # Hangul Romaja mode 
-  XK_Hangul_Codeinput == 0x0000FF37 # Hangul code input mode 
-  XK_Hangul_Jeonja == 0x0000FF38 # Jeonja mode 
-  XK_Hangul_Banja == 0x0000FF39 # Banja mode 
-  XK_Hangul_PreHanja == 0x0000FF3A # Pre Hanja conversion 
-  XK_Hangul_PostHanja == 0x0000FF3B # Post Hanja conversion 
-  XK_Hangul_SingleCandidate == 0x0000FF3C # Single candidate 
-  XK_Hangul_MultipleCandidate == 0x0000FF3D # Multiple candidate 
-  XK_Hangul_PreviousCandidate == 0x0000FF3E # Previous candidate 
-  XK_Hangul_Special == 0x0000FF3F # Special symbols 
-  XK_Hangul_switch == 0x0000FF7E # Alias for mode_switch 
-                                 # Hangul Consonant Characters 
-  XK_Hangul_Kiyeog == 0x00000EA1
-  XK_Hangul_SsangKiyeog == 0x00000EA2
-  XK_Hangul_KiyeogSios == 0x00000EA3
-  XK_Hangul_Nieun == 0x00000EA4
-  XK_Hangul_NieunJieuj == 0x00000EA5
-  XK_Hangul_NieunHieuh == 0x00000EA6
-  XK_Hangul_Dikeud == 0x00000EA7
-  XK_Hangul_SsangDikeud == 0x00000EA8
-  XK_Hangul_Rieul == 0x00000EA9
-  XK_Hangul_RieulKiyeog == 0x00000EAA
-  XK_Hangul_RieulMieum == 0x00000EAB
-  XK_Hangul_RieulPieub == 0x00000EAC
-  XK_Hangul_RieulSios == 0x00000EAD
-  XK_Hangul_RieulTieut == 0x00000EAE
-  XK_Hangul_RieulPhieuf == 0x00000EAF
-  XK_Hangul_RieulHieuh == 0x00000EB0
-  XK_Hangul_Mieum == 0x00000EB1
-  XK_Hangul_Pieub == 0x00000EB2
-  XK_Hangul_SsangPieub == 0x00000EB3
-  XK_Hangul_PieubSios == 0x00000EB4
-  XK_Hangul_Sios == 0x00000EB5
-  XK_Hangul_SsangSios == 0x00000EB6
-  XK_Hangul_Ieung == 0x00000EB7
-  XK_Hangul_Jieuj == 0x00000EB8
-  XK_Hangul_SsangJieuj == 0x00000EB9
-  XK_Hangul_Cieuc == 0x00000EBA
-  XK_Hangul_Khieuq == 0x00000EBB
-  XK_Hangul_Tieut == 0x00000EBC
-  XK_Hangul_Phieuf == 0x00000EBD
-  XK_Hangul_Hieuh == 0x00000EBE # Hangul Vowel Characters 
-  XK_Hangul_A == 0x00000EBF
-  XK_Hangul_AE == 0x00000EC0
-  XK_Hangul_YA == 0x00000EC1
-  XK_Hangul_YAE == 0x00000EC2
-  XK_Hangul_EO == 0x00000EC3
-  XK_Hangul_E == 0x00000EC4
-  XK_Hangul_YEO == 0x00000EC5
-  XK_Hangul_YE == 0x00000EC6
-  XK_Hangul_O == 0x00000EC7
-  XK_Hangul_WA == 0x00000EC8
-  XK_Hangul_WAE == 0x00000EC9
-  XK_Hangul_OE == 0x00000ECA
-  XK_Hangul_YO == 0x00000ECB
-  XK_Hangul_U == 0x00000ECC
-  XK_Hangul_WEO == 0x00000ECD
-  XK_Hangul_WE == 0x00000ECE
-  XK_Hangul_WI == 0x00000ECF
-  XK_Hangul_YU == 0x00000ED0
-  XK_Hangul_EU == 0x00000ED1
-  XK_Hangul_YI == 0x00000ED2
-  XK_Hangul_I == 0x00000ED3   # Hangul syllable-final (JongSeong) Characters 
-  XK_Hangul_J_Kiyeog == 0x00000ED4
-  XK_Hangul_J_SsangKiyeog == 0x00000ED5
-  XK_Hangul_J_KiyeogSios == 0x00000ED6
-  XK_Hangul_J_Nieun == 0x00000ED7
-  XK_Hangul_J_NieunJieuj == 0x00000ED8
-  XK_Hangul_J_NieunHieuh == 0x00000ED9
-  XK_Hangul_J_Dikeud == 0x00000EDA
-  XK_Hangul_J_Rieul == 0x00000EDB
-  XK_Hangul_J_RieulKiyeog == 0x00000EDC
-  XK_Hangul_J_RieulMieum == 0x00000EDD
-  XK_Hangul_J_RieulPieub == 0x00000EDE
-  XK_Hangul_J_RieulSios == 0x00000EDF
-  XK_Hangul_J_RieulTieut == 0x00000EE0
-  XK_Hangul_J_RieulPhieuf == 0x00000EE1
-  XK_Hangul_J_RieulHieuh == 0x00000EE2
-  XK_Hangul_J_Mieum == 0x00000EE3
-  XK_Hangul_J_Pieub == 0x00000EE4
-  XK_Hangul_J_PieubSios == 0x00000EE5
-  XK_Hangul_J_Sios == 0x00000EE6
-  XK_Hangul_J_SsangSios == 0x00000EE7
-  XK_Hangul_J_Ieung == 0x00000EE8
-  XK_Hangul_J_Jieuj == 0x00000EE9
-  XK_Hangul_J_Cieuc == 0x00000EEA
-  XK_Hangul_J_Khieuq == 0x00000EEB
-  XK_Hangul_J_Tieut == 0x00000EEC
-  XK_Hangul_J_Phieuf == 0x00000EED
-  XK_Hangul_J_Hieuh == 0x00000EEE # Ancient Hangul Consonant Characters 
-  XK_Hangul_RieulYeorinHieuh == 0x00000EEF
-  XK_Hangul_SunkyeongeumMieum == 0x00000EF0
-  XK_Hangul_SunkyeongeumPieub == 0x00000EF1
-  XK_Hangul_PanSios == 0x00000EF2
-  XK_Hangul_KkogjiDalrinIeung == 0x00000EF3
-  XK_Hangul_SunkyeongeumPhieuf == 0x00000EF4
-  XK_Hangul_YeorinHieuh == 0x00000EF5 # Ancient Hangul Vowel Characters 
-  XK_Hangul_AraeA == 0x00000EF6
-  XK_Hangul_AraeAE == 0x00000EF7 # Ancient Hangul syllable-final (JongSeong) Characters 
-  XK_Hangul_J_PanSios == 0x00000EF8
-  XK_Hangul_J_KkogjiDalrinIeung == 0x00000EF9
-  XK_Hangul_J_YeorinHieuh == 0x00000EFA # Korean currency symbol 
-  XK_Korean_Won == 0x00000EFF
-# XK_KOREAN 
-#*
-# *   Armenian
-# *   Byte 3 = = $14
-# *
-
-when defined(XK_ARMENIAN): 
-  XK_Armenian_eternity == 0x000014A1
-  XK_Armenian_ligature_ew == 0x000014A2
-  XK_Armenian_full_stop == 0x000014A3
-  XK_Armenian_verjaket == 0x000014A3
-  XK_Armenian_parenright == 0x000014A4
-  XK_Armenian_parenleft == 0x000014A5
-  XK_Armenian_guillemotright == 0x000014A6
-  XK_Armenian_guillemotleft == 0x000014A7
-  XK_Armenian_em_dash == 0x000014A8
-  XK_Armenian_dot == 0x000014A9
-  XK_Armenian_mijaket == 0x000014A9
-  XK_Armenian_separation_mark == 0x000014AA
-  XK_Armenian_but == 0x000014AA
-  XK_Armenian_comma == 0x000014AB
-  XK_Armenian_en_dash == 0x000014AC
-  XK_Armenian_hyphen == 0x000014AD
-  XK_Armenian_yentamna == 0x000014AD
-  XK_Armenian_ellipsis == 0x000014AE
-  XK_Armenian_exclam == 0x000014AF
-  XK_Armenian_amanak == 0x000014AF
-  XK_Armenian_accent == 0x000014B0
-  XK_Armenian_shesht == 0x000014B0
-  XK_Armenian_question == 0x000014B1
-  XK_Armenian_paruyk == 0x000014B1
-  XKc_Armenian_AYB == 0x000014B2
-  XK_Armenian_ayb == 0x000014B3
-  XKc_Armenian_BEN == 0x000014B4
-  XK_Armenian_ben == 0x000014B5
-  XKc_Armenian_GIM == 0x000014B6
-  XK_Armenian_gim == 0x000014B7
-  XKc_Armenian_DA == 0x000014B8
-  XK_Armenian_da == 0x000014B9
-  XKc_Armenian_YECH == 0x000014BA
-  XK_Armenian_yech == 0x000014BB
-  XKc_Armenian_ZA == 0x000014BC
-  XK_Armenian_za == 0x000014BD
-  XKc_Armenian_E == 0x000014BE
-  XK_Armenian_e == 0x000014BF
-  XKc_Armenian_AT == 0x000014C0
-  XK_Armenian_at == 0x000014C1
-  XKc_Armenian_TO == 0x000014C2
-  XK_Armenian_to == 0x000014C3
-  XKc_Armenian_ZHE == 0x000014C4
-  XK_Armenian_zhe == 0x000014C5
-  XKc_Armenian_INI == 0x000014C6
-  XK_Armenian_ini == 0x000014C7
-  XKc_Armenian_LYUN == 0x000014C8
-  XK_Armenian_lyun == 0x000014C9
-  XKc_Armenian_KHE == 0x000014CA
-  XK_Armenian_khe == 0x000014CB
-  XKc_Armenian_TSA == 0x000014CC
-  XK_Armenian_tsa == 0x000014CD
-  XKc_Armenian_KEN == 0x000014CE
-  XK_Armenian_ken == 0x000014CF
-  XKc_Armenian_HO == 0x000014D0
-  XK_Armenian_ho == 0x000014D1
-  XKc_Armenian_DZA == 0x000014D2
-  XK_Armenian_dza == 0x000014D3
-  XKc_Armenian_GHAT == 0x000014D4
-  XK_Armenian_ghat == 0x000014D5
-  XKc_Armenian_TCHE == 0x000014D6
-  XK_Armenian_tche == 0x000014D7
-  XKc_Armenian_MEN == 0x000014D8
-  XK_Armenian_men == 0x000014D9
-  XKc_Armenian_HI == 0x000014DA
-  XK_Armenian_hi == 0x000014DB
-  XKc_Armenian_NU == 0x000014DC
-  XK_Armenian_nu == 0x000014DD
-  XKc_Armenian_SHA == 0x000014DE
-  XK_Armenian_sha == 0x000014DF
-  XKc_Armenian_VO == 0x000014E0
-  XK_Armenian_vo == 0x000014E1
-  XKc_Armenian_CHA == 0x000014E2
-  XK_Armenian_cha == 0x000014E3
-  XKc_Armenian_PE == 0x000014E4
-  XK_Armenian_pe == 0x000014E5
-  XKc_Armenian_JE == 0x000014E6
-  XK_Armenian_je == 0x000014E7
-  XKc_Armenian_RA == 0x000014E8
-  XK_Armenian_ra == 0x000014E9
-  XKc_Armenian_SE == 0x000014EA
-  XK_Armenian_se == 0x000014EB
-  XKc_Armenian_VEV == 0x000014EC
-  XK_Armenian_vev == 0x000014ED
-  XKc_Armenian_TYUN == 0x000014EE
-  XK_Armenian_tyun == 0x000014EF
-  XKc_Armenian_RE == 0x000014F0
-  XK_Armenian_re == 0x000014F1
-  XKc_Armenian_TSO == 0x000014F2
-  XK_Armenian_tso == 0x000014F3
-  XKc_Armenian_VYUN == 0x000014F4
-  XK_Armenian_vyun == 0x000014F5
-  XKc_Armenian_PYUR == 0x000014F6
-  XK_Armenian_pyur == 0x000014F7
-  XKc_Armenian_KE == 0x000014F8
-  XK_Armenian_ke == 0x000014F9
-  XKc_Armenian_O == 0x000014FA
-  XK_Armenian_o == 0x000014FB
-  XKc_Armenian_FE == 0x000014FC
-  XK_Armenian_fe == 0x000014FD
-  XK_Armenian_apostrophe == 0x000014FE
-  XK_Armenian_section_sign == 0x000014FF
-# XK_ARMENIAN 
-#*
-# *   Georgian
-# *   Byte 3 = = $15
-# *
-
-when defined(XK_GEORGIAN): 
-  XK_Georgian_an == 0x000015D0
-  XK_Georgian_ban == 0x000015D1
-  XK_Georgian_gan == 0x000015D2
-  XK_Georgian_don == 0x000015D3
-  XK_Georgian_en == 0x000015D4
-  XK_Georgian_vin == 0x000015D5
-  XK_Georgian_zen == 0x000015D6
-  XK_Georgian_tan == 0x000015D7
-  XK_Georgian_in == 0x000015D8
-  XK_Georgian_kan == 0x000015D9
-  XK_Georgian_las == 0x000015DA
-  XK_Georgian_man == 0x000015DB
-  XK_Georgian_nar == 0x000015DC
-  XK_Georgian_on == 0x000015DD
-  XK_Georgian_par == 0x000015DE
-  XK_Georgian_zhar == 0x000015DF
-  XK_Georgian_rae == 0x000015E0
-  XK_Georgian_san == 0x000015E1
-  XK_Georgian_tar == 0x000015E2
-  XK_Georgian_un == 0x000015E3
-  XK_Georgian_phar == 0x000015E4
-  XK_Georgian_khar == 0x000015E5
-  XK_Georgian_ghan == 0x000015E6
-  XK_Georgian_qar == 0x000015E7
-  XK_Georgian_shin == 0x000015E8
-  XK_Georgian_chin == 0x000015E9
-  XK_Georgian_can == 0x000015EA
-  XK_Georgian_jil == 0x000015EB
-  XK_Georgian_cil == 0x000015EC
-  XK_Georgian_char == 0x000015ED
-  XK_Georgian_xan == 0x000015EE
-  XK_Georgian_jhan == 0x000015EF
-  XK_Georgian_hae == 0x000015F0
-  XK_Georgian_he == 0x000015F1
-  XK_Georgian_hie == 0x000015F2
-  XK_Georgian_we == 0x000015F3
-  XK_Georgian_har == 0x000015F4
-  XK_Georgian_hoe == 0x000015F5
-  XK_Georgian_fi == 0x000015F6
-# XK_GEORGIAN 
-#*
-# * Azeri (and other Turkic or Caucasian languages of ex-USSR)
-# * Byte 3 = = $16
-# *
-
-when defined(XK_CAUCASUS): 
-  # latin 
-  XKc_Ccedillaabovedot == 0x000016A2
-  XKc_Xabovedot == 0x000016A3
-  XKc_Qabovedot == 0x000016A5
-  XKc_Ibreve == 0x000016A6
-  XKc_IE == 0x000016A7
-  XKc_UO == 0x000016A8
-  XKc_Zstroke == 0x000016A9
-  XKc_Gcaron == 0x000016AA
-  XKc_Obarred == 0x000016AF
-  XK_ccedillaabovedot == 0x000016B2
-  XK_xabovedot == 0x000016B3
-  XKc_Ocaron == 0x000016B4
-  XK_qabovedot == 0x000016B5
-  XK_ibreve == 0x000016B6
-  XK_ie == 0x000016B7
-  XK_uo == 0x000016B8
-  XK_zstroke == 0x000016B9
-  XK_gcaron == 0x000016BA
-  XK_ocaron == 0x000016BD
-  XK_obarred == 0x000016BF
-  XKc_SCHWA == 0x000016C6
-  XK_schwa == 0x000016F6 # those are not really Caucasus, but I put them here for now 
-                         # For Inupiak 
-  XKc_Lbelowdot == 0x000016D1
-  XKc_Lstrokebelowdot == 0x000016D2
-  XK_lbelowdot == 0x000016E1
-  XK_lstrokebelowdot == 0x000016E2 # For Guarani 
-  XKc_Gtilde == 0x000016D3
-  XK_gtilde == 0x000016E3
-# XK_CAUCASUS 
-#*
-# *   Vietnamese
-# *   Byte 3 = = $1e
-# *
-
-when defined(XK_VIETNAMESE): 
-  XKc_Abelowdot == 0x00001EA0
-  XK_abelowdot == 0x00001EA1
-  XKc_Ahook == 0x00001EA2
-  XK_ahook == 0x00001EA3
-  XKc_Acircumflexacute == 0x00001EA4
-  XK_acircumflexacute == 0x00001EA5
-  XKc_Acircumflexgrave == 0x00001EA6
-  XK_acircumflexgrave == 0x00001EA7
-  XKc_Acircumflexhook == 0x00001EA8
-  XK_acircumflexhook == 0x00001EA9
-  XKc_Acircumflextilde == 0x00001EAA
-  XK_acircumflextilde == 0x00001EAB
-  XKc_Acircumflexbelowdot == 0x00001EAC
-  XK_acircumflexbelowdot == 0x00001EAD
-  XKc_Abreveacute == 0x00001EAE
-  XK_abreveacute == 0x00001EAF
-  XKc_Abrevegrave == 0x00001EB0
-  XK_abrevegrave == 0x00001EB1
-  XKc_Abrevehook == 0x00001EB2
-  XK_abrevehook == 0x00001EB3
-  XKc_Abrevetilde == 0x00001EB4
-  XK_abrevetilde == 0x00001EB5
-  XKc_Abrevebelowdot == 0x00001EB6
-  XK_abrevebelowdot == 0x00001EB7
-  XKc_Ebelowdot == 0x00001EB8
-  XK_ebelowdot == 0x00001EB9
-  XKc_Ehook == 0x00001EBA
-  XK_ehook == 0x00001EBB
-  XKc_Etilde == 0x00001EBC
-  XK_etilde == 0x00001EBD
-  XKc_Ecircumflexacute == 0x00001EBE
-  XK_ecircumflexacute == 0x00001EBF
-  XKc_Ecircumflexgrave == 0x00001EC0
-  XK_ecircumflexgrave == 0x00001EC1
-  XKc_Ecircumflexhook == 0x00001EC2
-  XK_ecircumflexhook == 0x00001EC3
-  XKc_Ecircumflextilde == 0x00001EC4
-  XK_ecircumflextilde == 0x00001EC5
-  XKc_Ecircumflexbelowdot == 0x00001EC6
-  XK_ecircumflexbelowdot == 0x00001EC7
-  XKc_Ihook == 0x00001EC8
-  XK_ihook == 0x00001EC9
-  XKc_Ibelowdot == 0x00001ECA
-  XK_ibelowdot == 0x00001ECB
-  XKc_Obelowdot == 0x00001ECC
-  XK_obelowdot == 0x00001ECD
-  XKc_Ohook == 0x00001ECE
-  XK_ohook == 0x00001ECF
-  XKc_Ocircumflexacute == 0x00001ED0
-  XK_ocircumflexacute == 0x00001ED1
-  XKc_Ocircumflexgrave == 0x00001ED2
-  XK_ocircumflexgrave == 0x00001ED3
-  XKc_Ocircumflexhook == 0x00001ED4
-  XK_ocircumflexhook == 0x00001ED5
-  XKc_Ocircumflextilde == 0x00001ED6
-  XK_ocircumflextilde == 0x00001ED7
-  XKc_Ocircumflexbelowdot == 0x00001ED8
-  XK_ocircumflexbelowdot == 0x00001ED9
-  XKc_Ohornacute == 0x00001EDA
-  XK_ohornacute == 0x00001EDB
-  XKc_Ohorngrave == 0x00001EDC
-  XK_ohorngrave == 0x00001EDD
-  XKc_Ohornhook == 0x00001EDE
-  XK_ohornhook == 0x00001EDF
-  XKc_Ohorntilde == 0x00001EE0
-  XK_ohorntilde == 0x00001EE1
-  XKc_Ohornbelowdot == 0x00001EE2
-  XK_ohornbelowdot == 0x00001EE3
-  XKc_Ubelowdot == 0x00001EE4
-  XK_ubelowdot == 0x00001EE5
-  XKc_Uhook == 0x00001EE6
-  XK_uhook == 0x00001EE7
-  XKc_Uhornacute == 0x00001EE8
-  XK_uhornacute == 0x00001EE9
-  XKc_Uhorngrave == 0x00001EEA
-  XK_uhorngrave == 0x00001EEB
-  XKc_Uhornhook == 0x00001EEC
-  XK_uhornhook == 0x00001EED
-  XKc_Uhorntilde == 0x00001EEE
-  XK_uhorntilde == 0x00001EEF
-  XKc_Uhornbelowdot == 0x00001EF0
-  XK_uhornbelowdot == 0x00001EF1
-  XKc_Ybelowdot == 0x00001EF4
-  XK_ybelowdot == 0x00001EF5
-  XKc_Yhook == 0x00001EF6
-  XK_yhook == 0x00001EF7
-  XKc_Ytilde == 0x00001EF8
-  XK_ytilde == 0x00001EF9
-  XKc_Ohorn == 0x00001EFA     # U+01a0 
-  XK_ohorn == 0x00001EFB      # U+01a1 
-  XKc_Uhorn == 0x00001EFC     # U+01af 
-  XK_uhorn == 0x00001EFD      # U+01b0 
-  XK_combining_tilde == 0x00001E9F # U+0303 
-  XK_combining_grave == 0x00001EF2 # U+0300 
-  XK_combining_acute == 0x00001EF3 # U+0301 
-  XK_combining_hook == 0x00001EFE # U+0309 
-  XK_combining_belowdot == 0x00001EFF # U+0323 
-# XK_VIETNAMESE 
-
-when defined(XK_CURRENCY): 
-  XK_EcuSign == 0x000020A0
-  XK_ColonSign == 0x000020A1
-  XK_CruzeiroSign == 0x000020A2
-  XK_FFrancSign == 0x000020A3
-  XK_LiraSign == 0x000020A4
-  XK_MillSign == 0x000020A5
-  XK_NairaSign == 0x000020A6
-  XK_PesetaSign == 0x000020A7
-  XK_RupeeSign == 0x000020A8
-  XK_WonSign == 0x000020A9
-  XK_NewSheqelSign == 0x000020AA
-  XK_DongSign == 0x000020AB
-  XK_EuroSign == 0x000020AC
-# implementation
diff --git a/lib/contnrs.nim b/lib/contnrs.nim
deleted file mode 100644
index fa993e104..000000000
--- a/lib/contnrs.nim
+++ /dev/null
@@ -1,11 +0,0 @@
-# Container library for Nimrod
-
-# Data structures for now:
-# TTable, TSet, TList
-# Algorithms: Trees, hashing,
-
-TTable[key, val, [Algorithm]]
-
-macro TTable(n: typeexpr): typeexpr =
-
-
diff --git a/lib/dlmalloc.c b/lib/dlmalloc.c
deleted file mode 100644
index 2a8b299a1..000000000
--- a/lib/dlmalloc.c
+++ /dev/null
@@ -1,5076 +0,0 @@
-
-#define USE_DL_PREFIX
-#define ASSEMBLY_VERSION
-
-/*
-#define FOOTERS 1
-#define DEBUG 1
-
-#define ABORT_ON_ASSERT_FAILURE 0
-*/
-
-#define ABORT do { /*printf("abort was called\n");*/ abort(); } while (0)
-
-/*
-  This is a version (aka dlmalloc) of malloc/free/realloc written by
-  Doug Lea and released to the public domain, as explained at
-  http://creativecommons.org/licenses/publicdomain.  Send questions,
-  comments, complaints, performance data, etc to dl@cs.oswego.edu
-
-* Version 2.8.3 Thu Sep 22 11:16:15 2005  Doug Lea  (dl at gee)
-
-   Note: There may be an updated version of this malloc obtainable at
-           ftp://gee.cs.oswego.edu/pub/misc/malloc.c
-         Check before installing!
-
-* Quickstart
-
-  This library is all in one file to simplify the most common usage:
-  ftp it, compile it (-O3), and link it into another program. All of
-  the compile-time options default to reasonable values for use on
-  most platforms.  You might later want to step through various
-  compile-time and dynamic tuning options.
-
-  For convenience, an include file for code using this malloc is at:
-     ftp://gee.cs.oswego.edu/pub/misc/malloc-2.8.3.h
-  You don't really need this .h file unless you call functions not
-  defined in your system include files.  The .h file contains only the
-  excerpts from this file needed for using this malloc on ANSI C/C++
-  systems, so long as you haven't changed compile-time options about
-  naming and tuning parameters.  If you do, then you can create your
-  own malloc.h that does include all settings by cutting at the point
-  indicated below. Note that you may already by default be using a C
-  library containing a malloc that is based on some version of this
-  malloc (for example in linux). You might still want to use the one
-  in this file to customize settings or to avoid overheads associated
-  with library versions.
-
-* Vital statistics:
-
-  Supported pointer/size_t representation:       4 or 8 bytes
-       size_t MUST be an unsigned type of the same width as
-       pointers. (If you are using an ancient system that declares
-       size_t as a signed type, or need it to be a different width
-       than pointers, you can use a previous release of this malloc
-       (e.g. 2.7.2) supporting these.)
-
-  Alignment:                                     8 bytes (default)
-       This suffices for nearly all current machines and C compilers.
-       However, you can define MALLOC_ALIGNMENT to be wider than this
-       if necessary (up to 128bytes), at the expense of using more space.
-
-  Minimum overhead per allocated chunk:   4 or  8 bytes (if 4byte sizes)
-                                          8 or 16 bytes (if 8byte sizes)
-       Each malloced chunk has a hidden word of overhead holding size
-       and status information, and additional cross-check word
-       if FOOTERS is defined.
-
-  Minimum allocated size: 4-byte ptrs:  16 bytes    (including overhead)
-                          8-byte ptrs:  32 bytes    (including overhead)
-
-       Even a request for zero bytes (i.e., malloc(0)) returns a
-       pointer to something of the minimum allocatable size.
-       The maximum overhead wastage (i.e., number of extra bytes
-       allocated than were requested in malloc) is less than or equal
-       to the minimum size, except for requests >= mmap_threshold that
-       are serviced via mmap(), where the worst case wastage is about
-       32 bytes plus the remainder from a system page (the minimal
-       mmap unit); typically 4096 or 8192 bytes.
-
-  Security: static-safe; optionally more or less
-       The "security" of malloc refers to the ability of malicious
-       code to accentuate the effects of errors (for example, freeing
-       space that is not currently malloc'ed or overwriting past the
-       ends of chunks) in code that calls malloc.  This malloc
-       guarantees not to modify any memory locations below the base of
-       heap, i.e., static variables, even in the presence of usage
-       errors.  The routines additionally detect most improper frees
-       and reallocs.  All this holds as long as the static bookkeeping
-       for malloc itself is not corrupted by some other means.  This
-       is only one aspect of security -- these checks do not, and
-       cannot, detect all possible programming errors.
-
-       If FOOTERS is defined nonzero, then each allocated chunk
-       carries an additional check word to verify that it was malloced
-       from its space.  These check words are the same within each
-       execution of a program using malloc, but differ across
-       executions, so externally crafted fake chunks cannot be
-       freed. This improves security by rejecting frees/reallocs that
-       could corrupt heap memory, in addition to the checks preventing
-       writes to statics that are always on.  This may further improve
-       security at the expense of time and space overhead.  (Note that
-       FOOTERS may also be worth using with MSPACES.)
-
-       By default detected errors cause the program to abort (calling
-       "abort()"). You can override this to instead proceed past
-       errors by defining PROCEED_ON_ERROR.  In this case, a bad free
-       has no effect, and a malloc that encounters a bad address
-       caused by user overwrites will ignore the bad address by
-       dropping pointers and indices to all known memory. This may
-       be appropriate for programs that should continue if at all
-       possible in the face of programming errors, although they may
-       run out of memory because dropped memory is never reclaimed.
-
-       If you don't like either of these options, you can define
-       CORRUPTION_ERROR_ACTION and USAGE_ERROR_ACTION to do anything
-       else. And if if you are sure that your program using malloc has
-       no errors or vulnerabilities, you can define INSECURE to 1,
-       which might (or might not) provide a small performance improvement.
-
-  Thread-safety: NOT thread-safe unless USE_LOCKS defined
-       When USE_LOCKS is defined, each public call to malloc, free,
-       etc is surrounded with either a pthread mutex or a win32
-       spinlock (depending on WIN32). This is not especially fast, and
-       can be a major bottleneck.  It is designed only to provide
-       minimal protection in concurrent environments, and to provide a
-       basis for extensions.  If you are using malloc in a concurrent
-       program, consider instead using ptmalloc, which is derived from
-       a version of this malloc. (See http://www.malloc.de).
-
-  System requirements: Any combination of MORECORE and/or MMAP/MUNMAP
-       This malloc can use unix sbrk or any emulation (invoked using
-       the CALL_MORECORE macro) and/or mmap/munmap or any emulation
-       (invoked using CALL_MMAP/CALL_MUNMAP) to get and release system
-       memory.  On most unix systems, it tends to work best if both
-       MORECORE and MMAP are enabled.  On Win32, it uses emulations
-       based on VirtualAlloc. It also uses common C library functions
-       like memset.
-
-  Compliance: I believe it is compliant with the Single Unix Specification
-       (See http://www.unix.org). Also SVID/XPG, ANSI C, and probably
-       others as well.
-
-* Overview of algorithms
-
-  This is not the fastest, most space-conserving, most portable, or
-  most tunable malloc ever written. However it is among the fastest
-  while also being among the most space-conserving, portable and
-  tunable.  Consistent balance across these factors results in a good
-  general-purpose allocator for malloc-intensive programs.
-
-  In most ways, this malloc is a best-fit allocator. Generally, it
-  chooses the best-fitting existing chunk for a request, with ties
-  broken in approximately least-recently-used order. (This strategy
-  normally maintains low fragmentation.) However, for requests less
-  than 256bytes, it deviates from best-fit when there is not an
-  exactly fitting available chunk by preferring to use space adjacent
-  to that used for the previous small request, as well as by breaking
-  ties in approximately most-recently-used order. (These enhance
-  locality of series of small allocations.)  And for very large requests
-  (>= 256Kb by default), it relies on system memory mapping
-  facilities, if supported.  (This helps avoid carrying around and
-  possibly fragmenting memory used only for large chunks.)
-
-  All operations (except malloc_stats and mallinfo) have execution
-  times that are bounded by a constant factor of the number of bits in
-  a size_t, not counting any clearing in calloc or copying in realloc,
-  or actions surrounding MORECORE and MMAP that have times
-  proportional to the number of non-contiguous regions returned by
-  system allocation routines, which is often just 1.
-
-  The implementation is not very modular and seriously overuses
-  macros. Perhaps someday all C compilers will do as good a job
-  inlining modular code as can now be done by brute-force expansion,
-  but now, enough of them seem not to.
-
-  Some compilers issue a lot of warnings about code that is
-  dead/unreachable only on some platforms, and also about intentional
-  uses of negation on unsigned types. All known cases of each can be
-  ignored.
-
-  For a longer but out of date high-level description, see
-     http://gee.cs.oswego.edu/dl/html/malloc.html
-
-* MSPACES
-  If MSPACES is defined, then in addition to malloc, free, etc.,
-  this file also defines mspace_malloc, mspace_free, etc. These
-  are versions of malloc routines that take an "mspace" argument
-  obtained using create_mspace, to control all internal bookkeeping.
-  If ONLY_MSPACES is defined, only these versions are compiled.
-  So if you would like to use this allocator for only some allocations,
-  and your system malloc for others, you can compile with
-  ONLY_MSPACES and then do something like...
-    static mspace mymspace = create_mspace(0,0); // for example
-    #define mymalloc(bytes)  mspace_malloc(mymspace, bytes)
-
-  (Note: If you only need one instance of an mspace, you can instead
-  use "USE_DL_PREFIX" to relabel the global malloc.)
-
-  You can similarly create thread-local allocators by storing
-  mspaces as thread-locals. For example:
-    static __thread mspace tlms = 0;
-    void*  tlmalloc(size_t bytes) {
-      if (tlms == 0) tlms = create_mspace(0, 0);
-      return mspace_malloc(tlms, bytes);
-    }
-    void  tlfree(void* mem) { mspace_free(tlms, mem); }
-
-  Unless FOOTERS is defined, each mspace is completely independent.
-  You cannot allocate from one and free to another (although
-  conformance is only weakly checked, so usage errors are not always
-  caught). If FOOTERS is defined, then each chunk carries around a tag
-  indicating its originating mspace, and frees are directed to their
-  originating spaces.
-
- -------------------------  Compile-time options ---------------------------
-
-Be careful in setting #define values for numerical constants of type
-size_t. On some systems, literal values are not automatically extended
-to size_t precision unless they are explicitly casted.
-
-WIN32                    default: defined if _WIN32 defined
-  Defining WIN32 sets up defaults for MS environment and compilers.
-  Otherwise defaults are for unix.
-
-MALLOC_ALIGNMENT         default: (size_t)8
-  Controls the minimum alignment for malloc'ed chunks.  It must be a
-  power of two and at least 8, even on machines for which smaller
-  alignments would suffice. It may be defined as larger than this
-  though. Note however that code and data structures are optimized for
-  the case of 8-byte alignment.
-
-MSPACES                  default: 0 (false)
-  If true, compile in support for independent allocation spaces.
-  This is only supported if HAVE_MMAP is true.
-
-ONLY_MSPACES             default: 0 (false)
-  If true, only compile in mspace versions, not regular versions.
-
-USE_LOCKS                default: 0 (false)
-  Causes each call to each public routine to be surrounded with
-  pthread or WIN32 mutex lock/unlock. (If set true, this can be
-  overridden on a per-mspace basis for mspace versions.)
-
-FOOTERS                  default: 0
-  If true, provide extra checking and dispatching by placing
-  information in the footers of allocated chunks. This adds
-  space and time overhead.
-
-INSECURE                 default: 0
-  If true, omit checks for usage errors and heap space overwrites.
-
-USE_DL_PREFIX            default: NOT defined
-  Causes compiler to prefix all public routines with the string 'dl'.
-  This can be useful when you only want to use this malloc in one part
-  of a program, using your regular system malloc elsewhere.
-
-ABORT                    default: defined as abort()
-  Defines how to abort on failed checks.  On most systems, a failed
-  check cannot die with an "assert" or even print an informative
-  message, because the underlying print routines in turn call malloc,
-  which will fail again.  Generally, the best policy is to simply call
-  abort(). It's not very useful to do more than this because many
-  errors due to overwriting will show up as address faults (null, odd
-  addresses etc) rather than malloc-triggered checks, so will also
-  abort.  Also, most compilers know that abort() does not return, so
-  can better optimize code conditionally calling it.
-
-PROCEED_ON_ERROR           default: defined as 0 (false)
-  Controls whether detected bad addresses cause them to bypassed
-  rather than aborting. If set, detected bad arguments to free and
-  realloc are ignored. And all bookkeeping information is zeroed out
-  upon a detected overwrite of freed heap space, thus losing the
-  ability to ever return it from malloc again, but enabling the
-  application to proceed. If PROCEED_ON_ERROR is defined, the
-  static variable malloc_corruption_error_count is compiled in
-  and can be examined to see if errors have occurred. This option
-  generates slower code than the default abort policy.
-
-DEBUG                    default: NOT defined
-  The DEBUG setting is mainly intended for people trying to modify
-  this code or diagnose problems when porting to new platforms.
-  However, it may also be able to better isolate user errors than just
-  using runtime checks.  The assertions in the check routines spell
-  out in more detail the assumptions and invariants underlying the
-  algorithms.  The checking is fairly extensive, and will slow down
-  execution noticeably. Calling malloc_stats or mallinfo with DEBUG
-  set will attempt to check every non-mmapped allocated and free chunk
-  in the course of computing the summaries.
-
-ABORT_ON_ASSERT_FAILURE   default: defined as 1 (true)
-  Debugging assertion failures can be nearly impossible if your
-  version of the assert macro causes malloc to be called, which will
-  lead to a cascade of further failures, blowing the runtime stack.
-  ABORT_ON_ASSERT_FAILURE cause assertions failures to call abort(),
-  which will usually make debugging easier.
-
-MALLOC_FAILURE_ACTION     default: sets errno to ENOMEM, or no-op on win32
-  The action to take before "return 0" when malloc fails to be able to
-  return memory because there is none available.
-
-HAVE_MORECORE             default: 1 (true) unless win32 or ONLY_MSPACES
-  True if this system supports sbrk or an emulation of it.
-
-MORECORE                  default: sbrk
-  The name of the sbrk-style system routine to call to obtain more
-  memory.  See below for guidance on writing custom MORECORE
-  functions. The type of the argument to sbrk/MORECORE varies across
-  systems.  It cannot be size_t, because it supports negative
-  arguments, so it is normally the signed type of the same width as
-  size_t (sometimes declared as "intptr_t").  It doesn't much matter
-  though. Internally, we only call it with arguments less than half
-  the max value of a size_t, which should work across all reasonable
-  possibilities, although sometimes generating compiler warnings.  See
-  near the end of this file for guidelines for creating a custom
-  version of MORECORE.
-
-MORECORE_CONTIGUOUS       default: 1 (true)
-  If true, take advantage of fact that consecutive calls to MORECORE
-  with positive arguments always return contiguous increasing
-  addresses.  This is true of unix sbrk. It does not hurt too much to
-  set it true anyway, since malloc copes with non-contiguities.
-  Setting it false when definitely non-contiguous saves time
-  and possibly wasted space it would take to discover this though.
-
-MORECORE_CANNOT_TRIM      default: NOT defined
-  True if MORECORE cannot release space back to the system when given
-  negative arguments. This is generally necessary only if you are
-  using a hand-crafted MORECORE function that cannot handle negative
-  arguments.
-
-HAVE_MMAP                 default: 1 (true)
-  True if this system supports mmap or an emulation of it.  If so, and
-  HAVE_MORECORE is not true, MMAP is used for all system
-  allocation. If set and HAVE_MORECORE is true as well, MMAP is
-  primarily used to directly allocate very large blocks. It is also
-  used as a backup strategy in cases where MORECORE fails to provide
-  space from system. Note: A single call to MUNMAP is assumed to be
-  able to unmap memory that may have be allocated using multiple calls
-  to MMAP, so long as they are adjacent.
-
-HAVE_MREMAP               default: 1 on linux, else 0
-  If true realloc() uses mremap() to re-allocate large blocks and
-  extend or shrink allocation spaces.
-
-MMAP_CLEARS               default: 1 on unix
-  True if mmap clears memory so calloc doesn't need to. This is true
-  for standard unix mmap using /dev/zero.
-
-USE_BUILTIN_FFS            default: 0 (i.e., not used)
-  Causes malloc to use the builtin ffs() function to compute indices.
-  Some compilers may recognize and intrinsify ffs to be faster than the
-  supplied C version. Also, the case of x86 using gcc is special-cased
-  to an asm instruction, so is already as fast as it can be, and so
-  this setting has no effect. (On most x86s, the asm version is only
-  slightly faster than the C version.)
-
-malloc_getpagesize         default: derive from system includes, or 4096.
-  The system page size. To the extent possible, this malloc manages
-  memory from the system in page-size units.  This may be (and
-  usually is) a function rather than a constant. This is ignored
-  if WIN32, where page size is determined using getSystemInfo during
-  initialization.
-
-USE_DEV_RANDOM             default: 0 (i.e., not used)
-  Causes malloc to use /dev/random to initialize secure magic seed for
-  stamping footers. Otherwise, the current time is used.
-
-NO_MALLINFO                default: 0
-  If defined, don't compile "mallinfo". This can be a simple way
-  of dealing with mismatches between system declarations and
-  those in this file.
-
-MALLINFO_FIELD_TYPE        default: size_t
-  The type of the fields in the mallinfo struct. This was originally
-  defined as "int" in SVID etc, but is more usefully defined as
-  size_t. The value is used only if  HAVE_USR_INCLUDE_MALLOC_H is not set
-
-REALLOC_ZERO_BYTES_FREES    default: not defined
-  This should be set if a call to realloc with zero bytes should
-  be the same as a call to free. Some people think it should. Otherwise,
-  since this malloc returns a unique pointer for malloc(0), so does
-  realloc(p, 0).
-
-LACKS_UNISTD_H, LACKS_FCNTL_H, LACKS_SYS_PARAM_H, LACKS_SYS_MMAN_H
-LACKS_STRINGS_H, LACKS_STRING_H, LACKS_SYS_TYPES_H,  LACKS_ERRNO_H
-LACKS_STDLIB_H                default: NOT defined unless on WIN32
-  Define these if your system does not have these header files.
-  You might need to manually insert some of the declarations they provide.
-
-DEFAULT_GRANULARITY        default: page size if MORECORE_CONTIGUOUS,
-                                system_info.dwAllocationGranularity in WIN32,
-                                otherwise 64K.
-      Also settable using mallopt(M_GRANULARITY, x)
-  The unit for allocating and deallocating memory from the system.  On
-  most systems with contiguous MORECORE, there is no reason to
-  make this more than a page. However, systems with MMAP tend to
-  either require or encourage larger granularities.  You can increase
-  this value to prevent system allocation functions to be called so
-  often, especially if they are slow.  The value must be at least one
-  page and must be a power of two.  Setting to 0 causes initialization
-  to either page size or win32 region size.  (Note: In previous
-  versions of malloc, the equivalent of this option was called
-  "TOP_PAD")
-
-DEFAULT_TRIM_THRESHOLD    default: 2MB
-      Also settable using mallopt(M_TRIM_THRESHOLD, x)
-  The maximum amount of unused top-most memory to keep before
-  releasing via malloc_trim in free().  Automatic trimming is mainly
-  useful in long-lived programs using contiguous MORECORE.  Because
-  trimming via sbrk can be slow on some systems, and can sometimes be
-  wasteful (in cases where programs immediately afterward allocate
-  more large chunks) the value should be high enough so that your
-  overall system performance would improve by releasing this much
-  memory.  As a rough guide, you might set to a value close to the
-  average size of a process (program) running on your system.
-  Releasing this much memory would allow such a process to run in
-  memory.  Generally, it is worth tuning trim thresholds when a
-  program undergoes phases where several large chunks are allocated
-  and released in ways that can reuse each other's storage, perhaps
-  mixed with phases where there are no such chunks at all. The trim
-  value must be greater than page size to have any useful effect.  To
-  disable trimming completely, you can set to MAX_SIZE_T. Note that the trick
-  some people use of mallocing a huge space and then freeing it at
-  program startup, in an attempt to reserve system memory, doesn't
-  have the intended effect under automatic trimming, since that memory
-  will immediately be returned to the system.
-
-DEFAULT_MMAP_THRESHOLD       default: 256K
-      Also settable using mallopt(M_MMAP_THRESHOLD, x)
-  The request size threshold for using MMAP to directly service a
-  request. Requests of at least this size that cannot be allocated
-  using already-existing space will be serviced via mmap.  (If enough
-  normal freed space already exists it is used instead.)  Using mmap
-  segregates relatively large chunks of memory so that they can be
-  individually obtained and released from the host system. A request
-  serviced through mmap is never reused by any other request (at least
-  not directly; the system may just so happen to remap successive
-  requests to the same locations).  Segregating space in this way has
-  the benefits that: Mmapped space can always be individually released
-  back to the system, which helps keep the system level memory demands
-  of a long-lived program low.  Also, mapped memory doesn't become
-  `locked' between other chunks, as can happen with normally allocated
-  chunks, which means that even trimming via malloc_trim would not
-  release them.  However, it has the disadvantage that the space
-  cannot be reclaimed, consolidated, and then used to service later
-  requests, as happens with normal chunks.  The advantages of mmap
-  nearly always outweigh disadvantages for "large" chunks, but the
-  value of "large" may vary across systems.  The default is an
-  empirically derived value that works well in most systems. You can
-  disable mmap by setting to MAX_SIZE_T.
-
-*/
-#if defined(__WATCOMC__) || defined(_MSC_VER)
-#define WIN32 1
-#endif
-
-#ifndef WIN32
-#ifdef _WIN32
-#define WIN32 1
-#endif  /* _WIN32 */
-#endif  /* WIN32 */
-#ifdef WIN32
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#define HAVE_MORECORE 0
-#define LACKS_UNISTD_H
-#define LACKS_SYS_PARAM_H
-#define LACKS_SYS_MMAN_H
-#define LACKS_STRING_H
-#define LACKS_STRINGS_H
-#define LACKS_SYS_TYPES_H
-#define LACKS_ERRNO_H
-#define MALLOC_FAILURE_ACTION
-#define MMAP_CLEARS 0 /* WINCE and some others apparently don't clear */
-#endif  /* WIN32 */
-
-#if defined(DARWIN) || defined(_DARWIN)
-/* Mac OSX docs advise not to use sbrk; it seems better to use mmap */
-#ifndef HAVE_MORECORE
-#define HAVE_MORECORE 0
-#define HAVE_MMAP 1
-#endif  /* HAVE_MORECORE */
-#endif  /* DARWIN */
-
-#ifndef LACKS_SYS_TYPES_H
-#include <sys/types.h>  /* For size_t */
-#endif  /* LACKS_SYS_TYPES_H */
-
-/* The maximum possible size_t value has all bits set */
-#define MAX_SIZE_T           (~(size_t)0)
-
-#ifndef ONLY_MSPACES
-#define ONLY_MSPACES 0
-#endif  /* ONLY_MSPACES */
-#ifndef MSPACES
-#if ONLY_MSPACES
-#define MSPACES 1
-#else   /* ONLY_MSPACES */
-#define MSPACES 0
-#endif  /* ONLY_MSPACES */
-#endif  /* MSPACES */
-#ifndef MALLOC_ALIGNMENT
-#define MALLOC_ALIGNMENT ((size_t)8U)
-#endif  /* MALLOC_ALIGNMENT */
-#ifndef FOOTERS
-#define FOOTERS 0
-#endif  /* FOOTERS */
-#ifndef ABORT
-#define ABORT  abort()
-#endif  /* ABORT */
-#ifndef ABORT_ON_ASSERT_FAILURE
-#define ABORT_ON_ASSERT_FAILURE 1
-#endif  /* ABORT_ON_ASSERT_FAILURE */
-#ifndef PROCEED_ON_ERROR
-#define PROCEED_ON_ERROR 0
-#endif  /* PROCEED_ON_ERROR */
-#ifndef USE_LOCKS
-#define USE_LOCKS 0
-#endif  /* USE_LOCKS */
-#ifndef INSECURE
-#define INSECURE 0
-#endif  /* INSECURE */
-#ifndef HAVE_MMAP
-#define HAVE_MMAP 1
-#endif  /* HAVE_MMAP */
-#ifndef MMAP_CLEARS
-#define MMAP_CLEARS 1
-#endif  /* MMAP_CLEARS */
-#ifndef HAVE_MREMAP
-#ifdef linux
-#define HAVE_MREMAP 1
-#else   /* linux */
-#define HAVE_MREMAP 0
-#endif  /* linux */
-#endif  /* HAVE_MREMAP */
-#ifndef MALLOC_FAILURE_ACTION
-#define MALLOC_FAILURE_ACTION  errno = ENOMEM;
-#endif  /* MALLOC_FAILURE_ACTION */
-#ifndef HAVE_MORECORE
-#if ONLY_MSPACES
-#define HAVE_MORECORE 0
-#else   /* ONLY_MSPACES */
-#define HAVE_MORECORE 1
-#endif  /* ONLY_MSPACES */
-#endif  /* HAVE_MORECORE */
-#if !HAVE_MORECORE
-#define MORECORE_CONTIGUOUS 0
-#else   /* !HAVE_MORECORE */
-#ifndef MORECORE
-#define MORECORE sbrk
-#endif  /* MORECORE */
-#ifndef MORECORE_CONTIGUOUS
-#define MORECORE_CONTIGUOUS 1
-#endif  /* MORECORE_CONTIGUOUS */
-#endif  /* HAVE_MORECORE */
-#ifndef DEFAULT_GRANULARITY
-#if MORECORE_CONTIGUOUS
-#define DEFAULT_GRANULARITY (0)  /* 0 means to compute in init_mparams */
-#else   /* MORECORE_CONTIGUOUS */
-#define DEFAULT_GRANULARITY ((size_t)64U * (size_t)1024U)
-#endif  /* MORECORE_CONTIGUOUS */
-#endif  /* DEFAULT_GRANULARITY */
-#ifndef DEFAULT_TRIM_THRESHOLD
-#ifndef MORECORE_CANNOT_TRIM
-#define DEFAULT_TRIM_THRESHOLD ((size_t)2U * (size_t)1024U * (size_t)1024U)
-#else   /* MORECORE_CANNOT_TRIM */
-#define DEFAULT_TRIM_THRESHOLD MAX_SIZE_T
-#endif  /* MORECORE_CANNOT_TRIM */
-#endif  /* DEFAULT_TRIM_THRESHOLD */
-#ifndef DEFAULT_MMAP_THRESHOLD
-#if HAVE_MMAP
-#define DEFAULT_MMAP_THRESHOLD ((size_t)256U * (size_t)1024U)
-#else   /* HAVE_MMAP */
-#define DEFAULT_MMAP_THRESHOLD MAX_SIZE_T
-#endif  /* HAVE_MMAP */
-#endif  /* DEFAULT_MMAP_THRESHOLD */
-#ifndef USE_BUILTIN_FFS
-#define USE_BUILTIN_FFS 0
-#endif  /* USE_BUILTIN_FFS */
-#ifndef USE_DEV_RANDOM
-#define USE_DEV_RANDOM 0
-#endif  /* USE_DEV_RANDOM */
-#ifndef NO_MALLINFO
-#define NO_MALLINFO 0
-#endif  /* NO_MALLINFO */
-#ifndef MALLINFO_FIELD_TYPE
-#define MALLINFO_FIELD_TYPE size_t
-#endif  /* MALLINFO_FIELD_TYPE */
-
-/*
-  mallopt tuning options.  SVID/XPG defines four standard parameter
-  numbers for mallopt, normally defined in malloc.h.  None of these
-  are used in this malloc, so setting them has no effect. But this
-  malloc does support the following options.
-*/
-
-#define M_TRIM_THRESHOLD     (-1)
-#define M_GRANULARITY        (-2)
-#define M_MMAP_THRESHOLD     (-3)
-
-/* ------------------------ Mallinfo declarations ------------------------ */
-
-#if !NO_MALLINFO
-/*
-  This version of malloc supports the standard SVID/XPG mallinfo
-  routine that returns a struct containing usage properties and
-  statistics. It should work on any system that has a
-  /usr/include/malloc.h defining struct mallinfo.  The main
-  declaration needed is the mallinfo struct that is returned (by-copy)
-  by mallinfo().  The malloinfo struct contains a bunch of fields that
-  are not even meaningful in this version of malloc.  These fields are
-  are instead filled by mallinfo() with other numbers that might be of
-  interest.
-
-  HAVE_USR_INCLUDE_MALLOC_H should be set if you have a
-  /usr/include/malloc.h file that includes a declaration of struct
-  mallinfo.  If so, it is included; else a compliant version is
-  declared below.  These must be precisely the same for mallinfo() to
-  work.  The original SVID version of this struct, defined on most
-  systems with mallinfo, declares all fields as ints. But some others
-  define as unsigned long. If your system defines the fields using a
-  type of different width than listed here, you MUST #include your
-  system version and #define HAVE_USR_INCLUDE_MALLOC_H.
-*/
-
-/* #define HAVE_USR_INCLUDE_MALLOC_H */
-
-#ifdef HAVE_USR_INCLUDE_MALLOC_H
-#include "/usr/include/malloc.h"
-#else /* HAVE_USR_INCLUDE_MALLOC_H */
-
-struct mallinfo {
-  MALLINFO_FIELD_TYPE arena;    /* non-mmapped space allocated from system */
-  MALLINFO_FIELD_TYPE ordblks;  /* number of free chunks */
-  MALLINFO_FIELD_TYPE smblks;   /* always 0 */
-  MALLINFO_FIELD_TYPE hblks;    /* always 0 */
-  MALLINFO_FIELD_TYPE hblkhd;   /* space in mmapped regions */
-  MALLINFO_FIELD_TYPE usmblks;  /* maximum total allocated space */
-  MALLINFO_FIELD_TYPE fsmblks;  /* always 0 */
-  MALLINFO_FIELD_TYPE uordblks; /* total allocated space */
-  MALLINFO_FIELD_TYPE fordblks; /* total free space */
-  MALLINFO_FIELD_TYPE keepcost; /* releasable (via malloc_trim) space */
-};
-
-#endif /* HAVE_USR_INCLUDE_MALLOC_H */
-#endif /* NO_MALLINFO */
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-#if !ONLY_MSPACES
-
-/* ------------------- Declarations of public routines ------------------- */
-
-#ifndef USE_DL_PREFIX
-#define dlcalloc               calloc
-#define dlfree                 free
-#define dlmalloc               malloc
-#define dlmemalign             memalign
-#define dlrealloc              realloc
-#define dlvalloc               valloc
-#define dlpvalloc              pvalloc
-#define dlmallinfo             mallinfo
-#define dlmallopt              mallopt
-#define dlmalloc_trim          malloc_trim
-#define dlmalloc_stats         malloc_stats
-#define dlmalloc_usable_size   malloc_usable_size
-#define dlmalloc_footprint     malloc_footprint
-#define dlmalloc_max_footprint malloc_max_footprint
-#define dlindependent_calloc   independent_calloc
-#define dlindependent_comalloc independent_comalloc
-#endif /* USE_DL_PREFIX */
-
-
-/*
-  malloc(size_t n)
-  Returns a pointer to a newly allocated chunk of at least n bytes, or
-  null if no space is available, in which case errno is set to ENOMEM
-  on ANSI C systems.
-
-  If n is zero, malloc returns a minimum-sized chunk. (The minimum
-  size is 16 bytes on most 32bit systems, and 32 bytes on 64bit
-  systems.)  Note that size_t is an unsigned type, so calls with
-  arguments that would be negative if signed are interpreted as
-  requests for huge amounts of space, which will often fail. The
-  maximum supported value of n differs across systems, but is in all
-  cases less than the maximum representable value of a size_t.
-*/
-void* dlmalloc(size_t);
-
-/*
-  free(void* p)
-  Releases the chunk of memory pointed to by p, that had been previously
-  allocated using malloc or a related routine such as realloc.
-  It has no effect if p is null. If p was not malloced or already
-  freed, free(p) will by default cause the current program to abort.
-*/
-void  dlfree(void*);
-
-/*
-  calloc(size_t n_elements, size_t element_size);
-  Returns a pointer to n_elements * element_size bytes, with all locations
-  set to zero.
-*/
-void* dlcalloc(size_t, size_t);
-
-/*
-  realloc(void* p, size_t n)
-  Returns a pointer to a chunk of size n that contains the same data
-  as does chunk p up to the minimum of (n, p's size) bytes, or null
-  if no space is available.
-
-  The returned pointer may or may not be the same as p. The algorithm
-  prefers extending p in most cases when possible, otherwise it
-  employs the equivalent of a malloc-copy-free sequence.
-
-  If p is null, realloc is equivalent to malloc.
-
-  If space is not available, realloc returns null, errno is set (if on
-  ANSI) and p is NOT freed.
-
-  if n is for fewer bytes than already held by p, the newly unused
-  space is lopped off and freed if possible.  realloc with a size
-  argument of zero (re)allocates a minimum-sized chunk.
-
-  The old unix realloc convention of allowing the last-free'd chunk
-  to be used as an argument to realloc is not supported.
-*/
-
-void* dlrealloc(void*, size_t);
-
-/*
-  memalign(size_t alignment, size_t n);
-  Returns a pointer to a newly allocated chunk of n bytes, aligned
-  in accord with the alignment argument.
-
-  The alignment argument should be a power of two. If the argument is
-  not a power of two, the nearest greater power is used.
-  8-byte alignment is guaranteed by normal malloc calls, so don't
-  bother calling memalign with an argument of 8 or less.
-
-  Overreliance on memalign is a sure way to fragment space.
-*/
-void* dlmemalign(size_t, size_t);
-
-/*
-  valloc(size_t n);
-  Equivalent to memalign(pagesize, n), where pagesize is the page
-  size of the system. If the pagesize is unknown, 4096 is used.
-*/
-void* dlvalloc(size_t);
-
-/*
-  mallopt(int parameter_number, int parameter_value)
-  Sets tunable parameters The format is to provide a
-  (parameter-number, parameter-value) pair.  mallopt then sets the
-  corresponding parameter to the argument value if it can (i.e., so
-  long as the value is meaningful), and returns 1 if successful else
-  0.  SVID/XPG/ANSI defines four standard param numbers for mallopt,
-  normally defined in malloc.h.  None of these are use in this malloc,
-  so setting them has no effect. But this malloc also supports other
-  options in mallopt. See below for details.  Briefly, supported
-  parameters are as follows (listed defaults are for "typical"
-  configurations).
-
-  Symbol            param #  default    allowed param values
-  M_TRIM_THRESHOLD     -1   2*1024*1024   any   (MAX_SIZE_T disables)
-  M_GRANULARITY        -2     page size   any power of 2 >= page size
-  M_MMAP_THRESHOLD     -3      256*1024   any   (or 0 if no MMAP support)
-*/
-int dlmallopt(int, int);
-
-/*
-  malloc_footprint();
-  Returns the number of bytes obtained from the system.  The total
-  number of bytes allocated by malloc, realloc etc., is less than this
-  value. Unlike mallinfo, this function returns only a precomputed
-  result, so can be called frequently to monitor memory consumption.
-  Even if locks are otherwise defined, this function does not use them,
-  so results might not be up to date.
-*/
-size_t dlmalloc_footprint(void);
-
-/*
-  malloc_max_footprint();
-  Returns the maximum number of bytes obtained from the system. This
-  value will be greater than current footprint if deallocated space
-  has been reclaimed by the system. The peak number of bytes allocated
-  by malloc, realloc etc., is less than this value. Unlike mallinfo,
-  this function returns only a precomputed result, so can be called
-  frequently to monitor memory consumption.  Even if locks are
-  otherwise defined, this function does not use them, so results might
-  not be up to date.
-*/
-size_t dlmalloc_max_footprint(void);
-
-#if !NO_MALLINFO
-/*
-  mallinfo()
-  Returns (by copy) a struct containing various summary statistics:
-
-  arena:     current total non-mmapped bytes allocated from system
-  ordblks:   the number of free chunks
-  smblks:    always zero.
-  hblks:     current number of mmapped regions
-  hblkhd:    total bytes held in mmapped regions
-  usmblks:   the maximum total allocated space. This will be greater
-                than current total if trimming has occurred.
-  fsmblks:   always zero
-  uordblks:  current total allocated space (normal or mmapped)
-  fordblks:  total free space
-  keepcost:  the maximum number of bytes that could ideally be released
-               back to system via malloc_trim. ("ideally" means that
-               it ignores page restrictions etc.)
-
-  Because these fields are ints, but internal bookkeeping may
-  be kept as longs, the reported values may wrap around zero and
-  thus be inaccurate.
-*/
-struct mallinfo dlmallinfo(void);
-#endif /* NO_MALLINFO */
-
-/*
-  independent_calloc(size_t n_elements, size_t element_size, void* chunks[]);
-
-  independent_calloc is similar to calloc, but instead of returning a
-  single cleared space, it returns an array of pointers to n_elements
-  independent elements that can hold contents of size elem_size, each
-  of which starts out cleared, and can be independently freed,
-  realloc'ed etc. The elements are guaranteed to be adjacently
-  allocated (this is not guaranteed to occur with multiple callocs or
-  mallocs), which may also improve cache locality in some
-  applications.
-
-  The "chunks" argument is optional (i.e., may be null, which is
-  probably the most typical usage). If it is null, the returned array
-  is itself dynamically allocated and should also be freed when it is
-  no longer needed. Otherwise, the chunks array must be of at least
-  n_elements in length. It is filled in with the pointers to the
-  chunks.
-
-  In either case, independent_calloc returns this pointer array, or
-  null if the allocation failed.  If n_elements is zero and "chunks"
-  is null, it returns a chunk representing an array with zero elements
-  (which should be freed if not wanted).
-
-  Each element must be individually freed when it is no longer
-  needed. If you'd like to instead be able to free all at once, you
-  should instead use regular calloc and assign pointers into this
-  space to represent elements.  (In this case though, you cannot
-  independently free elements.)
-
-  independent_calloc simplifies and speeds up implementations of many
-  kinds of pools.  It may also be useful when constructing large data
-  structures that initially have a fixed number of fixed-sized nodes,
-  but the number is not known at compile time, and some of the nodes
-  may later need to be freed. For example:
-
-  struct Node { int item; struct Node* next; };
-
-  struct Node* build_list() {
-    struct Node** pool;
-    int n = read_number_of_nodes_needed();
-    if (n <= 0) return 0;
-    pool = (struct Node**)(independent_calloc(n, sizeof(struct Node), 0);
-    if (pool == 0) die();
-    // organize into a linked list...
-    struct Node* first = pool[0];
-    for (i = 0; i < n-1; ++i)
-      pool[i]->next = pool[i+1];
-    free(pool);     // Can now free the array (or not, if it is needed later)
-    return first;
-  }
-*/
-void** dlindependent_calloc(size_t, size_t, void**);
-
-/*
-  independent_comalloc(size_t n_elements, size_t sizes[], void* chunks[]);
-
-  independent_comalloc allocates, all at once, a set of n_elements
-  chunks with sizes indicated in the "sizes" array.    It returns
-  an array of pointers to these elements, each of which can be
-  independently freed, realloc'ed etc. The elements are guaranteed to
-  be adjacently allocated (this is not guaranteed to occur with
-  multiple callocs or mallocs), which may also improve cache locality
-  in some applications.
-
-  The "chunks" argument is optional (i.e., may be null). If it is null
-  the returned array is itself dynamically allocated and should also
-  be freed when it is no longer needed. Otherwise, the chunks array
-  must be of at least n_elements in length. It is filled in with the
-  pointers to the chunks.
-
-  In either case, independent_comalloc returns this pointer array, or
-  null if the allocation failed.  If n_elements is zero and chunks is
-  null, it returns a chunk representing an array with zero elements
-  (which should be freed if not wanted).
-
-  Each element must be individually freed when it is no longer
-  needed. If you'd like to instead be able to free all at once, you
-  should instead use a single regular malloc, and assign pointers at
-  particular offsets in the aggregate space. (In this case though, you
-  cannot independently free elements.)
-
-  independent_comallac differs from independent_calloc in that each
-  element may have a different size, and also that it does not
-  automatically clear elements.
-
-  independent_comalloc can be used to speed up allocation in cases
-  where several structs or objects must always be allocated at the
-  same time.  For example:
-
-  struct Head { ... }
-  struct Foot { ... }
-
-  void send_message(char* msg) {
-    int msglen = strlen(msg);
-    size_t sizes[3] = { sizeof(struct Head), msglen, sizeof(struct Foot) };
-    void* chunks[3];
-    if (independent_comalloc(3, sizes, chunks) == 0)
-      die();
-    struct Head* head = (struct Head*)(chunks[0]);
-    char*        body = (char*)(chunks[1]);
-    struct Foot* foot = (struct Foot*)(chunks[2]);
-    // ...
-  }
-
-  In general though, independent_comalloc is worth using only for
-  larger values of n_elements. For small values, you probably won't
-  detect enough difference from series of malloc calls to bother.
-
-  Overuse of independent_comalloc can increase overall memory usage,
-  since it cannot reuse existing noncontiguous small chunks that
-  might be available for some of the elements.
-*/
-void** dlindependent_comalloc(size_t, size_t*, void**);
-
-
-/*
-  pvalloc(size_t n);
-  Equivalent to valloc(minimum-page-that-holds(n)), that is,
-  round up n to nearest pagesize.
- */
-void*  dlpvalloc(size_t);
-
-/*
-  malloc_trim(size_t pad);
-
-  If possible, gives memory back to the system (via negative arguments
-  to sbrk) if there is unused memory at the `high' end of the malloc
-  pool or in unused MMAP segments. You can call this after freeing
-  large blocks of memory to potentially reduce the system-level memory
-  requirements of a program. However, it cannot guarantee to reduce
-  memory. Under some allocation patterns, some large free blocks of
-  memory will be locked between two used chunks, so they cannot be
-  given back to the system.
-
-  The `pad' argument to malloc_trim represents the amount of free
-  trailing space to leave untrimmed. If this argument is zero, only
-  the minimum amount of memory to maintain internal data structures
-  will be left. Non-zero arguments can be supplied to maintain enough
-  trailing space to service future expected allocations without having
-  to re-obtain memory from the system.
-
-  Malloc_trim returns 1 if it actually released any memory, else 0.
-*/
-int  dlmalloc_trim(size_t);
-
-/*
-  malloc_usable_size(void* p);
-
-  Returns the number of bytes you can actually use in
-  an allocated chunk, which may be more than you requested (although
-  often not) due to alignment and minimum size constraints.
-  You can use this many bytes without worrying about
-  overwriting other allocated objects. This is not a particularly great
-  programming practice. malloc_usable_size can be more useful in
-  debugging and assertions, for example:
-
-  p = malloc(n);
-  assert(malloc_usable_size(p) >= 256);
-*/
-size_t dlmalloc_usable_size(void*);
-
-/*
-  malloc_stats();
-  Prints on stderr the amount of space obtained from the system (both
-  via sbrk and mmap), the maximum amount (which may be more than
-  current if malloc_trim and/or munmap got called), and the current
-  number of bytes allocated via malloc (or realloc, etc) but not yet
-  freed. Note that this is the number of bytes allocated, not the
-  number requested. It will be larger than the number requested
-  because of alignment and bookkeeping overhead. Because it includes
-  alignment wastage as being in use, this figure may be greater than
-  zero even when no user-level chunks are allocated.
-
-  The reported current and maximum system memory can be inaccurate if
-  a program makes other calls to system memory allocation functions
-  (normally sbrk) outside of malloc.
-
-  malloc_stats prints only the most commonly interesting statistics.
-  More information can be obtained by calling mallinfo.
-*/
-void  dlmalloc_stats(void);
-
-#endif /* ONLY_MSPACES */
-
-#if MSPACES
-
-/*
-  mspace is an opaque type representing an independent
-  region of space that supports mspace_malloc, etc.
-*/
-typedef void* mspace;
-
-/*
-  create_mspace creates and returns a new independent space with the
-  given initial capacity, or, if 0, the default granularity size.  It
-  returns null if there is no system memory available to create the
-  space.  If argument locked is non-zero, the space uses a separate
-  lock to control access. The capacity of the space will grow
-  dynamically as needed to service mspace_malloc requests.  You can
-  control the sizes of incremental increases of this space by
-  compiling with a different DEFAULT_GRANULARITY or dynamically
-  setting with mallopt(M_GRANULARITY, value).
-*/
-mspace create_mspace(size_t capacity, int locked);
-
-/*
-  destroy_mspace destroys the given space, and attempts to return all
-  of its memory back to the system, returning the total number of
-  bytes freed. After destruction, the results of access to all memory
-  used by the space become undefined.
-*/
-size_t destroy_mspace(mspace msp);
-
-/*
-  create_mspace_with_base uses the memory supplied as the initial base
-  of a new mspace. Part (less than 128*sizeof(size_t) bytes) of this
-  space is used for bookkeeping, so the capacity must be at least this
-  large. (Otherwise 0 is returned.) When this initial space is
-  exhausted, additional memory will be obtained from the system.
-  Destroying this space will deallocate all additionally allocated
-  space (if possible) but not the initial base.
-*/
-mspace create_mspace_with_base(void* base, size_t capacity, int locked);
-
-/*
-  mspace_malloc behaves as malloc, but operates within
-  the given space.
-*/
-void* mspace_malloc(mspace msp, size_t bytes);
-
-/*
-  mspace_free behaves as free, but operates within
-  the given space.
-
-  If compiled with FOOTERS==1, mspace_free is not actually needed.
-  free may be called instead of mspace_free because freed chunks from
-  any space are handled by their originating spaces.
-*/
-void mspace_free(mspace msp, void* mem);
-
-/*
-  mspace_realloc behaves as realloc, but operates within
-  the given space.
-
-  If compiled with FOOTERS==1, mspace_realloc is not actually
-  needed.  realloc may be called instead of mspace_realloc because
-  realloced chunks from any space are handled by their originating
-  spaces.
-*/
-void* mspace_realloc(mspace msp, void* mem, size_t newsize);
-
-/*
-  mspace_calloc behaves as calloc, but operates within
-  the given space.
-*/
-void* mspace_calloc(mspace msp, size_t n_elements, size_t elem_size);
-
-/*
-  mspace_memalign behaves as memalign, but operates within
-  the given space.
-*/
-void* mspace_memalign(mspace msp, size_t alignment, size_t bytes);
-
-/*
-  mspace_independent_calloc behaves as independent_calloc, but
-  operates within the given space.
-*/
-void** mspace_independent_calloc(mspace msp, size_t n_elements,
-                                 size_t elem_size, void* chunks[]);
-
-/*
-  mspace_independent_comalloc behaves as independent_comalloc, but
-  operates within the given space.
-*/
-void** mspace_independent_comalloc(mspace msp, size_t n_elements,
-                                   size_t sizes[], void* chunks[]);
-
-/*
-  mspace_footprint() returns the number of bytes obtained from the
-  system for this space.
-*/
-size_t mspace_footprint(mspace msp);
-
-/*
-  mspace_max_footprint() returns the peak number of bytes obtained from the
-  system for this space.
-*/
-size_t mspace_max_footprint(mspace msp);
-
-
-#if !NO_MALLINFO
-/*
-  mspace_mallinfo behaves as mallinfo, but reports properties of
-  the given space.
-*/
-struct mallinfo mspace_mallinfo(mspace msp);
-#endif /* NO_MALLINFO */
-
-/*
-  mspace_malloc_stats behaves as malloc_stats, but reports
-  properties of the given space.
-*/
-void mspace_malloc_stats(mspace msp);
-
-/*
-  mspace_trim behaves as malloc_trim, but
-  operates within the given space.
-*/
-int mspace_trim(mspace msp, size_t pad);
-
-/*
-  An alias for mallopt.
-*/
-int mspace_mallopt(int, int);
-
-#endif /* MSPACES */
-
-#ifdef __cplusplus
-};  /* end of extern "C" */
-#endif /* __cplusplus */
-
-/*
-  ========================================================================
-  To make a fully customizable malloc.h header file, cut everything
-  above this line, put into file malloc.h, edit to suit, and #include it
-  on the next line, as well as in programs that use this malloc.
-  ========================================================================
-*/
-
-/* #include "malloc.h" */
-
-/*------------------------------ internal #includes ---------------------- */
-
-#ifdef WIN32
-#pragma warning( disable : 4146 ) /* no "unsigned" warnings */
-#endif /* WIN32 */
-
-#include <stdio.h>       /* for printing in malloc_stats */
-
-#ifndef LACKS_ERRNO_H
-#include <errno.h>       /* for MALLOC_FAILURE_ACTION */
-#endif /* LACKS_ERRNO_H */
-#if FOOTERS
-#include <time.h>        /* for magic initialization */
-#endif /* FOOTERS */
-#ifndef LACKS_STDLIB_H
-#include <stdlib.h>      /* for abort() */
-#endif /* LACKS_STDLIB_H */
-#ifdef DEBUG
-#if ABORT_ON_ASSERT_FAILURE
-#define assert(x) if(!(x)) ABORT
-#else /* ABORT_ON_ASSERT_FAILURE */
-#include <assert.h>
-#endif /* ABORT_ON_ASSERT_FAILURE */
-#else  /* DEBUG */
-#define assert(x)
-#endif /* DEBUG */
-#ifndef LACKS_STRING_H
-#include <string.h>      /* for memset etc */
-#endif  /* LACKS_STRING_H */
-#if USE_BUILTIN_FFS
-#ifndef LACKS_STRINGS_H
-#include <strings.h>     /* for ffs */
-#endif /* LACKS_STRINGS_H */
-#endif /* USE_BUILTIN_FFS */
-#if HAVE_MMAP
-#ifndef LACKS_SYS_MMAN_H
-#include <sys/mman.h>    /* for mmap */
-#endif /* LACKS_SYS_MMAN_H */
-#ifndef LACKS_FCNTL_H
-#include <fcntl.h>
-#endif /* LACKS_FCNTL_H */
-#endif /* HAVE_MMAP */
-#if HAVE_MORECORE
-#ifndef LACKS_UNISTD_H
-#include <unistd.h>     /* for sbrk */
-#else /* LACKS_UNISTD_H */
-#if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__)
-extern void*     sbrk(ptrdiff_t);
-#endif /* FreeBSD etc */
-#endif /* LACKS_UNISTD_H */
-#endif /* HAVE_MMAP */
-
-#ifndef WIN32
-#ifndef malloc_getpagesize
-#  ifdef _SC_PAGESIZE         /* some SVR4 systems omit an underscore */
-#    ifndef _SC_PAGE_SIZE
-#      define _SC_PAGE_SIZE _SC_PAGESIZE
-#    endif
-#  endif
-#  ifdef _SC_PAGE_SIZE
-#    define malloc_getpagesize sysconf(_SC_PAGE_SIZE)
-#  else
-#    if defined(BSD) || defined(DGUX) || defined(HAVE_GETPAGESIZE)
-       extern size_t getpagesize();
-#      define malloc_getpagesize getpagesize()
-#    else
-#      ifdef WIN32 /* use supplied emulation of getpagesize */
-#        define malloc_getpagesize getpagesize()
-#      else
-#        ifndef LACKS_SYS_PARAM_H
-#          include <sys/param.h>
-#        endif
-#        ifdef EXEC_PAGESIZE
-#          define malloc_getpagesize EXEC_PAGESIZE
-#        else
-#          ifdef NBPG
-#            ifndef CLSIZE
-#              define malloc_getpagesize NBPG
-#            else
-#              define malloc_getpagesize (NBPG * CLSIZE)
-#            endif
-#          else
-#            ifdef NBPC
-#              define malloc_getpagesize NBPC
-#            else
-#              ifdef PAGESIZE
-#                define malloc_getpagesize PAGESIZE
-#              else /* just guess */
-#                define malloc_getpagesize ((size_t)4096U)
-#              endif
-#            endif
-#          endif
-#        endif
-#      endif
-#    endif
-#  endif
-#endif
-#endif
-
-/* ------------------- size_t and alignment properties -------------------- */
-
-/* The byte and bit size of a size_t */
-#define SIZE_T_SIZE         (sizeof(size_t))
-#define SIZE_T_BITSIZE      (sizeof(size_t) << 3)
-
-/* Some constants coerced to size_t */
-/* Annoying but necessary to avoid errors on some plaftorms */
-#define SIZE_T_ZERO         ((size_t)0)
-#define SIZE_T_ONE          ((size_t)1)
-#define SIZE_T_TWO          ((size_t)2)
-#define TWO_SIZE_T_SIZES    (SIZE_T_SIZE<<1)
-#define FOUR_SIZE_T_SIZES   (SIZE_T_SIZE<<2)
-#define SIX_SIZE_T_SIZES    (FOUR_SIZE_T_SIZES+TWO_SIZE_T_SIZES)
-#define HALF_MAX_SIZE_T     (MAX_SIZE_T / 2U)
-
-/* The bit mask value corresponding to MALLOC_ALIGNMENT */
-#define CHUNK_ALIGN_MASK    (MALLOC_ALIGNMENT - SIZE_T_ONE)
-
-/* True if address a has acceptable alignment */
-#define is_aligned(A)       (((size_t)((A)) & (CHUNK_ALIGN_MASK)) == 0)
-
-/* the number of bytes to offset an address to align it */
-#define align_offset(A)\
- ((((size_t)(A) & CHUNK_ALIGN_MASK) == 0)? 0 :\
-  ((MALLOC_ALIGNMENT - ((size_t)(A) & CHUNK_ALIGN_MASK)) & CHUNK_ALIGN_MASK))
-
-/* -------------------------- MMAP preliminaries ------------------------- */
-
-/*
-   If HAVE_MORECORE or HAVE_MMAP are false, we just define calls and
-   checks to fail so compiler optimizer can delete code rather than
-   using so many "#if"s.
-*/
-
-
-/* MORECORE and MMAP must return MFAIL on failure */
-#define MFAIL                ((void*)(MAX_SIZE_T))
-#define CMFAIL               ((char*)(MFAIL)) /* defined for convenience */
-
-#if !HAVE_MMAP
-#define IS_MMAPPED_BIT       (SIZE_T_ZERO)
-#define USE_MMAP_BIT         (SIZE_T_ZERO)
-#define CALL_MMAP(s)         MFAIL
-#define CALL_MUNMAP(a, s)    (-1)
-#define DIRECT_MMAP(s)       MFAIL
-
-#else /* HAVE_MMAP */
-#define IS_MMAPPED_BIT       (SIZE_T_ONE)
-#define USE_MMAP_BIT         (SIZE_T_ONE)
-
-#ifndef WIN32
-#define CALL_MUNMAP(a, s)    munmap((a), (s))
-#define MMAP_PROT            (PROT_READ|PROT_WRITE)
-#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
-#define MAP_ANONYMOUS        MAP_ANON
-#endif /* MAP_ANON */
-#ifdef MAP_ANONYMOUS
-#define MMAP_FLAGS           (MAP_PRIVATE|MAP_ANONYMOUS)
-#define CALL_MMAP(s)         mmap(0, (s), MMAP_PROT, MMAP_FLAGS, -1, 0)
-#else /* MAP_ANONYMOUS */
-/*
-   Nearly all versions of mmap support MAP_ANONYMOUS, so the following
-   is unlikely to be needed, but is supplied just in case.
-*/
-#define MMAP_FLAGS           (MAP_PRIVATE)
-static int dev_zero_fd = -1; /* Cached file descriptor for /dev/zero. */
-#define CALL_MMAP(s) ((dev_zero_fd < 0) ? \
-           (dev_zero_fd = open("/dev/zero", O_RDWR), \
-            mmap(0, (s), MMAP_PROT, MMAP_FLAGS, dev_zero_fd, 0)) : \
-            mmap(0, (s), MMAP_PROT, MMAP_FLAGS, dev_zero_fd, 0))
-#endif /* MAP_ANONYMOUS */
-
-#define DIRECT_MMAP(s)       CALL_MMAP(s)
-#else /* WIN32 */
-
-/* Win32 MMAP via VirtualAlloc */
-static void* win32mmap(size_t size) {
-  void* ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
-  return (ptr != 0)? ptr: MFAIL;
-}
-
-/* For direct MMAP, use MEM_TOP_DOWN to minimize interference */
-static void* win32direct_mmap(size_t size) {
-  void* ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN,
-                           PAGE_READWRITE);
-  return (ptr != 0)? ptr: MFAIL;
-}
-
-/* This function supports releasing coalesed segments */
-static int win32munmap(void* ptr, size_t size) {
-  MEMORY_BASIC_INFORMATION minfo;
-  char* cptr = ptr;
-  while (size) {
-    if (VirtualQuery(cptr, &minfo, sizeof(minfo)) == 0)
-      return -1;
-    if (minfo.BaseAddress != cptr || minfo.AllocationBase != cptr ||
-        minfo.State != MEM_COMMIT || minfo.RegionSize > size)
-      return -1;
-    if (VirtualFree(cptr, 0, MEM_RELEASE) == 0)
-      return -1;
-    cptr += minfo.RegionSize;
-    size -= minfo.RegionSize;
-  }
-  return 0;
-}
-
-#define CALL_MMAP(s)         win32mmap(s)
-#define CALL_MUNMAP(a, s)    win32munmap((a), (s))
-#define DIRECT_MMAP(s)       win32direct_mmap(s)
-#endif /* WIN32 */
-#endif /* HAVE_MMAP */
-
-#if HAVE_MMAP && HAVE_MREMAP
-#define CALL_MREMAP(addr, osz, nsz, mv) mremap((addr), (osz), (nsz), (mv))
-#else  /* HAVE_MMAP && HAVE_MREMAP */
-#define CALL_MREMAP(addr, osz, nsz, mv) MFAIL
-#endif /* HAVE_MMAP && HAVE_MREMAP */
-
-#if HAVE_MORECORE
-#define CALL_MORECORE(S)     MORECORE(S)
-#else  /* HAVE_MORECORE */
-#define CALL_MORECORE(S)     MFAIL
-#endif /* HAVE_MORECORE */
-
-/* mstate bit set if continguous morecore disabled or failed */
-#define USE_NONCONTIGUOUS_BIT (4U)
-
-/* segment bit set in create_mspace_with_base */
-#define EXTERN_BIT            (8U)
-
-
-/* --------------------------- Lock preliminaries ------------------------ */
-
-#if USE_LOCKS
-
-/*
-  When locks are defined, there are up to two global locks:
-
-  * If HAVE_MORECORE, morecore_mutex protects sequences of calls to
-    MORECORE.  In many cases sys_alloc requires two calls, that should
-    not be interleaved with calls by other threads.  This does not
-    protect against direct calls to MORECORE by other threads not
-    using this lock, so there is still code to cope the best we can on
-    interference.
-
-  * magic_init_mutex ensures that mparams.magic and other
-    unique mparams values are initialized only once.
-*/
-
-#ifndef WIN32
-/* By default use posix locks */
-#include <pthread.h>
-#define MLOCK_T pthread_mutex_t
-#define INITIAL_LOCK(l)      pthread_mutex_init(l, NULL)
-#define ACQUIRE_LOCK(l)      pthread_mutex_lock(l)
-#define RELEASE_LOCK(l)      pthread_mutex_unlock(l)
-
-#if HAVE_MORECORE
-static MLOCK_T morecore_mutex = PTHREAD_MUTEX_INITIALIZER;
-#endif /* HAVE_MORECORE */
-
-static MLOCK_T magic_init_mutex = PTHREAD_MUTEX_INITIALIZER;
-
-#else /* WIN32 */
-/*
-   Because lock-protected regions have bounded times, and there
-   are no recursive lock calls, we can use simple spinlocks.
-*/
-
-#define MLOCK_T long
-static int win32_acquire_lock (MLOCK_T *sl) {
-  for (;;) {
-#ifdef InterlockedCompareExchangePointer
-    if (!InterlockedCompareExchange(sl, 1, 0))
-      return 0;
-#else  /* Use older void* version */
-    if (!InterlockedCompareExchange((void**)sl, (void*)1, (void*)0))
-      return 0;
-#endif /* InterlockedCompareExchangePointer */
-    Sleep (0);
-  }
-}
-
-static void win32_release_lock (MLOCK_T *sl) {
-  InterlockedExchange (sl, 0);
-}
-
-#define INITIAL_LOCK(l)      *(l)=0
-#define ACQUIRE_LOCK(l)      win32_acquire_lock(l)
-#define RELEASE_LOCK(l)      win32_release_lock(l)
-#if HAVE_MORECORE
-static MLOCK_T morecore_mutex;
-#endif /* HAVE_MORECORE */
-static MLOCK_T magic_init_mutex;
-#endif /* WIN32 */
-
-#define USE_LOCK_BIT               (2U)
-#else  /* USE_LOCKS */
-#define USE_LOCK_BIT               (0U)
-#define INITIAL_LOCK(l)
-#endif /* USE_LOCKS */
-
-#if USE_LOCKS && HAVE_MORECORE
-#define ACQUIRE_MORECORE_LOCK()    ACQUIRE_LOCK(&morecore_mutex);
-#define RELEASE_MORECORE_LOCK()    RELEASE_LOCK(&morecore_mutex);
-#else /* USE_LOCKS && HAVE_MORECORE */
-#define ACQUIRE_MORECORE_LOCK()
-#define RELEASE_MORECORE_LOCK()
-#endif /* USE_LOCKS && HAVE_MORECORE */
-
-#if USE_LOCKS
-#define ACQUIRE_MAGIC_INIT_LOCK()  ACQUIRE_LOCK(&magic_init_mutex);
-#define RELEASE_MAGIC_INIT_LOCK()  RELEASE_LOCK(&magic_init_mutex);
-#else  /* USE_LOCKS */
-#define ACQUIRE_MAGIC_INIT_LOCK()
-#define RELEASE_MAGIC_INIT_LOCK()
-#endif /* USE_LOCKS */
-
-
-/* -----------------------  Chunk representations ------------------------ */
-
-/*
-  (The following includes lightly edited explanations by Colin Plumb.)
-
-  The malloc_chunk declaration below is misleading (but accurate and
-  necessary).  It declares a "view" into memory allowing access to
-  necessary fields at known offsets from a given base.
-
-  Chunks of memory are maintained using a `boundary tag' method as
-  originally described by Knuth.  (See the paper by Paul Wilson
-  ftp://ftp.cs.utexas.edu/pub/garbage/allocsrv.ps for a survey of such
-  techniques.)  Sizes of free chunks are stored both in the front of
-  each chunk and at the end.  This makes consolidating fragmented
-  chunks into bigger chunks fast.  The head fields also hold bits
-  representing whether chunks are free or in use.
-
-  Here are some pictures to make it clearer.  They are "exploded" to
-  show that the state of a chunk can be thought of as extending from
-  the high 31 bits of the head field of its header through the
-  prev_foot and PINUSE_BIT bit of the following chunk header.
-
-  A chunk that's in use looks like:
-
-   chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-           | Size of previous chunk (if P = 1)                             |
-           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |P|
-         | Size of this chunk                                         1| +-+
-   mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-         |                                                               |
-         +-                                                             -+
-         |                                                               |
-         +-                                                             -+
-         |                                                               :
-         +-      size - sizeof(size_t) available payload bytes          -+
-         :                                                               |
- chunk-> +-                                                             -+
-         |                                                               |
-         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |1|
-       | Size of next chunk (may or may not be in use)               | +-+
- mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-
-    And if it's free, it looks like this:
-
-   chunk-> +-                                                             -+
-           | User payload (must be in use, or we would have merged!)       |
-           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |P|
-         | Size of this chunk                                         0| +-+
-   mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-         | Next pointer                                                  |
-         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-         | Prev pointer                                                  |
-         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-         |                                                               :
-         +-      size - sizeof(struct chunk) unused bytes               -+
-         :                                                               |
- chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-         | Size of this chunk                                            |
-         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |0|
-       | Size of next chunk (must be in use, or we would have merged)| +-+
- mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-       |                                                               :
-       +- User payload                                                -+
-       :                                                               |
-       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-                                                                     |0|
-                                                                     +-+
-  Note that since we always merge adjacent free chunks, the chunks
-  adjacent to a free chunk must be in use.
-
-  Given a pointer to a chunk (which can be derived trivially from the
-  payload pointer) we can, in O(1) time, find out whether the adjacent
-  chunks are free, and if so, unlink them from the lists that they
-  are on and merge them with the current chunk.
-
-  Chunks always begin on even word boundaries, so the mem portion
-  (which is returned to the user) is also on an even word boundary, and
-  thus at least double-word aligned.
-
-  The P (PINUSE_BIT) bit, stored in the unused low-order bit of the
-  chunk size (which is always a multiple of two words), is an in-use
-  bit for the *previous* chunk.  If that bit is *clear*, then the
-  word before the current chunk size contains the previous chunk
-  size, and can be used to find the front of the previous chunk.
-  The very first chunk allocated always has this bit set, preventing
-  access to non-existent (or non-owned) memory. If pinuse is set for
-  any given chunk, then you CANNOT determine the size of the
-  previous chunk, and might even get a memory addressing fault when
-  trying to do so.
-
-  The C (CINUSE_BIT) bit, stored in the unused second-lowest bit of
-  the chunk size redundantly records whether the current chunk is
-  inuse. This redundancy enables usage checks within free and realloc,
-  and reduces indirection when freeing and consolidating chunks.
-
-  Each freshly allocated chunk must have both cinuse and pinuse set.
-  That is, each allocated chunk borders either a previously allocated
-  and still in-use chunk, or the base of its memory arena. This is
-  ensured by making all allocations from the the `lowest' part of any
-  found chunk.  Further, no free chunk physically borders another one,
-  so each free chunk is known to be preceded and followed by either
-  inuse chunks or the ends of memory.
-
-  Note that the `foot' of the current chunk is actually represented
-  as the prev_foot of the NEXT chunk. This makes it easier to
-  deal with alignments etc but can be very confusing when trying
-  to extend or adapt this code.
-
-  The exceptions to all this are
-
-     1. The special chunk `top' is the top-most available chunk (i.e.,
-        the one bordering the end of available memory). It is treated
-        specially.  Top is never included in any bin, is used only if
-        no other chunk is available, and is released back to the
-        system if it is very large (see M_TRIM_THRESHOLD).  In effect,
-        the top chunk is treated as larger (and thus less well
-        fitting) than any other available chunk.  The top chunk
-        doesn't update its trailing size field since there is no next
-        contiguous chunk that would have to index off it. However,
-        space is still allocated for it (TOP_FOOT_SIZE) to enable
-        separation or merging when space is extended.
-
-     3. Chunks allocated via mmap, which have the lowest-order bit
-        (IS_MMAPPED_BIT) set in their prev_foot fields, and do not set
-        PINUSE_BIT in their head fields.  Because they are allocated
-        one-by-one, each must carry its own prev_foot field, which is
-        also used to hold the offset this chunk has within its mmapped
-        region, which is needed to preserve alignment. Each mmapped
-        chunk is trailed by the first two fields of a fake next-chunk
-        for sake of usage checks.
-
-*/
-
-struct malloc_chunk {
-  size_t               prev_foot;  /* Size of previous chunk (if free).  */
-  size_t               head;       /* Size and inuse bits. */
-  struct malloc_chunk* fd;         /* double links -- used only if free. */
-  struct malloc_chunk* bk;
-};
-
-typedef struct malloc_chunk  mchunk;
-typedef struct malloc_chunk* mchunkptr;
-typedef struct malloc_chunk* sbinptr;  /* The type of bins of chunks */
-typedef unsigned int bindex_t;         /* Described below */
-typedef unsigned int binmap_t;         /* Described below */
-typedef unsigned int flag_t;           /* The type of various bit flag sets */
-
-/* ------------------- Chunks sizes and alignments ----------------------- */
-
-#define MCHUNK_SIZE         (sizeof(mchunk))
-
-#if FOOTERS
-#define CHUNK_OVERHEAD      (TWO_SIZE_T_SIZES)
-#else /* FOOTERS */
-#define CHUNK_OVERHEAD      (SIZE_T_SIZE)
-#endif /* FOOTERS */
-
-/* MMapped chunks need a second word of overhead ... */
-#define MMAP_CHUNK_OVERHEAD (TWO_SIZE_T_SIZES)
-/* ... and additional padding for fake next-chunk at foot */
-#define MMAP_FOOT_PAD       (FOUR_SIZE_T_SIZES)
-
-/* The smallest size we can malloc is an aligned minimal chunk */
-#define MIN_CHUNK_SIZE\
-  ((MCHUNK_SIZE + CHUNK_ALIGN_MASK) & ~CHUNK_ALIGN_MASK)
-
-/* conversion from malloc headers to user pointers, and back */
-#define chunk2mem(p)        ((void*)((char*)(p)       + TWO_SIZE_T_SIZES))
-#define mem2chunk(mem)      ((mchunkptr)((char*)(mem) - TWO_SIZE_T_SIZES))
-/* chunk associated with aligned address A */
-#define align_as_chunk(A)   (mchunkptr)((A) + align_offset(chunk2mem(A)))
-
-/* Bounds on request (not chunk) sizes. */
-#define MAX_REQUEST         ((-MIN_CHUNK_SIZE) << 2)
-#define MIN_REQUEST         (MIN_CHUNK_SIZE - CHUNK_OVERHEAD - SIZE_T_ONE)
-
-/* pad request bytes into a usable size */
-#define pad_request(req) \
-   (((req) + CHUNK_OVERHEAD + CHUNK_ALIGN_MASK) & ~CHUNK_ALIGN_MASK)
-
-/* pad request, checking for minimum (but not maximum) */
-#define request2size(req) \
-  (((req) < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(req))
-
-
-/* ------------------ Operations on head and foot fields ----------------- */
-
-/*
-  The head field of a chunk is or'ed with PINUSE_BIT when previous
-  adjacent chunk in use, and or'ed with CINUSE_BIT if this chunk is in
-  use. If the chunk was obtained with mmap, the prev_foot field has
-  IS_MMAPPED_BIT set, otherwise holding the offset of the base of the
-  mmapped region to the base of the chunk.
-*/
-
-#define PINUSE_BIT          (SIZE_T_ONE)
-#define CINUSE_BIT          (SIZE_T_TWO)
-#define INUSE_BITS          (PINUSE_BIT|CINUSE_BIT)
-
-/* Head value for fenceposts */
-#define FENCEPOST_HEAD      (INUSE_BITS|SIZE_T_SIZE)
-
-/* extraction of fields from head words */
-#define cinuse(p)           ((p)->head & CINUSE_BIT)
-#define pinuse(p)           ((p)->head & PINUSE_BIT)
-#define chunksize(p)        ((p)->head & ~(INUSE_BITS))
-
-#define clear_pinuse(p)     ((p)->head &= ~PINUSE_BIT)
-#define clear_cinuse(p)     ((p)->head &= ~CINUSE_BIT)
-
-/* Treat space at ptr +/- offset as a chunk */
-#define chunk_plus_offset(p, s)  ((mchunkptr)(((char*)(p)) + (s)))
-#define chunk_minus_offset(p, s) ((mchunkptr)(((char*)(p)) - (s)))
-
-/* Ptr to next or previous physical malloc_chunk. */
-#define next_chunk(p) ((mchunkptr)( ((char*)(p)) + ((p)->head & ~INUSE_BITS)))
-#define prev_chunk(p) ((mchunkptr)( ((char*)(p)) - ((p)->prev_foot) ))
-
-/* extract next chunk's pinuse bit */
-#define next_pinuse(p)  ((next_chunk(p)->head) & PINUSE_BIT)
-
-/* Get/set size at footer */
-#define get_foot(p, s)  (((mchunkptr)((char*)(p) + (s)))->prev_foot)
-#define set_foot(p, s)  (((mchunkptr)((char*)(p) + (s)))->prev_foot = (s))
-
-/* Set size, pinuse bit, and foot */
-#define set_size_and_pinuse_of_free_chunk(p, s)\
-  ((p)->head = (s|PINUSE_BIT), set_foot(p, s))
-
-/* Set size, pinuse bit, foot, and clear next pinuse */
-#define set_free_with_pinuse(p, s, n)\
-  (clear_pinuse(n), set_size_and_pinuse_of_free_chunk(p, s))
-
-#define is_mmapped(p)\
-  (!((p)->head & PINUSE_BIT) && ((p)->prev_foot & IS_MMAPPED_BIT))
-
-/* Get the internal overhead associated with chunk p */
-#define overhead_for(p)\
- (is_mmapped(p)? MMAP_CHUNK_OVERHEAD : CHUNK_OVERHEAD)
-
-/* Return true if malloced space is not necessarily cleared */
-#if MMAP_CLEARS
-#define calloc_must_clear(p) (!is_mmapped(p))
-#else /* MMAP_CLEARS */
-#define calloc_must_clear(p) (1)
-#endif /* MMAP_CLEARS */
-
-/* ---------------------- Overlaid data structures ----------------------- */
-
-/*
-  When chunks are not in use, they are treated as nodes of either
-  lists or trees.
-
-  "Small"  chunks are stored in circular doubly-linked lists, and look
-  like this:
-
-    chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-            |             Size of previous chunk                            |
-            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-    `head:' |             Size of chunk, in bytes                         |P|
-      mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-            |             Forward pointer to next chunk in list             |
-            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-            |             Back pointer to previous chunk in list            |
-            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-            |             Unused space (may be 0 bytes long)                .
-            .                                                               .
-            .                                                               |
-nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-    `foot:' |             Size of chunk, in bytes                           |
-            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-
-  Larger chunks are kept in a form of bitwise digital trees (aka
-  tries) keyed on chunksizes.  Because malloc_tree_chunks are only for
-  free chunks greater than 256 bytes, their size doesn't impose any
-  constraints on user chunk sizes.  Each node looks like:
-
-    chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-            |             Size of previous chunk                            |
-            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-    `head:' |             Size of chunk, in bytes                         |P|
-      mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-            |             Forward pointer to next chunk of same size        |
-            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-            |             Back pointer to previous chunk of same size       |
-            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-            |             Pointer to left child (child[0])                  |
-            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-            |             Pointer to right child (child[1])                 |
-            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-            |             Pointer to parent                                 |
-            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-            |             bin index of this chunk                           |
-            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-            |             Unused space                                      .
-            .                                                               |
-nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-    `foot:' |             Size of chunk, in bytes                           |
-            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-
-  Each tree holding treenodes is a tree of unique chunk sizes.  Chunks
-  of the same size are arranged in a circularly-linked list, with only
-  the oldest chunk (the next to be used, in our FIFO ordering)
-  actually in the tree.  (Tree members are distinguished by a non-null
-  parent pointer.)  If a chunk with the same size an an existing node
-  is inserted, it is linked off the existing node using pointers that
-  work in the same way as fd/bk pointers of small chunks.
-
-  Each tree contains a power of 2 sized range of chunk sizes (the
-  smallest is 0x100 <= x < 0x180), which is is divided in half at each
-  tree level, with the chunks in the smaller half of the range (0x100
-  <= x < 0x140 for the top nose) in the left subtree and the larger
-  half (0x140 <= x < 0x180) in the right subtree.  This is, of course,
-  done by inspecting individual bits.
-
-  Using these rules, each node's left subtree contains all smaller
-  sizes than its right subtree.  However, the node at the root of each
-  subtree has no particular ordering relationship to either.  (The
-  dividing line between the subtree sizes is based on trie relation.)
-  If we remove the last chunk of a given size from the interior of the
-  tree, we need to replace it with a leaf node.  The tree ordering
-  rules permit a node to be replaced by any leaf below it.
-
-  The smallest chunk in a tree (a common operation in a best-fit
-  allocator) can be found by walking a path to the leftmost leaf in
-  the tree.  Unlike a usual binary tree, where we follow left child
-  pointers until we reach a null, here we follow the right child
-  pointer any time the left one is null, until we reach a leaf with
-  both child pointers null. The smallest chunk in the tree will be
-  somewhere along that path.
-
-  The worst case number of steps to add, find, or remove a node is
-  bounded by the number of bits differentiating chunks within
-  bins. Under current bin calculations, this ranges from 6 up to 21
-  (for 32 bit sizes) or up to 53 (for 64 bit sizes). The typical case
-  is of course much better.
-*/
-
-struct malloc_tree_chunk {
-  /* The first four fields must be compatible with malloc_chunk */
-  size_t                    prev_foot;
-  size_t                    head;
-  struct malloc_tree_chunk* fd;
-  struct malloc_tree_chunk* bk;
-
-  struct malloc_tree_chunk* child[2];
-  struct malloc_tree_chunk* parent;
-  bindex_t                  index;
-};
-
-typedef struct malloc_tree_chunk  tchunk;
-typedef struct malloc_tree_chunk* tchunkptr;
-typedef struct malloc_tree_chunk* tbinptr; /* The type of bins of trees */
-
-/* A little helper macro for trees */
-#define leftmost_child(t) ((t)->child[0] != 0? (t)->child[0] : (t)->child[1])
-
-/* ----------------------------- Segments -------------------------------- */
-
-/*
-  Each malloc space may include non-contiguous segments, held in a
-  list headed by an embedded malloc_segment record representing the
-  top-most space. Segments also include flags holding properties of
-  the space. Large chunks that are directly allocated by mmap are not
-  included in this list. They are instead independently created and
-  destroyed without otherwise keeping track of them.
-
-  Segment management mainly comes into play for spaces allocated by
-  MMAP.  Any call to MMAP might or might not return memory that is
-  adjacent to an existing segment.  MORECORE normally contiguously
-  extends the current space, so this space is almost always adjacent,
-  which is simpler and faster to deal with. (This is why MORECORE is
-  used preferentially to MMAP when both are available -- see
-  sys_alloc.)  When allocating using MMAP, we don't use any of the
-  hinting mechanisms (inconsistently) supported in various
-  implementations of unix mmap, or distinguish reserving from
-  committing memory. Instead, we just ask for space, and exploit
-  contiguity when we get it.  It is probably possible to do
-  better than this on some systems, but no general scheme seems
-  to be significantly better.
-
-  Management entails a simpler variant of the consolidation scheme
-  used for chunks to reduce fragmentation -- new adjacent memory is
-  normally prepended or appended to an existing segment. However,
-  there are limitations compared to chunk consolidation that mostly
-  reflect the fact that segment processing is relatively infrequent
-  (occurring only when getting memory from system) and that we
-  don't expect to have huge numbers of segments:
-
-  * Segments are not indexed, so traversal requires linear scans.  (It
-    would be possible to index these, but is not worth the extra
-    overhead and complexity for most programs on most platforms.)
-  * New segments are only appended to old ones when holding top-most
-    memory; if they cannot be prepended to others, they are held in
-    different segments.
-
-  Except for the top-most segment of an mstate, each segment record
-  is kept at the tail of its segment. Segments are added by pushing
-  segment records onto the list headed by &mstate.seg for the
-  containing mstate.
-
-  Segment flags control allocation/merge/deallocation policies:
-  * If EXTERN_BIT set, then we did not allocate this segment,
-    and so should not try to deallocate or merge with others.
-    (This currently holds only for the initial segment passed
-    into create_mspace_with_base.)
-  * If IS_MMAPPED_BIT set, the segment may be merged with
-    other surrounding mmapped segments and trimmed/de-allocated
-    using munmap.
-  * If neither bit is set, then the segment was obtained using
-    MORECORE so can be merged with surrounding MORECORE'd segments
-    and deallocated/trimmed using MORECORE with negative arguments.
-*/
-
-struct malloc_segment {
-  char*        base;             /* base address */
-  size_t       size;             /* allocated size */
-  struct malloc_segment* next;   /* ptr to next segment */
-  flag_t       sflags;           /* mmap and extern flag */
-};
-
-#define is_mmapped_segment(S)  ((S)->sflags & IS_MMAPPED_BIT)
-#define is_extern_segment(S)   ((S)->sflags & EXTERN_BIT)
-
-typedef struct malloc_segment  msegment;
-typedef struct malloc_segment* msegmentptr;
-
-/* ---------------------------- malloc_state ----------------------------- */
-
-/*
-   A malloc_state holds all of the bookkeeping for a space.
-   The main fields are:
-
-  Top
-    The topmost chunk of the currently active segment. Its size is
-    cached in topsize.  The actual size of topmost space is
-    topsize+TOP_FOOT_SIZE, which includes space reserved for adding
-    fenceposts and segment records if necessary when getting more
-    space from the system.  The size at which to autotrim top is
-    cached from mparams in trim_check, except that it is disabled if
-    an autotrim fails.
-
-  Designated victim (dv)
-    This is the preferred chunk for servicing small requests that
-    don't have exact fits.  It is normally the chunk split off most
-    recently to service another small request.  Its size is cached in
-    dvsize. The link fields of this chunk are not maintained since it
-    is not kept in a bin.
-
-  SmallBins
-    An array of bin headers for free chunks.  These bins hold chunks
-    with sizes less than MIN_LARGE_SIZE bytes. Each bin contains
-    chunks of all the same size, spaced 8 bytes apart.  To simplify
-    use in double-linked lists, each bin header acts as a malloc_chunk
-    pointing to the real first node, if it exists (else pointing to
-    itself).  This avoids special-casing for headers.  But to avoid
-    waste, we allocate only the fd/bk pointers of bins, and then use
-    repositioning tricks to treat these as the fields of a chunk.
-
-  TreeBins
-    Treebins are pointers to the roots of trees holding a range of
-    sizes. There are 2 equally spaced treebins for each power of two
-    from TREE_SHIFT to TREE_SHIFT+16. The last bin holds anything
-    larger.
-
-  Bin maps
-    There is one bit map for small bins ("smallmap") and one for
-    treebins ("treemap).  Each bin sets its bit when non-empty, and
-    clears the bit when empty.  Bit operations are then used to avoid
-    bin-by-bin searching -- nearly all "search" is done without ever
-    looking at bins that won't be selected.  The bit maps
-    conservatively use 32 bits per map word, even if on 64bit system.
-    For a good description of some of the bit-based techniques used
-    here, see Henry S. Warren Jr's book "Hacker's Delight" (and
-    supplement at http://hackersdelight.org/). Many of these are
-    intended to reduce the branchiness of paths through malloc etc, as
-    well as to reduce the number of memory locations read or written.
-
-  Segments
-    A list of segments headed by an embedded malloc_segment record
-    representing the initial space.
-
-  Address check support
-    The least_addr field is the least address ever obtained from
-    MORECORE or MMAP. Attempted frees and reallocs of any address less
-    than this are trapped (unless INSECURE is defined).
-
-  Magic tag
-    A cross-check field that should always hold same value as mparams.magic.
-
-  Flags
-    Bits recording whether to use MMAP, locks, or contiguous MORECORE
-
-  Statistics
-    Each space keeps track of current and maximum system memory
-    obtained via MORECORE or MMAP.
-
-  Locking
-    If USE_LOCKS is defined, the "mutex" lock is acquired and released
-    around every public call using this mspace.
-*/
-
-/* Bin types, widths and sizes */
-#define NSMALLBINS        (32U)
-#define NTREEBINS         (32U)
-#define SMALLBIN_SHIFT    (3U)
-#define SMALLBIN_WIDTH    (SIZE_T_ONE << SMALLBIN_SHIFT)
-#define TREEBIN_SHIFT     (8U)
-#define MIN_LARGE_SIZE    (SIZE_T_ONE << TREEBIN_SHIFT)
-#define MAX_SMALL_SIZE    (MIN_LARGE_SIZE - SIZE_T_ONE)
-#define MAX_SMALL_REQUEST (MAX_SMALL_SIZE - CHUNK_ALIGN_MASK - CHUNK_OVERHEAD)
-
-struct malloc_state {
-  binmap_t   smallmap;
-  binmap_t   treemap;
-  size_t     dvsize;
-  size_t     topsize;
-  char*      least_addr;
-  mchunkptr  dv;
-  mchunkptr  top;
-  size_t     trim_check;
-  size_t     magic;
-  mchunkptr  smallbins[(NSMALLBINS+1)*2];
-  tbinptr    treebins[NTREEBINS];
-  size_t     footprint;
-  size_t     max_footprint;
-  flag_t     mflags;
-#if USE_LOCKS
-  MLOCK_T    mutex;     /* locate lock among fields that rarely change */
-#endif /* USE_LOCKS */
-  msegment   seg;
-};
-
-typedef struct malloc_state*    mstate;
-
-/* ------------- Global malloc_state and malloc_params ------------------- */
-
-/*
-  malloc_params holds global properties, including those that can be
-  dynamically set using mallopt. There is a single instance, mparams,
-  initialized in init_mparams.
-*/
-
-struct malloc_params {
-  size_t magic;
-  size_t page_size;
-  size_t granularity;
-  size_t mmap_threshold;
-  size_t trim_threshold;
-  flag_t default_mflags;
-};
-
-static struct malloc_params mparams;
-
-/* The global malloc_state used for all non-"mspace" calls */
-static struct malloc_state _gm_;
-#define gm                 (&_gm_)
-#define is_global(M)       ((M) == &_gm_)
-#define is_initialized(M)  ((M)->top != 0)
-
-/* -------------------------- system alloc setup ------------------------- */
-
-/* Operations on mflags */
-
-#define use_lock(M)           ((M)->mflags &   USE_LOCK_BIT)
-#define enable_lock(M)        ((M)->mflags |=  USE_LOCK_BIT)
-#define disable_lock(M)       ((M)->mflags &= ~USE_LOCK_BIT)
-
-#define use_mmap(M)           ((M)->mflags &   USE_MMAP_BIT)
-#define enable_mmap(M)        ((M)->mflags |=  USE_MMAP_BIT)
-#define disable_mmap(M)       ((M)->mflags &= ~USE_MMAP_BIT)
-
-#define use_noncontiguous(M)  ((M)->mflags &   USE_NONCONTIGUOUS_BIT)
-#define disable_contiguous(M) ((M)->mflags |=  USE_NONCONTIGUOUS_BIT)
-
-#define set_lock(M,L)\
- ((M)->mflags = (L)?\
-  ((M)->mflags | USE_LOCK_BIT) :\
-  ((M)->mflags & ~USE_LOCK_BIT))
-
-/* page-align a size */
-#define page_align(S)\
- (((S) + (mparams.page_size)) & ~(mparams.page_size - SIZE_T_ONE))
-
-/* granularity-align a size */
-#define granularity_align(S)\
-  (((S) + (mparams.granularity)) & ~(mparams.granularity - SIZE_T_ONE))
-
-#define is_page_aligned(S)\
-   (((size_t)(S) & (mparams.page_size - SIZE_T_ONE)) == 0)
-#define is_granularity_aligned(S)\
-   (((size_t)(S) & (mparams.granularity - SIZE_T_ONE)) == 0)
-
-/*  True if segment S holds address A */
-#define segment_holds(S, A)\
-  ((char*)(A) >= S->base && (char*)(A) < S->base + S->size)
-
-/* Return segment holding given address */
-static msegmentptr segment_holding(mstate m, char* addr) {
-  msegmentptr sp = &m->seg;
-  for (;;) {
-    if (addr >= sp->base && addr < sp->base + sp->size)
-      return sp;
-    if ((sp = sp->next) == 0)
-      return 0;
-  }
-}
-
-/* Return true if segment contains a segment link */
-static int has_segment_link(mstate m, msegmentptr ss) {
-  msegmentptr sp = &m->seg;
-  for (;;) {
-    if ((char*)sp >= ss->base && (char*)sp < ss->base + ss->size)
-      return 1;
-    if ((sp = sp->next) == 0)
-      return 0;
-  }
-}
-
-#ifndef MORECORE_CANNOT_TRIM
-#define should_trim(M,s)  ((s) > (M)->trim_check)
-#else  /* MORECORE_CANNOT_TRIM */
-#define should_trim(M,s)  (0)
-#endif /* MORECORE_CANNOT_TRIM */
-
-/*
-  TOP_FOOT_SIZE is padding at the end of a segment, including space
-  that may be needed to place segment records and fenceposts when new
-  noncontiguous segments are added.
-*/
-#define TOP_FOOT_SIZE\
-  (align_offset(chunk2mem(0))+pad_request(sizeof(struct malloc_segment))+MIN_CHUNK_SIZE)
-
-
-/* -------------------------------  Hooks -------------------------------- */
-
-/*
-  PREACTION should be defined to return 0 on success, and nonzero on
-  failure. If you are not using locking, you can redefine these to do
-  anything you like.
-*/
-
-#if USE_LOCKS
-
-/* Ensure locks are initialized */
-#define GLOBALLY_INITIALIZE() (mparams.page_size == 0 && init_mparams())
-
-#define PREACTION(M)  ((GLOBALLY_INITIALIZE() || use_lock(M))? ACQUIRE_LOCK(&(M)->mutex) : 0)
-#define POSTACTION(M) { if (use_lock(M)) RELEASE_LOCK(&(M)->mutex); }
-#else /* USE_LOCKS */
-
-#ifndef PREACTION
-#define PREACTION(M) (0)
-#endif  /* PREACTION */
-
-#ifndef POSTACTION
-#define POSTACTION(M)
-#endif  /* POSTACTION */
-
-#endif /* USE_LOCKS */
-
-/*
-  CORRUPTION_ERROR_ACTION is triggered upon detected bad addresses.
-  USAGE_ERROR_ACTION is triggered on detected bad frees and
-  reallocs. The argument p is an address that might have triggered the
-  fault. It is ignored by the two predefined actions, but might be
-  useful in custom actions that try to help diagnose errors.
-*/
-
-#if PROCEED_ON_ERROR
-
-/* A count of the number of corruption errors causing resets */
-int malloc_corruption_error_count;
-
-/* default corruption action */
-static void reset_on_error(mstate m);
-
-#define CORRUPTION_ERROR_ACTION(m)  reset_on_error(m)
-#define USAGE_ERROR_ACTION(m, p)
-
-#else /* PROCEED_ON_ERROR */
-
-#ifndef CORRUPTION_ERROR_ACTION
-#define CORRUPTION_ERROR_ACTION(m) ABORT
-#endif /* CORRUPTION_ERROR_ACTION */
-
-#ifndef USAGE_ERROR_ACTION
-#define USAGE_ERROR_ACTION(m,p) ABORT
-#endif /* USAGE_ERROR_ACTION */
-
-#endif /* PROCEED_ON_ERROR */
-
-/* -------------------------- Debugging setup ---------------------------- */
-
-#if ! DEBUG
-
-#define check_free_chunk(M,P)
-#define check_inuse_chunk(M,P)
-#define check_malloced_chunk(M,P,N)
-#define check_mmapped_chunk(M,P)
-#define check_malloc_state(M)
-#define check_top_chunk(M,P)
-
-#else /* DEBUG */
-#define check_free_chunk(M,P)       do_check_free_chunk(M,P)
-#define check_inuse_chunk(M,P)      do_check_inuse_chunk(M,P)
-#define check_top_chunk(M,P)        do_check_top_chunk(M,P)
-#define check_malloced_chunk(M,P,N) do_check_malloced_chunk(M,P,N)
-#define check_mmapped_chunk(M,P)    do_check_mmapped_chunk(M,P)
-#define check_malloc_state(M)       do_check_malloc_state(M)
-
-static void   do_check_any_chunk(mstate m, mchunkptr p);
-static void   do_check_top_chunk(mstate m, mchunkptr p);
-static void   do_check_mmapped_chunk(mstate m, mchunkptr p);
-static void   do_check_inuse_chunk(mstate m, mchunkptr p);
-static void   do_check_free_chunk(mstate m, mchunkptr p);
-static void   do_check_malloced_chunk(mstate m, void* mem, size_t s);
-static void   do_check_tree(mstate m, tchunkptr t);
-static void   do_check_treebin(mstate m, bindex_t i);
-static void   do_check_smallbin(mstate m, bindex_t i);
-static void   do_check_malloc_state(mstate m);
-static int    bin_find(mstate m, mchunkptr x);
-static size_t traverse_and_check(mstate m);
-#endif /* DEBUG */
-
-/* ---------------------------- Indexing Bins ---------------------------- */
-
-#define is_small(s)         (((s) >> SMALLBIN_SHIFT) < NSMALLBINS)
-#define small_index(s)      ((s)  >> SMALLBIN_SHIFT)
-#define small_index2size(i) ((i)  << SMALLBIN_SHIFT)
-#define MIN_SMALL_INDEX     (small_index(MIN_CHUNK_SIZE))
-
-/* addressing by index. See above about smallbin repositioning */
-#define smallbin_at(M, i)   ((sbinptr)((char*)&((M)->smallbins[(i)<<1])))
-#define treebin_at(M,i)     (&((M)->treebins[i]))
-
-/* assign tree index for size S to variable I */
-#if defined(__GNUC__) && defined(i386) && defined(ASSEMBLY_VERSION)
-#define compute_tree_index(S, I)\
-{\
-  size_t X = S >> TREEBIN_SHIFT;\
-  if (X == 0)\
-    I = 0;\
-  else if (X > 0xFFFF)\
-    I = NTREEBINS-1;\
-  else {\
-    unsigned int K;\
-    __asm__("bsrl %1,%0\n\t" : "=r" (K) : "rm"  (X));\
-    I =  (bindex_t)((K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1)));\
-  }\
-}
-#else /* GNUC */
-#define compute_tree_index(S, I)\
-{\
-  size_t X = S >> TREEBIN_SHIFT;\
-  if (X == 0)\
-    I = 0;\
-  else if (X > 0xFFFF)\
-    I = NTREEBINS-1;\
-  else {\
-    unsigned int Y = (unsigned int)X;\
-    unsigned int N = ((Y - 0x100) >> 16) & 8;\
-    unsigned int K = (((Y <<= N) - 0x1000) >> 16) & 4;\
-    N += K;\
-    N += K = (((Y <<= K) - 0x4000) >> 16) & 2;\
-    K = 14 - N + ((Y <<= K) >> 15);\
-    I = (K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1));\
-  }\
-}
-#endif /* GNUC */
-
-/* Bit representing maximum resolved size in a treebin at i */
-#define bit_for_tree_index(i) \
-   (i == NTREEBINS-1)? (SIZE_T_BITSIZE-1) : (((i) >> 1) + TREEBIN_SHIFT - 2)
-
-/* Shift placing maximum resolved bit in a treebin at i as sign bit */
-#define leftshift_for_tree_index(i) \
-   ((i == NTREEBINS-1)? 0 : \
-    ((SIZE_T_BITSIZE-SIZE_T_ONE) - (((i) >> 1) + TREEBIN_SHIFT - 2)))
-
-/* The size of the smallest chunk held in bin with index i */
-#define minsize_for_tree_index(i) \
-   ((SIZE_T_ONE << (((i) >> 1) + TREEBIN_SHIFT)) |  \
-   (((size_t)((i) & SIZE_T_ONE)) << (((i) >> 1) + TREEBIN_SHIFT - 1)))
-
-
-/* ------------------------ Operations on bin maps ----------------------- */
-
-/* bit corresponding to given index */
-#define idx2bit(i)              ((binmap_t)(1) << (i))
-
-/* Mark/Clear bits with given index */
-#define mark_smallmap(M,i)      ((M)->smallmap |=  idx2bit(i))
-#define clear_smallmap(M,i)     ((M)->smallmap &= ~idx2bit(i))
-#define smallmap_is_marked(M,i) ((M)->smallmap &   idx2bit(i))
-
-#define mark_treemap(M,i)       ((M)->treemap  |=  idx2bit(i))
-#define clear_treemap(M,i)      ((M)->treemap  &= ~idx2bit(i))
-#define treemap_is_marked(M,i)  ((M)->treemap  &   idx2bit(i))
-
-/* index corresponding to given bit */
-
-#if defined(__GNUC__) && defined(i386) && defined(ASSEMBLY_VERSION)
-#define compute_bit2idx(X, I)\
-{\
-  unsigned int J;\
-  __asm__("bsfl %1,%0\n\t" : "=r" (J) : "rm" (X));\
-  I = (bindex_t)J;\
-}
-
-#else /* GNUC */
-#if  USE_BUILTIN_FFS
-#define compute_bit2idx(X, I) I = ffs(X)-1
-
-#else /* USE_BUILTIN_FFS */
-#define compute_bit2idx(X, I)\
-{\
-  unsigned int Y = X - 1;\
-  unsigned int K = Y >> (16-4) & 16;\
-  unsigned int N = K;        Y >>= K;\
-  N += K = Y >> (8-3) &  8;  Y >>= K;\
-  N += K = Y >> (4-2) &  4;  Y >>= K;\
-  N += K = Y >> (2-1) &  2;  Y >>= K;\
-  N += K = Y >> (1-0) &  1;  Y >>= K;\
-  I = (bindex_t)(N + Y);\
-}
-#endif /* USE_BUILTIN_FFS */
-#endif /* GNUC */
-
-/* isolate the least set bit of a bitmap */
-#define least_bit(x)         ((x) & -(x))
-
-/* mask with all bits to left of least bit of x on */
-#define left_bits(x)         ((x<<1) | -(x<<1))
-
-/* mask with all bits to left of or equal to least bit of x on */
-#define same_or_left_bits(x) ((x) | -(x))
-
-
-/* ----------------------- Runtime Check Support ------------------------- */
-
-/*
-  For security, the main invariant is that malloc/free/etc never
-  writes to a static address other than malloc_state, unless static
-  malloc_state itself has been corrupted, which cannot occur via
-  malloc (because of these checks). In essence this means that we
-  believe all pointers, sizes, maps etc held in malloc_state, but
-  check all of those linked or offsetted from other embedded data
-  structures.  These checks are interspersed with main code in a way
-  that tends to minimize their run-time cost.
-
-  When FOOTERS is defined, in addition to range checking, we also
-  verify footer fields of inuse chunks, which can be used guarantee
-  that the mstate controlling malloc/free is intact.  This is a
-  streamlined version of the approach described by William Robertson
-  et al in "Run-time Detection of Heap-based Overflows" LISA'03
-  http://www.usenix.org/events/lisa03/tech/robertson.html The footer
-  of an inuse chunk holds the xor of its mstate and a random seed,
-  that is checked upon calls to free() and realloc().  This is
-  (probablistically) unguessable from outside the program, but can be
-  computed by any code successfully malloc'ing any chunk, so does not
-  itself provide protection against code that has already broken
-  security through some other means.  Unlike Robertson et al, we
-  always dynamically check addresses of all offset chunks (previous,
-  next, etc). This turns out to be cheaper than relying on hashes.
-*/
-
-#if !INSECURE
-/* Check if address a is at least as high as any from MORECORE or MMAP */
-#define ok_address(M, a) ((char*)(a) >= (M)->least_addr)
-/* Check if address of next chunk n is higher than base chunk p */
-#define ok_next(p, n)    ((char*)(p) < (char*)(n))
-/* Check if p has its cinuse bit on */
-#define ok_cinuse(p)     cinuse(p)
-/* Check if p has its pinuse bit on */
-#define ok_pinuse(p)     pinuse(p)
-
-#else /* !INSECURE */
-#define ok_address(M, a) (1)
-#define ok_next(b, n)    (1)
-#define ok_cinuse(p)     (1)
-#define ok_pinuse(p)     (1)
-#endif /* !INSECURE */
-
-#if (FOOTERS && !INSECURE)
-/* Check if (alleged) mstate m has expected magic field */
-#define ok_magic(M)      ((M)->magic == mparams.magic)
-#else  /* (FOOTERS && !INSECURE) */
-#define ok_magic(M)      (1)
-#endif /* (FOOTERS && !INSECURE) */
-
-
-/* In gcc, use __builtin_expect to minimize impact of checks */
-#if !INSECURE
-#if defined(__GNUC__) && __GNUC__ >= 3
-#define RTCHECK(e)  __builtin_expect(e, 1)
-#else /* GNUC */
-#define RTCHECK(e)  (e)
-#endif /* GNUC */
-#else /* !INSECURE */
-#define RTCHECK(e)  (1)
-#endif /* !INSECURE */
-
-/* macros to set up inuse chunks with or without footers */
-
-#if !FOOTERS
-
-#define mark_inuse_foot(M,p,s)
-
-/* Set cinuse bit and pinuse bit of next chunk */
-#define set_inuse(M,p,s)\
-  ((p)->head = (((p)->head & PINUSE_BIT)|s|CINUSE_BIT),\
-  ((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT)
-
-/* Set cinuse and pinuse of this chunk and pinuse of next chunk */
-#define set_inuse_and_pinuse(M,p,s)\
-  ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\
-  ((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT)
-
-/* Set size, cinuse and pinuse bit of this chunk */
-#define set_size_and_pinuse_of_inuse_chunk(M, p, s)\
-  ((p)->head = (s|PINUSE_BIT|CINUSE_BIT))
-
-#else /* FOOTERS */
-
-/* Set foot of inuse chunk to be xor of mstate and seed */
-#define mark_inuse_foot(M,p,s)\
-  (((mchunkptr)((char*)(p) + (s)))->prev_foot = ((size_t)(M) ^ mparams.magic))
-
-#define get_mstate_for(p)\
-  ((mstate)(((mchunkptr)((char*)(p) +\
-    (chunksize(p))))->prev_foot ^ mparams.magic))
-
-#define set_inuse(M,p,s)\
-  ((p)->head = (((p)->head & PINUSE_BIT)|s|CINUSE_BIT),\
-  (((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT), \
-  mark_inuse_foot(M,p,s))
-
-#define set_inuse_and_pinuse(M,p,s)\
-  ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\
-  (((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT),\
- mark_inuse_foot(M,p,s))
-
-#define set_size_and_pinuse_of_inuse_chunk(M, p, s)\
-  ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\
-  mark_inuse_foot(M, p, s))
-
-#endif /* !FOOTERS */
-
-/* ---------------------------- setting mparams -------------------------- */
-
-/* Initialize mparams */
-static int init_mparams(void) {
-  if (mparams.page_size == 0) {
-    size_t s;
-
-    mparams.mmap_threshold = DEFAULT_MMAP_THRESHOLD;
-    mparams.trim_threshold = DEFAULT_TRIM_THRESHOLD;
-#if MORECORE_CONTIGUOUS
-    mparams.default_mflags = USE_LOCK_BIT|USE_MMAP_BIT;
-#else  /* MORECORE_CONTIGUOUS */
-    mparams.default_mflags = USE_LOCK_BIT|USE_MMAP_BIT|USE_NONCONTIGUOUS_BIT;
-#endif /* MORECORE_CONTIGUOUS */
-
-#if (FOOTERS && !INSECURE)
-    {
-#if USE_DEV_RANDOM
-      int fd;
-      unsigned char buf[sizeof(size_t)];
-      /* Try to use /dev/urandom, else fall back on using time */
-      if ((fd = open("/dev/urandom", O_RDONLY)) >= 0 &&
-          read(fd, buf, sizeof(buf)) == sizeof(buf)) {
-        s = *((size_t *) buf);
-        close(fd);
-      }
-      else
-#endif /* USE_DEV_RANDOM */
-        s = (size_t)(time(0) ^ (size_t)0x55555555U);
-
-      s |= (size_t)8U;    /* ensure nonzero */
-      s &= ~(size_t)7U;   /* improve chances of fault for bad values */
-
-    }
-#else /* (FOOTERS && !INSECURE) */
-    s = (size_t)0x58585858U;
-#endif /* (FOOTERS && !INSECURE) */
-    ACQUIRE_MAGIC_INIT_LOCK();
-    if (mparams.magic == 0) {
-      mparams.magic = s;
-      /* Set up lock for main malloc area */
-      INITIAL_LOCK(&gm->mutex);
-      gm->mflags = mparams.default_mflags;
-    }
-    RELEASE_MAGIC_INIT_LOCK();
-
-#ifndef WIN32
-    mparams.page_size = malloc_getpagesize;
-    mparams.granularity = ((DEFAULT_GRANULARITY != 0)?
-                           DEFAULT_GRANULARITY : mparams.page_size);
-#else /* WIN32 */
-    {
-      SYSTEM_INFO system_info;
-      GetSystemInfo(&system_info);
-      mparams.page_size = system_info.dwPageSize;
-      mparams.granularity = system_info.dwAllocationGranularity;
-    }
-#endif /* WIN32 */
-
-    /* Sanity-check configuration:
-       size_t must be unsigned and as wide as pointer type.
-       ints must be at least 4 bytes.
-       alignment must be at least 8.
-       Alignment, min chunk size, and page size must all be powers of 2.
-    */
-    if ((sizeof(size_t) != sizeof(char*)) ||
-        (MAX_SIZE_T < MIN_CHUNK_SIZE)  ||
-        (sizeof(int) < 4)  ||
-        (MALLOC_ALIGNMENT < (size_t)8U) ||
-        ((MALLOC_ALIGNMENT    & (MALLOC_ALIGNMENT-SIZE_T_ONE))    != 0) ||
-        ((MCHUNK_SIZE         & (MCHUNK_SIZE-SIZE_T_ONE))         != 0) ||
-        ((mparams.granularity & (mparams.granularity-SIZE_T_ONE)) != 0) ||
-        ((mparams.page_size   & (mparams.page_size-SIZE_T_ONE))   != 0))
-      ABORT;
-  }
-  return 0;
-}
-
-/* support for mallopt */
-static int change_mparam(int param_number, int value) {
-  size_t val = (size_t)value;
-  init_mparams();
-  switch(param_number) {
-  case M_TRIM_THRESHOLD:
-    mparams.trim_threshold = val;
-    return 1;
-  case M_GRANULARITY:
-    if (val >= mparams.page_size && ((val & (val-1)) == 0)) {
-      mparams.granularity = val;
-      return 1;
-    }
-    else
-      return 0;
-  case M_MMAP_THRESHOLD:
-    mparams.mmap_threshold = val;
-    return 1;
-  default:
-    return 0;
-  }
-}
-
-#if DEBUG
-/* ------------------------- Debugging Support --------------------------- */
-
-/* Check properties of any chunk, whether free, inuse, mmapped etc  */
-static void do_check_any_chunk(mstate m, mchunkptr p) {
-  assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD));
-  assert(ok_address(m, p));
-}
-
-/* Check properties of top chunk */
-static void do_check_top_chunk(mstate m, mchunkptr p) {
-  msegmentptr sp = segment_holding(m, (char*)p);
-  size_t  sz = chunksize(p);
-  assert(sp != 0);
-  assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD));
-  assert(ok_address(m, p));
-  assert(sz == m->topsize);
-  assert(sz > 0);
-  assert(sz == ((sp->base + sp->size) - (char*)p) - TOP_FOOT_SIZE);
-  assert(pinuse(p));
-  assert(!next_pinuse(p));
-}
-
-/* Check properties of (inuse) mmapped chunks */
-static void do_check_mmapped_chunk(mstate m, mchunkptr p) {
-  size_t  sz = chunksize(p);
-  size_t len = (sz + (p->prev_foot & ~IS_MMAPPED_BIT) + MMAP_FOOT_PAD);
-  assert(is_mmapped(p));
-  assert(use_mmap(m));
-  assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD));
-  assert(ok_address(m, p));
-  assert(!is_small(sz));
-  assert((len & (mparams.page_size-SIZE_T_ONE)) == 0);
-  assert(chunk_plus_offset(p, sz)->head == FENCEPOST_HEAD);
-  assert(chunk_plus_offset(p, sz+SIZE_T_SIZE)->head == 0);
-}
-
-/* Check properties of inuse chunks */
-static void do_check_inuse_chunk(mstate m, mchunkptr p) {
-  do_check_any_chunk(m, p);
-  assert(cinuse(p));
-  assert(next_pinuse(p));
-  /* If not pinuse and not mmapped, previous chunk has OK offset */
-  assert(is_mmapped(p) || pinuse(p) || next_chunk(prev_chunk(p)) == p);
-  if (is_mmapped(p))
-    do_check_mmapped_chunk(m, p);
-}
-
-/* Check properties of free chunks */
-static void do_check_free_chunk(mstate m, mchunkptr p) {
-  size_t sz = p->head & ~(PINUSE_BIT|CINUSE_BIT);
-  mchunkptr next = chunk_plus_offset(p, sz);
-  do_check_any_chunk(m, p);
-  assert(!cinuse(p));
-  assert(!next_pinuse(p));
-  assert (!is_mmapped(p));
-  if (p != m->dv && p != m->top) {
-    if (sz >= MIN_CHUNK_SIZE) {
-      assert((sz & CHUNK_ALIGN_MASK) == 0);
-      assert(is_aligned(chunk2mem(p)));
-      assert(next->prev_foot == sz);
-      assert(pinuse(p));
-      assert (next == m->top || cinuse(next));
-      assert(p->fd->bk == p);
-      assert(p->bk->fd == p);
-    }
-    else  /* markers are always of size SIZE_T_SIZE */
-      assert(sz == SIZE_T_SIZE);
-  }
-}
-
-/* Check properties of malloced chunks at the point they are malloced */
-static void do_check_malloced_chunk(mstate m, void* mem, size_t s) {
-  if (mem != 0) {
-    mchunkptr p = mem2chunk(mem);
-    size_t sz = p->head & ~(PINUSE_BIT|CINUSE_BIT);
-    do_check_inuse_chunk(m, p);
-    assert((sz & CHUNK_ALIGN_MASK) == 0);
-    assert(sz >= MIN_CHUNK_SIZE);
-    assert(sz >= s);
-    /* unless mmapped, size is less than MIN_CHUNK_SIZE more than request */
-    assert(is_mmapped(p) || sz < (s + MIN_CHUNK_SIZE));
-  }
-}
-
-/* Check a tree and its subtrees.  */
-static void do_check_tree(mstate m, tchunkptr t) {
-  tchunkptr head = 0;
-  tchunkptr u = t;
-  bindex_t tindex = t->index;
-  size_t tsize = chunksize(t);
-  bindex_t idx;
-  compute_tree_index(tsize, idx);
-  assert(tindex == idx);
-  assert(tsize >= MIN_LARGE_SIZE);
-  assert(tsize >= minsize_for_tree_index(idx));
-  assert((idx == NTREEBINS-1) || (tsize < minsize_for_tree_index((idx+1))));
-
-  do { /* traverse through chain of same-sized nodes */
-    do_check_any_chunk(m, ((mchunkptr)u));
-    assert(u->index == tindex);
-    assert(chunksize(u) == tsize);
-    assert(!cinuse(u));
-    assert(!next_pinuse(u));
-    assert(u->fd->bk == u);
-    assert(u->bk->fd == u);
-    if (u->parent == 0) {
-      assert(u->child[0] == 0);
-      assert(u->child[1] == 0);
-    }
-    else {
-      assert(head == 0); /* only one node on chain has parent */
-      head = u;
-      assert(u->parent != u);
-      assert (u->parent->child[0] == u ||
-              u->parent->child[1] == u ||
-              *((tbinptr*)(u->parent)) == u);
-      if (u->child[0] != 0) {
-        assert(u->child[0]->parent == u);
-        assert(u->child[0] != u);
-        do_check_tree(m, u->child[0]);
-      }
-      if (u->child[1] != 0) {
-        assert(u->child[1]->parent == u);
-        assert(u->child[1] != u);
-        do_check_tree(m, u->child[1]);
-      }
-      if (u->child[0] != 0 && u->child[1] != 0) {
-        assert(chunksize(u->child[0]) < chunksize(u->child[1]));
-      }
-    }
-    u = u->fd;
-  } while (u != t);
-  assert(head != 0);
-}
-
-/*  Check all the chunks in a treebin.  */
-static void do_check_treebin(mstate m, bindex_t i) {
-  tbinptr* tb = treebin_at(m, i);
-  tchunkptr t = *tb;
-  int empty = (m->treemap & (1U << i)) == 0;
-  if (t == 0)
-    assert(empty);
-  if (!empty)
-    do_check_tree(m, t);
-}
-
-/*  Check all the chunks in a smallbin.  */
-static void do_check_smallbin(mstate m, bindex_t i) {
-  sbinptr b = smallbin_at(m, i);
-  mchunkptr p = b->bk;
-  unsigned int empty = (m->smallmap & (1U << i)) == 0;
-  if (p == b)
-    assert(empty);
-  if (!empty) {
-    for (; p != b; p = p->bk) {
-      size_t size = chunksize(p);
-      mchunkptr q;
-      /* each chunk claims to be free */
-      do_check_free_chunk(m, p);
-      /* chunk belongs in bin */
-      assert(small_index(size) == i);
-      assert(p->bk == b || chunksize(p->bk) == chunksize(p));
-      /* chunk is followed by an inuse chunk */
-      q = next_chunk(p);
-      if (q->head != FENCEPOST_HEAD)
-        do_check_inuse_chunk(m, q);
-    }
-  }
-}
-
-/* Find x in a bin. Used in other check functions. */
-static int bin_find(mstate m, mchunkptr x) {
-  size_t size = chunksize(x);
-  if (is_small(size)) {
-    bindex_t sidx = small_index(size);
-    sbinptr b = smallbin_at(m, sidx);
-    if (smallmap_is_marked(m, sidx)) {
-      mchunkptr p = b;
-      do {
-        if (p == x)
-          return 1;
-      } while ((p = p->fd) != b);
-    }
-  }
-  else {
-    bindex_t tidx;
-    compute_tree_index(size, tidx);
-    if (treemap_is_marked(m, tidx)) {
-      tchunkptr t = *treebin_at(m, tidx);
-      size_t sizebits = size << leftshift_for_tree_index(tidx);
-      while (t != 0 && chunksize(t) != size) {
-        t = t->child[(sizebits >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1];
-        sizebits <<= 1;
-      }
-      if (t != 0) {
-        tchunkptr u = t;
-        do {
-          if (u == (tchunkptr)x)
-            return 1;
-        } while ((u = u->fd) != t);
-      }
-    }
-  }
-  return 0;
-}
-
-/* Traverse each chunk and check it; return total */
-static size_t traverse_and_check(mstate m) {
-  size_t sum = 0;
-  if (is_initialized(m)) {
-    msegmentptr s = &m->seg;
-    sum += m->topsize + TOP_FOOT_SIZE;
-    while (s != 0) {
-      mchunkptr q = align_as_chunk(s->base);
-      mchunkptr lastq = 0;
-      assert(pinuse(q));
-      while (segment_holds(s, q) &&
-             q != m->top && q->head != FENCEPOST_HEAD) {
-        sum += chunksize(q);
-        if (cinuse(q)) {
-          assert(!bin_find(m, q));
-          do_check_inuse_chunk(m, q);
-        }
-        else {
-          assert(q == m->dv || bin_find(m, q));
-          assert(lastq == 0 || cinuse(lastq)); /* Not 2 consecutive free */
-          do_check_free_chunk(m, q);
-        }
-        lastq = q;
-        q = next_chunk(q);
-      }
-      s = s->next;
-    }
-  }
-  return sum;
-}
-
-/* Check all properties of malloc_state. */
-static void do_check_malloc_state(mstate m) {
-  bindex_t i;
-  size_t total;
-  /* check bins */
-  for (i = 0; i < NSMALLBINS; ++i)
-    do_check_smallbin(m, i);
-  for (i = 0; i < NTREEBINS; ++i)
-    do_check_treebin(m, i);
-
-  if (m->dvsize != 0) { /* check dv chunk */
-    do_check_any_chunk(m, m->dv);
-    assert(m->dvsize == chunksize(m->dv));
-    assert(m->dvsize >= MIN_CHUNK_SIZE);
-    assert(bin_find(m, m->dv) == 0);
-  }
-
-  if (m->top != 0) {   /* check top chunk */
-    do_check_top_chunk(m, m->top);
-    assert(m->topsize == chunksize(m->top));
-    assert(m->topsize > 0);
-    assert(bin_find(m, m->top) == 0);
-  }
-
-  total = traverse_and_check(m);
-  assert(total <= m->footprint);
-  assert(m->footprint <= m->max_footprint);
-}
-#endif /* DEBUG */
-
-/* ----------------------------- statistics ------------------------------ */
-
-#if !NO_MALLINFO
-static struct mallinfo internal_mallinfo(mstate m) {
-  struct mallinfo nm = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
-  if (!PREACTION(m)) {
-    check_malloc_state(m);
-    if (is_initialized(m)) {
-      size_t nfree = SIZE_T_ONE; /* top always free */
-      size_t mfree = m->topsize + TOP_FOOT_SIZE;
-      size_t sum = mfree;
-      msegmentptr s = &m->seg;
-      while (s != 0) {
-        mchunkptr q = align_as_chunk(s->base);
-        while (segment_holds(s, q) &&
-               q != m->top && q->head != FENCEPOST_HEAD) {
-          size_t sz = chunksize(q);
-          sum += sz;
-          if (!cinuse(q)) {
-            mfree += sz;
-            ++nfree;
-          }
-          q = next_chunk(q);
-        }
-        s = s->next;
-      }
-
-      nm.arena    = sum;
-      nm.ordblks  = nfree;
-      nm.hblkhd   = m->footprint - sum;
-      nm.usmblks  = m->max_footprint;
-      nm.uordblks = m->footprint - mfree;
-      nm.fordblks = mfree;
-      nm.keepcost = m->topsize;
-    }
-
-    POSTACTION(m);
-  }
-  return nm;
-}
-#endif /* !NO_MALLINFO */
-
-static void internal_malloc_stats(mstate m) {
-  if (!PREACTION(m)) {
-    size_t maxfp = 0;
-    size_t fp = 0;
-    size_t used = 0;
-    check_malloc_state(m);
-    if (is_initialized(m)) {
-      msegmentptr s = &m->seg;
-      maxfp = m->max_footprint;
-      fp = m->footprint;
-      used = fp - (m->topsize + TOP_FOOT_SIZE);
-
-      while (s != 0) {
-        mchunkptr q = align_as_chunk(s->base);
-        while (segment_holds(s, q) &&
-               q != m->top && q->head != FENCEPOST_HEAD) {
-          if (!cinuse(q))
-            used -= chunksize(q);
-          q = next_chunk(q);
-        }
-        s = s->next;
-      }
-    }
-
-    fprintf(stderr, "max system bytes = %10lu\n", (unsigned long)(maxfp));
-    fprintf(stderr, "system bytes     = %10lu\n", (unsigned long)(fp));
-    fprintf(stderr, "in use bytes     = %10lu\n", (unsigned long)(used));
-
-    POSTACTION(m);
-  }
-}
-
-/* ----------------------- Operations on smallbins ----------------------- */
-
-/*
-  Various forms of linking and unlinking are defined as macros.  Even
-  the ones for trees, which are very long but have very short typical
-  paths.  This is ugly but reduces reliance on inlining support of
-  compilers.
-*/
-
-/* Link a free chunk into a smallbin  */
-#define insert_small_chunk(M, P, S) {\
-  bindex_t I  = small_index(S);\
-  mchunkptr B = smallbin_at(M, I);\
-  mchunkptr F = B;\
-  assert(S >= MIN_CHUNK_SIZE);\
-  if (!smallmap_is_marked(M, I))\
-    mark_smallmap(M, I);\
-  else if (RTCHECK(ok_address(M, B->fd)))\
-    F = B->fd;\
-  else {\
-    CORRUPTION_ERROR_ACTION(M);\
-  }\
-  B->fd = P;\
-  F->bk = P;\
-  P->fd = F;\
-  P->bk = B;\
-}
-
-/* Unlink a chunk from a smallbin  */
-#define unlink_small_chunk(M, P, S) {\
-  mchunkptr F = P->fd;\
-  mchunkptr B = P->bk;\
-  bindex_t I = small_index(S);\
-  assert(P != B);\
-  assert(P != F);\
-  assert(chunksize(P) == small_index2size(I));\
-  if (F == B)\
-    clear_smallmap(M, I);\
-  else if (RTCHECK((F == smallbin_at(M,I) || ok_address(M, F)) &&\
-                   (B == smallbin_at(M,I) || ok_address(M, B)))) {\
-    F->bk = B;\
-    B->fd = F;\
-  }\
-  else {\
-    CORRUPTION_ERROR_ACTION(M);\
-  }\
-}
-
-/* Unlink the first chunk from a smallbin */
-#define unlink_first_small_chunk(M, B, P, I) {\
-  mchunkptr F = P->fd;\
-  assert(P != B);\
-  assert(P != F);\
-  assert(chunksize(P) == small_index2size(I));\
-  if (B == F)\
-    clear_smallmap(M, I);\
-  else if (RTCHECK(ok_address(M, F))) {\
-    B->fd = F;\
-    F->bk = B;\
-  }\
-  else {\
-    CORRUPTION_ERROR_ACTION(M);\
-  }\
-}
-
-/* Replace dv node, binning the old one */
-/* Used only when dvsize known to be small */
-#define replace_dv(M, P, S) {\
-  size_t DVS = M->dvsize;\
-  if (DVS != 0) {\
-    mchunkptr DV = M->dv;\
-    assert(is_small(DVS));\
-    insert_small_chunk(M, DV, DVS);\
-  }\
-  M->dvsize = S;\
-  M->dv = P;\
-}
-
-/* ------------------------- Operations on trees ------------------------- */
-
-/* Insert chunk into tree */
-#define insert_large_chunk(M, X, S) {\
-  tbinptr* H;\
-  bindex_t I;\
-  compute_tree_index(S, I);\
-  H = treebin_at(M, I);\
-  X->index = I;\
-  X->child[0] = X->child[1] = 0;\
-  if (!treemap_is_marked(M, I)) {\
-    mark_treemap(M, I);\
-    *H = X;\
-    X->parent = (tchunkptr)H;\
-    X->fd = X->bk = X;\
-  }\
-  else {\
-    tchunkptr T = *H;\
-    size_t K = S << leftshift_for_tree_index(I);\
-    for (;;) {\
-      if (chunksize(T) != S) {\
-        tchunkptr* C = &(T->child[(K >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1]);\
-        K <<= 1;\
-        if (*C != 0)\
-          T = *C;\
-        else if (RTCHECK(ok_address(M, C))) {\
-          *C = X;\
-          X->parent = T;\
-          X->fd = X->bk = X;\
-          break;\
-        }\
-        else {\
-          CORRUPTION_ERROR_ACTION(M);\
-          break;\
-        }\
-      }\
-      else {\
-        tchunkptr F = T->fd;\
-        if (RTCHECK(ok_address(M, T) && ok_address(M, F))) {\
-          T->fd = F->bk = X;\
-          X->fd = F;\
-          X->bk = T;\
-          X->parent = 0;\
-          break;\
-        }\
-        else {\
-          CORRUPTION_ERROR_ACTION(M);\
-          break;\
-        }\
-      }\
-    }\
-  }\
-}
-
-/*
-  Unlink steps:
-
-  1. If x is a chained node, unlink it from its same-sized fd/bk links
-     and choose its bk node as its replacement.
-  2. If x was the last node of its size, but not a leaf node, it must
-     be replaced with a leaf node (not merely one with an open left or
-     right), to make sure that lefts and rights of descendents
-     correspond properly to bit masks.  We use the rightmost descendent
-     of x.  We could use any other leaf, but this is easy to locate and
-     tends to counteract removal of leftmosts elsewhere, and so keeps
-     paths shorter than minimally guaranteed.  This doesn't loop much
-     because on average a node in a tree is near the bottom.
-  3. If x is the base of a chain (i.e., has parent links) relink
-     x's parent and children to x's replacement (or null if none).
-*/
-
-#define unlink_large_chunk(M, X) {\
-  tchunkptr XP = X->parent;\
-  tchunkptr R;\
-  if (X->bk != X) {\
-    tchunkptr F = X->fd;\
-    R = X->bk;\
-    if (RTCHECK(ok_address(M, F))) {\
-      F->bk = R;\
-      R->fd = F;\
-    }\
-    else {\
-      CORRUPTION_ERROR_ACTION(M);\
-    }\
-  }\
-  else {\
-    tchunkptr* RP;\
-    if (((R = *(RP = &(X->child[1]))) != 0) ||\
-        ((R = *(RP = &(X->child[0]))) != 0)) {\
-      tchunkptr* CP;\
-      while ((*(CP = &(R->child[1])) != 0) ||\
-             (*(CP = &(R->child[0])) != 0)) {\
-        R = *(RP = CP);\
-      }\
-      if (RTCHECK(ok_address(M, RP)))\
-        *RP = 0;\
-      else {\
-        CORRUPTION_ERROR_ACTION(M);\
-      }\
-    }\
-  }\
-  if (XP != 0) {\
-    tbinptr* H = treebin_at(M, X->index);\
-    if (X == *H) {\
-      if ((*H = R) == 0) \
-        clear_treemap(M, X->index);\
-    }\
-    else if (RTCHECK(ok_address(M, XP))) {\
-      if (XP->child[0] == X) \
-        XP->child[0] = R;\
-      else \
-        XP->child[1] = R;\
-    }\
-    else\
-      CORRUPTION_ERROR_ACTION(M);\
-    if (R != 0) {\
-      if (RTCHECK(ok_address(M, R))) {\
-        tchunkptr C0, C1;\
-        R->parent = XP;\
-        if ((C0 = X->child[0]) != 0) {\
-          if (RTCHECK(ok_address(M, C0))) {\
-            R->child[0] = C0;\
-            C0->parent = R;\
-          }\
-          else\
-            CORRUPTION_ERROR_ACTION(M);\
-        }\
-        if ((C1 = X->child[1]) != 0) {\
-          if (RTCHECK(ok_address(M, C1))) {\
-            R->child[1] = C1;\
-            C1->parent = R;\
-          }\
-          else\
-            CORRUPTION_ERROR_ACTION(M);\
-        }\
-      }\
-      else\
-        CORRUPTION_ERROR_ACTION(M);\
-    }\
-  }\
-}
-
-/* Relays to large vs small bin operations */
-
-#define insert_chunk(M, P, S)\
-  if (is_small(S)) insert_small_chunk(M, P, S)\
-  else { tchunkptr TP = (tchunkptr)(P); insert_large_chunk(M, TP, S); }
-
-#define unlink_chunk(M, P, S)\
-  if (is_small(S)) unlink_small_chunk(M, P, S)\
-  else { tchunkptr TP = (tchunkptr)(P); unlink_large_chunk(M, TP); }
-
-
-/* Relays to internal calls to malloc/free from realloc, memalign etc */
-
-#if ONLY_MSPACES
-#define internal_malloc(m, b) mspace_malloc(m, b)
-#define internal_free(m, mem) mspace_free(m,mem);
-#else /* ONLY_MSPACES */
-#if MSPACES
-#define internal_malloc(m, b)\
-   (m == gm)? dlmalloc(b) : mspace_malloc(m, b)
-#define internal_free(m, mem)\
-   if (m == gm) dlfree(mem); else mspace_free(m,mem);
-#else /* MSPACES */
-#define internal_malloc(m, b) dlmalloc(b)
-#define internal_free(m, mem) dlfree(mem)
-#endif /* MSPACES */
-#endif /* ONLY_MSPACES */
-
-/* -----------------------  Direct-mmapping chunks ----------------------- */
-
-/*
-  Directly mmapped chunks are set up with an offset to the start of
-  the mmapped region stored in the prev_foot field of the chunk. This
-  allows reconstruction of the required argument to MUNMAP when freed,
-  and also allows adjustment of the returned chunk to meet alignment
-  requirements (especially in memalign).  There is also enough space
-  allocated to hold a fake next chunk of size SIZE_T_SIZE to maintain
-  the PINUSE bit so frees can be checked.
-*/
-
-/* Malloc using mmap */
-static void* mmap_alloc(mstate m, size_t nb) {
-  size_t mmsize = granularity_align(nb + SIX_SIZE_T_SIZES + CHUNK_ALIGN_MASK);
-  if (mmsize > nb) {     /* Check for wrap around 0 */
-    char* mm = (char*)(DIRECT_MMAP(mmsize));
-    if (mm != CMFAIL) {
-      size_t offset = align_offset(chunk2mem(mm));
-      size_t psize = mmsize - offset - MMAP_FOOT_PAD;
-      mchunkptr p = (mchunkptr)(mm + offset);
-      p->prev_foot = offset | IS_MMAPPED_BIT;
-      (p)->head = (psize|CINUSE_BIT);
-      mark_inuse_foot(m, p, psize);
-      chunk_plus_offset(p, psize)->head = FENCEPOST_HEAD;
-      chunk_plus_offset(p, psize+SIZE_T_SIZE)->head = 0;
-
-      if (mm < m->least_addr)
-        m->least_addr = mm;
-      if ((m->footprint += mmsize) > m->max_footprint)
-        m->max_footprint = m->footprint;
-      assert(is_aligned(chunk2mem(p)));
-      check_mmapped_chunk(m, p);
-      return chunk2mem(p);
-    }
-  }
-  return 0;
-}
-
-/* Realloc using mmap */
-static mchunkptr mmap_resize(mstate m, mchunkptr oldp, size_t nb) {
-  size_t oldsize = chunksize(oldp);
-  if (is_small(nb)) /* Can't shrink mmap regions below small size */
-    return 0;
-  /* Keep old chunk if big enough but not too big */
-  if (oldsize >= nb + SIZE_T_SIZE &&
-      (oldsize - nb) <= (mparams.granularity << 1))
-    return oldp;
-  else {
-    size_t offset = oldp->prev_foot & ~IS_MMAPPED_BIT;
-    size_t oldmmsize = oldsize + offset + MMAP_FOOT_PAD;
-    size_t newmmsize = granularity_align(nb + SIX_SIZE_T_SIZES +
-                                         CHUNK_ALIGN_MASK);
-    char* cp = (char*)CALL_MREMAP((char*)oldp - offset,
-                                  oldmmsize, newmmsize, 1);
-    if (cp != CMFAIL) {
-      mchunkptr newp = (mchunkptr)(cp + offset);
-      size_t psize = newmmsize - offset - MMAP_FOOT_PAD;
-      newp->head = (psize|CINUSE_BIT);
-      mark_inuse_foot(m, newp, psize);
-      chunk_plus_offset(newp, psize)->head = FENCEPOST_HEAD;
-      chunk_plus_offset(newp, psize+SIZE_T_SIZE)->head = 0;
-
-      if (cp < m->least_addr)
-        m->least_addr = cp;
-      if ((m->footprint += newmmsize - oldmmsize) > m->max_footprint)
-        m->max_footprint = m->footprint;
-      check_mmapped_chunk(m, newp);
-      return newp;
-    }
-  }
-  return 0;
-}
-
-/* -------------------------- mspace management -------------------------- */
-
-/* Initialize top chunk and its size */
-static void init_top(mstate m, mchunkptr p, size_t psize) {
-  /* Ensure alignment */
-  size_t offset = align_offset(chunk2mem(p));
-  p = (mchunkptr)((char*)p + offset);
-  psize -= offset;
-
-  m->top = p;
-  m->topsize = psize;
-  p->head = psize | PINUSE_BIT;
-  /* set size of fake trailing chunk holding overhead space only once */
-  chunk_plus_offset(p, psize)->head = TOP_FOOT_SIZE;
-  m->trim_check = mparams.trim_threshold; /* reset on each update */
-}
-
-/* Initialize bins for a new mstate that is otherwise zeroed out */
-static void init_bins(mstate m) {
-  /* Establish circular links for smallbins */
-  bindex_t i;
-  for (i = 0; i < NSMALLBINS; ++i) {
-    sbinptr bin = smallbin_at(m,i);
-    bin->fd = bin->bk = bin;
-  }
-}
-
-#if PROCEED_ON_ERROR
-
-/* default corruption action */
-static void reset_on_error(mstate m) {
-  int i;
-  ++malloc_corruption_error_count;
-  /* Reinitialize fields to forget about all memory */
-  m->smallbins = m->treebins = 0;
-  m->dvsize = m->topsize = 0;
-  m->seg.base = 0;
-  m->seg.size = 0;
-  m->seg.next = 0;
-  m->top = m->dv = 0;
-  for (i = 0; i < NTREEBINS; ++i)
-    *treebin_at(m, i) = 0;
-  init_bins(m);
-}
-#endif /* PROCEED_ON_ERROR */
-
-/* Allocate chunk and prepend remainder with chunk in successor base. */
-static void* prepend_alloc(mstate m, char* newbase, char* oldbase,
-                           size_t nb) {
-  mchunkptr p = align_as_chunk(newbase);
-  mchunkptr oldfirst = align_as_chunk(oldbase);
-  size_t psize = (char*)oldfirst - (char*)p;
-  mchunkptr q = chunk_plus_offset(p, nb);
-  size_t qsize = psize - nb;
-  set_size_and_pinuse_of_inuse_chunk(m, p, nb);
-
-  assert((char*)oldfirst > (char*)q);
-  assert(pinuse(oldfirst));
-  assert(qsize >= MIN_CHUNK_SIZE);
-
-  /* consolidate remainder with first chunk of old base */
-  if (oldfirst == m->top) {
-    size_t tsize = m->topsize += qsize;
-    m->top = q;
-    q->head = tsize | PINUSE_BIT;
-    check_top_chunk(m, q);
-  }
-  else if (oldfirst == m->dv) {
-    size_t dsize = m->dvsize += qsize;
-    m->dv = q;
-    set_size_and_pinuse_of_free_chunk(q, dsize);
-  }
-  else {
-    if (!cinuse(oldfirst)) {
-      size_t nsize = chunksize(oldfirst);
-      unlink_chunk(m, oldfirst, nsize);
-      oldfirst = chunk_plus_offset(oldfirst, nsize);
-      qsize += nsize;
-    }
-    set_free_with_pinuse(q, qsize, oldfirst);
-    insert_chunk(m, q, qsize);
-    check_free_chunk(m, q);
-  }
-
-  check_malloced_chunk(m, chunk2mem(p), nb);
-  return chunk2mem(p);
-}
-
-
-/* Add a segment to hold a new noncontiguous region */
-static void add_segment(mstate m, char* tbase, size_t tsize, flag_t mmapped) {
-  /* Determine locations and sizes of segment, fenceposts, old top */
-  char* old_top = (char*)m->top;
-  msegmentptr oldsp = segment_holding(m, old_top);
-  char* old_end = oldsp->base + oldsp->size;
-  size_t ssize = pad_request(sizeof(struct malloc_segment));
-  char* rawsp = old_end - (ssize + FOUR_SIZE_T_SIZES + CHUNK_ALIGN_MASK);
-  size_t offset = align_offset(chunk2mem(rawsp));
-  char* asp = rawsp + offset;
-  char* csp = (asp < (old_top + MIN_CHUNK_SIZE))? old_top : asp;
-  mchunkptr sp = (mchunkptr)csp;
-  msegmentptr ss = (msegmentptr)(chunk2mem(sp));
-  mchunkptr tnext = chunk_plus_offset(sp, ssize);
-  mchunkptr p = tnext;
-  int nfences = 0;
-
-  /* reset top to new space */
-  init_top(m, (mchunkptr)tbase, tsize - TOP_FOOT_SIZE);
-
-  /* Set up segment record */
-  assert(is_aligned(ss));
-  set_size_and_pinuse_of_inuse_chunk(m, sp, ssize);
-  *ss = m->seg; /* Push current record */
-  m->seg.base = tbase;
-  m->seg.size = tsize;
-  m->seg.sflags = mmapped;
-  m->seg.next = ss;
-
-  /* Insert trailing fenceposts */
-  for (;;) {
-    mchunkptr nextp = chunk_plus_offset(p, SIZE_T_SIZE);
-    p->head = FENCEPOST_HEAD;
-    ++nfences;
-    if ((char*)(&(nextp->head)) < old_end)
-      p = nextp;
-    else
-      break;
-  }
-  assert(nfences >= 2);
-
-  /* Insert the rest of old top into a bin as an ordinary free chunk */
-  if (csp != old_top) {
-    mchunkptr q = (mchunkptr)old_top;
-    size_t psize = csp - old_top;
-    mchunkptr tn = chunk_plus_offset(q, psize);
-    set_free_with_pinuse(q, psize, tn);
-    insert_chunk(m, q, psize);
-  }
-
-  check_top_chunk(m, m->top);
-}
-
-/* -------------------------- System allocation -------------------------- */
-
-/* Get memory from system using MORECORE or MMAP */
-static void* sys_alloc(mstate m, size_t nb) {
-  char* tbase = CMFAIL;
-  size_t tsize = 0;
-  flag_t mmap_flag = 0;
-
-  init_mparams();
-
-  /* Directly map large chunks */
-  if (use_mmap(m) && nb >= mparams.mmap_threshold) {
-    void* mem = mmap_alloc(m, nb);
-    if (mem != 0)
-      return mem;
-  }
-
-  /*
-    Try getting memory in any of three ways (in most-preferred to
-    least-preferred order):
-    1. A call to MORECORE that can normally contiguously extend memory.
-       (disabled if not MORECORE_CONTIGUOUS or not HAVE_MORECORE or
-       or main space is mmapped or a previous contiguous call failed)
-    2. A call to MMAP new space (disabled if not HAVE_MMAP).
-       Note that under the default settings, if MORECORE is unable to
-       fulfill a request, and HAVE_MMAP is true, then mmap is
-       used as a noncontiguous system allocator. This is a useful backup
-       strategy for systems with holes in address spaces -- in this case
-       sbrk cannot contiguously expand the heap, but mmap may be able to
-       find space.
-    3. A call to MORECORE that cannot usually contiguously extend memory.
-       (disabled if not HAVE_MORECORE)
-  */
-
-  if (MORECORE_CONTIGUOUS && !use_noncontiguous(m)) {
-    char* br = CMFAIL;
-    msegmentptr ss = (m->top == 0)? 0 : segment_holding(m, (char*)m->top);
-    size_t asize = 0;
-    ACQUIRE_MORECORE_LOCK();
-
-    if (ss == 0) {  /* First time through or recovery */
-      char* base = (char*)CALL_MORECORE(0);
-      if (base != CMFAIL) {
-        asize = granularity_align(nb + TOP_FOOT_SIZE + SIZE_T_ONE);
-        /* Adjust to end on a page boundary */
-        if (!is_page_aligned(base))
-          asize += (page_align((size_t)base) - (size_t)base);
-        /* Can't call MORECORE if size is negative when treated as signed */
-        if (asize < HALF_MAX_SIZE_T &&
-            (br = (char*)(CALL_MORECORE(asize))) == base) {
-          tbase = base;
-          tsize = asize;
-        }
-      }
-    }
-    else {
-      /* Subtract out existing available top space from MORECORE request. */
-      asize = granularity_align(nb - m->topsize + TOP_FOOT_SIZE + SIZE_T_ONE);
-      /* Use mem here only if it did continuously extend old space */
-      if (asize < HALF_MAX_SIZE_T &&
-          (br = (char*)(CALL_MORECORE(asize))) == ss->base+ss->size) {
-        tbase = br;
-        tsize = asize;
-      }
-    }
-
-    if (tbase == CMFAIL) {    /* Cope with partial failure */
-      if (br != CMFAIL) {    /* Try to use/extend the space we did get */
-        if (asize < HALF_MAX_SIZE_T &&
-            asize < nb + TOP_FOOT_SIZE + SIZE_T_ONE) {
-          size_t esize = granularity_align(nb + TOP_FOOT_SIZE + SIZE_T_ONE - asize);
-          if (esize < HALF_MAX_SIZE_T) {
-            char* end = (char*)CALL_MORECORE(esize);
-            if (end != CMFAIL)
-              asize += esize;
-            else {            /* Can't use; try to release */
-              CALL_MORECORE(-asize);
-              br = CMFAIL;
-            }
-          }
-        }
-      }
-      if (br != CMFAIL) {    /* Use the space we did get */
-        tbase = br;
-        tsize = asize;
-      }
-      else
-        disable_contiguous(m); /* Don't try contiguous path in the future */
-    }
-
-    RELEASE_MORECORE_LOCK();
-  }
-
-  if (HAVE_MMAP && tbase == CMFAIL) {  /* Try MMAP */
-    size_t req = nb + TOP_FOOT_SIZE + SIZE_T_ONE;
-    size_t rsize = granularity_align(req);
-    if (rsize > nb) { /* Fail if wraps around zero */
-      char* mp = (char*)(CALL_MMAP(rsize));
-      if (mp != CMFAIL) {
-        tbase = mp;
-        tsize = rsize;
-        mmap_flag = IS_MMAPPED_BIT;
-      }
-    }
-  }
-
-  if (HAVE_MORECORE && tbase == CMFAIL) { /* Try noncontiguous MORECORE */
-    size_t asize = granularity_align(nb + TOP_FOOT_SIZE + SIZE_T_ONE);
-    if (asize < HALF_MAX_SIZE_T) {
-      char* br = CMFAIL;
-      char* end = CMFAIL;
-      ACQUIRE_MORECORE_LOCK();
-      br = (char*)(CALL_MORECORE(asize));
-      end = (char*)(CALL_MORECORE(0));
-      RELEASE_MORECORE_LOCK();
-      if (br != CMFAIL && end != CMFAIL && br < end) {
-        size_t ssize = end - br;
-        if (ssize > nb + TOP_FOOT_SIZE) {
-          tbase = br;
-          tsize = ssize;
-        }
-      }
-    }
-  }
-
-  if (tbase != CMFAIL) {
-
-    if ((m->footprint += tsize) > m->max_footprint)
-      m->max_footprint = m->footprint;
-
-    if (!is_initialized(m)) { /* first-time initialization */
-      m->seg.base = m->least_addr = tbase;
-      m->seg.size = tsize;
-      m->seg.sflags = mmap_flag;
-      m->magic = mparams.magic;
-      init_bins(m);
-      if (is_global(m))
-        init_top(m, (mchunkptr)tbase, tsize - TOP_FOOT_SIZE);
-      else {
-        /* Offset top by embedded malloc_state */
-        mchunkptr mn = next_chunk(mem2chunk(m));
-        init_top(m, mn, (size_t)((tbase + tsize) - (char*)mn) -TOP_FOOT_SIZE);
-      }
-    }
-
-    else {
-      /* Try to merge with an existing segment */
-      msegmentptr sp = &m->seg;
-      while (sp != 0 && tbase != sp->base + sp->size)
-        sp = sp->next;
-      if (sp != 0 &&
-          !is_extern_segment(sp) &&
-          (sp->sflags & IS_MMAPPED_BIT) == mmap_flag &&
-          segment_holds(sp, m->top)) { /* append */
-        sp->size += tsize;
-        init_top(m, m->top, m->topsize + tsize);
-      }
-      else {
-        if (tbase < m->least_addr)
-          m->least_addr = tbase;
-        sp = &m->seg;
-        while (sp != 0 && sp->base != tbase + tsize)
-          sp = sp->next;
-        if (sp != 0 &&
-            !is_extern_segment(sp) &&
-            (sp->sflags & IS_MMAPPED_BIT) == mmap_flag) {
-          char* oldbase = sp->base;
-          sp->base = tbase;
-          sp->size += tsize;
-          return prepend_alloc(m, tbase, oldbase, nb);
-        }
-        else
-          add_segment(m, tbase, tsize, mmap_flag);
-      }
-    }
-
-    if (nb < m->topsize) { /* Allocate from new or extended top space */
-      size_t rsize = m->topsize -= nb;
-      mchunkptr p = m->top;
-      mchunkptr r = m->top = chunk_plus_offset(p, nb);
-      r->head = rsize | PINUSE_BIT;
-      set_size_and_pinuse_of_inuse_chunk(m, p, nb);
-      check_top_chunk(m, m->top);
-      check_malloced_chunk(m, chunk2mem(p), nb);
-      return chunk2mem(p);
-    }
-  }
-
-  MALLOC_FAILURE_ACTION;
-  return 0;
-}
-
-/* -----------------------  system deallocation -------------------------- */
-
-/* Unmap and unlink any mmapped segments that don't contain used chunks */
-static size_t release_unused_segments(mstate m) {
-  size_t released = 0;
-  msegmentptr pred = &m->seg;
-  msegmentptr sp = pred->next;
-  while (sp != 0) {
-    char* base = sp->base;
-    size_t size = sp->size;
-    msegmentptr next = sp->next;
-    if (is_mmapped_segment(sp) && !is_extern_segment(sp)) {
-      mchunkptr p = align_as_chunk(base);
-      size_t psize = chunksize(p);
-      /* Can unmap if first chunk holds entire segment and not pinned */
-      if (!cinuse(p) && (char*)p + psize >= base + size - TOP_FOOT_SIZE) {
-        tchunkptr tp = (tchunkptr)p;
-        assert(segment_holds(sp, (char*)sp));
-        if (p == m->dv) {
-          m->dv = 0;
-          m->dvsize = 0;
-        }
-        else {
-          unlink_large_chunk(m, tp);
-        }
-        if (CALL_MUNMAP(base, size) == 0) {
-          released += size;
-          m->footprint -= size;
-          /* unlink obsoleted record */
-          sp = pred;
-          sp->next = next;
-        }
-        else { /* back out if cannot unmap */
-          insert_large_chunk(m, tp, psize);
-        }
-      }
-    }
-    pred = sp;
-    sp = next;
-  }
-  return released;
-}
-
-static int sys_trim(mstate m, size_t pad) {
-  size_t released = 0;
-  if (pad < MAX_REQUEST && is_initialized(m)) {
-    pad += TOP_FOOT_SIZE; /* ensure enough room for segment overhead */
-
-    if (m->topsize > pad) {
-      /* Shrink top space in granularity-size units, keeping at least one */
-      size_t unit = mparams.granularity;
-      size_t extra = ((m->topsize - pad + (unit - SIZE_T_ONE)) / unit -
-                      SIZE_T_ONE) * unit;
-      msegmentptr sp = segment_holding(m, (char*)m->top);
-
-      if (!is_extern_segment(sp)) {
-        if (is_mmapped_segment(sp)) {
-          if (HAVE_MMAP &&
-              sp->size >= extra &&
-              !has_segment_link(m, sp)) { /* can't shrink if pinned */
-            size_t newsize = sp->size - extra;
-            /* Prefer mremap, fall back to munmap */
-            if ((CALL_MREMAP(sp->base, sp->size, newsize, 0) != MFAIL) ||
-                (CALL_MUNMAP(sp->base + newsize, extra) == 0)) {
-              released = extra;
-            }
-          }
-        }
-        else if (HAVE_MORECORE) {
-          if (extra >= HALF_MAX_SIZE_T) /* Avoid wrapping negative */
-            extra = (HALF_MAX_SIZE_T) + SIZE_T_ONE - unit;
-          ACQUIRE_MORECORE_LOCK();
-          {
-            /* Make sure end of memory is where we last set it. */
-            char* old_br = (char*)(CALL_MORECORE(0));
-            if (old_br == sp->base + sp->size) {
-              char* rel_br = (char*)(CALL_MORECORE(-extra));
-              char* new_br = (char*)(CALL_MORECORE(0));
-              if (rel_br != CMFAIL && new_br < old_br)
-                released = old_br - new_br;
-            }
-          }
-          RELEASE_MORECORE_LOCK();
-        }
-      }
-
-      if (released != 0) {
-        sp->size -= released;
-        m->footprint -= released;
-        init_top(m, m->top, m->topsize - released);
-        check_top_chunk(m, m->top);
-      }
-    }
-
-    /* Unmap any unused mmapped segments */
-    if (HAVE_MMAP)
-      released += release_unused_segments(m);
-
-    /* On failure, disable autotrim to avoid repeated failed future calls */
-    if (released == 0)
-      m->trim_check = MAX_SIZE_T;
-  }
-
-  return (released != 0)? 1 : 0;
-}
-
-/* ---------------------------- malloc support --------------------------- */
-
-/* allocate a large request from the best fitting chunk in a treebin */
-static void* tmalloc_large(mstate m, size_t nb) {
-  tchunkptr v = 0;
-  size_t rsize = -nb; /* Unsigned negation */
-  tchunkptr t;
-  bindex_t idx;
-  compute_tree_index(nb, idx);
-
-  if ((t = *treebin_at(m, idx)) != 0) {
-    /* Traverse tree for this bin looking for node with size == nb */
-    size_t sizebits = nb << leftshift_for_tree_index(idx);
-    tchunkptr rst = 0;  /* The deepest untaken right subtree */
-    for (;;) {
-      tchunkptr rt;
-      size_t trem = chunksize(t) - nb;
-      if (trem < rsize) {
-        v = t;
-        if ((rsize = trem) == 0)
-          break;
-      }
-      rt = t->child[1];
-      t = t->child[(sizebits >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1];
-      if (rt != 0 && rt != t)
-        rst = rt;
-      if (t == 0) {
-        t = rst; /* set t to least subtree holding sizes > nb */
-        break;
-      }
-      sizebits <<= 1;
-    }
-  }
-
-  if (t == 0 && v == 0) { /* set t to root of next non-empty treebin */
-    binmap_t leftbits = left_bits(idx2bit(idx)) & m->treemap;
-    if (leftbits != 0) {
-      bindex_t i;
-      binmap_t leastbit = least_bit(leftbits);
-      compute_bit2idx(leastbit, i);
-      t = *treebin_at(m, i);
-    }
-  }
-
-  while (t != 0) { /* find smallest of tree or subtree */
-    size_t trem = chunksize(t) - nb;
-    if (trem < rsize) {
-      rsize = trem;
-      v = t;
-    }
-    t = leftmost_child(t);
-  }
-
-  /*  If dv is a better fit, return 0 so malloc will use it */
-  if (v != 0 && rsize < (size_t)(m->dvsize - nb)) {
-    if (RTCHECK(ok_address(m, v))) { /* split */
-      mchunkptr r = chunk_plus_offset(v, nb);
-      assert(chunksize(v) == rsize + nb);
-      if (RTCHECK(ok_next(v, r))) {
-        unlink_large_chunk(m, v);
-        if (rsize < MIN_CHUNK_SIZE)
-          set_inuse_and_pinuse(m, v, (rsize + nb));
-        else {
-          set_size_and_pinuse_of_inuse_chunk(m, v, nb);
-          set_size_and_pinuse_of_free_chunk(r, rsize);
-          insert_chunk(m, r, rsize);
-        }
-        return chunk2mem(v);
-      }
-    }
-    CORRUPTION_ERROR_ACTION(m);
-  }
-  return 0;
-}
-
-/* allocate a small request from the best fitting chunk in a treebin */
-static void* tmalloc_small(mstate m, size_t nb) {
-  tchunkptr t, v;
-  size_t rsize;
-  bindex_t i;
-  binmap_t leastbit = least_bit(m->treemap);
-  compute_bit2idx(leastbit, i);
-
-  v = t = *treebin_at(m, i);
-  rsize = chunksize(t) - nb;
-
-  while ((t = leftmost_child(t)) != 0) {
-    size_t trem = chunksize(t) - nb;
-    if (trem < rsize) {
-      rsize = trem;
-      v = t;
-    }
-  }
-
-  if (RTCHECK(ok_address(m, v))) {
-    mchunkptr r = chunk_plus_offset(v, nb);
-    assert(chunksize(v) == rsize + nb);
-    if (RTCHECK(ok_next(v, r))) {
-      unlink_large_chunk(m, v);
-      if (rsize < MIN_CHUNK_SIZE)
-        set_inuse_and_pinuse(m, v, (rsize + nb));
-      else {
-        set_size_and_pinuse_of_inuse_chunk(m, v, nb);
-        set_size_and_pinuse_of_free_chunk(r, rsize);
-        replace_dv(m, r, rsize);
-      }
-      return chunk2mem(v);
-    }
-  }
-
-  CORRUPTION_ERROR_ACTION(m);
-  return 0;
-}
-
-/* --------------------------- realloc support --------------------------- */
-
-static void* internal_realloc(mstate m, void* oldmem, size_t bytes) {
-  if (bytes >= MAX_REQUEST) {
-    MALLOC_FAILURE_ACTION;
-    return 0;
-  }
-  if (!PREACTION(m)) {
-    mchunkptr oldp = mem2chunk(oldmem);
-    size_t oldsize = chunksize(oldp);
-    mchunkptr next = chunk_plus_offset(oldp, oldsize);
-    mchunkptr newp = 0;
-    void* extra = 0;
-
-    /* Try to either shrink or extend into top. Else malloc-copy-free */
-
-    if (RTCHECK(ok_address(m, oldp) && ok_cinuse(oldp) &&
-                ok_next(oldp, next) && ok_pinuse(next))) {
-      size_t nb = request2size(bytes);
-      if (is_mmapped(oldp))
-        newp = mmap_resize(m, oldp, nb);
-      else if (oldsize >= nb) { /* already big enough */
-        size_t rsize = oldsize - nb;
-        newp = oldp;
-        if (rsize >= MIN_CHUNK_SIZE) {
-          mchunkptr remainder = chunk_plus_offset(newp, nb);
-          set_inuse(m, newp, nb);
-          set_inuse(m, remainder, rsize);
-          extra = chunk2mem(remainder);
-        }
-      }
-      else if (next == m->top && oldsize + m->topsize > nb) {
-        /* Expand into top */
-        size_t newsize = oldsize + m->topsize;
-        size_t newtopsize = newsize - nb;
-        mchunkptr newtop = chunk_plus_offset(oldp, nb);
-        set_inuse(m, oldp, nb);
-        newtop->head = newtopsize |PINUSE_BIT;
-        m->top = newtop;
-        m->topsize = newtopsize;
-        newp = oldp;
-      }
-    }
-    else {
-      USAGE_ERROR_ACTION(m, oldmem);
-      POSTACTION(m);
-      return 0;
-    }
-
-    POSTACTION(m);
-
-    if (newp != 0) {
-      if (extra != 0) {
-        internal_free(m, extra);
-      }
-      check_inuse_chunk(m, newp);
-      return chunk2mem(newp);
-    }
-    else {
-      void* newmem = internal_malloc(m, bytes);
-      if (newmem != 0) {
-        size_t oc = oldsize - overhead_for(oldp);
-        memcpy(newmem, oldmem, (oc < bytes)? oc : bytes);
-        internal_free(m, oldmem);
-      }
-      return newmem;
-    }
-  }
-  return 0;
-}
-
-/* --------------------------- memalign support -------------------------- */
-
-static void* internal_memalign(mstate m, size_t alignment, size_t bytes) {
-  if (alignment <= MALLOC_ALIGNMENT)    /* Can just use malloc */
-    return internal_malloc(m, bytes);
-  if (alignment <  MIN_CHUNK_SIZE) /* must be at least a minimum chunk size */
-    alignment = MIN_CHUNK_SIZE;
-  if ((alignment & (alignment-SIZE_T_ONE)) != 0) {/* Ensure a power of 2 */
-    size_t a = MALLOC_ALIGNMENT << 1;
-    while (a < alignment) a <<= 1;
-    alignment = a;
-  }
-
-  if (bytes >= MAX_REQUEST - alignment) {
-    if (m != 0)  { /* Test isn't needed but avoids compiler warning */
-      MALLOC_FAILURE_ACTION;
-    }
-  }
-  else {
-    size_t nb = request2size(bytes);
-    size_t req = nb + alignment + MIN_CHUNK_SIZE - CHUNK_OVERHEAD;
-    char* mem = (char*)internal_malloc(m, req);
-    if (mem != 0) {
-      void* leader = 0;
-      void* trailer = 0;
-      mchunkptr p = mem2chunk(mem);
-
-      if (PREACTION(m)) return 0;
-      if ((((size_t)(mem)) % alignment) != 0) { /* misaligned */
-        /*
-          Find an aligned spot inside chunk.  Since we need to give
-          back leading space in a chunk of at least MIN_CHUNK_SIZE, if
-          the first calculation places us at a spot with less than
-          MIN_CHUNK_SIZE leader, we can move to the next aligned spot.
-          We've allocated enough total room so that this is always
-          possible.
-        */
-        char* br = (char*)mem2chunk((size_t)(((size_t)(mem +
-                                                       alignment -
-                                                       SIZE_T_ONE)) &
-                                             -alignment));
-        char* pos = ((size_t)(br - (char*)(p)) >= MIN_CHUNK_SIZE)?
-          br : br+alignment;
-        mchunkptr newp = (mchunkptr)pos;
-        size_t leadsize = pos - (char*)(p);
-        size_t newsize = chunksize(p) - leadsize;
-
-        if (is_mmapped(p)) { /* For mmapped chunks, just adjust offset */
-          newp->prev_foot = p->prev_foot + leadsize;
-          newp->head = (newsize|CINUSE_BIT);
-        }
-        else { /* Otherwise, give back leader, use the rest */
-          set_inuse(m, newp, newsize);
-          set_inuse(m, p, leadsize);
-          leader = chunk2mem(p);
-        }
-        p = newp;
-      }
-
-      /* Give back spare room at the end */
-      if (!is_mmapped(p)) {
-        size_t size = chunksize(p);
-        if (size > nb + MIN_CHUNK_SIZE) {
-          size_t remainder_size = size - nb;
-          mchunkptr remainder = chunk_plus_offset(p, nb);
-          set_inuse(m, p, nb);
-          set_inuse(m, remainder, remainder_size);
-          trailer = chunk2mem(remainder);
-        }
-      }
-
-      assert (chunksize(p) >= nb);
-      assert((((size_t)(chunk2mem(p))) % alignment) == 0);
-      check_inuse_chunk(m, p);
-      POSTACTION(m);
-      if (leader != 0) {
-        internal_free(m, leader);
-      }
-      if (trailer != 0) {
-        internal_free(m, trailer);
-      }
-      return chunk2mem(p);
-    }
-  }
-  return 0;
-}
-
-/* ------------------------ comalloc/coalloc support --------------------- */
-
-static void** ialloc(mstate m,
-                     size_t n_elements,
-                     size_t* sizes,
-                     int opts,
-                     void* chunks[]) {
-  /*
-    This provides common support for independent_X routines, handling
-    all of the combinations that can result.
-
-    The opts arg has:
-    bit 0 set if all elements are same size (using sizes[0])
-    bit 1 set if elements should be zeroed
-  */
-
-  size_t    element_size;   /* chunksize of each element, if all same */
-  size_t    contents_size;  /* total size of elements */
-  size_t    array_size;     /* request size of pointer array */
-  void*     mem;            /* malloced aggregate space */
-  mchunkptr p;              /* corresponding chunk */
-  size_t    remainder_size; /* remaining bytes while splitting */
-  void**    marray;         /* either "chunks" or malloced ptr array */
-  mchunkptr array_chunk;    /* chunk for malloced ptr array */
-  flag_t    was_enabled;    /* to disable mmap */
-  size_t    size;
-  size_t    i;
-
-  /* compute array length, if needed */
-  if (chunks != 0) {
-    if (n_elements == 0)
-      return chunks; /* nothing to do */
-    marray = chunks;
-    array_size = 0;
-  }
-  else {
-    /* if empty req, must still return chunk representing empty array */
-    if (n_elements == 0)
-      return (void**)internal_malloc(m, 0);
-    marray = 0;
-    array_size = request2size(n_elements * (sizeof(void*)));
-  }
-
-  /* compute total element size */
-  if (opts & 0x1) { /* all-same-size */
-    element_size = request2size(*sizes);
-    contents_size = n_elements * element_size;
-  }
-  else { /* add up all the sizes */
-    element_size = 0;
-    contents_size = 0;
-    for (i = 0; i != n_elements; ++i)
-      contents_size += request2size(sizes[i]);
-  }
-
-  size = contents_size + array_size;
-
-  /*
-     Allocate the aggregate chunk.  First disable direct-mmapping so
-     malloc won't use it, since we would not be able to later
-     free/realloc space internal to a segregated mmap region.
-  */
-  was_enabled = use_mmap(m);
-  disable_mmap(m);
-  mem = internal_malloc(m, size - CHUNK_OVERHEAD);
-  if (was_enabled)
-    enable_mmap(m);
-  if (mem == 0)
-    return 0;
-
-  if (PREACTION(m)) return 0;
-  p = mem2chunk(mem);
-  remainder_size = chunksize(p);
-
-  assert(!is_mmapped(p));
-
-  if (opts & 0x2) {       /* optionally clear the elements */
-    memset((size_t*)mem, 0, remainder_size - SIZE_T_SIZE - array_size);
-  }
-
-  /* If not provided, allocate the pointer array as final part of chunk */
-  if (marray == 0) {
-    size_t  array_chunk_size;
-    array_chunk = chunk_plus_offset(p, contents_size);
-    array_chunk_size = remainder_size - contents_size;
-    marray = (void**) (chunk2mem(array_chunk));
-    set_size_and_pinuse_of_inuse_chunk(m, array_chunk, array_chunk_size);
-    remainder_size = contents_size;
-  }
-
-  /* split out elements */
-  for (i = 0; ; ++i) {
-    marray[i] = chunk2mem(p);
-    if (i != n_elements-1) {
-      if (element_size != 0)
-        size = element_size;
-      else
-        size = request2size(sizes[i]);
-      remainder_size -= size;
-      set_size_and_pinuse_of_inuse_chunk(m, p, size);
-      p = chunk_plus_offset(p, size);
-    }
-    else { /* the final element absorbs any overallocation slop */
-      set_size_and_pinuse_of_inuse_chunk(m, p, remainder_size);
-      break;
-    }
-  }
-
-#if DEBUG
-  if (marray != chunks) {
-    /* final element must have exactly exhausted chunk */
-    if (element_size != 0) {
-      assert(remainder_size == element_size);
-    }
-    else {
-      assert(remainder_size == request2size(sizes[i]));
-    }
-    check_inuse_chunk(m, mem2chunk(marray));
-  }
-  for (i = 0; i != n_elements; ++i)
-    check_inuse_chunk(m, mem2chunk(marray[i]));
-
-#endif /* DEBUG */
-
-  POSTACTION(m);
-  return marray;
-}
-
-
-/* -------------------------- public routines ---------------------------- */
-
-#if !ONLY_MSPACES
-
-void* dlmalloc(size_t bytes) {
-  /*
-     Basic algorithm:
-     If a small request (< 256 bytes minus per-chunk overhead):
-       1. If one exists, use a remainderless chunk in associated smallbin.
-          (Remainderless means that there are too few excess bytes to
-          represent as a chunk.)
-       2. If it is big enough, use the dv chunk, which is normally the
-          chunk adjacent to the one used for the most recent small request.
-       3. If one exists, split the smallest available chunk in a bin,
-          saving remainder in dv.
-       4. If it is big enough, use the top chunk.
-       5. If available, get memory from system and use it
-     Otherwise, for a large request:
-       1. Find the smallest available binned chunk that fits, and use it
-          if it is better fitting than dv chunk, splitting if necessary.
-       2. If better fitting than any binned chunk, use the dv chunk.
-       3. If it is big enough, use the top chunk.
-       4. If request size >= mmap threshold, try to directly mmap this chunk.
-       5. If available, get memory from system and use it
-
-     The ugly goto's here ensure that postaction occurs along all paths.
-  */
-
-  if (!PREACTION(gm)) {
-    void* mem;
-    size_t nb;
-    if (bytes <= MAX_SMALL_REQUEST) {
-      bindex_t idx;
-      binmap_t smallbits;
-      nb = (bytes < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(bytes);
-      idx = small_index(nb);
-      smallbits = gm->smallmap >> idx;
-
-      if ((smallbits & 0x3U) != 0) { /* Remainderless fit to a smallbin. */
-        mchunkptr b, p;
-        idx += ~smallbits & 1;       /* Uses next bin if idx empty */
-        b = smallbin_at(gm, idx);
-        p = b->fd;
-        assert(chunksize(p) == small_index2size(idx));
-        unlink_first_small_chunk(gm, b, p, idx);
-        set_inuse_and_pinuse(gm, p, small_index2size(idx));
-        mem = chunk2mem(p);
-        check_malloced_chunk(gm, mem, nb);
-        goto postaction;
-      }
-
-      else if (nb > gm->dvsize) {
-        if (smallbits != 0) { /* Use chunk in next nonempty smallbin */
-          mchunkptr b, p, r;
-          size_t rsize;
-          bindex_t i;
-          binmap_t leftbits = (smallbits << idx) & left_bits(idx2bit(idx));
-          binmap_t leastbit = least_bit(leftbits);
-          compute_bit2idx(leastbit, i);
-          b = smallbin_at(gm, i);
-          p = b->fd;
-          assert(chunksize(p) == small_index2size(i));
-          unlink_first_small_chunk(gm, b, p, i);
-          rsize = small_index2size(i) - nb;
-          /* Fit here cannot be remainderless if 4byte sizes */
-          if (SIZE_T_SIZE != 4 && rsize < MIN_CHUNK_SIZE)
-            set_inuse_and_pinuse(gm, p, small_index2size(i));
-          else {
-            set_size_and_pinuse_of_inuse_chunk(gm, p, nb);
-            r = chunk_plus_offset(p, nb);
-            set_size_and_pinuse_of_free_chunk(r, rsize);
-            replace_dv(gm, r, rsize);
-          }
-          mem = chunk2mem(p);
-          check_malloced_chunk(gm, mem, nb);
-          goto postaction;
-        }
-
-        else if (gm->treemap != 0 && (mem = tmalloc_small(gm, nb)) != 0) {
-          check_malloced_chunk(gm, mem, nb);
-          goto postaction;
-        }
-      }
-    }
-    else if (bytes >= MAX_REQUEST)
-      nb = MAX_SIZE_T; /* Too big to allocate. Force failure (in sys alloc) */
-    else {
-      nb = pad_request(bytes);
-      if (gm->treemap != 0 && (mem = tmalloc_large(gm, nb)) != 0) {
-        check_malloced_chunk(gm, mem, nb);
-        goto postaction;
-      }
-    }
-
-    if (nb <= gm->dvsize) {
-      size_t rsize = gm->dvsize - nb;
-      mchunkptr p = gm->dv;
-      if (rsize >= MIN_CHUNK_SIZE) { /* split dv */
-        mchunkptr r = gm->dv = chunk_plus_offset(p, nb);
-        gm->dvsize = rsize;
-        set_size_and_pinuse_of_free_chunk(r, rsize);
-        set_size_and_pinuse_of_inuse_chunk(gm, p, nb);
-      }
-      else { /* exhaust dv */
-        size_t dvs = gm->dvsize;
-        gm->dvsize = 0;
-        gm->dv = 0;
-        set_inuse_and_pinuse(gm, p, dvs);
-      }
-      mem = chunk2mem(p);
-      check_malloced_chunk(gm, mem, nb);
-      goto postaction;
-    }
-
-    else if (nb < gm->topsize) { /* Split top */
-      size_t rsize = gm->topsize -= nb;
-      mchunkptr p = gm->top;
-      mchunkptr r = gm->top = chunk_plus_offset(p, nb);
-      r->head = rsize | PINUSE_BIT;
-      set_size_and_pinuse_of_inuse_chunk(gm, p, nb);
-      mem = chunk2mem(p);
-      check_top_chunk(gm, gm->top);
-      check_malloced_chunk(gm, mem, nb);
-      goto postaction;
-    }
-
-    mem = sys_alloc(gm, nb);
-
-  postaction:
-    POSTACTION(gm);
-    return mem;
-  }
-
-  return 0;
-}
-
-void dlfree(void* mem) {
-  /*
-     Consolidate freed chunks with preceeding or succeeding bordering
-     free chunks, if they exist, and then place in a bin.  Intermixed
-     with special cases for top, dv, mmapped chunks, and usage errors.
-  */
-
-  if (mem != 0) {
-    mchunkptr p  = mem2chunk(mem);
-#if FOOTERS
-    mstate fm = get_mstate_for(p);
-    if (!ok_magic(fm)) {
-      USAGE_ERROR_ACTION(fm, p);
-      return;
-    }
-#else /* FOOTERS */
-#define fm gm
-#endif /* FOOTERS */
-    if (!PREACTION(fm)) {
-      check_inuse_chunk(fm, p);
-      if (RTCHECK(ok_address(fm, p) && ok_cinuse(p))) {
-        size_t psize = chunksize(p);
-        mchunkptr next = chunk_plus_offset(p, psize);
-        if (!pinuse(p)) {
-          size_t prevsize = p->prev_foot;
-          if ((prevsize & IS_MMAPPED_BIT) != 0) {
-            prevsize &= ~IS_MMAPPED_BIT;
-            psize += prevsize + MMAP_FOOT_PAD;
-            if (CALL_MUNMAP((char*)p - prevsize, psize) == 0)
-              fm->footprint -= psize;
-            goto postaction;
-          }
-          else {
-            mchunkptr prev = chunk_minus_offset(p, prevsize);
-            psize += prevsize;
-            p = prev;
-            if (RTCHECK(ok_address(fm, prev))) { /* consolidate backward */
-              if (p != fm->dv) {
-                unlink_chunk(fm, p, prevsize);
-              }
-              else if ((next->head & INUSE_BITS) == INUSE_BITS) {
-                fm->dvsize = psize;
-                set_free_with_pinuse(p, psize, next);
-                goto postaction;
-              }
-            }
-            else
-              goto erroraction;
-          }
-        }
-
-        if (RTCHECK(ok_next(p, next) && ok_pinuse(next))) {
-          if (!cinuse(next)) {  /* consolidate forward */
-            if (next == fm->top) {
-              size_t tsize = fm->topsize += psize;
-              fm->top = p;
-              p->head = tsize | PINUSE_BIT;
-              if (p == fm->dv) {
-                fm->dv = 0;
-                fm->dvsize = 0;
-              }
-              if (should_trim(fm, tsize))
-                sys_trim(fm, 0);
-              goto postaction;
-            }
-            else if (next == fm->dv) {
-              size_t dsize = fm->dvsize += psize;
-              fm->dv = p;
-              set_size_and_pinuse_of_free_chunk(p, dsize);
-              goto postaction;
-            }
-            else {
-              size_t nsize = chunksize(next);
-              psize += nsize;
-              unlink_chunk(fm, next, nsize);
-              set_size_and_pinuse_of_free_chunk(p, psize);
-              if (p == fm->dv) {
-                fm->dvsize = psize;
-                goto postaction;
-              }
-            }
-          }
-          else
-            set_free_with_pinuse(p, psize, next);
-          insert_chunk(fm, p, psize);
-          check_free_chunk(fm, p);
-          goto postaction;
-        }
-      }
-    erroraction:
-      USAGE_ERROR_ACTION(fm, p);
-    postaction:
-      POSTACTION(fm);
-    }
-  }
-#if !FOOTERS
-#undef fm
-#endif /* FOOTERS */
-}
-
-void* dlcalloc(size_t n_elements, size_t elem_size) {
-  void* mem;
-  size_t req = 0;
-  if (n_elements != 0) {
-    req = n_elements * elem_size;
-    if (((n_elements | elem_size) & ~(size_t)0xffff) &&
-        (req / n_elements != elem_size))
-      req = MAX_SIZE_T; /* force downstream failure on overflow */
-  }
-  mem = dlmalloc(req);
-  if (mem != 0 && calloc_must_clear(mem2chunk(mem)))
-    memset(mem, 0, req);
-  return mem;
-}
-
-void* dlrealloc(void* oldmem, size_t bytes) {
-  if (oldmem == 0)
-    return dlmalloc(bytes);
-#ifdef REALLOC_ZERO_BYTES_FREES
-  if (bytes == 0) {
-    dlfree(oldmem);
-    return 0;
-  }
-#endif /* REALLOC_ZERO_BYTES_FREES */
-  else {
-#if ! FOOTERS
-    mstate m = gm;
-#else /* FOOTERS */
-    mstate m = get_mstate_for(mem2chunk(oldmem));
-    if (!ok_magic(m)) {
-      USAGE_ERROR_ACTION(m, oldmem);
-      return 0;
-    }
-#endif /* FOOTERS */
-    return internal_realloc(m, oldmem, bytes);
-  }
-}
-
-void* dlmemalign(size_t alignment, size_t bytes) {
-  return internal_memalign(gm, alignment, bytes);
-}
-
-void** dlindependent_calloc(size_t n_elements, size_t elem_size,
-                                 void* chunks[]) {
-  size_t sz = elem_size; /* serves as 1-element array */
-  return ialloc(gm, n_elements, &sz, 3, chunks);
-}
-
-void** dlindependent_comalloc(size_t n_elements, size_t sizes[],
-                                   void* chunks[]) {
-  return ialloc(gm, n_elements, sizes, 0, chunks);
-}
-
-void* dlvalloc(size_t bytes) {
-  size_t pagesz;
-  init_mparams();
-  pagesz = mparams.page_size;
-  return dlmemalign(pagesz, bytes);
-}
-
-void* dlpvalloc(size_t bytes) {
-  size_t pagesz;
-  init_mparams();
-  pagesz = mparams.page_size;
-  return dlmemalign(pagesz, (bytes + pagesz - SIZE_T_ONE) & ~(pagesz - SIZE_T_ONE));
-}
-
-int dlmalloc_trim(size_t pad) {
-  int result = 0;
-  if (!PREACTION(gm)) {
-    result = sys_trim(gm, pad);
-    POSTACTION(gm);
-  }
-  return result;
-}
-
-size_t dlmalloc_footprint(void) {
-  return gm->footprint;
-}
-
-size_t dlmalloc_max_footprint(void) {
-  return gm->max_footprint;
-}
-
-#if !NO_MALLINFO
-struct mallinfo dlmallinfo(void) {
-  return internal_mallinfo(gm);
-}
-#endif /* NO_MALLINFO */
-
-void dlmalloc_stats() {
-  internal_malloc_stats(gm);
-}
-
-size_t dlmalloc_usable_size(void* mem) {
-  if (mem != 0) {
-    mchunkptr p = mem2chunk(mem);
-    if (cinuse(p))
-      return chunksize(p) - overhead_for(p);
-  }
-  return 0;
-}
-
-int dlmallopt(int param_number, int value) {
-  return change_mparam(param_number, value);
-}
-
-#endif /* !ONLY_MSPACES */
-
-/* ----------------------------- user mspaces ---------------------------- */
-
-#if MSPACES
-
-static mstate init_user_mstate(char* tbase, size_t tsize) {
-  size_t msize = pad_request(sizeof(struct malloc_state));
-  mchunkptr mn;
-  mchunkptr msp = align_as_chunk(tbase);
-  mstate m = (mstate)(chunk2mem(msp));
-  memset(m, 0, msize);
-  INITIAL_LOCK(&m->mutex);
-  msp->head = (msize|PINUSE_BIT|CINUSE_BIT);
-  m->seg.base = m->least_addr = tbase;
-  m->seg.size = m->footprint = m->max_footprint = tsize;
-  m->magic = mparams.magic;
-  m->mflags = mparams.default_mflags;
-  disable_contiguous(m);
-  init_bins(m);
-  mn = next_chunk(mem2chunk(m));
-  init_top(m, mn, (size_t)((tbase + tsize) - (char*)mn) - TOP_FOOT_SIZE);
-  check_top_chunk(m, m->top);
-  return m;
-}
-
-mspace create_mspace(size_t capacity, int locked) {
-  mstate m = 0;
-  size_t msize = pad_request(sizeof(struct malloc_state));
-  init_mparams(); /* Ensure pagesize etc initialized */
-
-  if (capacity < (size_t) -(msize + TOP_FOOT_SIZE + mparams.page_size)) {
-    size_t rs = ((capacity == 0)? mparams.granularity :
-                 (capacity + TOP_FOOT_SIZE + msize));
-    size_t tsize = granularity_align(rs);
-    char* tbase = (char*)(CALL_MMAP(tsize));
-    if (tbase != CMFAIL) {
-      m = init_user_mstate(tbase, tsize);
-      m->seg.sflags = IS_MMAPPED_BIT;
-      set_lock(m, locked);
-    }
-  }
-  return (mspace)m;
-}
-
-mspace create_mspace_with_base(void* base, size_t capacity, int locked) {
-  mstate m = 0;
-  size_t msize = pad_request(sizeof(struct malloc_state));
-  init_mparams(); /* Ensure pagesize etc initialized */
-
-  if (capacity > msize + TOP_FOOT_SIZE &&
-      capacity < (size_t) -(msize + TOP_FOOT_SIZE + mparams.page_size)) {
-    m = init_user_mstate((char*)base, capacity);
-    m->seg.sflags = EXTERN_BIT;
-    set_lock(m, locked);
-  }
-  return (mspace)m;
-}
-
-size_t destroy_mspace(mspace msp) {
-  size_t freed = 0;
-  mstate ms = (mstate)msp;
-  if (ok_magic(ms)) {
-    msegmentptr sp = &ms->seg;
-    while (sp != 0) {
-      char* base = sp->base;
-      size_t size = sp->size;
-      flag_t flag = sp->sflags;
-      sp = sp->next;
-      if ((flag & IS_MMAPPED_BIT) && !(flag & EXTERN_BIT) &&
-          CALL_MUNMAP(base, size) == 0)
-        freed += size;
-    }
-  }
-  else {
-    USAGE_ERROR_ACTION(ms,ms);
-  }
-  return freed;
-}
-
-/*
-  mspace versions of routines are near-clones of the global
-  versions. This is not so nice but better than the alternatives.
-*/
-
-
-void* mspace_malloc(mspace msp, size_t bytes) {
-  mstate ms = (mstate)msp;
-  if (!ok_magic(ms)) {
-    USAGE_ERROR_ACTION(ms,ms);
-    return 0;
-  }
-  if (!PREACTION(ms)) {
-    void* mem;
-    size_t nb;
-    if (bytes <= MAX_SMALL_REQUEST) {
-      bindex_t idx;
-      binmap_t smallbits;
-      nb = (bytes < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(bytes);
-      idx = small_index(nb);
-      smallbits = ms->smallmap >> idx;
-
-      if ((smallbits & 0x3U) != 0) { /* Remainderless fit to a smallbin. */
-        mchunkptr b, p;
-        idx += ~smallbits & 1;       /* Uses next bin if idx empty */
-        b = smallbin_at(ms, idx);
-        p = b->fd;
-        assert(chunksize(p) == small_index2size(idx));
-        unlink_first_small_chunk(ms, b, p, idx);
-        set_inuse_and_pinuse(ms, p, small_index2size(idx));
-        mem = chunk2mem(p);
-        check_malloced_chunk(ms, mem, nb);
-        goto postaction;
-      }
-
-      else if (nb > ms->dvsize) {
-        if (smallbits != 0) { /* Use chunk in next nonempty smallbin */
-          mchunkptr b, p, r;
-          size_t rsize;
-          bindex_t i;
-          binmap_t leftbits = (smallbits << idx) & left_bits(idx2bit(idx));
-          binmap_t leastbit = least_bit(leftbits);
-          compute_bit2idx(leastbit, i);
-          b = smallbin_at(ms, i);
-          p = b->fd;
-          assert(chunksize(p) == small_index2size(i));
-          unlink_first_small_chunk(ms, b, p, i);
-          rsize = small_index2size(i) - nb;
-          /* Fit here cannot be remainderless if 4byte sizes */
-          if (SIZE_T_SIZE != 4 && rsize < MIN_CHUNK_SIZE)
-            set_inuse_and_pinuse(ms, p, small_index2size(i));
-          else {
-            set_size_and_pinuse_of_inuse_chunk(ms, p, nb);
-            r = chunk_plus_offset(p, nb);
-            set_size_and_pinuse_of_free_chunk(r, rsize);
-            replace_dv(ms, r, rsize);
-          }
-          mem = chunk2mem(p);
-          check_malloced_chunk(ms, mem, nb);
-          goto postaction;
-        }
-
-        else if (ms->treemap != 0 && (mem = tmalloc_small(ms, nb)) != 0) {
-          check_malloced_chunk(ms, mem, nb);
-          goto postaction;
-        }
-      }
-    }
-    else if (bytes >= MAX_REQUEST)
-      nb = MAX_SIZE_T; /* Too big to allocate. Force failure (in sys alloc) */
-    else {
-      nb = pad_request(bytes);
-      if (ms->treemap != 0 && (mem = tmalloc_large(ms, nb)) != 0) {
-        check_malloced_chunk(ms, mem, nb);
-        goto postaction;
-      }
-    }
-
-    if (nb <= ms->dvsize) {
-      size_t rsize = ms->dvsize - nb;
-      mchunkptr p = ms->dv;
-      if (rsize >= MIN_CHUNK_SIZE) { /* split dv */
-        mchunkptr r = ms->dv = chunk_plus_offset(p, nb);
-        ms->dvsize = rsize;
-        set_size_and_pinuse_of_free_chunk(r, rsize);
-        set_size_and_pinuse_of_inuse_chunk(ms, p, nb);
-      }
-      else { /* exhaust dv */
-        size_t dvs = ms->dvsize;
-        ms->dvsize = 0;
-        ms->dv = 0;
-        set_inuse_and_pinuse(ms, p, dvs);
-      }
-      mem = chunk2mem(p);
-      check_malloced_chunk(ms, mem, nb);
-      goto postaction;
-    }
-
-    else if (nb < ms->topsize) { /* Split top */
-      size_t rsize = ms->topsize -= nb;
-      mchunkptr p = ms->top;
-      mchunkptr r = ms->top = chunk_plus_offset(p, nb);
-      r->head = rsize | PINUSE_BIT;
-      set_size_and_pinuse_of_inuse_chunk(ms, p, nb);
-      mem = chunk2mem(p);
-      check_top_chunk(ms, ms->top);
-      check_malloced_chunk(ms, mem, nb);
-      goto postaction;
-    }
-
-    mem = sys_alloc(ms, nb);
-
-  postaction:
-    POSTACTION(ms);
-    return mem;
-  }
-
-  return 0;
-}
-
-void mspace_free(mspace msp, void* mem) {
-  if (mem != 0) {
-    mchunkptr p  = mem2chunk(mem);
-#if FOOTERS
-    mstate fm = get_mstate_for(p);
-#else /* FOOTERS */
-    mstate fm = (mstate)msp;
-#endif /* FOOTERS */
-    if (!ok_magic(fm)) {
-      USAGE_ERROR_ACTION(fm, p);
-      return;
-    }
-    if (!PREACTION(fm)) {
-      check_inuse_chunk(fm, p);
-      if (RTCHECK(ok_address(fm, p) && ok_cinuse(p))) {
-        size_t psize = chunksize(p);
-        mchunkptr next = chunk_plus_offset(p, psize);
-        if (!pinuse(p)) {
-          size_t prevsize = p->prev_foot;
-          if ((prevsize & IS_MMAPPED_BIT) != 0) {
-            prevsize &= ~IS_MMAPPED_BIT;
-            psize += prevsize + MMAP_FOOT_PAD;
-            if (CALL_MUNMAP((char*)p - prevsize, psize) == 0)
-              fm->footprint -= psize;
-            goto postaction;
-          }
-          else {
-            mchunkptr prev = chunk_minus_offset(p, prevsize);
-            psize += prevsize;
-            p = prev;
-            if (RTCHECK(ok_address(fm, prev))) { /* consolidate backward */
-              if (p != fm->dv) {
-                unlink_chunk(fm, p, prevsize);
-              }
-              else if ((next->head & INUSE_BITS) == INUSE_BITS) {
-                fm->dvsize = psize;
-                set_free_with_pinuse(p, psize, next);
-                goto postaction;
-              }
-            }
-            else
-              goto erroraction;
-          }
-        }
-
-        if (RTCHECK(ok_next(p, next) && ok_pinuse(next))) {
-          if (!cinuse(next)) {  /* consolidate forward */
-            if (next == fm->top) {
-              size_t tsize = fm->topsize += psize;
-              fm->top = p;
-              p->head = tsize | PINUSE_BIT;
-              if (p == fm->dv) {
-                fm->dv = 0;
-                fm->dvsize = 0;
-              }
-              if (should_trim(fm, tsize))
-                sys_trim(fm, 0);
-              goto postaction;
-            }
-            else if (next == fm->dv) {
-              size_t dsize = fm->dvsize += psize;
-              fm->dv = p;
-              set_size_and_pinuse_of_free_chunk(p, dsize);
-              goto postaction;
-            }
-            else {
-              size_t nsize = chunksize(next);
-              psize += nsize;
-              unlink_chunk(fm, next, nsize);
-              set_size_and_pinuse_of_free_chunk(p, psize);
-              if (p == fm->dv) {
-                fm->dvsize = psize;
-                goto postaction;
-              }
-            }
-          }
-          else
-            set_free_with_pinuse(p, psize, next);
-          insert_chunk(fm, p, psize);
-          check_free_chunk(fm, p);
-          goto postaction;
-        }
-      }
-    erroraction:
-      USAGE_ERROR_ACTION(fm, p);
-    postaction:
-      POSTACTION(fm);
-    }
-  }
-}
-
-void* mspace_calloc(mspace msp, size_t n_elements, size_t elem_size) {
-  void* mem;
-  size_t req = 0;
-  mstate ms = (mstate)msp;
-  if (!ok_magic(ms)) {
-    USAGE_ERROR_ACTION(ms,ms);
-    return 0;
-  }
-  if (n_elements != 0) {
-    req = n_elements * elem_size;
-    if (((n_elements | elem_size) & ~(size_t)0xffff) &&
-        (req / n_elements != elem_size))
-      req = MAX_SIZE_T; /* force downstream failure on overflow */
-  }
-  mem = internal_malloc(ms, req);
-  if (mem != 0 && calloc_must_clear(mem2chunk(mem)))
-    memset(mem, 0, req);
-  return mem;
-}
-
-void* mspace_realloc(mspace msp, void* oldmem, size_t bytes) {
-  if (oldmem == 0)
-    return mspace_malloc(msp, bytes);
-#ifdef REALLOC_ZERO_BYTES_FREES
-  if (bytes == 0) {
-    mspace_free(msp, oldmem);
-    return 0;
-  }
-#endif /* REALLOC_ZERO_BYTES_FREES */
-  else {
-#if FOOTERS
-    mchunkptr p  = mem2chunk(oldmem);
-    mstate ms = get_mstate_for(p);
-#else /* FOOTERS */
-    mstate ms = (mstate)msp;
-#endif /* FOOTERS */
-    if (!ok_magic(ms)) {
-      USAGE_ERROR_ACTION(ms,ms);
-      return 0;
-    }
-    return internal_realloc(ms, oldmem, bytes);
-  }
-}
-
-void* mspace_memalign(mspace msp, size_t alignment, size_t bytes) {
-  mstate ms = (mstate)msp;
-  if (!ok_magic(ms)) {
-    USAGE_ERROR_ACTION(ms,ms);
-    return 0;
-  }
-  return internal_memalign(ms, alignment, bytes);
-}
-
-void** mspace_independent_calloc(mspace msp, size_t n_elements,
-                                 size_t elem_size, void* chunks[]) {
-  size_t sz = elem_size; /* serves as 1-element array */
-  mstate ms = (mstate)msp;
-  if (!ok_magic(ms)) {
-    USAGE_ERROR_ACTION(ms,ms);
-    return 0;
-  }
-  return ialloc(ms, n_elements, &sz, 3, chunks);
-}
-
-void** mspace_independent_comalloc(mspace msp, size_t n_elements,
-                                   size_t sizes[], void* chunks[]) {
-  mstate ms = (mstate)msp;
-  if (!ok_magic(ms)) {
-    USAGE_ERROR_ACTION(ms,ms);
-    return 0;
-  }
-  return ialloc(ms, n_elements, sizes, 0, chunks);
-}
-
-int mspace_trim(mspace msp, size_t pad) {
-  int result = 0;
-  mstate ms = (mstate)msp;
-  if (ok_magic(ms)) {
-    if (!PREACTION(ms)) {
-      result = sys_trim(ms, pad);
-      POSTACTION(ms);
-    }
-  }
-  else {
-    USAGE_ERROR_ACTION(ms,ms);
-  }
-  return result;
-}
-
-void mspace_malloc_stats(mspace msp) {
-  mstate ms = (mstate)msp;
-  if (ok_magic(ms)) {
-    internal_malloc_stats(ms);
-  }
-  else {
-    USAGE_ERROR_ACTION(ms,ms);
-  }
-}
-
-size_t mspace_footprint(mspace msp) {
-  size_t result;
-  mstate ms = (mstate)msp;
-  if (ok_magic(ms)) {
-    result = ms->footprint;
-  }
-  USAGE_ERROR_ACTION(ms,ms);
-  return result;
-}
-
-
-size_t mspace_max_footprint(mspace msp) {
-  size_t result;
-  mstate ms = (mstate)msp;
-  if (ok_magic(ms)) {
-    result = ms->max_footprint;
-  }
-  USAGE_ERROR_ACTION(ms,ms);
-  return result;
-}
-
-
-#if !NO_MALLINFO
-struct mallinfo mspace_mallinfo(mspace msp) {
-  mstate ms = (mstate)msp;
-  if (!ok_magic(ms)) {
-    USAGE_ERROR_ACTION(ms,ms);
-  }
-  return internal_mallinfo(ms);
-}
-#endif /* NO_MALLINFO */
-
-int mspace_mallopt(int param_number, int value) {
-  return change_mparam(param_number, value);
-}
-
-#endif /* MSPACES */
-
-/* -------------------- Alternative MORECORE functions ------------------- */
-
-/*
-  Guidelines for creating a custom version of MORECORE:
-
-  * For best performance, MORECORE should allocate in multiples of pagesize.
-  * MORECORE may allocate more memory than requested. (Or even less,
-      but this will usually result in a malloc failure.)
-  * MORECORE must not allocate memory when given argument zero, but
-      instead return one past the end address of memory from previous
-      nonzero call.
-  * For best performance, consecutive calls to MORECORE with positive
-      arguments should return increasing addresses, indicating that
-      space has been contiguously extended.
-  * Even though consecutive calls to MORECORE need not return contiguous
-      addresses, it must be OK for malloc'ed chunks to span multiple
-      regions in those cases where they do happen to be contiguous.
-  * MORECORE need not handle negative arguments -- it may instead
-      just return MFAIL when given negative arguments.
-      Negative arguments are always multiples of pagesize. MORECORE
-      must not misinterpret negative args as large positive unsigned
-      args. You can suppress all such calls from even occurring by defining
-      MORECORE_CANNOT_TRIM,
-
-  As an example alternative MORECORE, here is a custom allocator
-  kindly contributed for pre-OSX macOS.  It uses virtually but not
-  necessarily physically contiguous non-paged memory (locked in,
-  present and won't get swapped out).  You can use it by uncommenting
-  this section, adding some #includes, and setting up the appropriate
-  defines above:
-
-      #define MORECORE osMoreCore
-
-  There is also a shutdown routine that should somehow be called for
-  cleanup upon program exit.
-
-  #define MAX_POOL_ENTRIES 100
-  #define MINIMUM_MORECORE_SIZE  (64 * 1024U)
-  static int next_os_pool;
-  void *our_os_pools[MAX_POOL_ENTRIES];
-
-  void *osMoreCore(int size)
-  {
-    void *ptr = 0;
-    static void *sbrk_top = 0;
-
-    if (size > 0)
-    {
-      if (size < MINIMUM_MORECORE_SIZE)
-         size = MINIMUM_MORECORE_SIZE;
-      if (CurrentExecutionLevel() == kTaskLevel)
-         ptr = PoolAllocateResident(size + RM_PAGE_SIZE, 0);
-      if (ptr == 0)
-      {
-        return (void *) MFAIL;
-      }
-      // save ptrs so they can be freed during cleanup
-      our_os_pools[next_os_pool] = ptr;
-      next_os_pool++;
-      ptr = (void *) ((((size_t) ptr) + RM_PAGE_MASK) & ~RM_PAGE_MASK);
-      sbrk_top = (char *) ptr + size;
-      return ptr;
-    }
-    else if (size < 0)
-    {
-      // we don't currently support shrink behavior
-      return (void *) MFAIL;
-    }
-    else
-    {
-      return sbrk_top;
-    }
-  }
-
-  // cleanup any allocated memory pools
-  // called as last thing before shutting down driver
-
-  void osCleanupMem(void)
-  {
-    void **ptr;
-
-    for (ptr = our_os_pools; ptr < &our_os_pools[MAX_POOL_ENTRIES]; ptr++)
-      if (*ptr)
-      {
-         PoolDeallocate(*ptr);
-         *ptr = 0;
-      }
-  }
-
-*/
-
-
-/* -----------------------------------------------------------------------
-History:
-    V2.8.3 Thu Sep 22 11:16:32 2005  Doug Lea  (dl at gee)
-      * Add max_footprint functions
-      * Ensure all appropriate literals are size_t
-      * Fix conditional compilation problem for some #define settings
-      * Avoid concatenating segments with the one provided
-        in create_mspace_with_base
-      * Rename some variables to avoid compiler shadowing warnings
-      * Use explicit lock initialization.
-      * Better handling of sbrk interference.
-      * Simplify and fix segment insertion, trimming and mspace_destroy
-      * Reinstate REALLOC_ZERO_BYTES_FREES option from 2.7.x
-      * Thanks especially to Dennis Flanagan for help on these.
-
-    V2.8.2 Sun Jun 12 16:01:10 2005  Doug Lea  (dl at gee)
-      * Fix memalign brace error.
-
-    V2.8.1 Wed Jun  8 16:11:46 2005  Doug Lea  (dl at gee)
-      * Fix improper #endif nesting in C++
-      * Add explicit casts needed for C++
-
-    V2.8.0 Mon May 30 14:09:02 2005  Doug Lea  (dl at gee)
-      * Use trees for large bins
-      * Support mspaces
-      * Use segments to unify sbrk-based and mmap-based system allocation,
-        removing need for emulation on most platforms without sbrk.
-      * Default safety checks
-      * Optional footer checks. Thanks to William Robertson for the idea.
-      * Internal code refactoring
-      * Incorporate suggestions and platform-specific changes.
-        Thanks to Dennis Flanagan, Colin Plumb, Niall Douglas,
-        Aaron Bachmann,  Emery Berger, and others.
-      * Speed up non-fastbin processing enough to remove fastbins.
-      * Remove useless cfree() to avoid conflicts with other apps.
-      * Remove internal memcpy, memset. Compilers handle builtins better.
-      * Remove some options that no one ever used and rename others.
-
-    V2.7.2 Sat Aug 17 09:07:30 2002  Doug Lea  (dl at gee)
-      * Fix malloc_state bitmap array misdeclaration
-
-    V2.7.1 Thu Jul 25 10:58:03 2002  Doug Lea  (dl at gee)
-      * Allow tuning of FIRST_SORTED_BIN_SIZE
-      * Use PTR_UINT as type for all ptr->int casts. Thanks to John Belmonte.
-      * Better detection and support for non-contiguousness of MORECORE.
-        Thanks to Andreas Mueller, Conal Walsh, and Wolfram Gloger
-      * Bypass most of malloc if no frees. Thanks To Emery Berger.
-      * Fix freeing of old top non-contiguous chunk im sysmalloc.
-      * Raised default trim and map thresholds to 256K.
-      * Fix mmap-related #defines. Thanks to Lubos Lunak.
-      * Fix copy macros; added LACKS_FCNTL_H. Thanks to Neal Walfield.
-      * Branch-free bin calculation
-      * Default trim and mmap thresholds now 256K.
-
-    V2.7.0 Sun Mar 11 14:14:06 2001  Doug Lea  (dl at gee)
-      * Introduce independent_comalloc and independent_calloc.
-        Thanks to Michael Pachos for motivation and help.
-      * Make optional .h file available
-      * Allow > 2GB requests on 32bit systems.
-      * new WIN32 sbrk, mmap, munmap, lock code from <Walter@GeNeSys-e.de>.
-        Thanks also to Andreas Mueller <a.mueller at paradatec.de>,
-        and Anonymous.
-      * Allow override of MALLOC_ALIGNMENT (Thanks to Ruud Waij for
-        helping test this.)
-      * memalign: check alignment arg
-      * realloc: don't try to shift chunks backwards, since this
-        leads to  more fragmentation in some programs and doesn't
-        seem to help in any others.
-      * Collect all cases in malloc requiring system memory into sysmalloc
-      * Use mmap as backup to sbrk
-      * Place all internal state in malloc_state
-      * Introduce fastbins (although similar to 2.5.1)
-      * Many minor tunings and cosmetic improvements
-      * Introduce USE_PUBLIC_MALLOC_WRAPPERS, USE_MALLOC_LOCK
-      * Introduce MALLOC_FAILURE_ACTION, MORECORE_CONTIGUOUS
-        Thanks to Tony E. Bennett <tbennett@nvidia.com> and others.
-      * Include errno.h to support default failure action.
-
-    V2.6.6 Sun Dec  5 07:42:19 1999  Doug Lea  (dl at gee)
-      * return null for negative arguments
-      * Added Several WIN32 cleanups from Martin C. Fong <mcfong at yahoo.com>
-         * Add 'LACKS_SYS_PARAM_H' for those systems without 'sys/param.h'
-          (e.g. WIN32 platforms)
-         * Cleanup header file inclusion for WIN32 platforms
-         * Cleanup code to avoid Microsoft Visual C++ compiler complaints
-         * Add 'USE_DL_PREFIX' to quickly allow co-existence with existing
-           memory allocation routines
-         * Set 'malloc_getpagesize' for WIN32 platforms (needs more work)
-         * Use 'assert' rather than 'ASSERT' in WIN32 code to conform to
-           usage of 'assert' in non-WIN32 code
-         * Improve WIN32 'sbrk()' emulation's 'findRegion()' routine to
-           avoid infinite loop
-      * Always call 'fREe()' rather than 'free()'
-
-    V2.6.5 Wed Jun 17 15:57:31 1998  Doug Lea  (dl at gee)
-      * Fixed ordering problem with boundary-stamping
-
-    V2.6.3 Sun May 19 08:17:58 1996  Doug Lea  (dl at gee)
-      * Added pvalloc, as recommended by H.J. Liu
-      * Added 64bit pointer support mainly from Wolfram Gloger
-      * Added anonymously donated WIN32 sbrk emulation
-      * Malloc, calloc, getpagesize: add optimizations from Raymond Nijssen
-      * malloc_extend_top: fix mask error that caused wastage after
-        foreign sbrks
-      * Add linux mremap support code from HJ Liu
-
-    V2.6.2 Tue Dec  5 06:52:55 1995  Doug Lea  (dl at gee)
-      * Integrated most documentation with the code.
-      * Add support for mmap, with help from
-        Wolfram Gloger (Gloger@lrz.uni-muenchen.de).
-      * Use last_remainder in more cases.
-      * Pack bins using idea from  colin@nyx10.cs.du.edu
-      * Use ordered bins instead of best-fit threshhold
-      * Eliminate block-local decls to simplify tracing and debugging.
-      * Support another case of realloc via move into top
-      * Fix error occuring when initial sbrk_base not word-aligned.
-      * Rely on page size for units instead of SBRK_UNIT to
-        avoid surprises about sbrk alignment conventions.
-      * Add mallinfo, mallopt. Thanks to Raymond Nijssen
-        (raymond@es.ele.tue.nl) for the suggestion.
-      * Add `pad' argument to malloc_trim and top_pad mallopt parameter.
-      * More precautions for cases where other routines call sbrk,
-        courtesy of Wolfram Gloger (Gloger@lrz.uni-muenchen.de).
-      * Added macros etc., allowing use in linux libc from
-        H.J. Lu (hjl@gnu.ai.mit.edu)
-      * Inverted this history list
-
-    V2.6.1 Sat Dec  2 14:10:57 1995  Doug Lea  (dl at gee)
-      * Re-tuned and fixed to behave more nicely with V2.6.0 changes.
-      * Removed all preallocation code since under current scheme
-        the work required to undo bad preallocations exceeds
-        the work saved in good cases for most test programs.
-      * No longer use return list or unconsolidated bins since
-        no scheme using them consistently outperforms those that don't
-        given above changes.
-      * Use best fit for very large chunks to prevent some worst-cases.
-      * Added some support for debugging
-
-    V2.6.0 Sat Nov  4 07:05:23 1995  Doug Lea  (dl at gee)
-      * Removed footers when chunks are in use. Thanks to
-        Paul Wilson (wilson@cs.texas.edu) for the suggestion.
-
-    V2.5.4 Wed Nov  1 07:54:51 1995  Doug Lea  (dl at gee)
-      * Added malloc_trim, with help from Wolfram Gloger
-        (wmglo@Dent.MED.Uni-Muenchen.DE).
-
-    V2.5.3 Tue Apr 26 10:16:01 1994  Doug Lea  (dl at g)
-
-    V2.5.2 Tue Apr  5 16:20:40 1994  Doug Lea  (dl at g)
-      * realloc: try to expand in both directions
-      * malloc: swap order of clean-bin strategy;
-      * realloc: only conditionally expand backwards
-      * Try not to scavenge used bins
-      * Use bin counts as a guide to preallocation
-      * Occasionally bin return list chunks in first scan
-      * Add a few optimizations from colin@nyx10.cs.du.edu
-
-    V2.5.1 Sat Aug 14 15:40:43 1993  Doug Lea  (dl at g)
-      * faster bin computation & slightly different binning
-      * merged all consolidations to one part of malloc proper
-         (eliminating old malloc_find_space & malloc_clean_bin)
-      * Scan 2 returns chunks (not just 1)
-      * Propagate failure in realloc if malloc returns 0
-      * Add stuff to allow compilation on non-ANSI compilers
-          from kpv@research.att.com
-
-    V2.5 Sat Aug  7 07:41:59 1993  Doug Lea  (dl at g.oswego.edu)
-      * removed potential for odd address access in prev_chunk
-      * removed dependency on getpagesize.h
-      * misc cosmetics and a bit more internal documentation
-      * anticosmetics: mangled names in macros to evade debugger strangeness
-      * tested on sparc, hp-700, dec-mips, rs6000
-          with gcc & native cc (hp, dec only) allowing
-          Detlefs & Zorn comparison study (in SIGPLAN Notices.)
-
-    Trial version Fri Aug 28 13:14:29 1992  Doug Lea  (dl at g.oswego.edu)
-      * Based loosely on libg++-1.2X malloc. (It retains some of the overall
-         structure of old version,  but most details differ.)
-
-*/
diff --git a/lib/dlmalloc.h b/lib/dlmalloc.h
deleted file mode 100644
index 197b36667..000000000
--- a/lib/dlmalloc.h
+++ /dev/null
@@ -1,1143 +0,0 @@
-#ifndef DLMALLOC_H

-#define DLMALLOC_H

-

-#define USE_DL_PREFIX

-

-/*

-

-#define FOOTERS 1

-#define DEBUG 1

-#define ABORT_ON_ASSERT_FAILURE 0

-*/

-

-/*

-  This is a version (aka dlmalloc) of malloc/free/realloc written by

-  Doug Lea and released to the public domain, as explained at

-  http://creativecommons.org/licenses/publicdomain.  Send questions,

-  comments, complaints, performance data, etc to dl@cs.oswego.edu

-

-* Version 2.8.3 Thu Sep 22 11:16:15 2005  Doug Lea  (dl at gee)

-

-   Note: There may be an updated version of this malloc obtainable at

-           ftp://gee.cs.oswego.edu/pub/misc/malloc.c

-         Check before installing!

-

-* Quickstart

-

-  This library is all in one file to simplify the most common usage:

-  ftp it, compile it (-O3), and link it into another program. All of

-  the compile-time options default to reasonable values for use on

-  most platforms.  You might later want to step through various

-  compile-time and dynamic tuning options.

-

-  For convenience, an include file for code using this malloc is at:

-     ftp://gee.cs.oswego.edu/pub/misc/malloc-2.8.3.h

-  You don't really need this .h file unless you call functions not

-  defined in your system include files.  The .h file contains only the

-  excerpts from this file needed for using this malloc on ANSI C/C++

-  systems, so long as you haven't changed compile-time options about

-  naming and tuning parameters.  If you do, then you can create your

-  own malloc.h that does include all settings by cutting at the point

-  indicated below. Note that you may already by default be using a C

-  library containing a malloc that is based on some version of this

-  malloc (for example in linux). You might still want to use the one

-  in this file to customize settings or to avoid overheads associated

-  with library versions.

-

-* Vital statistics:

-

-  Supported pointer/size_t representation:       4 or 8 bytes

-       size_t MUST be an unsigned type of the same width as

-       pointers. (If you are using an ancient system that declares

-       size_t as a signed type, or need it to be a different width

-       than pointers, you can use a previous release of this malloc

-       (e.g. 2.7.2) supporting these.)

-

-  Alignment:                                     8 bytes (default)

-       This suffices for nearly all current machines and C compilers.

-       However, you can define MALLOC_ALIGNMENT to be wider than this

-       if necessary (up to 128bytes), at the expense of using more space.

-

-  Minimum overhead per allocated chunk:   4 or  8 bytes (if 4byte sizes)

-                                          8 or 16 bytes (if 8byte sizes)

-       Each malloced chunk has a hidden word of overhead holding size

-       and status information, and additional cross-check word

-       if FOOTERS is defined.

-

-  Minimum allocated size: 4-byte ptrs:  16 bytes    (including overhead)

-                          8-byte ptrs:  32 bytes    (including overhead)

-

-       Even a request for zero bytes (i.e., malloc(0)) returns a

-       pointer to something of the minimum allocatable size.

-       The maximum overhead wastage (i.e., number of extra bytes

-       allocated than were requested in malloc) is less than or equal

-       to the minimum size, except for requests >= mmap_threshold that

-       are serviced via mmap(), where the worst case wastage is about

-       32 bytes plus the remainder from a system page (the minimal

-       mmap unit); typically 4096 or 8192 bytes.

-

-  Security: static-safe; optionally more or less

-       The "security" of malloc refers to the ability of malicious

-       code to accentuate the effects of errors (for example, freeing

-       space that is not currently malloc'ed or overwriting past the

-       ends of chunks) in code that calls malloc.  This malloc

-       guarantees not to modify any memory locations below the base of

-       heap, i.e., static variables, even in the presence of usage

-       errors.  The routines additionally detect most improper frees

-       and reallocs.  All this holds as long as the static bookkeeping

-       for malloc itself is not corrupted by some other means.  This

-       is only one aspect of security -- these checks do not, and

-       cannot, detect all possible programming errors.

-

-       If FOOTERS is defined nonzero, then each allocated chunk

-       carries an additional check word to verify that it was malloced

-       from its space.  These check words are the same within each

-       execution of a program using malloc, but differ across

-       executions, so externally crafted fake chunks cannot be

-       freed. This improves security by rejecting frees/reallocs that

-       could corrupt heap memory, in addition to the checks preventing

-       writes to statics that are always on.  This may further improve

-       security at the expense of time and space overhead.  (Note that

-       FOOTERS may also be worth using with MSPACES.)

-

-       By default detected errors cause the program to abort (calling

-       "abort()"). You can override this to instead proceed past

-       errors by defining PROCEED_ON_ERROR.  In this case, a bad free

-       has no effect, and a malloc that encounters a bad address

-       caused by user overwrites will ignore the bad address by

-       dropping pointers and indices to all known memory. This may

-       be appropriate for programs that should continue if at all

-       possible in the face of programming errors, although they may

-       run out of memory because dropped memory is never reclaimed.

-

-       If you don't like either of these options, you can define

-       CORRUPTION_ERROR_ACTION and USAGE_ERROR_ACTION to do anything

-       else. And if if you are sure that your program using malloc has

-       no errors or vulnerabilities, you can define INSECURE to 1,

-       which might (or might not) provide a small performance improvement.

-

-  Thread-safety: NOT thread-safe unless USE_LOCKS defined

-       When USE_LOCKS is defined, each public call to malloc, free,

-       etc is surrounded with either a pthread mutex or a win32

-       spinlock (depending on WIN32). This is not especially fast, and

-       can be a major bottleneck.  It is designed only to provide

-       minimal protection in concurrent environments, and to provide a

-       basis for extensions.  If you are using malloc in a concurrent

-       program, consider instead using ptmalloc, which is derived from

-       a version of this malloc. (See http://www.malloc.de).

-

-  System requirements: Any combination of MORECORE and/or MMAP/MUNMAP

-       This malloc can use unix sbrk or any emulation (invoked using

-       the CALL_MORECORE macro) and/or mmap/munmap or any emulation

-       (invoked using CALL_MMAP/CALL_MUNMAP) to get and release system

-       memory.  On most unix systems, it tends to work best if both

-       MORECORE and MMAP are enabled.  On Win32, it uses emulations

-       based on VirtualAlloc. It also uses common C library functions

-       like memset.

-

-  Compliance: I believe it is compliant with the Single Unix Specification

-       (See http://www.unix.org). Also SVID/XPG, ANSI C, and probably

-       others as well.

-

-* Overview of algorithms

-

-  This is not the fastest, most space-conserving, most portable, or

-  most tunable malloc ever written. However it is among the fastest

-  while also being among the most space-conserving, portable and

-  tunable.  Consistent balance across these factors results in a good

-  general-purpose allocator for malloc-intensive programs.

-

-  In most ways, this malloc is a best-fit allocator. Generally, it

-  chooses the best-fitting existing chunk for a request, with ties

-  broken in approximately least-recently-used order. (This strategy

-  normally maintains low fragmentation.) However, for requests less

-  than 256bytes, it deviates from best-fit when there is not an

-  exactly fitting available chunk by preferring to use space adjacent

-  to that used for the previous small request, as well as by breaking

-  ties in approximately most-recently-used order. (These enhance

-  locality of series of small allocations.)  And for very large requests

-  (>= 256Kb by default), it relies on system memory mapping

-  facilities, if supported.  (This helps avoid carrying around and

-  possibly fragmenting memory used only for large chunks.)

-

-  All operations (except malloc_stats and mallinfo) have execution

-  times that are bounded by a constant factor of the number of bits in

-  a size_t, not counting any clearing in calloc or copying in realloc,

-  or actions surrounding MORECORE and MMAP that have times

-  proportional to the number of non-contiguous regions returned by

-  system allocation routines, which is often just 1.

-

-  The implementation is not very modular and seriously overuses

-  macros. Perhaps someday all C compilers will do as good a job

-  inlining modular code as can now be done by brute-force expansion,

-  but now, enough of them seem not to.

-

-  Some compilers issue a lot of warnings about code that is

-  dead/unreachable only on some platforms, and also about intentional

-  uses of negation on unsigned types. All known cases of each can be

-  ignored.

-

-  For a longer but out of date high-level description, see

-     http://gee.cs.oswego.edu/dl/html/malloc.html

-

-* MSPACES

-  If MSPACES is defined, then in addition to malloc, free, etc.,

-  this file also defines mspace_malloc, mspace_free, etc. These

-  are versions of malloc routines that take an "mspace" argument

-  obtained using create_mspace, to control all internal bookkeeping.

-  If ONLY_MSPACES is defined, only these versions are compiled.

-  So if you would like to use this allocator for only some allocations,

-  and your system malloc for others, you can compile with

-  ONLY_MSPACES and then do something like...

-    static mspace mymspace = create_mspace(0,0); // for example

-    #define mymalloc(bytes)  mspace_malloc(mymspace, bytes)

-

-  (Note: If you only need one instance of an mspace, you can instead

-  use "USE_DL_PREFIX" to relabel the global malloc.)

-

-  You can similarly create thread-local allocators by storing

-  mspaces as thread-locals. For example:

-    static __thread mspace tlms = 0;

-    void*  tlmalloc(size_t bytes) {

-      if (tlms == 0) tlms = create_mspace(0, 0);

-      return mspace_malloc(tlms, bytes);

-    }

-    void  tlfree(void* mem) { mspace_free(tlms, mem); }

-

-  Unless FOOTERS is defined, each mspace is completely independent.

-  You cannot allocate from one and free to another (although

-  conformance is only weakly checked, so usage errors are not always

-  caught). If FOOTERS is defined, then each chunk carries around a tag

-  indicating its originating mspace, and frees are directed to their

-  originating spaces.

-

- -------------------------  Compile-time options ---------------------------

-

-Be careful in setting #define values for numerical constants of type

-size_t. On some systems, literal values are not automatically extended

-to size_t precision unless they are explicitly casted.

-

-WIN32                    default: defined if _WIN32 defined

-  Defining WIN32 sets up defaults for MS environment and compilers.

-  Otherwise defaults are for unix.

-

-MALLOC_ALIGNMENT         default: (size_t)8

-  Controls the minimum alignment for malloc'ed chunks.  It must be a

-  power of two and at least 8, even on machines for which smaller

-  alignments would suffice. It may be defined as larger than this

-  though. Note however that code and data structures are optimized for

-  the case of 8-byte alignment.

-

-MSPACES                  default: 0 (false)

-  If true, compile in support for independent allocation spaces.

-  This is only supported if HAVE_MMAP is true.

-

-ONLY_MSPACES             default: 0 (false)

-  If true, only compile in mspace versions, not regular versions.

-

-USE_LOCKS                default: 0 (false)

-  Causes each call to each public routine to be surrounded with

-  pthread or WIN32 mutex lock/unlock. (If set true, this can be

-  overridden on a per-mspace basis for mspace versions.)

-

-FOOTERS                  default: 0

-  If true, provide extra checking and dispatching by placing

-  information in the footers of allocated chunks. This adds

-  space and time overhead.

-

-INSECURE                 default: 0

-  If true, omit checks for usage errors and heap space overwrites.

-

-USE_DL_PREFIX            default: NOT defined

-  Causes compiler to prefix all public routines with the string 'dl'.

-  This can be useful when you only want to use this malloc in one part

-  of a program, using your regular system malloc elsewhere.

-

-ABORT                    default: defined as abort()

-  Defines how to abort on failed checks.  On most systems, a failed

-  check cannot die with an "assert" or even print an informative

-  message, because the underlying print routines in turn call malloc,

-  which will fail again.  Generally, the best policy is to simply call

-  abort(). It's not very useful to do more than this because many

-  errors due to overwriting will show up as address faults (null, odd

-  addresses etc) rather than malloc-triggered checks, so will also

-  abort.  Also, most compilers know that abort() does not return, so

-  can better optimize code conditionally calling it.

-

-PROCEED_ON_ERROR           default: defined as 0 (false)

-  Controls whether detected bad addresses cause them to bypassed

-  rather than aborting. If set, detected bad arguments to free and

-  realloc are ignored. And all bookkeeping information is zeroed out

-  upon a detected overwrite of freed heap space, thus losing the

-  ability to ever return it from malloc again, but enabling the

-  application to proceed. If PROCEED_ON_ERROR is defined, the

-  static variable malloc_corruption_error_count is compiled in

-  and can be examined to see if errors have occurred. This option

-  generates slower code than the default abort policy.

-

-DEBUG                    default: NOT defined

-  The DEBUG setting is mainly intended for people trying to modify

-  this code or diagnose problems when porting to new platforms.

-  However, it may also be able to better isolate user errors than just

-  using runtime checks.  The assertions in the check routines spell

-  out in more detail the assumptions and invariants underlying the

-  algorithms.  The checking is fairly extensive, and will slow down

-  execution noticeably. Calling malloc_stats or mallinfo with DEBUG

-  set will attempt to check every non-mmapped allocated and free chunk

-  in the course of computing the summaries.

-

-ABORT_ON_ASSERT_FAILURE   default: defined as 1 (true)

-  Debugging assertion failures can be nearly impossible if your

-  version of the assert macro causes malloc to be called, which will

-  lead to a cascade of further failures, blowing the runtime stack.

-  ABORT_ON_ASSERT_FAILURE cause assertions failures to call abort(),

-  which will usually make debugging easier.

-

-MALLOC_FAILURE_ACTION     default: sets errno to ENOMEM, or no-op on win32

-  The action to take before "return 0" when malloc fails to be able to

-  return memory because there is none available.

-

-HAVE_MORECORE             default: 1 (true) unless win32 or ONLY_MSPACES

-  True if this system supports sbrk or an emulation of it.

-

-MORECORE                  default: sbrk

-  The name of the sbrk-style system routine to call to obtain more

-  memory.  See below for guidance on writing custom MORECORE

-  functions. The type of the argument to sbrk/MORECORE varies across

-  systems.  It cannot be size_t, because it supports negative

-  arguments, so it is normally the signed type of the same width as

-  size_t (sometimes declared as "intptr_t").  It doesn't much matter

-  though. Internally, we only call it with arguments less than half

-  the max value of a size_t, which should work across all reasonable

-  possibilities, although sometimes generating compiler warnings.  See

-  near the end of this file for guidelines for creating a custom

-  version of MORECORE.

-

-MORECORE_CONTIGUOUS       default: 1 (true)

-  If true, take advantage of fact that consecutive calls to MORECORE

-  with positive arguments always return contiguous increasing

-  addresses.  This is true of unix sbrk. It does not hurt too much to

-  set it true anyway, since malloc copes with non-contiguities.

-  Setting it false when definitely non-contiguous saves time

-  and possibly wasted space it would take to discover this though.

-

-MORECORE_CANNOT_TRIM      default: NOT defined

-  True if MORECORE cannot release space back to the system when given

-  negative arguments. This is generally necessary only if you are

-  using a hand-crafted MORECORE function that cannot handle negative

-  arguments.

-

-HAVE_MMAP                 default: 1 (true)

-  True if this system supports mmap or an emulation of it.  If so, and

-  HAVE_MORECORE is not true, MMAP is used for all system

-  allocation. If set and HAVE_MORECORE is true as well, MMAP is

-  primarily used to directly allocate very large blocks. It is also

-  used as a backup strategy in cases where MORECORE fails to provide

-  space from system. Note: A single call to MUNMAP is assumed to be

-  able to unmap memory that may have be allocated using multiple calls

-  to MMAP, so long as they are adjacent.

-

-HAVE_MREMAP               default: 1 on linux, else 0

-  If true realloc() uses mremap() to re-allocate large blocks and

-  extend or shrink allocation spaces.

-

-MMAP_CLEARS               default: 1 on unix

-  True if mmap clears memory so calloc doesn't need to. This is true

-  for standard unix mmap using /dev/zero.

-

-USE_BUILTIN_FFS            default: 0 (i.e., not used)

-  Causes malloc to use the builtin ffs() function to compute indices.

-  Some compilers may recognize and intrinsify ffs to be faster than the

-  supplied C version. Also, the case of x86 using gcc is special-cased

-  to an asm instruction, so is already as fast as it can be, and so

-  this setting has no effect. (On most x86s, the asm version is only

-  slightly faster than the C version.)

-

-malloc_getpagesize         default: derive from system includes, or 4096.

-  The system page size. To the extent possible, this malloc manages

-  memory from the system in page-size units.  This may be (and

-  usually is) a function rather than a constant. This is ignored

-  if WIN32, where page size is determined using getSystemInfo during

-  initialization.

-

-USE_DEV_RANDOM             default: 0 (i.e., not used)

-  Causes malloc to use /dev/random to initialize secure magic seed for

-  stamping footers. Otherwise, the current time is used.

-

-NO_MALLINFO                default: 0

-  If defined, don't compile "mallinfo". This can be a simple way

-  of dealing with mismatches between system declarations and

-  those in this file.

-

-MALLINFO_FIELD_TYPE        default: size_t

-  The type of the fields in the mallinfo struct. This was originally

-  defined as "int" in SVID etc, but is more usefully defined as

-  size_t. The value is used only if  HAVE_USR_INCLUDE_MALLOC_H is not set

-

-REALLOC_ZERO_BYTES_FREES    default: not defined

-  This should be set if a call to realloc with zero bytes should

-  be the same as a call to free. Some people think it should. Otherwise,

-  since this malloc returns a unique pointer for malloc(0), so does

-  realloc(p, 0).

-

-LACKS_UNISTD_H, LACKS_FCNTL_H, LACKS_SYS_PARAM_H, LACKS_SYS_MMAN_H

-LACKS_STRINGS_H, LACKS_STRING_H, LACKS_SYS_TYPES_H,  LACKS_ERRNO_H

-LACKS_STDLIB_H                default: NOT defined unless on WIN32

-  Define these if your system does not have these header files.

-  You might need to manually insert some of the declarations they provide.

-

-DEFAULT_GRANULARITY        default: page size if MORECORE_CONTIGUOUS,

-                                system_info.dwAllocationGranularity in WIN32,

-                                otherwise 64K.

-      Also settable using mallopt(M_GRANULARITY, x)

-  The unit for allocating and deallocating memory from the system.  On

-  most systems with contiguous MORECORE, there is no reason to

-  make this more than a page. However, systems with MMAP tend to

-  either require or encourage larger granularities.  You can increase

-  this value to prevent system allocation functions to be called so

-  often, especially if they are slow.  The value must be at least one

-  page and must be a power of two.  Setting to 0 causes initialization

-  to either page size or win32 region size.  (Note: In previous

-  versions of malloc, the equivalent of this option was called

-  "TOP_PAD")

-

-DEFAULT_TRIM_THRESHOLD    default: 2MB

-      Also settable using mallopt(M_TRIM_THRESHOLD, x)

-  The maximum amount of unused top-most memory to keep before

-  releasing via malloc_trim in free().  Automatic trimming is mainly

-  useful in long-lived programs using contiguous MORECORE.  Because

-  trimming via sbrk can be slow on some systems, and can sometimes be

-  wasteful (in cases where programs immediately afterward allocate

-  more large chunks) the value should be high enough so that your

-  overall system performance would improve by releasing this much

-  memory.  As a rough guide, you might set to a value close to the

-  average size of a process (program) running on your system.

-  Releasing this much memory would allow such a process to run in

-  memory.  Generally, it is worth tuning trim thresholds when a

-  program undergoes phases where several large chunks are allocated

-  and released in ways that can reuse each other's storage, perhaps

-  mixed with phases where there are no such chunks at all. The trim

-  value must be greater than page size to have any useful effect.  To

-  disable trimming completely, you can set to MAX_SIZE_T. Note that the trick

-  some people use of mallocing a huge space and then freeing it at

-  program startup, in an attempt to reserve system memory, doesn't

-  have the intended effect under automatic trimming, since that memory

-  will immediately be returned to the system.

-

-DEFAULT_MMAP_THRESHOLD       default: 256K

-      Also settable using mallopt(M_MMAP_THRESHOLD, x)

-  The request size threshold for using MMAP to directly service a

-  request. Requests of at least this size that cannot be allocated

-  using already-existing space will be serviced via mmap.  (If enough

-  normal freed space already exists it is used instead.)  Using mmap

-  segregates relatively large chunks of memory so that they can be

-  individually obtained and released from the host system. A request

-  serviced through mmap is never reused by any other request (at least

-  not directly; the system may just so happen to remap successive

-  requests to the same locations).  Segregating space in this way has

-  the benefits that: Mmapped space can always be individually released

-  back to the system, which helps keep the system level memory demands

-  of a long-lived program low.  Also, mapped memory doesn't become

-  `locked' between other chunks, as can happen with normally allocated

-  chunks, which means that even trimming via malloc_trim would not

-  release them.  However, it has the disadvantage that the space

-  cannot be reclaimed, consolidated, and then used to service later

-  requests, as happens with normal chunks.  The advantages of mmap

-  nearly always outweigh disadvantages for "large" chunks, but the

-  value of "large" may vary across systems.  The default is an

-  empirically derived value that works well in most systems. You can

-  disable mmap by setting to MAX_SIZE_T.

-

-*/

-

-#ifndef WIN32

-#ifdef _WIN32

-#define WIN32 1

-#endif  /* _WIN32 */

-#endif  /* WIN32 */

-#ifdef WIN32

-#define WIN32_LEAN_AND_MEAN

-#include <windows.h>

-#define HAVE_MMAP 1

-#define HAVE_MORECORE 0

-#define LACKS_UNISTD_H

-#define LACKS_SYS_PARAM_H

-#define LACKS_SYS_MMAN_H

-#define LACKS_STRING_H

-#define LACKS_STRINGS_H

-#define LACKS_SYS_TYPES_H

-#define LACKS_ERRNO_H

-#define MALLOC_FAILURE_ACTION

-#define MMAP_CLEARS 0 /* WINCE and some others apparently don't clear */

-#endif  /* WIN32 */

-

-#if defined(DARWIN) || defined(_DARWIN)

-/* Mac OSX docs advise not to use sbrk; it seems better to use mmap */

-#ifndef HAVE_MORECORE

-#define HAVE_MORECORE 0

-#define HAVE_MMAP 1

-#endif  /* HAVE_MORECORE */

-#endif  /* DARWIN */

-

-#ifndef LACKS_SYS_TYPES_H

-#include <sys/types.h>  /* For size_t */

-#endif  /* LACKS_SYS_TYPES_H */

-

-/* The maximum possible size_t value has all bits set */

-#define MAX_SIZE_T           (~(size_t)0)

-

-#ifndef ONLY_MSPACES

-#define ONLY_MSPACES 0

-#endif  /* ONLY_MSPACES */

-#ifndef MSPACES

-#if ONLY_MSPACES

-#define MSPACES 1

-#else   /* ONLY_MSPACES */

-#define MSPACES 0

-#endif  /* ONLY_MSPACES */

-#endif  /* MSPACES */

-#ifndef MALLOC_ALIGNMENT

-#define MALLOC_ALIGNMENT ((size_t)8U)

-#endif  /* MALLOC_ALIGNMENT */

-#ifndef FOOTERS

-#define FOOTERS 0

-#endif  /* FOOTERS */

-#ifndef ABORT

-#define ABORT  abort()

-#endif  /* ABORT */

-#ifndef ABORT_ON_ASSERT_FAILURE

-#define ABORT_ON_ASSERT_FAILURE 1

-#endif  /* ABORT_ON_ASSERT_FAILURE */

-#ifndef PROCEED_ON_ERROR

-#define PROCEED_ON_ERROR 0

-#endif  /* PROCEED_ON_ERROR */

-#ifndef USE_LOCKS

-#define USE_LOCKS 0

-#endif  /* USE_LOCKS */

-#ifndef INSECURE

-#define INSECURE 0

-#endif  /* INSECURE */

-#ifndef HAVE_MMAP

-#define HAVE_MMAP 1

-#endif  /* HAVE_MMAP */

-#ifndef MMAP_CLEARS

-#define MMAP_CLEARS 1

-#endif  /* MMAP_CLEARS */

-#ifndef HAVE_MREMAP

-#ifdef linux

-#define HAVE_MREMAP 1

-#else   /* linux */

-#define HAVE_MREMAP 0

-#endif  /* linux */

-#endif  /* HAVE_MREMAP */

-#ifndef MALLOC_FAILURE_ACTION

-#define MALLOC_FAILURE_ACTION  errno = ENOMEM;

-#endif  /* MALLOC_FAILURE_ACTION */

-#ifndef HAVE_MORECORE

-#if ONLY_MSPACES

-#define HAVE_MORECORE 0

-#else   /* ONLY_MSPACES */

-#define HAVE_MORECORE 1

-#endif  /* ONLY_MSPACES */

-#endif  /* HAVE_MORECORE */

-#if !HAVE_MORECORE

-#define MORECORE_CONTIGUOUS 0

-#else   /* !HAVE_MORECORE */

-#ifndef MORECORE

-#define MORECORE sbrk

-#endif  /* MORECORE */

-#ifndef MORECORE_CONTIGUOUS

-#define MORECORE_CONTIGUOUS 1

-#endif  /* MORECORE_CONTIGUOUS */

-#endif  /* HAVE_MORECORE */

-#ifndef DEFAULT_GRANULARITY

-#if MORECORE_CONTIGUOUS

-#define DEFAULT_GRANULARITY (0)  /* 0 means to compute in init_mparams */

-#else   /* MORECORE_CONTIGUOUS */

-#define DEFAULT_GRANULARITY ((size_t)64U * (size_t)1024U)

-#endif  /* MORECORE_CONTIGUOUS */

-#endif  /* DEFAULT_GRANULARITY */

-#ifndef DEFAULT_TRIM_THRESHOLD

-#ifndef MORECORE_CANNOT_TRIM

-#define DEFAULT_TRIM_THRESHOLD ((size_t)2U * (size_t)1024U * (size_t)1024U)

-#else   /* MORECORE_CANNOT_TRIM */

-#define DEFAULT_TRIM_THRESHOLD MAX_SIZE_T

-#endif  /* MORECORE_CANNOT_TRIM */

-#endif  /* DEFAULT_TRIM_THRESHOLD */

-#ifndef DEFAULT_MMAP_THRESHOLD

-#if HAVE_MMAP

-#define DEFAULT_MMAP_THRESHOLD ((size_t)256U * (size_t)1024U)

-#else   /* HAVE_MMAP */

-#define DEFAULT_MMAP_THRESHOLD MAX_SIZE_T

-#endif  /* HAVE_MMAP */

-#endif  /* DEFAULT_MMAP_THRESHOLD */

-#ifndef USE_BUILTIN_FFS

-#define USE_BUILTIN_FFS 0

-#endif  /* USE_BUILTIN_FFS */

-#ifndef USE_DEV_RANDOM

-#define USE_DEV_RANDOM 0

-#endif  /* USE_DEV_RANDOM */

-#ifndef NO_MALLINFO

-#define NO_MALLINFO 0

-#endif  /* NO_MALLINFO */

-#ifndef MALLINFO_FIELD_TYPE

-#define MALLINFO_FIELD_TYPE size_t

-#endif  /* MALLINFO_FIELD_TYPE */

-

-/*

-  mallopt tuning options.  SVID/XPG defines four standard parameter

-  numbers for mallopt, normally defined in malloc.h.  None of these

-  are used in this malloc, so setting them has no effect. But this

-  malloc does support the following options.

-*/

-

-#define M_TRIM_THRESHOLD     (-1)

-#define M_GRANULARITY        (-2)

-#define M_MMAP_THRESHOLD     (-3)

-

-/* ------------------------ Mallinfo declarations ------------------------ */

-

-#if !NO_MALLINFO

-/*

-  This version of malloc supports the standard SVID/XPG mallinfo

-  routine that returns a struct containing usage properties and

-  statistics. It should work on any system that has a

-  /usr/include/malloc.h defining struct mallinfo.  The main

-  declaration needed is the mallinfo struct that is returned (by-copy)

-  by mallinfo().  The malloinfo struct contains a bunch of fields that

-  are not even meaningful in this version of malloc.  These fields are

-  are instead filled by mallinfo() with other numbers that might be of

-  interest.

-

-  HAVE_USR_INCLUDE_MALLOC_H should be set if you have a

-  /usr/include/malloc.h file that includes a declaration of struct

-  mallinfo.  If so, it is included; else a compliant version is

-  declared below.  These must be precisely the same for mallinfo() to

-  work.  The original SVID version of this struct, defined on most

-  systems with mallinfo, declares all fields as ints. But some others

-  define as unsigned long. If your system defines the fields using a

-  type of different width than listed here, you MUST #include your

-  system version and #define HAVE_USR_INCLUDE_MALLOC_H.

-*/

-

-/* #define HAVE_USR_INCLUDE_MALLOC_H */

-

-#ifdef HAVE_USR_INCLUDE_MALLOC_H

-#include "/usr/include/malloc.h"

-#else /* HAVE_USR_INCLUDE_MALLOC_H */

-

-struct mallinfo {

-  MALLINFO_FIELD_TYPE arena;    /* non-mmapped space allocated from system */

-  MALLINFO_FIELD_TYPE ordblks;  /* number of free chunks */

-  MALLINFO_FIELD_TYPE smblks;   /* always 0 */

-  MALLINFO_FIELD_TYPE hblks;    /* always 0 */

-  MALLINFO_FIELD_TYPE hblkhd;   /* space in mmapped regions */

-  MALLINFO_FIELD_TYPE usmblks;  /* maximum total allocated space */

-  MALLINFO_FIELD_TYPE fsmblks;  /* always 0 */

-  MALLINFO_FIELD_TYPE uordblks; /* total allocated space */

-  MALLINFO_FIELD_TYPE fordblks; /* total free space */

-  MALLINFO_FIELD_TYPE keepcost; /* releasable (via malloc_trim) space */

-};

-

-#endif /* HAVE_USR_INCLUDE_MALLOC_H */

-#endif /* NO_MALLINFO */

-

-#ifdef __cplusplus

-extern "C" {

-#endif /* __cplusplus */

-

-#if !ONLY_MSPACES

-

-/* ------------------- Declarations of public routines ------------------- */

-

-#ifndef USE_DL_PREFIX

-#define dlcalloc               calloc

-#define dlfree                 free

-#define dlmalloc               malloc

-#define dlmemalign             memalign

-#define dlrealloc              realloc

-#define dlvalloc               valloc

-#define dlpvalloc              pvalloc

-#define dlmallinfo             mallinfo

-#define dlmallopt              mallopt

-#define dlmalloc_trim          malloc_trim

-#define dlmalloc_stats         malloc_stats

-#define dlmalloc_usable_size   malloc_usable_size

-#define dlmalloc_footprint     malloc_footprint

-#define dlmalloc_max_footprint malloc_max_footprint

-#define dlindependent_calloc   independent_calloc

-#define dlindependent_comalloc independent_comalloc

-#endif /* USE_DL_PREFIX */

-

-

-/*

-  malloc(size_t n)

-  Returns a pointer to a newly allocated chunk of at least n bytes, or

-  null if no space is available, in which case errno is set to ENOMEM

-  on ANSI C systems.

-

-  If n is zero, malloc returns a minimum-sized chunk. (The minimum

-  size is 16 bytes on most 32bit systems, and 32 bytes on 64bit

-  systems.)  Note that size_t is an unsigned type, so calls with

-  arguments that would be negative if signed are interpreted as

-  requests for huge amounts of space, which will often fail. The

-  maximum supported value of n differs across systems, but is in all

-  cases less than the maximum representable value of a size_t.

-*/

-void* dlmalloc(size_t);

-

-/*

-  free(void* p)

-  Releases the chunk of memory pointed to by p, that had been previously

-  allocated using malloc or a related routine such as realloc.

-  It has no effect if p is null. If p was not malloced or already

-  freed, free(p) will by default cause the current program to abort.

-*/

-void  dlfree(void*);

-

-/*

-  calloc(size_t n_elements, size_t element_size);

-  Returns a pointer to n_elements * element_size bytes, with all locations

-  set to zero.

-*/

-void* dlcalloc(size_t, size_t);

-

-/*

-  realloc(void* p, size_t n)

-  Returns a pointer to a chunk of size n that contains the same data

-  as does chunk p up to the minimum of (n, p's size) bytes, or null

-  if no space is available.

-

-  The returned pointer may or may not be the same as p. The algorithm

-  prefers extending p in most cases when possible, otherwise it

-  employs the equivalent of a malloc-copy-free sequence.

-

-  If p is null, realloc is equivalent to malloc.

-

-  If space is not available, realloc returns null, errno is set (if on

-  ANSI) and p is NOT freed.

-

-  if n is for fewer bytes than already held by p, the newly unused

-  space is lopped off and freed if possible.  realloc with a size

-  argument of zero (re)allocates a minimum-sized chunk.

-

-  The old unix realloc convention of allowing the last-free'd chunk

-  to be used as an argument to realloc is not supported.

-*/

-

-void* dlrealloc(void*, size_t);

-

-/*

-  memalign(size_t alignment, size_t n);

-  Returns a pointer to a newly allocated chunk of n bytes, aligned

-  in accord with the alignment argument.

-

-  The alignment argument should be a power of two. If the argument is

-  not a power of two, the nearest greater power is used.

-  8-byte alignment is guaranteed by normal malloc calls, so don't

-  bother calling memalign with an argument of 8 or less.

-

-  Overreliance on memalign is a sure way to fragment space.

-*/

-void* dlmemalign(size_t, size_t);

-

-/*

-  valloc(size_t n);

-  Equivalent to memalign(pagesize, n), where pagesize is the page

-  size of the system. If the pagesize is unknown, 4096 is used.

-*/

-void* dlvalloc(size_t);

-

-/*

-  mallopt(int parameter_number, int parameter_value)

-  Sets tunable parameters The format is to provide a

-  (parameter-number, parameter-value) pair.  mallopt then sets the

-  corresponding parameter to the argument value if it can (i.e., so

-  long as the value is meaningful), and returns 1 if successful else

-  0.  SVID/XPG/ANSI defines four standard param numbers for mallopt,

-  normally defined in malloc.h.  None of these are use in this malloc,

-  so setting them has no effect. But this malloc also supports other

-  options in mallopt. See below for details.  Briefly, supported

-  parameters are as follows (listed defaults are for "typical"

-  configurations).

-

-  Symbol            param #  default    allowed param values

-  M_TRIM_THRESHOLD     -1   2*1024*1024   any   (MAX_SIZE_T disables)

-  M_GRANULARITY        -2     page size   any power of 2 >= page size

-  M_MMAP_THRESHOLD     -3      256*1024   any   (or 0 if no MMAP support)

-*/

-int dlmallopt(int, int);

-

-/*

-  malloc_footprint();

-  Returns the number of bytes obtained from the system.  The total

-  number of bytes allocated by malloc, realloc etc., is less than this

-  value. Unlike mallinfo, this function returns only a precomputed

-  result, so can be called frequently to monitor memory consumption.

-  Even if locks are otherwise defined, this function does not use them,

-  so results might not be up to date.

-*/

-size_t dlmalloc_footprint(void);

-

-/*

-  malloc_max_footprint();

-  Returns the maximum number of bytes obtained from the system. This

-  value will be greater than current footprint if deallocated space

-  has been reclaimed by the system. The peak number of bytes allocated

-  by malloc, realloc etc., is less than this value. Unlike mallinfo,

-  this function returns only a precomputed result, so can be called

-  frequently to monitor memory consumption.  Even if locks are

-  otherwise defined, this function does not use them, so results might

-  not be up to date.

-*/

-size_t dlmalloc_max_footprint(void);

-

-#if !NO_MALLINFO

-/*

-  mallinfo()

-  Returns (by copy) a struct containing various summary statistics:

-

-  arena:     current total non-mmapped bytes allocated from system

-  ordblks:   the number of free chunks

-  smblks:    always zero.

-  hblks:     current number of mmapped regions

-  hblkhd:    total bytes held in mmapped regions

-  usmblks:   the maximum total allocated space. This will be greater

-                than current total if trimming has occurred.

-  fsmblks:   always zero

-  uordblks:  current total allocated space (normal or mmapped)

-  fordblks:  total free space

-  keepcost:  the maximum number of bytes that could ideally be released

-               back to system via malloc_trim. ("ideally" means that

-               it ignores page restrictions etc.)

-

-  Because these fields are ints, but internal bookkeeping may

-  be kept as longs, the reported values may wrap around zero and

-  thus be inaccurate.

-*/

-struct mallinfo dlmallinfo(void);

-#endif /* NO_MALLINFO */

-

-/*

-  independent_calloc(size_t n_elements, size_t element_size, void* chunks[]);

-

-  independent_calloc is similar to calloc, but instead of returning a

-  single cleared space, it returns an array of pointers to n_elements

-  independent elements that can hold contents of size elem_size, each

-  of which starts out cleared, and can be independently freed,

-  realloc'ed etc. The elements are guaranteed to be adjacently

-  allocated (this is not guaranteed to occur with multiple callocs or

-  mallocs), which may also improve cache locality in some

-  applications.

-

-  The "chunks" argument is optional (i.e., may be null, which is

-  probably the most typical usage). If it is null, the returned array

-  is itself dynamically allocated and should also be freed when it is

-  no longer needed. Otherwise, the chunks array must be of at least

-  n_elements in length. It is filled in with the pointers to the

-  chunks.

-

-  In either case, independent_calloc returns this pointer array, or

-  null if the allocation failed.  If n_elements is zero and "chunks"

-  is null, it returns a chunk representing an array with zero elements

-  (which should be freed if not wanted).

-

-  Each element must be individually freed when it is no longer

-  needed. If you'd like to instead be able to free all at once, you

-  should instead use regular calloc and assign pointers into this

-  space to represent elements.  (In this case though, you cannot

-  independently free elements.)

-

-  independent_calloc simplifies and speeds up implementations of many

-  kinds of pools.  It may also be useful when constructing large data

-  structures that initially have a fixed number of fixed-sized nodes,

-  but the number is not known at compile time, and some of the nodes

-  may later need to be freed. For example:

-

-  struct Node { int item; struct Node* next; };

-

-  struct Node* build_list() {

-    struct Node** pool;

-    int n = read_number_of_nodes_needed();

-    if (n <= 0) return 0;

-    pool = (struct Node**)(independent_calloc(n, sizeof(struct Node), 0);

-    if (pool == 0) die();

-    // organize into a linked list...

-    struct Node* first = pool[0];

-    for (i = 0; i < n-1; ++i)

-      pool[i]->next = pool[i+1];

-    free(pool);     // Can now free the array (or not, if it is needed later)

-    return first;

-  }

-*/

-void** dlindependent_calloc(size_t, size_t, void**);

-

-/*

-  independent_comalloc(size_t n_elements, size_t sizes[], void* chunks[]);

-

-  independent_comalloc allocates, all at once, a set of n_elements

-  chunks with sizes indicated in the "sizes" array.    It returns

-  an array of pointers to these elements, each of which can be

-  independently freed, realloc'ed etc. The elements are guaranteed to

-  be adjacently allocated (this is not guaranteed to occur with

-  multiple callocs or mallocs), which may also improve cache locality

-  in some applications.

-

-  The "chunks" argument is optional (i.e., may be null). If it is null

-  the returned array is itself dynamically allocated and should also

-  be freed when it is no longer needed. Otherwise, the chunks array

-  must be of at least n_elements in length. It is filled in with the

-  pointers to the chunks.

-

-  In either case, independent_comalloc returns this pointer array, or

-  null if the allocation failed.  If n_elements is zero and chunks is

-  null, it returns a chunk representing an array with zero elements

-  (which should be freed if not wanted).

-

-  Each element must be individually freed when it is no longer

-  needed. If you'd like to instead be able to free all at once, you

-  should instead use a single regular malloc, and assign pointers at

-  particular offsets in the aggregate space. (In this case though, you

-  cannot independently free elements.)

-

-  independent_comallac differs from independent_calloc in that each

-  element may have a different size, and also that it does not

-  automatically clear elements.

-

-  independent_comalloc can be used to speed up allocation in cases

-  where several structs or objects must always be allocated at the

-  same time.  For example:

-

-  struct Head { ... }

-  struct Foot { ... }

-

-  void send_message(char* msg) {

-    int msglen = strlen(msg);

-    size_t sizes[3] = { sizeof(struct Head), msglen, sizeof(struct Foot) };

-    void* chunks[3];

-    if (independent_comalloc(3, sizes, chunks) == 0)

-      die();

-    struct Head* head = (struct Head*)(chunks[0]);

-    char*        body = (char*)(chunks[1]);

-    struct Foot* foot = (struct Foot*)(chunks[2]);

-    // ...

-  }

-

-  In general though, independent_comalloc is worth using only for

-  larger values of n_elements. For small values, you probably won't

-  detect enough difference from series of malloc calls to bother.

-

-  Overuse of independent_comalloc can increase overall memory usage,

-  since it cannot reuse existing noncontiguous small chunks that

-  might be available for some of the elements.

-*/

-void** dlindependent_comalloc(size_t, size_t*, void**);

-

-

-/*

-  pvalloc(size_t n);

-  Equivalent to valloc(minimum-page-that-holds(n)), that is,

-  round up n to nearest pagesize.

- */

-void*  dlpvalloc(size_t);

-

-/*

-  malloc_trim(size_t pad);

-

-  If possible, gives memory back to the system (via negative arguments

-  to sbrk) if there is unused memory at the `high' end of the malloc

-  pool or in unused MMAP segments. You can call this after freeing

-  large blocks of memory to potentially reduce the system-level memory

-  requirements of a program. However, it cannot guarantee to reduce

-  memory. Under some allocation patterns, some large free blocks of

-  memory will be locked between two used chunks, so they cannot be

-  given back to the system.

-

-  The `pad' argument to malloc_trim represents the amount of free

-  trailing space to leave untrimmed. If this argument is zero, only

-  the minimum amount of memory to maintain internal data structures

-  will be left. Non-zero arguments can be supplied to maintain enough

-  trailing space to service future expected allocations without having

-  to re-obtain memory from the system.

-

-  Malloc_trim returns 1 if it actually released any memory, else 0.

-*/

-int  dlmalloc_trim(size_t);

-

-/*

-  malloc_usable_size(void* p);

-

-  Returns the number of bytes you can actually use in

-  an allocated chunk, which may be more than you requested (although

-  often not) due to alignment and minimum size constraints.

-  You can use this many bytes without worrying about

-  overwriting other allocated objects. This is not a particularly great

-  programming practice. malloc_usable_size can be more useful in

-  debugging and assertions, for example:

-

-  p = malloc(n);

-  assert(malloc_usable_size(p) >= 256);

-*/

-size_t dlmalloc_usable_size(void*);

-

-/*

-  malloc_stats();

-  Prints on stderr the amount of space obtained from the system (both

-  via sbrk and mmap), the maximum amount (which may be more than

-  current if malloc_trim and/or munmap got called), and the current

-  number of bytes allocated via malloc (or realloc, etc) but not yet

-  freed. Note that this is the number of bytes allocated, not the

-  number requested. It will be larger than the number requested

-  because of alignment and bookkeeping overhead. Because it includes

-  alignment wastage as being in use, this figure may be greater than

-  zero even when no user-level chunks are allocated.

-

-  The reported current and maximum system memory can be inaccurate if

-  a program makes other calls to system memory allocation functions

-  (normally sbrk) outside of malloc.

-

-  malloc_stats prints only the most commonly interesting statistics.

-  More information can be obtained by calling mallinfo.

-*/

-void  dlmalloc_stats(void);

-

-#endif /* ONLY_MSPACES */

-

-#if MSPACES

-

-/*

-  mspace is an opaque type representing an independent

-  region of space that supports mspace_malloc, etc.

-*/

-typedef void* mspace;

-

-/*

-  create_mspace creates and returns a new independent space with the

-  given initial capacity, or, if 0, the default granularity size.  It

-  returns null if there is no system memory available to create the

-  space.  If argument locked is non-zero, the space uses a separate

-  lock to control access. The capacity of the space will grow

-  dynamically as needed to service mspace_malloc requests.  You can

-  control the sizes of incremental increases of this space by

-  compiling with a different DEFAULT_GRANULARITY or dynamically

-  setting with mallopt(M_GRANULARITY, value).

-*/

-mspace create_mspace(size_t capacity, int locked);

-

-/*

-  destroy_mspace destroys the given space, and attempts to return all

-  of its memory back to the system, returning the total number of

-  bytes freed. After destruction, the results of access to all memory

-  used by the space become undefined.

-*/

-size_t destroy_mspace(mspace msp);

-

-/*

-  create_mspace_with_base uses the memory supplied as the initial base

-  of a new mspace. Part (less than 128*sizeof(size_t) bytes) of this

-  space is used for bookkeeping, so the capacity must be at least this

-  large. (Otherwise 0 is returned.) When this initial space is

-  exhausted, additional memory will be obtained from the system.

-  Destroying this space will deallocate all additionally allocated

-  space (if possible) but not the initial base.

-*/

-mspace create_mspace_with_base(void* base, size_t capacity, int locked);

-

-/*

-  mspace_malloc behaves as malloc, but operates within

-  the given space.

-*/

-void* mspace_malloc(mspace msp, size_t bytes);

-

-/*

-  mspace_free behaves as free, but operates within

-  the given space.

-

-  If compiled with FOOTERS==1, mspace_free is not actually needed.

-  free may be called instead of mspace_free because freed chunks from

-  any space are handled by their originating spaces.

-*/

-void mspace_free(mspace msp, void* mem);

-

-/*

-  mspace_realloc behaves as realloc, but operates within

-  the given space.

-

-  If compiled with FOOTERS==1, mspace_realloc is not actually

-  needed.  realloc may be called instead of mspace_realloc because

-  realloced chunks from any space are handled by their originating

-  spaces.

-*/

-void* mspace_realloc(mspace msp, void* mem, size_t newsize);

-

-/*

-  mspace_calloc behaves as calloc, but operates within

-  the given space.

-*/

-void* mspace_calloc(mspace msp, size_t n_elements, size_t elem_size);

-

-/*

-  mspace_memalign behaves as memalign, but operates within

-  the given space.

-*/

-void* mspace_memalign(mspace msp, size_t alignment, size_t bytes);

-

-/*

-  mspace_independent_calloc behaves as independent_calloc, but

-  operates within the given space.

-*/

-void** mspace_independent_calloc(mspace msp, size_t n_elements,

-                                 size_t elem_size, void* chunks[]);

-

-/*

-  mspace_independent_comalloc behaves as independent_comalloc, but

-  operates within the given space.

-*/

-void** mspace_independent_comalloc(mspace msp, size_t n_elements,

-                                   size_t sizes[], void* chunks[]);

-

-/*

-  mspace_footprint() returns the number of bytes obtained from the

-  system for this space.

-*/

-size_t mspace_footprint(mspace msp);

-

-/*

-  mspace_max_footprint() returns the peak number of bytes obtained from the

-  system for this space.

-*/

-size_t mspace_max_footprint(mspace msp);

-

-

-#if !NO_MALLINFO

-/*

-  mspace_mallinfo behaves as mallinfo, but reports properties of

-  the given space.

-*/

-struct mallinfo mspace_mallinfo(mspace msp);

-#endif /* NO_MALLINFO */

-

-/*

-  mspace_malloc_stats behaves as malloc_stats, but reports

-  properties of the given space.

-*/

-void mspace_malloc_stats(mspace msp);

-

-/*

-  mspace_trim behaves as malloc_trim, but

-  operates within the given space.

-*/

-int mspace_trim(mspace msp, size_t pad);

-

-/*

-  An alias for mallopt.

-*/

-int mspace_mallopt(int, int);

-

-#endif /* MSPACES */

-

-#ifdef __cplusplus

-};  /* end of extern "C" */

-#endif /* __cplusplus */

-

-#endif /* DLMALLOC_H */

diff --git a/lib/generics.nim b/lib/generics.nim
deleted file mode 100644
index 1ed7651e1..000000000
--- a/lib/generics.nim
+++ /dev/null
@@ -1,169 +0,0 @@
-#
-#
-#            Nimrod's Runtime Library
-#        (c) Copyright 2008 Andreas Rumpf
-#
-#    See the file "copying.txt", included in this
-#    distribution, for details about the copyright.
-#
-
-## This module contains basic abstract data types.
-
-type
-  TListItem[T] = object
-    next, prev: ref TListItem[T]
-    data: T
-
-  TList*[T] = ref TListItem[T]
-#  TIndex*[T] = object
-
-#proc succ*[T](i: TIndex[T]): TIndex[T] =
-#  result = i.next
-
-#proc pred*[T](i: TIndex[T]): TIndex[T] =
-#  result = i.prev
-
-#proc getIndex*[T](c: TList[T]): TIndex[TList[T]] =
-#  return c
-
-proc init*[T](c: var TList[T]) {.inline.} =
-  c = nil
-
-iterator items*[T](c: TList[T]): var T {.inline.} =
-  var it = c
-  while it != nil:
-    yield it.data
-    it = it.next
-
-proc add*[T](c: var TList[T], item: T) {.inline.} =
-  var it: ref TListItem[T]
-  new(it)
-  it.data = item
-  it.prev = c.prev
-  it.next = c.next
-  c = it
-
-proc incl*[T](c: var TList[T], item: T) =
-  for i in items(c):
-    if i == item: return
-  add(c, item)
-
-proc excl*[T](c: var TList[T], item: T) =
-  var it: TList[T] = c
-  while it != nil:
-    if it.data == item:
-      # remove from list
-    it = it.next
-
-proc del*[T](c: var TList[T], item: T) {.inline.} = excl(c, item)
-
-proc hash*(p: pointer): int {.inline.} =
-  # Returns the hash value of a pointer. This is very fast.
-  return cast[TAddress](p) shr 3
-
-proc hash*(x: int): int {.inline.} = return x
-proc hash*(x: char): int {.inline.} = return ord(x)
-proc hash*(x: bool): int {.inline.} = return ord(x)
-
-proc hash*(s: string): int =
-  # The generic hash table implementation work on a type `T` that has a hash
-  # proc. Predefined for string, pointers, int, char, bool.
-  var h = 0
-  for i in 0..s.len-1:
-    h = h +% Ord(s[i])
-    h = h +% h shl 10
-    h = h xor (h shr 6)
-  h = h +% h shl 3
-  h = h xor (h shr 11)
-  h = h +% h shl 15
-  result = h
-
-proc isNil*(x: int): bool {.inline.} = return x == low(int)
-proc nilValue*(x: int): int {.inline.} = return low(int)
-proc nilValue*(x: pointer): pointer {.inline.} = return nil
-proc nilValue*(x: string): string {.inline.} = return nil
-proc nilValue*[T](x: seq[T]): seq[T] {.inline.} = return nil
-proc nilValue*(x: float): float {.inline.} = return NaN
-
-proc mustRehash(len, counter: int): bool =
-  assert(len > counter)
-  result = (len * 2 < counter * 3) or (len-counter < 4)
-
-proc nextTry(h, maxHash: int): int {.inline.} =
-  return ((5*%h) +% 1) and maxHash
-
-type
-  TPair*[TKey, TValue] = tuple[key: TKey, val: TValue]
-  TTable*[TKey, TValue] =
-      object of TObject ## A table which stores (key, value)
-                        ## pairs. The used algorithm is hashing.
-    d: seq[TPair[TKey, TValue]]
-    counter: natural
-
-const
-  growthFactor = 2 # must be power of two
-
-proc init*[TKey, TValue](t: var TTable[TKey, TValue], capacity: natural = 32) =
-  newSeq(t.d, capacity)
-
-proc len*[TKey, TValue](t: TTable[TKey, TValue]): natural = return t.counter
-
-iterator pairs*[TKey,TValue](t: TTable[TKey,TValue]): TPair[TKey, TValue] =
-  for i in 0..t.d.len-1:
-    if not isNil(t.d[i].key):
-      yield (t.d[i].key, t.d[i].val)
-
-proc TableRawGet[TKey, TValue](t: TTable[TKey, TValue], key: TKey): int =
-  var h = hash(key) and high(t.d)
-  while not isNil(t.d[h].key):
-    if t.d[h].key == key: return h
-    h = nextTry(h, high(t.d))
-  return -1
-
-proc `[]`*[TKey, TValue](t: TTable[TKey, TValue], key: TKey): TValue =
-  var index = TableRawGet(t, key)
-  return if index >= 0: t.d[index].val else: nilValue(t.d[0].val)
-
-proc TableRawInsert[TKey, TValue](data: var seq[TPair[TKey, TValue]],
-                                  key: TKey, val: TValue) =
-  var h = hash(key) and high(data)
-  while not isNil(data[h].key):
-    assert(data[h].key != key)
-    h = nextTry(h, high(data))
-  assert(isNil(data[h].key))
-  data[h].key = key
-  data[h].val = val
-
-proc TableEnlarge[TKey, TValue](t: var TTable[TKey, TValue]) =
-  var n: seq[TPair[TKey,TValue]]
-  newSeq(n, len(t.d) * growthFactor)
-  for i in 0..high(t.d):
-    if not isNil(t.d[i].key):
-      TableRawInsert(n, t.d[i].key, t.d[i].val)
-  swap(t.d, n)
-
-proc `[]=`*[TKey, TValue](t: var TTable[TKey, TValue], key: TKey, val: TValue) =
-  var index = TableRawGet(t, key)
-  if index >= 0:
-    t.d[index].val = val
-  else:
-    if mustRehash(len(t.d), t.counter): TableEnlarge(t)
-    TableRawInsert(t.d, key, val)
-    inc(t.counter)
-
-proc add*[TKey, TValue](t: var TTable[TKey, TValue], key: TKey, val: TValue) =
-  if mustRehash(len(t.d), t.counter): TableEnlarge(t)
-  TableRawInsert(t.d, key, val)
-  inc(t.counter)
-
-proc test =
-  var
-    t: TTable[string, int]
-  init(t)
-  t["key1"] = 1
-  t["key2"] = 2
-  t["key3"] = 3
-  for key, val in pairs(t):
-    echo(key & " = " & $val)
-
-test()
diff --git a/lib/i386.asm.in b/lib/i386.asm.in
deleted file mode 100644
index 483dc2d95..000000000
--- a/lib/i386.asm.in
+++ /dev/null
@@ -1,70 +0,0 @@
-; This contains the CPU-dependant variants of some routines.

-; (C) 2005 Andreas Rumpf

-; This code was inspired by the Freepascal compiler's sources

-; All routines here have the _cdecl calling convention because

-; that is the only convention any C compiler supports.

-

-\python{

-# as usual I use my own preprocessor :-)

-import os

-

-def c(name): 

-  if os.name == 'posix':

-    return name

-  else:

-    return "_" + name

-}

-

-segment code

-

-global \c{cpu_inc_locked}

-global \c{cpu_dec_locked}

-global \c{cpu_lock}

-global \c{cpu_unlock}

-

-\c{cpu_dec_locked}:  

-          push ebp 

-          mov ebp,esp 

-          mov eax,[ebp+8] ; first parameter to function 

-          lock dec dword [eax]

-          setz      al

-          mov esp,ebp 

-          pop ebp 

-          ret

-

-\c{cpu_inc_locked}:

-          push ebp 

-          mov ebp,esp 

-          mov eax,[ebp+8] ; first parameter to function 

-          lock inc dword [eax]

-          mov esp,ebp 

-          pop ebp 

-          ret

-

-; This code uses the highest bit of the RC to indicate that the RC is

-; locked (spinlock).

-\c{cpu_lock}

-          push ebp 

-          mov ebp, esp 

-          mov eax, [ebp+8]     ; first parameter to function 

-          mov edx, [eax]       ; load RC

-          or  edx, 0x80000000  ; set highest bit

-     spin:

-          xchg [eax], edx      ; atomic instruction!

-          pause                ; wait a few cycles

-          and edx, 0x80000000  ; mask highest bit

-          jnz spin

-          mov esp, ebp

-          pop ebp

-          ret

-

-\c{cpu_unlock}

-          push ebp            

-          mov ebp, esp 

-          mov eax, [ebp+8]     ; first parameter to function 

-          mov edx, [eax]       ; load RC

-          and edx, 0x7FFFFFFF  ; unset highest bit

-          xchg [eax], edx      ; atomic instruction!

-          mov esp, ebp

-          pop ebp

-          ret

diff --git a/lib/base/dialogs.nim b/lib/impure/dialogs.nim
index cf81a3d29..cf81a3d29 100644
--- a/lib/base/dialogs.nim
+++ b/lib/impure/dialogs.nim
diff --git a/lib/base/web.nim b/lib/impure/web.nim
index 83d1406af..83d1406af 100644
--- a/lib/base/web.nim
+++ b/lib/impure/web.nim
diff --git a/lib/base/zip/zipfiles.nim b/lib/impure/zipfiles.nim
index e48b0f08e..e48b0f08e 100644
--- a/lib/base/zip/zipfiles.nim
+++ b/lib/impure/zipfiles.nim
diff --git a/lib/int64s.nim b/lib/int64s.nim
deleted file mode 100644
index 7a3dbad77..000000000
--- a/lib/int64s.nim
+++ /dev/null
@@ -1,71 +0,0 @@
-#
-#
-#            Nimrod's Runtime Library
-#        (c) Copyright 2006 Andreas Rumpf
-#
-#    See the file "copying.txt", included in this
-#    distribution, for details about the copyright.
-#
-
-# 64 bit integers for platforms that don't have those
-
-type
-  IInt64 = tuple[lo, hi: int32]
-
-proc cmpI64(x, y: IInt64): int32 {.compilerproc.} =
-  result = x.hi -% y.hi
-  if result == 0: result = x.lo -% y.lo
-
-proc addI64(x, y: IInt64): IInt64 {.compilerproc.} =
-  result = x
-  result.lo = result.lo +% y.lo
-  result.hi = result.hi +% y.hi
-  if y.lo > 0 and result.lo < y.lo:
-    inc(result.hi)
-  elif y.lo < 0 and result.lo > y.lo:
-    dec(result.hi)
-
-proc subI64(x, y: IInt64): IInt64 {.compilerproc.} =
-  result = x
-  result.lo = result.lo -% y.lo
-  result.hi = result.hi -% y.hi
-  if y.lo > 0 and result.lo < y.lo:
-    inc(result.hi)
-  elif y.lo < 0 and result.lo > y.lo:
-    dec(result.hi)
-
-proc mulI64(x, y: IInt64): IInt64 {.compilerproc.} =
-  result.lo = x.lo *% y.lo
-  result.hi = y.hi *% y.hi
-  if y.lo > 0 and result.lo < y.lo:
-    inc(result.hi)
-  elif y.lo < 0 and result.lo > y.lo:
-    dec(result.hi)
-
-proc divI64(x, y: IInt64): IInt64 {.compilerproc.} =
-  # XXX: to implement
-
-proc modI64(x, y: IInt64): IInt64 {.compilerproc.} =
-  # XXX: to implement
-
-proc bitandI64(x, y: IInt64): IInt64 {.compilerproc.} =
-  result.hi = x.hi and y.hi
-  result.lo = x.lo and y.lo
-
-proc bitorI64(x, y: IInt64): IInt64 {.compilerproc.} =
-  result.hi = x.hi or y.hi
-  result.lo = x.lo or y.lo
-
-proc bitxorI64(x, y: IInt64): IInt64 {.compilerproc.} =
-  result.hi = x.hi xor y.hi
-  result.lo = x.lo xor y.lo
-
-proc bitnotI64(x: IInt64): IInt64 {.compilerproc.} =
-  result.lo = not x.lo
-  result.hi = not x.hi
-
-proc shlI64(x, y: IInt64): IInt64 {.compilerproc.} =
-  # XXX: to implement
-
-proc shrI64(x, y: IInt64): IInt64 {.compilerproc.} =
-  # XXX: to implement
diff --git a/lib/locks.nim b/lib/locks.nim
deleted file mode 100644
index 89d26dfca..000000000
--- a/lib/locks.nim
+++ /dev/null
@@ -1,18 +0,0 @@
-#
-#
-#            Nimrod's Runtime Library
-#        (c) Copyright 2008 Andreas Rumpf
-#
-#    See the file "copying.txt", included in this
-#    distribution, for details about the copyright.
-#
-
-# Simple platform dependant lock implementation
-
-type
-  TSimpleLock = pointer
-
-proc initLock(s: TSimpleLock)
-proc deinitLock(s: TSimpleLock)
-proc lock(s: TSimpleLock)
-proc unlock(s: TSimpleLock)
diff --git a/lib/posix/detect.nim b/lib/posix/detect.nim
deleted file mode 100644
index d92269707..000000000
--- a/lib/posix/detect.nim
+++ /dev/null
@@ -1,824 +0,0 @@
-# Posix detect program
-# (c) 2009 Andreas Rumpf
-
-# This program produces a C program that produces a Nimrod include file.
-# The Nimrod include file lists the values of each POSIX constant.
-# This is needed because POSIX is brain-dead: It only cares for C, any other
-# language is ignored. It would have been easier had they specified the
-# concrete values of the constants. Sigh.
-
-import os, strutils
-
-const
-  cc = "gcc -o $1 $1.c"
-
-  cfile = """
-/* Generated by detect.nim */
-
-#include <stdlib.h>
-#include <stdio.h>
-$1
-
-int main() {
-  FILE* f;
-  f = fopen("$3_$4_consts.nim", "w+");
-  fputs("# Generated by detect.nim\nconst\n", f);
-  $2
-  fclose(f);
-}
-"""
-
-type
-  TTypeKind = enum 
-    cint, cshort, clong, cstring, pointer
-
-var
-  hd = ""
-  tl = ""
-
-proc myExec(cmd: string): bool = 
-  return executeShellCommand(cmd) == 0
-
-proc header(s: string): bool = 
-  const testh = "testh"
-  var f: TFile
-  if openFile(f, appendFileExt(testh, "c"), fmWrite):
-    f.write("#include $1\n" % s)
-    f.write("int main() { return 0; }\n")
-    closeFile(f)
-    result = myExec(cc % testh)
-    removeFile(appendFileExt(testh, "c"))
-  if result:
-    addf(hd, "#include $1\n", s)
-    echo("Found: ", s)
-  else:
-    echo("Not found: ", s)
-
-proc main = 
-  const gen = "genconsts"
-  var f: TFile
-  if openFile(f, appendFileExt(gen, "c"), fmWrite): 
-    f.write(cfile % [hd, tl, system.hostOS, system.hostCPU])
-    closeFile(f)
-  if not myExec(cc % gen): quit(1)
-  if not myExec("./" & gen): quit(1)
-  removeFile(appendFileExt(gen, "c"))
-  echo("Success")
-
-proc v(name: string, typ: TTypeKind=cint) = 
-  var n = if name[0] == '_': copy(name, 1) else: name
-  var t = $typ
-  case typ
-  of pointer: 
-    addf(tl, 
-      "#ifdef $3\n  fprintf(f, \"  $1* = cast[$2](%p)\\n\", $3);\n#endif\n", 
-      n, t, name)
-  
-  of cstring:
-    addf(tl, 
-      "#ifdef $3\n  fprintf(f, \"  $1* = $2(\\\"%s\\\")\\n\", $3);\n#endif\n",
-      n, t, name)
-  of clong:
-    addf(tl, 
-      "#ifdef $3\n  fprintf(f, \"  $1* = $2(%ld)\\n\", $3);\n#endif\n", 
-      n, t, name)  
-  else:  
-    addf(tl, 
-      "#ifdef $3\n  fprintf(f, \"  $1* = $2(%d)\\n\", $3);\n#endif\n", 
-      n, t, name)
-
-if header("<aio.h>"):
-  v("AIO_ALLDONE")
-  v("AIO_CANCELED")
-  v("AIO_NOTCANCELED")
-  v("LIO_NOP")
-  v("LIO_NOWAIT")
-  v("LIO_READ")
-  v("LIO_WAIT")
-  v("LIO_WRITE")
-
-if header("<dlfcn.h>"):
-  v("RTLD_LAZY")
-  v("RTLD_NOW")

-  v("RTLD_GLOBAL")

-  v("RTLD_LOCAL")

-
-if header("<errno.h>"):

-  v("E2BIG")

-  v("EACCES")

-  v("EADDRINUSE")

-  v("EADDRNOTAVAIL")

-  v("EAFNOSUPPORT")

-  v("EAGAIN")

-  v("EALREADY")

-  v("EBADF")

-  v("EBADMSG")

-  v("EBUSY")

-  v("ECANCELED")

-  v("ECHILD")

-  v("ECONNABORTED")

-  v("ECONNREFUSED")

-  v("ECONNRESET")

-  v("EDEADLK")

-  v("EDESTADDRREQ")

-  v("EDOM")

-  v("EDQUOT")

-  v("EEXIST")

-  v("EFAULT")

-  v("EFBIG")

-  v("EHOSTUNREACH")

-  v("EIDRM")

-  v("EILSEQ")

-  v("EINPROGRESS")

-  v("EINTR")

-  v("EINVAL")

-  v("EIO")

-  v("EISCONN")

-  v("EISDIR")

-  v("ELOOP")

-  v("EMFILE")

-  v("EMLINK")

-  v("EMSGSIZE")

-  v("EMULTIHOP")

-  v("ENAMETOOLONG")

-  v("ENETDOWN")

-  v("ENETRESET")

-  v("ENETUNREACH")

-  v("ENFILE")

-  v("ENOBUFS")

-  v("ENODATA")

-  v("ENODEV")

-  v("ENOENT")

-  v("ENOEXEC")

-  v("ENOLCK")

-  v("ENOLINK")

-  v("ENOMEM")

-  v("ENOMSG")

-  v("ENOPROTOOPT")

-  v("ENOSPC")

-  v("ENOSR")

-  v("ENOSTR")

-  v("ENOSYS")

-  v("ENOTCONN")

-  v("ENOTDIR")

-  v("ENOTEMPTY")

-  v("ENOTSOCK")

-  v("ENOTSUP")

-  v("ENOTTY")

-  v("ENXIO")

-  v("EOPNOTSUPP")

-  v("EOVERFLOW")

-  v("EPERM")

-  v("EPIPE")

-  v("EPROTO")

-  v("EPROTONOSUPPORT")

-  v("EPROTOTYPE")

-  v("ERANGE")

-  v("EROFS")

-  v("ESPIPE")

-  v("ESRCH")

-  v("ESTALE")

-  v("ETIME")

-  v("ETIMEDOUT")

-  v("ETXTBSY")

-  v("EWOULDBLOCK")

-  v("EXDEV")

-  
-if header("<fcntl.h>"):
-  v("F_DUPFD")

-  v("F_GETFD")

-  v("F_SETFD")

-  v("F_GETFL")

-  v("F_SETFL")

-  v("F_GETLK")

-  v("F_SETLK")

-  v("F_SETLKW")

-  v("F_GETOWN")

-  v("F_SETOWN")

-  v("FD_CLOEXEC")

-  v("F_RDLCK")

-  v("F_UNLCK")

-  v("F_WRLCK")

-  v("O_CREAT")

-  v("O_EXCL")

-  v("O_NOCTTY")

-  v("O_TRUNC")

-  v("O_APPEND")

-  v("O_DSYNC")

-  v("O_NONBLOCK")

-  v("O_RSYNC")

-  v("O_SYNC")

-  v("O_ACCMODE")

-  v("O_RDONLY")

-  v("O_RDWR")

-  v("O_WRONLY")

-  v("POSIX_FADV_NORMAL")

-  v("POSIX_FADV_SEQUENTIAL")

-  v("POSIX_FADV_RANDOM")

-  v("POSIX_FADV_WILLNEED")

-  v("POSIX_FADV_DONTNEED")

-  v("POSIX_FADV_NOREUSE")

-
-if header("<fenv.h>"):

-  v("FE_DIVBYZERO")

-  v("FE_INEXACT")

-  v("FE_INVALID")

-  v("FE_OVERFLOW")

-  v("FE_UNDERFLOW")

-  v("FE_ALL_EXCEPT")

-  v("FE_DOWNWARD")

-  v("FE_TONEAREST")

-  v("FE_TOWARDZERO")

-  v("FE_UPWARD")

-  v("FE_DFL_ENV", pointer)

-
-if header("<fmtmsg.h>"):

-  v("MM_HARD")

-  v("MM_SOFT")

-  v("MM_FIRM")

-  v("MM_APPL")

-  v("MM_UTIL")

-  v("MM_OPSYS")

-  v("MM_RECOVER")

-  v("MM_NRECOV")

-  v("MM_HALT")

-  v("MM_ERROR")

-  v("MM_WARNING")

-  v("MM_INFO")

-  v("MM_NOSEV")

-  v("MM_PRINT")

-  v("MM_CONSOLE")

-  v("MM_OK")

-  v("MM_NOTOK")

-  v("MM_NOMSG")

-  v("MM_NOCON")

-
-if header("<fnmatch.h>"):

-  v("FNM_NOMATCH")

-  v("FNM_PATHNAME")

-  v("FNM_PERIOD")

-  v("FNM_NOESCAPE")

-  v("FNM_NOSYS")

-
-if header("<ftw.h>"):

-  v("FTW_F")

-  v("FTW_D")

-  v("FTW_DNR")

-  v("FTW_DP")

-  v("FTW_NS")

-  v("FTW_SL")

-  v("FTW_SLN")

-  v("FTW_PHYS")

-  v("FTW_MOUNT")

-  v("FTW_DEPTH")

-  v("FTW_CHDIR")

-
-if header("<glob.h>"):
-  v("GLOB_APPEND")

-  v("GLOB_DOOFFS")

-  v("GLOB_ERR")

-  v("GLOB_MARK")

-  v("GLOB_NOCHECK")

-  v("GLOB_NOESCAPE")

-  v("GLOB_NOSORT")

-  v("GLOB_ABORTED")

-  v("GLOB_NOMATCH")

-  v("GLOB_NOSPACE")

-  v("GLOB_NOSYS")

-

-if header("<langinfo.h>"):
-  v("CODESET")

-  v("D_T_FMT")

-  v("D_FMT")

-  v("T_FMT")

-  v("T_FMT_AMPM")

-  v("AM_STR")

-  v("PM_STR")

-  v("DAY_1")

-  v("DAY_2")

-  v("DAY_3")

-  v("DAY_4")

-  v("DAY_5")

-  v("DAY_6")

-  v("DAY_7")

-  v("ABDAY_1")

-  v("ABDAY_2")

-  v("ABDAY_3")

-  v("ABDAY_4")

-  v("ABDAY_5")

-  v("ABDAY_6")

-  v("ABDAY_7")

-  v("MON_1")

-  v("MON_2")

-  v("MON_3")

-  v("MON_4")

-  v("MON_5")

-  v("MON_6")

-  v("MON_7")

-  v("MON_8")

-  v("MON_9")

-  v("MON_10")

-  v("MON_11")

-  v("MON_12")

-  v("ABMON_1")

-  v("ABMON_2")

-  v("ABMON_3")

-  v("ABMON_4")

-  v("ABMON_5")

-  v("ABMON_6")

-  v("ABMON_7")

-  v("ABMON_8")

-  v("ABMON_9")

-  v("ABMON_10")

-  v("ABMON_11")

-  v("ABMON_12")

-  v("ERA")

-  v("ERA_D_FMT")

-  v("ERA_D_T_FMT")

-  v("ERA_T_FMT")

-  v("ALT_DIGITS")

-  v("RADIXCHAR")

-  v("THOUSEP")

-  v("YESEXPR")

-  v("NOEXPR")

-  v("CRNCYSTR")

-    
-if header("<locale.h>"):

-  v("LC_ALL") #{.importc, header: .}: cint

-  v("LC_COLLATE") #{.importc, header: "<locale.h>".}: cint

-  v("LC_CTYPE") #{.importc, header: "<locale.h>".}: cint

-  v("LC_MESSAGES") #{.importc, header: "<locale.h>".}: cint

-  v("LC_MONETARY") #{.importc, header: "<locale.h>".}: cint

-  v("LC_NUMERIC") #{.importc, header: "<locale.h>".}: cint

-  v("LC_TIME") #{.importc, header: "<locale.h>".}: cint

-
-if header("<pthread.h>"):

-  v("PTHREAD_BARRIER_SERIAL_THREAD")

-  v("PTHREAD_CANCEL_ASYNCHRONOUS") 

-  v("PTHREAD_CANCEL_ENABLE") 

-  v("PTHREAD_CANCEL_DEFERRED")

-  v("PTHREAD_CANCEL_DISABLE") 

-  #v("PTHREAD_CANCELED")

-  #v("PTHREAD_COND_INITIALIZER") 

-  v("PTHREAD_CREATE_DETACHED")

-  v("PTHREAD_CREATE_JOINABLE")

-  v("PTHREAD_EXPLICIT_SCHED")

-  v("PTHREAD_INHERIT_SCHED") 

-  v("PTHREAD_MUTEX_DEFAULT") 

-  v("PTHREAD_MUTEX_ERRORCHECK")

-  #v("PTHREAD_MUTEX_INITIALIZER") 

-  v("PTHREAD_MUTEX_NORMAL") 

-  v("PTHREAD_MUTEX_RECURSIVE") #{.importc, header: "<pthread.h>".}: cint

-  v("PTHREAD_ONCE_INIT") #{.importc, header: "<pthread.h>".}: cint

-  v("PTHREAD_PRIO_INHERIT") #{.importc, header: "<pthread.h>".}: cint

-  v("PTHREAD_PRIO_NONE") #{.importc, header: "<pthread.h>".}: cint

-  v("PTHREAD_PRIO_PROTECT") #{.importc, header: "<pthread.h>".}: cint

-  v("PTHREAD_PROCESS_SHARED") #{.importc, header: "<pthread.h>".}: cint

-  v("PTHREAD_PROCESS_PRIVATE") #{.importc, header: "<pthread.h>".}: cint

-  v("PTHREAD_SCOPE_PROCESS") #{.importc, header: "<pthread.h>".}: cint

-  v("PTHREAD_SCOPE_SYSTEM") #{.importc, header: "<pthread.h>".}: cint

-
-if header("<unistd.h>"):

-  v("_POSIX_ASYNC_IO")

-  v("_POSIX_PRIO_IO")

-  v("_POSIX_SYNC_IO")

-  v("F_OK")

-  v("R_OK")

-  v("W_OK")

-  v("X_OK")

-

-  v("_CS_PATH")

-  v("_CS_POSIX_V6_ILP32_OFF32_CFLAGS") 

-  v("_CS_POSIX_V6_ILP32_OFF32_LDFLAGS") 

-  v("_CS_POSIX_V6_ILP32_OFF32_LIBS") 

-  v("_CS_POSIX_V6_ILP32_OFFBIG_CFLAGS") 

-  v("_CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS") 

-  v("_CS_POSIX_V6_ILP32_OFFBIG_LIBS") 

-  v("_CS_POSIX_V6_LP64_OFF64_CFLAGS") 

-  v("_CS_POSIX_V6_LP64_OFF64_LDFLAGS")

-  v("_CS_POSIX_V6_LP64_OFF64_LIBS") 

-  v("_CS_POSIX_V6_LPBIG_OFFBIG_CFLAGS") 

-  v("_CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGS") 

-  v("_CS_POSIX_V6_LPBIG_OFFBIG_LIBS") 

-  v("_CS_POSIX_V6_WIDTH_RESTRICTED_ENVS")
-
-  v("F_LOCK") 

-  v("F_TEST") #{.importc: "F_TEST", header: "<unistd.h>".}: cint

-  v("F_TLOCK") #{.importc: "F_TLOCK", header: "<unistd.h>".}: cint

-  v("F_ULOCK") #{.importc: "F_ULOCK", header: "<unistd.h>".}: cint

-  v("_PC_2_SYMLINKS") #{.importc: "_PC_2_SYMLINKS", header: "<unistd.h>".}: cint

-  v("_PC_ALLOC_SIZE_MIN") 

-  v("_PC_ASYNC_IO") #{.importc: "_PC_ASYNC_IO", header: "<unistd.h>".}: cint

-  v("_PC_CHOWN_RESTRICTED") 

-  v("_PC_FILESIZEBITS") #{.importc: "_PC_FILESIZEBITS", header: "<unistd.h>".}: cint

-  v("_PC_LINK_MAX") #{.importc: "_PC_LINK_MAX", header: "<unistd.h>".}: cint

-  v("_PC_MAX_CANON") #{.importc: "_PC_MAX_CANON", header: "<unistd.h>".}: cint

-  v("_PC_MAX_INPUT") #{.importc: "_PC_MAX_INPUT", header: "<unistd.h>".}: cint

-  v("_PC_NAME_MAX") #{.importc: "_PC_NAME_MAX", header: "<unistd.h>".}: cint

-  v("_PC_NO_TRUNC") #{.importc: "_PC_NO_TRUNC", header: "<unistd.h>".}: cint

-  v("_PC_PATH_MAX") #{.importc: "_PC_PATH_MAX", header: "<unistd.h>".}: cint

-  v("_PC_PIPE_BUF") #{.importc: "_PC_PIPE_BUF", header: "<unistd.h>".}: cint

-  v("_PC_PRIO_IO") #{.importc: "_PC_PRIO_IO", header: "<unistd.h>".}: cint

-  v("_PC_REC_INCR_XFER_SIZE") 

-  v("_PC_REC_MIN_XFER_SIZE") 

-  v("_PC_REC_XFER_ALIGN") 

-  v("_PC_SYMLINK_MAX") #{.importc: "_PC_SYMLINK_MAX", header: "<unistd.h>".}: cint

-  v("_PC_SYNC_IO") #{.importc: "_PC_SYNC_IO", header: "<unistd.h>".}: cint

-  v("_PC_VDISABLE") #{.importc: "_PC_VDISABLE", header: "<unistd.h>".}: cint

-  v("_SC_2_C_BIND") #{.importc: "_SC_2_C_BIND", header: "<unistd.h>".}: cint

-  v("_SC_2_C_DEV") #{.importc: "_SC_2_C_DEV", header: "<unistd.h>".}: cint

-  v("_SC_2_CHAR_TERM") #{.importc: "_SC_2_CHAR_TERM", header: "<unistd.h>".}: cint

-  v("_SC_2_FORT_DEV") #{.importc: "_SC_2_FORT_DEV", header: "<unistd.h>".}: cint

-  v("_SC_2_FORT_RUN") #{.importc: "_SC_2_FORT_RUN", header: "<unistd.h>".}: cint

-  v("_SC_2_LOCALEDEF") #{.importc: "_SC_2_LOCALEDEF", header: "<unistd.h>".}: cint

-  v("_SC_2_PBS") #{.importc: "_SC_2_PBS", header: "<unistd.h>".}: cint

-  v("_SC_2_PBS_ACCOUNTING") 

-  v("_SC_2_PBS_CHECKPOINT") 

-  v("_SC_2_PBS_LOCATE") #{.importc: "_SC_2_PBS_LOCATE", header: "<unistd.h>".}: cint

-  v("_SC_2_PBS_MESSAGE") #{.importc: "_SC_2_PBS_MESSAGE", header: "<unistd.h>".}: cint

-  v("_SC_2_PBS_TRACK") #{.importc: "_SC_2_PBS_TRACK", header: "<unistd.h>".}: cint

-  v("_SC_2_SW_DEV") #{.importc: "_SC_2_SW_DEV", header: "<unistd.h>".}: cint

-  v("_SC_2_UPE") #{.importc: "_SC_2_UPE", header: "<unistd.h>".}: cint

-  v("_SC_2_VERSION") #{.importc: "_SC_2_VERSION", header: "<unistd.h>".}: cint

-  v("_SC_ADVISORY_INFO") #{.importc: "_SC_ADVISORY_INFO", header: "<unistd.h>".}: cint

-  v("_SC_AIO_LISTIO_MAX") 

-  v("_SC_AIO_MAX") #{.importc: "_SC_AIO_MAX", header: "<unistd.h>".}: cint

-  v("_SC_AIO_PRIO_DELTA_MAX") 

-  v("_SC_ARG_MAX") #{.importc: "_SC_ARG_MAX", header: "<unistd.h>".}: cint

-  v("_SC_ASYNCHRONOUS_IO") 

-  v("_SC_ATEXIT_MAX") #{.importc: "_SC_ATEXIT_MAX", header: "<unistd.h>".}: cint

-  v("_SC_BARRIERS") #{.importc: "_SC_BARRIERS", header: "<unistd.h>".}: cint

-  v("_SC_BC_BASE_MAX") #{.importc: "_SC_BC_BASE_MAX", header: "<unistd.h>".}: cint

-  v("_SC_BC_DIM_MAX") #{.importc: "_SC_BC_DIM_MAX", header: "<unistd.h>".}: cint

-  v("_SC_BC_SCALE_MAX") #{.importc: "_SC_BC_SCALE_MAX", header: "<unistd.h>".}: cint

-  v("_SC_BC_STRING_MAX") #{.importc: "_SC_BC_STRING_MAX", header: "<unistd.h>".}: cint

-  v("_SC_CHILD_MAX") #{.importc: "_SC_CHILD_MAX", header: "<unistd.h>".}: cint

-  v("_SC_CLK_TCK") #{.importc: "_SC_CLK_TCK", header: "<unistd.h>".}: cint

-  v("_SC_CLOCK_SELECTION") 

-  v("_SC_COLL_WEIGHTS_MAX")

-  v("_SC_CPUTIME") #{.importc: "_SC_CPUTIME", header: "<unistd.h>".}: cint

-  v("_SC_DELAYTIMER_MAX") 

-  v("_SC_EXPR_NEST_MAX") #{.importc: "_SC_EXPR_NEST_MAX", header: "<unistd.h>".}: cint

-  v("_SC_FSYNC") #{.importc: "_SC_FSYNC", header: "<unistd.h>".}: cint

-  v("_SC_GETGR_R_SIZE_MAX")

-  v("_SC_GETPW_R_SIZE_MAX")

-  v("_SC_HOST_NAME_MAX") #{.importc: "_SC_HOST_NAME_MAX", header: "<unistd.h>".}: cint

-  v("_SC_IOV_MAX") #{.importc: "_SC_IOV_MAX", header: "<unistd.h>".}: cint

-  v("_SC_IPV6") #{.importc: "_SC_IPV6", header: "<unistd.h>".}: cint

-  v("_SC_JOB_CONTROL") #{.importc: "_SC_JOB_CONTROL", header: "<unistd.h>".}: cint

-  v("_SC_LINE_MAX") #{.importc: "_SC_LINE_MAX", header: "<unistd.h>".}: cint

-  v("_SC_LOGIN_NAME_MAX") 

-  v("_SC_MAPPED_FILES") #{.importc: "_SC_MAPPED_FILES", header: "<unistd.h>".}: cint

-  v("_SC_MEMLOCK") #{.importc: "_SC_MEMLOCK", header: "<unistd.h>".}: cint

-  v("_SC_MEMLOCK_RANGE") #{.importc: "_SC_MEMLOCK_RANGE", header: "<unistd.h>".}: cint

-  v("_SC_MEMORY_PROTECTION")

-  v("_SC_MESSAGE_PASSING") 

-  v("_SC_MONOTONIC_CLOCK") 

-  v("_SC_MQ_OPEN_MAX") #{.importc: "_SC_MQ_OPEN_MAX", header: "<unistd.h>".}: cint

-  v("_SC_MQ_PRIO_MAX") #{.importc: "_SC_MQ_PRIO_MAX", header: "<unistd.h>".}: cint

-  v("_SC_NGROUPS_MAX") #{.importc: "_SC_NGROUPS_MAX", header: "<unistd.h>".}: cint

-  v("_SC_OPEN_MAX") #{.importc: "_SC_OPEN_MAX", header: "<unistd.h>".}: cint

-  v("_SC_PAGE_SIZE") #{.importc: "_SC_PAGE_SIZE", header: "<unistd.h>".}: cint

-  v("_SC_PRIORITIZED_IO") 

-  v("_SC_PRIORITY_SCHEDULING") 

-  v("_SC_RAW_SOCKETS") #{.importc: "_SC_RAW_SOCKETS", header: "<unistd.h>".}: cint

-  v("_SC_RE_DUP_MAX") #{.importc: "_SC_RE_DUP_MAX", header: "<unistd.h>".}: cint

-  v("_SC_READER_WRITER_LOCKS") 

-  v("_SC_REALTIME_SIGNALS") 

-  v("_SC_REGEXP") #{.importc: "_SC_REGEXP", header: "<unistd.h>".}: cint

-  v("_SC_RTSIG_MAX") #{.importc: "_SC_RTSIG_MAX", header: "<unistd.h>".}: cint

-  v("_SC_SAVED_IDS") #{.importc: "_SC_SAVED_IDS", header: "<unistd.h>".}: cint

-  v("_SC_SEM_NSEMS_MAX") #{.importc: "_SC_SEM_NSEMS_MAX", header: "<unistd.h>".}: cint

-  v("_SC_SEM_VALUE_MAX") #{.importc: "_SC_SEM_VALUE_MAX", header: "<unistd.h>".}: cint

-  v("_SC_SEMAPHORES") #{.importc: "_SC_SEMAPHORES", header: "<unistd.h>".}: cint

-  v("_SC_SHARED_MEMORY_OBJECTS") 

-  v("_SC_SHELL") #{.importc: "_SC_SHELL", header: "<unistd.h>".}: cint

-  v("_SC_SIGQUEUE_MAX") #{.importc: "_SC_SIGQUEUE_MAX", header: "<unistd.h>".}: cint

-  v("_SC_SPAWN") #{.importc: "_SC_SPAWN", header: "<unistd.h>".}: cint

-  v("_SC_SPIN_LOCKS") #{.importc: "_SC_SPIN_LOCKS", header: "<unistd.h>".}: cint

-  v("_SC_SPORADIC_SERVER") 

-  v("_SC_SS_REPL_MAX") #{.importc: "_SC_SS_REPL_MAX", header: "<unistd.h>".}: cint

-  v("_SC_STREAM_MAX") #{.importc: "_SC_STREAM_MAX", header: "<unistd.h>".}: cint

-  v("_SC_SYMLOOP_MAX") #{.importc: "_SC_SYMLOOP_MAX", header: "<unistd.h>".}: cint

-  v("_SC_SYNCHRONIZED_IO") 

-  v("_SC_THREAD_ATTR_STACKADDR") 

-  v("_SC_THREAD_ATTR_STACKSIZE") 

-  v("_SC_THREAD_CPUTIME") 

-  v("_SC_THREAD_DESTRUCTOR_ITERATIONS") 

-  v("_SC_THREAD_KEYS_MAX") 

-  v("_SC_THREAD_PRIO_INHERIT") 

-  v("_SC_THREAD_PRIO_PROTECT") 

-  v("_SC_THREAD_PRIORITY_SCHEDULING") 

-  v("_SC_THREAD_PROCESS_SHARED") 

-  v("_SC_THREAD_SAFE_FUNCTIONS") 

-  v("_SC_THREAD_SPORADIC_SERVER")

-  v("_SC_THREAD_STACK_MIN") 

-  v("_SC_THREAD_THREADS_MAX") 

-  v("_SC_THREADS") #{.importc: "_SC_THREADS", header: "<unistd.h>".}: cint

-  v("_SC_TIMEOUTS") #{.importc: "_SC_TIMEOUTS", header: "<unistd.h>".}: cint

-  v("_SC_TIMER_MAX") #{.importc: "_SC_TIMER_MAX", header: "<unistd.h>".}: cint

-  v("_SC_TIMERS") #{.importc: "_SC_TIMERS", header: "<unistd.h>".}: cint

-  v("_SC_TRACE") #{.importc: "_SC_TRACE", header: "<unistd.h>".}: cint

-  v("_SC_TRACE_EVENT_FILTER") 

-  v("_SC_TRACE_EVENT_NAME_MAX")

-  v("_SC_TRACE_INHERIT") #{.importc: "_SC_TRACE_INHERIT", header: "<unistd.h>".}: cint

-  v("_SC_TRACE_LOG") #{.importc: "_SC_TRACE_LOG", header: "<unistd.h>".}: cint

-  v("_SC_TRACE_NAME_MAX") 

-  v("_SC_TRACE_SYS_MAX") #{.importc: "_SC_TRACE_SYS_MAX", header: "<unistd.h>".}: cint

-  v("_SC_TRACE_USER_EVENT_MAX") 

-  v("_SC_TTY_NAME_MAX") #{.importc: "_SC_TTY_NAME_MAX", header: "<unistd.h>".}: cint

-  v("_SC_TYPED_MEMORY_OBJECTS") 

-  v("_SC_TZNAME_MAX") #{.importc: "_SC_TZNAME_MAX", header: "<unistd.h>".}: cint

-  v("_SC_V6_ILP32_OFF32") 

-  v("_SC_V6_ILP32_OFFBIG") 

-  v("_SC_V6_LP64_OFF64") #{.importc: "_SC_V6_LP64_OFF64", header: "<unistd.h>".}: cint

-  v("_SC_V6_LPBIG_OFFBIG") 

-  v("_SC_VERSION") #{.importc: "_SC_VERSION", header: "<unistd.h>".}: cint

-  v("_SC_XBS5_ILP32_OFF32") 

-  v("_SC_XBS5_ILP32_OFFBIG") 

-  v("_SC_XBS5_LP64_OFF64") 

-  v("_SC_XBS5_LPBIG_OFFBIG") 

-  v("_SC_XOPEN_CRYPT") #{.importc: "_SC_XOPEN_CRYPT", header: "<unistd.h>".}: cint

-  v("_SC_XOPEN_ENH_I18N") 

-  v("_SC_XOPEN_LEGACY") #{.importc: "_SC_XOPEN_LEGACY", header: "<unistd.h>".}: cint

-  v("_SC_XOPEN_REALTIME") 

-  v("_SC_XOPEN_REALTIME_THREADS") 

-  v("_SC_XOPEN_SHM") #{.importc: "_SC_XOPEN_SHM", header: "<unistd.h>".}: cint

-  v("_SC_XOPEN_STREAMS") #{.importc: "_SC_XOPEN_STREAMS", header: "<unistd.h>".}: cint

-  v("_SC_XOPEN_UNIX") #{.importc: "_SC_XOPEN_UNIX", header: "<unistd.h>".}: cint

-  v("_SC_XOPEN_VERSION") #{.importc: "_SC_XOPEN_VERSION", header: "<unistd.h>".}: cint

-
-  v("SEEK_SET") #{.importc, header: "<unistd.h>".}: cint

-  v("SEEK_CUR") #{.importc, header: "<unistd.h>".}: cint

-  v("SEEK_END") #{.importc, header: "<unistd.h>".}: cint

-
-
-if header("<semaphore.h>"):

-  v("SEM_FAILED", pointer)
-
-if header("<sys/ipc.h>"):

-  v("IPC_CREAT") #{.importc, header: .}: cint

-  v("IPC_EXCL") #{.importc, header: "<sys/ipc.h>".}: cint

-  v("IPC_NOWAIT") #{.importc, header: "<sys/ipc.h>".}: cint

-  v("IPC_PRIVATE") #{.importc, header: "<sys/ipc.h>".}: cint

-  v("IPC_RMID") #{.importc, header: "<sys/ipc.h>".}: cint

-  v("IPC_SET") #{.importc, header: "<sys/ipc.h>".}: cint

-  v("IPC_STAT") #{.importc, header: "<sys/ipc.h>".}: cint
-
-if header("<sys/stat.h>"):

-  v("S_IFMT") #{.importc, header: .}: cint

-  v("S_IFBLK") #{.importc, header: "<sys/stat.h>".}: cint

-  v("S_IFCHR") #{.importc, header: "<sys/stat.h>".}: cint

-  v("S_IFIFO") #{.importc, header: "<sys/stat.h>".}: cint

-  v("S_IFREG") #{.importc, header: "<sys/stat.h>".}: cint

-  v("S_IFDIR") #{.importc, header: "<sys/stat.h>".}: cint

-  v("S_IFLNK") #{.importc, header: "<sys/stat.h>".}: cint

-  v("S_IFSOCK") #{.importc, header: "<sys/stat.h>".}: cint

-  v("S_IRWXU") #{.importc, header: "<sys/stat.h>".}: cint

-  v("S_IRUSR") #{.importc, header: "<sys/stat.h>".}: cint

-  v("S_IWUSR") #{.importc, header: "<sys/stat.h>".}: cint

-  v("S_IXUSR") #{.importc, header: "<sys/stat.h>".}: cint

-  v("S_IRWXG") #{.importc, header: "<sys/stat.h>".}: cint

-  v("S_IRGRP") #{.importc, header: "<sys/stat.h>".}: cint

-  v("S_IWGRP") #{.importc, header: "<sys/stat.h>".}: cint

-  v("S_IXGRP") #{.importc, header: "<sys/stat.h>".}: cint

-  v("S_IRWXO") #{.importc, header: "<sys/stat.h>".}: cint

-  v("S_IROTH") #{.importc, header: "<sys/stat.h>".}: cint

-  v("S_IWOTH") #{.importc, header: "<sys/stat.h>".}: cint

-  v("S_IXOTH") #{.importc, header: "<sys/stat.h>".}: cint

-  v("S_ISUID") #{.importc, header: "<sys/stat.h>".}: cint

-  v("S_ISGID") #{.importc, header: "<sys/stat.h>".}: cint

-  v("S_ISVTX") #{.importc, header: "<sys/stat.h>".}: cint

-
-if header("<sys/statvfs.h>"):

-  v("ST_RDONLY") #{.importc, header: .}: cint

-  v("ST_NOSUID") #{.importc, header: "<sys/statvfs.h>".}: cint

-       
-if header("<sys/mman.h>"):

-  v("PROT_READ") #{.importc, header: .}: cint

-  v("PROT_WRITE") #{.importc, header: "<sys/mman.h>".}: cint

-  v("PROT_EXEC") #{.importc, header: "<sys/mman.h>".}: cint

-  v("PROT_NONE") #{.importc, header: "<sys/mman.h>".}: cint

-  v("MAP_SHARED") #{.importc, header: "<sys/mman.h>".}: cint

-  v("MAP_PRIVATE") #{.importc, header: "<sys/mman.h>".}: cint

-  v("MAP_FIXED") #{.importc, header: "<sys/mman.h>".}: cint

-  v("MS_ASYNC") #{.importc, header: "<sys/mman.h>".}: cint

-  v("MS_SYNC") #{.importc, header: "<sys/mman.h>".}: cint

-  v("MS_INVALIDATE") #{.importc, header: "<sys/mman.h>".}: cint

-  v("MCL_CURRENT") #{.importc, header: "<sys/mman.h>".}: cint

-  v("MCL_FUTURE") #{.importc, header: "<sys/mman.h>".}: cint

-
-  v("MAP_FAILED", pointer)

-  v("POSIX_MADV_NORMAL") #{.importc, header: "<sys/mman.h>".}: cint

-  v("POSIX_MADV_SEQUENTIAL") #{.importc, header: "<sys/mman.h>".}: cint

-  v("POSIX_MADV_RANDOM") #{.importc, header: "<sys/mman.h>".}: cint

-  v("POSIX_MADV_WILLNEED") #{.importc, header: "<sys/mman.h>".}: cint

-  v("POSIX_MADV_DONTNEED") #{.importc, header: "<sys/mman.h>".}: cint

-  v("POSIX_TYPED_MEM_ALLOCATE") #{.importc, header: "<sys/mman.h>".}: cint

-  v("POSIX_TYPED_MEM_ALLOCATE_CONTIG") #{.importc, header: "<sys/mman.h>".}: cint

-  v("POSIX_TYPED_MEM_MAP_ALLOCATABLE") #{.importc, header: "<sys/mman.h>".}: cint

-

-if header("<time.h>"):

-  v("CLOCKS_PER_SEC", clong) 

-  v("CLOCK_PROCESS_CPUTIME_ID")

-  v("CLOCK_THREAD_CPUTIME_ID")

-  v("CLOCK_REALTIME")

-  v("TIMER_ABSTIME") 

-  v("CLOCK_MONOTONIC") 

-
-if header("<sys/wait.h>"):

-  v("WNOHANG") #{.importc, header: .}: cint

-  v("WUNTRACED") #{.importc, header: "<sys/wait.h>".}: cint

-  #v("WEXITSTATUS") 

-  #v("WIFCONTINUED") 

-  #v("WIFEXITED") 

-  #v("WIFSIGNALED")

-  #v("WIFSTOPPED") 

-  #v("WSTOPSIG") 

-  #v("WTERMSIG") 

-  v("WEXITED") #{.importc, header: "<sys/wait.h>".}: cint

-  v("WSTOPPED") #{.importc, header: "<sys/wait.h>".}: cint

-  v("WCONTINUED") #{.importc, header: "<sys/wait.h>".}: cint

-  v("WNOWAIT") #{.importc, header: "<sys/wait.h>".}: cint

-  v("P_ALL") #{.importc, header: "<sys/wait.h>".}: cint 

-  v("P_PID") #{.importc, header: "<sys/wait.h>".}: cint 

-  v("P_PGID") #{.importc, header: "<sys/wait.h>".}: cint

-         
-if header("<signal.h>"):

-  v("SIGEV_NONE") #{.importc, header: "<signal.h>".}: cint

-  v("SIGEV_SIGNAL") #{.importc, header: "<signal.h>".}: cint

-  v("SIGEV_THREAD") #{.importc, header: "<signal.h>".}: cint

-  v("SIGABRT") #{.importc, header: "<signal.h>".}: cint

-  v("SIGALRM") #{.importc, header: "<signal.h>".}: cint

-  v("SIGBUS") #{.importc, header: "<signal.h>".}: cint

-  v("SIGCHLD") #{.importc, header: "<signal.h>".}: cint

-  v("SIGCONT") #{.importc, header: "<signal.h>".}: cint

-  v("SIGFPE") #{.importc, header: "<signal.h>".}: cint

-  v("SIGHUP") #{.importc, header: "<signal.h>".}: cint

-  v("SIGILL") #{.importc, header: "<signal.h>".}: cint

-  v("SIGINT") #{.importc, header: "<signal.h>".}: cint

-  v("SIGKILL") #{.importc, header: "<signal.h>".}: cint

-  v("SIGPIPE") #{.importc, header: "<signal.h>".}: cint

-  v("SIGQUIT") #{.importc, header: "<signal.h>".}: cint

-  v("SIGSEGV") #{.importc, header: "<signal.h>".}: cint

-  v("SIGSTOP") #{.importc, header: "<signal.h>".}: cint

-  v("SIGTERM") #{.importc, header: "<signal.h>".}: cint

-  v("SIGTSTP") #{.importc, header: "<signal.h>".}: cint

-  v("SIGTTIN") #{.importc, header: "<signal.h>".}: cint

-  v("SIGTTOU") #{.importc, header: "<signal.h>".}: cint

-  v("SIGUSR1") #{.importc, header: "<signal.h>".}: cint

-  v("SIGUSR2") #{.importc, header: "<signal.h>".}: cint

-  v("SIGPOLL") #{.importc, header: "<signal.h>".}: cint

-  v("SIGPROF") #{.importc, header: "<signal.h>".}: cint

-  v("SIGSYS") #{.importc, header: "<signal.h>".}: cint

-  v("SIGTRAP") #{.importc, header: "<signal.h>".}: cint

-  v("SIGURG") #{.importc, header: "<signal.h>".}: cint

-  v("SIGVTALRM") #{.importc, header: "<signal.h>".}: cint

-  v("SIGXCPU") #{.importc, header: "<signal.h>".}: cint

-  v("SIGXFSZ") #{.importc, header: "<signal.h>".}: cint

-  v("SA_NOCLDSTOP") #{.importc, header: "<signal.h>".}: cint

-  v("SIG_BLOCK") #{.importc, header: "<signal.h>".}: cint

-  v("SIG_UNBLOCK") #{.importc, header: "<signal.h>".}: cint

-  v("SIG_SETMASK") #{.importc, header: "<signal.h>".}: cint

-  v("SA_ONSTACK") #{.importc, header: "<signal.h>".}: cint

-  v("SA_RESETHAND") #{.importc, header: "<signal.h>".}: cint

-  v("SA_RESTART") #{.importc, header: "<signal.h>".}: cint

-  v("SA_SIGINFO") #{.importc, header: "<signal.h>".}: cint

-  v("SA_NOCLDWAIT") #{.importc, header: "<signal.h>".}: cint

-  v("SA_NODEFER") #{.importc, header: "<signal.h>".}: cint

-  v("SS_ONSTACK") #{.importc, header: "<signal.h>".}: cint

-  v("SS_DISABLE") #{.importc, header: "<signal.h>".}: cint

-  v("MINSIGSTKSZ") #{.importc, header: "<signal.h>".}: cint

-  v("SIGSTKSZ") #{.importc, header: "<signal.h>".}: cint

-
-if header("<nl_types.h>"):

-  v("NL_SETD") #{.importc, header: .}: cint

-  v("NL_CAT_LOCALE") #{.importc, header: "<nl_types.h>".}: cint

-
-if header("<sched.h>"):

-  v("SCHED_FIFO")

-  v("SCHED_RR")

-  v("SCHED_SPORADIC")

-  v("SCHED_OTHER")

-
-if header("<sys/select.h>"):
-  v("FD_SETSIZE")

-

-if header("<net/if.h>"):
-  v("IF_NAMESIZE")
-
-if header("<sys/socket.h>"):
-  v("SCM_RIGHTS") #{.importc, header: .}: cint
-  v("SOCK_DGRAM") #{.importc, header: "<sys/socket.h>".}: cint
-  v("SOCK_RAW") #{.importc, header: "<sys/socket.h>".}: cint
-  v("SOCK_SEQPACKET") #{.importc, header: "<sys/socket.h>".}: cint
-  v("SOCK_STREAM") #{.importc, header: "<sys/socket.h>".}: cint
-  v("SOL_SOCKET") #{.importc, header: "<sys/socket.h>".}: cint
-  v("SO_ACCEPTCONN") #{.importc, header: "<sys/socket.h>".}: cint
-  v("SO_BROADCAST") #{.importc, header: "<sys/socket.h>".}: cint
-  v("SO_DEBUG") #{.importc, header: "<sys/socket.h>".}: cint
-  v("SO_DONTROUTE") #{.importc, header: "<sys/socket.h>".}: cint
-  v("SO_ERROR") #{.importc, header: "<sys/socket.h>".}: cint
-  v("SO_KEEPALIVE") #{.importc, header: "<sys/socket.h>".}: cint
-  v("SO_LINGER") #{.importc, header: "<sys/socket.h>".}: cint
-  v("SO_OOBINLINE") #{.importc, header: "<sys/socket.h>".}: cint
-  v("SO_RCVBUF") #{.importc, header: "<sys/socket.h>".}: cint
-  v("SO_RCVLOWAT") #{.importc, header: "<sys/socket.h>".}: cint
-  v("SO_RCVTIMEO") #{.importc, header: "<sys/socket.h>".}: cint
-  v("SO_REUSEADDR") #{.importc, header: "<sys/socket.h>".}: cint
-  v("SO_SNDBUF") #{.importc, header: "<sys/socket.h>".}: cint
-  v("SO_SNDLOWAT") #{.importc, header: "<sys/socket.h>".}: cint
-  v("SO_SNDTIMEO") #{.importc, header: "<sys/socket.h>".}: cint
-  v("SO_TYPE") #{.importc, header: "<sys/socket.h>".}: cint
-  v("SOMAXCONN") #{.importc, header: "<sys/socket.h>".}: cint
-  v("MSG_CTRUNC") #{.importc, header: "<sys/socket.h>".}: cint
-  v("MSG_DONTROUTE") #{.importc, header: "<sys/socket.h>".}: cint
-  v("MSG_EOR") #{.importc, header: "<sys/socket.h>".}: cint
-  v("MSG_OOB") #{.importc, header: "<sys/socket.h>".}: cint
-  v("MSG_PEEK") #{.importc, header: "<sys/socket.h>".}: cint
-  v("MSG_TRUNC") #{.importc, header: "<sys/socket.h>".}: cint
-  v("MSG_WAITALL") #{.importc, header: "<sys/socket.h>".}: cint
-  v("AF_INET") #{.importc, header: "<sys/socket.h>".}: cint
-  v("AF_INET6") #{.importc, header: "<sys/socket.h>".}: cint
-  v("AF_UNIX") #{.importc, header: "<sys/socket.h>".}: cint
-  v("AF_UNSPEC") #{.importc, header: "<sys/socket.h>".}: cint
-  v("SHUT_RD") #{.importc, header: "<sys/socket.h>".}: cint
-  v("SHUT_RDWR") #{.importc, header: "<sys/socket.h>".}: cint
-  v("SHUT_WR") #{.importc, header: "<sys/socket.h>".}: cint
-
-if header("<netinet/in.h>"):
-  v("IPPROTO_IP") #{.importc, header: .}: cint
-  v("IPPROTO_IPV6") #{.importc, header: "<netinet/in.h>".}: cint
-  v("IPPROTO_ICMP") #{.importc, header: "<netinet/in.h>".}: cint
-  v("IPPROTO_RAW") #{.importc, header: "<netinet/in.h>".}: cint
-  v("IPPROTO_TCP") #{.importc, header: "<netinet/in.h>".}: cint
-  v("IPPROTO_UDP") #{.importc, header: "<netinet/in.h>".}: cint
-  v("INADDR_ANY") #{.importc, header: "<netinet/in.h>".}: TinAddrScalar
-  v("INADDR_BROADCAST") #{.importc, header: "<netinet/in.h>".}: TinAddrScalar
-  v("INET_ADDRSTRLEN") #{.importc, header: "<netinet/in.h>".}: cint
-
-  v("IPV6_JOIN_GROUP") #{.importc, header: "<netinet/in.h>".}: cint
-  v("IPV6_LEAVE_GROUP") #{.importc, header: "<netinet/in.h>".}: cint
-  v("IPV6_MULTICAST_HOPS") #{.importc, header: "<netinet/in.h>".}: cint
-  v("IPV6_MULTICAST_IF") #{.importc, header: "<netinet/in.h>".}: cint
-  v("IPV6_MULTICAST_LOOP") #{.importc, header: "<netinet/in.h>".}: cint
-  v("IPV6_UNICAST_HOPS") #{.importc, header: "<netinet/in.h>".}: cint
-  v("IPV6_V6ONLY") #{.importc, header: "<netinet/in.h>".}: cint
-
-  v("TCP_NODELAY") #{.importc, header: "<netinet/tcp.h>".}: cint
-
-if header("<netdb.h>"):
-  v("IPPORT_RESERVED")
-
-  v("HOST_NOT_FOUND")
-  v("NO_DATA")
-  v("NO_RECOVERY") 
-  v("TRY_AGAIN") 
-
-  v("AI_PASSIVE") 
-  v("AI_CANONNAME") 
-  v("AI_NUMERICHOST") 
-  v("AI_NUMERICSERV") 
-  v("AI_V4MAPPED") 
-  v("AI_ALL") 
-  v("AI_ADDRCONFIG") 
-
-  v("NI_NOFQDN") 
-  v("NI_NUMERICHOST") 
-  v("NI_NAMEREQD") 
-  v("NI_NUMERICSERV") 
-  v("NI_NUMERICSCOPE") 
-  v("NI_DGRAM") 
-  v("EAI_AGAIN")
-  v("EAI_BADFLAGS")
-  v("EAI_FAIL")
-  v("EAI_FAMILY")
-  v("EAI_MEMORY")
-  v("EAI_NONAME")
-  v("EAI_SERVICE")
-  v("EAI_SOCKTYPE")
-  v("EAI_SYSTEM")
-  v("EAI_OVERFLOW")
-
-if header("<poll.h>"):
-  v("POLLIN", cshort)
-  v("POLLRDNORM", cshort)
-  v("POLLRDBAND", cshort)
-  v("POLLPRI", cshort)
-  v("POLLOUT", cshort)
-  v("POLLWRNORM", cshort)
-  v("POLLWRBAND", cshort)
-  v("POLLERR", cshort)
-  v("POLLHUP", cshort)
-  v("POLLNVAL", cshort)
-
-if header("<spawn.h>"):
-  v("POSIX_SPAWN_RESETIDS")

-  v("POSIX_SPAWN_SETPGROUP")

-  v("POSIX_SPAWN_SETSCHEDPARAM")

-  v("POSIX_SPAWN_SETSCHEDULER")

-  v("POSIX_SPAWN_SETSIGDEF")

-  v("POSIX_SPAWN_SETSIGMASK")

-
-main()
-
diff --git a/lib/posix/linux_amd64_consts.nim b/lib/posix/linux_amd64_consts.nim
deleted file mode 100644
index 2fadcd83b..000000000
--- a/lib/posix/linux_amd64_consts.nim
+++ /dev/null
@@ -1,620 +0,0 @@
-# Generated by detect.nim
-const
-  AIO_ALLDONE* = cint(2)
-  AIO_CANCELED* = cint(0)
-  AIO_NOTCANCELED* = cint(1)
-  LIO_NOP* = cint(2)
-  LIO_NOWAIT* = cint(1)
-  LIO_READ* = cint(0)
-  LIO_WAIT* = cint(0)
-  LIO_WRITE* = cint(1)
-  RTLD_LAZY* = cint(1)
-  RTLD_NOW* = cint(2)
-  RTLD_GLOBAL* = cint(256)
-  RTLD_LOCAL* = cint(0)
-  E2BIG* = cint(7)
-  EACCES* = cint(13)
-  EADDRINUSE* = cint(98)
-  EADDRNOTAVAIL* = cint(99)
-  EAFNOSUPPORT* = cint(97)
-  EAGAIN* = cint(11)
-  EALREADY* = cint(114)
-  EBADF* = cint(9)
-  EBADMSG* = cint(74)
-  EBUSY* = cint(16)
-  ECANCELED* = cint(125)
-  ECHILD* = cint(10)
-  ECONNABORTED* = cint(103)
-  ECONNREFUSED* = cint(111)
-  ECONNRESET* = cint(104)
-  EDEADLK* = cint(35)
-  EDESTADDRREQ* = cint(89)
-  EDOM* = cint(33)
-  EDQUOT* = cint(122)
-  EEXIST* = cint(17)
-  EFAULT* = cint(14)
-  EFBIG* = cint(27)
-  EHOSTUNREACH* = cint(113)
-  EIDRM* = cint(43)
-  EILSEQ* = cint(84)
-  EINPROGRESS* = cint(115)
-  EINTR* = cint(4)
-  EINVAL* = cint(22)
-  EIO* = cint(5)
-  EISCONN* = cint(106)
-  EISDIR* = cint(21)
-  ELOOP* = cint(40)
-  EMFILE* = cint(24)
-  EMLINK* = cint(31)
-  EMSGSIZE* = cint(90)
-  EMULTIHOP* = cint(72)
-  ENAMETOOLONG* = cint(36)
-  ENETDOWN* = cint(100)
-  ENETRESET* = cint(102)
-  ENETUNREACH* = cint(101)
-  ENFILE* = cint(23)
-  ENOBUFS* = cint(105)
-  ENODATA* = cint(61)
-  ENODEV* = cint(19)
-  ENOENT* = cint(2)
-  ENOEXEC* = cint(8)
-  ENOLCK* = cint(37)
-  ENOLINK* = cint(67)
-  ENOMEM* = cint(12)
-  ENOMSG* = cint(42)
-  ENOPROTOOPT* = cint(92)
-  ENOSPC* = cint(28)
-  ENOSR* = cint(63)
-  ENOSTR* = cint(60)
-  ENOSYS* = cint(38)
-  ENOTCONN* = cint(107)
-  ENOTDIR* = cint(20)
-  ENOTEMPTY* = cint(39)
-  ENOTSOCK* = cint(88)
-  ENOTSUP* = cint(95)
-  ENOTTY* = cint(25)
-  ENXIO* = cint(6)
-  EOPNOTSUPP* = cint(95)
-  EOVERFLOW* = cint(75)
-  EPERM* = cint(1)
-  EPIPE* = cint(32)
-  EPROTO* = cint(71)
-  EPROTONOSUPPORT* = cint(93)
-  EPROTOTYPE* = cint(91)
-  ERANGE* = cint(34)
-  EROFS* = cint(30)
-  ESPIPE* = cint(29)
-  ESRCH* = cint(3)
-  ESTALE* = cint(116)
-  ETIME* = cint(62)
-  ETIMEDOUT* = cint(110)
-  ETXTBSY* = cint(26)
-  EWOULDBLOCK* = cint(11)
-  EXDEV* = cint(18)
-  F_DUPFD* = cint(0)
-  F_GETFD* = cint(1)
-  F_SETFD* = cint(2)
-  F_GETFL* = cint(3)
-  F_SETFL* = cint(4)
-  F_GETLK* = cint(5)
-  F_SETLK* = cint(6)
-  F_SETLKW* = cint(7)
-  F_GETOWN* = cint(9)
-  F_SETOWN* = cint(8)
-  FD_CLOEXEC* = cint(1)
-  F_RDLCK* = cint(0)
-  F_UNLCK* = cint(2)
-  F_WRLCK* = cint(1)
-  O_CREAT* = cint(64)
-  O_EXCL* = cint(128)
-  O_NOCTTY* = cint(256)
-  O_TRUNC* = cint(512)
-  O_APPEND* = cint(1024)
-  O_DSYNC* = cint(4096)
-  O_NONBLOCK* = cint(2048)
-  O_RSYNC* = cint(4096)
-  O_SYNC* = cint(4096)
-  O_ACCMODE* = cint(3)
-  O_RDONLY* = cint(0)
-  O_RDWR* = cint(2)
-  O_WRONLY* = cint(1)
-  POSIX_FADV_NORMAL* = cint(0)
-  POSIX_FADV_SEQUENTIAL* = cint(2)
-  POSIX_FADV_RANDOM* = cint(1)
-  POSIX_FADV_WILLNEED* = cint(3)
-  POSIX_FADV_DONTNEED* = cint(4)
-  POSIX_FADV_NOREUSE* = cint(5)
-  FE_DIVBYZERO* = cint(4)
-  FE_INEXACT* = cint(32)
-  FE_INVALID* = cint(1)
-  FE_OVERFLOW* = cint(8)
-  FE_UNDERFLOW* = cint(16)
-  FE_ALL_EXCEPT* = cint(61)
-  FE_DOWNWARD* = cint(1024)
-  FE_TONEAREST* = cint(0)
-  FE_TOWARDZERO* = cint(3072)
-  FE_UPWARD* = cint(2048)
-  FE_DFL_ENV* = cast[pointer](0xffffffffffffffff)
-  MM_HARD* = cint(1)
-  MM_SOFT* = cint(2)
-  MM_FIRM* = cint(4)
-  MM_APPL* = cint(8)
-  MM_UTIL* = cint(16)
-  MM_OPSYS* = cint(32)
-  MM_RECOVER* = cint(64)
-  MM_NRECOV* = cint(128)
-  MM_HALT* = cint(1)
-  MM_ERROR* = cint(2)
-  MM_WARNING* = cint(3)
-  MM_INFO* = cint(4)
-  MM_NOSEV* = cint(0)
-  MM_PRINT* = cint(256)
-  MM_CONSOLE* = cint(512)
-  MM_OK* = cint(0)
-  MM_NOTOK* = cint(-1)
-  MM_NOMSG* = cint(1)
-  MM_NOCON* = cint(4)
-  FNM_NOMATCH* = cint(1)
-  FNM_PATHNAME* = cint(1)
-  FNM_PERIOD* = cint(4)
-  FNM_NOESCAPE* = cint(2)
-  FTW_F* = cint(0)
-  FTW_D* = cint(1)
-  FTW_DNR* = cint(2)
-  FTW_NS* = cint(3)
-  FTW_SL* = cint(4)
-  GLOB_APPEND* = cint(32)
-  GLOB_DOOFFS* = cint(8)
-  GLOB_ERR* = cint(1)
-  GLOB_MARK* = cint(2)
-  GLOB_NOCHECK* = cint(16)
-  GLOB_NOESCAPE* = cint(64)
-  GLOB_NOSORT* = cint(4)
-  GLOB_ABORTED* = cint(2)
-  GLOB_NOMATCH* = cint(3)
-  GLOB_NOSPACE* = cint(1)
-  GLOB_NOSYS* = cint(4)
-  CODESET* = cint(14)
-  D_T_FMT* = cint(131112)
-  D_FMT* = cint(131113)
-  T_FMT* = cint(131114)
-  T_FMT_AMPM* = cint(131115)
-  AM_STR* = cint(131110)
-  PM_STR* = cint(131111)
-  DAY_1* = cint(131079)
-  DAY_2* = cint(131080)
-  DAY_3* = cint(131081)
-  DAY_4* = cint(131082)
-  DAY_5* = cint(131083)
-  DAY_6* = cint(131084)
-  DAY_7* = cint(131085)
-  ABDAY_1* = cint(131072)
-  ABDAY_2* = cint(131073)
-  ABDAY_3* = cint(131074)
-  ABDAY_4* = cint(131075)
-  ABDAY_5* = cint(131076)
-  ABDAY_6* = cint(131077)
-  ABDAY_7* = cint(131078)
-  MON_1* = cint(131098)
-  MON_2* = cint(131099)
-  MON_3* = cint(131100)
-  MON_4* = cint(131101)
-  MON_5* = cint(131102)
-  MON_6* = cint(131103)
-  MON_7* = cint(131104)
-  MON_8* = cint(131105)
-  MON_9* = cint(131106)
-  MON_10* = cint(131107)
-  MON_11* = cint(131108)
-  MON_12* = cint(131109)
-  ABMON_1* = cint(131086)
-  ABMON_2* = cint(131087)
-  ABMON_3* = cint(131088)
-  ABMON_4* = cint(131089)
-  ABMON_5* = cint(131090)
-  ABMON_6* = cint(131091)
-  ABMON_7* = cint(131092)
-  ABMON_8* = cint(131093)
-  ABMON_9* = cint(131094)
-  ABMON_10* = cint(131095)
-  ABMON_11* = cint(131096)
-  ABMON_12* = cint(131097)
-  ERA* = cint(131116)
-  ERA_D_FMT* = cint(131118)
-  ERA_D_T_FMT* = cint(131120)
-  ERA_T_FMT* = cint(131121)
-  ALT_DIGITS* = cint(131119)
-  RADIXCHAR* = cint(65536)
-  THOUSEP* = cint(65537)
-  YESEXPR* = cint(327680)
-  NOEXPR* = cint(327681)
-  CRNCYSTR* = cint(262159)
-  LC_ALL* = cint(6)
-  LC_COLLATE* = cint(3)
-  LC_CTYPE* = cint(0)
-  LC_MESSAGES* = cint(5)
-  LC_MONETARY* = cint(4)
-  LC_NUMERIC* = cint(1)
-  LC_TIME* = cint(2)
-  PTHREAD_BARRIER_SERIAL_THREAD* = cint(-1)
-  PTHREAD_CANCEL_ASYNCHRONOUS* = cint(1)
-  PTHREAD_CANCEL_ENABLE* = cint(0)
-  PTHREAD_CANCEL_DEFERRED* = cint(0)
-  PTHREAD_CANCEL_DISABLE* = cint(1)
-  PTHREAD_CREATE_DETACHED* = cint(1)
-  PTHREAD_CREATE_JOINABLE* = cint(0)
-  PTHREAD_EXPLICIT_SCHED* = cint(1)
-  PTHREAD_INHERIT_SCHED* = cint(0)
-  PTHREAD_ONCE_INIT* = cint(0)
-  PTHREAD_PROCESS_SHARED* = cint(1)
-  PTHREAD_PROCESS_PRIVATE* = cint(0)
-  PTHREAD_SCOPE_PROCESS* = cint(1)
-  PTHREAD_SCOPE_SYSTEM* = cint(0)
-  POSIX_ASYNC_IO* = cint(1)
-  F_OK* = cint(0)
-  R_OK* = cint(4)
-  W_OK* = cint(2)
-  X_OK* = cint(1)
-  CS_PATH* = cint(0)
-  CS_POSIX_V6_ILP32_OFF32_CFLAGS* = cint(1116)
-  CS_POSIX_V6_ILP32_OFF32_LDFLAGS* = cint(1117)
-  CS_POSIX_V6_ILP32_OFF32_LIBS* = cint(1118)
-  CS_POSIX_V6_ILP32_OFFBIG_CFLAGS* = cint(1120)
-  CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS* = cint(1121)
-  CS_POSIX_V6_ILP32_OFFBIG_LIBS* = cint(1122)
-  CS_POSIX_V6_LP64_OFF64_CFLAGS* = cint(1124)
-  CS_POSIX_V6_LP64_OFF64_LDFLAGS* = cint(1125)
-  CS_POSIX_V6_LP64_OFF64_LIBS* = cint(1126)
-  CS_POSIX_V6_LPBIG_OFFBIG_CFLAGS* = cint(1128)
-  CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGS* = cint(1129)
-  CS_POSIX_V6_LPBIG_OFFBIG_LIBS* = cint(1130)
-  CS_POSIX_V6_WIDTH_RESTRICTED_ENVS* = cint(1)
-  F_LOCK* = cint(1)
-  F_TEST* = cint(3)
-  F_TLOCK* = cint(2)
-  F_ULOCK* = cint(0)
-  PC_2_SYMLINKS* = cint(20)
-  PC_ALLOC_SIZE_MIN* = cint(18)
-  PC_ASYNC_IO* = cint(10)
-  PC_CHOWN_RESTRICTED* = cint(6)
-  PC_FILESIZEBITS* = cint(13)
-  PC_LINK_MAX* = cint(0)
-  PC_MAX_CANON* = cint(1)
-  PC_MAX_INPUT* = cint(2)
-  PC_NAME_MAX* = cint(3)
-  PC_NO_TRUNC* = cint(7)
-  PC_PATH_MAX* = cint(4)
-  PC_PIPE_BUF* = cint(5)
-  PC_PRIO_IO* = cint(11)
-  PC_REC_INCR_XFER_SIZE* = cint(14)
-  PC_REC_MIN_XFER_SIZE* = cint(16)
-  PC_REC_XFER_ALIGN* = cint(17)
-  PC_SYMLINK_MAX* = cint(19)
-  PC_SYNC_IO* = cint(9)
-  PC_VDISABLE* = cint(8)
-  SC_2_C_BIND* = cint(47)
-  SC_2_C_DEV* = cint(48)
-  SC_2_CHAR_TERM* = cint(95)
-  SC_2_FORT_DEV* = cint(49)
-  SC_2_FORT_RUN* = cint(50)
-  SC_2_LOCALEDEF* = cint(52)
-  SC_2_PBS* = cint(168)
-  SC_2_PBS_ACCOUNTING* = cint(169)
-  SC_2_PBS_CHECKPOINT* = cint(175)
-  SC_2_PBS_LOCATE* = cint(170)
-  SC_2_PBS_MESSAGE* = cint(171)
-  SC_2_PBS_TRACK* = cint(172)
-  SC_2_SW_DEV* = cint(51)
-  SC_2_UPE* = cint(97)
-  SC_2_VERSION* = cint(46)
-  SC_ADVISORY_INFO* = cint(132)
-  SC_AIO_LISTIO_MAX* = cint(23)
-  SC_AIO_MAX* = cint(24)
-  SC_AIO_PRIO_DELTA_MAX* = cint(25)
-  SC_ARG_MAX* = cint(0)
-  SC_ASYNCHRONOUS_IO* = cint(12)
-  SC_ATEXIT_MAX* = cint(87)
-  SC_BARRIERS* = cint(133)
-  SC_BC_BASE_MAX* = cint(36)
-  SC_BC_DIM_MAX* = cint(37)
-  SC_BC_SCALE_MAX* = cint(38)
-  SC_BC_STRING_MAX* = cint(39)
-  SC_CHILD_MAX* = cint(1)
-  SC_CLK_TCK* = cint(2)
-  SC_CLOCK_SELECTION* = cint(137)
-  SC_COLL_WEIGHTS_MAX* = cint(40)
-  SC_CPUTIME* = cint(138)
-  SC_DELAYTIMER_MAX* = cint(26)
-  SC_EXPR_NEST_MAX* = cint(42)
-  SC_FSYNC* = cint(15)
-  SC_GETGR_R_SIZE_MAX* = cint(69)
-  SC_GETPW_R_SIZE_MAX* = cint(70)
-  SC_HOST_NAME_MAX* = cint(180)
-  SC_IOV_MAX* = cint(60)
-  SC_IPV6* = cint(235)
-  SC_JOB_CONTROL* = cint(7)
-  SC_LINE_MAX* = cint(43)
-  SC_LOGIN_NAME_MAX* = cint(71)
-  SC_MAPPED_FILES* = cint(16)
-  SC_MEMLOCK* = cint(17)
-  SC_MEMLOCK_RANGE* = cint(18)
-  SC_MEMORY_PROTECTION* = cint(19)
-  SC_MESSAGE_PASSING* = cint(20)
-  SC_MONOTONIC_CLOCK* = cint(149)
-  SC_MQ_OPEN_MAX* = cint(27)
-  SC_MQ_PRIO_MAX* = cint(28)
-  SC_NGROUPS_MAX* = cint(3)
-  SC_OPEN_MAX* = cint(4)
-  SC_PAGE_SIZE* = cint(30)
-  SC_PRIORITIZED_IO* = cint(13)
-  SC_PRIORITY_SCHEDULING* = cint(10)
-  SC_RAW_SOCKETS* = cint(236)
-  SC_RE_DUP_MAX* = cint(44)
-  SC_READER_WRITER_LOCKS* = cint(153)
-  SC_REALTIME_SIGNALS* = cint(9)
-  SC_REGEXP* = cint(155)
-  SC_RTSIG_MAX* = cint(31)
-  SC_SAVED_IDS* = cint(8)
-  SC_SEM_NSEMS_MAX* = cint(32)
-  SC_SEM_VALUE_MAX* = cint(33)
-  SC_SEMAPHORES* = cint(21)
-  SC_SHARED_MEMORY_OBJECTS* = cint(22)
-  SC_SHELL* = cint(157)
-  SC_SIGQUEUE_MAX* = cint(34)
-  SC_SPAWN* = cint(159)
-  SC_SPIN_LOCKS* = cint(154)
-  SC_SPORADIC_SERVER* = cint(160)
-  SC_STREAM_MAX* = cint(5)
-  SC_SYMLOOP_MAX* = cint(173)
-  SC_SYNCHRONIZED_IO* = cint(14)
-  SC_THREAD_ATTR_STACKADDR* = cint(77)
-  SC_THREAD_ATTR_STACKSIZE* = cint(78)
-  SC_THREAD_CPUTIME* = cint(139)
-  SC_THREAD_DESTRUCTOR_ITERATIONS* = cint(73)
-  SC_THREAD_KEYS_MAX* = cint(74)
-  SC_THREAD_PRIO_INHERIT* = cint(80)
-  SC_THREAD_PRIO_PROTECT* = cint(81)
-  SC_THREAD_PRIORITY_SCHEDULING* = cint(79)
-  SC_THREAD_PROCESS_SHARED* = cint(82)
-  SC_THREAD_SAFE_FUNCTIONS* = cint(68)
-  SC_THREAD_SPORADIC_SERVER* = cint(161)
-  SC_THREAD_STACK_MIN* = cint(75)
-  SC_THREAD_THREADS_MAX* = cint(76)
-  SC_THREADS* = cint(67)
-  SC_TIMEOUTS* = cint(164)
-  SC_TIMER_MAX* = cint(35)
-  SC_TIMERS* = cint(11)
-  SC_TRACE* = cint(181)
-  SC_TRACE_EVENT_FILTER* = cint(182)
-  SC_TRACE_INHERIT* = cint(183)
-  SC_TRACE_LOG* = cint(184)
-  SC_TTY_NAME_MAX* = cint(72)
-  SC_TYPED_MEMORY_OBJECTS* = cint(165)
-  SC_TZNAME_MAX* = cint(6)
-  SC_V6_ILP32_OFF32* = cint(176)
-  SC_V6_ILP32_OFFBIG* = cint(177)
-  SC_V6_LP64_OFF64* = cint(178)
-  SC_V6_LPBIG_OFFBIG* = cint(179)
-  SC_VERSION* = cint(29)
-  SC_XBS5_ILP32_OFF32* = cint(125)
-  SC_XBS5_ILP32_OFFBIG* = cint(126)
-  SC_XBS5_LP64_OFF64* = cint(127)
-  SC_XBS5_LPBIG_OFFBIG* = cint(128)
-  SC_XOPEN_CRYPT* = cint(92)
-  SC_XOPEN_ENH_I18N* = cint(93)
-  SC_XOPEN_LEGACY* = cint(129)
-  SC_XOPEN_REALTIME* = cint(130)
-  SC_XOPEN_REALTIME_THREADS* = cint(131)
-  SC_XOPEN_SHM* = cint(94)
-  SC_XOPEN_UNIX* = cint(91)
-  SC_XOPEN_VERSION* = cint(89)
-  SEEK_SET* = cint(0)
-  SEEK_CUR* = cint(1)
-  SEEK_END* = cint(2)
-  SEM_FAILED* = cast[pointer]((nil))
-  IPC_CREAT* = cint(512)
-  IPC_EXCL* = cint(1024)
-  IPC_NOWAIT* = cint(2048)
-  IPC_PRIVATE* = cint(0)
-  IPC_RMID* = cint(0)
-  IPC_SET* = cint(1)
-  IPC_STAT* = cint(2)
-  S_IFMT* = cint(61440)
-  S_IFBLK* = cint(24576)
-  S_IFCHR* = cint(8192)
-  S_IFIFO* = cint(4096)
-  S_IFREG* = cint(32768)
-  S_IFDIR* = cint(16384)
-  S_IFLNK* = cint(40960)
-  S_IFSOCK* = cint(49152)
-  S_IRWXU* = cint(448)
-  S_IRUSR* = cint(256)
-  S_IWUSR* = cint(128)
-  S_IXUSR* = cint(64)
-  S_IRWXG* = cint(56)
-  S_IRGRP* = cint(32)
-  S_IWGRP* = cint(16)
-  S_IXGRP* = cint(8)
-  S_IRWXO* = cint(7)
-  S_IROTH* = cint(4)
-  S_IWOTH* = cint(2)
-  S_IXOTH* = cint(1)
-  S_ISUID* = cint(2048)
-  S_ISGID* = cint(1024)
-  S_ISVTX* = cint(512)
-  ST_RDONLY* = cint(1)
-  ST_NOSUID* = cint(2)
-  PROT_READ* = cint(1)
-  PROT_WRITE* = cint(2)
-  PROT_EXEC* = cint(4)
-  PROT_NONE* = cint(0)
-  MAP_SHARED* = cint(1)
-  MAP_PRIVATE* = cint(2)
-  MAP_FIXED* = cint(16)
-  MS_ASYNC* = cint(1)
-  MS_SYNC* = cint(4)
-  MS_INVALIDATE* = cint(2)
-  MCL_CURRENT* = cint(1)
-  MCL_FUTURE* = cint(2)
-  MAP_FAILED* = cast[pointer](0xffffffffffffffff)
-  POSIX_MADV_NORMAL* = cint(0)
-  POSIX_MADV_SEQUENTIAL* = cint(2)
-  POSIX_MADV_RANDOM* = cint(1)
-  POSIX_MADV_WILLNEED* = cint(3)
-  POSIX_MADV_DONTNEED* = cint(4)
-  CLOCKS_PER_SEC* = clong(1000000)
-  CLOCK_PROCESS_CPUTIME_ID* = cint(2)
-  CLOCK_THREAD_CPUTIME_ID* = cint(3)
-  CLOCK_REALTIME* = cint(0)
-  TIMER_ABSTIME* = cint(1)
-  CLOCK_MONOTONIC* = cint(1)
-  WNOHANG* = cint(1)
-  WUNTRACED* = cint(2)
-  WEXITED* = cint(4)
-  WSTOPPED* = cint(2)
-  WCONTINUED* = cint(8)
-  WNOWAIT* = cint(16777216)
-  SIGEV_NONE* = cint(1)
-  SIGEV_SIGNAL* = cint(0)
-  SIGEV_THREAD* = cint(2)
-  SIGABRT* = cint(6)
-  SIGALRM* = cint(14)
-  SIGBUS* = cint(7)
-  SIGCHLD* = cint(17)
-  SIGCONT* = cint(18)
-  SIGFPE* = cint(8)
-  SIGHUP* = cint(1)
-  SIGILL* = cint(4)
-  SIGINT* = cint(2)
-  SIGKILL* = cint(9)
-  SIGPIPE* = cint(13)
-  SIGQUIT* = cint(3)
-  SIGSEGV* = cint(11)
-  SIGSTOP* = cint(19)
-  SIGTERM* = cint(15)
-  SIGTSTP* = cint(20)
-  SIGTTIN* = cint(21)
-  SIGTTOU* = cint(22)
-  SIGUSR1* = cint(10)
-  SIGUSR2* = cint(12)
-  SIGPOLL* = cint(29)
-  SIGPROF* = cint(27)
-  SIGSYS* = cint(31)
-  SIGTRAP* = cint(5)
-  SIGURG* = cint(23)
-  SIGVTALRM* = cint(26)
-  SIGXCPU* = cint(24)
-  SIGXFSZ* = cint(25)
-  SA_NOCLDSTOP* = cint(1)
-  SIG_BLOCK* = cint(0)
-  SIG_UNBLOCK* = cint(1)
-  SIG_SETMASK* = cint(2)
-  SA_ONSTACK* = cint(134217728)
-  SA_RESETHAND* = cint(-2147483648)
-  SA_RESTART* = cint(268435456)
-  SA_SIGINFO* = cint(4)
-  SA_NOCLDWAIT* = cint(2)
-  SA_NODEFER* = cint(1073741824)
-  SS_ONSTACK* = cint(1)
-  SS_DISABLE* = cint(2)
-  MINSIGSTKSZ* = cint(2048)
-  SIGSTKSZ* = cint(8192)
-  NL_SETD* = cint(1)
-  NL_CAT_LOCALE* = cint(1)
-  SCHED_FIFO* = cint(1)
-  SCHED_RR* = cint(2)
-  SCHED_OTHER* = cint(0)
-  FD_SETSIZE* = cint(1024)
-  IF_NAMESIZE* = cint(16)
-  SCM_RIGHTS* = cint(1)
-  SOCK_DGRAM* = cint(2)
-  SOCK_RAW* = cint(3)
-  SOCK_SEQPACKET* = cint(5)
-  SOCK_STREAM* = cint(1)
-  SOL_SOCKET* = cint(1)
-  SO_ACCEPTCONN* = cint(30)
-  SO_BROADCAST* = cint(6)
-  SO_DEBUG* = cint(1)
-  SO_DONTROUTE* = cint(5)
-  SO_ERROR* = cint(4)
-  SO_KEEPALIVE* = cint(9)
-  SO_LINGER* = cint(13)
-  SO_OOBINLINE* = cint(10)
-  SO_RCVBUF* = cint(8)
-  SO_RCVLOWAT* = cint(18)
-  SO_RCVTIMEO* = cint(20)
-  SO_REUSEADDR* = cint(2)
-  SO_SNDBUF* = cint(7)
-  SO_SNDLOWAT* = cint(19)
-  SO_SNDTIMEO* = cint(21)
-  SO_TYPE* = cint(3)
-  SOMAXCONN* = cint(128)
-  MSG_CTRUNC* = cint(8)
-  MSG_DONTROUTE* = cint(4)
-  MSG_EOR* = cint(128)
-  MSG_OOB* = cint(1)
-  MSG_PEEK* = cint(2)
-  MSG_TRUNC* = cint(32)
-  MSG_WAITALL* = cint(256)
-  AF_INET* = cint(2)
-  AF_INET6* = cint(10)
-  AF_UNIX* = cint(1)
-  AF_UNSPEC* = cint(0)
-  SHUT_RD* = cint(0)
-  SHUT_RDWR* = cint(2)
-  SHUT_WR* = cint(1)
-  IPPROTO_IP* = cint(0)
-  IPPROTO_IPV6* = cint(41)
-  IPPROTO_ICMP* = cint(1)
-  IPPROTO_RAW* = cint(255)
-  IPPROTO_TCP* = cint(6)
-  IPPROTO_UDP* = cint(17)
-  INADDR_ANY* = cint(0)
-  INADDR_BROADCAST* = cint(-1)
-  INET_ADDRSTRLEN* = cint(16)
-  IPV6_JOIN_GROUP* = cint(20)
-  IPV6_LEAVE_GROUP* = cint(21)
-  IPV6_MULTICAST_HOPS* = cint(18)
-  IPV6_MULTICAST_IF* = cint(17)
-  IPV6_MULTICAST_LOOP* = cint(19)
-  IPV6_UNICAST_HOPS* = cint(16)
-  IPV6_V6ONLY* = cint(26)
-  IPPORT_RESERVED* = cint(1024)
-  HOST_NOT_FOUND* = cint(1)
-  NO_DATA* = cint(4)
-  NO_RECOVERY* = cint(3)
-  TRY_AGAIN* = cint(2)
-  AI_PASSIVE* = cint(1)
-  AI_CANONNAME* = cint(2)
-  AI_NUMERICHOST* = cint(4)
-  AI_NUMERICSERV* = cint(1024)
-  AI_V4MAPPED* = cint(8)
-  AI_ALL* = cint(16)
-  AI_ADDRCONFIG* = cint(32)
-  NI_NOFQDN* = cint(4)
-  NI_NUMERICHOST* = cint(1)
-  NI_NAMEREQD* = cint(8)
-  NI_NUMERICSERV* = cint(2)
-  NI_DGRAM* = cint(16)
-  EAI_AGAIN* = cint(-3)
-  EAI_BADFLAGS* = cint(-1)
-  EAI_FAIL* = cint(-4)
-  EAI_FAMILY* = cint(-6)
-  EAI_MEMORY* = cint(-10)
-  EAI_NONAME* = cint(-2)
-  EAI_SERVICE* = cint(-8)
-  EAI_SOCKTYPE* = cint(-7)
-  EAI_SYSTEM* = cint(-11)
-  EAI_OVERFLOW* = cint(-12)
-  POLLIN* = cshort(1)
-  POLLPRI* = cshort(2)
-  POLLOUT* = cshort(4)
-  POLLERR* = cshort(8)
-  POLLHUP* = cshort(16)
-  POLLNVAL* = cshort(32)
-  POSIX_SPAWN_RESETIDS* = cint(1)
-  POSIX_SPAWN_SETPGROUP* = cint(2)
-  POSIX_SPAWN_SETSCHEDPARAM* = cint(16)
-  POSIX_SPAWN_SETSCHEDULER* = cint(32)
-  POSIX_SPAWN_SETSIGDEF* = cint(4)
-  POSIX_SPAWN_SETSIGMASK* = cint(8)
diff --git a/lib/posix/linux_consts.nim b/lib/posix/linux_consts.nim
deleted file mode 100644
index 2fadcd83b..000000000
--- a/lib/posix/linux_consts.nim
+++ /dev/null
@@ -1,620 +0,0 @@
-# Generated by detect.nim
-const
-  AIO_ALLDONE* = cint(2)
-  AIO_CANCELED* = cint(0)
-  AIO_NOTCANCELED* = cint(1)
-  LIO_NOP* = cint(2)
-  LIO_NOWAIT* = cint(1)
-  LIO_READ* = cint(0)
-  LIO_WAIT* = cint(0)
-  LIO_WRITE* = cint(1)
-  RTLD_LAZY* = cint(1)
-  RTLD_NOW* = cint(2)
-  RTLD_GLOBAL* = cint(256)
-  RTLD_LOCAL* = cint(0)
-  E2BIG* = cint(7)
-  EACCES* = cint(13)
-  EADDRINUSE* = cint(98)
-  EADDRNOTAVAIL* = cint(99)
-  EAFNOSUPPORT* = cint(97)
-  EAGAIN* = cint(11)
-  EALREADY* = cint(114)
-  EBADF* = cint(9)
-  EBADMSG* = cint(74)
-  EBUSY* = cint(16)
-  ECANCELED* = cint(125)
-  ECHILD* = cint(10)
-  ECONNABORTED* = cint(103)
-  ECONNREFUSED* = cint(111)
-  ECONNRESET* = cint(104)
-  EDEADLK* = cint(35)
-  EDESTADDRREQ* = cint(89)
-  EDOM* = cint(33)
-  EDQUOT* = cint(122)
-  EEXIST* = cint(17)
-  EFAULT* = cint(14)
-  EFBIG* = cint(27)
-  EHOSTUNREACH* = cint(113)
-  EIDRM* = cint(43)
-  EILSEQ* = cint(84)
-  EINPROGRESS* = cint(115)
-  EINTR* = cint(4)
-  EINVAL* = cint(22)
-  EIO* = cint(5)
-  EISCONN* = cint(106)
-  EISDIR* = cint(21)
-  ELOOP* = cint(40)
-  EMFILE* = cint(24)
-  EMLINK* = cint(31)
-  EMSGSIZE* = cint(90)
-  EMULTIHOP* = cint(72)
-  ENAMETOOLONG* = cint(36)
-  ENETDOWN* = cint(100)
-  ENETRESET* = cint(102)
-  ENETUNREACH* = cint(101)
-  ENFILE* = cint(23)
-  ENOBUFS* = cint(105)
-  ENODATA* = cint(61)
-  ENODEV* = cint(19)
-  ENOENT* = cint(2)
-  ENOEXEC* = cint(8)
-  ENOLCK* = cint(37)
-  ENOLINK* = cint(67)
-  ENOMEM* = cint(12)
-  ENOMSG* = cint(42)
-  ENOPROTOOPT* = cint(92)
-  ENOSPC* = cint(28)
-  ENOSR* = cint(63)
-  ENOSTR* = cint(60)
-  ENOSYS* = cint(38)
-  ENOTCONN* = cint(107)
-  ENOTDIR* = cint(20)
-  ENOTEMPTY* = cint(39)
-  ENOTSOCK* = cint(88)
-  ENOTSUP* = cint(95)
-  ENOTTY* = cint(25)
-  ENXIO* = cint(6)
-  EOPNOTSUPP* = cint(95)
-  EOVERFLOW* = cint(75)
-  EPERM* = cint(1)
-  EPIPE* = cint(32)
-  EPROTO* = cint(71)
-  EPROTONOSUPPORT* = cint(93)
-  EPROTOTYPE* = cint(91)
-  ERANGE* = cint(34)
-  EROFS* = cint(30)
-  ESPIPE* = cint(29)
-  ESRCH* = cint(3)
-  ESTALE* = cint(116)
-  ETIME* = cint(62)
-  ETIMEDOUT* = cint(110)
-  ETXTBSY* = cint(26)
-  EWOULDBLOCK* = cint(11)
-  EXDEV* = cint(18)
-  F_DUPFD* = cint(0)
-  F_GETFD* = cint(1)
-  F_SETFD* = cint(2)
-  F_GETFL* = cint(3)
-  F_SETFL* = cint(4)
-  F_GETLK* = cint(5)
-  F_SETLK* = cint(6)
-  F_SETLKW* = cint(7)
-  F_GETOWN* = cint(9)
-  F_SETOWN* = cint(8)
-  FD_CLOEXEC* = cint(1)
-  F_RDLCK* = cint(0)
-  F_UNLCK* = cint(2)
-  F_WRLCK* = cint(1)
-  O_CREAT* = cint(64)
-  O_EXCL* = cint(128)
-  O_NOCTTY* = cint(256)
-  O_TRUNC* = cint(512)
-  O_APPEND* = cint(1024)
-  O_DSYNC* = cint(4096)
-  O_NONBLOCK* = cint(2048)
-  O_RSYNC* = cint(4096)
-  O_SYNC* = cint(4096)
-  O_ACCMODE* = cint(3)
-  O_RDONLY* = cint(0)
-  O_RDWR* = cint(2)
-  O_WRONLY* = cint(1)
-  POSIX_FADV_NORMAL* = cint(0)
-  POSIX_FADV_SEQUENTIAL* = cint(2)
-  POSIX_FADV_RANDOM* = cint(1)
-  POSIX_FADV_WILLNEED* = cint(3)
-  POSIX_FADV_DONTNEED* = cint(4)
-  POSIX_FADV_NOREUSE* = cint(5)
-  FE_DIVBYZERO* = cint(4)
-  FE_INEXACT* = cint(32)
-  FE_INVALID* = cint(1)
-  FE_OVERFLOW* = cint(8)
-  FE_UNDERFLOW* = cint(16)
-  FE_ALL_EXCEPT* = cint(61)
-  FE_DOWNWARD* = cint(1024)
-  FE_TONEAREST* = cint(0)
-  FE_TOWARDZERO* = cint(3072)
-  FE_UPWARD* = cint(2048)
-  FE_DFL_ENV* = cast[pointer](0xffffffffffffffff)
-  MM_HARD* = cint(1)
-  MM_SOFT* = cint(2)
-  MM_FIRM* = cint(4)
-  MM_APPL* = cint(8)
-  MM_UTIL* = cint(16)
-  MM_OPSYS* = cint(32)
-  MM_RECOVER* = cint(64)
-  MM_NRECOV* = cint(128)
-  MM_HALT* = cint(1)
-  MM_ERROR* = cint(2)
-  MM_WARNING* = cint(3)
-  MM_INFO* = cint(4)
-  MM_NOSEV* = cint(0)
-  MM_PRINT* = cint(256)
-  MM_CONSOLE* = cint(512)
-  MM_OK* = cint(0)
-  MM_NOTOK* = cint(-1)
-  MM_NOMSG* = cint(1)
-  MM_NOCON* = cint(4)
-  FNM_NOMATCH* = cint(1)
-  FNM_PATHNAME* = cint(1)
-  FNM_PERIOD* = cint(4)
-  FNM_NOESCAPE* = cint(2)
-  FTW_F* = cint(0)
-  FTW_D* = cint(1)
-  FTW_DNR* = cint(2)
-  FTW_NS* = cint(3)
-  FTW_SL* = cint(4)
-  GLOB_APPEND* = cint(32)
-  GLOB_DOOFFS* = cint(8)
-  GLOB_ERR* = cint(1)
-  GLOB_MARK* = cint(2)
-  GLOB_NOCHECK* = cint(16)
-  GLOB_NOESCAPE* = cint(64)
-  GLOB_NOSORT* = cint(4)
-  GLOB_ABORTED* = cint(2)
-  GLOB_NOMATCH* = cint(3)
-  GLOB_NOSPACE* = cint(1)
-  GLOB_NOSYS* = cint(4)
-  CODESET* = cint(14)
-  D_T_FMT* = cint(131112)
-  D_FMT* = cint(131113)
-  T_FMT* = cint(131114)
-  T_FMT_AMPM* = cint(131115)
-  AM_STR* = cint(131110)
-  PM_STR* = cint(131111)
-  DAY_1* = cint(131079)
-  DAY_2* = cint(131080)
-  DAY_3* = cint(131081)
-  DAY_4* = cint(131082)
-  DAY_5* = cint(131083)
-  DAY_6* = cint(131084)
-  DAY_7* = cint(131085)
-  ABDAY_1* = cint(131072)
-  ABDAY_2* = cint(131073)
-  ABDAY_3* = cint(131074)
-  ABDAY_4* = cint(131075)
-  ABDAY_5* = cint(131076)
-  ABDAY_6* = cint(131077)
-  ABDAY_7* = cint(131078)
-  MON_1* = cint(131098)
-  MON_2* = cint(131099)
-  MON_3* = cint(131100)
-  MON_4* = cint(131101)
-  MON_5* = cint(131102)
-  MON_6* = cint(131103)
-  MON_7* = cint(131104)
-  MON_8* = cint(131105)
-  MON_9* = cint(131106)
-  MON_10* = cint(131107)
-  MON_11* = cint(131108)
-  MON_12* = cint(131109)
-  ABMON_1* = cint(131086)
-  ABMON_2* = cint(131087)
-  ABMON_3* = cint(131088)
-  ABMON_4* = cint(131089)
-  ABMON_5* = cint(131090)
-  ABMON_6* = cint(131091)
-  ABMON_7* = cint(131092)
-  ABMON_8* = cint(131093)
-  ABMON_9* = cint(131094)
-  ABMON_10* = cint(131095)
-  ABMON_11* = cint(131096)
-  ABMON_12* = cint(131097)
-  ERA* = cint(131116)
-  ERA_D_FMT* = cint(131118)
-  ERA_D_T_FMT* = cint(131120)
-  ERA_T_FMT* = cint(131121)
-  ALT_DIGITS* = cint(131119)
-  RADIXCHAR* = cint(65536)
-  THOUSEP* = cint(65537)
-  YESEXPR* = cint(327680)
-  NOEXPR* = cint(327681)
-  CRNCYSTR* = cint(262159)
-  LC_ALL* = cint(6)
-  LC_COLLATE* = cint(3)
-  LC_CTYPE* = cint(0)
-  LC_MESSAGES* = cint(5)
-  LC_MONETARY* = cint(4)
-  LC_NUMERIC* = cint(1)
-  LC_TIME* = cint(2)
-  PTHREAD_BARRIER_SERIAL_THREAD* = cint(-1)
-  PTHREAD_CANCEL_ASYNCHRONOUS* = cint(1)
-  PTHREAD_CANCEL_ENABLE* = cint(0)
-  PTHREAD_CANCEL_DEFERRED* = cint(0)
-  PTHREAD_CANCEL_DISABLE* = cint(1)
-  PTHREAD_CREATE_DETACHED* = cint(1)
-  PTHREAD_CREATE_JOINABLE* = cint(0)
-  PTHREAD_EXPLICIT_SCHED* = cint(1)
-  PTHREAD_INHERIT_SCHED* = cint(0)
-  PTHREAD_ONCE_INIT* = cint(0)
-  PTHREAD_PROCESS_SHARED* = cint(1)
-  PTHREAD_PROCESS_PRIVATE* = cint(0)
-  PTHREAD_SCOPE_PROCESS* = cint(1)
-  PTHREAD_SCOPE_SYSTEM* = cint(0)
-  POSIX_ASYNC_IO* = cint(1)
-  F_OK* = cint(0)
-  R_OK* = cint(4)
-  W_OK* = cint(2)
-  X_OK* = cint(1)
-  CS_PATH* = cint(0)
-  CS_POSIX_V6_ILP32_OFF32_CFLAGS* = cint(1116)
-  CS_POSIX_V6_ILP32_OFF32_LDFLAGS* = cint(1117)
-  CS_POSIX_V6_ILP32_OFF32_LIBS* = cint(1118)
-  CS_POSIX_V6_ILP32_OFFBIG_CFLAGS* = cint(1120)
-  CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS* = cint(1121)
-  CS_POSIX_V6_ILP32_OFFBIG_LIBS* = cint(1122)
-  CS_POSIX_V6_LP64_OFF64_CFLAGS* = cint(1124)
-  CS_POSIX_V6_LP64_OFF64_LDFLAGS* = cint(1125)
-  CS_POSIX_V6_LP64_OFF64_LIBS* = cint(1126)
-  CS_POSIX_V6_LPBIG_OFFBIG_CFLAGS* = cint(1128)
-  CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGS* = cint(1129)
-  CS_POSIX_V6_LPBIG_OFFBIG_LIBS* = cint(1130)
-  CS_POSIX_V6_WIDTH_RESTRICTED_ENVS* = cint(1)
-  F_LOCK* = cint(1)
-  F_TEST* = cint(3)
-  F_TLOCK* = cint(2)
-  F_ULOCK* = cint(0)
-  PC_2_SYMLINKS* = cint(20)
-  PC_ALLOC_SIZE_MIN* = cint(18)
-  PC_ASYNC_IO* = cint(10)
-  PC_CHOWN_RESTRICTED* = cint(6)
-  PC_FILESIZEBITS* = cint(13)
-  PC_LINK_MAX* = cint(0)
-  PC_MAX_CANON* = cint(1)
-  PC_MAX_INPUT* = cint(2)
-  PC_NAME_MAX* = cint(3)
-  PC_NO_TRUNC* = cint(7)
-  PC_PATH_MAX* = cint(4)
-  PC_PIPE_BUF* = cint(5)
-  PC_PRIO_IO* = cint(11)
-  PC_REC_INCR_XFER_SIZE* = cint(14)
-  PC_REC_MIN_XFER_SIZE* = cint(16)
-  PC_REC_XFER_ALIGN* = cint(17)
-  PC_SYMLINK_MAX* = cint(19)
-  PC_SYNC_IO* = cint(9)
-  PC_VDISABLE* = cint(8)
-  SC_2_C_BIND* = cint(47)
-  SC_2_C_DEV* = cint(48)
-  SC_2_CHAR_TERM* = cint(95)
-  SC_2_FORT_DEV* = cint(49)
-  SC_2_FORT_RUN* = cint(50)
-  SC_2_LOCALEDEF* = cint(52)
-  SC_2_PBS* = cint(168)
-  SC_2_PBS_ACCOUNTING* = cint(169)
-  SC_2_PBS_CHECKPOINT* = cint(175)
-  SC_2_PBS_LOCATE* = cint(170)
-  SC_2_PBS_MESSAGE* = cint(171)
-  SC_2_PBS_TRACK* = cint(172)
-  SC_2_SW_DEV* = cint(51)
-  SC_2_UPE* = cint(97)
-  SC_2_VERSION* = cint(46)
-  SC_ADVISORY_INFO* = cint(132)
-  SC_AIO_LISTIO_MAX* = cint(23)
-  SC_AIO_MAX* = cint(24)
-  SC_AIO_PRIO_DELTA_MAX* = cint(25)
-  SC_ARG_MAX* = cint(0)
-  SC_ASYNCHRONOUS_IO* = cint(12)
-  SC_ATEXIT_MAX* = cint(87)
-  SC_BARRIERS* = cint(133)
-  SC_BC_BASE_MAX* = cint(36)
-  SC_BC_DIM_MAX* = cint(37)
-  SC_BC_SCALE_MAX* = cint(38)
-  SC_BC_STRING_MAX* = cint(39)
-  SC_CHILD_MAX* = cint(1)
-  SC_CLK_TCK* = cint(2)
-  SC_CLOCK_SELECTION* = cint(137)
-  SC_COLL_WEIGHTS_MAX* = cint(40)
-  SC_CPUTIME* = cint(138)
-  SC_DELAYTIMER_MAX* = cint(26)
-  SC_EXPR_NEST_MAX* = cint(42)
-  SC_FSYNC* = cint(15)
-  SC_GETGR_R_SIZE_MAX* = cint(69)
-  SC_GETPW_R_SIZE_MAX* = cint(70)
-  SC_HOST_NAME_MAX* = cint(180)
-  SC_IOV_MAX* = cint(60)
-  SC_IPV6* = cint(235)
-  SC_JOB_CONTROL* = cint(7)
-  SC_LINE_MAX* = cint(43)
-  SC_LOGIN_NAME_MAX* = cint(71)
-  SC_MAPPED_FILES* = cint(16)
-  SC_MEMLOCK* = cint(17)
-  SC_MEMLOCK_RANGE* = cint(18)
-  SC_MEMORY_PROTECTION* = cint(19)
-  SC_MESSAGE_PASSING* = cint(20)
-  SC_MONOTONIC_CLOCK* = cint(149)
-  SC_MQ_OPEN_MAX* = cint(27)
-  SC_MQ_PRIO_MAX* = cint(28)
-  SC_NGROUPS_MAX* = cint(3)
-  SC_OPEN_MAX* = cint(4)
-  SC_PAGE_SIZE* = cint(30)
-  SC_PRIORITIZED_IO* = cint(13)
-  SC_PRIORITY_SCHEDULING* = cint(10)
-  SC_RAW_SOCKETS* = cint(236)
-  SC_RE_DUP_MAX* = cint(44)
-  SC_READER_WRITER_LOCKS* = cint(153)
-  SC_REALTIME_SIGNALS* = cint(9)
-  SC_REGEXP* = cint(155)
-  SC_RTSIG_MAX* = cint(31)
-  SC_SAVED_IDS* = cint(8)
-  SC_SEM_NSEMS_MAX* = cint(32)
-  SC_SEM_VALUE_MAX* = cint(33)
-  SC_SEMAPHORES* = cint(21)
-  SC_SHARED_MEMORY_OBJECTS* = cint(22)
-  SC_SHELL* = cint(157)
-  SC_SIGQUEUE_MAX* = cint(34)
-  SC_SPAWN* = cint(159)
-  SC_SPIN_LOCKS* = cint(154)
-  SC_SPORADIC_SERVER* = cint(160)
-  SC_STREAM_MAX* = cint(5)
-  SC_SYMLOOP_MAX* = cint(173)
-  SC_SYNCHRONIZED_IO* = cint(14)
-  SC_THREAD_ATTR_STACKADDR* = cint(77)
-  SC_THREAD_ATTR_STACKSIZE* = cint(78)
-  SC_THREAD_CPUTIME* = cint(139)
-  SC_THREAD_DESTRUCTOR_ITERATIONS* = cint(73)
-  SC_THREAD_KEYS_MAX* = cint(74)
-  SC_THREAD_PRIO_INHERIT* = cint(80)
-  SC_THREAD_PRIO_PROTECT* = cint(81)
-  SC_THREAD_PRIORITY_SCHEDULING* = cint(79)
-  SC_THREAD_PROCESS_SHARED* = cint(82)
-  SC_THREAD_SAFE_FUNCTIONS* = cint(68)
-  SC_THREAD_SPORADIC_SERVER* = cint(161)
-  SC_THREAD_STACK_MIN* = cint(75)
-  SC_THREAD_THREADS_MAX* = cint(76)
-  SC_THREADS* = cint(67)
-  SC_TIMEOUTS* = cint(164)
-  SC_TIMER_MAX* = cint(35)
-  SC_TIMERS* = cint(11)
-  SC_TRACE* = cint(181)
-  SC_TRACE_EVENT_FILTER* = cint(182)
-  SC_TRACE_INHERIT* = cint(183)
-  SC_TRACE_LOG* = cint(184)
-  SC_TTY_NAME_MAX* = cint(72)
-  SC_TYPED_MEMORY_OBJECTS* = cint(165)
-  SC_TZNAME_MAX* = cint(6)
-  SC_V6_ILP32_OFF32* = cint(176)
-  SC_V6_ILP32_OFFBIG* = cint(177)
-  SC_V6_LP64_OFF64* = cint(178)
-  SC_V6_LPBIG_OFFBIG* = cint(179)
-  SC_VERSION* = cint(29)
-  SC_XBS5_ILP32_OFF32* = cint(125)
-  SC_XBS5_ILP32_OFFBIG* = cint(126)
-  SC_XBS5_LP64_OFF64* = cint(127)
-  SC_XBS5_LPBIG_OFFBIG* = cint(128)
-  SC_XOPEN_CRYPT* = cint(92)
-  SC_XOPEN_ENH_I18N* = cint(93)
-  SC_XOPEN_LEGACY* = cint(129)
-  SC_XOPEN_REALTIME* = cint(130)
-  SC_XOPEN_REALTIME_THREADS* = cint(131)
-  SC_XOPEN_SHM* = cint(94)
-  SC_XOPEN_UNIX* = cint(91)
-  SC_XOPEN_VERSION* = cint(89)
-  SEEK_SET* = cint(0)
-  SEEK_CUR* = cint(1)
-  SEEK_END* = cint(2)
-  SEM_FAILED* = cast[pointer]((nil))
-  IPC_CREAT* = cint(512)
-  IPC_EXCL* = cint(1024)
-  IPC_NOWAIT* = cint(2048)
-  IPC_PRIVATE* = cint(0)
-  IPC_RMID* = cint(0)
-  IPC_SET* = cint(1)
-  IPC_STAT* = cint(2)
-  S_IFMT* = cint(61440)
-  S_IFBLK* = cint(24576)
-  S_IFCHR* = cint(8192)
-  S_IFIFO* = cint(4096)
-  S_IFREG* = cint(32768)
-  S_IFDIR* = cint(16384)
-  S_IFLNK* = cint(40960)
-  S_IFSOCK* = cint(49152)
-  S_IRWXU* = cint(448)
-  S_IRUSR* = cint(256)
-  S_IWUSR* = cint(128)
-  S_IXUSR* = cint(64)
-  S_IRWXG* = cint(56)
-  S_IRGRP* = cint(32)
-  S_IWGRP* = cint(16)
-  S_IXGRP* = cint(8)
-  S_IRWXO* = cint(7)
-  S_IROTH* = cint(4)
-  S_IWOTH* = cint(2)
-  S_IXOTH* = cint(1)
-  S_ISUID* = cint(2048)
-  S_ISGID* = cint(1024)
-  S_ISVTX* = cint(512)
-  ST_RDONLY* = cint(1)
-  ST_NOSUID* = cint(2)
-  PROT_READ* = cint(1)
-  PROT_WRITE* = cint(2)
-  PROT_EXEC* = cint(4)
-  PROT_NONE* = cint(0)
-  MAP_SHARED* = cint(1)
-  MAP_PRIVATE* = cint(2)
-  MAP_FIXED* = cint(16)
-  MS_ASYNC* = cint(1)
-  MS_SYNC* = cint(4)
-  MS_INVALIDATE* = cint(2)
-  MCL_CURRENT* = cint(1)
-  MCL_FUTURE* = cint(2)
-  MAP_FAILED* = cast[pointer](0xffffffffffffffff)
-  POSIX_MADV_NORMAL* = cint(0)
-  POSIX_MADV_SEQUENTIAL* = cint(2)
-  POSIX_MADV_RANDOM* = cint(1)
-  POSIX_MADV_WILLNEED* = cint(3)
-  POSIX_MADV_DONTNEED* = cint(4)
-  CLOCKS_PER_SEC* = clong(1000000)
-  CLOCK_PROCESS_CPUTIME_ID* = cint(2)
-  CLOCK_THREAD_CPUTIME_ID* = cint(3)
-  CLOCK_REALTIME* = cint(0)
-  TIMER_ABSTIME* = cint(1)
-  CLOCK_MONOTONIC* = cint(1)
-  WNOHANG* = cint(1)
-  WUNTRACED* = cint(2)
-  WEXITED* = cint(4)
-  WSTOPPED* = cint(2)
-  WCONTINUED* = cint(8)
-  WNOWAIT* = cint(16777216)
-  SIGEV_NONE* = cint(1)
-  SIGEV_SIGNAL* = cint(0)
-  SIGEV_THREAD* = cint(2)
-  SIGABRT* = cint(6)
-  SIGALRM* = cint(14)
-  SIGBUS* = cint(7)
-  SIGCHLD* = cint(17)
-  SIGCONT* = cint(18)
-  SIGFPE* = cint(8)
-  SIGHUP* = cint(1)
-  SIGILL* = cint(4)
-  SIGINT* = cint(2)
-  SIGKILL* = cint(9)
-  SIGPIPE* = cint(13)
-  SIGQUIT* = cint(3)
-  SIGSEGV* = cint(11)
-  SIGSTOP* = cint(19)
-  SIGTERM* = cint(15)
-  SIGTSTP* = cint(20)
-  SIGTTIN* = cint(21)
-  SIGTTOU* = cint(22)
-  SIGUSR1* = cint(10)
-  SIGUSR2* = cint(12)
-  SIGPOLL* = cint(29)
-  SIGPROF* = cint(27)
-  SIGSYS* = cint(31)
-  SIGTRAP* = cint(5)
-  SIGURG* = cint(23)
-  SIGVTALRM* = cint(26)
-  SIGXCPU* = cint(24)
-  SIGXFSZ* = cint(25)
-  SA_NOCLDSTOP* = cint(1)
-  SIG_BLOCK* = cint(0)
-  SIG_UNBLOCK* = cint(1)
-  SIG_SETMASK* = cint(2)
-  SA_ONSTACK* = cint(134217728)
-  SA_RESETHAND* = cint(-2147483648)
-  SA_RESTART* = cint(268435456)
-  SA_SIGINFO* = cint(4)
-  SA_NOCLDWAIT* = cint(2)
-  SA_NODEFER* = cint(1073741824)
-  SS_ONSTACK* = cint(1)
-  SS_DISABLE* = cint(2)
-  MINSIGSTKSZ* = cint(2048)
-  SIGSTKSZ* = cint(8192)
-  NL_SETD* = cint(1)
-  NL_CAT_LOCALE* = cint(1)
-  SCHED_FIFO* = cint(1)
-  SCHED_RR* = cint(2)
-  SCHED_OTHER* = cint(0)
-  FD_SETSIZE* = cint(1024)
-  IF_NAMESIZE* = cint(16)
-  SCM_RIGHTS* = cint(1)
-  SOCK_DGRAM* = cint(2)
-  SOCK_RAW* = cint(3)
-  SOCK_SEQPACKET* = cint(5)
-  SOCK_STREAM* = cint(1)
-  SOL_SOCKET* = cint(1)
-  SO_ACCEPTCONN* = cint(30)
-  SO_BROADCAST* = cint(6)
-  SO_DEBUG* = cint(1)
-  SO_DONTROUTE* = cint(5)
-  SO_ERROR* = cint(4)
-  SO_KEEPALIVE* = cint(9)
-  SO_LINGER* = cint(13)
-  SO_OOBINLINE* = cint(10)
-  SO_RCVBUF* = cint(8)
-  SO_RCVLOWAT* = cint(18)
-  SO_RCVTIMEO* = cint(20)
-  SO_REUSEADDR* = cint(2)
-  SO_SNDBUF* = cint(7)
-  SO_SNDLOWAT* = cint(19)
-  SO_SNDTIMEO* = cint(21)
-  SO_TYPE* = cint(3)
-  SOMAXCONN* = cint(128)
-  MSG_CTRUNC* = cint(8)
-  MSG_DONTROUTE* = cint(4)
-  MSG_EOR* = cint(128)
-  MSG_OOB* = cint(1)
-  MSG_PEEK* = cint(2)
-  MSG_TRUNC* = cint(32)
-  MSG_WAITALL* = cint(256)
-  AF_INET* = cint(2)
-  AF_INET6* = cint(10)
-  AF_UNIX* = cint(1)
-  AF_UNSPEC* = cint(0)
-  SHUT_RD* = cint(0)
-  SHUT_RDWR* = cint(2)
-  SHUT_WR* = cint(1)
-  IPPROTO_IP* = cint(0)
-  IPPROTO_IPV6* = cint(41)
-  IPPROTO_ICMP* = cint(1)
-  IPPROTO_RAW* = cint(255)
-  IPPROTO_TCP* = cint(6)
-  IPPROTO_UDP* = cint(17)
-  INADDR_ANY* = cint(0)
-  INADDR_BROADCAST* = cint(-1)
-  INET_ADDRSTRLEN* = cint(16)
-  IPV6_JOIN_GROUP* = cint(20)
-  IPV6_LEAVE_GROUP* = cint(21)
-  IPV6_MULTICAST_HOPS* = cint(18)
-  IPV6_MULTICAST_IF* = cint(17)
-  IPV6_MULTICAST_LOOP* = cint(19)
-  IPV6_UNICAST_HOPS* = cint(16)
-  IPV6_V6ONLY* = cint(26)
-  IPPORT_RESERVED* = cint(1024)
-  HOST_NOT_FOUND* = cint(1)
-  NO_DATA* = cint(4)
-  NO_RECOVERY* = cint(3)
-  TRY_AGAIN* = cint(2)
-  AI_PASSIVE* = cint(1)
-  AI_CANONNAME* = cint(2)
-  AI_NUMERICHOST* = cint(4)
-  AI_NUMERICSERV* = cint(1024)
-  AI_V4MAPPED* = cint(8)
-  AI_ALL* = cint(16)
-  AI_ADDRCONFIG* = cint(32)
-  NI_NOFQDN* = cint(4)
-  NI_NUMERICHOST* = cint(1)
-  NI_NAMEREQD* = cint(8)
-  NI_NUMERICSERV* = cint(2)
-  NI_DGRAM* = cint(16)
-  EAI_AGAIN* = cint(-3)
-  EAI_BADFLAGS* = cint(-1)
-  EAI_FAIL* = cint(-4)
-  EAI_FAMILY* = cint(-6)
-  EAI_MEMORY* = cint(-10)
-  EAI_NONAME* = cint(-2)
-  EAI_SERVICE* = cint(-8)
-  EAI_SOCKTYPE* = cint(-7)
-  EAI_SYSTEM* = cint(-11)
-  EAI_OVERFLOW* = cint(-12)
-  POLLIN* = cshort(1)
-  POLLPRI* = cshort(2)
-  POLLOUT* = cshort(4)
-  POLLERR* = cshort(8)
-  POLLHUP* = cshort(16)
-  POLLNVAL* = cshort(32)
-  POSIX_SPAWN_RESETIDS* = cint(1)
-  POSIX_SPAWN_SETPGROUP* = cint(2)
-  POSIX_SPAWN_SETSCHEDPARAM* = cint(16)
-  POSIX_SPAWN_SETSCHEDULER* = cint(32)
-  POSIX_SPAWN_SETSIGDEF* = cint(4)
-  POSIX_SPAWN_SETSIGMASK* = cint(8)
diff --git a/lib/posix/posix.nim b/lib/posix/posix.nim
index e71e8a003..42cbbba75 100644
--- a/lib/posix/posix.nim
+++ b/lib/posix/posix.nim
@@ -26,33 +26,37 @@
 ## This library relies on the header files of your C compiler. Thus the

 ## resulting C code will just include <XYZ.h> and *not* define the

 ## symbols declared here.

+
+from times import TTime
 

 const

   hasSpawnH = defined(linux)

   hasAioH = defined(linux)

-

+
+when false:

+  const

+    C_IRUSR = 0c000400 ## Read by owner.

+    C_IWUSR = 0c000200 ## Write by owner.

+    C_IXUSR = 0c000100 ## Execute by owner.

+    C_IRGRP = 0c000040 ## Read by group.

+    C_IWGRP = 0c000020 ## Write by group.

+    C_IXGRP = 0c000010 ## Execute by group.

+    C_IROTH = 0c000004 ## Read by others.

+    C_IWOTH = 0c000002 ## Write by others.

+    C_IXOTH = 0c000001 ## Execute by others.

+    C_ISUID = 0c004000 ## Set user ID.

+    C_ISGID = 0c002000 ## Set group ID.

+    C_ISVTX = 0c001000 ## On directories, restricted deletion flag.

+    C_ISDIR = 0c040000 ## Directory.

+    C_ISFIFO = 0c010000 ##FIFO.

+    C_ISREG = 0c100000 ## Regular file.

+    C_ISBLK = 0c060000 ## Block special.

+    C_ISCHR = 0c020000 ## Character special.

+    C_ISCTG = 0c110000 ## Reserved.

+    C_ISLNK = 0c120000 ## Symbolic link.</p>

+    C_ISSOCK = 0c140000 ## Socket.

+
 const

-  C_IRUSR* = 0c000400 ## Read by owner.

-  C_IWUSR* = 0c000200 ## Write by owner.

-  C_IXUSR* = 0c000100 ## Execute by owner.

-  C_IRGRP* = 0c000040 ## Read by group.

-  C_IWGRP* = 0c000020 ## Write by group.

-  C_IXGRP* = 0c000010 ## Execute by group.

-  C_IROTH* = 0c000004 ## Read by others.

-  C_IWOTH* = 0c000002 ## Write by others.

-  C_IXOTH* = 0c000001 ## Execute by others.

-  C_ISUID* = 0c004000 ## Set user ID.

-  C_ISGID* = 0c002000 ## Set group ID.

-  C_ISVTX* = 0c001000 ## On directories, restricted deletion flag.

-  C_ISDIR* = 0c040000 ## Directory.

-  C_ISFIFO* = 0c010000 ##FIFO.

-  C_ISREG* = 0c100000 ## Regular file.

-  C_ISBLK* = 0c060000 ## Block special.

-  C_ISCHR* = 0c020000 ## Character special.

-  C_ISCTG* = 0c110000 ## Reserved.

-  C_ISLNK* = 0c120000 ## Symbolic link.</p>

-  C_ISSOCK* = 0c140000 ## Socket.

-

   MM_NULLLBL* = nil

   MM_NULLSEV* = 0

   MM_NULLMC* = 0

@@ -104,9 +108,9 @@ type
     

   TGlob* {.importc: "glob_t", header: "<glob.h>", 
            final, pure.} = object ## glob_t

-    gl_pathc*: int         ## Count of paths matched by pattern. 

-    gl_pathv*: ptr cstring ## Pointer to a list of matched pathnames. 

-    gl_offs*: int          ## Slots to reserve at the beginning of gl_pathv. 

+    gl_pathc*: int          ## Count of paths matched by pattern. 

+    gl_pathv*: cstringArray ## Pointer to a list of matched pathnames. 

+    gl_offs*: int           ## Slots to reserve at the beginning of gl_pathv. 

   

   TGroup* {.importc: "struct group", header: "<grp.h>", 
             final, pure.} = object ## struct group

@@ -198,7 +202,7 @@ type
                        header: "<sys/types.h>".} = int

   Tpthread* {.importc: "pthread_t", header: "<sys/types.h>".} = int

   Tsuseconds* {.importc: "suseconds_t", header: "<sys/types.h>".} = int

-  Ttime* {.importc: "time_t", header: "<sys/types.h>".} = int

+  #Ttime* {.importc: "time_t", header: "<sys/types.h>".} = int

   Ttimer* {.importc: "timer_t", header: "<sys/types.h>".} = int

   Ttrace_attr* {.importc: "trace_attr_t", header: "<sys/types.h>".} = int

   Ttrace_event_id* {.importc: "trace_event_id_t", 
@@ -2431,4 +2435,7 @@ proc setservent*(a1: cint) {.importc, header: "<netdb.h>".}
 proc poll*(a1: ptr Tpollfd, a2: Tnfds, a3: int): cint {.
   importc, header: "<poll.h>".}
 
+proc realpath*(name, resolved: CString): CString {.
+  importc: "realpath", header: "<stdlib.h>".}
+
 
diff --git a/lib/powerpc.asm.in b/lib/powerpc.asm.in
deleted file mode 100644
index 107f887ab..000000000
--- a/lib/powerpc.asm.in
+++ /dev/null
@@ -1,35 +0,0 @@
-; This contains the CPU-dependant variants of some routines.

-; (C) 2005 Andreas Rumpf

-; This code was inspired by the Freepascal compiler's sources

-; All routines here have the _cdecl calling convention because

-; that is the only convention any C compiler supports.

-

-\python{

-def c(name): 

-  if os.name == 'posix':

-    return name

-  else:

-    return "_" + name

-}

-

-segment code

-

-global \c{cpu_inc_locked}

-global \c{cpu_dec_locked}

-

-\c{cpu_dec_locked}: 

-; input:  address of arg in r3 

-  .LDecLockedLoop:

-    lwarx   r10,0,r3

-    subi    r10,r10,1

-    stwcx.  r10,0,r3

-    bne-    .LDecLockedLoop

-    cntlzw  r3,r10

-    srwi    r3,r3,5

-     

-\c{cpu_inc_locked}:

-  .LIncLockedLoop:

-    lwarx   r10,0,r3

-    addi    r10,r10,1

-    stwcx.  r10,0,r3

-    bne-    .LIncLockedLoop

diff --git a/lib/base/cgi.nim b/lib/pure/cgi.nim
index 5cf6d0bfa..5cf6d0bfa 100644
--- a/lib/base/cgi.nim
+++ b/lib/pure/cgi.nim
diff --git a/lib/complex.nim b/lib/pure/complex.nim
index f50ff4bd0..f50ff4bd0 100644
--- a/lib/complex.nim
+++ b/lib/pure/complex.nim
diff --git a/lib/pure/dynlib.nim b/lib/pure/dynlib.nim
new file mode 100644
index 000000000..592073e3d
--- /dev/null
+++ b/lib/pure/dynlib.nim
@@ -0,0 +1,84 @@
+#
+#
+#            Nimrod's Runtime Library
+#        (c) Copyright 2009 Andreas Rumpf
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+## This module implements the ability to access symbols from shared
+## libraries. On POSIX this uses the ``dlsym`` mechanism, on 
+## Windows ``LoadLibrary``. 
+
+type
+  TLibHandle* = pointer ## a handle to a dynamically loaded library
+
+proc LoadLib*(path: string): TLibHandle
+  ## loads a library from `path`. Returns nil if the library could not 
+  ## be loaded.
+
+proc UnloadLib*(lib: TLibHandle)
+  ## unloads the library `lib`
+
+proc symAddr*(lib: TLibHandle, name: string): pointer
+  ## retrieves the address of a procedure/variable from `lib`. Returns nil
+  ## if the symbol could not be found.
+
+proc checkedSymAddr*(lib: TLibHandle, name: string): pointer =
+  ## retrieves the address of a procedure/variable from `lib`. Raises
+  ## `EInvalidLibrary` if the symbol could not be found.
+  result = symAddr(lib, name)
+  if result == nil: 
+    var e: ref EInvalidLibrary
+    new(e)
+    e.msg = "could not find symbol: " & name
+    raise e
+
+when defined(posix):
+  #
+  # =========================================================================
+  # This is an implementation based on the dlfcn interface.
+  # The dlfcn interface is available in Linux, SunOS, Solaris, IRIX, FreeBSD,
+  # NetBSD, AIX 4.2, HPUX 11, and probably most other Unix flavors, at least
+  # as an emulation layer on top of native functions.
+  # =========================================================================
+  #
+  var
+    RTLD_NOW {.importc: "RTLD_NOW", header: "<dlfcn.h>".}: int
+
+  proc dlclose(lib: TLibHandle) {.importc, header: "<dlfcn.h>".}
+  proc dlopen(path: CString, mode: int): TLibHandle {.
+      importc, header: "<dlfcn.h>".}
+  proc dlsym(lib: TLibHandle, name: cstring): pointer {.
+      importc, header: "<dlfcn.h>".}
+
+  proc LoadLib(path: string): TLibHandle = return dlopen(path, RTLD_NOW)
+  proc UnloadLib(lib: TLibHandle) = dlclose(lib)
+  proc symAddr(lib: TLibHandle, name: string): pointer = 
+    return dlsym(lib, name)
+
+elif defined(windows) or defined(dos):
+  #
+  # =======================================================================
+  # Native Windows Implementation
+  # =======================================================================
+  #
+  type
+    THINSTANCE {.importc: "HINSTANCE".} = pointer
+
+  proc FreeLibrary(lib: THINSTANCE) {.importc, header: "<windows.h>", stdcall.}
+  proc winLoadLibrary(path: cstring): THINSTANCE {.
+      importc: "LoadLibraryA", header: "<windows.h>", stdcall.}
+  proc GetProcAddress(lib: THINSTANCE, name: cstring): pointer {.
+      importc: "GetProcAddress", header: "<windows.h>", stdcall.}
+
+  proc LoadLib(path: string): TLibHandle =
+    result = cast[TLibHandle](winLoadLibrary(path))
+  proc UnloadLib(lib: TLibHandle) = FreeLibrary(cast[THINSTANCE](lib))
+
+  proc symAddr(lib: TLibHandle, name: string): pointer =
+    result = GetProcAddress(cast[THINSTANCE](lib), name)
+
+else:
+  {.error: "no implementation for dynlib".}
diff --git a/lib/hashes.nim b/lib/pure/hashes.nim
index 1593119bd..1593119bd 100644
--- a/lib/hashes.nim
+++ b/lib/pure/hashes.nim
diff --git a/lib/lexbase.nim b/lib/pure/lexbase.nim
index bb207e92a..bb207e92a 100644
--- a/lib/lexbase.nim
+++ b/lib/pure/lexbase.nim
diff --git a/lib/macros.nim b/lib/pure/macros.nim
index 2b75a1545..ce026a832 100644
--- a/lib/macros.nim
+++ b/lib/pure/macros.nim
@@ -64,19 +64,19 @@ type
     nnkStmtListExpr, nnkBlockExpr, nnkStmtListType, nnkBlockType, 
     nnkVm, nnkTypeOfExpr, nnkObjectTy, nnkTupleTy, 
     nnkRecList, nnkRecCase, nnkRecWhen, nnkRefTy, 
-    nnkPtrTy, nnkVarTy, nnkProcTy, nnkEnumTy, 
-    nnkEnumFieldDef, nnkReturnToken
+    nnkPtrTy, nnkVarTy, nnkAbstractTy, nnkProcTy, 
+    nnkEnumTy, nnkEnumFieldDef, nnkReturnToken
   TNimNodeKinds* = set[TNimrodNodeKind]
   TNimrodTypeKind* = enum
     ntyNone, ntyBool, ntyChar, ntyEmpty, 
     ntyArrayConstr, ntyNil, ntyGeneric, ntyGenericInst, 
-    ntyGenericParam, ntyEnum, ntyAnyEnum, ntyArray, 
-    ntyObject, ntyTuple, ntySet, ntyRange, 
-    ntyPtr, ntyRef, ntyVar, ntySequence, 
-    ntyProc, ntyPointer, ntyOpenArray, ntyString, 
-    ntyCString, ntyForward, ntyInt, ntyInt8, 
-    ntyInt16, ntyInt32, ntyInt64, ntyFloat, 
-    ntyFloat32, ntyFloat64, ntyFloat128
+    ntyGenericParam, ntyAbstract, ntyEnum, ntyOrdinal, 
+    ntyArray, ntyObject, ntyTuple, ntySet, 
+    ntyRange, ntyPtr, ntyRef, ntyVar, 
+    ntySequence, ntyProc, ntyPointer, ntyOpenArray, 
+    ntyString, ntyCString, ntyForward, ntyInt, 
+    ntyInt8, ntyInt16, ntyInt32, ntyInt64, 
+    ntyFloat, ntyFloat32, ntyFloat64, ntyFloat128
   TNimTypeKinds* = set[TNimrodTypeKind]
   TNimrodSymKind* = enum
     nskUnknownSym, nskConditional, nskDynLib, nskParam, 
diff --git a/lib/math.nim b/lib/pure/math.nim
index bc180f72c..a3e57e403 100644
--- a/lib/math.nim
+++ b/lib/pure/math.nim
@@ -86,7 +86,7 @@ proc nextPowerOfTwo*(x: int): int =
 proc countBits*(n: int32): int {.noSideEffect.}
   ## counts the set bits in `n`.
 
-include cntbits
+include "system/cntbits"
 
 proc sum*[T](x: openarray[T]): T {.noSideEffect.} = 
   ## computes the sum of the elements in `x`. 
diff --git a/lib/pure/md5.nim b/lib/pure/md5.nim
new file mode 100644
index 000000000..d9bb92949
--- /dev/null
+++ b/lib/pure/md5.nim
@@ -0,0 +1,245 @@
+#
+#
+#            Nimrod's Runtime Library
+#        (c) Copyright 2009 Andreas Rumpf
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+## Module for computing MD5 checksums.
+
+type 
+  MD5State = array[0..3, int32]
+  MD5Block = array[0..15, int32]
+  MD5CBits = array[0..7, int8]
+  MD5Digest* = array[0..15, int8]
+  MD5Buffer = array[0..63, int8]
+  MD5Context* {.final.} = object 
+    State: MD5State
+    Count: array[0..1, int32]
+    Buffer: MD5Buffer
+
+const 
+  padding: cstring = "\x80\0\0\0" &
+                     "\0\0\0\0\0\0\0\0" &
+                     "\0\0\0\0\0\0\0\0" &
+                     "\0\0\0\0\0\0\0\0" &
+                     "\0\0\0\0\0\0\0\0" &
+                     "\0\0\0\0\0\0\0\0" &
+                     "\0\0\0\0\0\0\0\0" &
+                     "\0\0\0\0\0\0\0\0" &
+                     "\0\0\0\0"
+
+proc F(x, y, z: int32): int32 {.inline.} = 
+  Result = (x and y) or ((not x) and z)
+
+proc G(x, y, z: int32): int32 {.inline.} = 
+  Result = (x and z) or (y and (not z))
+
+proc H(x, y, z: int32): int32 {.inline.} = 
+  Result = x xor y xor z
+
+proc I(x, y, z: int32): int32 {.inline.} = 
+  Result = y xor (x or (not z))
+
+proc rot(x: var int32, n: int8) {.inline.} = 
+  x = toU32(x shl ze(n)) or (x shr toU32(32 -% ze(n)))
+
+proc FF(a: var int32, b, c, d, x: int32, s: int8, ac: int32) = 
+  a = a +% F(b, c, d) +% x +% ac
+  rot(a, s)
+  a = a +% b
+
+proc GG(a: var int32, b, c, d, x: int32, s: int8, ac: int32) = 
+  a = a +% G(b, c, d) +% x +% ac
+  rot(a, s)
+  a = a +% b
+
+proc HH(a: var int32, b, c, d, x: int32, s: int8, ac: int32) = 
+  a = a +% H(b, c, d) +% x +% ac
+  rot(a, s)
+  a = a +% b
+
+proc II(a: var int32, b, c, d, x: int32, s: int8, ac: int32) = 
+  a = a +% I(b, c, d) +% x +% ac
+  rot(a, s)
+  a = a +% b
+
+proc encode(dest: var MD5Block, src: cstring) = 
+  var j = 0
+  for i in 0..high(dest):
+    dest[i] = toU32(ord(src[j]) or 
+                ord(src[j+1]) shl 8 or
+                ord(src[j+2]) shl 16 or
+                ord(src[j+3]) shl 24)
+    inc(j, 4)
+
+proc decode(dest: var openarray[int8], src: openarray[int32]) = 
+  var i = 0
+  for j in 0..high(src):
+    dest[i] = toU8(src[j] and 0xff'i32)
+    dest[i+1] = toU8(src[j] shr 8'i32 and 0xff'i32)
+    dest[i+2] = toU8(src[j] shr 16'i32 and 0xff'i32)
+    dest[i+3] = toU8(src[j] shr 24'i32 and 0xff'i32)
+    inc(i, 4)
+
+proc transform(Buffer: pointer, State: var MD5State) = 
+  var
+    myBlock: MD5Block
+  encode(myBlock, cast[cstring](buffer))
+  var a = State[0]
+  var b = State[1]
+  var c = State[2]
+  var d = State[3]
+  FF(a, b, c, d, myBlock[0], 7'i8, 0xD76AA478'i32)
+  FF(d, a, b, c, myBlock[1], 12'i8, 0xE8C7B756'i32)
+  FF(c, d, a, b, myBlock[2], 17'i8, 0x242070DB'i32)
+  FF(b, c, d, a, myBlock[3], 22'i8, 0xC1BDCEEE'i32)
+  FF(a, b, c, d, myBlock[4], 7'i8, 0xF57C0FAF'i32)
+  FF(d, a, b, c, myBlock[5], 12'i8, 0x4787C62A'i32)
+  FF(c, d, a, b, myBlock[6], 17'i8, 0xA8304613'i32)
+  FF(b, c, d, a, myBlock[7], 22'i8, 0xFD469501'i32)
+  FF(a, b, c, d, myBlock[8], 7'i8, 0x698098D8'i32)
+  FF(d, a, b, c, myBlock[9], 12'i8, 0x8B44F7AF'i32)
+  FF(c, d, a, b, myBlock[10], 17'i8, 0xFFFF5BB1'i32)
+  FF(b, c, d, a, myBlock[11], 22'i8, 0x895CD7BE'i32)
+  FF(a, b, c, d, myBlock[12], 7'i8, 0x6B901122'i32)
+  FF(d, a, b, c, myBlock[13], 12'i8, 0xFD987193'i32)
+  FF(c, d, a, b, myBlock[14], 17'i8, 0xA679438E'i32)
+  FF(b, c, d, a, myBlock[15], 22'i8, 0x49B40821'i32)
+  GG(a, b, c, d, myBlock[1], 5'i8, 0xF61E2562'i32)
+  GG(d, a, b, c, myBlock[6], 9'i8, 0xC040B340'i32)
+  GG(c, d, a, b, myBlock[11], 14'i8, 0x265E5A51'i32)
+  GG(b, c, d, a, myBlock[0], 20'i8, 0xE9B6C7AA'i32)
+  GG(a, b, c, d, myBlock[5], 5'i8, 0xD62F105D'i32)
+  GG(d, a, b, c, myBlock[10], 9'i8, 0x02441453'i32)
+  GG(c, d, a, b, myBlock[15], 14'i8, 0xD8A1E681'i32)
+  GG(b, c, d, a, myBlock[4], 20'i8, 0xE7D3FBC8'i32)
+  GG(a, b, c, d, myBlock[9], 5'i8, 0x21E1CDE6'i32)
+  GG(d, a, b, c, myBlock[14], 9'i8, 0xC33707D6'i32)
+  GG(c, d, a, b, myBlock[3], 14'i8, 0xF4D50D87'i32)
+  GG(b, c, d, a, myBlock[8], 20'i8, 0x455A14ED'i32)
+  GG(a, b, c, d, myBlock[13], 5'i8, 0xA9E3E905'i32)
+  GG(d, a, b, c, myBlock[2], 9'i8, 0xFCEFA3F8'i32)
+  GG(c, d, a, b, myBlock[7], 14'i8, 0x676F02D9'i32)
+  GG(b, c, d, a, myBlock[12], 20'i8, 0x8D2A4C8A'i32)
+  HH(a, b, c, d, myBlock[5], 4'i8, 0xFFFA3942'i32)
+  HH(d, a, b, c, myBlock[8], 11'i8, 0x8771F681'i32)
+  HH(c, d, a, b, myBlock[11], 16'i8, 0x6D9D6122'i32)
+  HH(b, c, d, a, myBlock[14], 23'i8, 0xFDE5380C'i32)
+  HH(a, b, c, d, myBlock[1], 4'i8, 0xA4BEEA44'i32)
+  HH(d, a, b, c, myBlock[4], 11'i8, 0x4BDECFA9'i32)
+  HH(c, d, a, b, myBlock[7], 16'i8, 0xF6BB4B60'i32)
+  HH(b, c, d, a, myBlock[10], 23'i8, 0xBEBFBC70'i32)
+  HH(a, b, c, d, myBlock[13], 4'i8, 0x289B7EC6'i32)
+  HH(d, a, b, c, myBlock[0], 11'i8, 0xEAA127FA'i32)
+  HH(c, d, a, b, myBlock[3], 16'i8, 0xD4EF3085'i32)
+  HH(b, c, d, a, myBlock[6], 23'i8, 0x04881D05'i32)
+  HH(a, b, c, d, myBlock[9], 4'i8, 0xD9D4D039'i32)
+  HH(d, a, b, c, myBlock[12], 11'i8, 0xE6DB99E5'i32)
+  HH(c, d, a, b, myBlock[15], 16'i8, 0x1FA27CF8'i32)
+  HH(b, c, d, a, myBlock[2], 23'i8, 0xC4AC5665'i32)
+  II(a, b, c, d, myBlock[0], 6'i8, 0xF4292244'i32)
+  II(d, a, b, c, myBlock[7], 10'i8, 0x432AFF97'i32)
+  II(c, d, a, b, myBlock[14], 15'i8, 0xAB9423A7'i32)
+  II(b, c, d, a, myBlock[5], 21'i8, 0xFC93A039'i32)
+  II(a, b, c, d, myBlock[12], 6'i8, 0x655B59C3'i32)
+  II(d, a, b, c, myBlock[3], 10'i8, 0x8F0CCC92'i32)
+  II(c, d, a, b, myBlock[10], 15'i8, 0xFFEFF47D'i32)
+  II(b, c, d, a, myBlock[1], 21'i8, 0x85845DD1'i32)
+  II(a, b, c, d, myBlock[8], 6'i8, 0x6FA87E4F'i32)
+  II(d, a, b, c, myBlock[15], 10'i8, 0xFE2CE6E0'i32)
+  II(c, d, a, b, myBlock[6], 15'i8, 0xA3014314'i32)
+  II(b, c, d, a, myBlock[13], 21'i8, 0x4E0811A1'i32)
+  II(a, b, c, d, myBlock[4], 6'i8, 0xF7537E82'i32)
+  II(d, a, b, c, myBlock[11], 10'i8, 0xBD3AF235'i32)
+  II(c, d, a, b, myBlock[2], 15'i8, 0x2AD7D2BB'i32)
+  II(b, c, d, a, myBlock[9], 21'i8, 0xEB86D391'i32)
+  State[0] = State[0] +% a
+  State[1] = State[1] +% b
+  State[2] = State[2] +% c
+  State[3] = State[3] +% d
+  
+proc MD5Init*(c: var MD5Context) = 
+  ## initializes a MD5Context  
+  c.State[0] = 0x67452301'i32
+  c.State[1] = 0xEFCDAB89'i32
+  c.State[2] = 0x98BADCFE'i32
+  c.State[3] = 0x10325476'i32
+  c.Count[0] = 0'i32
+  c.Count[1] = 0'i32
+  ZeroMem(addr(c.Buffer), SizeOf(MD5Buffer))
+
+proc MD5Update*(c: var MD5Context, input: cstring, len: int) = 
+  ## updates the MD5Context with the `input` data of length `len`
+  var input = input
+  var Index = (c.Count[0] shr 3) and 0x3F
+  c.Count[0] = c.count[0] +% toU32(len shl 3)
+  if c.Count[0] < (len shl 3): c.Count[1] = c.count[1] +% 1'i32
+  c.Count[1] = c.count[1] +% toU32(len shr 29)
+  var PartLen = 64 - Index
+  if len >= PartLen: 
+    CopyMem(addr(c.Buffer[Index]), Input, PartLen)
+    transform(addr(c.Buffer), c.State)
+    var i = PartLen
+    while i + 63 < len: 
+      Transform(addr(Input[I]), c.State)
+      inc(i, 64)
+    CopyMem(addr(c.Buffer[0]), addr(Input[i]), len-i)
+  else:
+    CopyMem(addr(c.Buffer[Index]), addr(Input[0]), len)
+
+proc MD5Final*(c: var MD5Context, digest: var MD5Digest) = 
+  ## finishes the MD5Context and stores the result in `digest`
+  var
+    Bits: MD5CBits
+    PadLen: int
+  decode(bits, c.Count)
+  var Index = (c.Count[0] shr 3) and 0x3F
+  if Index < 56: PadLen = 56 - Index
+  else: PadLen = 120 - Index
+  MD5Update(c, padding, PadLen)
+  MD5Update(c, cast[cstring](addr(Bits)), 8)
+  decode(digest, c.State)
+  ZeroMem(addr(c), SizeOf(MD5Context))
+
+proc toMD5*(s: string): MD5Digest = 
+  ## computes the MD5Digest value for a string `s`
+  var c: MD5Context
+  MD5Init(c)
+  MD5Update(c, cstring(s), len(s))
+  MD5Final(c, result)
+  
+proc `$`*(D: MD5Digest): string = 
+  ## converts a MD5Digest value into its string representation
+  const digits = "0123456789abcdef"
+  result = ""
+  for i in 0..15: 
+    add(result, Digits[(D[I] shr 4) and 0xF])
+    add(result, Digits[D[I] and 0xF])
+
+proc getMD5*(s: string): string =  
+  ## computes an MD5 value of `s` and returns its string representation
+  var 
+    c: MD5Context
+    d: MD5Digest
+  MD5Init(c)
+  MD5Update(c, cstring(s), len(s))
+  MD5Final(c, d)
+  result = $d
+  
+proc `==`*(D1, D2: MD5Digest): bool =  
+  ## checks if two MD5Digest values are identical
+  for i in 0..15: 
+    if D1[i] != D2[i]: return false
+  return true
+
+when isMainModule:
+  assert(getMD5("Franz jagt im komplett verwahrlosten Taxi quer durch Bayern") ==
+    "a3cca2b2aa1e3b5b3b5aad99a8529074")
+  assert(getMD5("Frank jagt im komplett verwahrlosten Taxi quer durch Bayern") ==
+    "7e716d0e702df0505fc72e2b89467910")
+  assert($toMD5("") == "d41d8cd98f00b204e9800998ecf8427e")
+
+
diff --git a/lib/os.nim b/lib/pure/os.nim
index 20e803ec0..847117d93 100644
--- a/lib/os.nim
+++ b/lib/pure/os.nim
@@ -18,6 +18,15 @@
 import
   strutils, times
 
+when defined(windows):
+  import winlean
+elif defined(posix): 
+  import posix
+else:
+  {.error: "OS module not ported to your operating system!".}
+
+include "system/ansi_c"
+
 # copied from excpt.nim, because I don't want to make this template public
 template newException(exceptn, message: expr): expr =
   block: # open a new scope
@@ -150,200 +159,6 @@ const
     ## The character which separates the base filename from the extension;
     ## for example, the '.' in ``os.nim``.
 
-proc getApplicationDir*(): string {.noSideEffect.}
-  ## Returns the directory of the application's executable.
-
-proc getApplicationFilename*(): string {.noSideEffect.}
-  ## Returns the filename of the application's executable.
-
-proc getCurrentDir*(): string {.noSideEffect.}
-  ## Returns the current working directory.
-
-proc setCurrentDir*(newDir: string) {.inline.}
-  ## Sets the current working directory; `EOS` is raised if
-  ## `newDir` cannot been set.
-
-proc getHomeDir*(): string {.noSideEffect.}
-  ## Returns the home directory of the current user.
-
-proc getConfigDir*(): string {.noSideEffect.}
-  ## Returns the config directory of the current user for applications.
-
-proc expandFilename*(filename: string): string
-  ## Returns the full path of `filename`, raises EOS in case of an error.
-
-proc ExistsFile*(filename: string): bool
-  ## Returns true if the file exists, false otherwise.
-
-proc JoinPath*(head, tail: string): string {.noSideEffect.}
-  ## Joins two directory names to one.
-  ##
-  ## For example on Unix:
-  ##
-  ## ..code-block:: nimrod
-  ##   JoinPath("usr", "lib")
-  ##
-  ## results in:
-  ##
-  ## ..code-block:: nimrod
-  ##   "usr/lib"
-  ##
-  ## If head is the empty string, tail is returned.
-  ## If tail is the empty string, head is returned.
-
-proc `/` * (head, tail: string): string {.noSideEffect.} =
-  ## The same as ``joinPath(head, tail)``
-  return joinPath(head, tail)
-
-proc JoinPath*(parts: openarray[string]): string {.noSideEffect.}
-  ## The same as `JoinPath(head, tail)`, but works with any number
-  ## of directory parts.
-
-proc SplitPath*(path: string, head, tail: var string) {.noSideEffect.}
-  ## Splits a directory into (head, tail), so that
-  ## ``JoinPath(head, tail) == path``.
-  ##
-  ## Example: After ``SplitPath("usr/local/bin", head, tail)``,
-  ## `head` is "usr/local" and `tail` is "bin".
-  ## Example: After ``SplitPath("usr/local/bin/", head, tail)``,
-  ## `head` is "usr/local/bin" and `tail` is "".
-
-proc parentDir*(path: string): string {.noSideEffect.}
-  ## Returns the parent directory of `path`.
-  ##
-  ## This is often the same as the ``head`` result of ``splitPath``.
-  ## If there is no parent, ``path`` is returned.
-  ## Example: ``parentDir("/usr/local/bin") == "/usr/local"``.
-  ## Example: ``parentDir("/usr/local/bin/") == "/usr/local"``.
-
-proc `/../` * (head, tail: string): string {.noSideEffect.} =
-  ## The same as ``parentDir(head) / tail``
-  return parentDir(head) / tail
-
-proc UnixToNativePath*(path: string): string {.noSideEffect.}
-  ## Converts an UNIX-like path to a native one.
-  ##
-  ## On an UNIX system this does nothing. Else it converts
-  ## '/', '.', '..' to the appropriate things.
-
-proc SplitFilename*(filename: string, name, extension: var string) {.
-  noSideEffect.}
-  ## Splits a filename into (name, extension), so that
-  ## ``name & extension == filename``.
-  ##
-  ## Example: After ``SplitFilename("usr/local/nimrodc.html", name, ext)``,
-  ## `name` is "usr/local/nimrodc" and `ext` is ".html".
-  ## It the file has no extension, extention is the empty string.
-
-proc extractDir*(path: string): string {.noSideEffect.}
-  ## Extracts the directory of a given path. This is almost the
-  ## same as the `head` result of `splitPath`, except that
-  ## ``extractDir("/usr/lib/") == "/usr/lib/"``.
-
-proc extractFilename*(path: string): string {.noSideEffect.}
-  ## Extracts the filename of a given `path`. This is almost the
-  ## same as the `tail` result of `splitPath`, except that
-  ## ``extractFilename("/usr/lib/") == ""``.
-
-proc extractFileExt*(filename: string): string {.noSideEffect.} =
-  ## Extracts the file extension of a given `filename`. This is the
-  ## same as the `extension` result of `splitFilename`.
-  var dummy: string
-  splitFilename(filename, dummy, result)
-
-proc extractFileTrunk*(filename: string): string {.noSideEffect.} =
-  ## Extracts the file name of a given `filename`. This removes any
-  ## directory information and the file extension.
-  var dummy: string
-  splitFilename(extractFilename(filename), result, dummy)
-
-proc cmpPaths*(pathA, pathB: string): int {.noSideEffect.}
-  ## Compares two paths.
-  ##
-  ## On a case-sensitive filesystem this is done
-  ## case-sensitively otherwise case-insensitively. Returns:
-  ##
-  ## | 0 iff pathA == pathB
-  ## | < 0 iff pathA < pathB
-  ## | > 0 iff pathA > pathB
-
-proc AppendFileExt*(filename, ext: string): string {.noSideEffect.}
-  ## Appends the file extension `ext` to the `filename`, even if
-  ## the `filename` already has an extension.
-  ##
-  ## `Ext` should be given without the leading '.', because some
-  ## filesystems may use a different character.
-  ## (Although I know of none such beast.)
-
-proc ChangeFileExt*(filename, ext: string): string {.noSideEffect.}
-  ## Changes the file extension to `ext`.
-  ##
-  ## If the `filename` has no extension, `ext` will be added.
-  ## If `ext` == "" then the filename will get no extension.
-  ## `Ext` should be given without the leading '.', because some
-  ## filesystems may use a different character. (Although I know
-  ## of none such beast.)
-
-proc executeShellCommand*(command: string): int
-  ## Executes a shell command.
-  ##
-  ## Command has the form 'program args' where args are the command
-  ## line arguments given to program. The proc returns the error code
-  ## of the shell when it has finished. The proc does not return until
-  ## the process has finished. To execute a program without having a
-  ## shell involved, use the `executeProcess` proc of the `osproc`
-  ## module.
-
-# procs operating on a high level for files:
-proc copyFile*(dest, source: string)
-  ## Copies a file from `source` to `dest`. If this fails,
-  ## `EOS` is raised.
-
-proc moveFile*(dest, source: string)
-  ## Moves a file from `source` to `dest`. If this fails, `EOS` is raised.
-
-proc removeFile*(file: string)
-  ## Removes the `file`. If this fails, `EOS` is raised.
-
-proc removeDir*(dir: string)
-  ## Removes the directory `dir` including all subdirectories or files
-  ## in `dir` (recursively). If this fails, `EOS` is raised.
-
-proc createDir*(dir: string)
-  ## Creates the directory `dir`.
-  ##
-  ## The directory may contain several
-  ## subdirectories that do not exist yet. The full path is created. If this
-  ## fails, `EOS` is raised. It does **not** fail if the path already exists
-  ## because for most usages this does not indicate an error.
-
-proc existsDir*(dir: string): bool
-  ## Returns true iff the directory `dir` exists. If `dir` is a file, false
-  ## is returned.
-
-proc getLastModificationTime*(file: string): TTime
-  ## Returns the time of the `file`'s last modification.
-
-proc fileNewer*(a, b: string): bool
-  ## Returns true if the file `a` is newer than file `b`, i.e. if `a`'s
-  ## modification time is later than `b`'s.
-
-# procs dealing with environment variables:
-proc putEnv*(key, val: string)
-  ## Sets the value of the environment variable named `key` to `val`.
-  ## If an error occurs, `EInvalidEnvVar` is raised.
-
-proc getEnv*(key: string): string
-  ## Returns the value of the environment variable named `key`.
-  ##
-  ## If the variable does not exist, "" is returned. To distinguish
-  ## whether a variable exists or it's value is just "", call
-  ## `existsEnv(key)`.
-
-proc existsEnv*(key: string): bool
-  ## Checks whether the environment variable named `key` exists.
-  ## Returns true if it exists, false otherwise.
-
 # procs dealing with command line arguments:
 proc paramCount*(): int
   ## Returns the number of command line arguments given to the
@@ -356,18 +171,6 @@ proc paramStr*(i: int): string
   ## `i` should be in the range `1..paramCount()`, else
   ## the `EOutOfIndex` exception is raised.
 
-when defined(windows):
-  proc GetLastError(): int32 {.importc, stdcall, dynlib: "kernel32".}
-  proc FormatMessageA(dwFlags: int32, lpSource: pointer,
-                      dwMessageId, dwLanguageId: int32,
-                      lpBuffer: pointer, nSize: int32,
-                      Arguments: pointer): int32 {.
-                      importc, stdcall, dynlib: "kernel32".}
-  proc LocalFree(p: pointer) {.importc, stdcall, dynlib: "kernel32".}
-
-var errno {.importc, header: "<errno.h>".}: cint ## error variable
-proc strerror(errnum: cint): cstring {.importc, header: "<string.h>".}
-
 proc OSError*(msg: string = "") {.noinline.} =
   ## raises an EOS exception with the given message ``msg``.
   ## If ``msg == ""``, the operating system's error flag
@@ -387,15 +190,17 @@ proc OSError*(msg: string = "") {.noinline.} =
             LocalFree(msgbuf)
           raise newException(EOS, m)
     if errno != 0'i32:
-      raise newException(EOS, $strerror(errno))
+      raise newException(EOS, $os.strerror(errno))
     else:
       raise newException(EOS, "unknown OS error")
   else:
     raise newException(EOS, msg)
 
-# implementation
-
-proc UnixToNativePath(path: string): string =
+proc UnixToNativePath*(path: string): string {.noSideEffect.} =
+  ## Converts an UNIX-like path to a native one.
+  ##
+  ## On an UNIX system this does nothing. Else it converts
+  ## '/', '.', '..' to the appropriate things.
   when defined(unix):
     result = path
   else:
@@ -436,151 +241,73 @@ proc UnixToNativePath(path: string): string =
         add result, path[i]
         inc(i)
 
-# interface to C library:
-
-const
-  cunder = if defined(pcc): "_" else: ""
-
-type
-  TStat {.importc: "struct " & cunder & "stat",
-          header: "<sys/stat.h>", pure.} = object
-    st_dev: int16
-    st_ino: int16
-    st_mode: int16
-    st_nlink: int16
-    st_uid: int16
-    st_gid: int16
-    st_rdev: int32
-    st_size: int32
-    st_atime: TTime
-    st_mtime: TTime
-    st_ctime: TTime
-
-
-when defined(unix):
-  var
-    EEXIST {.importc: "EEXIST", header: "<errno.h>".}: cint
-
-  proc mkdir(dir: CString, theAccess: cint): cint {.
-    importc: "mkdir", header: "<sys/stat.h>".}
-  proc realpath(name, resolved: CString): CString {.
-    importc: "realpath", header: "<stdlib.h>".}
-  proc getcwd(buf: CString, buflen: cint): CString {.
-    importc: "getcwd", header: "<unistd.h>".}
-  proc chdir(path: CString): cint {.
-    importc: "chdir", header: "<unistd.h>".}
-  proc rmdir(dir: CString): cint {.
-    importc: "rmdir", header: "<unistd.h>".}
-
-  # is in <stdlib.h>:
-  proc cputenv(env: CString): cint {.importc: "putenv", noDecl.}
-
-elif defined(windows):
-  proc GetCurrentDirectoryA(nBufferLength: int32, lpBuffer: cstring): int32 {.
-    importc, dynlib: "kernel32", stdcall.}
-  proc SetCurrentDirectoryA(lpPathName: cstring): int32 {.
-    importc, dynlib: "kernel32", stdcall.}
-  proc CreateDirectoryA(pathName: cstring, security: Pointer): int32 {.
-    importc: "CreateDirectoryA", dynlib: "kernel32", stdcall.}
-  proc RemoveDirectoryA(lpPathName: cstring): int32 {.
-    importc, dynlib: "kernel32", stdcall.}
-  proc SetEnvironmentVariableA(lpName, lpValue: cstring): int32 {.
-    stdcall, dynlib: "kernel32", importc.}
-else:
-  {.error: "os library not ported to your OS. Please help!".}
-
-
-
-when defined(unix):
-  proc free(c: cstring) {.importc: "free", nodecl.}
-    # some C procs return a buffer that has to be freed with free(),
-    # so we define it here
-  proc strlen(str: CString): int {.importc: "strlen", nodecl.}
-
-proc stat(f: CString, res: var TStat): cint {.
-  importc: cunder & "stat", header: "<time.h>".}
-  # stat is of course in ``<sys/stat.h>``, but I include
-  # time.h which is needed for stat() too. stat() needs both time.h and
-  # sys/stat.h.
-
-when defined(windows):
-  proc GetModuleFileNameA(handle: int32, buf: CString, size: int32): int32 {.
-    importc, dynlib: "kernel32", stdcall.}
-
-proc getLastModificationTime(file: string): TTime =
-  var
-    res: TStat
-  discard stat(file, res)
-  return res.st_mtime
-
-proc setCurrentDir(newDir: string) =
-  when defined(Windows):
-    if SetCurrentDirectoryA(newDir) == 0'i32: OSError()
+proc existsFile*(filename: string): bool =
+  ## Returns true if the file exists, false otherwise.
+  when defined(windows):
+    var a = GetFileAttributesA(filename)
+    if a != -1'i32:
+      result = (a and FILE_ATTRIBUTE_DIRECTORY) == 0'i32
   else:
-    if chdir(newDir) != 0'i32: OSError()
-
-when defined(linux) or defined(solaris) or defined(bsd) or defined(aix):
-  proc readlink(link, buf: cstring, size: int): int {.
-    header: "<unistd.h>", cdecl.}
-
-  proc getApplAux(procPath: string): string =
-    result = newString(256)
-    var len = readlink(procPath, result, 256)
-    if len > 256:
-      result = newString(len+1)
-      len = readlink(procPath, result, len)
-    setlen(result, len)
-
-when defined(solaris) or defined(bsd):
-  proc getpid(): int {.importc, header: "<unistd.h>", cdecl.}
-elif defined(macosx):
-  # a really hacky solution: since we like to include 2 headers we have to
-  # define two procs which in reality are the same
-  proc getExecPath1(c: cstring, size: var int32) {.
-    importc: "_NSGetExecutablePath", header: "<sys/param.h>".}
-  proc getExecPath2(c: cstring, size: var int32): bool {.
-    importc: "_NSGetExecutablePath", header: "<mach-o/dyld.h>".}
+    var res: TStat
+    return stat(filename, res) >= 0'i32 and S_ISREG(res.st_mode)
 
-proc getApplicationFilename(): string =
-  # Linux: /proc/<pid>/exe
-  # Solaris:
-  # /proc/<pid>/object/a.out (filename only)
-  # /proc/<pid>/path/a.out (complete pathname)
-  # *BSD (and maybe Darwin too):
-  # /proc/<pid>/file
+proc existsDir*(dir: string): bool =
+  ## Returns true iff the directory `dir` exists. If `dir` is a file, false
+  ## is returned.
   when defined(windows):
-    result = newString(256)
-    var len = getModuleFileNameA(0, result, 256)
-    setlen(result, int(len))
-  elif defined(linux) or defined(aix):
-    result = getApplAux("/proc/self/exe")
-  elif defined(solaris):
-    result = getApplAux("/proc/" & $getpid() & "/path/a.out")
-  elif defined(bsd):
-    result = getApplAux("/proc/" & $getpid() & "/file")
-  elif defined(macosx):
-    var size: int32
-    getExecPath1(nil, size)
-    result = newString(int(size))
-    if getExecPath2(result, size):
-      result = "" # error!
+    var a = GetFileAttributesA(dir)
+    if a != -1'i32:
+      result = (a and FILE_ATTRIBUTE_DIRECTORY) != 0'i32
   else:
-    # little heuristic that may work on other POSIX-like systems:
-    result = getEnv("_")
-    if len(result) == 0:
-      result = ParamStr(0) # POSIX guaranties that this contains the executable
-                           # as it has been executed by the calling process
-      if len(result) > 0 and result[0] != DirSep: # not an absolute path?
-        # iterate over any path in the $PATH environment variable
-        for p in split(getEnv("PATH"), {PathSep}):
-          var x = joinPath(p, result)
-          if ExistsFile(x): return x
+    var res: TStat
+    return stat(dir, res) >= 0'i32 and S_ISDIR(res.st_mode)
 
-proc getApplicationDir(): string =
-  var tail: string
-  splitPath(getApplicationFilename(), result, tail)
+proc getLastModificationTime*(file: string): TTime =
+  ## Returns the `file`'s last modification time.
+  when defined(posix):
+    var res: TStat
+    if stat(file, res) < 0'i32: OSError()
+    return res.st_mtime
+  else:
+    var f: TWIN32_Find_Data
+    var h = findfirstFileA(file, f)
+    if h == -1'i32: OSError()
+    result = winTimeToUnixTime(rdFileTime(f.ftLastWriteTime))
+    findclose(h)
+
+proc getLastAccessTime*(file: string): TTime =
+  ## Returns the `file`'s last read or write access time.
+  when defined(posix):
+    var res: TStat
+    if stat(file, res) < 0'i32: OSError()
+    return res.st_atime
+  else:
+    var f: TWIN32_Find_Data
+    var h = findfirstFileA(file, f)
+    if h == -1'i32: OSError()
+    result = winTimeToUnixTime(rdFileTime(f.ftLastAccessTime))
+    findclose(h)
+
+proc getCreationTime*(file: string): TTime = 
+  ## Returns the `file`'s creation time.
+  when defined(posix):
+    var res: TStat
+    if stat(file, res) < 0'i32: OSError()
+    return res.st_ctime
+  else:
+    var f: TWIN32_Find_Data
+    var h = findfirstFileA(file, f)
+    if h == -1'i32: OSError()
+    result = winTimeToUnixTime(rdFileTime(f.ftCreationTime))
+    findclose(h)
 
-proc getCurrentDir(): string =
+proc fileNewer*(a, b: string): bool =
+  ## Returns true if the file `a` is newer than file `b`, i.e. if `a`'s
+  ## modification time is later than `b`'s.
+  result = getLastModificationTime(a) - getLastModificationTime(b) > 0
+
+proc getCurrentDir*(): string =
+  ## Returns the current working directory.
   const bufsize = 512 # should be enough
   result = newString(bufsize)
   when defined(windows):
@@ -589,11 +316,33 @@ proc getCurrentDir(): string =
     setLen(result, L)
   else:
     if getcwd(result, bufsize) != nil:
-      setlen(result, strlen(result))
+      setlen(result, c_strlen(result))
     else:
       OSError()
 
-proc JoinPath(head, tail: string): string =
+proc setCurrentDir*(newDir: string) {.inline.} =
+  ## Sets the current working directory; `EOS` is raised if
+  ## `newDir` cannot been set.
+  when defined(Windows):
+    if SetCurrentDirectoryA(newDir) == 0'i32: OSError()
+  else:
+    if chdir(newDir) != 0'i32: OSError()
+
+proc JoinPath*(head, tail: string): string {.noSideEffect.} =
+  ## Joins two directory names to one.
+  ##
+  ## For example on Unix:
+  ##
+  ## ..code-block:: nimrod
+  ##   JoinPath("usr", "lib")
+  ##
+  ## results in:
+  ##
+  ## ..code-block:: nimrod
+  ##   "usr/lib"
+  ##
+  ## If head is the empty string, tail is returned.
+  ## If tail is the empty string, head is returned.
   if len(head) == 0:
     result = tail
   elif head[len(head)-1] in {DirSep, AltSep}:
@@ -607,41 +356,67 @@ proc JoinPath(head, tail: string): string =
     else:
       result = head & DirSep & tail
 
-proc JoinPath(parts: openarray[string]): string =
+proc JoinPath*(parts: openarray[string]): string {.noSideEffect.} =
+  ## The same as `JoinPath(head, tail)`, but works with any number
+  ## of directory parts.
   result = parts[0]
   for i in 1..high(parts):
     result = JoinPath(result, parts[i])
 
-proc parentDir(path: string): string =
+proc `/` * (head, tail: string): string {.noSideEffect.} =
+  ## The same as ``joinPath(head, tail)``
+  return joinPath(head, tail)
+
+proc SplitPath*(path: string, head, tail: var string) {.noSideEffect.} =
+  ## Splits a directory into (head, tail), so that
+  ## ``JoinPath(head, tail) == path``.
+  ##
+  ## Example: After ``SplitPath("usr/local/bin", head, tail)``,
+  ## `head` is "usr/local" and `tail` is "bin".
+  ## Example: After ``SplitPath("usr/local/bin/", head, tail)``,
+  ## `head` is "usr/local/bin" and `tail` is "".
   var
     sepPos = -1
-    q = 1
-  if path[len(path)-1] in {dirsep, altsep}:
-    q = 2
-  for i in countdown(len(path)-q, 0):
+  for i in countdown(len(path)-1, 0):
     if path[i] in {dirsep, altsep}:
       sepPos = i
       break
   if sepPos >= 0:
-    result = copy(path, 0, sepPos-1)
+    head = copy(path, 0, sepPos-1)
+    tail = copy(path, sepPos+1)
   else:
-    result = path
+    head = ""
+    tail = path # make a string copy here
 
-proc SplitPath(path: string, head, tail: var string) =
+proc parentDir*(path: string): string {.noSideEffect.} =
+  ## Returns the parent directory of `path`.
+  ##
+  ## This is often the same as the ``head`` result of ``splitPath``.
+  ## If there is no parent, ``path`` is returned.
+  ## Example: ``parentDir("/usr/local/bin") == "/usr/local"``.
+  ## Example: ``parentDir("/usr/local/bin/") == "/usr/local"``.
   var
     sepPos = -1
-  for i in countdown(len(path)-1, 0):
+    q = 1
+  if path[len(path)-1] in {dirsep, altsep}:
+    q = 2
+  for i in countdown(len(path)-q, 0):
     if path[i] in {dirsep, altsep}:
       sepPos = i
       break
   if sepPos >= 0:
-    head = copy(path, 0, sepPos-1)
-    tail = copy(path, sepPos+1)
+    result = copy(path, 0, sepPos-1)
   else:
-    head = ""
-    tail = path # make a string copy here
+    result = path
+
+proc `/../` * (head, tail: string): string {.noSideEffect.} =
+  ## The same as ``parentDir(head) / tail``
+  return parentDir(head) / tail
+
+proc normExt(ext: string): string =
+  if ext == "" or ext[0] == extSep: result = ext # no copy needed here
+  else: result = extSep & ext
 
-# helper:
 proc searchExtPos(s: string): int =
   result = -1
   for i in countdown(len(s)-1, 0):
@@ -651,7 +426,48 @@ proc searchExtPos(s: string): int =
     elif s[i] in {dirsep, altsep}:
       break # do not skip over path
 
-proc SplitFilename(filename: string, name, extension: var string) =
+proc extractDir*(path: string): string {.noSideEffect.} =
+  ## Extracts the directory of a given path. This is almost the
+  ## same as the `head` result of `splitPath`, except that
+  ## ``extractDir("/usr/lib/") == "/usr/lib/"``.
+  if path.len == 0 or path[path.len-1] in {dirSep, altSep}:
+    result = path
+  else:
+    var tail: string
+    splitPath(path, result, tail)
+
+proc extractFilename*(path: string): string {.noSideEffect.} =
+  ## Extracts the filename of a given `path`. This is almost the
+  ## same as the `tail` result of `splitPath`, except that
+  ## ``extractFilename("/usr/lib/") == ""``.
+  if path.len == 0 or path[path.len-1] in {dirSep, altSep}:
+    result = ""
+  else:
+    var head: string
+    splitPath(path, head, result)
+
+proc expandFilename*(filename: string): string =
+  ## Returns the full path of `filename`, raises EOS in case of an error.
+  when defined(windows):
+    var unused: cstring
+    result = newString(3072)
+    var L = GetFullPathNameA(filename, 3072'i32, result, unused)
+    if L <= 0'i32 or L >= 3072'i32: OSError()
+    setLen(result, L)
+  else:
+    var res = realpath(filename, nil)
+    if res == nil: OSError()
+    result = $res
+    c_free(res)
+
+proc SplitFilename*(filename: string, name, extension: var string) {.
+  noSideEffect.} = 
+  ## Splits a filename into (name, extension), so that
+  ## ``name & extension == filename``.
+  ##
+  ## Example: After ``SplitFilename("usr/local/nimrodc.html", name, ext)``,
+  ## `name` is "usr/local/nimrodc" and `ext` is ".html".
+  ## It the file has no extension, extention is the empty string.
   var extPos = searchExtPos(filename)
   if extPos >= 0:
     name = copy(filename, 0, extPos-1)
@@ -660,85 +476,54 @@ proc SplitFilename(filename: string, name, extension: var string) =
     name = filename # make a string copy here
     extension = ""
 
-proc normExt(ext: string): string =
-  if ext == "" or ext[0] == extSep: result = ext # no copy needed here
-  else: result = extSep & ext
+proc extractFileExt*(filename: string): string {.noSideEffect.} =
+  ## Extracts the file extension of a given `filename`. This is the
+  ## same as the `extension` result of `splitFilename`.
+  var dummy: string
+  splitFilename(filename, dummy, result)
+
+proc extractFileTrunk*(filename: string): string {.noSideEffect.} =
+  ## Extracts the file name of a given `filename`. This removes any
+  ## directory information and the file extension.
+  var dummy: string
+  splitFilename(extractFilename(filename), result, dummy)
 
-proc ChangeFileExt(filename, ext: string): string =
+proc ChangeFileExt*(filename, ext: string): string {.noSideEffect.} =
+  ## Changes the file extension to `ext`.
+  ##
+  ## If the `filename` has no extension, `ext` will be added.
+  ## If `ext` == "" then any extension is removed.
+  ## `Ext` should be given without the leading '.', because some
+  ## filesystems may use a different character. (Although I know
+  ## of none such beast.)
   var extPos = searchExtPos(filename)
   if extPos < 0: result = filename & normExt(ext)
   else: result = copy(filename, 0, extPos-1) & normExt(ext)
 
-proc AppendFileExt(filename, ext: string): string =
+proc AppendFileExt*(filename, ext: string): string {.noSideEffect.} =
+  ## Appends the file extension `ext` to `filename`, unless
+  ## `filename` already has an extension.
+  ##
+  ## `Ext` should be given without the leading '.', because some
+  ## filesystems may use a different character.
+  ## (Although I know of none such beast.)
   var extPos = searchExtPos(filename)
   if extPos < 0: result = filename & normExt(ext)
   else: result = filename #make a string copy here
 
-# some more C things:
-
-proc csystem(cmd: CString): cint {.importc: "system", noDecl.}
-  # is in <stdlib.h>!
-
-proc cgetenv(env: CString): CString {.importc: "getenv", noDecl.}
-
-when defined(windows):
-  const
-    FILE_ATTRIBUTE_DIRECTORY = 16
-    MAX_PATH = 260
-  type
-    HANDLE = int
-    FILETIME {.pure.} = object
-      dwLowDateTime: int32
-      dwHighDateTime: int32
-    TWIN32_FIND_DATA {.pure.} = object
-      dwFileAttributes: int32
-      ftCreationTime: FILETIME
-      ftLastAccessTime: FILETIME
-      ftLastWriteTime: FILETIME
-      nFileSizeHigh: int32
-      nFileSizeLow: int32
-      dwReserved0: int32
-      dwReserved1: int32
-      cFileName: array[0..(MAX_PATH) - 1, char]
-      cAlternateFileName: array[0..13, char]
-  proc FindFirstFileA(lpFileName: cstring,
-                      lpFindFileData: var TWIN32_FIND_DATA): HANDLE {.
-      stdcall, dynlib: "kernel32", importc: "FindFirstFileA".}
-  proc FindNextFileA(hFindFile: HANDLE,
-                     lpFindFileData: var TWIN32_FIND_DATA): int32 {.
-      stdcall, dynlib: "kernel32", importc: "FindNextFileA".}
-  proc FindClose(hFindFile: HANDLE) {.stdcall, dynlib: "kernel32",
-    importc: "FindClose".}
-
-  proc GetFullPathNameA(lpFileName: cstring, nBufferLength: int32,
-                        lpBuffer: cstring, lpFilePart: var cstring): int32 {.
-                        stdcall, dynlib: "kernel32", importc.}
-  proc GetFileAttributesA(lpFileName: cstring): int32 {.
-                          stdcall, dynlib: "kernel32", importc.}
-
-else:
-  type
-    TDIR {.importc: "DIR", header: "<dirent.h>", pure.} = object
-    TDirent {.importc: "struct dirent", header: "<dirent.h>", pure.} = object
-      d_name: array [0..255, char]
-
-  proc opendir(dir: cstring): ptr TDIR {.importc, header: "<dirent.h>".}
-  proc closedir(dir: ptr TDIR) {.importc, header: "<dirent.h>".}
-  proc readdir(dir: ptr TDIR): ptr TDirent {.importc, header: "<dirent.h>".}
-
-  type
-    TGlob {.importc: "glob_t", header: "<glob.h>", final, pure.} = object
-      gl_pathc: int     # count of paths matched by pattern
-      gl_pathv: cstringArray # list of matched path names
-      gl_offs: int      # slots to reserve at beginning of gl_pathv
-    PGlob = ptr TGlob
-
-  proc glob(pattern: cstring, flags: cint, errfunc: pointer,
-            pglob: PGlob): cint {.
-    importc: "glob", header: "<glob.h>".}
-
-  proc globfree(pglob: PGlob) {.
-    importc: "globfree", header: "<glob.h>".}
+proc cmpPaths*(pathA, pathB: string): int {.noSideEffect.} =
+  ## Compares two paths.
+  ##
+  ## On a case-sensitive filesystem this is done
+  ## case-sensitively otherwise case-insensitively. Returns:
+  ##
+  ## | 0 iff pathA == pathB
+  ## | < 0 iff pathA < pathB
+  ## | > 0 iff pathA > pathB
+  if FileSystemCaseSensitive:
+    result = cmp(pathA, pathB)
+  else:
+    result = cmpIgnoreCase(pathA, pathB)
 
 proc sameFile*(path1, path2: string): bool =
   ## Returns True if both pathname arguments refer to the same file or
@@ -794,20 +579,13 @@ proc sameFileContent*(path1, path2: string): bool =
   closeFile(a)
   closeFile(b)
 
-# Ansi C has these:
-proc cremove(filename: CString): cint {.importc: "remove", noDecl.}
-proc crename(oldname, newname: CString): cint {.importc: "rename", noDecl.}
-
-when defined(Windows):
-  proc CopyFileA(lpExistingFileName, lpNewFileName: CString,
-                 bFailIfExists: cint): cint {.
-    importc, stdcall, dynlib: "kernel32".}
-  proc copyFile(dest, source: string) =
+proc copyFile*(dest, source: string) =
+  ## Copies a file from `source` to `dest`. If this fails,
+  ## `EOS` is raised.
+  when defined(Windows):
     if CopyFileA(source, dest, 0'i32) == 0'i32: OSError()
-
-else:
-  # generic version of copyFile which works for any platform:
-  proc copyFile(dest, source: string) =
+  else:
+    # generic version of copyFile which works for any platform:
     const
       bufSize = 8192 # 8K buffer
     var
@@ -828,32 +606,23 @@ else:
     closeFile(s)
     closeFile(d)
 
-proc moveFile(dest, source: string) =
+proc moveFile*(dest, source: string) =
+  ## Moves a file from `source` to `dest`. If this fails, `EOS` is raised.
   if crename(source, dest) != 0'i32: OSError()
 
-proc removeFile(file: string) =
+proc removeFile*(file: string) =
+  ## Removes the `file`. If this fails, `EOS` is raised.
   if cremove(file) != 0'i32: OSError()
 
-proc removeDir(dir: string) =
-  when defined(windows):
-    if RemoveDirectoryA(dir) == 0'i32: OSError()
-  else:
-    if rmdir(dir) != 0'i32: OSError()
-
-proc rawCreateDir(dir: string) =
-  when defined(unix):
-    if mkdir(dir, 0o711) != 0'i32 and errno != EEXIST:
-      OSError()
-  else:
-    if CreateDirectoryA(dir, nil) == 0'i32 and GetLastError() != 183'i32:
-      OSError()
-
-proc createDir(dir: string) =
-  for i in 1.. dir.len-1:
-    if dir[i] in {dirsep, altsep}: rawCreateDir(copy(dir, 0, i-1))
-  rawCreateDir(dir)
-
-proc executeShellCommand(command: string): int =
+proc executeShellCommand*(command: string): int =
+  ## Executes a shell command.
+  ##
+  ## Command has the form 'program args' where args are the command
+  ## line arguments given to program. The proc returns the error code
+  ## of the shell when it has finished. The proc does not return until
+  ## the process has finished. To execute a program without having a
+  ## shell involved, use the `executeProcess` proc of the `osproc`
+  ## module.
   result = csystem(command)
 
 var
@@ -863,12 +632,8 @@ var
 when defined(windows):
   # because we support Windows GUI applications, things get really
   # messy here...
-  proc GetEnvironmentStringsA(): cstring {.
-    stdcall, dynlib: "kernel32", importc.}
-  proc FreeEnvironmentStringsA(para1: cstring): int32 {.
-    stdcall, dynlib: "kernel32", importc.}
-
-  proc strEnd(cstr: CString, c = 0): CString {.importc: "strchr", nodecl.}
+  proc strEnd(cstr: CString, c = 0'i32): CString {.
+    importc: "strchr", header: "<string.h>".}
 
   proc getEnvVarsC() =
     if not envComputed:
@@ -905,7 +670,12 @@ proc findEnvVar(key: string): int =
     if startsWith(environment[i], temp): return i
   return -1
 
-proc getEnv(key: string): string =
+proc getEnv*(key: string): string =
+  ## Returns the value of the environment variable named `key`.
+  ##
+  ## If the variable does not exist, "" is returned. To distinguish
+  ## whether a variable exists or it's value is just "", call
+  ## `existsEnv(key)`.
   var i = findEnvVar(key)
   if i >= 0:
     return copy(environment[i], find(environment[i], '=')+1)
@@ -914,19 +684,16 @@ proc getEnv(key: string): string =
     if env == nil: return ""
     result = $env
 
-proc existsEnv(key: string): bool =
+proc existsEnv*(key: string): bool =
+  ## Checks whether the environment variable named `key` exists.
+  ## Returns true if it exists, false otherwise.
   if cgetenv(key) != nil: return true
   else: return findEnvVar(key) >= 0
 
-iterator iterOverEnvironment*(): tuple[key, value: string] =
-  ## Iterate over all environments varialbes. In the first component of the
-  ## tuple is the name of the current variable stored, in the second its value.
-  getEnvVarsC()
-  for i in 0..high(environment):
-    var p = find(environment[i], '=')
-    yield (copy(environment[i], 0, p-1), copy(environment[i], p+1))
+proc putEnv*(key, val: string) =
+  ## Sets the value of the environment variable named `key` to `val`.
+  ## If an error occurs, `EInvalidEnvVar` is raised.
 
-proc putEnv(key, val: string) =
   # Note: by storing the string in the environment sequence,
   # we gurantee that we don't free the memory before the program
   # ends (this is needed for POSIX compliance). It is also needed so that
@@ -944,6 +711,14 @@ proc putEnv(key, val: string) =
     if SetEnvironmentVariableA(key, val) == 0'i32:
       OSError()
 
+iterator iterOverEnvironment*(): tuple[key, value: string] =
+  ## Iterate over all environments varialbes. In the first component of the
+  ## tuple is the name of the current variable stored, in the second its value.
+  getEnvVarsC()
+  for i in 0..high(environment):
+    var p = find(environment[i], '=')
+    yield (copy(environment[i], 0, p-1), copy(environment[i], p+1))
+
 iterator walkFiles*(pattern: string): string =
   ## Iterate over all the files that match the `pattern`.
   ##
@@ -981,11 +756,6 @@ type
     pcDirectory,          ## path refers to a directory
     pcLinkToDirectory     ## path refers to a symbolic link to a directory
 
-when defined(posix):
-  proc S_ISDIR(m: int16): bool {.importc, header: "<sys/stat.h>".}
-  proc S_ISLNK(m: int16): bool {.importc, header: "<sys/stat.h>".}
-  proc S_ISREG(m: int16): bool {.importc, header: "<sys/stat.h>".}
-
 iterator walkDir*(dir: string): tuple[kind: TPathComponent, path: string] =
   ## walks over the directory `dir` and yields for each directory or file in
   ## `dir`. The component type and full path for each item is returned.
@@ -1014,7 +784,7 @@ iterator walkDir*(dir: string): tuple[kind: TPathComponent, path: string] =
       while true:
         var k = pcFile
         if f.cFilename[0] != '.':
-          if (int(f.dwFileAttributes) and FILE_ATTRIBUTE_DIRECTORY) != 0:
+          if (f.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) != 0'i32:
             k = pcDirectory
           yield (k, dir / extractFilename($f.cFilename))
         if findnextFileA(h, f) == 0'i32: break
@@ -1034,59 +804,41 @@ iterator walkDir*(dir: string): tuple[kind: TPathComponent, path: string] =
           if S_ISDIR(s.st_mode): k = pcDirectory
           if S_ISLNK(s.st_mode): k = succ(k)
           yield (k, y)
-      closeDir(d)
-
-proc ExistsFile(filename: string): bool =
-  when defined(windows):
-    var a = GetFileAttributesA(filename)
-    if a != -1:
-      result = (a and FILE_ATTRIBUTE_DIRECTORY) == 0
-  else:
-    var res: TStat
-    return stat(filename, res) >= 0'i32 and S_ISREG(res.st_mode)
+      discard closeDir(d)
 
-proc existsDir(dir: string): bool =
+proc rawRemoveDir(dir: string) = 
   when defined(windows):
-    var a = GetFileAttributesA(dir)
-    if a != -1:
-      result = (a and FILE_ATTRIBUTE_DIRECTORY) != 0
-  else:
-    var res: TStat
-    return stat(dir, res) >= 0'i32 and S_ISDIR(res.st_mode)
-
-proc cmpPaths(pathA, pathB: string): int =
-  if FileSystemCaseSensitive:
-    result = cmp(pathA, pathB)
+    if RemoveDirectoryA(dir) == 0'i32: OSError()
   else:
-    result = cmpIgnoreCase(pathA, pathB)
+    if rmdir(dir) != 0'i32: OSError()
 
-proc extractDir(path: string): string =
-  if path.len == 0 or path[path.len-1] in {dirSep, altSep}:
-    result = path
-  else:
-    var tail: string
-    splitPath(path, result, tail)
+proc removeDir*(dir: string) =
+  ## Removes the directory `dir` including all subdirectories or files
+  ## in `dir` (recursively). If this fails, `EOS` is raised.
+  for kind, path in walkDir(dir): 
+    case kind
+    of pcFile, pcLinkToFile, pcLinkToDirectory: removeFile(path)
+    of pcDirectory: removeDir(dir)
+  rawRemoveDir(dir)
 
-proc extractFilename(path: string): string =
-  if path.len == 0 or path[path.len-1] in {dirSep, altSep}:
-    result = ""
+proc rawCreateDir(dir: string) =
+  when defined(unix):
+    if mkdir(dir, 0o711) != 0'i32 and errno != EEXIST:
+      OSError()
   else:
-    var head: string
-    splitPath(path, head, result)
+    if CreateDirectoryA(dir, nil) == 0'i32 and GetLastError() != 183'i32:
+      OSError()
 
-proc expandFilename(filename: string): string =
-  # returns the full path of 'filename'; "" on error
-  when defined(windows):
-    var unused: cstring
-    result = newString(3072)
-    var L = GetFullPathNameA(filename, 3072'i32, result, unused)
-    if L <= 0'i32 or L >= 3072'i32: OSError()
-    setLen(result, L)
-  else:
-    var res = realpath(filename, nil)
-    if res == nil: OSError()
-    result = $res
-    free(res)
+proc createDir*(dir: string) =
+  ## Creates the directory `dir`.
+  ##
+  ## The directory may contain several subdirectories that do not exist yet.
+  ## The full path is created. If this fails, `EOS` is raised. It does **not**
+  ## fail if the path already exists because for most usages this does not 
+  ## indicate an error.
+  for i in 1.. dir.len-1:
+    if dir[i] in {dirsep, altsep}: rawCreateDir(copy(dir, 0, i-1))
+  rawCreateDir(dir)
 
 proc parseCmdLine*(c: string): seq[string] =
   ## Splits a command line into several components; components are separated by
@@ -1094,8 +846,9 @@ proc parseCmdLine*(c: string): seq[string] =
   ## This proc is only occassionally useful, better use the `parseopt` module.
   result = @[]
   var i = 0
+  var a = ""
   while c[i] != '\0':
-    var a = ""
+    setLen(a, 0)
     while c[i] >= '\1' and c[i] <= ' ': inc(i) # skip whitespace
     case c[i]
     of '\'', '\"':
@@ -1111,17 +864,107 @@ proc parseCmdLine*(c: string): seq[string] =
         inc(i)
     add(result, a)
 
-when defined(windows):
-  proc GetHomeDir(): string = return getEnv("USERPROFILE") & "\\"
-  proc GetConfigDir(): string = return getEnv("APPDATA") & "\\"
+type
+  TFilePermission* = enum  ## file access permission; modelled after UNIX
+    fpUserExec,            ## execute access for the file owner
+    fpUserWrite,           ## write access for the file owner
+    fpUserRead,            ## read access for the file owner
+    fpGroupExec,           ## execute access for the group
+    fpGroupWrite,          ## write access for the group
+    fpGroupRead,           ## read access for the group
+    fpOthersExec,          ## execute access for others
+    fpOthersWrite,         ## write access for others
+    fpOthersRead           ## read access for others
+
+proc getFilePermissions*(filename: string): set[TFilePermission] =
+  ## retrives file permissions for `filename`. `OSError` is raised in case of
+  ## an error. On Windows, only the ``readonly`` flag is checked, every other
+  ## permission is available in any case.
+  when defined(posix):
+    var a: TStat
+    if stat(filename, a) < 0'i32: OSError()
+    result = {}
+    if (a.st_mode and S_IRUSR) != 0'i32: result.incl(fpUserRead)
+    if (a.st_mode and S_IWUSR) != 0'i32: result.incl(fpUserWrite)
+    if (a.st_mode and S_IXUSR) != 0'i32: result.incl(fpUserExec)
+
+    if (a.st_mode and S_IRGRP) != 0'i32: result.incl(fpGroupRead)
+    if (a.st_mode and S_IWGRP) != 0'i32: result.incl(fpGroupWrite)
+    if (a.st_mode and S_IXGRP) != 0'i32: result.incl(fpGroupExec)
+
+    if (a.st_mode and S_IROTH) != 0'i32: result.incl(fpOthersRead)
+    if (a.st_mode and S_IWOTH) != 0'i32: result.incl(fpOthersWrite)
+    if (a.st_mode and S_IXOTH) != 0'i32: result.incl(fpOthersExec)
+  else:
+    var res = GetFileAttributesA(filename)
+    if res == -1'i32: OSError()
+    if (res and FILE_ATTRIBUTE_READONLY) != 0'i32:
+      result = {fpUserExec, fpUserRead, fpGroupExec, fpGroupRead, 
+                fpOthersExec, fpOthersRead}
+    else:
+      result = {fpUserExec..fpOthersRead}
+  
+proc setFilePermissions*(filename: string, permissions: set[TFilePermission]) =
+  ## sets the file permissions for `filename`. `OSError` is raised in case of
+  ## an error. On Windows, only the ``readonly`` flag is changed, depending on
+  ## ``fpUserWrite``.
+  when defined(posix):
+    var p = 0'i32
+    if fpUserRead in permissions: p = p or S_IRUSR
+    if fpUserWrite in permissions: p = p or S_IWUSR
+    if fpUserExec in permissions: p = p or S_IXUSR
+    
+    if fpGroupRead in permissions: p = p or S_IRGRP
+    if fpGroupWrite in permissions: p = p or S_IWGRP
+    if fpGroupExec in permissions: p = p or S_IXGRP
+    
+    if fpOthersRead in permissions: p = p or S_IROTH
+    if fpOthersWrite in permissions: p = p or S_IWOTH
+    if fpOthersExec in permissions: p = p or S_IXOTH
+    
+    if chmod(filename, p) != 0: OSError()
+  else:
+    var res = GetFileAttributesA(filename)
+    if res == -1'i32: OSError()
+    if fpUserWrite in permissions: 
+      res = res and not FILE_ATTRIBUTE_READONLY
+    else:
+      res = res or FILE_ATTRIBUTE_READONLY
+    if SetFileAttributesA(filename, res) != 0'i32: 
+      OSError()
+  
+proc inclFilePermissions*(filename: string, 
+                          permissions: set[TFilePermission]) =
+  ## a convenience procedure for: 
+  ##
+  ## .. code-block:: nimrod
+  ##   setFilePermissions(filename, getFilePermissions(filename)+permissions)
+  setFilePermissions(filename, getFilePermissions(filename)+permissions)
 
+proc exclFilePermissions*(filename: string, 
+                          permissions: set[TFilePermission]) =
+  ## a convenience procedure for: 
+  ##
+  ## .. code-block:: nimrod
+  ##   setFilePermissions(filename, getFilePermissions(filename)-permissions)
+  setFilePermissions(filename, getFilePermissions(filename)-permissions)
+
+proc getHomeDir*(): string =
+  ## Returns the home directory of the current user.
+  when defined(windows): return getEnv("USERPROFILE") & "\\"
+  else: return getEnv("HOME") & "/"
+
+proc getConfigDir*(): string {.noSideEffect.} =
+  ## Returns the config directory of the current user for applications.
+  when defined(windows): return getEnv("APPDATA") & "\\"
+  else: return getEnv("HOME") & "/.config/"
+
+when defined(windows):
   # Since we support GUI applications with Nimrod, we sometimes generate
   # a WinMain entry proc. But a WinMain proc has no access to the parsed
   # command line arguments. The way to get them differs. Thus we parse them
   # ourselves. This has the additional benefit that the program's behaviour
   # is always the same -- independent of the used C compiler.
-  proc GetCommandLineA(): CString {.importc, stdcall, dynlib: "kernel32".}
-
   var
     ownArgv: seq[string]
 
@@ -1134,9 +977,6 @@ when defined(windows):
     result = ownArgv.len-1
 
 else:
-  proc GetHomeDir(): string = return getEnv("HOME") & "/"
-  proc GetConfigDir(): string = return getEnv("HOME") & "/.config/"
-
   var
     cmdCount {.importc: "cmdCount".}: cint
     cmdLine {.importc: "cmdLine".}: cstringArray
@@ -1147,7 +987,63 @@ else:
 
   proc paramCount(): int = return cmdCount-1
 
-proc fileNewer(a, b: string): bool =
-  result = getLastModificationTime(a) - getLastModificationTime(b) > 0
+when defined(linux) or defined(solaris) or defined(bsd) or defined(aix):
+  proc getApplAux(procPath: string): string =
+    result = newString(256)
+    var len = readlink(procPath, result, 256)
+    if len > 256:
+      result = newString(len+1)
+      len = readlink(procPath, result, len)
+    setlen(result, len)
+
+when defined(macosx):
+  # a really hacky solution: since we like to include 2 headers we have to
+  # define two procs which in reality are the same
+  proc getExecPath1(c: cstring, size: var int32) {.
+    importc: "_NSGetExecutablePath", header: "<sys/param.h>".}
+  proc getExecPath2(c: cstring, size: var int32): bool {.
+    importc: "_NSGetExecutablePath", header: "<mach-o/dyld.h>".}
+
+proc getApplicationFilename*(): string =
+  ## Returns the filename of the application's executable.
+
+  # Linux: /proc/<pid>/exe
+  # Solaris:
+  # /proc/<pid>/object/a.out (filename only)
+  # /proc/<pid>/path/a.out (complete pathname)
+  # *BSD (and maybe Darwin too):
+  # /proc/<pid>/file
+  when defined(windows):
+    result = newString(256)
+    var len = getModuleFileNameA(0, result, 256)
+    setlen(result, int(len))
+  elif defined(linux) or defined(aix):
+    result = getApplAux("/proc/self/exe")
+  elif defined(solaris):
+    result = getApplAux("/proc/" & $getpid() & "/path/a.out")
+  elif defined(bsd):
+    result = getApplAux("/proc/" & $getpid() & "/file")
+  elif defined(macosx):
+    var size: int32
+    getExecPath1(nil, size)
+    result = newString(int(size))
+    if getExecPath2(result, size):
+      result = "" # error!
+  else:
+    # little heuristic that may work on other POSIX-like systems:
+    result = getEnv("_")
+    if len(result) == 0:
+      result = ParamStr(0) # POSIX guaranties that this contains the executable
+                           # as it has been executed by the calling process
+      if len(result) > 0 and result[0] != DirSep: # not an absolute path?
+        # iterate over any path in the $PATH environment variable
+        for p in split(getEnv("PATH"), {PathSep}):
+          var x = joinPath(p, result)
+          if ExistsFile(x): return x
+
+proc getApplicationDir*(): string =
+  ## Returns the directory of the application's executable.
+  var tail: string
+  splitPath(getApplicationFilename(), result, tail)
 
 {.pop.}
diff --git a/lib/osproc.nim b/lib/pure/osproc.nim
index 205460614..205460614 100644
--- a/lib/osproc.nim
+++ b/lib/pure/osproc.nim
diff --git a/lib/parsecfg.nim b/lib/pure/parsecfg.nim
index 29ba8b4ad..5704f591c 100644
--- a/lib/parsecfg.nim
+++ b/lib/pure/parsecfg.nim
@@ -198,6 +198,7 @@ proc getString(c: var TCfgParser, tok: var TToken, rawMode: bool) =
     inc(pos, 2)               # skip ""
                               # skip leading newline:
     pos = HandleCRLF(c, pos)
+    buf = c.buf
     while true: 
       case buf[pos]
       of '\"': 
@@ -206,6 +207,7 @@ proc getString(c: var TCfgParser, tok: var TToken, rawMode: bool) =
         Inc(pos)
       of '\c', '\L': 
         pos = HandleCRLF(c, pos)
+        buf = c.buf
         add(tok.literal, nl)
       of lexbase.EndOfFile: 
         tok.kind = tkInvalid
@@ -254,6 +256,7 @@ proc skip(c: var TCfgParser) =
       while not (buf[pos] in {'\c', '\L', lexbase.EndOfFile}): inc(pos)
     of '\c', '\L': 
       pos = HandleCRLF(c, pos)
+      buf = c.buf
     else: 
       break                   # EndOfFile also leaves the loop
   c.bufpos = pos
diff --git a/lib/parsecsv.nim b/lib/pure/parsecsv.nim
index 7665c8287..5970f2090 100644
--- a/lib/parsecsv.nim
+++ b/lib/pure/parsecsv.nim
@@ -103,9 +103,11 @@ proc parseField(my: var TCsvParser, a: var string) =
         case c
         of '\c': 
           pos = handleCR(my, pos)
+          buf = my.buf
           add(a, "\n")
         of '\l': 
           pos = handleLF(my, pos)
+          buf = my.buf
           add(a, "\n")
         else:
           add(a, c)
diff --git a/lib/parseopt.nim b/lib/pure/parseopt.nim
index 12060ba70..12060ba70 100644
--- a/lib/parseopt.nim
+++ b/lib/pure/parseopt.nim
diff --git a/lib/pure/parsesql.nim b/lib/pure/parsesql.nim
new file mode 100644
index 000000000..112e79a09
--- /dev/null
+++ b/lib/pure/parsesql.nim
@@ -0,0 +1,1333 @@
+#
+#
+#            Nimrod's Runtime Library
+#        (c) Copyright 2009 Andreas Rumpf
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+## The ``parsesql`` module implements a high performance SQL file 
+## parser. It parses PostgreSQL syntax and the SQL ANSI standard.
+
+import 
+  hashes, strutils, lexbase, streams
+
+# ------------------- scanner -------------------------------------------------
+
+type
+  TTokKind = enum       ## enumeration of all SQL tokens
+    tkInvalid,          ## invalid token
+    tkEof,              ## end of file reached
+    tkIdentifier,       ## abc
+    tkQuotedIdentifier, ## "abc"
+    tkStringConstant,   ## 'abc'
+    tkEscapeConstant,       ## e'abc'
+    tkDollarQuotedConstant, ## $tag$abc$tag$
+    tkBitStringConstant,    ## B'00011'
+    tkHexStringConstant,    ## x'00011'
+    tkInteger,
+    tkNumeric,
+    tkOperator,             ## + - * / < > = ~ ! @ # % ^ & | ` ?
+    tkSemicolon,            ## ';'
+    tkColon,                ## ':'
+    tkComma,                ## ','
+    tkParLe,                ## '('
+    tkParRi,                ## ')'
+    tkBracketLe,            ## '['
+    tkBracketRi,            ## ']'
+    tkDot                   ## '.'
+  
+  TToken {.final.} = object  # a token
+    kind: TTokKind           # the type of the token
+    literal: string          # the parsed (string) literal
+  
+  TSqlLexer* = object of TBaseLexer ## the parser object.
+    filename: string
+
+const
+  tokKindToStr: array[TTokKind, string] = [
+    "invalid", "[EOF]", "identifier", "quoted identifier", "string constant",
+    "escape string constant", "dollar quoted constant", "bit string constant",
+    "hex string constant", "integer constant", "numeric constant", "operator",
+    ";", ":", ",", "(", ")", "[", "]", "."
+  ]
+
+proc open(L: var TSqlLexer, input: PStream, filename: string) = 
+  lexbase.open(L, input)
+  L.filename = filename
+  
+proc close(L: var TSqlLexer) = 
+  lexbase.close(L)
+
+proc getColumn(L: TSqlLexer): int = 
+  ## get the current column the parser has arrived at.
+  result = getColNumber(L, L.bufPos)
+
+proc getLine(L: TSqlLexer): int = 
+  result = L.linenumber
+
+proc handleHexChar(c: var TSqlLexer, xi: var int) = 
+  case c.buf[c.bufpos]
+  of '0'..'9': 
+    xi = (xi shl 4) or (ord(c.buf[c.bufpos]) - ord('0'))
+    inc(c.bufpos)
+  of 'a'..'f': 
+    xi = (xi shl 4) or (ord(c.buf[c.bufpos]) - ord('a') + 10)
+    inc(c.bufpos)
+  of 'A'..'F': 
+    xi = (xi shl 4) or (ord(c.buf[c.bufpos]) - ord('A') + 10)
+    inc(c.bufpos)
+  else: 
+    nil
+
+proc handleOctChar(c: var TSqlLexer, xi: var int) = 
+  if c.buf[c.bufpos] in {'0'..'7'}:
+    xi = (xi shl 3) or (ord(c.buf[c.bufpos]) - ord('0'))
+    inc(c.bufpos)
+
+proc getEscapedChar(c: var TSqlLexer, tok: var TToken) = 
+  inc(c.bufpos)
+  case c.buf[c.bufpos]
+  of 'n', 'N': 
+    add(tok.literal, '\L')
+    Inc(c.bufpos)
+  of 'r', 'R', 'c', 'C': 
+    add(tok.literal, '\c')
+    Inc(c.bufpos)
+  of 'l', 'L': 
+    add(tok.literal, '\L')
+    Inc(c.bufpos)
+  of 'f', 'F': 
+    add(tok.literal, '\f')
+    inc(c.bufpos)
+  of 'e', 'E': 
+    add(tok.literal, '\e')
+    Inc(c.bufpos)
+  of 'a', 'A': 
+    add(tok.literal, '\a')
+    Inc(c.bufpos)
+  of 'b', 'B': 
+    add(tok.literal, '\b')
+    Inc(c.bufpos)
+  of 'v', 'V': 
+    add(tok.literal, '\v')
+    Inc(c.bufpos)
+  of 't', 'T': 
+    add(tok.literal, '\t')
+    Inc(c.bufpos)
+  of '\'', '\"': 
+    add(tok.literal, c.buf[c.bufpos])
+    Inc(c.bufpos)
+  of '\\': 
+    add(tok.literal, '\\')
+    Inc(c.bufpos)
+  of 'x', 'X': 
+    inc(c.bufpos)
+    var xi = 0
+    handleHexChar(c, xi)
+    handleHexChar(c, xi)
+    add(tok.literal, Chr(xi))
+  of '0'..'7': 
+    var xi = 0
+    handleOctChar(c, xi)
+    handleOctChar(c, xi)
+    handleOctChar(c, xi)
+    if (xi <= 255): add(tok.literal, Chr(xi))
+    else: tok.kind = tkInvalid
+  else: tok.kind = tkInvalid
+  
+proc HandleCRLF(c: var TSqlLexer, pos: int): int = 
+  case c.buf[pos]
+  of '\c': result = lexbase.HandleCR(c, pos)
+  of '\L': result = lexbase.HandleLF(c, pos)
+  else: result = pos
+
+proc skip(c: var TSqlLexer) = 
+  var pos = c.bufpos
+  var buf = c.buf
+  var nested = 0
+  while true: 
+    case buf[pos]
+    of ' ', '\t': 
+      Inc(pos)
+    of '-':
+      if buf[pos+1] == '-':
+        while not (buf[pos] in {'\c', '\L', lexbase.EndOfFile}): inc(pos)
+      else:
+        break
+    of '/':
+      if buf[pos+1] == '*':
+        inc(pos,2)
+        while true:
+          case buf[pos]
+          of '\0': break
+          of '\c', '\L': 
+            pos = HandleCRLF(c, pos)
+            buf = c.buf
+          of '*':
+            if buf[pos+1] == '/':
+              inc(pos, 2)
+              if nested <= 0: break
+              dec(nested)
+            else:
+              inc(pos)
+          of '/':
+            if buf[pos+1] == '*':
+              inc(pos, 2)
+              inc(nested)
+            else:
+              inc(pos)
+          else: inc(pos)
+      else: break
+    of '\c', '\L': 
+      pos = HandleCRLF(c, pos)
+      buf = c.buf
+    else: 
+      break                   # EndOfFile also leaves the loop
+  c.bufpos = pos
+  
+proc getString(c: var TSqlLexer, tok: var TToken, kind: TTokKind) = 
+  var pos = c.bufPos + 1
+  var buf = c.buf
+  tok.kind = kind
+  block parseLoop:
+    while true:
+      while true: 
+        var ch = buf[pos]
+        if ch == '\'':
+          if buf[pos+1] == '\'':
+            inc(pos, 2)
+            add(tok.literal, '\'')
+          else:
+            inc(pos)
+            break 
+        elif ch in {'\c', '\L', lexbase.EndOfFile}: 
+          tok.kind = tkInvalid
+          break parseLoop
+        elif (ch == '\\') and kind == tkEscapeConstant: 
+          c.bufPos = pos
+          getEscapedChar(c, tok)
+          pos = c.bufPos
+        else: 
+          add(tok.literal, ch)
+          Inc(pos)
+      c.bufpos = pos
+      var line = c.linenumber
+      skip(c)
+      if c.linenumber > line:
+        # a new line whitespace has been parsed, so we check if the string
+        # continues after the whitespace:
+        buf = c.buf # may have been reallocated
+        pos = c.bufpos
+        if buf[pos] == '\'': inc(pos)
+        else: break parseLoop
+      else: break parseLoop
+  c.bufpos = pos
+
+proc getDollarString(c: var TSqlLexer, tok: var TToken) = 
+  var pos = c.bufPos + 1
+  var buf = c.buf
+  tok.kind = tkDollarQuotedConstant
+  var tag = "$"
+  while buf[pos] in IdentChars:
+    add(tag, buf[pos])
+    inc(pos)
+  if buf[pos] == '$': inc(pos)
+  else:
+    tok.kind = tkInvalid
+    return
+  while true:
+    case buf[pos]
+    of '\c', '\L': 
+      pos = HandleCRLF(c, pos)
+      buf = c.buf
+      add(tok.literal, "\L")
+    of '\0':
+      tok.kind = tkInvalid
+      break
+    of '$':
+      inc(pos)
+      var tag2 = "$"
+      while buf[pos] in IdentChars:
+        add(tag2, buf[pos])
+        inc(pos)
+      if buf[pos] == '$': inc(pos)
+      if tag2 == tag: break
+      add(tok.literal, tag2)
+      add(tok.literal, '$')
+    else:
+      add(tok.literal, buf[pos])
+      inc(pos)
+  c.bufpos = pos
+
+proc getSymbol(c: var TSqlLexer, tok: var TToken) = 
+  var pos = c.bufpos
+  var buf = c.buf
+  while true: 
+    add(tok.literal, buf[pos])
+    Inc(pos)
+    if not (buf[pos] in {'a'..'z','A'..'Z','0'..'9','_','$', '\128'..'\255'}):
+      break
+  c.bufpos = pos
+  tok.kind = tkIdentifier
+
+proc getQuotedIdentifier(c: var TSqlLexer, tok: var TToken) = 
+  var pos = c.bufPos + 1
+  var buf = c.buf
+  tok.kind = tkQuotedIdentifier
+  while true:
+    var ch = buf[pos]
+    if ch == '\"':
+      if buf[pos+1] == '\"':
+        inc(pos, 2)
+        add(tok.literal, '\"')
+      else:
+        inc(pos)
+        break
+    elif ch in {'\c', '\L', lexbase.EndOfFile}: 
+      tok.kind = tkInvalid
+      break
+    else:
+      add(tok.literal, ch)
+      Inc(pos)
+  c.bufpos = pos
+
+proc getBitHexString(c: var TSqlLexer, tok: var TToken, validChars: TCharSet) =
+  var pos = c.bufPos + 1
+  var buf = c.buf
+  block parseLoop:
+    while true:
+      while true: 
+        var ch = buf[pos]
+        if ch in validChars:
+          add(tok.literal, ch)
+          Inc(pos)          
+        elif ch == '\'':
+          inc(pos)
+          break
+        else: 
+          tok.kind = tkInvalid
+          break parseLoop
+      c.bufpos = pos
+      var line = c.linenumber
+      skip(c)
+      if c.linenumber > line:
+        # a new line whitespace has been parsed, so we check if the string
+        # continues after the whitespace:
+        buf = c.buf # may have been reallocated
+        pos = c.bufpos
+        if buf[pos] == '\'': inc(pos)
+        else: break parseLoop
+      else: break parseLoop
+  c.bufpos = pos
+
+proc getNumeric(c: var TSqlLexer, tok: var TToken) =
+  tok.kind = tkInteger
+  var pos = c.bufPos
+  var buf = c.buf
+  while buf[pos] in Digits:
+    add(tok.literal, buf[pos])
+    inc(pos)
+  if buf[pos] == '.':
+    tok.kind = tkNumeric
+    add(tok.literal, buf[pos])
+    inc(pos)
+    while buf[pos] in Digits:
+      add(tok.literal, buf[pos])
+      inc(pos)
+  if buf[pos] in {'E', 'e'}:
+    tok.kind = tkNumeric
+    add(tok.literal, buf[pos])
+    inc(pos)
+    if buf[pos] == '+':
+      inc(pos)
+    elif buf[pos] == '-':
+      add(tok.literal, buf[pos])
+      inc(pos)
+    if buf[pos] in Digits:
+      while buf[pos] in Digits:
+        add(tok.literal, buf[pos])
+        inc(pos)
+    else:
+      tok.kind = tkInvalid
+  c.bufpos = pos  
+
+proc getOperator(c: var TSqlLexer, tok: var TToken) =
+  const operators = {'+', '-', '*', '/', '<', '>', '=', '~', '!', '@', '#', '%',
+                     '^', '&', '|', '`', '?'}
+  tok.kind = tkOperator
+  var pos = c.bufPos
+  var buf = c.buf
+  var trailingPlusMinus = false
+  while true:
+    case buf[pos]
+    of '-':
+      if buf[pos] == '-': break
+      if not trailingPlusMinus and buf[pos+1] notin operators and
+           tok.literal.len > 0: break
+    of '/':
+      if buf[pos] == '*': break
+    of '~', '!', '@', '#', '%', '^', '&', '|', '`', '?':
+      trailingPlusMinus = true
+    of '+':
+      if not trailingPlusMinus and buf[pos+1] notin operators and
+           tok.literal.len > 0: break
+    of '*', '<', '>', '=': nil
+    else: break
+    add(tok.literal, buf[pos])
+    inc(pos)
+  c.bufpos = pos
+
+proc getTok(c: var TSqlLexer, tok: var TToken) = 
+  tok.kind = tkInvalid
+  setlen(tok.literal, 0)
+  skip(c)
+  case c.buf[c.bufpos]
+  of ';': 
+    tok.kind = tkSemiColon
+    inc(c.bufPos)
+    add(tok.literal, ';')
+  of ',':
+    tok.kind = tkComma
+    inc(c.bufpos)
+    add(tok.literal, ',')
+  of ':': 
+    tok.kind = tkColon
+    inc(c.bufpos)
+    add(tok.literal, ':')
+  of 'e', 'E': 
+    if c.buf[c.bufPos + 1] == '\'': 
+      Inc(c.bufPos)
+      getString(c, tok, tkEscapeConstant)
+    else: 
+      getSymbol(c, tok)
+  of 'b', 'B':
+    if c.buf[c.bufPos + 1] == '\'':
+      tok.kind = tkBitStringConstant
+      getBitHexString(c, tok, {'0'..'1'})
+    else:
+      getSymbol(c, tok)
+  of 'x', 'X':
+    if c.buf[c.bufPos + 1] == '\'':
+      tok.kind = tkHexStringConstant
+      getBitHexString(c, tok, {'a'..'f','A'..'F','0'..'9'})
+    else:
+      getSymbol(c, tok)
+  of '$': getDollarString(c, tok)
+  of '[': 
+    tok.kind = tkBracketLe
+    inc(c.bufpos)
+    add(tok.literal, '[')
+  of ']': 
+    tok.kind = tkBracketRi
+    Inc(c.bufpos)
+    add(tok.literal, ']')
+  of '(':
+    tok.kind = tkParLe
+    Inc(c.bufpos)
+    add(tok.literal, '(')
+  of ')':
+    tok.kind = tkParRi
+    Inc(c.bufpos)
+    add(tok.literal, ')')
+  of '.': 
+    if c.buf[c.bufPos + 1] in Digits:
+      getNumeric(c, tok)
+    else:
+      tok.kind = tkDot
+      inc(c.bufpos)
+    add(tok.literal, '.')
+  of '0'..'9': getNumeric(c, tok)
+  of '\'': getString(c, tok, tkStringConstant)
+  of '"': getQuotedIdentifier(c, tok)
+  of lexbase.EndOfFile: 
+    tok.kind = tkEof
+    tok.literal = "[EOF]"
+  of 'a', 'c', 'd', 'f'..'w', 'y', 'z', 'A', 'C', 'D', 'F'..'W', 'Y', 'Z', '_',
+     '\128'..'\255':
+    getSymbol(c, tok)
+  of '+', '-', '*', '/', '<', '>', '=', '~', '!', '@', '#', '%',
+     '^', '&', '|', '`', '?':
+    getOperator(c, tok)
+  else:
+    add(tok.literal, c.buf[c.bufpos])
+    inc(c.bufpos)
+  
+proc errorStr(L: TSqlLexer, msg: string): string = 
+  result = "$1($2, $3) Error: $4" % [L.filename, $getLine(L), $getColumn(L), msg]
+
+
+# ----------------------------- parser ----------------------------------------
+
+# Operator/Element	Associativity	Description
+# .	                left    	table/column name separator
+# ::            	left	        PostgreSQL-style typecast
+# [ ]	                left    	array element selection
+# -	                right	        unary minus
+# ^             	left	        exponentiation
+# * / %	                left	        multiplication, division, modulo
+# + -	                left	        addition, subtraction
+# IS	 	IS TRUE, IS FALSE, IS UNKNOWN, IS NULL
+# ISNULL	 	test for null
+# NOTNULL	 	test for not null
+# (any other)	        left    	all other native and user-defined oprs
+# IN	          	set membership
+# BETWEEN	 	range containment
+# OVERLAPS	 	time interval overlap
+# LIKE ILIKE SIMILAR	 	string pattern matching
+# < >	 	less than, greater than
+# =	                right	        equality, assignment
+# NOT	                right	        logical negation
+# AND	                left	        logical conjunction
+# OR              	left	        logical disjunction
+
+type
+  TSqlNodeKind* = enum
+    nkNone,
+    nkIdent,
+    nkStringLit,
+    nkBitStringLit,
+    nkHexStringLit,
+    nkIntegerLit,
+    nkNumericLit,
+    nkPrimaryKey,
+    nkForeignKey,
+    nkNotNull,
+    
+    nkStmtList,
+    nkDot,
+    nkDotDot,
+    nkPrefix,
+    nkInfix,
+    nkCall,
+    nkColumnReference,
+    nkReferences,
+    nkDefault,
+    nkCheck,
+    nkConstraint,
+    nkUnique,
+    nkIdentity,
+    nkColumnDef,        ## name, datatype, constraints
+    nkInsert,
+    nkUpdate,
+    nkDelete,
+    nkSelect,
+    nkSelectDistinct,
+    nkSelectColumns,
+    nkAsgn,
+    nkFrom,
+    nkGroup,
+    nkHaving,
+    nkOrder,
+    nkDesc,
+    nkUnion,
+    nkIntersect,
+    nkExcept,
+    nkColumnList,
+    nkValueList,
+    nkWhere,
+    nkCreateTable,
+    nkCreateTableIfNotExists, 
+    nkCreateType,
+    nkCreateTypeIfNotExists,
+    nkCreateIndex,
+    nkCreateIndexIfNotExists,
+    nkEnumDef
+    
+type
+  EInvalidSql* = object of EBase    
+  PSqlNode* = ref TSqlNode
+  TSqlNode* = object
+    case kind*: TSqlNodeKind
+    of nkIdent, nkStringLit, nkBitStringLit, nkHexStringLit,
+                nkIntegerLit, nkNumericLit:
+      strVal*: string
+    else:
+      sons*: seq[PSqlNode]
+
+  TSqlParser = object of TSqlLexer
+    tok: TToken
+
+proc newNode(k: TSqlNodeKind): PSqlNode =
+  new(result)
+  result.kind = k
+
+proc newNode(k: TSqlNodeKind, s: string): PSqlNode =
+  new(result)
+  result.kind = k
+  result.strVal = s
+  
+proc len*(n: PSqlNode): int =
+  if isNil(n.sons): result = 0
+  else: result = n.sons.len
+  
+proc add*(father, n: PSqlNode) =
+  if isNil(father.sons): father.sons = @[]
+  add(father.sons, n)
+
+proc getTok(p: var TSqlParser) =
+  getTok(p, p.tok)
+
+proc sqlError(p: TSqlParser, msg: string) =
+  var e: ref EInvalidSql
+  e.msg = errorStr(p, msg)
+  raise e
+
+proc isKeyw(p: TSqlParser, keyw: string): bool =
+  result = p.tok.kind == tkIdentifier and
+           cmpIgnoreCase(p.tok.literal, keyw) == 0
+
+proc isOpr(p: TSqlParser, opr: string): bool =
+  result = p.tok.kind == tkOperator and
+           cmpIgnoreCase(p.tok.literal, opr) == 0
+
+proc optKeyw(p: var TSqlParser, keyw: string) =
+  if p.tok.kind == tkIdentifier and cmpIgnoreCase(p.tok.literal, keyw) == 0:
+    getTok(p)
+
+proc expectIdent(p: TSqlParser) =
+  if p.tok.kind != tkIdentifier and p.tok.kind != tkQuotedIdentifier:
+    sqlError(p, "identifier expected")
+
+proc expect(p: TSqlParser, kind: TTokKind) =
+  if p.tok.kind != kind:
+    sqlError(p, tokKindToStr[kind] & " expected")
+
+proc eat(p: var TSqlParser, kind: TTokKind) =
+  if p.tok.kind == kind:
+    getTok(p)
+  else:
+    sqlError(p, tokKindToStr[kind] & " expected")
+
+proc eat(p: var TSqlParser, keyw: string) =
+  if isKeyw(p, keyw):
+    getTok(p)
+  else:
+    sqlError(p, keyw.toUpper() & " expected")
+
+proc parseDataType(p: var TSqlParser): PSqlNode =
+  if isKeyw(p, "enum"):
+    result = newNode(nkEnumDef)
+    getTok(p)
+    if p.tok.kind == tkParLe:
+      getTok(p)
+      result.add(newNode(nkStringLit, p.tok.literal))
+      getTok(p)
+      while p.tok.kind == tkComma:
+        getTok(p)
+        result.add(newNode(nkStringLit, p.tok.literal))
+        getTok(p)
+      eat(p, tkParRi)
+  else:
+    expectIdent(p)
+    result = newNode(nkIdent, p.tok.literal)
+    getTok(p)
+    # ignore (12, 13) part:
+    if p.tok.kind == tkParLe:
+      getTok(p)
+      expect(p, tkInteger)
+      getTok(p)
+      while p.tok.kind == tkComma:
+        getTok(p)
+        expect(p, tkInteger)
+        getTok(p)
+      eat(p, tkParRi)
+
+proc getPrecedence(p: TSqlParser): int = 
+  if isOpr(p, "*") or isOpr(p, "/") or isOpr(p, "%"):
+    result = 6
+  elif isOpr(p, "+") or isOpr(p, "-"):
+    result = 5  
+  elif isOpr(p, "=") or isOpr(p, "<") or isOpr(p, ">") or isOpr(p, ">=") or
+       isOpr(p, "<=") or isOpr(p, "<>") or isOpr(p, "!=") or isKeyw(p, "is") or
+       isKeyw(p, "like"):
+    result = 3
+  elif isKeyw(p, "and"):
+    result = 2
+  elif isKeyw(p, "or"):
+    result = 1
+  elif p.tok.kind == tkOperator:
+    # user-defined operator:
+    result = 0
+  else:
+    result = - 1
+
+proc parseExpr(p: var TSqlParser): PSqlNode
+
+proc identOrLiteral(p: var TSqlParser): PSqlNode = 
+  case p.tok.kind
+  of tkIdentifier, tkQuotedIdentifier: 
+    result = newNode(nkIdent, p.tok.literal)
+    getTok(p)
+  of tkStringConstant, tkEscapeConstant, tkDollarQuotedConstant:
+    result = newNode(nkStringLit, p.tok.literal)
+    getTok(p)
+  of tkBitStringConstant:
+    result = newNode(nkBitStringLit, p.tok.literal)
+    getTok(p)
+  of tkHexStringConstant:
+    result = newNode(nkHexStringLit, p.tok.literal)
+    getTok(p)
+  of tkInteger:
+    result = newNode(nkIntegerLit, p.tok.literal)
+    getTok(p)
+  of tkNumeric:
+    result = newNode(nkNumericLit, p.tok.literal)
+    getTok(p)
+  of tkParLe:
+    getTok(p)
+    result = parseExpr(p)
+    eat(p, tkParRi)
+  else: 
+    sqlError(p, "expression expected")
+    getTok(p) # we must consume a token here to prevend endless loops!
+
+proc primary(p: var TSqlParser): PSqlNode = 
+  if p.tok.kind == tkOperator or isKeyw(p, "not"): 
+    result = newNode(nkPrefix)
+    result.add(newNode(nkIdent, p.tok.literal))
+    getTok(p)
+    result.add(primary(p))
+    return
+  result = identOrLiteral(p)
+  while true: 
+    case p.tok.kind
+    of tkParLe: 
+      var a = result
+      result = newNode(nkCall)
+      result.add(a)
+      getTok(p)
+      while true:
+        result.add(parseExpr(p))
+        if p.tok.kind == tkComma: getTok(p)
+        else: break
+      eat(p, tkParRi)
+    of tkDot: 
+      getTok(p)
+      var a = result
+      if p.tok.kind == tkDot:
+        getTok(p)
+        result = newNode(nkDotDot)
+      else:
+        result = newNode(nkDot)
+      result.add(a)
+      if isOpr(p, "*"):
+        result.add(newNode(nkIdent, "*"))
+      elif p.tok.kind in {tkIdentifier, tkQuotedIdentifier}:
+        result.add(newNode(nkIdent, p.tok.literal))
+      else:
+        sqlError(p, "identifier expected")
+      getTok(p)
+    else: break
+  
+proc lowestExprAux(p: var TSqlParser, v: var PSqlNode, limit: int): int = 
+  var
+    v2, node, opNode: PSqlNode
+  v = primary(p) # expand while operators have priorities higher than 'limit'
+  var opPred = getPrecedence(p)
+  result = opPred
+  while opPred > limit: 
+    node = newNode(nkInfix)
+    opNode = newNode(nkIdent, p.tok.literal)
+    getTok(p)
+    result = lowestExprAux(p, v2, opPred)
+    node.add(opNode)
+    node.add(v)
+    node.add(v2)
+    v = node
+    opPred = getPrecedence(p)
+  
+proc parseExpr(p: var TSqlParser): PSqlNode = 
+  discard lowestExprAux(p, result, - 1)
+
+proc parseTableName(p: var TSqlParser): PSqlNode =
+  expectIdent(p)
+  result = primary(p)
+
+proc parseColumnReference(p: var TSqlParser): PSqlNode =
+  result = parseTableName(p)
+  if p.tok.kind == tkParLe:
+    getTok(p)
+    var a = result
+    result = newNode(nkColumnReference)
+    result.add(a)
+    result.add(parseTableName(p))
+    while p.tok.kind == tkComma:
+      getTok(p)
+      result.add(parseTableName(p))
+    eat(p, tkParRi)
+
+proc parseCheck(p: var TSqlParser): PSqlNode = 
+  getTok(p)
+  result = newNode(nkCheck)
+  result.add(parseExpr(p))
+
+proc parseConstraint(p: var TSqlParser): PSqlNode =
+  getTok(p)
+  result = newNode(nkConstraint)
+  expectIdent(p)
+  result.add(newNode(nkIdent, p.tok.literal))
+  getTok(p)
+  eat(p, "check")
+  result.add(parseExpr(p))
+
+proc parseColumnConstraints(p: var TSqlParser, result: PSqlNode) =
+  while true:
+    if isKeyw(p, "default"):
+      getTok(p)
+      var n = newNode(nkDefault)
+      n.add(parseExpr(p))
+      result.add(n)
+    elif isKeyw(p, "references"):
+      getTok(p)
+      var n = newNode(nkReferences)
+      n.add(parseColumnReference(p))
+      result.add(n)
+    elif isKeyw(p, "not"):
+      getTok(p)
+      eat(p, "null")
+      result.add(newNode(nkNotNull))
+    elif isKeyw(p, "identity"):
+      getTok(p)
+      result.add(newNode(nkIdentity))
+    elif isKeyw(p, "primary"):
+      getTok(p)
+      eat(p, "key")
+      result.add(newNode(nkPrimaryKey))
+    elif isKeyw(p, "check"):
+      result.add(parseCheck(p))
+    elif isKeyw(p, "constraint"):
+      result.add(parseConstraint(p))
+    elif isKeyw(p, "unique"):
+      result.add(newNode(nkUnique))
+    else:
+      break
+
+proc parseColumnDef(p: var TSqlParser): PSqlNode =
+  expectIdent(p)
+  result = newNode(nkColumnDef)
+  result.add(newNode(nkIdent, p.tok.literal))
+  getTok(p)
+  result.add(parseDataType(p))
+  parseColumnConstraints(p, result)  
+
+proc parseIfNotExists(p: var TSqlParser, k: TSqlNodeKind): PSqlNode = 
+  getTok(p)
+  if isKeyw(p, "if"):
+    getTok(p)
+    eat(p, "not")
+    eat(p, "exists")
+    result = newNode(succ(k))
+  else:
+    result = newNode(k)
+
+proc parseParIdentList(p: var TSqlParser, father: PSqlNode) =
+  eat(p, tkParLe)
+  while true:
+    expectIdent(p)
+    father.add(newNode(nkIdent, p.tok.literal))
+    getTok(p)
+    if p.tok.kind != tkComma: break
+    getTok(p)
+  eat(p, tkParRi)
+
+proc parseTableConstraint(p: var TSqlParser): PSqlNode =
+  if isKeyw(p, "primary"):
+    getTok(p)
+    eat(p, "key")
+    result = newNode(nkPrimaryKey)
+    parseParIdentList(p, result)
+  elif isKeyw(p, "foreign"):
+    getTok(p)
+    eat(p, "key")
+    result = newNode(nkForeignKey)
+    parseParIdentList(p, result)
+    eat(p, "references")
+    var m = newNode(nkReferences)
+    m.add(parseColumnReference(p))
+    result.add(m)
+  elif isKeyw(p, "unique"):
+    getTok(p)
+    eat(p, "key")
+    result = newNode(nkUnique)
+    parseParIdentList(p, result)
+  elif isKeyw(p, "check"):
+    result = parseCheck(p)
+  elif isKeyw(p, "constraint"):
+    result = parseConstraint(p)
+  else:
+    sqlError(p, "column definition expected")
+
+proc parseTableDef(p: var TSqlParser): PSqlNode =
+  result = parseIfNotExists(p, nkCreateTable)
+  expectIdent(p)
+  result.add(newNode(nkIdent, p.tok.literal))
+  getTok(p)
+  if p.tok.kind == tkParLe:
+    while true:
+      getTok(p)
+      if p.tok.kind == tkIdentifier or p.tok.kind == tkQuotedIdentifier:
+        result.add(parseColumnDef(p))
+      else:
+        result.add(parseTableConstraint(p))
+      if p.tok.kind != tkComma: break
+    eat(p, tkParRi)
+  
+proc parseTypeDef(p: var TSqlParser): PSqlNode =
+  result = parseIfNotExists(p, nkCreateType)
+  expectIdent(p)
+  result.add(newNode(nkIdent, p.tok.literal))
+  getTok(p)
+  eat(p, "as")
+  result.add(parseDataType(p))
+
+proc parseWhere(p: var TSqlParser): PSqlNode =
+  getTok(p)
+  result = newNode(nkWhere)
+  result.add(parseExpr(p))
+
+proc parseIndexDef(p: var TSqlParser): PSqlNode =
+  result = parseIfNotExists(p, nkCreateIndex)
+  if isKeyw(p, "primary"):
+    getTok(p)
+    eat(p, "key")
+    result.add(newNode(nkPrimaryKey))
+  else:
+    expectIdent(p)
+    result.add(newNode(nkIdent, p.tok.literal))
+    getTok(p)
+  eat(p, "on")
+  expectIdent(p)
+  result.add(newNode(nkIdent, p.tok.literal))
+  getTok(p)
+  eat(p, tkParLe)
+  expectIdent(p)
+  result.add(newNode(nkIdent, p.tok.literal))
+  getTok(p)
+  while p.tok.kind == tkComma:
+    getTok(p)
+    expectIdent(p)
+    result.add(newNode(nkIdent, p.tok.literal))
+    getTok(p)
+  eat(p, tkParRi)
+
+proc parseInsert(p: var TSqlParser): PSqlNode =
+  getTok(p)
+  eat(p, "into")
+  expectIdent(p)
+  result = newNode(nkInsert)
+  result.add(newNode(nkIdent, p.tok.literal))
+  getTok(p)
+  if p.tok.kind == tkParLe:
+    var n = newNode(nkColumnList)
+    parseParIdentList(p, n)
+  else:
+    result.add(nil)
+  if isKeyw(p, "default"):
+    getTok(p)
+    eat(p, "values")
+    result.add(newNode(nkDefault))
+  else:
+    eat(p, "values")
+    eat(p, tkParLe)
+    var n = newNode(nkValueList)
+    while true:
+      n.add(parseExpr(p))
+      if p.tok.kind != tkComma: break
+      getTok(p)
+    result.add(n)
+    eat(p, tkParRi)
+
+proc parseUpdate(p: var TSqlParser): PSqlNode =
+  getTok(p)
+  result = newNode(nkUpdate)
+  result.add(primary(p))
+  eat(p, "set")
+  while true:
+    var a = newNode(nkAsgn)
+    expectIdent(p)
+    a.add(newNode(nkIdent, p.tok.literal))
+    getTok(p)
+    if isOpr(p, "="): getTok(p)
+    else: sqlError(p, "= expected")
+    a.add(parseExpr(p))
+    result.add(a)
+    if p.tok.kind != tkComma: break
+    getTok(p)
+  if isKeyw(p, "where"):
+    result.add(parseWhere(p))
+  else:
+    result.add(nil)
+    
+proc parseDelete(p: var TSqlParser): PSqlNode =
+  getTok(p)
+  result = newNode(nkDelete)
+  eat(p, "from")
+  result.add(primary(p))
+  if isKeyw(p, "where"):
+    result.add(parseWhere(p))
+  else:
+    result.add(nil)
+
+proc parseSelect(p: var TSqlParser): PSqlNode =
+  getTok(p)
+  if isKeyw(p, "distinct"):
+    getTok(p)
+    result = newNode(nkSelectDistinct)
+  elif isKeyw(p, "all"):
+    getTok(p)
+  result = newNode(nkSelect)
+  var a = newNode(nkSelectColumns)
+  while true:
+    if isOpr(p, "*"):
+      a.add(newNode(nkIdent, "*"))
+      getTok(p)
+    else:
+      a.add(parseExpr(p))
+    if p.tok.kind != tkComma: break
+    getTok(p)
+  result.add(a)
+  if isKeyw(p, "from"):
+    var f = newNode(nkFrom)
+    while true:
+      getTok(p)
+      f.add(parseExpr(p))
+      if p.tok.kind != tkComma: break
+    result.add(f)
+  if isKeyw(p, "where"):
+    result.add(parseWhere(p))
+  if isKeyw(p, "group"):
+    getTok(p)
+    eat(p, "by")
+    var g = newNode(nkGroup)
+    while true:
+      g.add(parseExpr(p))
+      if p.tok.kind != tkComma: break
+      getTok(p)
+    result.add(g)
+  if isKeyw(p, "having"):
+    var h = newNode(nkHaving)
+    while true:
+      getTok(p)
+      h.add(parseExpr(p))
+      if p.tok.kind != tkComma: break    
+    result.add(h)
+  if isKeyw(p, "union"):
+    result.add(newNode(nkUnion))
+    getTok(p)
+  elif isKeyw(p, "intersect"):
+    result.add(newNode(nkIntersect))
+    getTok(p)  
+  elif isKeyw(p, "except"):
+    result.add(newNode(nkExcept))
+    getTok(p)
+  if isKeyw(p, "order"):
+    getTok(p)
+    eat(p, "by")
+    var n = newNode(nkOrder)
+    while true:
+      var e = parseExpr(p)
+      if isKeyw(p, "asc"): getTok(p) # is default
+      elif isKeyw(p, "desc"):
+        getTok(p)
+        var x = newNode(nkDesc)
+        x.add(e)
+        e = x
+      n.add(e)
+      if p.tok.kind != tkComma: break
+      getTok(p)
+    result.add(n)
+
+proc parseStmt(p: var TSqlParser): PSqlNode =
+  if isKeyw(p, "create"):
+    getTok(p)
+    optKeyw(p, "cached")
+    optKeyw(p, "memory")
+    optKeyw(p, "temp")
+    optKeyw(p, "global")
+    optKeyw(p, "local")
+    optKeyw(p, "temporary")
+    optKeyw(p, "unique")
+    optKeyw(p, "hash")
+    if isKeyw(p, "table"):
+      result = parseTableDef(p)
+    elif isKeyw(p, "type"):
+      result = parseTypeDef(p)
+    elif isKeyw(p, "index"):
+      result = parseIndexDef(p)
+    else:
+      sqlError(p, "TABLE expected")
+  elif isKeyw(p, "insert"):
+    result = parseInsert(p)
+  elif isKeyw(p, "update"):
+    result = parseUpdate(p)
+  elif isKeyw(p, "delete"):
+    result = parseDelete(p)
+  elif isKeyw(p, "select"):
+    result = parseSelect(p)
+  else:
+    sqlError(p, "CREATE expected")
+
+proc parse*(p: var TSqlParser): PSqlNode =
+  result = newNode(nkStmtList)
+  while p.tok.kind != tkEof:
+    var s = parseStmt(p)
+    eat(p, tkSemiColon)
+    result.add(s)
+  if result.len == 1:
+    result = result.sons[0]
+
+proc open*(p: var TSqlParser, input: PStream, filename: string) =
+  open(TSqlLexer(p), input, filename)
+  p.tok.kind = tkInvalid
+  p.tok.literal = ""
+  getTok(p)
+  
+proc close*(p: var TSqlParser) = 
+  close(TSqlLexer(p))
+
+proc parseSQL*(input: PStream, filename: string): PSqlNode =
+  var p: TSqlParser
+  open(p, input, filename)
+  result = parse(p)
+  close(p)
+
+proc ra(n: PSqlNode, s: var string, indent: int)
+
+proc rs(n: PSqlNode, s: var string, indent: int,
+        prefix = "(", suffix = ")",
+        sep = ", ") = 
+  if n.len > 0:
+    s.add(prefix)
+    for i in 0 .. n.len-1:
+      if i > 0: s.add(sep)
+      ra(n.sons[i], s, indent)
+    s.add(suffix)
+
+proc ra(n: PSqlNode, s: var string, indent: int) =
+  if n == nil: return
+  case n.kind
+  of nkNone: nil
+  of nkIdent:
+    if allCharsInSet(n.strVal, {'\33'..'\127'}):
+      s.add(n.strVal)
+    else:
+      s.add("\"" & replaceStr(n.strVal, "\"", "\"\"") & "\"")
+  of nkStringLit:
+    s.add(escape(n.strVal, "e'", "'"))
+  of nkBitStringLit:
+    s.add("b'" & n.strVal & "'")
+  of nkHexStringLit:
+    s.add("x'" & n.strVal & "'")
+  of nkIntegerLit, nkNumericLit:
+    s.add(n.strVal)
+  of nkPrimaryKey:
+    s.add(" primary key")
+    rs(n, s, indent)
+  of nkForeignKey:
+    s.add(" foreign key")
+    rs(n, s, indent)
+  of nkNotNull:
+    s.add(" not null")
+  of nkDot:
+    ra(n.sons[0], s, indent)
+    s.add(".")
+    ra(n.sons[1], s, indent)
+  of nkDotDot:
+    ra(n.sons[0], s, indent)
+    s.add(". .")
+    ra(n.sons[1], s, indent)
+  of nkPrefix:
+    s.add('(')
+    ra(n.sons[0], s, indent)
+    s.add(' ')
+    ra(n.sons[1], s, indent)
+    s.add(')')
+  of nkInfix:
+    s.add('(')    
+    ra(n.sons[1], s, indent)
+    s.add(' ')
+    ra(n.sons[0], s, indent)
+    s.add(' ')
+    ra(n.sons[2], s, indent)
+    s.add(')')
+  of nkCall, nkColumnReference:
+    ra(n.sons[0], s, indent)
+    s.add('(')
+    for i in 1..n.len-1:
+      if i > 1: s.add(", ")
+      ra(n.sons[i], s, indent)
+    s.add(')')
+  of nkReferences:
+    s.add(" references ")
+    ra(n.sons[0], s, indent)
+  of nkDefault:
+    s.add(" default ")
+    ra(n.sons[0], s, indent)
+  of nkCheck:
+    s.add(" check ")
+    ra(n.sons[0], s, indent)
+  of nkConstraint:
+    s.add(" constraint ")
+    ra(n.sons[0], s, indent)
+    s.add(" check ")
+    ra(n.sons[1], s, indent)
+  of nkUnique:
+    s.add(" unique")
+    rs(n, s, indent)
+  of nkIdentity:
+    s.add(" identity")
+  of nkColumnDef:
+    s.add("\n  ")
+    rs(n, s, indent, "", "", " ")
+  of nkStmtList:
+    for i in 0..n.len-1:
+      ra(n.sons[i], s, indent)
+      s.add("\n")
+  of nkInsert:
+    assert n.len == 3
+    s.add("insert into ")
+    ra(n.sons[0], s, indent)
+    ra(n.sons[1], s, indent)
+    if n.sons[2].kind == nkDefault: 
+      s.add("default values")
+    else:
+      s.add("\nvalues ")
+      ra(n.sons[2], s, indent)
+    s.add(';')
+  of nkUpdate: 
+    s.add("update ")
+    ra(n.sons[0], s, indent)
+    s.add(" set ")
+    var L = n.len
+    for i in 1 .. L-2:
+      if i > 1: s.add(", ")
+      var it = n.sons[i]
+      assert it.kind == nkAsgn
+      ra(it, s, indent)
+    ra(n.sons[L-1], s, indent)
+    s.add(';')
+  of nkDelete: 
+    s.add("delete from ")
+    ra(n.sons[0], s, indent)
+    ra(n.sons[1], s, indent)
+    s.add(';')
+  of nkSelect, nkSelectDistinct:
+    s.add("select ")
+    if n.kind == nkSelectDistinct:
+      s.add("distinct ")
+    rs(n.sons[0], s, indent, "", "", ", ")
+    for i in 1 .. n.len-1: ra(n.sons[i], s, indent)
+    s.add(';')
+  of nkSelectColumns: 
+    assert(false)
+  of nkAsgn:
+    ra(n.sons[0], s, indent)
+    s.add(" = ")
+    ra(n.sons[1], s, indent)  
+  of nkFrom:
+    s.add("\nfrom ")
+    rs(n, s, indent, "", "", ", ")
+  of nkGroup:
+    s.add("\ngroup by")
+    rs(n, s, indent, "", "", ", ")
+  of nkHaving:
+    s.add("\nhaving")
+    rs(n, s, indent, "", "", ", ")
+  of nkOrder:
+    s.add("\norder by ")
+    rs(n, s, indent, "", "", ", ")
+  of nkDesc:
+    ra(n.sons[0], s, indent)
+    s.add(" desc")
+  of nkUnion:
+    s.add(" union")
+  of nkIntersect:
+    s.add(" intersect")
+  of nkExcept:
+    s.add(" except")
+  of nkColumnList:
+    rs(n, s, indent)
+  of nkValueList:
+    s.add("values ")
+    rs(n, s, indent)
+  of nkWhere:
+    s.add("\nwhere ")
+    ra(n.sons[0], s, indent)
+  of nkCreateTable, nkCreateTableIfNotExists:
+    s.add("create table ")
+    if n.kind == nkCreateTableIfNotExists:
+      s.add("if not exists ")
+    ra(n.sons[0], s, indent)
+    s.add('(')
+    for i in 1..n.len-1:
+      if i > 1: s.add(", ")
+      ra(n.sons[i], s, indent)
+    s.add(");")
+  of nkCreateType, nkCreateTypeIfNotExists:
+    s.add("create type ")
+    if n.kind == nkCreateTypeIfNotExists:
+      s.add("if not exists ")
+    ra(n.sons[0], s, indent)
+    s.add(" as ")
+    ra(n.sons[1], s, indent)
+    s.add(';')
+  of nkCreateIndex, nkCreateIndexIfNotExists:
+    s.add("create index ")
+    if n.kind == nkCreateIndexIfNotExists:
+      s.add("if not exists ")
+    ra(n.sons[0], s, indent)
+    s.add(" on ")
+    ra(n.sons[1], s, indent)
+    s.add('(')
+    for i in 2..n.len-1:
+      if i > 2: s.add(", ")
+      ra(n.sons[i], s, indent)
+    s.add(");")
+  of nkEnumDef:
+    s.add("enum ")
+    rs(n, s, indent)
+
+# What I want: 
+#
+#select(columns = [T1.all, T2.name], 
+#       fromm = [T1, T2],
+#       where = T1.name ==. T2.name,
+#       orderby = [name]):
+#  
+#for row in dbQuery(db, """select x, y, z 
+#                          from a, b 
+#                          where a.name = b.name"""):
+#  
+
+#select x, y, z:
+#  fromm: Table1, Table2
+#  where: x.name == y.name
+#db.select(fromm = [t1, t2], where = t1.name == t2.name):
+#for x, y, z in db.select(fromm = a, b where = a.name == b.name): 
+#  writeln x, y, z
+
+proc renderSQL*(n: PSqlNode): string =
+  ## Converts an SQL abstract syntax tree to its string representation.
+  result = ""
+  ra(n, result, 0)
+
+when isMainModule:
+  echo(renderSQL(parseSQL(newStringStream("""
+      CREATE TYPE happiness AS ENUM ('happy', 'very happy', 'ecstatic');
+      CREATE TABLE holidays (
+         num_weeks int,
+         happiness happiness
+      );
+      CREATE INDEX table1_attr1 ON table1(attr1);
+      
+      SELECT * FROM myTab WHERE col1 = 'happy';
+  """), "stdin")))
+
+# CREATE TYPE happiness AS ENUM ('happy', 'very happy', 'ecstatic');
+# CREATE TABLE holidays (
+#    num_weeks int,
+#    happiness happiness
+# );
+# CREATE INDEX table1_attr1 ON table1(attr1)
diff --git a/lib/parsexml.nim b/lib/pure/parsexml.nim
index 78be404d1..242a4f01c 100644
--- a/lib/parsexml.nim
+++ b/lib/pure/parsexml.nim
@@ -215,9 +215,11 @@ proc parseCDATA(my: var TXMLParser) =
       break
     of '\c': 
       pos = lexbase.HandleCR(my, pos)
+      buf = my.buf
       add(my.a, '\L')
     of '\L': 
       pos = lexbase.HandleLF(my, pos)
+      buf = my.buf
       add(my.a, '\L')
     else:
       add(my.a, buf[pos])
@@ -241,9 +243,11 @@ proc parseComment(my: var TXMLParser) =
       break
     of '\c': 
       pos = lexbase.HandleCR(my, pos)
+      buf = my.buf
       if my.options.contains(reportComments): add(my.a, '\L')
     of '\L': 
       pos = lexbase.HandleLF(my, pos)
+      buf = my.buf
       if my.options.contains(reportComments): add(my.a, '\L')
     else:
       if my.options.contains(reportComments): add(my.a, buf[pos])
@@ -262,9 +266,11 @@ proc parseWhitespace(my: var TXmlParser, skip=False) =
     of '\c':  
       # the specification says that CR-LF, CR are to be transformed to LF
       pos = lexbase.HandleCR(my, pos)
+      buf = my.buf
       if not skip: add(my.a, '\L')
     of '\L': 
       pos = lexbase.HandleLF(my, pos)
+      buf = my.buf
       if not skip: add(my.a, '\L')
     else:
       break
@@ -358,9 +364,11 @@ proc parsePI(my: var TXmlParser) =
     of '\c':  
       # the specification says that CR-LF, CR are to be transformed to LF
       pos = lexbase.HandleCR(my, pos)
+      buf = my.buf      
       add(my.b, '\L')
     of '\L': 
       pos = lexbase.HandleLF(my, pos)
+      buf = my.buf
       add(my.b, '\L')
     else:
       add(my.b, buf[pos])
@@ -391,9 +399,11 @@ proc parseSpecial(my: var TXmlParser) =
       add(my.a, '>')
     of '\c':  
       pos = lexbase.HandleCR(my, pos)
+      buf = my.buf
       add(my.a, '\L')
     of '\L': 
       pos = lexbase.HandleLF(my, pos)
+      buf = my.buf
       add(my.a, '\L')
     else:
       add(my.a, buf[pos])
@@ -474,9 +484,11 @@ proc parseAttribute(my: var TXmlParser) =
         inc(pos)
       of '\c':  
         pos = lexbase.HandleCR(my, pos)
+        buf = my.buf
         pendingSpace = true
       of '\L': 
         pos = lexbase.HandleLF(my, pos)
+        buf = my.buf
         pendingSpace = true
       else:
         if buf[pos] == quote:
@@ -502,9 +514,11 @@ proc parseCharData(my: var TXmlParser) =
     of '\c':  
       # the specification says that CR-LF, CR are to be transformed to LF
       pos = lexbase.HandleCR(my, pos)
+      buf = my.buf
       add(my.a, '\L')
     of '\L': 
       pos = lexbase.HandleLF(my, pos)
+      buf = my.buf
       add(my.a, '\L')
     else:
       add(my.a, buf[pos])
diff --git a/lib/base/regexprs.nim b/lib/pure/regexprs.nim
index e2aac3d17..e2aac3d17 100644
--- a/lib/base/regexprs.nim
+++ b/lib/pure/regexprs.nim
diff --git a/lib/streams.nim b/lib/pure/streams.nim
index 238cba4ec..238cba4ec 100644
--- a/lib/streams.nim
+++ b/lib/pure/streams.nim
diff --git a/lib/strtabs.nim b/lib/pure/strtabs.nim
index 10cd0b933..10cd0b933 100644
--- a/lib/strtabs.nim
+++ b/lib/pure/strtabs.nim
diff --git a/lib/strutils.nim b/lib/pure/strutils.nim
index 075e6b252..a4895110b 100644
--- a/lib/strutils.nim
+++ b/lib/pure/strutils.nim
@@ -393,6 +393,17 @@ proc endsWith(s, suffix: string): bool =
     if s[i+j] != suffix[i]: return false
     inc(i)
 
+when false:
+  proc abbrev(s: string, possibilities: openarray[string]): int = 
+    ## returns the index of the first item in `possibilities` if not
+    ## ambigious; -1 if no item has been found; -2 if multiple items
+    ## match.
+    result = -1 # none found
+    for i in 0..possibilities.len-1: 
+      if possibilities[i].startsWith(s): 
+        if result >= 0: return -2 # ambigious
+        result = i
+
 proc repeatChar(count: int, c: Char = ' '): string =
   result = newString(count)
   for i in 0..count-1:
diff --git a/lib/base/terminal.nim b/lib/pure/terminal.nim
index 42bd80cb4..42bd80cb4 100644
--- a/lib/base/terminal.nim
+++ b/lib/pure/terminal.nim
diff --git a/lib/times.nim b/lib/pure/times.nim
index 459b6c2ad..793b55ead 100644
--- a/lib/times.nim
+++ b/lib/pure/times.nim
@@ -1,7 +1,7 @@
 #
 #
 #            Nimrod's Runtime Library
-#        (c) Copyright 2008 Andreas Rumpf
+#        (c) Copyright 2009 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -22,10 +22,19 @@ type
     mJan, mFeb, mMar, mApr, mMay, mJun, mJul, mAug, mSep, mOct, mNov, mDec
   TWeekDay* = enum ## represents a weekday
     dMon, dTue, dWed, dThu, dFri, dSat, dSun
-
-  TTime* {.importc: "time_t", header: "<time.h>", final.} = object ## abstract type that 
-                                                                   ## represents a time
-    when defined(ECMAScript):
+    
+when defined(posix): 
+  type
+    TTime* = abstract int ## abstract type that represents a time
+elif defined(windows):
+  when defined(vcc):
+    # newest version of Visual C++ defines time_t to be of 64 bits
+    type TTime* = abstract int64
+  else:
+    type TTime* = abstract int32
+elif defined(ECMAScript):
+  type
+    TTime* {.final.} = object
       getDay: proc (): int
       getFullYear: proc (): int
       getHours: proc (): int
@@ -64,7 +73,7 @@ type
       toLocaleString: proc (): cstring
       UTC: proc (): int
 
-
+type
   TTimeInfo* = object of TObject ## represents a time in different parts
     second*: range[0..61]     ## The number of seconds after the minute,
                               ## normally in the range 0 to 59, but can
@@ -121,8 +130,7 @@ proc getStartMilsecs*(): int
   ## get the miliseconds from the start of the program
 
 
-when not defined(ECMAScript):
-  
+when not defined(ECMAScript):  
   # C wrapper:
   type
     structTM {.importc: "struct tm", final.} = object
@@ -225,6 +233,18 @@ when not defined(ECMAScript):
     var a = time
     return toStringTillNL(ctime(addr(a)))
 
+  const
+    epochDiff = 116444736000000000'i64
+    rateDiff = 10000000'i64 # 100 nsecs
+
+  proc unixTimeToWinTime*(t: TTime): int64 = 
+    ## converts a UNIX `TTime` (``time_t``) to a Windows file time
+    result = int64(t) * rateDiff + epochDiff
+    
+  proc winTimeToUnixTime*(t: int64): TTime = 
+    ## converts a Windows time to a UNIX `TTime` (``time_t``)
+    result = TTime((t - epochDiff) div rateDiff)
+
 else:
   proc getTime(): TTime {.importc: "new Date", nodecl.}
 
diff --git a/lib/unicode.nim b/lib/pure/unicode.nim
index 70a18f70d..735713cf5 100644
--- a/lib/unicode.nim
+++ b/lib/pure/unicode.nim
@@ -1,7 +1,7 @@
 #
 #
 #            Nimrod's Runtime Library
-#        (c) Copyright 2008 Andreas Rumpf
+#        (c) Copyright 2009 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
diff --git a/lib/xmlgen.nim b/lib/pure/xmlgen.nim
index 79a782252..79a782252 100644
--- a/lib/xmlgen.nim
+++ b/lib/pure/xmlgen.nim
diff --git a/lib/system.nim b/lib/system.nim
index 3be233b50..5f7eefa45 100644
--- a/lib/system.nim
+++ b/lib/system.nim
@@ -38,7 +38,7 @@ type
   string* {.magic: String.} ## built-in string type
   cstring* {.magic: Cstring.} ## built-in cstring (*compatible string*) type
   pointer* {.magic: Pointer.} ## built-in pointer type
-  TAnyEnum {.magic: AnyEnum.}
+  Ordinal* {.magic: Ordinal.}[T]
 
 type
   `nil` {.magic: "Nil".}
@@ -115,7 +115,7 @@ when not defined(EcmaScript) and not defined(NimrodVM):
       data: array[0..100_000_000, char]
     NimString = ptr NimStringDesc
 
-  include hti
+  include "system/hti"
 
 type
   Byte* = Int8 ## this is an alias for ``int8``, that is a signed
@@ -157,6 +157,8 @@ type
                               ## system raises.
   EIO* = object of ESystem    ## raised if an IO error occured.
   EOS* = object of ESystem    ## raised if an operating system service failed.
+  EInvalidLibrary* = object of EOS ## raised if a dynamic library
+                                   ## could not be loaded.
   ERessourceExhausted* = object of ESystem ## raised if a ressource request
                                            ## could not be fullfilled.
   EArithmetic* = object of ESynch       ## raised if any kind of arithmetic
@@ -218,26 +220,26 @@ proc sizeof*[T](x: T): natural {.magic: "SizeOf", noSideEffect.}
   ## that one never needs to know ``x``'s size. As a special semantic rule,
   ## ``x`` may also be a type identifier (``sizeof(int)`` is valid).
 
-proc succ*[T](x: T, y = 1): T {.magic: "Succ", noSideEffect.}
+proc succ*[T](x: ordinal[T], y = 1): T {.magic: "Succ", noSideEffect.}
   ## returns the ``y``-th successor of the value ``x``. ``T`` has to be
   ## an ordinal type. If such a value does not exist, ``EOutOfRange`` is raised
   ## or a compile time error occurs.
 
-proc pred*[T](x: T, y = 1): T {.magic: "Pred", noSideEffect.}
+proc pred*[T](x: ordinal[T], y = 1): T {.magic: "Pred", noSideEffect.}
   ## returns the ``y``-th predecessor of the value ``x``. ``T`` has to be
   ## an ordinal type. If such a value does not exist, ``EOutOfRange`` is raised
   ## or a compile time error occurs.
 
-proc inc*[T](x: var T, y = 1) {.magic: "Inc".}
+proc inc*[T](x: var ordinal[T], y = 1) {.magic: "Inc".}
   ## increments the ordinal ``x`` by ``y``. If such a value does not
   ## exist, ``EOutOfRange`` is raised or a compile time error occurs. This is a
   ## short notation for: ``x = succ(x, y)``.
 
-proc dec*[T](x: var T, y = 1) {.magic: "Dec".}
+proc dec*[T](x: var ordinal[T], y = 1) {.magic: "Dec".}
   ## decrements the ordinal ``x`` by ``y``. If such a value does not
   ## exist, ``EOutOfRange`` is raised or a compile time error occurs. This is a
   ## short notation for: ``x = pred(x, y)``.
-
+  
 proc newSeq*[T](s: var seq[T], len: int) {.magic: "NewSeq".}
   ## creates a new sequence of type ``seq[T]`` with length ``len``.
   ## This is equivalent to ``s = []; setlen(s, len)``, but more
@@ -546,7 +548,7 @@ proc `-+-` *[T](x, y: set[T]): set[T] {.magic: "SymDiffSet", noSideEffect.}
   ## ``(A - B) + (B - A)``, but more efficient.
 
 # comparison operators:
-proc `==` *(x, y: TAnyEnum): bool {.magic: "EqEnum", noSideEffect.}
+proc `==` *[T](x, y: ordinal[T]): bool {.magic: "EqEnum", noSideEffect.}
 proc `==` *(x, y: pointer): bool {.magic: "EqRef", noSideEffect.}
 proc `==` *(x, y: string): bool {.magic: "EqStr", noSideEffect.}
 proc `==` *(x, y: cstring): bool {.magic: "EqCString", noSideEffect.}
@@ -556,7 +558,7 @@ proc `==` *[T](x, y: set[T]): bool {.magic: "EqSet", noSideEffect.}
 proc `==` *[T](x, y: ref T): bool {.magic: "EqRef", noSideEffect.}
 proc `==` *[T](x, y: ptr T): bool {.magic: "EqRef", noSideEffect.}
 
-proc `<=` *(x, y: TAnyEnum): bool {.magic: "LeEnum", noSideEffect.}
+proc `<=` *[T](x, y: ordinal[T]): bool {.magic: "LeEnum", noSideEffect.}
 proc `<=` *(x, y: string): bool {.magic: "LeStr", noSideEffect.}
 proc `<=` *(x, y: char): bool {.magic: "LeCh", noSideEffect.}
 proc `<=` *[T](x, y: set[T]): bool {.magic: "LeSet", noSideEffect.}
@@ -564,7 +566,7 @@ proc `<=` *(x, y: bool): bool {.magic: "LeB", noSideEffect.}
 proc `<=` *[T](x, y: ref T): bool {.magic: "LePtr", noSideEffect.}
 proc `<=` *(x, y: pointer): bool {.magic: "LePtr", noSideEffect.}
 
-proc `<` *(x, y: TAnyEnum): bool {.magic: "LtEnum", noSideEffect.}
+proc `<` *[T](x, y: ordinal[T]): bool {.magic: "LtEnum", noSideEffect.}
 proc `<` *(x, y: string): bool {.magic: "LtStr", noSideEffect.}
 proc `<` *(x, y: char): bool {.magic: "LtCh", noSideEffect.}
 proc `<` *[T](x, y: set[T]): bool {.magic: "LtSet", noSideEffect.}
@@ -925,7 +927,7 @@ proc `$` *(x: string): string {.magic: "StrToStr", noSideEffect.}
   ## as it is. This operator is useful for generic code, so
   ## that ``$expr`` also works if ``expr`` is already a string.
 
-proc `$` *(x: TAnyEnum): string {.magic: "EnumToStr", noSideEffect.}
+proc `$` *[T](x: ordinal[T]): string {.magic: "EnumToStr", noSideEffect.}
   ## The stingify operator for an enumeration argument. This works for
   ## any enumeration type thanks to compiler magic. If a
   ## a ``$`` operator for a concrete enumeration is provided, this is
@@ -1182,15 +1184,10 @@ proc GC_unref*(x: string) {.magic: "GCunref".}
 # however, stack-traces are available for most parts
 # of the code
 
-proc echo*[Ty](x: Ty) {.inline.}
-  ## equivalent to ``writeln(stdout, x); flush(stdout)``. BUT: This is
-  ## available for the ECMAScript target too!
-
-proc echo*[Ty](x: openarray[Ty]) {.inline.}
+proc echo*[Ty](x: openarray[Ty]) {.magic: "Echo".}
   ## equivalent to ``writeln(stdout, x); flush(stdout)``. BUT: This is
   ## available for the ECMAScript target too!
 
-
 template newException(exceptn, message: expr): expr =
   block: # open a new scope
     var
@@ -1235,7 +1232,7 @@ when not defined(EcmaScript) and not defined(NimrodVM):
 
   {.push stack_trace: off.}
 
-  include ansi_c
+  include "system/ansi_c"
 
   proc cmp(x, y: string): int =
     return int(c_strcmp(x, y))
@@ -1390,7 +1387,7 @@ when not defined(EcmaScript) and not defined(NimrodVM):
     ## retrieves the current position of the file pointer that is used to
     ## read from the file `f`. The file's first byte has the index zero.
 
-  include sysio
+  include "system/sysio"
 
   iterator lines*(filename: string): string =
     ## Iterate over any line in the file named `filename`.
@@ -1416,12 +1413,12 @@ when not defined(EcmaScript) and not defined(NimrodVM):
 
   # ----------------------------------------------------------------------------
 
-  include excpt
+  include "system/excpt"
   # we cannot compile this with stack tracing on
   # as it would recurse endlessly!
-  include arithm
+  include "system/arithm"
   {.pop.} # stack trace
-  include dyncalls
+  include "system/dyncalls"
 
   const
     GenericSeqSize = (2 * sizeof(int))
@@ -1448,10 +1445,10 @@ when not defined(EcmaScript) and not defined(NimrodVM):
     else:
       result = n.sons[n.len]
 
-  include mm
-  include sysstr
-  include assign
-  include repr
+  include "system/mm"
+  include "system/sysstr"
+  include "system/assign"
+  include "system/repr"
 
   # we have to implement it here after gentostr for the cstrToNimStrDummy proc
   proc getCurrentExceptionMsg(): string =
@@ -1460,14 +1457,14 @@ when not defined(EcmaScript) and not defined(NimrodVM):
 
   {.push stack_trace: off.}
   when defined(endb):
-    include debugger
+    include "system/debugger"
 
   when defined(profiler):
-    include profiler
+    include "system/profiler"
   {.pop.} # stacktrace
 
 elif defined(ecmaScript):
-  include ecmasys
+  include "system/ecmasys"
 elif defined(NimrodVM):
   # Stubs for the GC interface:
   proc GC_disable() = nil
@@ -1481,8 +1478,6 @@ elif defined(NimrodVM):
   proc getOccupiedMem(): int = return -1
   proc getFreeMem(): int = return -1
   proc getTotalMem(): int = return -1
-  proc echo[Ty](x: Ty) = nil
-  proc echo[Ty](x: openarray[Ty]) = nil
   
   proc cmp(x, y: string): int =
     if x == y: return 0
diff --git a/lib/alloc.nim b/lib/system/alloc.nim
index 95feff854..95feff854 100644
--- a/lib/alloc.nim
+++ b/lib/system/alloc.nim
diff --git a/lib/ansi_c.nim b/lib/system/ansi_c.nim
index f307fb9ab..bdde11d50 100644
--- a/lib/ansi_c.nim
+++ b/lib/system/ansi_c.nim
@@ -11,10 +11,12 @@
 # and definitions of Ansi C types in Nimrod syntax
 # All symbols are prefixed with 'c_' to avoid ambiguities
 
+{.push hints:off}
+
 proc c_strcmp(a, b: CString): cint {.nodecl, importc: "strcmp".}
 proc c_memcmp(a, b: CString, size: cint): cint {.nodecl, importc: "memcmp".}
 proc c_memcpy(a, b: CString, size: cint) {.nodecl, importc: "memcpy".}
-proc c_strlen(a: CString): cint {.nodecl, importc: "strlen".}
+proc c_strlen(a: CString): int {.nodecl, importc: "strlen".}
 proc c_memset(p: pointer, value: cint, size: int) {.nodecl, importc: "memset".}
 
 type
@@ -87,3 +89,16 @@ proc c_feof(stream: C_TextFileStar): bool {.importc: "feof", nodecl.}
 proc c_malloc(size: int): pointer {.importc: "malloc", nodecl.}
 proc c_free(p: pointer) {.importc: "free", nodecl.}
 proc c_realloc(p: pointer, newsize: int): pointer {.importc: "realloc", nodecl.}
+
+var errno {.importc, header: "<errno.h>".}: cint ## error variable
+proc strerror(errnum: cint): cstring {.importc, header: "<string.h>".}
+
+proc c_remove(filename: CString): cint {.importc: "remove", noDecl.}
+proc c_rename(oldname, newname: CString): cint {.importc: "rename", noDecl.}
+
+proc c_system(cmd: CString): cint {.importc: "system", header: "<stdlib.h>".}
+proc c_getenv(env: CString): CString {.importc: "getenv", noDecl.}
+proc c_putenv(env: CString): cint {.importc: "putenv", noDecl.}
+
+{.pop}
+
diff --git a/lib/arithm.nim b/lib/system/arithm.nim
index a0e8e3338..a0e8e3338 100644
--- a/lib/arithm.nim
+++ b/lib/system/arithm.nim
diff --git a/lib/assign.nim b/lib/system/assign.nim
index 3d4bf4d61..3d4bf4d61 100644
--- a/lib/assign.nim
+++ b/lib/system/assign.nim
diff --git a/lib/cellsets.nim b/lib/system/cellsets.nim
index 0ce83864c..0ce83864c 100644
--- a/lib/cellsets.nim
+++ b/lib/system/cellsets.nim
diff --git a/lib/cntbits.nim b/lib/system/cntbits.nim
index a975f38ae..a975f38ae 100644
--- a/lib/cntbits.nim
+++ b/lib/system/cntbits.nim
diff --git a/lib/debugger.nim b/lib/system/debugger.nim
index 73a1e4db2..73a1e4db2 100644
--- a/lib/debugger.nim
+++ b/lib/system/debugger.nim
diff --git a/lib/dyncalls.nim b/lib/system/dyncalls.nim
index c46b8a931..c0371d069 100644
--- a/lib/dyncalls.nim
+++ b/lib/system/dyncalls.nim
@@ -1,7 +1,7 @@
 #
 #
 #            Nimrod's Runtime Library
-#        (c) Copyright 2006 Andreas Rumpf
+#        (c) Copyright 2009 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -13,9 +13,6 @@
 # account and been ported to all major platforms.
 
 type
-  EInvalidLibrary = object of EOS
-
-type
   TLibHandle = pointer       # private type
   TProcAddr = pointer        # libary loading and loading of procs:
 
@@ -26,6 +23,9 @@ proc nimLoadLibrary(path: string): TLibHandle {.compilerproc.}
 proc nimUnloadLibrary(lib: TLibHandle) {.compilerproc.}
 proc nimGetProcAddr(lib: TLibHandle, name: cstring): TProcAddr {.compilerproc.}
 
+proc nimLoadLibraryError(path: string) {.compilerproc, noinline.} =
+  raise newException(EInvalidLibrary, "could not load: " & path)
+
 # this code was inspired from Lua's source code:
 # Lua - An Extensible Extension Language
 # Tecgraf: Computer Graphics Technology Group, PUC-Rio, Brazil
@@ -57,11 +57,6 @@ when defined(posix):
 
   proc nimLoadLibrary(path: string): TLibHandle =
     result = dlopen(path, RTLD_NOW)
-    if result == nil:
-      writeToStdErr("could not load: ")
-      writeToStdErr(path)
-      writeToStdErr("\n")
-      #raise newException(EInvalidLibrary, "could not load: " & path)
 
   proc nimGetProcAddr(lib: TLibHandle, name: cstring): TProcAddr =
     result = dlsym(lib, name)
@@ -86,11 +81,6 @@ elif defined(windows) or defined(dos):
 
   proc nimLoadLibrary(path: string): TLibHandle =
     result = cast[TLibHandle](winLoadLibrary(path))
-    if result == nil:
-      writeToStdErr("could not load: ")
-      writeToStdErr(path)
-      writeToStdErr("\n")
-      #raise newException(EInvalidLibrary, "could not load: " & path)
 
   proc nimGetProcAddr(lib: TLibHandle, name: cstring): TProcAddr =
     result = GetProcAddress(cast[THINSTANCE](lib), name)
@@ -123,11 +113,6 @@ elif defined(mac):
                                         NSLINKMODULE_OPTION_RETURN_ON_ERROR)
         NSDestroyObjectFileImage(img)
         result = TLibHandle(modul)
-        if result == nil:
-          writeToStdErr("could not load: ")
-          writeToStdErr(path)
-          writeToStdErr("\n")          
-          #raise newException(EInvalidLibrary, "could not load: " & path)
 
   proc nimGetProcAddr(lib: TLibHandle, cname: string): TProcAddr =
     var
diff --git a/lib/ecmasys.nim b/lib/system/ecmasys.nim
index e26e763be..c0d0a5fd6 100644
--- a/lib/ecmasys.nim
+++ b/lib/system/ecmasys.nim
@@ -418,7 +418,7 @@ proc internalAssert(file: cstring, line: int) {.pure, compilerproc.} =
 include hti
 
 proc isFatPointer(ti: PNimType): bool =
-  # This has to be consistens with the code generator!
+  # This has to be consistent with the code generator!
   return ti.base.kind notin {tyRecord, tyRecordConstr, tyObject,
     tyArray, tyArrayConstr, tyPureObject, tyTuple,
     tyEmptySet, tyOpenArray, tySet, tyVar, tyRef, tyPtr}
diff --git a/lib/excpt.nim b/lib/system/excpt.nim
index 293491fe9..293491fe9 100644
--- a/lib/excpt.nim
+++ b/lib/system/excpt.nim
diff --git a/lib/gc.nim b/lib/system/gc.nim
index f91b8843e..f91b8843e 100644
--- a/lib/gc.nim
+++ b/lib/system/gc.nim
diff --git a/lib/hti.nim b/lib/system/hti.nim
index 7639cf6a3..dd74bfa3f 100644
--- a/lib/hti.nim
+++ b/lib/system/hti.nim
@@ -1,7 +1,7 @@
 #
 #
 #            Nimrod's Runtime Library
-#        (c) Copyright 2008 Andreas Rumpf
+#        (c) Copyright 2009 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -19,26 +19,27 @@ type # This should be he same as ast.TTypeKind
     tyGeneric, # 6
     tyGenericInst, # 7
     tyGenericParam, # 8
-    tyEnum, # 9
-    tyAnyEnum, # 10
-    tyArray, # 11
-    tyObject, # 12 
-    tyTuple, # 13
-    tySet, # 14
-    tyRange, # 15
-    tyPtr, # 16
-    tyRef, # 17
-    tyVar, # 18
-    tySequence, # 19
-    tyProc, # 20
-    tyPointer, # 21
-    tyOpenArray, # 22
-    tyString, # 23
-    tyCString, # 24
-    tyForward, # 25
+    tyAbstract, # 9
+    tyEnum, # 10
+    tyOrdinal, # 11
+    tyArray, # 12
+    tyObject, # 13 
+    tyTuple, # 14
+    tySet, # 15
+    tyRange, # 16
+    tyPtr, # 17
+    tyRef, # 18
+    tyVar, # 19
+    tySequence, # 20
+    tyProc, # 21
+    tyPointer, # 22
+    tyOpenArray, # 23
+    tyString, # 24
+    tyCString, # 25
+    tyForward, # 26
     tyInt, tyInt8, tyInt16, tyInt32, tyInt64,
     tyFloat, tyFloat32, tyFloat64, tyFloat128,
-    tyPureObject # 35: signals that object has no `n_type` field
+    tyPureObject # 36: signals that object has no `n_type` field
 
   TNimNodeKind = enum nkNone, nkSlot, nkList, nkCase
   TNimNode {.compilerproc, final.} = object
diff --git a/lib/mm.nim b/lib/system/mm.nim
index 3bfb8a689..9e207fcf0 100644
--- a/lib/mm.nim
+++ b/lib/system/mm.nim
@@ -128,7 +128,7 @@ when defined(boehmgc):
   proc asgnRefNoCycle(dest: ppointer, src: pointer) {.compilerproc, inline.} =
     dest^ = src
 
-  include cellsets
+  include "system/cellsets"
 elif defined(nogc):
   proc alloc(size: int): pointer =
     result = c_malloc(size)
@@ -176,12 +176,12 @@ elif defined(nogc):
   proc asgnRefNoCycle(dest: ppointer, src: pointer) {.compilerproc, inline.} =
     dest^ = src
 
-  include cellsets
+  include "system/cellsets"
 else:
-  include alloc
-  include cellsets
+  include "system/alloc"
+  include "system/cellsets"
   assert(sizeof(TCell) == sizeof(TFreeCell))
-  include gc
+  include "system/gc"
   
 {.pop.}
 
diff --git a/lib/profiler.nim b/lib/system/profiler.nim
index 97c7dcfeb..97c7dcfeb 100644
--- a/lib/profiler.nim
+++ b/lib/system/profiler.nim
diff --git a/lib/repr.nim b/lib/system/repr.nim
index 765d66be0..765d66be0 100644
--- a/lib/repr.nim
+++ b/lib/system/repr.nim
diff --git a/lib/sets.nim b/lib/system/sets.nim
index 395a2286c..651cc534b 100644
--- a/lib/sets.nim
+++ b/lib/system/sets.nim
@@ -20,7 +20,7 @@ proc countBits(n: int32): int {.exportc: "countBits".}
 # in math.nim too. So when linking with math.nim it'd give a duplicated
 # symbol error which we avoid by renaming here.
 
-include cntbits
+include "system/cntbits"
 
 proc unionSets(res: var TNimSet, a, b: TNimSet, len: int) {.
     compilerproc, inline.} =
diff --git a/lib/sysio.nim b/lib/system/sysio.nim
index bd52ef5ea..81746c8fb 100644
--- a/lib/sysio.nim
+++ b/lib/system/sysio.nim
@@ -99,10 +99,8 @@ proc writeln[Ty](f: TFile, x: openArray[Ty]) =
   for i in items(x): write(f, i)
   write(f, "\n")
 
-proc echo[Ty](x: Ty) = writeln(stdout, x)
-proc echo[Ty](x: openArray[Ty]) = 
-  for i in items(x): write(stdout, i)
-  write(stdout, "\n")
+proc rawEcho(x: string) {.inline, compilerproc.} = write(stdout, x)
+proc rawEchoNL() {.inline, compilerproc.} = write(stdout, "\n")
 
 # interface to the C procs:
 proc fopen(filename, mode: CString): pointer {.importc: "fopen", noDecl.}
diff --git a/lib/sysstr.nim b/lib/system/sysstr.nim
index 783bce6af..783bce6af 100644
--- a/lib/sysstr.nim
+++ b/lib/system/sysstr.nim
diff --git a/lib/target.h b/lib/target.h
deleted file mode 100644
index 1afd62aef..000000000
--- a/lib/target.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef _TARGET_H_
-#define _TARGET_H_
-
-#include <pthread.h>
-
-#define TLSF_MLOCK_T            pthread_mutex_t
-#define TLSF_CREATE_LOCK(l)     pthread_mutex_init (l, NULL)
-#define TLSF_DESTROY_LOCK(l)    pthread_mutex_destroy(l)
-#define TLSF_ACQUIRE_LOCK(l)    pthread_mutex_lock(l)
-#define TLSF_RELEASE_LOCK(l)    pthread_mutex_unlock(l)
-
-#endif
diff --git a/lib/tlsf.c b/lib/tlsf.c
deleted file mode 100644
index 767299ed6..000000000
--- a/lib/tlsf.c
+++ /dev/null
@@ -1,1005 +0,0 @@
-/* 
- * Two Levels Segregate Fit memory allocator (TLSF)
- * Version 2.4.3
- *
- * Written by Miguel Masmano Tello <mimastel@doctor.upv.es>
- *
- * Thanks to Ismael Ripoll for his suggestions and reviews
- *
- * Copyright (C) 2008, 2007, 2006, 2005, 2004
- *
- * This code is released using a dual license strategy: GPL/LGPL
- * You can choose the licence that better fits your requirements.
- *
- * Released under the terms of the GNU General Public License Version 2.0
- * Released under the terms of the GNU Lesser General Public License Version 2.1
- *
- */
-
-/*
- * Code contributions:
- *
- * (Jul 28 2007)  Herman ten Brugge <hermantenbrugge@home.nl>:
- *
- * - Add 64 bit support. It now runs on x86_64 and solaris64.
- * - I also tested this on vxworks/32and solaris/32 and i386/32 processors.
- * - Remove assembly code. I could not measure any performance difference 
- *   on my core2 processor. This also makes the code more portable.
- * - Moved defines/typedefs from tlsf.h to tlsf.c
- * - Changed MIN_BLOCK_SIZE to sizeof (free_ptr_t) and BHDR_OVERHEAD to 
- *   (sizeof (bhdr_t) - MIN_BLOCK_SIZE). This does not change the fact 
- *    that the minumum size is still sizeof 
- *   (bhdr_t).
- * - Changed all C++ comment style to C style. (// -> /.* ... *./)
- * - Used ls_bit instead of ffs and ms_bit instead of fls. I did this to 
- *   avoid confusion with the standard ffs function which returns 
- *   different values.
- * - Created set_bit/clear_bit fuctions because they are not present 
- *   on x86_64.
- * - Added locking support + extra file target.h to show how to use it.
- * - Added get_used_size function (REMOVED in 2.4)
- * - Added rtl_realloc and rtl_calloc function
- * - Implemented realloc clever support.
- * - Added some test code in the example directory.
- *        
- *
- * (Oct 23 2006) Adam Scislowicz: 
- *
- * - Support for ARMv5 implemented
- *
- */
-
-/************************************************************************/
-
-#define USE_SBRK        (1) 
-#define USE_MMAP        (1) 
-#define TLSF_STATISTIC  (1)
-
-#include <stdio.h>
-#include <string.h>
-
-#ifndef TLSF_USE_LOCKS
-#define  TLSF_USE_LOCKS   (0)
-#endif
-
-#ifndef TLSF_STATISTIC
-#define  TLSF_STATISTIC   (0)
-#endif
-
-#ifndef USE_MMAP
-#define  USE_MMAP   (0)
-#endif
-
-#ifndef USE_SBRK
-#define  USE_SBRK   (0)
-#endif
-
-
-#if TLSF_USE_LOCKS
-#include "target.h"
-#else
-#define TLSF_CREATE_LOCK(_unused_)   do {} while(0)
-#define TLSF_DESTROY_LOCK(_unused_)  do {} while(0) 
-#define TLSF_ACQUIRE_LOCK(_unused_)  do {} while(0)
-#define TLSF_RELEASE_LOCK(_unused_)  do {} while(0)
-#endif
-
-#if TLSF_STATISTIC
-#define  TLSF_ADD_SIZE(tlsf, b) do {                  \
-    tlsf->used_size += (b->size & BLOCK_SIZE) + BHDR_OVERHEAD;  \
-    if (tlsf->used_size > tlsf->max_size)             \
-      tlsf->max_size = tlsf->used_size;            \
-    } while(0)
-
-#define  TLSF_REMOVE_SIZE(tlsf, b) do {                \
-    tlsf->used_size -= (b->size & BLOCK_SIZE) + BHDR_OVERHEAD;  \
-  } while(0)
-#else
-#define  TLSF_ADD_SIZE(tlsf, b)       do{}while(0)
-#define  TLSF_REMOVE_SIZE(tlsf, b)    do{}while(0)
-#endif
-
-#if USE_MMAP || USE_SBRK
-#include <unistd.h>
-#endif
-
-#if USE_MMAP
-#include <sys/mman.h>
-#endif
-
-#include "tlsf.h"
-
-#if !defined(__GNUC__)
-#ifndef __inline__
-#define __inline__
-#endif
-#endif
-
-/* The  debug functions  only can  be used  when _DEBUG_TLSF_  is set. */
-#ifndef _DEBUG_TLSF_
-#define _DEBUG_TLSF_  (0)
-#endif
-
-/*************************************************************************/
-/* Definition of the structures used by TLSF */
-
-
-/* Some IMPORTANT TLSF parameters */
-/* Unlike the preview TLSF versions, now they are statics */
-#define BLOCK_ALIGN (sizeof(void *) * 2)
-
-#define MAX_FLI    (30)
-#define MAX_LOG2_SLI  (5)
-#define MAX_SLI    (1 << MAX_LOG2_SLI)     /* MAX_SLI = 2^MAX_LOG2_SLI */
-
-#define FLI_OFFSET  (6)     /* tlsf structure just will manage blocks bigger */
-/* than 128 bytes */
-#define SMALL_BLOCK  (128)
-#define REAL_FLI  (MAX_FLI - FLI_OFFSET)
-#define MIN_BLOCK_SIZE  (sizeof (free_ptr_t))
-#define BHDR_OVERHEAD  (sizeof (bhdr_t) - MIN_BLOCK_SIZE)
-#define TLSF_SIGNATURE  (0x2A59FA59)
-
-#define  PTR_MASK  (sizeof(void *) - 1)
-#define BLOCK_SIZE  (0xFFFFFFFF - PTR_MASK)
-
-#define GET_NEXT_BLOCK(_addr, _r) ((bhdr_t *) ((char *) (_addr) + (_r)))
-#define  MEM_ALIGN      ((BLOCK_ALIGN) - 1)
-#define ROUNDUP_SIZE(_r)          (((_r) + MEM_ALIGN) & ~MEM_ALIGN)
-#define ROUNDDOWN_SIZE(_r)        ((_r) & ~MEM_ALIGN)
-#define ROUNDUP(_x, _v)           ((((~(_x)) + 1) & ((_v)-1)) + (_x))
-
-#define BLOCK_STATE  (0x1)
-#define PREV_STATE  (0x2)
-
-/* bit 0 of the block size */
-#define FREE_BLOCK  (0x1)
-#define USED_BLOCK  (0x0)
-
-/* bit 1 of the block size */
-#define PREV_FREE  (0x2)
-#define PREV_USED  (0x0)
-
-
-#define DEFAULT_AREA_SIZE (1024*10)
-
-#ifdef USE_MMAP
-#define PAGE_SIZE (getpagesize())
-#endif
-
-#define PRINT_MSG(fmt, args...) printf(fmt, ## args)
-#define ERROR_MSG(fmt, args...) printf(fmt, ## args)
-
-typedef unsigned int u32_t;     /* NOTE: Make sure that this type is 4 bytes long on your computer */
-typedef unsigned char u8_t;     /* NOTE: Make sure that this type is 1 byte on your computer */
-
-typedef struct free_ptr_struct {
-    struct bhdr_struct *prev;
-    struct bhdr_struct *next;
-} free_ptr_t;
-
-typedef struct bhdr_struct {
-    /* This pointer is just valid if the first bit of size is set */
-    struct bhdr_struct *prev_hdr;
-    /* The size is stored in bytes */
-    size_t size;                /* bit 0 indicates whether the block is used and */
-    /* bit 1 allows to know whether the previous block is free */
-    union {
-        struct free_ptr_struct free_ptr;
-        u8_t buffer[1];         /*sizeof(struct free_ptr_struct)]; */
-    } ptr;
-} bhdr_t;
-
-/* This structure is embedded at the beginning of each area, giving us
- * enough information to cope with a set of areas */
-
-typedef struct area_info_struct {
-    bhdr_t *end;
-    struct area_info_struct *next;
-} area_info_t;
-
-typedef struct TLSF_struct {
-    /* the TLSF's structure signature */
-    u32_t tlsf_signature;
-
-#if TLSF_USE_LOCKS
-    TLSF_MLOCK_T lock;
-#endif
-
-#if TLSF_STATISTIC
-    /* These can not be calculated outside tlsf because we
-     * do not know the sizes when freeing/reallocing memory. */
-    size_t used_size;
-    size_t max_size;
-#endif
-
-    /* A linked list holding all the existing areas */
-    area_info_t *area_head;
-
-    /* the first-level bitmap */
-    /* This array should have a size of REAL_FLI bits */
-    u32_t fl_bitmap;
-
-    /* the second-level bitmap */
-    u32_t sl_bitmap[REAL_FLI];
-
-    bhdr_t *matrix[REAL_FLI][MAX_SLI];
-} tlsf_t;
-
-
-/******************************************************************/
-/**************     Helping functions    **************************/
-/******************************************************************/
-static __inline__ void set_bit(int nr, u32_t * addr);
-static __inline__ void clear_bit(int nr, u32_t * addr);
-static __inline__ int ls_bit(int x);
-static __inline__ int ms_bit(int x);
-static __inline__ void MAPPING_SEARCH(size_t * _r, int *_fl, int *_sl);
-static __inline__ void MAPPING_INSERT(size_t _r, int *_fl, int *_sl);
-static __inline__ bhdr_t *FIND_SUITABLE_BLOCK(tlsf_t * _tlsf, int *_fl, int *_sl);
-static __inline__ bhdr_t *process_area(void *area, size_t size);
-#if USE_SBRK || USE_MMAP
-static __inline__ void *get_new_area(size_t * size);
-#endif
-
-static const int table[] = {
-    -1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4,
-    4, 4,
-    4, 4, 4, 4, 4, 4, 4,
-    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
-    5,
-    5, 5, 5, 5, 5, 5, 5,
-    6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
-    6,
-    6, 6, 6, 6, 6, 6, 6,
-    6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
-    6,
-    6, 6, 6, 6, 6, 6, 6,
-    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
-    7,
-    7, 7, 7, 7, 7, 7, 7,
-    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
-    7,
-    7, 7, 7, 7, 7, 7, 7,
-    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
-    7,
-    7, 7, 7, 7, 7, 7, 7,
-    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
-    7,
-    7, 7, 7, 7, 7, 7, 7
-};
-
-static __inline__ int ls_bit(int i)
-{
-    unsigned int a;
-    unsigned int x = i & -i;
-
-    a = x <= 0xffff ? (x <= 0xff ? 0 : 8) : (x <= 0xffffff ? 16 : 24);
-    return table[x >> a] + a;
-}
-
-static __inline__ int ms_bit(int i)
-{
-    unsigned int a;
-    unsigned int x = (unsigned int) i;
-
-    a = x <= 0xffff ? (x <= 0xff ? 0 : 8) : (x <= 0xffffff ? 16 : 24);
-    return table[x >> a] + a;
-}
-
-static __inline__ void set_bit(int nr, u32_t * addr)
-{
-    addr[nr >> 5] |= 1 << (nr & 0x1f);
-}
-
-static __inline__ void clear_bit(int nr, u32_t * addr)
-{
-    addr[nr >> 5] &= ~(1 << (nr & 0x1f));
-}
-
-static __inline__ void MAPPING_SEARCH(size_t * _r, int *_fl, int *_sl)
-{
-    int _t;
-
-    if (*_r < SMALL_BLOCK) {
-        *_fl = 0;
-        *_sl = *_r / (SMALL_BLOCK / MAX_SLI);
-    } else {
-        _t = (1 << (ms_bit(*_r) - MAX_LOG2_SLI)) - 1;
-        *_r = *_r + _t;
-        *_fl = ms_bit(*_r);
-        *_sl = (*_r >> (*_fl - MAX_LOG2_SLI)) - MAX_SLI;
-        *_fl -= FLI_OFFSET;
-        /*if ((*_fl -= FLI_OFFSET) < 0) // FL wil be always >0!
-         *_fl = *_sl = 0;
-         */
-        *_r &= ~_t;
-    }
-}
-
-static __inline__ void MAPPING_INSERT(size_t _r, int *_fl, int *_sl)
-{
-    if (_r < SMALL_BLOCK) {
-        *_fl = 0;
-        *_sl = _r / (SMALL_BLOCK / MAX_SLI);
-    } else {
-        *_fl = ms_bit(_r);
-        *_sl = (_r >> (*_fl - MAX_LOG2_SLI)) - MAX_SLI;
-        *_fl -= FLI_OFFSET;
-    }
-}
-
-
-static __inline__ bhdr_t *FIND_SUITABLE_BLOCK(tlsf_t * _tlsf, int *_fl, int *_sl)
-{
-    u32_t _tmp = _tlsf->sl_bitmap[*_fl] & (~0 << *_sl);
-    bhdr_t *_b = NULL;
-
-    if (_tmp) {
-        *_sl = ls_bit(_tmp);
-        _b = _tlsf->matrix[*_fl][*_sl];
-    } else {
-        *_fl = ls_bit(_tlsf->fl_bitmap & (~0 << (*_fl + 1)));
-        if (*_fl > 0) {         /* likely */
-            *_sl = ls_bit(_tlsf->sl_bitmap[*_fl]);
-            _b = _tlsf->matrix[*_fl][*_sl];
-        }
-    }
-    return _b;
-}
-
-
-#define EXTRACT_BLOCK_HDR(_b, _tlsf, _fl, _sl) do {          \
-    _tlsf -> matrix [_fl] [_sl] = _b -> ptr.free_ptr.next;    \
-    if (_tlsf -> matrix[_fl][_sl])                \
-      _tlsf -> matrix[_fl][_sl] -> ptr.free_ptr.prev = NULL;  \
-    else {                            \
-      clear_bit (_sl, &_tlsf -> sl_bitmap [_fl]);        \
-      if (!_tlsf -> sl_bitmap [_fl])              \
-        clear_bit (_fl, &_tlsf -> fl_bitmap);        \
-    }                              \
-    _b -> ptr.free_ptr.prev =  NULL;        \
-    _b -> ptr.free_ptr.next =  NULL;        \
-  }while(0)
-
-
-#define EXTRACT_BLOCK(_b, _tlsf, _fl, _sl) do {              \
-    if (_b -> ptr.free_ptr.next)                  \
-      _b -> ptr.free_ptr.next -> ptr.free_ptr.prev = _b -> ptr.free_ptr.prev; \
-    if (_b -> ptr.free_ptr.prev)                  \
-      _b -> ptr.free_ptr.prev -> ptr.free_ptr.next = _b -> ptr.free_ptr.next; \
-    if (_tlsf -> matrix [_fl][_sl] == _b) {              \
-      _tlsf -> matrix [_fl][_sl] = _b -> ptr.free_ptr.next;    \
-      if (!_tlsf -> matrix [_fl][_sl]) {              \
-        clear_bit (_sl, &_tlsf -> sl_bitmap[_fl]);        \
-        if (!_tlsf -> sl_bitmap [_fl])              \
-          clear_bit (_fl, &_tlsf -> fl_bitmap);        \
-      }                              \
-    }                                \
-    _b -> ptr.free_ptr.prev = NULL;          \
-    _b -> ptr.free_ptr.next = NULL;          \
-  } while(0)
-
-#define INSERT_BLOCK(_b, _tlsf, _fl, _sl) do {              \
-    _b -> ptr.free_ptr.prev = NULL; \
-    _b -> ptr.free_ptr.next = _tlsf -> matrix [_fl][_sl]; \
-    if (_tlsf -> matrix [_fl][_sl])                  \
-      _tlsf -> matrix [_fl][_sl] -> ptr.free_ptr.prev = _b;    \
-    _tlsf -> matrix [_fl][_sl] = _b;                \
-    set_bit (_sl, &_tlsf -> sl_bitmap [_fl]);            \
-    set_bit (_fl, &_tlsf -> fl_bitmap);                \
-  } while(0)
-
-#ifndef MAP_ANONYMOUS
-#  ifdef MAP_ANON
-#    define MAP_ANONYMOUS MAP_ANON
-#  else
-#    define MAP_ANONYMOUS 0x20
-#  endif
-#endif
-
-#if USE_SBRK || USE_MMAP
-static __inline__ void *get_new_area(size_t * size) 
-{
-    void *area;
-
-#if USE_SBRK
-    area = (void *)sbrk(0);
-    if (((void *)sbrk(*size)) != ((void *) -1))
-        return area;
-#endif
-
-#if USE_MMAP
-    *size = ROUNDUP(*size, PAGE_SIZE);
-    if ((area = mmap(0, *size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)) != MAP_FAILED)
-        return area;
-#endif
-    return ((void *) ~0);
-}
-#endif
-
-static __inline__ bhdr_t *process_area(void *area, size_t size)
-{
-    bhdr_t *b, *lb, *ib;
-    area_info_t *ai;
-
-    ib = (bhdr_t *) area;
-    ib->size =
-        (sizeof(area_info_t) <
-         MIN_BLOCK_SIZE) ? MIN_BLOCK_SIZE : ROUNDUP_SIZE(sizeof(area_info_t)) | USED_BLOCK | PREV_USED;
-    b = (bhdr_t *) GET_NEXT_BLOCK(ib->ptr.buffer, ib->size & BLOCK_SIZE);
-    b->size = ROUNDDOWN_SIZE(size - 3 * BHDR_OVERHEAD - (ib->size & BLOCK_SIZE)) | USED_BLOCK | PREV_USED;
-    b->ptr.free_ptr.prev = b->ptr.free_ptr.next = 0;
-    lb = GET_NEXT_BLOCK(b->ptr.buffer, b->size & BLOCK_SIZE);
-    lb->prev_hdr = b;
-    lb->size = 0 | USED_BLOCK | PREV_FREE;
-    ai = (area_info_t *) ib->ptr.buffer;
-    ai->next = 0;
-    ai->end = lb;
-    return ib;
-}
-
-/******************************************************************/
-/******************** Begin of the allocator code *****************/
-/******************************************************************/
-
-static char *mp = NULL;         /* Default memory pool. */
-
-/******************************************************************/
-size_t init_memory_pool(size_t mem_pool_size, void *mem_pool)
-{
-/******************************************************************/
-    tlsf_t *tlsf;
-    bhdr_t *b, *ib;
-
-    if (!mem_pool || !mem_pool_size || mem_pool_size < sizeof(tlsf_t) + BHDR_OVERHEAD * 8) {
-        ERROR_MSG("init_memory_pool (): memory_pool invalid\n");
-        return -1;
-    }
-
-    if (((unsigned long) mem_pool & PTR_MASK)) {
-        ERROR_MSG("init_memory_pool (): mem_pool must be aligned to a word\n");
-        return -1;
-    }
-    tlsf = (tlsf_t *) mem_pool;
-    /* Check if already initialised */
-    if (tlsf->tlsf_signature == TLSF_SIGNATURE) {
-        mp = mem_pool;
-        b = GET_NEXT_BLOCK(mp, ROUNDUP_SIZE(sizeof(tlsf_t)));
-        return b->size & BLOCK_SIZE;
-    }
-
-    mp = mem_pool;
-
-    /* Zeroing the memory pool */
-    memset(mem_pool, 0, sizeof(tlsf_t));
-
-    tlsf->tlsf_signature = TLSF_SIGNATURE;
-
-    TLSF_CREATE_LOCK(&tlsf->lock);
-
-    ib = process_area(GET_NEXT_BLOCK
-                      (mem_pool, ROUNDUP_SIZE(sizeof(tlsf_t))), ROUNDDOWN_SIZE(mem_pool_size - sizeof(tlsf_t)));
-    b = GET_NEXT_BLOCK(ib->ptr.buffer, ib->size & BLOCK_SIZE);
-    free_ex(b->ptr.buffer, tlsf);
-    tlsf->area_head = (area_info_t *) ib->ptr.buffer;
-
-#if TLSF_STATISTIC
-    tlsf->used_size = mem_pool_size - (b->size & BLOCK_SIZE);
-    tlsf->max_size = tlsf->used_size;
-#endif
-
-    return (b->size & BLOCK_SIZE);
-}
-
-/******************************************************************/
-size_t add_new_area(void *area, size_t area_size, void *mem_pool)
-{
-/******************************************************************/
-    tlsf_t *tlsf = (tlsf_t *) mem_pool;
-    area_info_t *ptr, *ptr_prev, *ai;
-    bhdr_t *ib0, *b0, *lb0, *ib1, *b1, *lb1, *next_b;
-
-    memset(area, 0, area_size);
-    ptr = tlsf->area_head;
-    ptr_prev = 0;
-
-    ib0 = process_area(area, area_size);
-    b0 = GET_NEXT_BLOCK(ib0->ptr.buffer, ib0->size & BLOCK_SIZE);
-    lb0 = GET_NEXT_BLOCK(b0->ptr.buffer, b0->size & BLOCK_SIZE);
-
-    /* Before inserting the new area, we have to merge this area with the
-       already existing ones */
-
-    while (ptr) {
-        ib1 = (bhdr_t *) ((char *) ptr - BHDR_OVERHEAD);
-        b1 = GET_NEXT_BLOCK(ib1->ptr.buffer, ib1->size & BLOCK_SIZE);
-        lb1 = ptr->end;
-
-        /* Merging the new area with the next physically contigous one */
-        if ((unsigned long) ib1 == (unsigned long) lb0 + BHDR_OVERHEAD) {
-            if (tlsf->area_head == ptr) {
-                tlsf->area_head = ptr->next;
-                ptr = ptr->next;
-            } else {
-                ptr_prev->next = ptr->next;
-                ptr = ptr->next;
-            }
-
-            b0->size =
-                ROUNDDOWN_SIZE((b0->size & BLOCK_SIZE) +
-                               (ib1->size & BLOCK_SIZE) + 2 * BHDR_OVERHEAD) | USED_BLOCK | PREV_USED;
-
-            b1->prev_hdr = b0;
-            lb0 = lb1;
-
-            continue;
-        }
-
-        /* Merging the new area with the previous physically contigous
-           one */
-        if ((unsigned long) lb1->ptr.buffer == (unsigned long) ib0) {
-            if (tlsf->area_head == ptr) {
-                tlsf->area_head = ptr->next;
-                ptr = ptr->next;
-            } else {
-                ptr_prev->next = ptr->next;
-                ptr = ptr->next;
-            }
-
-            lb1->size =
-                ROUNDDOWN_SIZE((b0->size & BLOCK_SIZE) +
-                               (ib0->size & BLOCK_SIZE) + 2 * BHDR_OVERHEAD) | USED_BLOCK | (lb1->size & PREV_STATE);
-            next_b = GET_NEXT_BLOCK(lb1->ptr.buffer, lb1->size & BLOCK_SIZE);
-            next_b->prev_hdr = lb1;
-            b0 = lb1;
-            ib0 = ib1;
-
-            continue;
-        }
-        ptr_prev = ptr;
-        ptr = ptr->next;
-    }
-
-    /* Inserting the area in the list of linked areas */
-    ai = (area_info_t *) ib0->ptr.buffer;
-    ai->next = tlsf->area_head;
-    ai->end = lb0;
-    tlsf->area_head = ai;
-    free_ex(b0->ptr.buffer, mem_pool);
-    return (b0->size & BLOCK_SIZE);
-}
-
-
-/******************************************************************/
-size_t get_used_size(void *mem_pool)
-{
-/******************************************************************/
-#if TLSF_STATISTIC
-    return ((tlsf_t *) mem_pool)->used_size;
-#else
-    return 0;
-#endif
-}
-
-/******************************************************************/
-size_t get_max_size(void *mem_pool)
-{
-/******************************************************************/
-#if TLSF_STATISTIC
-    return ((tlsf_t *) mem_pool)->max_size;
-#else
-    return 0;
-#endif
-}
-
-/******************************************************************/
-void destroy_memory_pool(void *mem_pool)
-{
-/******************************************************************/
-    tlsf_t *tlsf = (tlsf_t *) mem_pool;
-
-    tlsf->tlsf_signature = 0;
-
-    TLSF_DESTROY_LOCK(&tlsf->lock);
-
-}
-
-
-/******************************************************************/
-void *tlsf_malloc(size_t size)
-{
-/******************************************************************/
-    void *ret;
-
-#if USE_MMAP || USE_SBRK
-    if (!mp) {
-        size_t area_size;
-        void *area;
-
-        area_size = sizeof(tlsf_t) + BHDR_OVERHEAD * 8; /* Just a safety constant */
-        area_size = (area_size > DEFAULT_AREA_SIZE) ? area_size : DEFAULT_AREA_SIZE;
-        area = get_new_area(&area_size);
-        if (area == ((void *) ~0))
-            return NULL;        /* Not enough system memory */
-        init_memory_pool(area_size, area);
-    }
-#endif
-
-    TLSF_ACQUIRE_LOCK(&((tlsf_t *)mp)->lock);
-
-    ret = malloc_ex(size, mp);
-
-    TLSF_RELEASE_LOCK(&((tlsf_t *)mp)->lock);
-
-    return ret;
-}
-
-/******************************************************************/
-void tlsf_free(void *ptr)
-{
-/******************************************************************/
-
-    TLSF_ACQUIRE_LOCK(&((tlsf_t *)mp)->lock);
-
-    free_ex(ptr, mp);
-
-    TLSF_RELEASE_LOCK(&((tlsf_t *)mp)->lock);
-
-}
-
-/******************************************************************/
-void *tlsf_realloc(void *ptr, size_t size)
-{
-/******************************************************************/
-    void *ret;
-
-#if USE_MMAP || USE_SBRK
-  if (!mp) {
-    return tlsf_malloc(size);
-  }
-#endif
-
-    TLSF_ACQUIRE_LOCK(&((tlsf_t *)mp)->lock);
-
-    ret = realloc_ex(ptr, size, mp);
-
-    TLSF_RELEASE_LOCK(&((tlsf_t *)mp)->lock);
-
-    return ret;
-}
-
-/******************************************************************/
-void *tlsf_calloc(size_t nelem, size_t elem_size)
-{
-/******************************************************************/
-    void *ret;
-
-    TLSF_ACQUIRE_LOCK(&((tlsf_t *)mp)->lock);
-
-    ret = calloc_ex(nelem, elem_size, mp);
-
-    TLSF_RELEASE_LOCK(&((tlsf_t *)mp)->lock);
-
-    return ret;
-}
-
-/******************************************************************/
-void *malloc_ex(size_t size, void *mem_pool)
-{
-/******************************************************************/
-    tlsf_t *tlsf = (tlsf_t *) mem_pool;
-    bhdr_t *b, *b2, *next_b;
-    int fl, sl;
-    size_t tmp_size;
-
-    size = (size < MIN_BLOCK_SIZE) ? MIN_BLOCK_SIZE : ROUNDUP_SIZE(size);
-
-    /* Rounding up the requested size and calculating fl and sl */
-    MAPPING_SEARCH(&size, &fl, &sl);
-
-    /* Searching a free block, recall that this function changes the values of fl and sl,
-       so they are not longer valid when the function fails */
-    b = FIND_SUITABLE_BLOCK(tlsf, &fl, &sl);
-#if USE_MMAP || USE_SBRK
-    if (!b) {
-        size_t area_size;
-        void *area;
-        /* Growing the pool size when needed */
-        area_size = size + BHDR_OVERHEAD * 8;   /* size plus enough room for the requered headers. */
-        area_size = (area_size > DEFAULT_AREA_SIZE) ? area_size : DEFAULT_AREA_SIZE;
-        area = get_new_area(&area_size);        /* Call sbrk or mmap */
-        if (area == ((void *) ~0))
-            return NULL;        /* Not enough system memory */
-        add_new_area(area, area_size, mem_pool);
-        /* Rounding up the requested size and calculating fl and sl */
-        MAPPING_SEARCH(&size, &fl, &sl);
-        /* Searching a free block */
-        b = FIND_SUITABLE_BLOCK(tlsf, &fl, &sl);
-    }
-#endif
-    if (!b)
-        return NULL;            /* Not found */
-
-    EXTRACT_BLOCK_HDR(b, tlsf, fl, sl);
-
-    /*-- found: */
-    next_b = GET_NEXT_BLOCK(b->ptr.buffer, b->size & BLOCK_SIZE);
-    /* Should the block be split? */
-    tmp_size = (b->size & BLOCK_SIZE) - size;
-    if (tmp_size >= sizeof(bhdr_t)) {
-        tmp_size -= BHDR_OVERHEAD;
-        b2 = GET_NEXT_BLOCK(b->ptr.buffer, size);
-        b2->size = tmp_size | FREE_BLOCK | PREV_USED;
-        next_b->prev_hdr = b2;
-        MAPPING_INSERT(tmp_size, &fl, &sl);
-        INSERT_BLOCK(b2, tlsf, fl, sl);
-
-        b->size = size | (b->size & PREV_STATE);
-    } else {
-        next_b->size &= (~PREV_FREE);
-        b->size &= (~FREE_BLOCK);       /* Now it's used */
-    }
-
-    TLSF_ADD_SIZE(tlsf, b);
-
-    return (void *) b->ptr.buffer;
-}
-
-extern void free_ex(void *ptr, void *mem_pool) {
-    tlsf_t *tlsf = (tlsf_t *) mem_pool;
-    bhdr_t *b, *tmp_b;
-    int fl = 0, sl = 0;
-
-    if (!ptr) {
-        return;
-    }
-    b = (bhdr_t *) ((char *) ptr - BHDR_OVERHEAD);
-    b->size |= FREE_BLOCK;
-
-    TLSF_REMOVE_SIZE(tlsf, b);
-
-    b->ptr.free_ptr.prev = NULL;
-    b->ptr.free_ptr.next = NULL;
-    tmp_b = GET_NEXT_BLOCK(b->ptr.buffer, b->size & BLOCK_SIZE);
-    if (tmp_b->size & FREE_BLOCK) {
-        MAPPING_INSERT(tmp_b->size & BLOCK_SIZE, &fl, &sl);
-        EXTRACT_BLOCK(tmp_b, tlsf, fl, sl);
-        b->size += (tmp_b->size & BLOCK_SIZE) + BHDR_OVERHEAD;
-    }
-    if (b->size & PREV_FREE) {
-        tmp_b = b->prev_hdr;
-        MAPPING_INSERT(tmp_b->size & BLOCK_SIZE, &fl, &sl);
-        EXTRACT_BLOCK(tmp_b, tlsf, fl, sl);
-        tmp_b->size += (b->size & BLOCK_SIZE) + BHDR_OVERHEAD;
-        b = tmp_b;
-    }
-    MAPPING_INSERT(b->size & BLOCK_SIZE, &fl, &sl);
-    INSERT_BLOCK(b, tlsf, fl, sl);
-
-    tmp_b = GET_NEXT_BLOCK(b->ptr.buffer, b->size & BLOCK_SIZE);
-    tmp_b->size |= PREV_FREE;
-    tmp_b->prev_hdr = b;
-}
-
-/******************************************************************/
-void *realloc_ex(void *ptr, size_t new_size, void *mem_pool)
-{
-/******************************************************************/
-    tlsf_t *tlsf = (tlsf_t *) mem_pool;
-    void *ptr_aux;
-    unsigned int cpsize;
-    bhdr_t *b, *tmp_b, *next_b;
-    int fl, sl;
-    size_t tmp_size;
-
-    if (!ptr) {
-        if (new_size)
-            return (void *) malloc_ex(new_size, mem_pool);
-        if (!new_size)
-            return NULL;
-    } else if (!new_size) {
-        free_ex(ptr, mem_pool);
-        return NULL;
-    }
-
-    b = (bhdr_t *) ((char *) ptr - BHDR_OVERHEAD);
-    next_b = GET_NEXT_BLOCK(b->ptr.buffer, b->size & BLOCK_SIZE);
-    new_size = (new_size < MIN_BLOCK_SIZE) ? MIN_BLOCK_SIZE : ROUNDUP_SIZE(new_size);
-    tmp_size = (b->size & BLOCK_SIZE);
-    if (new_size <= tmp_size) {
-        TLSF_REMOVE_SIZE(tlsf, b);
-        if (next_b->size & FREE_BLOCK) {
-            MAPPING_INSERT(next_b->size & BLOCK_SIZE, &fl, &sl);
-            EXTRACT_BLOCK(next_b, tlsf, fl, sl);
-            tmp_size += (next_b->size & BLOCK_SIZE) + BHDR_OVERHEAD;
-            next_b = GET_NEXT_BLOCK(next_b->ptr.buffer, next_b->size & BLOCK_SIZE);
-            /* We allways reenter this free block because tmp_size will
-               be greater then sizeof (bhdr_t) */
-        }
-        tmp_size -= new_size;
-        if (tmp_size >= sizeof(bhdr_t)) {
-            tmp_size -= BHDR_OVERHEAD;
-            tmp_b = GET_NEXT_BLOCK(b->ptr.buffer, new_size);
-            tmp_b->size = tmp_size | FREE_BLOCK | PREV_USED;
-            next_b->prev_hdr = tmp_b;
-            next_b->size |= PREV_FREE;
-            MAPPING_INSERT(tmp_size, &fl, &sl);
-            INSERT_BLOCK(tmp_b, tlsf, fl, sl);
-            b->size = new_size | (b->size & PREV_STATE);
-        }
-        TLSF_ADD_SIZE(tlsf, b);
-        return (void *) b->ptr.buffer;
-    }
-    if ((next_b->size & FREE_BLOCK)) {
-        if (new_size <= (tmp_size + (next_b->size & BLOCK_SIZE))) {
-            TLSF_REMOVE_SIZE(tlsf, b);
-            MAPPING_INSERT(next_b->size & BLOCK_SIZE, &fl, &sl);
-            EXTRACT_BLOCK(next_b, tlsf, fl, sl);
-            b->size += (next_b->size & BLOCK_SIZE) + BHDR_OVERHEAD;
-            next_b = GET_NEXT_BLOCK(b->ptr.buffer, b->size & BLOCK_SIZE);
-            next_b->prev_hdr = b;
-            next_b->size &= ~PREV_FREE;
-            tmp_size = (b->size & BLOCK_SIZE) - new_size;
-            if (tmp_size >= sizeof(bhdr_t)) {
-                tmp_size -= BHDR_OVERHEAD;
-                tmp_b = GET_NEXT_BLOCK(b->ptr.buffer, new_size);
-                tmp_b->size = tmp_size | FREE_BLOCK | PREV_USED;
-                next_b->prev_hdr = tmp_b;
-                next_b->size |= PREV_FREE;
-                MAPPING_INSERT(tmp_size, &fl, &sl);
-                INSERT_BLOCK(tmp_b, tlsf, fl, sl);
-                b->size = new_size | (b->size & PREV_STATE);
-            }
-            TLSF_ADD_SIZE(tlsf, b);
-            return (void *) b->ptr.buffer;
-        }
-    }
-
-    ptr_aux = malloc_ex(new_size, mem_pool);
-
-    cpsize = ((b->size & BLOCK_SIZE) > new_size) ? new_size : (b->size & BLOCK_SIZE);
-
-    memcpy(ptr_aux, ptr, cpsize);
-
-    free_ex(ptr, mem_pool);
-    return ptr_aux;
-}
-
-
-/******************************************************************/
-void *calloc_ex(size_t nelem, size_t elem_size, void *mem_pool)
-{
-/******************************************************************/
-    void *ptr;
-
-    if (nelem <= 0 || elem_size <= 0)
-        return NULL;
-
-    if (!(ptr = malloc_ex(nelem * elem_size, mem_pool)))
-        return NULL;
-    memset(ptr, 0, nelem * elem_size);
-
-    return ptr;
-}
-
-/* for Nimrod: */
-size_t TLSF_GET_USED_SIZE(void) { return (((tlsf_t *)mp)->used_size); }
-size_t TLSF_GET_MAX_SIZE(void) { return (((tlsf_t *)mp)->max_size); }
-
-
-#if _DEBUG_TLSF_
-
-/***************  DEBUG FUNCTIONS   **************/
-
-/* The following functions have been designed to ease the debugging of */
-/* the TLSF  structure.  For non-developing  purposes, it may  be they */
-/* haven't too much worth.  To enable them, _DEBUG_TLSF_ must be set.  */
-
-extern void dump_memory_region(unsigned char *mem_ptr, unsigned int size);
-extern void print_block(bhdr_t * b);
-extern void print_tlsf(tlsf_t * tlsf);
-void print_all_blocks(tlsf_t * tlsf);
-
-void dump_memory_region(unsigned char *mem_ptr, unsigned int size)
-{
-
-    unsigned long begin = (unsigned long) mem_ptr;
-    unsigned long end = (unsigned long) mem_ptr + size;
-    int column = 0;
-
-    begin >>= 2;
-    begin <<= 2;
-
-    end >>= 2;
-    end++;
-    end <<= 2;
-
-    PRINT_MSG("\nMemory region dumped: 0x%lx - 0x%lx\n\n", begin, end);
-
-    column = 0;
-    PRINT_MSG("0x%lx ", begin);
-
-    while (begin < end) {
-        if (((unsigned char *) begin)[0] == 0)
-            PRINT_MSG("00");
-        else
-            PRINT_MSG("%02x", ((unsigned char *) begin)[0]);
-        if (((unsigned char *) begin)[1] == 0)
-            PRINT_MSG("00 ");
-        else
-            PRINT_MSG("%02x ", ((unsigned char *) begin)[1]);
-        begin += 2;
-        column++;
-        if (column == 8) {
-            PRINT_MSG("\n0x%lx ", begin);
-            column = 0;
-        }
-
-    }
-    PRINT_MSG("\n\n");
-}
-
-void print_block(bhdr_t * b)
-{
-    if (!b)
-        return;
-    PRINT_MSG(">> [%p] (", b);
-    if ((b->size & BLOCK_SIZE))
-        PRINT_MSG("%lu bytes, ", (unsigned long) (b->size & BLOCK_SIZE));
-    else
-        PRINT_MSG("sentinel, ");
-    if ((b->size & BLOCK_STATE) == FREE_BLOCK)
-        PRINT_MSG("free [%p, %p], ", b->ptr.free_ptr.prev, b->ptr.free_ptr.next);
-    else
-        PRINT_MSG("used, ");
-    if ((b->size & PREV_STATE) == PREV_FREE)
-        PRINT_MSG("prev. free [%p])\n", b->prev_hdr);
-    else
-        PRINT_MSG("prev used)\n");
-}
-
-void print_tlsf(tlsf_t * tlsf)
-{
-    bhdr_t *next;
-    int i, j;
-
-    PRINT_MSG("\nTLSF at %p\n", tlsf);
-
-    PRINT_MSG("FL bitmap: 0x%x\n\n", (unsigned) tlsf->fl_bitmap);
-
-    for (i = 0; i < REAL_FLI; i++) {
-        if (tlsf->sl_bitmap[i])
-            PRINT_MSG("SL bitmap 0x%x\n", (unsigned) tlsf->sl_bitmap[i]);
-        for (j = 0; j < MAX_SLI; j++) {
-            next = tlsf->matrix[i][j];
-            if (next)
-                PRINT_MSG("-> [%d][%d]\n", i, j);
-            while (next) {
-                print_block(next);
-                next = next->ptr.free_ptr.next;
-            }
-        }
-    }
-}
-
-void print_all_blocks(tlsf_t * tlsf)
-{
-    area_info_t *ai;
-    bhdr_t *next;
-    PRINT_MSG("\nTLSF at %p\nALL BLOCKS\n\n", tlsf);
-    ai = tlsf->area_head;
-    while (ai) {
-        next = (bhdr_t *) ((char *) ai - BHDR_OVERHEAD);
-        while (next) {
-            print_block(next);
-            if ((next->size & BLOCK_SIZE))
-                next = GET_NEXT_BLOCK(next->ptr.buffer, next->size & BLOCK_SIZE);
-            else
-                next = NULL;
-        }
-        ai = ai->next;
-    }
-}
-
-#endif
diff --git a/lib/tlsf.h b/lib/tlsf.h
deleted file mode 100644
index 7c8e2ad66..000000000
--- a/lib/tlsf.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Two Levels Segregate Fit memory allocator (TLSF)
- * Version 2.4.3
- *
- * Written by Miguel Masmano Tello <mimastel@doctor.upv.es>
- *
- * Thanks to Ismael Ripoll for his suggestions and reviews
- *
- * Copyright (C) 2008, 2007, 2006, 2005, 2004
- *
- * This code is released using a dual license strategy: GPL/LGPL
- * You can choose the licence that better fits your requirements.
- *
- * Released under the terms of the GNU General Public License Version 2.0
- * Released under the terms of the GNU Lesser General Public License Version 2.1
- *
- */
-
-#ifndef _TLSF_H_
-#define _TLSF_H_
-
-#include <sys/types.h>
-
-extern size_t init_memory_pool(size_t, void *);
-extern size_t get_used_size(void *);
-extern size_t get_max_size(void *);
-extern void destroy_memory_pool(void *);
-extern size_t add_new_area(void *, size_t, void *);
-extern void *malloc_ex(size_t, void *);
-extern void free_ex(void *, void *);
-extern void *realloc_ex(void *, size_t, void *);
-extern void *calloc_ex(size_t, size_t, void *);
-
-extern void *tlsf_malloc(size_t size);
-extern void tlsf_free(void *ptr);
-extern void *tlsf_realloc(void *ptr, size_t size);
-extern void *tlsf_calloc(size_t nelem, size_t elem_size);
-
-#endif
diff --git a/lib/tlsfnim.nim b/lib/tlsfnim.nim
deleted file mode 100644
index 249607e2d..000000000
--- a/lib/tlsfnim.nim
+++ /dev/null
@@ -1,698 +0,0 @@
-#
-#
-#            Nimrod's Runtime Library
-#        (c) Copyright 2008 Andreas Rumpf
-#
-#    See the file "copying.txt", included in this
-#    distribution, for details about the copyright.
-#
-
-
-# Memory manager. Based on:
-# Two Levels Segregate Fit memory allocator (TLSF)
-# Version 2.4.2
-#
-# Written by Miguel Masmano Tello <mimastel@doctor.upv.es>
-#
-# Thanks to Ismael Ripoll for his suggestions and reviews
-#
-# Copyright (C) 2008, 2007, 2006, 2005, 2004
-# 
-# This code is released using a dual license strategy: GPL/LGPL
-# You can choose the licence that better fits your requirements.
-# 
-# Released under the terms of the GNU General Public License Version 2.0
-# Released under the terms of the GNU Lesser General Public License Version 2.1
-
-
-# Some IMPORTANT TLSF parameters
-const
-  blockAlign = sizeof(pointer) * 2
-  maxFli = 30
-  maxLog2Sli = 5
-  maxSli = 1 shl maxLog2Sli
-  
-  fliOffset = 6 # tlsf structure just will manage blocks bigger than 128 bytes
-  smallBlock = 128
-  realFli = MaxFli - fliOffset
-  
-type
-  TFreePtr {.final.} = object
-    prev, next: PBhdr
-  Pbhdr = ptr Tbhdr
-  Tbhdr {.final.} = object
-    prevHdr: Pbhdr # this is just valid if the first bit of size is set
-    size: int # the size is stored in bytes 
-              # bit 0 indicates whether the block is used and
-              # bit 1 allows to know whether the previous block is free
-    freePtr: TFreePtr # at this offset bhdr.buffer starts (was a union in the
-                      # C version)
-  TAreaInfo  {.final.} = object  # This structure is embedded at the beginning
-                                 # of each area, giving us enough information 
-                                 # to cope with a set of areas
-    theEnd: Pbhdr
-    next: PAreaInfo
-  PAreaInfo = ptr TAreaInfo
-
-  TLSF {.final.} = object
-    tlsf_signature: int32 # the TLSF's structure signature
-    usedSize, maxSize: int
-    areaHead: PAreaInfo # A linked list holding all the existing areas
-
-    flBitmap: int32  # the first-level bitmap
-                     # This array should have a size of REAL_FLI bits
-    slBitmap: array[0..realFli, int32] # the second-level bitmap
-    matrix: array [0..realFli, array[0..maxSli, PBhdr]]
-  
-const
-  minBlockSize = sizeof(TFreePtr)
-  bhdrOverhead = sizeof(Tbhdr) - minBlockSize
-  tlsfSignature = 0x2A59FA59
-  ptrMask = sizeof(pointer) - 1
-  blockSize = 0xFFFFFFFF - ptrMask
-  memAlign = blockAlign - 1
-  blockState = 0x1
-  prevState = 0x2
-
-  freeBlock = 0x1 # bit 0 of the block size
-  usedBlock = 0x0
-
-  prevFree = 0x2 # bit 1 of the block size
-  prevUsed = 0x0
-  
-  defaultAreaSize = 64*1024 # 1024*10
-  pageSize = if defined(cpu32): 4096 else: 4096*2
-  
-
-proc getNextBlock(adr: pointer, r: int): PBhdr {.inline.} = 
-  return cast[PBhdr](cast[TAddress](adr) +% r)
-
-proc roundupSize(r: int): int = return (r +% memAlign) and not memAlign
-proc rounddownSize(r: int): int = return r and not memAlign
-proc roundup(x, v: int): int = return (((not x)+%1) and (v-%1)) +% x
-
-proc addSize(s: PTLSF, b: Pbhdr) =
-  inc(s.usedSize, (b.size and blockSize) + bhdrOverhead)
-  s.maxSize = max(s.maxSize, s.usedSize)
-
-proc removeSize(s: PTLSF, b: Pbhdr) =
-  dec(s.usedSize, (b.size and blockSize) + bhdrOverhead)
-
-# ------------ platform specific code -----------------------------------------
-
-when defined(posix): 
-  const # XXX: make these variables for portability?
-    PROT_READ  = 1             # page can be read 
-    PROT_WRITE = 2             # page can be written 
-    PROT_EXEC  = 4             # page can be executed 
-    PROT_NONE  = 0             # page can not be accessed 
-
-    MAP_SHARED    = 1          # Share changes 
-    MAP_PRIVATE   = 2          # Changes are private 
-    MAP_TYPE      = 0xf        # Mask for type of mapping 
-    MAP_FIXED     = 0x10       # Interpret addr exactly 
-    MAP_ANONYMOUS = 0x20       # don't use a file 
-
-    MAP_GROWSDOWN  = 0x100     # stack-like segment 
-    MAP_DENYWRITE  = 0x800     # ETXTBSY 
-    MAP_EXECUTABLE = 0x1000    # mark it as an executable 
-    MAP_LOCKED     = 0x2000    # pages are locked 
-    MAP_NORESERVE  = 0x4000    # don't check for reservations 
-
-  proc mmap(adr: pointer, len: int, prot, flags, fildes: cint,
-            off: int): pointer {.header: "<sys/mman.h>".}
-
-  proc getNewArea(size: var int): pointer {.inline.} = 
-    size = roundup(size, PageSize)
-    result = mmap(0, size, PROT_READ or PROT_WRITE, 
-                           MAP_PRIVATE or MAP_ANONYMOUS, -1, 0)
-    if result == nil or result == cast[pointer](-1):
-      raiseOutOfMem()
-  
-elif defined(windows): 
-  const
-    MEM_RESERVE = 0x2000 
-    MEM_COMMIT = 0x1000
-    MEM_TOP_DOWN = 0x100000
-    PAGE_READWRITE = 0x04
-
-  proc VirtualAlloc(lpAddress: pointer, dwSize: int, flAllocationType,
-                    flProtect: int32): pointer {.
-                    header: "<windows.h>", stdcall.}
-  
-  proc getNewArea(size: var int): pointer {.inline.} = 
-    size = roundup(size, PageSize)
-    result = VirtualAlloc(nil, size, MEM_RESERVE or MEM_COMMIT or MEM_TOP_DOWN,
-                          PAGE_READWRITE)
-    if result == nil: raiseOutOfMem()
-
-else: 
-  {.warning: "Generic code for allocating pages is used".}
-  # generic implementation relying on malloc:
-  proc malloc(size: int): pointer {.nodecl, importc.}
-  
-  proc getNewArea(size: var int): pointer {.inline.} = 
-    size = roundup(size, PageSize)
-    result = malloc(size)
-    if result == nil: raiseOutOfMem()
-
-# ---------------------------------------------------------------------------
-# small fixed size allocator:
-
-# Design: We manage pages. A page is of constant size, but not necessarily
-# the OS's page size. Pages are managed in a hash table taking advantage of
-# the fact that the OS is likely to give us pages with contingous numbers. 
-# A page contains either small fixed size objects of the same size or 
-# variable length objects. An object's size is always aligned at 16 byte
-# boundary. Huge objects are dealt with the TLSF algorithm. 
-# The design supports iterating over any object in a fast way. 
-
-# A bitset contains any page that starts an allocated page. The page may be
-# empty however. This bitset can be used to quickly determine if a given
-# page belongs to the GC heap. The design of the memory allocator makes it 
-# simple to return unused pages back to the OS.
-
-
-# Small bocks 
-# -----------
-#
-# If we use a list in the free object's space. Allocation and deallocation are
-# O(1). Since any object is of the same size, iteration is quite efficient too.
-# However, pointer detection is easy too: Just check if the type-field is nil.
-# Deallocation sets it to nil.
-# Algorithm:
-
-# i = 0
-# f = b.f # first free address
-# while i < max: 
-#  if a[i] == f: # not a valid block
-#    f = f.next  # next free address
-#  else:
-#    a[i] is a valid object of size s
-#  inc(i)
-
-# The zero count table is an array. Since we know that the RC is zero, we can
-# use the bits for an index into this array. Thus multiple ZCT tables are not
-# difficult to support and insertion and removal is O(1). We use negative
-# indexes for this. This makes it even fast enough (and necessary!) to do a ZCT
-# removal if the RC is incremented. 
-# 
-
-# Huge blocks
-# -----------
-#
-# Huge blocks are always rounded up to a multiple of the page size. These are
-# called *strides*. We also need to keep an index structure 
-# of (stridesize, pagelist). 
-# 
-
-const
-  MemAlign = 8
-  PageShift = if sizeof(int) == 4: 12 else: 13
-  PageSize = 1 shl PageShift
-type
-  TFreeList {.final.} = object
-    next, prev: ptr TFreeList
-
-  TPageDesc {.final.} = object  # the start of a stride always starts with this!
-    size: int                   # lowest bit is set, if it is a huge block
-    free: ptr TFreeList         # only used if it manages multiple cells
-    snext, sprev: ptr TPageDesc # next and prev pagedescs with the same size
-
-  TCellArray {.final.} = object
-    i: int # length
-    d: ptr array [0..1000_000, TCell]
-
-  TPageManager = table[page, ptr TPageDesc]
-
-  TGcHeap {.final.} = object
-    # structure that manages the garbage collected heap
-    zct: TCellArray
-    stackCells: TCellArray
-    smallBlocks: array [PageSize div MemAlign, ptr TPageDesc]
-    freeLists: array [PageSize div MemAlign, ptr TFreeList]
-    pages: TPageManager
-    usedPages: TPageList
-    freePages: TPageList
-
-# small blocks: 
-proc allocSmall(var h: TGcHeap, size: int): pointer = 
-  var s = align(size)
-  var f = h.freeLists[s]
-  if f != nil: 
-    f.prev = f.next # remove from list
-    f.next.prev = f.prev
-    return f
-  var p = h.smallBlocks[s]
-  if p == nil or p.free == nil:
-    p = newSmallBlock(s, p)
-    h.smallBlocks[s] = p
-  
-
-
-proc decRef(cell: PCell) {.inline.} =
-  assert(cell in ct.AT)
-  assert(cell.refcount > 0) # this should be the case!
-  assert(seqCheck(cell))
-  dec(cell.refcount)
-  if cell.refcount == 0:
-    # add to zero count table:
-    zct.d[zct.i] = cell
-    cell.recfcount = -zct.i
-    inc(zct.i)
-
-proc incRef(cell: PCell) {.inline.} =
-  assert(seqCheck(cell))
-  if cell.refcount < 0: 
-    # remove from zero count table:
-    zct.d[-cell.refcount] = zct.d[zct.i-1]
-    dec(zct.i) 
-    cell.refcount = 1
-  else:
-    inc(cell.refcount)
-
-proc asgnRef(dest: ppointer, src: pointer) =
-  # the code generator calls this proc!
-  assert(not isOnStack(dest))
-  # BUGFIX: first incRef then decRef!
-  if src != nil: incRef(usrToCell(src))
-  if dest^ != nil: decRef(usrToCell(dest^))
-  dest^ = src
-
-
-# ----------------------------------------------------------------------------
-#     helpers
-
-const
-  table: array[0..255, int8] = [
-      -1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4,
-      4, 4, 4, 4, 4, 4, 4, 4, 4,
-      5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
-      5, 5, 5, 5, 5, 5, 5, 5,
-      6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
-      6, 6, 6, 6, 6, 6, 6, 6,
-      6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
-      6, 6, 6, 6, 6, 6, 6, 6,
-      7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
-      7, 7, 7, 7, 7, 7, 7, 7,
-      7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
-      7, 7, 7, 7, 7, 7, 7, 7,
-      7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
-      7, 7, 7, 7, 7, 7, 7, 7,
-      7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
-      7, 7, 7, 7, 7, 7, 7, 7
-    ]
-
-proc ls_bit(i: int32): int {.inline.} = 
-  var 
-    a: int = 0
-    x: int = i and -i
-  if x <=% 0xffff:
-    if x <=% ff: a = 0
-    else: a = 8
-  elif x <=% 0xffffff: a = 16
-  else: a = 24
-  return table[x shr a] + a
-
-proc ms_bit(i: int): int {.inline.} = 
-  var
-    a = if i <=% 0xffff: (if i <=% 0xff: 0 else: 8) elif 
-           i <=% 0xffffff: 16 else: 24
-  return table[i shr a] + a
-
-proc set_bit[IX](nr: int, adr: var array[IX, int32]) {.inline.} =
-  adr[nr shr 5] = adr[nr shr 5] or (1 shl (nr and 0x1f))
-
-proc clear_bit[IX](nr: int, adr: var array[IX, int32]) {.inline.} =
-  adr[nr shr 5] = adr[nr shr 5] and not (1 shl (nr and 0x1f))
-
-proc mappingSearch(r, fl, sl: var int) {.inline.} = 
-  if r < smallBlock: 
-    fl = 0
-    sl = r div (smallBlock div maxSli)
-  else:
-    var t = (1 shl (ms_bit(r) - maxLog2Sli)) - 1
-    r = r + t
-    fl = ms_bit(r)
-    sl = (r shl (fl - maxLog2Sli)) - maxSli
-    fl = fl - fliOffset
-    r = r and not t
-
-proc mappingInsert(r: int, fl, sl: var int) {.inline.} = 
-  if r < smallBlock:
-    fl = 0
-    sl = r div (smallBlock div maxSli)
-  else:
-    fl = ms_bit(r)
-    sl = (r shr (fl - maxLog2Sli)) - maxSli
-    fl = fl - fliOffset
-
-proc findSuitableBlock(t: var TLSF, fl, sl: var int): Pbhdr =
-  var tmp = t.slBitmap[fl] and ((not 0) shl sl)
-  if tmp != 0:
-    sl = ls_bit(tmp)
-    result = t.matrix[fl][sl]
-  else:
-    fl = ls_bit(t.flBitmap and (not 0 shl (fl + 1)))
-    if fl > 0: # likely
-      sl = ls_bit(t.slBitmap[fl])
-      result = t.matrix[fl][sl]
-
-proc extractBlockHdr(b: Pbhdr, t: var TLSF, fl, sl: int) {.inline.} = 
-  t.matrix[fl][sl] = b.freePtr.next
-  if t.matrix[fl][sl] != nil:
-    t.matrix[fl][sl].freePtr.prev = nil
-  else:
-    clear_bit(sl, t.slBitmap[fl])
-    if t.slBitmap[fl] == 0:
-      clear_bit(fl, t.flBitmap)
-  b.freePtr.prev = nil
-  b.freePtr.next = nil
-
-proc extractBlock(b: Pbhdr, t: var TLSF, fl, sl: int) {.inline.} =
-  if b.freePtr.next != nil:
-    b.freePtr.next.freePtr.prev = b.freePtr.prev
-  if b.freePtr.prev != nil:
-    b.freePtr.prev.freePtr.next = b.freePtr.next
-  if t.matrix[fl][sl] == b:
-    t.matrix[fl][sl] = b.freePtr.next
-    if t.matrix[fl][sl] == nil:
-      clear_bit(sl, t.slBitmap[fl])
-      if t.slBitmap[fl] == 0:
-        clear_bit(fl, t.flBitmap)
-  b.freePtr.prev = nil
-  b.freePtr.next = nil
-
-proc insertBlock(b: Pbhdr, t: var TLSF, fl, sl: int) {.inline.} = 
-  b.freePtr.prev = nil
-  b.freePtr.next = t.matrix[fl][sl] 
-  if t.matrix[fl][sl] != nil:
-    t.matrix[fl][sl].freePtr.prev = b		
-  t.matrix[fl][sl] = b
-  set_bit(sl, t.slBitmap[fl])
-  set_bit(fl, t.flBitmap)
-
-proc getBuffer(b: Pbhdr): pointer {.inline.} = 
-  result = cast[pointer](addr(b.freePtr))
-
-proc processArea(area: pointer, size: int): Pbhdr =
-  var 
-    b, lb, ib: Pbhdr
-    ai: PAreaInfo
-  ib = cast[Pbhdr](area)
-  if sizeof(TAreaInfo) < minBlockSize:
-    ib.size = minBlockSize or usedBlock or prevUsed
-  else
-    ib.size = roundupSize(sizeof(TAreaInfo)) or usedBlock or prevUsed
-  b = getNextBlock(getBuffer(ib), ib.size and blockSize)
-  b.size = rounddownSize(size - 3 * bhdrOverhead - (ib.size and blockSize)) or
-           usedBlock or prevUsed
-  b.freePtr.prev = nil
-  b.freePtr.next = nil
-  lb = getNextBlock(getBuffer(b), b.size and blockSize)
-  lb.prevHdr = b
-  lb.size = 0 or usedBlock or prevFree
-  ai = cast[PAreaInfo](getBuffer(ib))
-  ai.next = nil
-  ai.theEnd = lb
-  return ib
-
-# ----------------------------------------------------------------------------
-#                  Begin of the allocator code
-
-proc initMemoryPool(memPoolSize: int, memPool: pointer): int = 
-  var
-    t: PLSF
-    b, ib: Pbhdr
-
-  if memPool == nil or memPoolSize < sizeof(TLSF) + bhdrOverhead * 8:
-    writeToStdErr("initMemoryPool(): memory_pool invalid\n")
-    return -1
-
-  if (cast[TAddress](memPool) and ptrMask) != 0:
-    writeToStdErr("initMemoryPool(): memPool must be aligned to a word\n")
-    return -1
-  t = cast[PLSF](memPool)
-  # Check if already initialised
-  if t.signature == tlsfSignature:
-    b = getNextBlock(memPool, roundupSize(sizeof(TLSF)))
-    return b.size and blockSize
-  zeroMem(memPool, sizeof(TLSF))
-
-  t.signature = tlsfSignature
-  ib = processArea(getNextBlock(memPool, roundupSize(sizeof(TLSF))), 
-                   rounddownSize(memPoolSize - sizeof(TLSF)))
-  b = getNextBlock(getBuffer(ib), ib.size and blockSize)
-  freeEx(getBuffer(b), t)
-  t.areaHead = cast[PAreaInfo](getBuffer(ib))
-
-  t.used_size = memPoolSize - (b.size and blockSize)
-  t.max_size = t.used_size
-  return b.size and blockSize
-
-
-proc addNewArea(area: pointer, areaSize: int, t: var TLSF): int = 
-  var
-    p, ptrPrev, ai: PAreaInfo
-    ib0, b0, lb0, ib1, b1, lb1, nextB: Pbhdr
-
-  zeroMem(area, areaSize)
-  p = t.areaHead
-  ptrPrev = 0
-
-  ib0 = processArea(area, areaSize)
-  b0 = getNextBlock(getBuffer(ib0), ib0.size and blockSize)
-  lb0 = getNextBlock(getBuffer(b0), b0.size and blockSize)
-
-  # Before inserting the new area, we have to merge this area with the
-  # already existing ones
-  while p != nil:
-    ib1 = cast[Pbhdr](cast[TAddress](p) -% bhdrOverhead) 
-    b1 = getNextBlock(getBuffer(ib1), ib1.size and blockSize)
-    lb1 = p.theEnd
-
-    # Merging the new area with the next physically contigous one
-    if cast[TAddress](ib1) == cast[TAddress](lb0) +% bhdrOverhead:
-      if t.areaHead == p:
-        t.areaHead = p.next
-        p = p.next
-      else:
-        ptrPrev.next = p.next
-        p = p.next
-      b0.size = rounddownSize((b0.size and blockSize) +
-                         (ib1.size and blockSize) + 2 * bhdrOverhead) or
-                         usedBlock or prevUsed
-      b1.prevHdr = b0
-      lb0 = lb1
-      continue
-
-    # Merging the new area with the previous physically contigous one
-    if getBuffer(lb1) == pointer(ib0):
-      if t.areaHead == p:
-        t.areaHead = p.next
-        p = p.next
-      else:
-        ptrPrev.next = p.next
-        p = p.next
-      lb1->size = rounddownSize((b0.size and blockSize) +
-                   (ib0.size and blockSize) + 2 * bhdrOverhead) or
-                   usedBlock or (lb1.size and prevState)
-      nextB = getNextBlock(getBuffer(lb1), lb1.size and blockSize)
-      nextB.prevHdr = lb1
-      b0 = lb1
-      ib0 = ib1
-      continue
-    ptrPrev = p
-    p = p.next
-
-  # Inserting the area in the list of linked areas 
-  ai = cast[PAreaInfo](getBuffer(ib0))
-  ai.next = t.areaHead
-  ai.theEnd = lb0
-  t.areaHead = ai
-  freeEx(getBuffer(b0), memPool)
-  return (b0.size and blockSize)
-
-proc mallocEx(asize: int, t: var TLSF): pointer = 
-  var
-    b, b2, nextB: Pbhdr
-    fl, sl, tmpSize, size: int
-
-  size = if asize < minBlockSize: minBlockSize else: roundupSize(asize)
-
-  # Rounding up the requested size and calculating fl and sl
-  mappingSearch(size, fl, sl)
-
-  # Searching a free block, recall that this function changes the values
-  # of fl and sl, so they are not longer valid when the function fails
-  b = findSuitableBlock(tlsf, fl, sl)
-  if b == nil: 
-    # Growing the pool size when needed 
-    # size plus enough room for the required headers:
-    var areaSize = max(size + bhdrOverhead * 8, defaultAreaSize)
-    var area = getNewArea(areaSize)
-    addNewArea(area, areaSize, t)
-    # Rounding up the requested size and calculating fl and sl
-    mappingSearch(size, fl, sl)
-    # Searching a free block
-    b = findSuitableBlock(t, fl, sl)
-    if b == nil: 
-      raiseOutOfMem()
-
-  extractBlockHdr(b, t, fl, sl)
-
-  #-- found:
-  nextB = getNextBlock(getBuffer(b), b.size and blockSize)
-  # Should the block be split?
-  tmpSize = (b.size and blockSize) - size
-  if tmpSize >= sizeof(Tbhdr):
-    dec(tmpSize, bhdrOverhead)
-    b2 = getNextBlock(getBuffer(b), size)
-    b2.size = tmpSize or freeBlock or prevUsed
-    nextB.prevHdr = b2
-    mappingInsert(tmpSize, fl, sl)
-    insertBlock(b2, t, fl, sl)
-
-    b.size = size or (b.size and prevState)
-  else:
-    nextB.size = nextB.size and not prevFree
-    b.size = b.size and not freeBlock # Now it's used
-
-  addSize(t, b)
-  return getBuffer(b)
-
-
-proc freeEx(p: pointer, t: var TLSF) =
-  var
-    fl = 0
-    sl = 0
-    b, tmpB: Pbhdr
-
-  assert(p != nil)
-  b = cast[Pbhdr](cast[TAddress](p) -% bhdrOverhead)
-  b.size = b.size or freeBlock
-
-  removeSize(t, b)
-  b.freePtr.prev = nil
-  b.freePtr.next = nil
-  tmpB = getNextBlock(getBuffer(b), b.size and blockSize)
-  if (tmpB.size and freeBlock) != 0:
-    mappingInsert(tmpB.size and blockSize, fl, sl)
-    extractBlock(tmpB, t, fl, sl)
-    inc(b.size, (tmpB.size and blockSize) + bhdrOverhead)
-  if (b.size and prevFree) != 0:
-    tmpB = b.prevHdr
-    mappingInsert(tmpB.size and blockSize, fl, sl)
-    extractBlock(tmpB, t, fl, sl)
-    inc(tmpB.size, (b.size and blockSize) + bhdrOverhead)
-    b = tmpB
-  mappingInsert(b.size and blockSize, fl, sl)
-  insertBlock(b, t, fl, sl)
-
-  tmpB = getNextBlock(getBuffer(b), b.size and blockSize)
-  tmpB.size = tmpB.size or prevFree
-  tmpB.prevHdr = b
-
-proc reallocEx(p: pointer, newSize: int, t: var TLSF): pointer = 
-  var
-    cpsize, fl, sl, tmpSize: int
-    b, tmpB, nextB: Pbhdr
-
-  assert(p != nil)
-  assert(newSize > 0)
-
-  b = cast[Pbhdr](cast[TAddress](p) -% bhdrOverhead)
-  nextB = getNextBlock(getBuffer(b), b.size and blockSize)
-  newSize = if newSize < minBlockSize: minBlockSize else: roundupSize(newSize)
-  tmpSize = b.size and blockSize
-  if newSize <= tmpSize:
-    removeSize(t, b)
-    if (nextB.size and freeBlock) != 0: 
-      mappingInsert(nextB.size and blockSize, fl, sl)
-      extractBlock(nextB, t, fl, sl)
-      inc(tmpSize, (nextB.size and blockSize) + bhdrOverhead)
-      nextB = getNextBlock(getBuffer(nextB), nextB.size and blockSize)
-      # We always reenter this free block because tmpSize will
-      # be greater then sizeof(Tbhdr)
-    dec(tmpSize, newSize)
-    if tmpSize >= sizeof(Tbhdr):
-      dec(tmpSize, bhdrOverhead)
-      tmpB = getNextBlock(getBuffer(b), newSize)
-      tmpB.size = tmpSize or freeBlock or prevUsed
-      nextB.prevHdr = tmpB
-      nextB.size = nextB.size or prevFree
-      mappingInsert(tmpSize, fl, sl)
-      insertBlock(tmpB, t, fl, sl)
-      b.size = newSize or (b.size and prevState)
-    addSize(t, b)
-    return getBuffer(b)
-  
-  if (nextB.size and freeBlock) != 0:
-    if newSize <= tmpSize + (nextB.size and blockSize):
-      removeSize(t, b)
-      mappingInsert(nextB.size and blockSize, fl, sl)
-      extractBlock(nextB, t, fl, sl)
-      inc(b.size, (nextB.size and blockSize) + bhdrOverhead)
-      nextB = getNextBlock(getBuffer(b), b.size and blockSize)
-      nextB.prevHdr = b
-      nextB.size = nextB.size and not prevFree
-      tmpSize = (b.size and blockSize) - newSize
-      if tmpSize >= sizeof(Tbhdr):
-        dec(tmpSize, bhdrOverhead)
-        tmpB = getNextBlock(getBuffer(b), newSize)
-        tmpB.size = tmpSize or freeBlock or prevUsed
-        nextB.prevHdr = tmpB
-        nextB.size = nextB.size or prevFree
-        mappingInsert(tmpSize, fl, sl)
-        insertBlock(tmpB, t, fl, sl)
-        b.size = newSize or (b.size and prevState)
-      addSize(t, b)
-      return getBuffer(b)
-
-  var ptrAux = mallocEx(newSize, t)
-  cpsize = if (b.size and blockSize) > newSize: newSize else:
-                                                (b.size and blockSize)
-  copyMem(ptrAux, p, cpsize)
-  freeEx(p, memPool)
-  return ptrAux
-
-
-proc ansiCrealloc(p: pointer, newSize: int, t: var TLSF): pointer = 
-  if p == nil: 
-    if newSize > 0: 
-      result = mallocEx(newSize, t)
-    else:
-      result = nil
-  elif newSize <= 0:
-    freeEx(p, t)
-    result = nil
-  else:
-    result = reallocEx(p, newSize, t)
-
-proc InitTLSF(t: var TLSF) = 
-  var areaSize = sizeof(TLSF) + BHDR_OVERHEAD * 8 # Just a safety constant
-  areaSize = max(areaSize, DEFAULT_areaSize)
-  var area = getNewArea(areaSize)
-  
-  
-  initMemoryPool(areaSize, area)
-
-  var
-    t: PLSF
-    b, ib: Pbhdr
-
-  t = cast[PLSF](memPool)
-  
-  zeroMem(area, areaSize)
-
-  t.signature = tlsfSignature
-  var ib = processArea(getNextBlock(memPool, roundupSize(sizeof(TLSF))), 
-                   rounddownSize(memPoolSize - sizeof(TLSF)))
-  var b = getNextBlock(getBuffer(ib), ib.size and blockSize)
-  freeEx(getBuffer(b), t)
-  t.areaHead = cast[PAreaInfo](getBuffer(ib))
-
-  t.used_size = memPoolSize - (b.size and blockSize)
-  t.max_size = t.used_size
-
-  # XXX
diff --git a/lib/winlean.nim b/lib/windows/winlean.nim
index 747ce7db5..b497ddad3 100644
--- a/lib/winlean.nim
+++ b/lib/windows/winlean.nim
@@ -105,4 +105,82 @@ proc SetStdHandle*(nStdHandle: int32, hHandle: THANDLE): WINBOOL {.stdcall,
     dynlib: "kernel32", importc: "SetStdHandle".}

 proc FlushFileBuffers*(hFile: THANDLE): WINBOOL {.stdcall, dynlib: "kernel32",

     importc: "FlushFileBuffers".}

-

+
+proc GetLastError*(): int32 {.importc, stdcall, dynlib: "kernel32".}
+proc FormatMessageA*(dwFlags: int32, lpSource: pointer,
+                    dwMessageId, dwLanguageId: int32,
+                    lpBuffer: pointer, nSize: int32,
+                    Arguments: pointer): int32 {.
+                    importc, stdcall, dynlib: "kernel32".}
+proc LocalFree*(p: pointer) {.importc, stdcall, dynlib: "kernel32".}
+
+proc GetCurrentDirectoryA*(nBufferLength: int32, lpBuffer: cstring): int32 {.
+  importc, dynlib: "kernel32", stdcall.}
+proc SetCurrentDirectoryA*(lpPathName: cstring): int32 {.
+  importc, dynlib: "kernel32", stdcall.}
+proc CreateDirectoryA*(pathName: cstring, security: Pointer): int32 {.
+  importc: "CreateDirectoryA", dynlib: "kernel32", stdcall.}
+proc RemoveDirectoryA*(lpPathName: cstring): int32 {.
+  importc, dynlib: "kernel32", stdcall.}
+proc SetEnvironmentVariableA*(lpName, lpValue: cstring): int32 {.
+  stdcall, dynlib: "kernel32", importc.}
+
+proc GetModuleFileNameA*(handle: THandle, buf: CString, size: int32): int32 {.
+  importc, dynlib: "kernel32", stdcall.}
+
+const
+  FILE_ATTRIBUTE_ARCHIVE* = 32'i32
+  FILE_ATTRIBUTE_COMPRESSED* = 2048'i32
+  FILE_ATTRIBUTE_NORMAL* = 128'i32
+  FILE_ATTRIBUTE_DIRECTORY* = 16'i32
+  FILE_ATTRIBUTE_HIDDEN* = 2'i32
+  FILE_ATTRIBUTE_READONLY* = 1'i32
+  FILE_ATTRIBUTE_SYSTEM* = 4'i32
+
+  MAX_PATH* = 260
+type
+  FILETIME* {.final, pure.} = object ## CANNOT BE int64 BECAUSE OF ALIGNMENT
+    dwLowDateTime*: int32
+    dwHighDateTime*: int32
+  TWIN32_FIND_DATA* {.pure.} = object
+    dwFileAttributes*: int32
+    ftCreationTime*: FILETIME
+    ftLastAccessTime*: FILETIME
+    ftLastWriteTime*: FILETIME
+    nFileSizeHigh*: int32
+    nFileSizeLow*: int32
+    dwReserved0: int32
+    dwReserved1: int32
+    cFileName*: array[0..(MAX_PATH) - 1, char]
+    cAlternateFileName*: array[0..13, char]
+proc FindFirstFileA*(lpFileName: cstring,
+                    lpFindFileData: var TWIN32_FIND_DATA): THANDLE {.
+    stdcall, dynlib: "kernel32", importc: "FindFirstFileA".}
+proc FindNextFileA*(hFindFile: THANDLE,
+                   lpFindFileData: var TWIN32_FIND_DATA): int32 {.
+    stdcall, dynlib: "kernel32", importc: "FindNextFileA".}
+proc FindClose*(hFindFile: THANDLE) {.stdcall, dynlib: "kernel32",
+  importc: "FindClose".}
+
+proc GetFullPathNameA*(lpFileName: cstring, nBufferLength: int32,
+                      lpBuffer: cstring, lpFilePart: var cstring): int32 {.
+                      stdcall, dynlib: "kernel32", importc.}
+proc GetFileAttributesA*(lpFileName: cstring): int32 {.
+                        stdcall, dynlib: "kernel32", importc.}
+proc SetFileAttributesA*(lpFileName: cstring, dwFileAttributes: int32): WINBOOL {.
+    stdcall, dynlib: "kernel32", importc: "SetFileAttributesA".}
+
+proc CopyFileA*(lpExistingFileName, lpNewFileName: CString,
+               bFailIfExists: cint): cint {.
+  importc, stdcall, dynlib: "kernel32".}
+
+proc GetEnvironmentStringsA*(): cstring {.
+  stdcall, dynlib: "kernel32", importc.}
+proc FreeEnvironmentStringsA*(para1: cstring): int32 {.
+  stdcall, dynlib: "kernel32", importc.}
+
+proc GetCommandLineA*(): CString {.importc, stdcall, dynlib: "kernel32".}
+
+proc rdFileTime*(f: FILETIME): int64 = 
+  result = ze64(f.dwLowDateTime) or (ze64(f.dwHighDateTime) shl 32)
+
diff --git a/lib/base/cairo/cairo.nim b/lib/wrappers/cairo/cairo.nim
index 6da8183f3..6da8183f3 100644
--- a/lib/base/cairo/cairo.nim
+++ b/lib/wrappers/cairo/cairo.nim
diff --git a/lib/base/cairo/cairoft.nim b/lib/wrappers/cairo/cairoft.nim
index 2418aa922..2418aa922 100644
--- a/lib/base/cairo/cairoft.nim
+++ b/lib/wrappers/cairo/cairoft.nim
diff --git a/lib/base/cairo/cairowin32.nim b/lib/wrappers/cairo/cairowin32.nim
index 5d07c2611..5d07c2611 100644
--- a/lib/base/cairo/cairowin32.nim
+++ b/lib/wrappers/cairo/cairowin32.nim
diff --git a/lib/base/cairo/cairoxlib.nim b/lib/wrappers/cairo/cairoxlib.nim
index dfe44eb87..dfe44eb87 100644
--- a/lib/base/cairo/cairoxlib.nim
+++ b/lib/wrappers/cairo/cairoxlib.nim
diff --git a/lib/base/gtk/atk.nim b/lib/wrappers/gtk/atk.nim
index ae7a34c4b..ae7a34c4b 100644
--- a/lib/base/gtk/atk.nim
+++ b/lib/wrappers/gtk/atk.nim
diff --git a/lib/base/gtk/gdk2.nim b/lib/wrappers/gtk/gdk2.nim
index 0ca5056b5..0ca5056b5 100644
--- a/lib/base/gtk/gdk2.nim
+++ b/lib/wrappers/gtk/gdk2.nim
diff --git a/lib/base/gtk/gdk2pixbuf.nim b/lib/wrappers/gtk/gdk2pixbuf.nim
index daaa1479b..daaa1479b 100644
--- a/lib/base/gtk/gdk2pixbuf.nim
+++ b/lib/wrappers/gtk/gdk2pixbuf.nim
diff --git a/lib/base/gtk/gdkglext.nim b/lib/wrappers/gtk/gdkglext.nim
index 524b5f730..524b5f730 100644
--- a/lib/base/gtk/gdkglext.nim
+++ b/lib/wrappers/gtk/gdkglext.nim
diff --git a/lib/base/gtk/glib2.nim b/lib/wrappers/gtk/glib2.nim
index aca1b5551..aca1b5551 100644
--- a/lib/base/gtk/glib2.nim
+++ b/lib/wrappers/gtk/glib2.nim
diff --git a/lib/base/gtk/gtk2.nim b/lib/wrappers/gtk/gtk2.nim
index d1e72e708..d1e72e708 100644
--- a/lib/base/gtk/gtk2.nim
+++ b/lib/wrappers/gtk/gtk2.nim
diff --git a/lib/base/gtk/gtkglext.nim b/lib/wrappers/gtk/gtkglext.nim
index 38da5d25e..38da5d25e 100644
--- a/lib/base/gtk/gtkglext.nim
+++ b/lib/wrappers/gtk/gtkglext.nim
diff --git a/lib/base/gtk/gtkhtml.nim b/lib/wrappers/gtk/gtkhtml.nim
index d015a78bc..d015a78bc 100644
--- a/lib/base/gtk/gtkhtml.nim
+++ b/lib/wrappers/gtk/gtkhtml.nim
diff --git a/lib/base/gtk/libglade2.nim b/lib/wrappers/gtk/libglade2.nim
index 5e323680e..5e323680e 100644
--- a/lib/base/gtk/libglade2.nim
+++ b/lib/wrappers/gtk/libglade2.nim
diff --git a/lib/base/gtk/pango.nim b/lib/wrappers/gtk/pango.nim
index ade2da989..ade2da989 100644
--- a/lib/base/gtk/pango.nim
+++ b/lib/wrappers/gtk/pango.nim
diff --git a/lib/base/gtk/pangoutils.nim b/lib/wrappers/gtk/pangoutils.nim
index e6f3ab94c..e6f3ab94c 100644
--- a/lib/base/gtk/pangoutils.nim
+++ b/lib/wrappers/gtk/pangoutils.nim
diff --git a/lib/base/libcurl.nim b/lib/wrappers/libcurl.nim
index 5d54a2640..5d54a2640 100644
--- a/lib/base/libcurl.nim
+++ b/lib/wrappers/libcurl.nim
diff --git a/lib/base/lua/lauxlib.nim b/lib/wrappers/lua/lauxlib.nim
index 143a6cc46..b9a0a8d04 100644
--- a/lib/base/lua/lauxlib.nim
+++ b/lib/wrappers/lua/lauxlib.nim
@@ -21,7 +21,7 @@
 #**   In french or in english
 #
 
-import "lib/base/lua/lua"
+import lua
 
 proc lua_pushstring*(L: Plua_State, s: string)
   # compatibilty macros
diff --git a/lib/base/lua/lua.nim b/lib/wrappers/lua/lua.nim
index ab872fd23..9bf4e673e 100644
--- a/lib/base/lua/lua.nim
+++ b/lib/wrappers/lua/lua.nim
@@ -37,16 +37,16 @@
 
 when defined(MACOSX): 
   const 
-    LUA_NAME* = "liblua5.1.dylib"
-    LUA_LIB_NAME* = "liblua5.1.dylib"
+    LUA_NAME* = "liblua(5.2|5.1|5.0).dylib"
+    LUA_LIB_NAME* = "liblua(5.2|5.1|5.0).dylib"
 elif defined(UNIX): 
   const 
-    LUA_NAME* = "liblua5.1.so"
-    LUA_LIB_NAME* = "liblua5.1.so"
+    LUA_NAME* = "liblua(5.2|5.1|5.0).so.0"
+    LUA_LIB_NAME* = "liblua(5.2|5.1|5.0).so.0"
 else: 
   const 
-    LUA_NAME* = "lua5.1.dll"
-    LUA_LIB_NAME* = "lua5.1.dll"
+    LUA_NAME* = "lua(5.2|5.1|5.0).dll"
+    LUA_LIB_NAME* = "lua(5.2|5.1|5.0).dll"
 type 
   size_t* = int
   Psize_t* = ptr size_t
diff --git a/lib/base/lua/lualib.nim b/lib/wrappers/lua/lualib.nim
index efd3ab923..df5d53101 100644
--- a/lib/base/lua/lualib.nim
+++ b/lib/wrappers/lua/lualib.nim
@@ -19,7 +19,7 @@
 #**   In french or in english
 #
 
-import "lib/base/lua/lua"
+import lua
 
 const 
   LUA_COLIBNAME* = "coroutine"
diff --git a/lib/base/mysql.nim b/lib/wrappers/mysql.nim
index 60c6bd80c..60c6bd80c 100644
--- a/lib/base/mysql.nim
+++ b/lib/wrappers/mysql.nim
diff --git a/lib/base/odbcsql.nim b/lib/wrappers/odbcsql.nim
index 8f8804092..8f8804092 100644
--- a/lib/base/odbcsql.nim
+++ b/lib/wrappers/odbcsql.nim
diff --git a/lib/base/opengl/gl.nim b/lib/wrappers/opengl/gl.nim
index 79f09b544..79f09b544 100644
--- a/lib/base/opengl/gl.nim
+++ b/lib/wrappers/opengl/gl.nim
diff --git a/lib/base/opengl/gl.pp b/lib/wrappers/opengl/gl.pp
index f6e0ddc39..f6e0ddc39 100644
--- a/lib/base/opengl/gl.pp
+++ b/lib/wrappers/opengl/gl.pp
diff --git a/lib/base/opengl/glext.nim b/lib/wrappers/opengl/glext.nim
index 0a2138584..0a2138584 100644
--- a/lib/base/opengl/glext.nim
+++ b/lib/wrappers/opengl/glext.nim
diff --git a/lib/base/opengl/glext.pp b/lib/wrappers/opengl/glext.pp
index 4c9fc2119..4c9fc2119 100644
--- a/lib/base/opengl/glext.pp
+++ b/lib/wrappers/opengl/glext.pp
diff --git a/lib/base/opengl/glu.nim b/lib/wrappers/opengl/glu.nim
index 297f4d354..297f4d354 100644
--- a/lib/base/opengl/glu.nim
+++ b/lib/wrappers/opengl/glu.nim
diff --git a/lib/base/opengl/glu.pp b/lib/wrappers/opengl/glu.pp
index 1594085ed..1594085ed 100644
--- a/lib/base/opengl/glu.pp
+++ b/lib/wrappers/opengl/glu.pp
diff --git a/lib/base/opengl/glut.nim b/lib/wrappers/opengl/glut.nim
index 55ee18bda..55ee18bda 100644
--- a/lib/base/opengl/glut.nim
+++ b/lib/wrappers/opengl/glut.nim
diff --git a/lib/base/opengl/glut.pp b/lib/wrappers/opengl/glut.pp
index 3a6e7d9fc..3a6e7d9fc 100644
--- a/lib/base/opengl/glut.pp
+++ b/lib/wrappers/opengl/glut.pp
diff --git a/lib/base/opengl/glx.nim b/lib/wrappers/opengl/glx.nim
index a967acfc6..a967acfc6 100644
--- a/lib/base/opengl/glx.nim
+++ b/lib/wrappers/opengl/glx.nim
diff --git a/lib/base/opengl/glx.pp b/lib/wrappers/opengl/glx.pp
index 2b8c1eed7..2b8c1eed7 100644
--- a/lib/base/opengl/glx.pp
+++ b/lib/wrappers/opengl/glx.pp
diff --git a/lib/base/opengl/wingl.nim b/lib/wrappers/opengl/wingl.nim
index 2cebf8622..2cebf8622 100644
--- a/lib/base/opengl/wingl.nim
+++ b/lib/wrappers/opengl/wingl.nim
diff --git a/lib/base/opengl/wingl.pp b/lib/wrappers/opengl/wingl.pp
index 70be6674e..70be6674e 100644
--- a/lib/base/opengl/wingl.pp
+++ b/lib/wrappers/opengl/wingl.pp
diff --git a/lib/base/pcre.nim b/lib/wrappers/pcre/pcre.nim
index 4f4c27a09..05f937579 100644
--- a/lib/base/pcre.nim
+++ b/lib/wrappers/pcre/pcre.nim
@@ -1,7 +1,7 @@
 #
 #
 #            Nimrod's Runtime Library
-#        (c) Copyright 2006 Andreas Rumpf
+#        (c) Copyright 2009 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
diff --git a/lib/base/pcre_all.c b/lib/wrappers/pcre/pcre_all.c
index bcda06e50..bcda06e50 100644
--- a/lib/base/pcre_all.c
+++ b/lib/wrappers/pcre/pcre_all.c
diff --git a/lib/base/postgres.nim b/lib/wrappers/postgres.nim
index c61edaa1e..d3c5e265b 100644
--- a/lib/base/postgres.nim
+++ b/lib/wrappers/postgres.nim
@@ -2,8 +2,8 @@
 # functions used by frontend postgres applications. It is based on
 # Postgresql's libpq-fe.h.
 #
-#  It is for postgreSQL version 7.4 and higher with support for the v3.0
-#  connection-protocol
+# It is for postgreSQL version 7.4 and higher with support for the v3.0
+# connection-protocol.
 #
 
 when defined(windows):
diff --git a/lib/wrappers/python.nim b/lib/wrappers/python.nim
new file mode 100644
index 000000000..c9f68e52d
--- /dev/null
+++ b/lib/wrappers/python.nim
@@ -0,0 +1,1581 @@
+#
+#    Light-weight binding for the Python interpreter
+#       (c) 2009 Andreas Rumpf 
+#    Based on 'PythonEngine' module by Dr. Dietmar Budelsky
+#
+#
+#************************************************************************
+#                                                                        
+# Module:  Unit 'PythonEngine'     Copyright (c) 1997                    
+#                                                                        
+# Version: 3.0                     Dr. Dietmar Budelsky                  
+# Sub-Version: 0.25                dbudelsky@web.de                      
+#                                  Germany                               
+#                                                                        
+#                                  Morgan Martinet                       
+#                                  4721 rue Brebeuf                      
+#                                  H2J 3L2 MONTREAL (QC)                 
+#                                  CANADA                                
+#                                  e-mail: mmm@free.fr                   
+#                                                                        
+#  look our page at: http://www.multimania.com/marat                     
+#************************************************************************
+#  Functionality:  Delphi Components that provide an interface to the    
+#                  Python language (see python.txt for more infos on     
+#                  Python itself).                                       
+#                                                                        
+#************************************************************************
+#  Contributors:                                                         
+#      Grzegorz Makarewicz (mak@mikroplan.com.pl)                        
+#      Andrew Robinson (andy@hps1.demon.co.uk)                           
+#      Mark Watts(mark_watts@hotmail.com)                                
+#      Olivier Deckmyn (olivier.deckmyn@mail.dotcom.fr)                  
+#      Sigve Tjora (public@tjora.no)                                     
+#      Mark Derricutt (mark@talios.com)                                  
+#      Igor E. Poteryaev (jah@mail.ru)                                   
+#      Yuri Filimonov (fil65@mail.ru)                                    
+#      Stefan Hoffmeister (Stefan.Hoffmeister@Econos.de)                 
+#************************************************************************
+# This source code is distributed with no WARRANTY, for no reason or use.
+# Everyone is allowed to use and change this code free for his own tasks 
+# and projects, as long as this header and its copyright text is intact. 
+# For changed versions of this code, which are public distributed the    
+# following additional conditions have to be fullfilled:                 
+# 1) The header has to contain a comment on the change and the author of 
+#    it.                                                                 
+# 2) A copy of the changed source has to be sent to the above E-Mail     
+#    address or my then valid address, if this is possible to the        
+#    author.                                                             
+# The second condition has the target to maintain an up to date central  
+# version of the component. If this condition is not acceptable for      
+# confidential or legal reasons, everyone is free to derive a component  
+# or to generate a diff file to my or other original sources.            
+# Dr. Dietmar Budelsky, 1997-11-17                                       
+#************************************************************************
+
+import 
+  dynlib
+
+
+when defined(windows): 
+  const dllname = "python(26|25|24|23|22|21|20|16|15).dll"
+elif defined(macosx):
+  const dllname = "libpython(2.6|2.5|2.4|2.3|2.2|2.1|2.0|1.6|1.5).dylib"
+else: 
+  const dllver = ".1"
+  const dllname = "libpython(2.6|2.5|2.4|2.3|2.2|2.1|2.0|1.6|1.5).so" & dllver
+  
+const 
+  PYT_METHOD_BUFFER_INCREASE* = 10
+  PYT_MEMBER_BUFFER_INCREASE* = 10
+  PYT_GETSET_BUFFER_INCREASE* = 10
+  METH_VARARGS* = 0x0001
+  METH_KEYWORDS* = 0x0002 # Masks for the co_flags field of PyCodeObject
+  CO_OPTIMIZED* = 0x0001
+  CO_NEWLOCALS* = 0x0002
+  CO_VARARGS* = 0x0004
+  CO_VARKEYWORDS* = 0x0008
+
+type                          # Rich comparison opcodes introduced in version 2.1
+  TRichComparisonOpcode* = enum 
+    pyLT, pyLE, pyEQ, pyNE, pyGT, pyGE
+
+const
+  Py_TPFLAGS_HAVE_GETCHARBUFFER* = (1 shl 0) # PySequenceMethods contains sq_contains
+  Py_TPFLAGS_HAVE_SEQUENCE_IN* = (1 shl 1) # Objects which participate in garbage collection (see objimp.h)
+  Py_TPFLAGS_GC* = (1 shl 2)  # PySequenceMethods and PyNumberMethods contain in-place operators
+  Py_TPFLAGS_HAVE_INPLACEOPS* = (1 shl 3) # PyNumberMethods do their own coercion */
+  Py_TPFLAGS_CHECKTYPES* = (1 shl 4)
+  Py_TPFLAGS_HAVE_RICHCOMPARE* = (1 shl 5) # Objects which are weakly referencable if their tp_weaklistoffset is >0
+                                           # XXX Should this have the same value as Py_TPFLAGS_HAVE_RICHCOMPARE?
+                                           # These both indicate a feature that appeared in the same alpha release.
+  Py_TPFLAGS_HAVE_WEAKREFS* = (1 shl 6) # tp_iter is defined
+  Py_TPFLAGS_HAVE_ITER* = (1 shl 7) # New members introduced by Python 2.2 exist
+  Py_TPFLAGS_HAVE_CLASS* = (1 shl 8) # Set if the type object is dynamically allocated
+  Py_TPFLAGS_HEAPTYPE* = (1 shl 9) # Set if the type allows subclassing
+  Py_TPFLAGS_BASETYPE* = (1 shl 10) # Set if the type is 'ready' -- fully initialized
+  Py_TPFLAGS_READY* = (1 shl 12) # Set while the type is being 'readied', to prevent recursive ready calls
+  Py_TPFLAGS_READYING* = (1 shl 13) # Objects support garbage collection (see objimp.h)
+  Py_TPFLAGS_HAVE_GC* = (1 shl 14)
+  Py_TPFLAGS_DEFAULT* = Py_TPFLAGS_HAVE_GETCHARBUFFER or
+      Py_TPFLAGS_HAVE_SEQUENCE_IN or Py_TPFLAGS_HAVE_INPLACEOPS or
+      Py_TPFLAGS_HAVE_RICHCOMPARE or Py_TPFLAGS_HAVE_WEAKREFS or
+      Py_TPFLAGS_HAVE_ITER or Py_TPFLAGS_HAVE_CLASS 
+
+type 
+  TPFlag* = enum 
+    tpfHaveGetCharBuffer, tpfHaveSequenceIn, tpfGC, tpfHaveInplaceOps, 
+    tpfCheckTypes, tpfHaveRichCompare, tpfHaveWeakRefs, tpfHaveIter, 
+    tpfHaveClass, tpfHeapType, tpfBaseType, tpfReady, tpfReadying, tpfHaveGC
+  TPFlags* = set[TPFlag]
+
+const 
+  TPFLAGS_DEFAULT* = {tpfHaveGetCharBuffer, tpfHaveSequenceIn, 
+    tpfHaveInplaceOps, tpfHaveRichCompare, tpfHaveWeakRefs, tpfHaveIter, 
+    tpfHaveClass}
+
+const # Python opcodes
+  single_input* = 256 
+  file_input* = 257
+  eval_input* = 258
+  funcdef* = 259
+  parameters* = 260
+  varargslist* = 261
+  fpdef* = 262
+  fplist* = 263
+  stmt* = 264
+  simple_stmt* = 265
+  small_stmt* = 266
+  expr_stmt* = 267
+  augassign* = 268
+  print_stmt* = 269
+  del_stmt* = 270
+  pass_stmt* = 271
+  flow_stmt* = 272
+  break_stmt* = 273
+  continue_stmt* = 274
+  return_stmt* = 275
+  raise_stmt* = 276
+  import_stmt* = 277
+  import_as_name* = 278
+  dotted_as_name* = 279
+  dotted_name* = 280
+  global_stmt* = 281
+  exec_stmt* = 282
+  assert_stmt* = 283
+  compound_stmt* = 284
+  if_stmt* = 285
+  while_stmt* = 286
+  for_stmt* = 287
+  try_stmt* = 288
+  except_clause* = 289
+  suite* = 290
+  test* = 291
+  and_test* = 291
+  not_test* = 293
+  comparison* = 294
+  comp_op* = 295
+  expr* = 296
+  xor_expr* = 297
+  and_expr* = 298
+  shift_expr* = 299
+  arith_expr* = 300
+  term* = 301
+  factor* = 302
+  power* = 303
+  atom* = 304
+  listmaker* = 305
+  lambdef* = 306
+  trailer* = 307
+  subscriptlist* = 308
+  subscript* = 309
+  sliceop* = 310
+  exprlist* = 311
+  testlist* = 312
+  dictmaker* = 313
+  classdef* = 314
+  arglist* = 315
+  argument* = 316
+  list_iter* = 317
+  list_for* = 318
+  list_if* = 319
+
+const 
+  T_SHORT* = 0
+  T_INT* = 1
+  T_LONG* = 2
+  T_FLOAT* = 3
+  T_DOUBLE* = 4
+  T_STRING* = 5
+  T_OBJECT* = 6
+  T_CHAR* = 7                 # 1-character string
+  T_BYTE* = 8                 # 8-bit signed int
+  T_UBYTE* = 9
+  T_USHORT* = 10
+  T_UINT* = 11
+  T_ULONG* = 12
+  T_STRING_INPLACE* = 13
+  T_OBJECT_EX* = 16 
+  READONLY* = 1
+  RO* = READONLY              # Shorthand 
+  READ_RESTRICTED* = 2
+  WRITE_RESTRICTED* = 4
+  RESTRICTED* = (READ_RESTRICTED or WRITE_RESTRICTED)
+
+type 
+  TPyMemberType* = enum 
+    mtShort, mtInt, mtLong, mtFloat, mtDouble, mtString, mtObject, mtChar, 
+    mtByte, mtUByte, mtUShort, mtUInt, mtULong, mtStringInplace, mtObjectEx
+  TPyMemberFlag* = enum 
+    mfDefault, mfReadOnly, mfReadRestricted, mfWriteRestricted, mfRestricted
+
+type 
+  PInt* = ptr int
+
+#  PLong* = ptr int32
+#  PFloat* = ptr float32
+#  PShort* = ptr int8
+  
+type 
+  PP_frozen* = ptr Pfrozen
+  P_frozen* = ptr Tfrozen
+  PPyObject* = ptr TPyObject
+  PPPyObject* = ptr PPyObject
+  PPPPyObject* = ptr PPPyObject
+  PPyIntObject* = ptr TPyIntObject
+  PPyTypeObject* = ptr TPyTypeObject
+  PPySliceObject* = ptr TPySliceObject
+  TPyCFunction* = proc (self, args: PPyObject): PPyObject{.cdecl.}
+  Tunaryfunc* = proc (ob1: PPyObject): PPyObject{.cdecl.}
+  Tbinaryfunc* = proc (ob1, ob2: PPyObject): PPyObject{.cdecl.}
+  Tternaryfunc* = proc (ob1, ob2, ob3: PPyObject): PPyObject{.cdecl.}
+  Tinquiry* = proc (ob1: PPyObject): int{.cdecl.}
+  Tcoercion* = proc (ob1, ob2: PPPyObject): int{.cdecl.}
+  Tintargfunc* = proc (ob1: PPyObject, i: int): PPyObject{.cdecl.}
+  Tintintargfunc* = proc (ob1: PPyObject, i1, i2: int): PPyObject{.cdecl.}
+  Tintobjargproc* = proc (ob1: PPyObject, i: int, ob2: PPyObject): int{.cdecl.}
+  Tintintobjargproc* = proc (ob1: PPyObject, i1, i2: int, ob2: PPyObject): int{.
+      cdecl.}
+  Tobjobjargproc* = proc (ob1, ob2, ob3: PPyObject): int{.cdecl.}
+  Tpydestructor* = proc (ob: PPyObject){.cdecl.}
+  Tprintfunc* = proc (ob: PPyObject, f: TFile, i: int): int{.cdecl.}
+  Tgetattrfunc* = proc (ob1: PPyObject, name: cstring): PPyObject{.cdecl.}
+  Tsetattrfunc* = proc (ob1: PPyObject, name: cstring, ob2: PPyObject): int{.
+      cdecl.}
+  Tcmpfunc* = proc (ob1, ob2: PPyObject): int{.cdecl.}
+  Treprfunc* = proc (ob: PPyObject): PPyObject{.cdecl.}
+  Thashfunc* = proc (ob: PPyObject): int32{.cdecl.}
+  Tgetattrofunc* = proc (ob1, ob2: PPyObject): PPyObject{.cdecl.}
+  Tsetattrofunc* = proc (ob1, ob2, ob3: PPyObject): int{.cdecl.} 
+  Tgetreadbufferproc* = proc (ob1: PPyObject, i: int, p: Pointer): int{.cdecl.}
+  Tgetwritebufferproc* = proc (ob1: PPyObject, i: int, p: Pointer): int{.cdecl.}
+  Tgetsegcountproc* = proc (ob1: PPyObject, i: int): int{.cdecl.}
+  Tgetcharbufferproc* = proc (ob1: PPyObject, i: int, pstr: cstring): int{.cdecl.}
+  Tobjobjproc* = proc (ob1, ob2: PPyObject): int{.cdecl.}
+  Tvisitproc* = proc (ob1: PPyObject, p: Pointer): int{.cdecl.}
+  Ttraverseproc* = proc (ob1: PPyObject, prc: TVisitproc, p: Pointer): int{.
+      cdecl.}
+  Trichcmpfunc* = proc (ob1, ob2: PPyObject, i: int): PPyObject{.cdecl.}
+  Tgetiterfunc* = proc (ob1: PPyObject): PPyObject{.cdecl.}
+  Titernextfunc* = proc (ob1: PPyObject): PPyObject{.cdecl.}
+  Tdescrgetfunc* = proc (ob1, ob2, ob3: PPyObject): PPyObject{.cdecl.}
+  Tdescrsetfunc* = proc (ob1, ob2, ob3: PPyObject): int{.cdecl.}
+  Tinitproc* = proc (self, args, kwds: PPyObject): int{.cdecl.}
+  Tnewfunc* = proc (subtype: PPyTypeObject, args, kwds: PPyObject): PPyObject{.
+      cdecl.}
+  Tallocfunc* = proc (self: PPyTypeObject, nitems: int): PPyObject{.cdecl.}
+  TPyNumberMethods*{.final.} = object 
+    nb_add*: Tbinaryfunc
+    nb_substract*: Tbinaryfunc
+    nb_multiply*: Tbinaryfunc
+    nb_divide*: Tbinaryfunc
+    nb_remainder*: Tbinaryfunc
+    nb_divmod*: Tbinaryfunc
+    nb_power*: Tternaryfunc
+    nb_negative*: Tunaryfunc
+    nb_positive*: Tunaryfunc
+    nb_absolute*: Tunaryfunc
+    nb_nonzero*: Tinquiry
+    nb_invert*: Tunaryfunc
+    nb_lshift*: Tbinaryfunc
+    nb_rshift*: Tbinaryfunc
+    nb_and*: Tbinaryfunc
+    nb_xor*: Tbinaryfunc
+    nb_or*: Tbinaryfunc
+    nb_coerce*: Tcoercion
+    nb_int*: Tunaryfunc
+    nb_long*: Tunaryfunc
+    nb_float*: Tunaryfunc
+    nb_oct*: Tunaryfunc
+    nb_hex*: Tunaryfunc       #/ jah 29-sep-2000: updated for python 2.0
+                              #/                   added from .h
+    nb_inplace_add*: Tbinaryfunc
+    nb_inplace_subtract*: Tbinaryfunc
+    nb_inplace_multiply*: Tbinaryfunc
+    nb_inplace_divide*: Tbinaryfunc
+    nb_inplace_remainder*: Tbinaryfunc
+    nb_inplace_power*: Tternaryfunc
+    nb_inplace_lshift*: Tbinaryfunc
+    nb_inplace_rshift*: Tbinaryfunc
+    nb_inplace_and*: Tbinaryfunc
+    nb_inplace_xor*: Tbinaryfunc
+    nb_inplace_or*: Tbinaryfunc # Added in release 2.2
+                                # The following require the Py_TPFLAGS_HAVE_CLASS flag
+    nb_floor_divide*: Tbinaryfunc
+    nb_true_divide*: Tbinaryfunc
+    nb_inplace_floor_divide*: Tbinaryfunc
+    nb_inplace_true_divide*: Tbinaryfunc
+
+  PPyNumberMethods* = ptr TPyNumberMethods
+  TPySequenceMethods*{.final.} = object 
+    sq_length*: Tinquiry
+    sq_concat*: Tbinaryfunc
+    sq_repeat*: Tintargfunc
+    sq_item*: Tintargfunc
+    sq_slice*: Tintintargfunc
+    sq_ass_item*: Tintobjargproc
+    sq_ass_slice*: Tintintobjargproc 
+    sq_contains*: Tobjobjproc
+    sq_inplace_concat*: Tbinaryfunc
+    sq_inplace_repeat*: Tintargfunc
+
+  PPySequenceMethods* = ptr TPySequenceMethods
+  TPyMappingMethods*{.final.} = object 
+    mp_length*: Tinquiry
+    mp_subscript*: Tbinaryfunc
+    mp_ass_subscript*: Tobjobjargproc
+
+  PPyMappingMethods* = ptr TPyMappingMethods 
+  TPyBufferProcs*{.final.} = object 
+    bf_getreadbuffer*: Tgetreadbufferproc
+    bf_getwritebuffer*: Tgetwritebufferproc
+    bf_getsegcount*: Tgetsegcountproc
+    bf_getcharbuffer*: Tgetcharbufferproc
+
+  PPyBufferProcs* = ptr TPyBufferProcs
+  TPy_complex*{.final.} = object 
+    float*: float64
+    imag*: float64
+
+  TPyObject*{.pure.} = object 
+    ob_refcnt*: int
+    ob_type*: PPyTypeObject
+
+  TPyIntObject* = object of TPyObject
+    ob_ival*: int32
+
+  PByte* = ptr int8
+  Tfrozen*{.final.} = object 
+    name*: cstring
+    code*: PByte
+    size*: int
+
+  TPySliceObject* = object of TPyObject
+    start*, stop*, step*: PPyObject
+
+  PPyMethodDef* = ptr TPyMethodDef
+  TPyMethodDef*{.final.} = object  # structmember.h
+    ml_name*: cstring
+    ml_meth*: TPyCFunction
+    ml_flags*: int
+    ml_doc*: cstring
+
+  PPyMemberDef* = ptr TPyMemberDef
+  TPyMemberDef*{.final.} = object  # descrobject.h
+                                   # Descriptors
+    name*: cstring
+    theType*: int
+    offset*: int
+    flags*: int
+    doc*: cstring
+
+  Tgetter* = proc (obj: PPyObject, context: Pointer): PPyObject{.cdecl.}
+  Tsetter* = proc (obj, value: PPyObject, context: Pointer): int{.cdecl.}
+  PPyGetSetDef* = ptr TPyGetSetDef
+  TPyGetSetDef*{.final.} = object 
+    name*: cstring
+    get*: Tgetter
+    set_*: Tsetter
+    doc*: cstring
+    closure*: Pointer
+
+  Twrapperfunc* = proc (self, args: PPyObject, wrapped: Pointer): PPyObject{.
+      cdecl.}
+  pwrapperbase* = ptr Twrapperbase
+  Twrapperbase*{.final.} = object  # Various kinds of descriptor objects
+                                   ##define PyDescr_COMMON \
+                                   #          PyObject_HEAD \
+                                   #          PyTypeObject *d_type; \
+                                   #          PyObject *d_name
+                                   #  
+    name*: cstring
+    wrapper*: Twrapperfunc
+    doc*: cstring
+
+  PPyDescrObject* = ptr TPyDescrObject
+  TPyDescrObject* = object of TPyObject
+    d_type*: PPyTypeObject
+    d_name*: PPyObject
+
+  PPyMethodDescrObject* = ptr TPyMethodDescrObject
+  TPyMethodDescrObject* = object of TPyDescrObject
+    d_method*: PPyMethodDef
+
+  PPyMemberDescrObject* = ptr TPyMemberDescrObject
+  TPyMemberDescrObject* = object of TPyDescrObject
+    d_member*: PPyMemberDef
+
+  PPyGetSetDescrObject* = ptr TPyGetSetDescrObject
+  TPyGetSetDescrObject* = object of TPyDescrObject
+    d_getset*: PPyGetSetDef
+
+  PPyWrapperDescrObject* = ptr TPyWrapperDescrObject
+  TPyWrapperDescrObject* = object of TPyDescrObject # object.h
+    d_base*: pwrapperbase
+    d_wrapped*: Pointer       # This can be any function pointer
+  
+  TPyTypeObject* = object of TPyObject
+    ob_size*: int             # Number of items in variable part
+    tp_name*: cstring         # For printing
+    tp_basicsize*, tp_itemsize*: int # For allocation
+                                     # Methods to implement standard operations
+    tp_dealloc*: Tpydestructor
+    tp_print*: Tprintfunc
+    tp_getattr*: Tgetattrfunc
+    tp_setattr*: Tsetattrfunc
+    tp_compare*: Tcmpfunc
+    tp_repr*: Treprfunc       # Method suites for standard classes
+    tp_as_number*: PPyNumberMethods
+    tp_as_sequence*: PPySequenceMethods
+    tp_as_mapping*: PPyMappingMethods # More standard operations (here for binary compatibility)
+    tp_hash*: Thashfunc
+    tp_call*: Tternaryfunc
+    tp_str*: Treprfunc
+    tp_getattro*: Tgetattrofunc
+    tp_setattro*: Tsetattrofunc #/ jah 29-sep-2000: updated for python 2.0
+                                # Functions to access object as input/output buffer
+    tp_as_buffer*: PPyBufferProcs # Flags to define presence of optional/expanded features
+    tp_flags*: int32
+    tp_doc*: cstring          # Documentation string
+                              # call function for all accessible objects
+    tp_traverse*: Ttraverseproc # delete references to contained objects
+    tp_clear*: Tinquiry       # rich comparisons
+    tp_richcompare*: Trichcmpfunc # weak reference enabler
+    tp_weaklistoffset*: int32 # Iterators
+    tp_iter*: Tgetiterfunc
+    tp_iternext*: Titernextfunc # Attribute descriptor and subclassing stuff
+    tp_methods*: PPyMethodDef
+    tp_members*: PPyMemberDef
+    tp_getset*: PPyGetSetDef
+    tp_base*: PPyTypeObject
+    tp_dict*: PPyObject
+    tp_descr_get*: Tdescrgetfunc
+    tp_descr_set*: Tdescrsetfunc
+    tp_dictoffset*: int32
+    tp_init*: Tinitproc
+    tp_alloc*: Tallocfunc
+    tp_new*: Tnewfunc
+    tp_free*: Tpydestructor   # Low-level free-memory routine
+    tp_is_gc*: Tinquiry       # For PyObject_IS_GC
+    tp_bases*: PPyObject
+    tp_mro*: PPyObject        # method resolution order
+    tp_cache*: PPyObject
+    tp_subclasses*: PPyObject
+    tp_weaklist*: PPyObject   #More spares
+    tp_xxx7*: pointer
+    tp_xxx8*: pointer
+
+  PPyMethodChain* = ptr TPyMethodChain
+  TPyMethodChain*{.final.} = object 
+    methods*: PPyMethodDef
+    link*: PPyMethodChain
+
+  PPyClassObject* = ptr TPyClassObject
+  TPyClassObject* = object of TPyObject
+    cl_bases*: PPyObject      # A tuple of class objects
+    cl_dict*: PPyObject       # A dictionary
+    cl_name*: PPyObject       # A string
+                              # The following three are functions or NULL
+    cl_getattr*: PPyObject
+    cl_setattr*: PPyObject
+    cl_delattr*: PPyObject
+
+  PPyInstanceObject* = ptr TPyInstanceObject
+  TPyInstanceObject* = object of TPyObject 
+    in_class*: PPyClassObject # The class object
+    in_dict*: PPyObject       # A dictionary
+  
+  PPyMethodObject* = ptr TPyMethodObject
+  TPyMethodObject* = object of TPyObject # Bytecode object, compile.h
+    im_func*: PPyObject       # The function implementing the method
+    im_self*: PPyObject       # The instance it is bound to, or NULL
+    im_class*: PPyObject      # The class that defined the method
+  
+  PPyCodeObject* = ptr TPyCodeObject
+  TPyCodeObject* = object of TPyObject # from pystate.h
+    co_argcount*: int         # #arguments, except *args
+    co_nlocals*: int          # #local variables
+    co_stacksize*: int        # #entries needed for evaluation stack
+    co_flags*: int            # CO_..., see below
+    co_code*: PPyObject       # instruction opcodes (it hides a PyStringObject)
+    co_consts*: PPyObject     # list (constants used)
+    co_names*: PPyObject      # list of strings (names used)
+    co_varnames*: PPyObject   # tuple of strings (local variable names)
+    co_freevars*: PPyObject   # tuple of strings (free variable names)
+    co_cellvars*: PPyObject   # tuple of strings (cell variable names)
+                              # The rest doesn't count for hash/cmp
+    co_filename*: PPyObject   # string (where it was loaded from)
+    co_name*: PPyObject       # string (name, for reference)
+    co_firstlineno*: int      # first source line number
+    co_lnotab*: PPyObject     # string (encoding addr<->lineno mapping)
+  
+  PPyInterpreterState* = ptr TPyInterpreterState
+  PPyThreadState* = ptr TPyThreadState
+  PPyFrameObject* = ptr TPyFrameObject # Interpreter environments
+  TPyInterpreterState*{.final.} = object  # Thread specific information
+    next*: PPyInterpreterState
+    tstate_head*: PPyThreadState
+    modules*: PPyObject
+    sysdict*: PPyObject
+    builtins*: PPyObject
+    checkinterval*: int
+
+  TPyThreadState*{.final.} = object  # from frameobject.h
+    next*: PPyThreadState
+    interp*: PPyInterpreterState
+    frame*: PPyFrameObject
+    recursion_depth*: int
+    ticker*: int
+    tracing*: int
+    sys_profilefunc*: PPyObject
+    sys_tracefunc*: PPyObject
+    curexc_type*: PPyObject
+    curexc_value*: PPyObject
+    curexc_traceback*: PPyObject
+    exc_type*: PPyObject
+    exc_value*: PPyObject
+    exc_traceback*: PPyObject
+    dict*: PPyObject
+
+  PPyTryBlock* = ptr TPyTryBlock
+  TPyTryBlock*{.final.} = object 
+    b_type*: int              # what kind of block this is
+    b_handler*: int           # where to jump to find handler
+    b_level*: int             # value stack level to pop to
+  
+  CO_MAXBLOCKS* = range[0..19]
+  TPyFrameObject* = object of TPyObject # start of the VAR_HEAD of an object
+                                        # From traceback.c
+    ob_size*: int             # Number of items in variable part
+                              # End of the Head of an object
+    f_back*: PPyFrameObject   # previous frame, or NULL
+    f_code*: PPyCodeObject    # code segment
+    f_builtins*: PPyObject    # builtin symbol table (PyDictObject)
+    f_globals*: PPyObject     # global symbol table (PyDictObject)
+    f_locals*: PPyObject      # local symbol table (PyDictObject)
+    f_valuestack*: PPPyObject # points after the last local
+                              # Next free slot in f_valuestack. Frame creation sets to f_valuestack.
+                              # Frame evaluation usually NULLs it, but a frame that yields sets it
+                              # to the current stack top. 
+    f_stacktop*: PPPyObject
+    f_trace*: PPyObject       # Trace function
+    f_exc_type*, f_exc_value*, f_exc_traceback*: PPyObject
+    f_tstate*: PPyThreadState
+    f_lasti*: int             # Last instruction if called
+    f_lineno*: int            # Current line number
+    f_restricted*: int        # Flag set if restricted operations
+                              # in this scope
+    f_iblock*: int            # index in f_blockstack
+    f_blockstack*: array[CO_MAXBLOCKS, TPyTryBlock] # for try and loop blocks
+    f_nlocals*: int           # number of locals
+    f_ncells*: int
+    f_nfreevars*: int
+    f_stacksize*: int         # size of value stack
+    f_localsplus*: array[0..0, PPyObject] # locals+stack, dynamically sized
+  
+  PPyTraceBackObject* = ptr TPyTraceBackObject
+  TPyTraceBackObject* = object of TPyObject # Parse tree node interface
+    tb_next*: PPyTraceBackObject
+    tb_frame*: PPyFrameObject
+    tb_lasti*: int
+    tb_lineno*: int
+
+  PNode* = ptr Tnode
+  Tnode*{.final.} = object    # From weakrefobject.h
+    n_type*: int16
+    n_str*: cstring
+    n_lineno*: int16
+    n_nchildren*: int16
+    n_child*: PNode
+
+  PPyWeakReference* = ptr TPyWeakReference
+  TPyWeakReference* = object of TPyObject 
+    wr_object*: PPyObject
+    wr_callback*: PPyObject
+    hash*: int32
+    wr_prev*: PPyWeakReference
+    wr_next*: PPyWeakReference
+
+
+const                         
+  PyDateTime_DATE_DATASIZE* = 4 # # of bytes for year, month, and day
+  PyDateTime_TIME_DATASIZE* = 6 # # of bytes for hour, minute, second, and usecond
+  PyDateTime_DATETIME_DATASIZE* = 10 # # of bytes for year, month, 
+                                     # day, hour, minute, second, and usecond. 
+
+type 
+  TPyDateTime_Delta* = object of TPyObject
+    hashcode*: int            # -1 when unknown
+    days*: int                # -MAX_DELTA_DAYS <= days <= MAX_DELTA_DAYS
+    seconds*: int             # 0 <= seconds < 24*3600 is invariant
+    microseconds*: int        # 0 <= microseconds < 1000000 is invariant
+  
+  PPyDateTime_Delta* = ptr TPyDateTime_Delta
+  TPyDateTime_TZInfo* = object of TPyObject # a pure abstract base clase
+  PPyDateTime_TZInfo* = ptr TPyDateTime_TZInfo 
+  TPyDateTime_BaseTZInfo* = object of TPyObject
+    hashcode*: int
+    hastzinfo*: bool          # boolean flag
+  
+  PPyDateTime_BaseTZInfo* = ptr TPyDateTime_BaseTZInfo 
+  TPyDateTime_BaseTime* = object of TPyDateTime_BaseTZInfo
+    data*: array[0..Pred(PyDateTime_TIME_DATASIZE), int8]
+
+  PPyDateTime_BaseTime* = ptr TPyDateTime_BaseTime
+  TPyDateTime_Time* = object of TPyDateTime_BaseTime # hastzinfo true
+    tzinfo*: PPyObject
+
+  PPyDateTime_Time* = ptr TPyDateTime_Time 
+  TPyDateTime_Date* = object of TPyDateTime_BaseTZInfo
+    data*: array[0..Pred(PyDateTime_DATE_DATASIZE), int8]
+
+  PPyDateTime_Date* = ptr TPyDateTime_Date 
+  TPyDateTime_BaseDateTime* = object of TPyDateTime_BaseTZInfo
+    data*: array[0..Pred(PyDateTime_DATETIME_DATASIZE), int8]
+
+  PPyDateTime_BaseDateTime* = ptr TPyDateTime_BaseDateTime
+  TPyDateTime_DateTime* = object of TPyDateTime_BaseTZInfo
+    data*: array[0..Pred(PyDateTime_DATETIME_DATASIZE), int8]
+    tzinfo*: PPyObject
+
+  PPyDateTime_DateTime* = ptr TPyDateTime_DateTime 
+
+#----------------------------------------------------#
+#                                                    #
+#         New exception classes                      #
+#                                                    #
+#----------------------------------------------------#
+
+#
+#  // Python's exceptions
+#  EPythonError   = object(Exception)
+#      EName: String;
+#      EValue: String;
+#  end;
+#  EPyExecError   = object(EPythonError)
+#  end;
+#
+#  // Standard exception classes of Python
+#
+#/// jah 29-sep-2000: updated for python 2.0
+#///                   base classes updated according python documentation
+#
+#{ Hierarchy of Python exceptions, Python 2.3, copied from <INSTALL>\Python\exceptions.c
+#
+#Exception\n\
+# |\n\
+# +-- SystemExit\n\
+# +-- StopIteration\n\
+# +-- StandardError\n\
+# |    |\n\
+# |    +-- KeyboardInterrupt\n\
+# |    +-- ImportError\n\
+# |    +-- EnvironmentError\n\
+# |    |    |\n\
+# |    |    +-- IOError\n\
+# |    |    +-- OSError\n\
+# |    |         |\n\
+# |    |         +-- WindowsError\n\
+# |    |         +-- VMSError\n\
+# |    |\n\
+# |    +-- EOFError\n\
+# |    +-- RuntimeError\n\
+# |    |    |\n\
+# |    |    +-- NotImplementedError\n\
+# |    |\n\
+# |    +-- NameError\n\
+# |    |    |\n\
+# |    |    +-- UnboundLocalError\n\
+# |    |\n\
+# |    +-- AttributeError\n\
+# |    +-- SyntaxError\n\
+# |    |    |\n\
+# |    |    +-- IndentationError\n\
+# |    |         |\n\
+# |    |         +-- TabError\n\
+# |    |\n\
+# |    +-- TypeError\n\
+# |    +-- AssertionError\n\
+# |    +-- LookupError\n\
+# |    |    |\n\
+# |    |    +-- IndexError\n\
+# |    |    +-- KeyError\n\
+# |    |\n\
+# |    +-- ArithmeticError\n\
+# |    |    |\n\
+# |    |    +-- OverflowError\n\
+# |    |    +-- ZeroDivisionError\n\
+# |    |    +-- FloatingPointError\n\
+# |    |\n\
+# |    +-- ValueError\n\
+# |    |    |\n\
+# |    |    +-- UnicodeError\n\
+# |    |        |\n\
+# |    |        +-- UnicodeEncodeError\n\
+# |    |        +-- UnicodeDecodeError\n\
+# |    |        +-- UnicodeTranslateError\n\
+# |    |\n\
+# |    +-- ReferenceError\n\
+# |    +-- SystemError\n\
+# |    +-- MemoryError\n\
+# |\n\
+# +---Warning\n\
+#      |\n\
+#      +-- UserWarning\n\
+#      +-- DeprecationWarning\n\
+#      +-- PendingDeprecationWarning\n\
+#      +-- SyntaxWarning\n\
+#      +-- OverflowWarning\n\
+#      +-- RuntimeWarning\n\
+#      +-- FutureWarning"
+#}
+#   EPyException = class (EPythonError);
+#   EPyStandardError = class (EPyException);
+#   EPyArithmeticError = class (EPyStandardError);
+#   EPyLookupError = class (EPyStandardError);
+#   EPyAssertionError = class (EPyStandardError);
+#   EPyAttributeError = class (EPyStandardError);
+#   EPyEOFError = class (EPyStandardError);
+#   EPyFloatingPointError = class (EPyArithmeticError);
+#   EPyEnvironmentError = class (EPyStandardError);
+#   EPyIOError = class (EPyEnvironmentError);
+#   EPyOSError = class (EPyEnvironmentError);
+#   EPyImportError = class (EPyStandardError);
+#   EPyIndexError = class (EPyLookupError);
+#   EPyKeyError = class (EPyLookupError);
+#   EPyKeyboardInterrupt = class (EPyStandardError);
+#   EPyMemoryError = class (EPyStandardError);
+#   EPyNameError = class (EPyStandardError);
+#   EPyOverflowError = class (EPyArithmeticError);
+#   EPyRuntimeError = class (EPyStandardError);
+#   EPyNotImplementedError = class (EPyRuntimeError);
+#   EPySyntaxError = class (EPyStandardError)
+#   public
+#      EFileName: string;
+#      ELineStr: string;
+#      ELineNumber: Integer;
+#      EOffset: Integer;
+#   end;
+#   EPyIndentationError = class (EPySyntaxError);
+#   EPyTabError = class (EPyIndentationError);
+#   EPySystemError = class (EPyStandardError);
+#   EPySystemExit = class (EPyException);
+#   EPyTypeError = class (EPyStandardError);
+#   EPyUnboundLocalError = class (EPyNameError);
+#   EPyValueError = class (EPyStandardError);
+#   EPyUnicodeError = class (EPyValueError);
+#   UnicodeEncodeError = class (EPyUnicodeError);
+#   UnicodeDecodeError = class (EPyUnicodeError);
+#   UnicodeTranslateError = class (EPyUnicodeError);
+#   EPyZeroDivisionError = class (EPyArithmeticError);
+#   EPyStopIteration = class(EPyException);
+#   EPyWarning = class (EPyException);
+#   EPyUserWarning = class (EPyWarning);
+#   EPyDeprecationWarning = class (EPyWarning);
+#   PendingDeprecationWarning = class (EPyWarning);
+#   FutureWarning = class (EPyWarning);
+#   EPySyntaxWarning = class (EPyWarning);
+#   EPyOverflowWarning = class (EPyWarning);
+#   EPyRuntimeWarning = class (EPyWarning);
+#   EPyReferenceError = class (EPyStandardError);
+#
+
+var 
+  PyArg_Parse*: proc (args: PPyObject, format: cstring): int{.cdecl, varargs.} 
+  PyArg_ParseTuple*: proc (args: PPyObject, format: cstring, x1: Pointer = nil, 
+                           x2: Pointer = nil, x3: Pointer = nil): int{.cdecl, varargs.} 
+  Py_BuildValue*: proc (format: cstring): PPyObject{.cdecl, varargs.} 
+  PyCode_Addr2Line*: proc (co: PPyCodeObject, addrq: int): int{.cdecl.}
+  DLL_Py_GetBuildInfo*: proc (): cstring{.cdecl.}
+
+var
+  Py_DebugFlag*: PInt
+  Py_VerboseFlag*: PInt
+  Py_InteractiveFlag*: PInt
+  Py_OptimizeFlag*: PInt
+  Py_NoSiteFlag*: PInt
+  Py_UseClassExceptionsFlag*: PInt
+  Py_FrozenFlag*: PInt
+  Py_TabcheckFlag*: PInt
+  Py_UnicodeFlag*: PInt
+  Py_IgnoreEnvironmentFlag*: PInt
+  Py_DivisionWarningFlag*: PInt 
+  #_PySys_TraceFunc:    PPPyObject;
+  #_PySys_ProfileFunc: PPPPyObject;
+  PyImport_FrozenModules*: PP_frozen
+  Py_None*: PPyObject
+  Py_Ellipsis*: PPyObject
+  Py_False*: PPyIntObject
+  Py_True*: PPyIntObject
+  Py_NotImplemented*: PPyObject
+  PyExc_AttributeError*: PPPyObject
+  PyExc_EOFError*: PPPyObject
+  PyExc_IOError*: PPPyObject
+  PyExc_ImportError*: PPPyObject
+  PyExc_IndexError*: PPPyObject
+  PyExc_KeyError*: PPPyObject
+  PyExc_KeyboardInterrupt*: PPPyObject
+  PyExc_MemoryError*: PPPyObject
+  PyExc_NameError*: PPPyObject
+  PyExc_OverflowError*: PPPyObject
+  PyExc_RuntimeError*: PPPyObject
+  PyExc_SyntaxError*: PPPyObject
+  PyExc_SystemError*: PPPyObject
+  PyExc_SystemExit*: PPPyObject
+  PyExc_TypeError*: PPPyObject
+  PyExc_ValueError*: PPPyObject
+  PyExc_ZeroDivisionError*: PPPyObject
+  PyExc_ArithmeticError*: PPPyObject
+  PyExc_Exception*: PPPyObject
+  PyExc_FloatingPointError*: PPPyObject
+  PyExc_LookupError*: PPPyObject
+  PyExc_StandardError*: PPPyObject
+  PyExc_AssertionError*: PPPyObject
+  PyExc_EnvironmentError*: PPPyObject
+  PyExc_IndentationError*: PPPyObject
+  PyExc_MemoryErrorInst*: PPPyObject
+  PyExc_NotImplementedError*: PPPyObject
+  PyExc_OSError*: PPPyObject
+  PyExc_TabError*: PPPyObject
+  PyExc_UnboundLocalError*: PPPyObject
+  PyExc_UnicodeError*: PPPyObject
+  PyExc_Warning*: PPPyObject
+  PyExc_DeprecationWarning*: PPPyObject
+  PyExc_RuntimeWarning*: PPPyObject
+  PyExc_SyntaxWarning*: PPPyObject
+  PyExc_UserWarning*: PPPyObject
+  PyExc_OverflowWarning*: PPPyObject
+  PyExc_ReferenceError*: PPPyObject
+  PyExc_StopIteration*: PPPyObject
+  PyExc_FutureWarning*: PPPyObject
+  PyExc_PendingDeprecationWarning*: PPPyObject
+  PyExc_UnicodeDecodeError*: PPPyObject
+  PyExc_UnicodeEncodeError*: PPPyObject
+  PyExc_UnicodeTranslateError*: PPPyObject
+  PyType_Type*: PPyTypeObject
+  PyCFunction_Type*: PPyTypeObject
+  PyCObject_Type*: PPyTypeObject
+  PyClass_Type*: PPyTypeObject
+  PyCode_Type*: PPyTypeObject
+  PyComplex_Type*: PPyTypeObject
+  PyDict_Type*: PPyTypeObject
+  PyFile_Type*: PPyTypeObject
+  PyFloat_Type*: PPyTypeObject
+  PyFrame_Type*: PPyTypeObject
+  PyFunction_Type*: PPyTypeObject
+  PyInstance_Type*: PPyTypeObject
+  PyInt_Type*: PPyTypeObject
+  PyList_Type*: PPyTypeObject
+  PyLong_Type*: PPyTypeObject
+  PyMethod_Type*: PPyTypeObject
+  PyModule_Type*: PPyTypeObject
+  PyObject_Type*: PPyTypeObject
+  PyRange_Type*: PPyTypeObject
+  PySlice_Type*: PPyTypeObject
+  PyString_Type*: PPyTypeObject
+  PyTuple_Type*: PPyTypeObject
+  PyBaseObject_Type*: PPyTypeObject
+  PyBuffer_Type*: PPyTypeObject
+  PyCallIter_Type*: PPyTypeObject
+  PyCell_Type*: PPyTypeObject
+  PyClassMethod_Type*: PPyTypeObject
+  PyProperty_Type*: PPyTypeObject
+  PySeqIter_Type*: PPyTypeObject
+  PyStaticMethod_Type*: PPyTypeObject
+  PySuper_Type*: PPyTypeObject
+  PySymtableEntry_Type*: PPyTypeObject
+  PyTraceBack_Type*: PPyTypeObject
+  PyUnicode_Type*: PPyTypeObject
+  PyWrapperDescr_Type*: PPyTypeObject
+  PyBaseString_Type*: PPyTypeObject
+  PyBool_Type*: PPyTypeObject
+  PyEnum_Type*: PPyTypeObject
+
+  #PyArg_GetObject: proc(args: PPyObject; nargs, i: integer; p_a: PPPyObject): integer; cdecl;
+  #PyArg_GetLong: proc(args: PPyObject; nargs, i: integer; p_a: PLong): integer; cdecl;
+  #PyArg_GetShort: proc(args: PPyObject; nargs, i: integer; p_a: PShort): integer; cdecl;
+  #PyArg_GetFloat: proc(args: PPyObject; nargs, i: integer; p_a: PFloat): integer; cdecl;
+  #PyArg_GetString: proc(args: PPyObject; nargs, i: integer; p_a: PString): integer; cdecl;
+  #PyArgs_VaParse:  proc (args: PPyObject; format: PChar; 
+  #                          va_list: array of const): integer; cdecl;
+  # Does not work!
+  # Py_VaBuildValue: proc (format: PChar; va_list: array of const): PPyObject; cdecl;
+  #PyBuiltin_Init: proc; cdecl;
+proc PyComplex_FromCComplex*(c: TPy_complex): PPyObject{.cdecl, importc, dynlib: dllname.}
+proc PyComplex_FromDoubles*(realv, imag: float64): PPyObject{.cdecl, importc, dynlib: dllname.}
+proc PyComplex_RealAsDouble*(op: PPyObject): float64{.cdecl, importc, dynlib: dllname.}
+proc PyComplex_ImagAsDouble*(op: PPyObject): float64{.cdecl, importc, dynlib: dllname.}
+proc PyComplex_AsCComplex*(op: PPyObject): TPy_complex{.cdecl, importc, dynlib: dllname.}
+proc PyCFunction_GetFunction*(ob: PPyObject): Pointer{.cdecl, importc, dynlib: dllname.}
+proc PyCFunction_GetSelf*(ob: PPyObject): PPyObject{.cdecl, importc, dynlib: dllname.}
+proc PyCallable_Check*(ob: PPyObject): int{.cdecl, importc, dynlib: dllname.}
+proc PyCObject_FromVoidPtr*(cobj, destruct: Pointer): PPyObject{.cdecl, importc, dynlib: dllname.}
+proc PyCObject_AsVoidPtr*(ob: PPyObject): Pointer{.cdecl, importc, dynlib: dllname.}
+proc PyClass_New*(ob1, ob2, ob3: PPyObject): PPyObject{.cdecl, importc, dynlib: dllname.}
+proc PyClass_IsSubclass*(ob1, ob2: PPyObject): int{.cdecl, importc, dynlib: dllname.}
+proc Py_InitModule4*(name: cstring, methods: PPyMethodDef, doc: cstring, 
+                         passthrough: PPyObject, Api_Version: int): PPyObject{.
+      cdecl, importc, dynlib: dllname.}
+proc PyErr_BadArgument*(): int{.cdecl, importc, dynlib: dllname.}
+proc PyErr_BadInternalCall*(){.cdecl, importc, dynlib: dllname.}
+proc PyErr_CheckSignals*(): int{.cdecl, importc, dynlib: dllname.}
+proc PyErr_Clear*(){.cdecl, importc, dynlib: dllname.}
+proc PyErr_Fetch*(errtype, errvalue, errtraceback: PPPyObject){.cdecl, importc, dynlib: dllname.}
+proc PyErr_NoMemory*(): PPyObject{.cdecl, importc, dynlib: dllname.}
+proc PyErr_Occurred*(): PPyObject{.cdecl, importc, dynlib: dllname.}
+proc PyErr_Print*(){.cdecl, importc, dynlib: dllname.}
+proc PyErr_Restore*(errtype, errvalue, errtraceback: PPyObject){.cdecl, importc, dynlib: dllname.}
+proc PyErr_SetFromErrno*(ob: PPyObject): PPyObject{.cdecl, importc, dynlib: dllname.}
+proc PyErr_SetNone*(value: PPyObject){.cdecl, importc, dynlib: dllname.}
+proc PyErr_SetObject*(ob1, ob2: PPyObject){.cdecl, importc, dynlib: dllname.}
+proc PyErr_SetString*(ErrorObject: PPyObject, text: cstring){.cdecl, importc, dynlib: dllname.}
+proc PyImport_GetModuleDict*(): PPyObject{.cdecl, importc, dynlib: dllname.}
+proc PyInt_FromLong*(x: int32): PPyObject{.cdecl, importc, dynlib: dllname.}
+proc Py_Initialize*(){.cdecl, importc, dynlib: dllname.}
+proc Py_Exit*(RetVal: int){.cdecl, importc, dynlib: dllname.}
+proc PyEval_GetBuiltins*(): PPyObject{.cdecl, importc, dynlib: dllname.}
+proc PyDict_GetItem*(mp, key: PPyObject): PPyObject{.cdecl, importc, dynlib: dllname.}
+proc PyDict_SetItem*(mp, key, item: PPyObject): int{.cdecl, importc, dynlib: dllname.}
+proc PyDict_DelItem*(mp, key: PPyObject): int{.cdecl, importc, dynlib: dllname.}
+proc PyDict_Clear*(mp: PPyObject){.cdecl, importc, dynlib: dllname.}
+proc PyDict_Next*(mp: PPyObject, pos: PInt, key, value: PPPyObject): int{.
+      cdecl, importc, dynlib: dllname.}
+proc PyDict_Keys*(mp: PPyObject): PPyObject{.cdecl, importc, dynlib: dllname.}
+proc PyDict_Values*(mp: PPyObject): PPyObject{.cdecl, importc, dynlib: dllname.}
+proc PyDict_Items*(mp: PPyObject): PPyObject{.cdecl, importc, dynlib: dllname.}
+proc PyDict_Size*(mp: PPyObject): int{.cdecl, importc, dynlib: dllname.}
+proc PyDict_DelItemString*(dp: PPyObject, key: cstring): int{.cdecl, importc, dynlib: dllname.}
+proc PyDict_New*(): PPyObject{.cdecl, importc, dynlib: dllname.}
+proc PyDict_GetItemString*(dp: PPyObject, key: cstring): PPyObject{.cdecl, importc, dynlib: dllname.}
+proc PyDict_SetItemString*(dp: PPyObject, key: cstring, item: PPyObject): int{.
+      cdecl, importc, dynlib: dllname.}
+proc PyDictProxy_New*(obj: PPyObject): PPyObject{.cdecl, importc, dynlib: dllname.}
+proc PyModule_GetDict*(module: PPyObject): PPyObject{.cdecl, importc, dynlib: dllname.}
+proc PyObject_Str*(v: PPyObject): PPyObject{.cdecl, importc, dynlib: dllname.}
+proc PyRun_String*(str: cstring, start: int, globals: PPyObject, 
+                       locals: PPyObject): PPyObject{.cdecl, importc, dynlib: dllname.}
+proc PyRun_SimpleString*(str: cstring): int{.cdecl, importc, dynlib: dllname.}
+proc PyString_AsString*(ob: PPyObject): cstring{.cdecl, importc, dynlib: dllname.}
+proc PyString_FromString*(str: cstring): PPyObject{.cdecl, importc, dynlib: dllname.}
+proc PySys_SetArgv*(argc: int, argv: cstringArray){.cdecl, importc, dynlib: dllname.} 
+  #+ means, Grzegorz or me has tested his non object version of this function
+  #+
+proc PyCFunction_New*(md: PPyMethodDef, ob: PPyObject): PPyObject{.cdecl, importc, dynlib: dllname.} #+
+proc PyEval_CallObject*(ob1, ob2: PPyObject): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc PyEval_CallObjectWithKeywords*(ob1, ob2, ob3: PPyObject): PPyObject{.
+      cdecl, importc, dynlib: dllname.}                 #-
+proc PyEval_GetFrame*(): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc PyEval_GetGlobals*(): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc PyEval_GetLocals*(): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc PyEval_GetOwner*(): PPyObject {.cdecl, importc, dynlib: dllname.}
+proc PyEval_GetRestricted*(): int{.cdecl, importc, dynlib: dllname.} #-
+proc PyEval_InitThreads*(){.cdecl, importc, dynlib: dllname.} #-
+proc PyEval_RestoreThread*(tstate: PPyThreadState){.cdecl, importc, dynlib: dllname.} #-
+proc PyEval_SaveThread*(): PPyThreadState{.cdecl, importc, dynlib: dllname.} #-
+proc PyFile_FromString*(pc1, pc2: cstring): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc PyFile_GetLine*(ob: PPyObject, i: int): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc PyFile_Name*(ob: PPyObject): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc PyFile_SetBufSize*(ob: PPyObject, i: int){.cdecl, importc, dynlib: dllname.} #-
+proc PyFile_SoftSpace*(ob: PPyObject, i: int): int{.cdecl, importc, dynlib: dllname.} #-
+proc PyFile_WriteObject*(ob1, ob2: PPyObject, i: int): int{.cdecl, importc, dynlib: dllname.} #-
+proc PyFile_WriteString*(s: cstring, ob: PPyObject){.cdecl, importc, dynlib: dllname.} #+
+proc PyFloat_AsDouble*(ob: PPyObject): float64{.cdecl, importc, dynlib: dllname.} #+
+proc PyFloat_FromDouble*(db: float64): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc PyFunction_GetCode*(ob: PPyObject): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc PyFunction_GetGlobals*(ob: PPyObject): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc PyFunction_New*(ob1, ob2: PPyObject): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc PyImport_AddModule*(name: cstring): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc PyImport_Cleanup*(){.cdecl, importc, dynlib: dllname.} #-
+proc PyImport_GetMagicNumber*(): int32{.cdecl, importc, dynlib: dllname.} #+
+proc PyImport_ImportFrozenModule*(key: cstring): int{.cdecl, importc, dynlib: dllname.} #+
+proc PyImport_ImportModule*(name: cstring): PPyObject{.cdecl, importc, dynlib: dllname.} #+
+proc PyImport_Import*(name: PPyObject): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+                                                               
+proc PyImport_Init*() {.cdecl, importc, dynlib: dllname.}
+proc PyImport_ReloadModule*(ob: PPyObject): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc PyInstance_New*(obClass, obArg, obKW: PPyObject): PPyObject{.cdecl, importc, dynlib: dllname.} #+
+proc PyInt_AsLong*(ob: PPyObject): int32{.cdecl, importc, dynlib: dllname.} #-
+proc PyList_Append*(ob1, ob2: PPyObject): int{.cdecl, importc, dynlib: dllname.} #-
+proc PyList_AsTuple*(ob: PPyObject): PPyObject{.cdecl, importc, dynlib: dllname.} #+
+proc PyList_GetItem*(ob: PPyObject, i: int): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc PyList_GetSlice*(ob: PPyObject, i1, i2: int): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc PyList_Insert*(dp: PPyObject, idx: int, item: PPyObject): int{.cdecl, importc, dynlib: dllname.} #-
+proc PyList_New*(size: int): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc PyList_Reverse*(ob: PPyObject): int{.cdecl, importc, dynlib: dllname.} #-
+proc PyList_SetItem*(dp: PPyObject, idx: int, item: PPyObject): int{.cdecl, importc, dynlib: dllname.} #-
+proc PyList_SetSlice*(ob: PPyObject, i1, i2: int, ob2: PPyObject): int{.
+      cdecl, importc, dynlib: dllname.}                 #+
+proc PyList_Size*(ob: PPyObject): int{.cdecl, importc, dynlib: dllname.} #-
+proc PyList_Sort*(ob: PPyObject): int{.cdecl, importc, dynlib: dllname.} #-
+proc PyLong_AsDouble*(ob: PPyObject): float64{.cdecl, importc, dynlib: dllname.} #+
+proc PyLong_AsLong*(ob: PPyObject): int32{.cdecl, importc, dynlib: dllname.} #+
+proc PyLong_FromDouble*(db: float64): PPyObject{.cdecl, importc, dynlib: dllname.} #+
+proc PyLong_FromLong*(L: int32): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc PyLong_FromString*(pc: cstring, ppc: var cstring, i: int): PPyObject{.
+      cdecl, importc, dynlib: dllname.}                 #-
+proc PyLong_FromUnsignedLong*(val: int): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc PyLong_AsUnsignedLong*(ob: PPyObject): int{.cdecl, importc, dynlib: dllname.} #-
+proc PyLong_FromUnicode*(ob: PPyObject, a, b: int): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc PyLong_FromLongLong*(val: Int64): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc PyLong_AsLongLong*(ob: PPyObject): Int64{.cdecl, importc, dynlib: dllname.} #-
+proc PyMapping_Check*(ob: PPyObject): int{.cdecl, importc, dynlib: dllname.} #-
+proc PyMapping_GetItemString*(ob: PPyObject, key: cstring): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc PyMapping_HasKey*(ob, key: PPyObject): int{.cdecl, importc, dynlib: dllname.} #-
+proc PyMapping_HasKeyString*(ob: PPyObject, key: cstring): int{.cdecl, importc, dynlib: dllname.} #-
+proc PyMapping_Length*(ob: PPyObject): int{.cdecl, importc, dynlib: dllname.} #-
+proc PyMapping_SetItemString*(ob: PPyObject, key: cstring, value: PPyObject): int{.
+      cdecl, importc, dynlib: dllname.}                 #-
+proc PyMethod_Class*(ob: PPyObject): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc PyMethod_Function*(ob: PPyObject): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc PyMethod_New*(ob1, ob2, ob3: PPyObject): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc PyMethod_Self*(ob: PPyObject): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc PyModule_GetName*(ob: PPyObject): cstring{.cdecl, importc, dynlib: dllname.} #-
+proc PyModule_New*(key: cstring): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc PyNumber_Absolute*(ob: PPyObject): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc PyNumber_Add*(ob1, ob2: PPyObject): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc PyNumber_And*(ob1, ob2: PPyObject): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc PyNumber_Check*(ob: PPyObject): int{.cdecl, importc, dynlib: dllname.} #-
+proc PyNumber_Coerce*(ob1, ob2: var PPyObject): int{.cdecl, importc, dynlib: dllname.} #-
+proc PyNumber_Divide*(ob1, ob2: PPyObject): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc PyNumber_FloorDivide*(ob1, ob2: PPyObject): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc PyNumber_TrueDivide*(ob1, ob2: PPyObject): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc PyNumber_Divmod*(ob1, ob2: PPyObject): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc PyNumber_Float*(ob: PPyObject): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc PyNumber_Int*(ob: PPyObject): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc PyNumber_Invert*(ob: PPyObject): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc PyNumber_Long*(ob: PPyObject): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc PyNumber_Lshift*(ob1, ob2: PPyObject): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc PyNumber_Multiply*(ob1, ob2: PPyObject): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc PyNumber_Negative*(ob: PPyObject): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc PyNumber_Or*(ob1, ob2: PPyObject): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc PyNumber_Positive*(ob: PPyObject): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc PyNumber_Power*(ob1, ob2, ob3: PPyObject): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc PyNumber_Remainder*(ob1, ob2: PPyObject): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc PyNumber_Rshift*(ob1, ob2: PPyObject): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc PyNumber_Subtract*(ob1, ob2: PPyObject): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc PyNumber_Xor*(ob1, ob2: PPyObject): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc PyOS_InitInterrupts*(){.cdecl, importc, dynlib: dllname.} #-
+proc PyOS_InterruptOccurred*(): int{.cdecl, importc, dynlib: dllname.} #-
+proc PyObject_CallObject*(ob, args: PPyObject): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc PyObject_Compare*(ob1, ob2: PPyObject): int{.cdecl, importc, dynlib: dllname.} #-
+proc PyObject_GetAttr*(ob1, ob2: PPyObject): PPyObject{.cdecl, importc, dynlib: dllname.} #+
+proc PyObject_GetAttrString*(ob: PPyObject, c: cstring): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc PyObject_GetItem*(ob, key: PPyObject): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc PyObject_DelItem*(ob, key: PPyObject): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc PyObject_HasAttrString*(ob: PPyObject, key: cstring): int{.cdecl, importc, dynlib: dllname.} #-
+proc PyObject_Hash*(ob: PPyObject): int32{.cdecl, importc, dynlib: dllname.} #-
+proc PyObject_IsTrue*(ob: PPyObject): int{.cdecl, importc, dynlib: dllname.} #-
+proc PyObject_Length*(ob: PPyObject): int{.cdecl, importc, dynlib: dllname.} #-
+proc PyObject_Repr*(ob: PPyObject): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc PyObject_SetAttr*(ob1, ob2, ob3: PPyObject): int{.cdecl, importc, dynlib: dllname.} #-
+proc PyObject_SetAttrString*(ob: PPyObject, key: cstring, value: PPyObject): int{.
+      cdecl, importc, dynlib: dllname.}                 #-
+proc PyObject_SetItem*(ob1, ob2, ob3: PPyObject): int{.cdecl, importc, dynlib: dllname.} #-
+proc PyObject_Init*(ob: PPyObject, t: PPyTypeObject): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc PyObject_InitVar*(ob: PPyObject, t: PPyTypeObject, size: int): PPyObject{.
+      cdecl, importc, dynlib: dllname.}                 #-
+proc PyObject_New*(t: PPyTypeObject): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc PyObject_NewVar*(t: PPyTypeObject, size: int): PPyObject{.cdecl, importc, dynlib: dllname.}
+proc PyObject_Free*(ob: PPyObject){.cdecl, importc, dynlib: dllname.} #-
+proc PyObject_IsInstance*(inst, cls: PPyObject): int{.cdecl, importc, dynlib: dllname.} #-
+proc PyObject_IsSubclass*(derived, cls: PPyObject): int{.cdecl, importc, dynlib: dllname.}
+proc PyObject_GenericGetAttr*(obj, name: PPyObject): PPyObject{.cdecl, importc, dynlib: dllname.}
+proc PyObject_GenericSetAttr*(obj, name, value: PPyObject): int{.cdecl, importc, dynlib: dllname.} #-
+proc PyObject_GC_Malloc*(size: int): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc PyObject_GC_New*(t: PPyTypeObject): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc PyObject_GC_NewVar*(t: PPyTypeObject, size: int): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc PyObject_GC_Resize*(t: PPyObject, newsize: int): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc PyObject_GC_Del*(ob: PPyObject){.cdecl, importc, dynlib: dllname.} #-
+proc PyObject_GC_Track*(ob: PPyObject){.cdecl, importc, dynlib: dllname.} #-
+proc PyObject_GC_UnTrack*(ob: PPyObject){.cdecl, importc, dynlib: dllname.} #-
+proc PyRange_New*(l1, l2, l3: int32, i: int): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc PySequence_Check*(ob: PPyObject): int{.cdecl, importc, dynlib: dllname.} #-
+proc PySequence_Concat*(ob1, ob2: PPyObject): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc PySequence_Count*(ob1, ob2: PPyObject): int{.cdecl, importc, dynlib: dllname.} #-
+proc PySequence_GetItem*(ob: PPyObject, i: int): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc PySequence_GetSlice*(ob: PPyObject, i1, i2: int): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc PySequence_In*(ob1, ob2: PPyObject): int{.cdecl, importc, dynlib: dllname.} #-
+proc PySequence_Index*(ob1, ob2: PPyObject): int{.cdecl, importc, dynlib: dllname.} #-
+proc PySequence_Length*(ob: PPyObject): int{.cdecl, importc, dynlib: dllname.} #-
+proc PySequence_Repeat*(ob: PPyObject, count: int): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc PySequence_SetItem*(ob: PPyObject, i: int, value: PPyObject): int{.
+      cdecl, importc, dynlib: dllname.}                 #-
+proc PySequence_SetSlice*(ob: PPyObject, i1, i2: int, value: PPyObject): int{.
+      cdecl, importc, dynlib: dllname.}                 #-
+proc PySequence_DelSlice*(ob: PPyObject, i1, i2: int): int{.cdecl, importc, dynlib: dllname.} #-
+proc PySequence_Tuple*(ob: PPyObject): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc PySequence_Contains*(ob, value: PPyObject): int{.cdecl, importc, dynlib: dllname.} #-
+proc PySlice_GetIndices*(ob: PPySliceObject, len: int, 
+                             start, stop, step: var int): int{.cdecl, importc, dynlib: dllname.} #-
+proc PySlice_GetIndicesEx*(ob: PPySliceObject, len: int, 
+                               start, stop, step, slicelength: var int): int{.
+      cdecl, importc, dynlib: dllname.}                 #-
+proc PySlice_New*(start, stop, step: PPyObject): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc PyString_Concat*(ob1: var PPyObject, ob2: PPyObject){.cdecl, importc, dynlib: dllname.} #-
+proc PyString_ConcatAndDel*(ob1: var PPyObject, ob2: PPyObject){.cdecl, importc, dynlib: dllname.} #-
+proc PyString_Format*(ob1, ob2: PPyObject): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc PyString_FromStringAndSize*(s: cstring, i: int): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc PyString_Size*(ob: PPyObject): int{.cdecl, importc, dynlib: dllname.} #-
+proc PyString_DecodeEscape*(s: cstring, length: int, errors: cstring, 
+                                unicode: int, recode_encoding: cstring): PPyObject{.
+      cdecl, importc, dynlib: dllname.}                 #-
+proc PyString_Repr*(ob: PPyObject, smartquotes: int): PPyObject{.cdecl, importc, dynlib: dllname.} #+
+proc PySys_GetObject*(s: cstring): PPyObject{.cdecl, importc, dynlib: dllname.} 
+#-
+#PySys_Init:procedure; cdecl, importc, dynlib: dllname;
+#-
+proc PySys_SetObject*(s: cstring, ob: PPyObject): int{.cdecl, importc, dynlib: dllname.} #-
+proc PySys_SetPath*(path: cstring){.cdecl, importc, dynlib: dllname.} #-
+#PyTraceBack_Fetch:function:PPyObject; cdecl, importc, dynlib: dllname;
+#-
+proc PyTraceBack_Here*(p: pointer): int{.cdecl, importc, dynlib: dllname.} #-
+proc PyTraceBack_Print*(ob1, ob2: PPyObject): int{.cdecl, importc, dynlib: dllname.} #-
+#PyTraceBack_Store:function (ob:PPyObject):integer; cdecl, importc, dynlib: dllname;
+#+
+proc PyTuple_GetItem*(ob: PPyObject, i: int): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc PyTuple_GetSlice*(ob: PPyObject, i1, i2: int): PPyObject{.cdecl, importc, dynlib: dllname.} #+
+proc PyTuple_New*(size: int): PPyObject{.cdecl, importc, dynlib: dllname.} #+
+proc PyTuple_SetItem*(ob: PPyObject, key: int, value: PPyObject): int{.cdecl, importc, dynlib: dllname.} #+
+proc PyTuple_Size*(ob: PPyObject): int{.cdecl, importc, dynlib: dllname.} #+
+proc PyType_IsSubtype*(a, b: PPyTypeObject): int{.cdecl, importc, dynlib: dllname.}
+proc PyType_GenericAlloc*(atype: PPyTypeObject, nitems: int): PPyObject{.
+      cdecl, importc, dynlib: dllname.}
+proc PyType_GenericNew*(atype: PPyTypeObject, args, kwds: PPyObject): PPyObject{.
+      cdecl, importc, dynlib: dllname.}
+proc PyType_Ready*(atype: PPyTypeObject): int{.cdecl, importc, dynlib: dllname.} #+
+proc PyUnicode_FromWideChar*(w: pointer, size: int): PPyObject{.cdecl, importc, dynlib: dllname.} #+
+proc PyUnicode_AsWideChar*(unicode: PPyObject, w: pointer, size: int): int{.
+      cdecl, importc, dynlib: dllname.}                 #-
+proc PyUnicode_FromOrdinal*(ordinal: int): PPyObject{.cdecl, importc, dynlib: dllname.}
+proc PyWeakref_GetObject*(theRef: PPyObject): PPyObject{.cdecl, importc, dynlib: dllname.}
+proc PyWeakref_NewProxy*(ob, callback: PPyObject): PPyObject{.cdecl, importc, dynlib: dllname.}
+proc PyWeakref_NewRef*(ob, callback: PPyObject): PPyObject{.cdecl, importc, dynlib: dllname.}
+proc PyWrapper_New*(ob1, ob2: PPyObject): PPyObject{.cdecl, importc, dynlib: dllname.}
+proc PyBool_FromLong*(ok: int): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc Py_AtExit*(prc: proc ()): int{.cdecl, importc, dynlib: dllname.} #-
+#Py_Cleanup:procedure; cdecl, importc, dynlib: dllname;
+#-
+proc Py_CompileString*(s1, s2: cstring, i: int): PPyObject{.cdecl, importc, dynlib: dllname.} #-
+proc Py_FatalError*(s: cstring){.cdecl, importc, dynlib: dllname.} #-
+proc Py_FindMethod*(md: PPyMethodDef, ob: PPyObject, key: cstring): PPyObject{.
+      cdecl, importc, dynlib: dllname.}                 #-
+proc Py_FindMethodInChain*(mc: PPyMethodChain, ob: PPyObject, key: cstring): PPyObject{.
+      cdecl, importc, dynlib: dllname.}                 #-
+proc Py_FlushLine*(){.cdecl, importc, dynlib: dllname.} #+
+proc Py_Finalize*(){.cdecl, importc, dynlib: dllname.} #-
+proc PyErr_ExceptionMatches*(exc: PPyObject): int{.cdecl, importc, dynlib: dllname.} #-
+proc PyErr_GivenExceptionMatches*(raised_exc, exc: PPyObject): int{.cdecl, importc, dynlib: dllname.} #-
+proc PyEval_EvalCode*(co: PPyCodeObject, globals, locals: PPyObject): PPyObject{.
+      cdecl, importc, dynlib: dllname.}                 #+
+proc Py_GetVersion*(): cstring{.cdecl, importc, dynlib: dllname.} #+
+proc Py_GetCopyright*(): cstring{.cdecl, importc, dynlib: dllname.} #+
+proc Py_GetExecPrefix*(): cstring{.cdecl, importc, dynlib: dllname.} #+
+proc Py_GetPath*(): cstring{.cdecl, importc, dynlib: dllname.} #+
+proc Py_GetPrefix*(): cstring{.cdecl, importc, dynlib: dllname.} #+
+proc Py_GetProgramName*(): cstring{.cdecl, importc, dynlib: dllname.} #-
+proc PyParser_SimpleParseString*(str: cstring, start: int): PNode{.cdecl, importc, dynlib: dllname.} #-
+proc PyNode_Free*(n: PNode){.cdecl, importc, dynlib: dllname.} #-
+proc PyErr_NewException*(name: cstring, base, dict: PPyObject): PPyObject{.
+      cdecl, importc, dynlib: dllname.}                 #-
+proc Py_Malloc*(size: int): Pointer {.cdecl, importc, dynlib: dllname.}
+proc PyMem_Malloc*(size: int): Pointer {.cdecl, importc, dynlib: dllname.}
+proc PyObject_CallMethod*(obj: PPyObject, theMethod, 
+                              format: cstring): PPyObject{.cdecl, importc, dynlib: dllname.}
+proc Py_SetProgramName*(name: cstring){.cdecl, importc, dynlib: dllname.}
+proc Py_IsInitialized*(): int{.cdecl, importc, dynlib: dllname.}
+proc Py_GetProgramFullPath*(): cstring{.cdecl, importc, dynlib: dllname.}
+proc Py_NewInterpreter*(): PPyThreadState{.cdecl, importc, dynlib: dllname.}
+proc Py_EndInterpreter*(tstate: PPyThreadState){.cdecl, importc, dynlib: dllname.}
+proc PyEval_AcquireLock*(){.cdecl, importc, dynlib: dllname.}
+proc PyEval_ReleaseLock*(){.cdecl, importc, dynlib: dllname.}
+proc PyEval_AcquireThread*(tstate: PPyThreadState){.cdecl, importc, dynlib: dllname.}
+proc PyEval_ReleaseThread*(tstate: PPyThreadState){.cdecl, importc, dynlib: dllname.}
+proc PyInterpreterState_New*(): PPyInterpreterState{.cdecl, importc, dynlib: dllname.}
+proc PyInterpreterState_Clear*(interp: PPyInterpreterState){.cdecl, importc, dynlib: dllname.}
+proc PyInterpreterState_Delete*(interp: PPyInterpreterState){.cdecl, importc, dynlib: dllname.}
+proc PyThreadState_New*(interp: PPyInterpreterState): PPyThreadState{.cdecl, importc, dynlib: dllname.}
+proc PyThreadState_Clear*(tstate: PPyThreadState){.cdecl, importc, dynlib: dllname.}
+proc PyThreadState_Delete*(tstate: PPyThreadState){.cdecl, importc, dynlib: dllname.}
+proc PyThreadState_Get*(): PPyThreadState{.cdecl, importc, dynlib: dllname.}
+proc PyThreadState_Swap*(tstate: PPyThreadState): PPyThreadState{.cdecl, importc, dynlib: dllname.} 
+
+#Further exported Objects, may be implemented later
+#
+#    PyCode_New: Pointer;
+#    PyErr_SetInterrupt: Pointer;
+#    PyFile_AsFile: Pointer;
+#    PyFile_FromFile: Pointer;
+#    PyFloat_AsString: Pointer;
+#    PyFrame_BlockPop: Pointer;
+#    PyFrame_BlockSetup: Pointer;
+#    PyFrame_ExtendStack: Pointer;
+#    PyFrame_FastToLocals: Pointer;
+#    PyFrame_LocalsToFast: Pointer;
+#    PyFrame_New: Pointer;
+#    PyGrammar_AddAccelerators: Pointer;
+#    PyGrammar_FindDFA: Pointer;
+#    PyGrammar_LabelRepr: Pointer;
+#    PyInstance_DoBinOp: Pointer;
+#    PyInt_GetMax: Pointer;
+#    PyMarshal_Init: Pointer;
+#    PyMarshal_ReadLongFromFile: Pointer;
+#    PyMarshal_ReadObjectFromFile: Pointer;
+#    PyMarshal_ReadObjectFromString: Pointer;
+#    PyMarshal_WriteLongToFile: Pointer;
+#    PyMarshal_WriteObjectToFile: Pointer;
+#    PyMember_Get: Pointer;
+#    PyMember_Set: Pointer;
+#    PyNode_AddChild: Pointer;
+#    PyNode_Compile: Pointer;
+#    PyNode_New: Pointer;
+#    PyOS_GetLastModificationTime: Pointer;
+#    PyOS_Readline: Pointer;
+#    PyOS_strtol: Pointer;
+#    PyOS_strtoul: Pointer;
+#    PyObject_CallFunction: Pointer;
+#    PyObject_CallMethod: Pointer;
+#    PyObject_Print: Pointer;
+#    PyParser_AddToken: Pointer;
+#    PyParser_Delete: Pointer;
+#    PyParser_New: Pointer;
+#    PyParser_ParseFile: Pointer;
+#    PyParser_ParseString: Pointer;
+#    PyParser_SimpleParseFile: Pointer;
+#    PyRun_AnyFile: Pointer;
+#    PyRun_File: Pointer;
+#    PyRun_InteractiveLoop: Pointer;
+#    PyRun_InteractiveOne: Pointer;
+#    PyRun_SimpleFile: Pointer;
+#    PySys_GetFile: Pointer;
+#    PyToken_OneChar: Pointer;
+#    PyToken_TwoChars: Pointer;
+#    PyTokenizer_Free: Pointer;
+#    PyTokenizer_FromFile: Pointer;
+#    PyTokenizer_FromString: Pointer;
+#    PyTokenizer_Get: Pointer;
+#    Py_Main: Pointer;
+#    _PyObject_NewVar: Pointer;
+#    _PyParser_Grammar: Pointer;
+#    _PyParser_TokenNames: Pointer;
+#    _PyThread_Started: Pointer;
+#    _Py_c_diff: Pointer;
+#    _Py_c_neg: Pointer;
+#    _Py_c_pow: Pointer;
+#    _Py_c_prod: Pointer;
+#    _Py_c_quot: Pointer;
+#    _Py_c_sum: Pointer;
+#
+
+# This function handles all cardinals, pointer types (with no adjustment of pointers!)
+# (Extended) floats, which are handled as Python doubles and currencies, handled
+# as (normalized) Python doubles.
+proc PyImport_ExecCodeModule*(name: String, codeobject: PPyObject): PPyObject
+proc PyString_Check*(obj: PPyObject): bool
+proc PyString_CheckExact*(obj: PPyObject): bool
+proc PyFloat_Check*(obj: PPyObject): bool
+proc PyFloat_CheckExact*(obj: PPyObject): bool
+proc PyInt_Check*(obj: PPyObject): bool
+proc PyInt_CheckExact*(obj: PPyObject): bool
+proc PyLong_Check*(obj: PPyObject): bool
+proc PyLong_CheckExact*(obj: PPyObject): bool
+proc PyTuple_Check*(obj: PPyObject): bool
+proc PyTuple_CheckExact*(obj: PPyObject): bool
+proc PyInstance_Check*(obj: PPyObject): bool
+proc PyClass_Check*(obj: PPyObject): bool
+proc PyMethod_Check*(obj: PPyObject): bool
+proc PyList_Check*(obj: PPyObject): bool
+proc PyList_CheckExact*(obj: PPyObject): bool
+proc PyDict_Check*(obj: PPyObject): bool
+proc PyDict_CheckExact*(obj: PPyObject): bool
+proc PyModule_Check*(obj: PPyObject): bool
+proc PyModule_CheckExact*(obj: PPyObject): bool
+proc PySlice_Check*(obj: PPyObject): bool
+proc PyFunction_Check*(obj: PPyObject): bool
+proc PyUnicode_Check*(obj: PPyObject): bool
+proc PyUnicode_CheckExact*(obj: PPyObject): bool
+proc PyType_IS_GC*(t: PPyTypeObject): bool
+proc PyObject_IS_GC*(obj: PPyObject): bool
+proc PyBool_Check*(obj: PPyObject): bool
+proc PyBaseString_Check*(obj: PPyObject): bool
+proc PyEnum_Check*(obj: PPyObject): bool
+proc PyObject_TypeCheck*(obj: PPyObject, t: PPyTypeObject): bool
+proc Py_InitModule*(name: cstring, md: PPyMethodDef): PPyObject
+proc PyType_HasFeature*(AType: PPyTypeObject, AFlag: int): bool
+# implementation
+
+proc Py_INCREF*(op: PPyObject) {.inline.} = 
+  Inc(op.ob_refcnt)
+
+proc Py_DECREF*(op: PPyObject) {.inline.} = 
+  Dec(op.ob_refcnt)
+  if op.ob_refcnt == 0: 
+    op.ob_type.tp_dealloc(op)
+
+proc Py_XINCREF*(op: PPyObject) {.inline.} = 
+  if op != nil: Py_INCREF(op)
+  
+proc Py_XDECREF*(op: PPyObject) {.inline.} = 
+  if op != nil: Py_DECREF(op)
+  
+proc PyImport_ExecCodeModule(name: string, codeobject: PPyObject): PPyObject = 
+  var m, d, v, modules: PPyObject
+  m = PyImport_AddModule(cstring(name))
+  if m == nil: 
+    return nil
+  d = PyModule_GetDict(m)
+  if PyDict_GetItemString(d, "__builtins__") == nil: 
+    if PyDict_SetItemString(d, "__builtins__", PyEval_GetBuiltins()) != 0: 
+      return nil
+  if PyDict_SetItemString(d, "__file__", 
+                          PPyCodeObject(codeobject).co_filename) != 0: 
+    PyErr_Clear() # Not important enough to report
+  v = PyEval_EvalCode(PPyCodeObject(codeobject), d, d) # XXX owner ?
+  if v == nil: 
+    return nil
+  Py_XDECREF(v)
+  modules = PyImport_GetModuleDict()
+  if PyDict_GetItemString(modules, cstring(name)) == nil: 
+    PyErr_SetString(PyExc_ImportError^ , cstring(
+        "Loaded module " & name & "not found in sys.modules"))
+    return nil
+  Py_XINCREF(m)
+  Result = m
+
+proc PyString_Check(obj: PPyObject): bool = 
+  Result = PyObject_TypeCheck(obj, PyString_Type)
+
+proc PyString_CheckExact(obj: PPyObject): bool = 
+  Result = (obj != nil) and (obj.ob_type == PyString_Type)
+
+proc PyFloat_Check(obj: PPyObject): bool = 
+  Result = PyObject_TypeCheck(obj, PyFloat_Type)
+
+proc PyFloat_CheckExact(obj: PPyObject): bool = 
+  Result = (obj != nil) and (obj.ob_type == PyFloat_Type)
+
+proc PyInt_Check(obj: PPyObject): bool = 
+  Result = PyObject_TypeCheck(obj, PyInt_Type)
+
+proc PyInt_CheckExact(obj: PPyObject): bool = 
+  Result = (obj != nil) and (obj.ob_type == PyInt_Type)
+
+proc PyLong_Check(obj: PPyObject): bool = 
+  Result = PyObject_TypeCheck(obj, PyLong_Type)
+
+proc PyLong_CheckExact(obj: PPyObject): bool = 
+  Result = (obj != nil) and (obj.ob_type == PyLong_Type)
+
+proc PyTuple_Check(obj: PPyObject): bool = 
+  Result = PyObject_TypeCheck(obj, PyTuple_Type)
+
+proc PyTuple_CheckExact(obj: PPyObject): bool = 
+  Result = (obj != nil) and (obj^ .ob_type == PyTuple_Type)
+
+proc PyInstance_Check(obj: PPyObject): bool = 
+  Result = (obj != nil) and (obj^ .ob_type == PyInstance_Type)
+
+proc PyClass_Check(obj: PPyObject): bool = 
+  Result = (obj != nil) and (obj^ .ob_type == PyClass_Type)
+
+proc PyMethod_Check(obj: PPyObject): bool = 
+  Result = (obj != nil) and (obj^ .ob_type == PyMethod_Type)
+
+proc PyList_Check(obj: PPyObject): bool = 
+  Result = PyObject_TypeCheck(obj, PyList_Type)
+
+proc PyList_CheckExact(obj: PPyObject): bool = 
+  Result = (obj != nil) and (obj^ .ob_type == PyList_Type)
+
+proc PyDict_Check(obj: PPyObject): bool = 
+  Result = PyObject_TypeCheck(obj, PyDict_Type)
+
+proc PyDict_CheckExact(obj: PPyObject): bool = 
+  Result = (obj != nil) and (obj^ .ob_type == PyDict_Type)
+
+proc PyModule_Check(obj: PPyObject): bool = 
+  Result = PyObject_TypeCheck(obj, PyModule_Type)
+
+proc PyModule_CheckExact(obj: PPyObject): bool = 
+  Result = (obj != nil) and (obj^ .ob_type == PyModule_Type)
+
+proc PySlice_Check(obj: PPyObject): bool = 
+  Result = (obj != nil) and (obj^ .ob_type == PySlice_Type)
+
+proc PyFunction_Check(obj: PPyObject): bool = 
+  Result = (obj != nil) and
+      ((obj.ob_type == PyCFunction_Type) or
+      (obj.ob_type == PyFunction_Type))
+
+proc PyUnicode_Check(obj: PPyObject): bool = 
+  Result = PyObject_TypeCheck(obj, PyUnicode_Type)
+
+proc PyUnicode_CheckExact(obj: PPyObject): bool = 
+  Result = (obj != nil) and (obj.ob_type == PyUnicode_Type)
+
+proc PyType_IS_GC(t: PPyTypeObject): bool = 
+  Result = PyType_HasFeature(t, Py_TPFLAGS_HAVE_GC)
+
+proc PyObject_IS_GC(obj: PPyObject): bool = 
+  Result = PyType_IS_GC(obj.ob_type) and
+      ((obj.ob_type.tp_is_gc == nil) or (obj.ob_type.tp_is_gc(obj) == 1))
+
+proc PyBool_Check(obj: PPyObject): bool = 
+  Result = (obj != nil) and (obj.ob_type == PyBool_Type)
+
+proc PyBaseString_Check(obj: PPyObject): bool = 
+  Result = PyObject_TypeCheck(obj, PyBaseString_Type)
+
+proc PyEnum_Check(obj: PPyObject): bool = 
+  Result = (obj != nil) and (obj.ob_type == PyEnum_Type)
+
+proc PyObject_TypeCheck(obj: PPyObject, t: PPyTypeObject): bool = 
+  Result = (obj != nil) and (obj.ob_type == t)
+  if not Result and (obj != nil) and (t != nil): 
+    Result = PyType_IsSubtype(obj.ob_type, t) == 1
+  
+proc Py_InitModule(name: cstring, md: PPyMethodDef): PPyObject = 
+  result = Py_InitModule4(name, md, nil, nil, 1012)
+
+proc PyType_HasFeature(AType: PPyTypeObject, AFlag: int): bool = 
+  #(((t)->tp_flags & (f)) != 0)
+  Result = (AType.tp_flags and AFlag) != 0
+
+proc init(lib: TLibHandle) = 
+  Py_DebugFlag = cast[PInt](symAddr(lib, "Py_DebugFlag"))
+  Py_VerboseFlag = cast[PInt](symAddr(lib, "Py_VerboseFlag"))
+  Py_InteractiveFlag = cast[PInt](symAddr(lib, "Py_InteractiveFlag"))
+  Py_OptimizeFlag = cast[PInt](symAddr(lib, "Py_OptimizeFlag"))
+  Py_NoSiteFlag = cast[PInt](symAddr(lib, "Py_NoSiteFlag"))
+  Py_UseClassExceptionsFlag = cast[PInt](symAddr(lib, "Py_UseClassExceptionsFlag"))
+  Py_FrozenFlag = cast[PInt](symAddr(lib, "Py_FrozenFlag"))
+  Py_TabcheckFlag = cast[PInt](symAddr(lib, "Py_TabcheckFlag"))
+  Py_UnicodeFlag = cast[PInt](symAddr(lib, "Py_UnicodeFlag"))
+  Py_IgnoreEnvironmentFlag = cast[PInt](symAddr(lib, "Py_IgnoreEnvironmentFlag"))
+  Py_DivisionWarningFlag = cast[PInt](symAddr(lib, "Py_DivisionWarningFlag"))
+  Py_None = cast[PPyObject](symAddr(lib, "_Py_NoneStruct"))
+  Py_Ellipsis = cast[PPyObject](symAddr(lib, "_Py_EllipsisObject"))
+  Py_False = cast[PPyIntObject](symAddr(lib, "_Py_ZeroStruct"))
+  Py_True = cast[PPyIntObject](symAddr(lib, "_Py_TrueStruct"))
+  Py_NotImplemented = cast[PPyObject](symAddr(lib, "_Py_NotImplementedStruct"))
+  PyImport_FrozenModules = cast[PP_frozen](symAddr(lib, "PyImport_FrozenModules"))
+  PyExc_AttributeError = cast[PPPyObject](symAddr(lib, "PyExc_AttributeError"))
+  PyExc_EOFError = cast[PPPyObject](symAddr(lib, "PyExc_EOFError"))
+  PyExc_IOError = cast[PPPyObject](symAddr(lib, "PyExc_IOError"))
+  PyExc_ImportError = cast[PPPyObject](symAddr(lib, "PyExc_ImportError"))
+  PyExc_IndexError = cast[PPPyObject](symAddr(lib, "PyExc_IndexError"))
+  PyExc_KeyError = cast[PPPyObject](symAddr(lib, "PyExc_KeyError"))
+  PyExc_KeyboardInterrupt = cast[PPPyObject](symAddr(lib, "PyExc_KeyboardInterrupt"))
+  PyExc_MemoryError = cast[PPPyObject](symAddr(lib, "PyExc_MemoryError"))
+  PyExc_NameError = cast[PPPyObject](symAddr(lib, "PyExc_NameError"))
+  PyExc_OverflowError = cast[PPPyObject](symAddr(lib, "PyExc_OverflowError"))
+  PyExc_RuntimeError = cast[PPPyObject](symAddr(lib, "PyExc_RuntimeError"))
+  PyExc_SyntaxError = cast[PPPyObject](symAddr(lib, "PyExc_SyntaxError"))
+  PyExc_SystemError = cast[PPPyObject](symAddr(lib, "PyExc_SystemError"))
+  PyExc_SystemExit = cast[PPPyObject](symAddr(lib, "PyExc_SystemExit"))
+  PyExc_TypeError = cast[PPPyObject](symAddr(lib, "PyExc_TypeError"))
+  PyExc_ValueError = cast[PPPyObject](symAddr(lib, "PyExc_ValueError"))
+  PyExc_ZeroDivisionError = cast[PPPyObject](symAddr(lib, "PyExc_ZeroDivisionError"))
+  PyExc_ArithmeticError = cast[PPPyObject](symAddr(lib, "PyExc_ArithmeticError"))
+  PyExc_Exception = cast[PPPyObject](symAddr(lib, "PyExc_Exception"))
+  PyExc_FloatingPointError = cast[PPPyObject](symAddr(lib, "PyExc_FloatingPointError"))
+  PyExc_LookupError = cast[PPPyObject](symAddr(lib, "PyExc_LookupError"))
+  PyExc_StandardError = cast[PPPyObject](symAddr(lib, "PyExc_StandardError"))
+  PyExc_AssertionError = cast[PPPyObject](symAddr(lib, "PyExc_AssertionError"))
+  PyExc_EnvironmentError = cast[PPPyObject](symAddr(lib, "PyExc_EnvironmentError"))
+  PyExc_IndentationError = cast[PPPyObject](symAddr(lib, "PyExc_IndentationError"))
+  PyExc_MemoryErrorInst = cast[PPPyObject](symAddr(lib, "PyExc_MemoryErrorInst"))
+  PyExc_NotImplementedError = cast[PPPyObject](symAddr(lib, "PyExc_NotImplementedError"))
+  PyExc_OSError = cast[PPPyObject](symAddr(lib, "PyExc_OSError"))
+  PyExc_TabError = cast[PPPyObject](symAddr(lib, "PyExc_TabError"))
+  PyExc_UnboundLocalError = cast[PPPyObject](symAddr(lib, "PyExc_UnboundLocalError"))
+  PyExc_UnicodeError = cast[PPPyObject](symAddr(lib, "PyExc_UnicodeError"))
+  PyExc_Warning = cast[PPPyObject](symAddr(lib, "PyExc_Warning"))
+  PyExc_DeprecationWarning = cast[PPPyObject](symAddr(lib, "PyExc_DeprecationWarning"))
+  PyExc_RuntimeWarning = cast[PPPyObject](symAddr(lib, "PyExc_RuntimeWarning"))
+  PyExc_SyntaxWarning = cast[PPPyObject](symAddr(lib, "PyExc_SyntaxWarning"))
+  PyExc_UserWarning = cast[PPPyObject](symAddr(lib, "PyExc_UserWarning"))
+  PyExc_OverflowWarning = cast[PPPyObject](symAddr(lib, "PyExc_OverflowWarning"))
+  PyExc_ReferenceError = cast[PPPyObject](symAddr(lib, "PyExc_ReferenceError"))
+  PyExc_StopIteration = cast[PPPyObject](symAddr(lib, "PyExc_StopIteration"))
+  PyExc_FutureWarning = cast[PPPyObject](symAddr(lib, "PyExc_FutureWarning"))
+  PyExc_PendingDeprecationWarning = cast[PPPyObject](symAddr(lib, 
+      "PyExc_PendingDeprecationWarning"))
+  PyExc_UnicodeDecodeError = cast[PPPyObject](symAddr(lib, "PyExc_UnicodeDecodeError"))
+  PyExc_UnicodeEncodeError = cast[PPPyObject](symAddr(lib, "PyExc_UnicodeEncodeError"))
+  PyExc_UnicodeTranslateError = cast[PPPyObject](symAddr(lib, "PyExc_UnicodeTranslateError"))
+  PyType_Type = cast[PPyTypeObject](symAddr(lib, "PyType_Type"))
+  PyCFunction_Type = cast[PPyTypeObject](symAddr(lib, "PyCFunction_Type"))
+  PyCObject_Type = cast[PPyTypeObject](symAddr(lib, "PyCObject_Type"))
+  PyClass_Type = cast[PPyTypeObject](symAddr(lib, "PyClass_Type"))
+  PyCode_Type = cast[PPyTypeObject](symAddr(lib, "PyCode_Type"))
+  PyComplex_Type = cast[PPyTypeObject](symAddr(lib, "PyComplex_Type"))
+  PyDict_Type = cast[PPyTypeObject](symAddr(lib, "PyDict_Type"))
+  PyFile_Type = cast[PPyTypeObject](symAddr(lib, "PyFile_Type"))
+  PyFloat_Type = cast[PPyTypeObject](symAddr(lib, "PyFloat_Type"))
+  PyFrame_Type = cast[PPyTypeObject](symAddr(lib, "PyFrame_Type"))
+  PyFunction_Type = cast[PPyTypeObject](symAddr(lib, "PyFunction_Type"))
+  PyInstance_Type = cast[PPyTypeObject](symAddr(lib, "PyInstance_Type"))
+  PyInt_Type = cast[PPyTypeObject](symAddr(lib, "PyInt_Type"))
+  PyList_Type = cast[PPyTypeObject](symAddr(lib, "PyList_Type"))
+  PyLong_Type = cast[PPyTypeObject](symAddr(lib, "PyLong_Type"))
+  PyMethod_Type = cast[PPyTypeObject](symAddr(lib, "PyMethod_Type"))
+  PyModule_Type = cast[PPyTypeObject](symAddr(lib, "PyModule_Type"))
+  PyObject_Type = cast[PPyTypeObject](symAddr(lib, "PyObject_Type"))
+  PyRange_Type = cast[PPyTypeObject](symAddr(lib, "PyRange_Type"))
+  PySlice_Type = cast[PPyTypeObject](symAddr(lib, "PySlice_Type"))
+  PyString_Type = cast[PPyTypeObject](symAddr(lib, "PyString_Type"))
+  PyTuple_Type = cast[PPyTypeObject](symAddr(lib, "PyTuple_Type"))
+  PyUnicode_Type = cast[PPyTypeObject](symAddr(lib, "PyUnicode_Type"))
+  PyBaseObject_Type = cast[PPyTypeObject](symAddr(lib, "PyBaseObject_Type"))
+  PyBuffer_Type = cast[PPyTypeObject](symAddr(lib, "PyBuffer_Type"))
+  PyCallIter_Type = cast[PPyTypeObject](symAddr(lib, "PyCallIter_Type"))
+  PyCell_Type = cast[PPyTypeObject](symAddr(lib, "PyCell_Type"))
+  PyClassMethod_Type = cast[PPyTypeObject](symAddr(lib, "PyClassMethod_Type"))
+  PyProperty_Type = cast[PPyTypeObject](symAddr(lib, "PyProperty_Type"))
+  PySeqIter_Type = cast[PPyTypeObject](symAddr(lib, "PySeqIter_Type"))
+  PyStaticMethod_Type = cast[PPyTypeObject](symAddr(lib, "PyStaticMethod_Type"))
+  PySuper_Type = cast[PPyTypeObject](symAddr(lib, "PySuper_Type"))
+  PySymtableEntry_Type = cast[PPyTypeObject](symAddr(lib, "PySymtableEntry_Type"))
+  PyTraceBack_Type = cast[PPyTypeObject](symAddr(lib, "PyTraceBack_Type"))
+  PyWrapperDescr_Type = cast[PPyTypeObject](symAddr(lib, "PyWrapperDescr_Type"))
+  PyBaseString_Type = cast[PPyTypeObject](symAddr(lib, "PyBaseString_Type"))
+  PyBool_Type = cast[PPyTypeObject](symAddr(lib, "PyBool_Type"))
+  PyEnum_Type = cast[PPyTypeObject](symAddr(lib, "PyEnum_Type"))
+
+# Unfortunately we have to duplicate the loading mechanism here, because Nimrod
+# does not support variables from dynamic libraries. Well designed API's don't
+# require this anyway. Python is an exception.
+
+var
+  lib: TLibHandle
+
+when defined(windows): 
+  const
+    LibNames = ["python26.dll", "python25.dll", 
+      "python24.dll", "python23.dll", "python22.dll", "python21.dll", 
+      "python20.dll", "python16.dll", "python15.dll"]
+elif defined(macosx):
+  const
+    LibNames = ["libpython2.6.dylib", "libpython2.5.dylib", 
+      "libpython2.4.dylib", "libpython2.3.dylib", "libpython2.2.dylib", 
+      "libpython2.1.dylib", "libpython2.0.dylib",
+      "libpython1.6.dylib", "libpython1.5.dylib"]
+else: 
+  const
+    LibNames = ["libpython2.6.so" & dllver, 
+      "libpython2.5.so" & dllver, 
+      "libpython2.4.so" & dllver, 
+      "libpython2.3.so" & dllver, 
+      "libpython2.2.so" & dllver, 
+      "libpython2.1.so" & dllver, 
+      "libpython2.0.so" & dllver,
+      "libpython1.6.so" & dllver, 
+      "libpython1.5.so" & dllver]
+  
+for libName in items(libNames): 
+  lib = loadLib(libName)
+  if lib != nil: break
+
+if lib == nil: quit("could not load python library")
+init(lib)
+
diff --git a/lib/base/sdl/sdl.nim b/lib/wrappers/sdl/sdl.nim
index 7d2b6ba26..7d2b6ba26 100644
--- a/lib/base/sdl/sdl.nim
+++ b/lib/wrappers/sdl/sdl.nim
diff --git a/lib/base/sdl/sdl_gfx.nim b/lib/wrappers/sdl/sdl_gfx.nim
index 8ae8eca0b..8ae8eca0b 100644
--- a/lib/base/sdl/sdl_gfx.nim
+++ b/lib/wrappers/sdl/sdl_gfx.nim
diff --git a/lib/base/sdl/sdl_image.nim b/lib/wrappers/sdl/sdl_image.nim
index a15afd575..a15afd575 100644
--- a/lib/base/sdl/sdl_image.nim
+++ b/lib/wrappers/sdl/sdl_image.nim
diff --git a/lib/base/sdl/sdl_mixer.nim b/lib/wrappers/sdl/sdl_mixer.nim
index f840dc52a..f840dc52a 100644
--- a/lib/base/sdl/sdl_mixer.nim
+++ b/lib/wrappers/sdl/sdl_mixer.nim
diff --git a/lib/base/sdl/sdl_mixer_nosmpeg.nim b/lib/wrappers/sdl/sdl_mixer_nosmpeg.nim
index 6282b5edc..6282b5edc 100644
--- a/lib/base/sdl/sdl_mixer_nosmpeg.nim
+++ b/lib/wrappers/sdl/sdl_mixer_nosmpeg.nim
diff --git a/lib/base/sdl/sdl_net.nim b/lib/wrappers/sdl/sdl_net.nim
index f27a674ae..f27a674ae 100644
--- a/lib/base/sdl/sdl_net.nim
+++ b/lib/wrappers/sdl/sdl_net.nim
diff --git a/lib/base/sdl/sdl_ttf.nim b/lib/wrappers/sdl/sdl_ttf.nim
index 724c2f634..724c2f634 100644
--- a/lib/base/sdl/sdl_ttf.nim
+++ b/lib/wrappers/sdl/sdl_ttf.nim
diff --git a/lib/base/sdl/sdlutils.pas b/lib/wrappers/sdl/sdlutils.pas
index e4206e935..e4206e935 100644
--- a/lib/base/sdl/sdlutils.pas
+++ b/lib/wrappers/sdl/sdlutils.pas
diff --git a/lib/base/sdl/smpeg.nim b/lib/wrappers/sdl/smpeg.nim
index ada0ed57c..ada0ed57c 100644
--- a/lib/base/sdl/smpeg.nim
+++ b/lib/wrappers/sdl/smpeg.nim
diff --git a/lib/base/sqlite3.nim b/lib/wrappers/sqlite3.nim
index 9a97330ec..9a97330ec 100644
--- a/lib/base/sqlite3.nim
+++ b/lib/wrappers/sqlite3.nim
diff --git a/lib/wrappers/tcl.nim b/lib/wrappers/tcl.nim
new file mode 100644
index 000000000..3539bf92e
--- /dev/null
+++ b/lib/wrappers/tcl.nim
@@ -0,0 +1,855 @@
+#
+#
+#            Nimrod's Runtime Library
+#        (c) Copyright 2009 Andreas Rumpf
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+## This module is a wrapper for the TCL programming language.
+
+#
+#  tcl.h --
+# 
+#  This header file describes the externally-visible facilities of the Tcl
+#  interpreter.
+# 
+#  Translated to Pascal Copyright (c) 2002 by Max Artemev
+#  aka Bert Raccoon (bert@furry.ru, bert_raccoon@freemail.ru)
+# 
+# 
+#  Copyright (c) 1998-2000 by Scriptics Corporation.
+#  Copyright (c) 1994-1998 Sun Microsystems, Inc.
+#  Copyright (c) 1993-1996 Lucent Technologies.
+#  Copyright (c) 1987-1994 John Ousterhout, The Regents of the
+#                          University of California, Berkeley.
+# 
+#  ***********************************************************************
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#  ***********************************************************************
+# 
+
+when defined(WIN32): 
+  const dllName = "tcl(85|84|83|82|81|80).dll"
+elif defined(macosx): 
+  const dllName = "libtcl(8.5|8.4|8.3|8.2|8.1).dynlib"
+else:
+  const dllName = "libtcl(8.5|8.4|8.3|8.2|8.1).so.(1|0)"
+
+const 
+  TCL_DESTROYED* = 0xDEADDEAD
+  TCL_OK* = 0
+  TCL_ERROR* = 1
+  TCL_RETURN* = 2
+  TCL_BREAK* = 3
+  TCL_CONTINUE* = 4
+  TCL_RESULT_SIZE* = 200
+  MAX_ARGV* = 0x00007FFF
+  TCL_VERSION_MAJOR* = 0
+  TCL_VERSION_MINOR* = 0
+  TCL_NO_EVAL* = 0x00010000
+  TCL_EVAL_GLOBAL* = 0x00020000 #* Flag values passed to variable-related procedures. *
+  TCL_GLOBAL_ONLY* = 1
+  TCL_NAMESPACE_ONLY* = 2
+  TCL_APPEND_VALUE* = 4
+  TCL_LIST_ELEMENT* = 8
+  TCL_TRACE_READS* = 0x00000010
+  TCL_TRACE_WRITES* = 0x00000020
+  TCL_TRACE_UNSETS* = 0x00000040
+  TCL_TRACE_DESTROYED* = 0x00000080
+  TCL_INTERP_DESTROYED* = 0x00000100
+  TCL_LEAVE_ERR_MSG* = 0x00000200
+  TCL_PARSE_PART1* = 0x00000400 #* Types for linked variables: *
+  TCL_LINK_INT* = 1
+  TCL_LINK_DOUBLE* = 2
+  TCL_LINK_BOOLEAN* = 3
+  TCL_LINK_STRING* = 4
+  TCL_LINK_READ_ONLY* = 0x00000080
+  TCL_SMALL_HASH_TABLE* = 4   #* Hash Table *
+  TCL_STRING_KEYS* = 0
+  TCL_ONE_WORD_KEYS* = 1      #* Const/enums Tcl_QueuePosition *
+                              # typedef enum {
+  TCL_QUEUE_TAIL* = 0
+  TCL_QUEUE_HEAD* = 1
+  TCL_QUEUE_MARK* = 2         #} Tcl_QueuePosition;
+                              # Event Flags
+  TCL_DONT_WAIT* = 1 shl 1
+  TCL_WINDOW_EVENTS* = 1 shl 2
+  TCL_FILE_EVENTS* = 1 shl 3
+  TCL_TIMER_EVENTS* = 1 shl 4
+  TCL_IDLE_EVENTS* = 1 shl 5  #* WAS 0x10 ???? *
+  TCL_ALL_EVENTS* = not TCL_DONT_WAIT 
+
+  TCL_VOLATILE* = 1
+  TCL_STATIC* = 0
+  TCL_DYNAMIC* = 3            # Channel
+  TCL_STDIN* = 1 shl 1
+  TCL_STDOUT* = 1 shl 2
+  TCL_STDERR* = 1 shl 3
+  TCL_ENFORCE_MODE* = 1 shl 4
+  TCL_READABLE* = 1 shl 1
+  TCL_WRITABLE* = 1 shl 2
+  TCL_EXCEPTION* = 1 shl 3    #* POSIX *
+  EPERM* = 1 # Operation not permitted; only the owner of the file (or other
+             # resource) or processes with special privileges can perform the
+             # operation.
+             #
+  ENOENT* = 2 # No such file or directory.  This is a "file doesn't exist" error
+              # for ordinary files that are referenced in contexts where they are
+              # expected to already exist.
+              #
+  ESRCH* = 3                  #* No process matches the specified process ID. *
+  EINTR* = 4 #* Interrupted function call; an asynchronous signal occurred and
+             # * prevented completion of the call.  When this happens, you should
+             # * try the call again.
+             # *
+  EIO* = 5                    #* Input/output error; usually used for physical read or write errors. *
+  ENXIO* = 6 #* No such device or address.  The system tried to use the device
+             # * represented by a file you specified, and it couldn't find the
+             # * device.  This can mean that the device file was installed
+             # * incorrectly, or that the physical device is missing or not
+             # * correctly attached to the computer.
+             # *
+  E2BIG* = 7 #* Argument list too long; used when the arguments passed to a new
+             # * program being executed with one of the `exec' functions (*note
+             # * Executing a File::.) occupy too much memory space.  This condition
+             # * never arises in the GNU system.
+             # *
+  ENOEXEC* = 8 #* Invalid executable file format.  This condition is detected by the
+               # * `exec' functions; see *Note Executing a File::.
+               # *
+  EBADF* = 9 #* Bad file descriptor; for example, I/O on a descriptor that has been
+             # * closed or reading from a descriptor open only for writing (or vice
+             # * versa).
+             # *
+  ECHILD* = 10 #* There are no child processes.  This error happens on operations
+               # * that are supposed to manipulate child processes, when there aren't
+               # * any processes to manipulate.
+               # *
+  EDEADLK* = 11 #* Deadlock avoided; allocating a system resource would have resulted
+                # * in a deadlock situation.  The system does not guarantee that it
+                # * will notice all such situations.  This error means you got lucky
+                # * and the system noticed; it might just hang.  *Note File Locks::,
+                # * for an example.
+                # *
+  ENOMEM* = 12 #* No memory available.  The system cannot allocate more virtual
+               # * memory because its capacity is full.
+               # *
+  EACCES* = 13 #* Permission denied; the file permissions do not allow the attempted
+               # * operation.
+               # *
+  EFAULT* = 14 #* Bad address; an invalid pointer was detected.  In the GNU system,
+               # * this error never happens; you get a signal instead.
+               # *
+  ENOTBLK* = 15 #* A file that isn't a block special file was given in a situation
+                # * that requires one.  For example, trying to mount an ordinary file
+                # * as a file system in Unix gives this error.
+                # *
+  EBUSY* = 16 #* Resource busy; a system resource that can't be shared is already
+              # * in use.  For example, if you try to delete a file that is the root
+              # * of a currently mounted filesystem, you get this error.
+              # *
+  EEXIST* = 17 #* File exists; an existing file was specified in a context where it
+               # * only makes sense to specify a new file.
+               # *
+  EXDEV* = 18 #* An attempt to make an improper link across file systems was
+              # * detected.  This happens not only when you use `link' (*note Hard
+              # * Links::.) but also when you rename a file with `rename' (*note
+              # * Renaming Files::.).
+              # *
+  ENODEV* = 19 #* The wrong type of device was given to a function that expects a
+               # * particular sort of device.
+               # *
+  ENOTDIR* = 20 #* A file that isn't a directory was specified when a directory is
+                # * required.
+                # *
+  EISDIR* = 21 #* File is a directory; you cannot open a directory for writing, or
+               # * create or remove hard links to it.
+               # *
+  EINVAL* = 22 #* Invalid argument.  This is used to indicate various kinds of
+               # * problems with passing the wrong argument to a library function.
+               # *
+  EMFILE* = 24 #* The current process has too many files open and can't open any
+               # * more.  Duplicate descriptors do count toward this limit.
+               # *
+               # * In BSD and GNU, the number of open files is controlled by a
+               # * resource limit that can usually be increased.  If you get this
+               # * error, you might want to increase the `RLIMIT_NOFILE' limit or
+               # * make it unlimited; *note Limits on Resources::..
+               # *
+  ENFILE* = 23 #* There are too many distinct file openings in the entire system.
+               # * Note that any number of linked channels count as just one file
+               # * opening; see *Note Linked Channels::.  This error never occurs in
+               # * the GNU system.
+               # *
+  ENOTTY* = 25 #* Inappropriate I/O control operation, such as trying to set terminal
+               # * modes on an ordinary file.
+               # *
+  ETXTBSY* = 26 #* An attempt to execute a file that is currently open for writing, or
+                # * write to a file that is currently being executed.  Often using a
+                # * debugger to run a program is considered having it open for writing
+                # * and will cause this error.  (The name stands for "text file
+                # * busy".)  This is not an error in the GNU system; the text is
+                # * copied as necessary.
+                # *
+  EFBIG* = 27 #* File too big; the size of a file would be larger than allowed by
+              # * the system.
+              # *
+  ENOSPC* = 28 #* No space left on device; write operation on a file failed because
+               # * the disk is full.
+               # *
+  ESPIPE* = 29                #* Invalid seek operation (such as on a pipe).  *
+  EROFS* = 30                 #* An attempt was made to modify something on a read-only file system.  *
+  EMLINK* = 31 #* Too many links; the link count of a single file would become too
+               # * large.  `rename' can cause this error if the file being renamed
+               # * already has as many links as it can take (*note Renaming Files::.).
+               # *
+  EPIPE* = 32 #* Broken pipe; there is no process reading from the other end of a
+              # * pipe.  Every library function that returns this error code also
+              # * generates a `SIGPIPE' signal; this signal terminates the program
+              # * if not handled or blocked.  Thus, your program will never actually
+              # * see `EPIPE' unless it has handled or blocked `SIGPIPE'.
+              # *
+  EDOM* = 33 #* Domain error; used by mathematical functions when an argument
+             # * value does not fall into the domain over which the function is
+             # * defined.
+             # *
+  ERANGE* = 34 #* Range error; used by mathematical functions when the result value
+               # * is not representable because of overflow or underflow.
+               # *
+  EAGAIN* = 35 #* Resource temporarily unavailable; the call might work if you try
+               # * again later.  The macro `EWOULDBLOCK' is another name for `EAGAIN';
+               # * they are always the same in the GNU C library.
+               # *
+  EWOULDBLOCK* = EAGAIN #* In the GNU C library, this is another name for `EAGAIN' (above).
+                        # * The values are always the same, on every operating system.
+                        # * C libraries in many older Unix systems have `EWOULDBLOCK' as a
+                        # * separate error code.
+                        # *
+  EINPROGRESS* = 36 #* An operation that cannot complete immediately was initiated on an
+                    # * object that has non-blocking mode selected.  Some functions that
+                    # * must always block (such as `connect'; *note Connecting::.) never
+                    # * return `EAGAIN'.  Instead, they return `EINPROGRESS' to indicate
+                    # * that the operation has begun and will take some time.  Attempts to
+                    # * manipulate the object before the call completes return `EALREADY'.
+                    # * You can use the `select' function to find out when the pending
+                    # * operation has completed; *note Waiting for I/O::..
+                    # *
+  EALREADY* = 37 #* An operation is already in progress on an object that has
+                 # * non-blocking mode selected.
+                 # *
+  ENOTSOCK* = 38              #* A file that isn't a socket was specified when a socket is required.  *
+  EDESTADDRREQ* = 39 #* No default destination address was set for the socket.  You get
+                     # * this error when you try to transmit data over a connectionless
+                     # * socket, without first specifying a destination for the data with
+                     # * `connect'.
+                     # *
+  EMSGSIZE* = 40 #* The size of a message sent on a socket was larger than the
+                 # * supported maximum size.
+                 # *
+  EPROTOTYPE* = 41 #* The socket type does not support the requested communications
+                   # * protocol.
+                   # *
+  ENOPROTOOPT* = 42 #* You specified a socket option that doesn't make sense for the
+                    # * particular protocol being used by the socket.  *Note Socket
+                    # * Options::.
+                    # *
+  EPROTONOSUPPORT* = 43 #* The socket domain does not support the requested communications
+                        # * protocol (perhaps because the requested protocol is completely
+                        # * invalid.) *Note Creating a Socket::.
+                        # *
+  ESOCKTNOSUPPORT* = 44       #* The socket type is not supported.  *
+  EOPNOTSUPP* = 45 #* The operation you requested is not supported.  Some socket
+                   # * functions don't make sense for all types of sockets, and others
+                   # * may not be implemented for all communications protocols.  In the
+                   # * GNU system, this error can happen for many calls when the object
+                   # * does not support the particular operation; it is a generic
+                   # * indication that the server knows nothing to do for that call.
+                   # *
+  EPFNOSUPPORT* = 46 #* The socket communications protocol family you requested is not
+                     # * supported.
+                     # *
+  EAFNOSUPPORT* = 47 #* The address family specified for a socket is not supported; it is
+                     # * inconsistent with the protocol being used on the socket.  *Note
+                     # * Sockets::.
+                     # *
+  EADDRINUSE* = 48 #* The requested socket address is already in use.  *Note Socket
+                   # * Addresses::.
+                   # *
+  EADDRNOTAVAIL* = 49 #* The requested socket address is not available; for example, you
+                      # * tried to give a socket a name that doesn't match the local host
+                      # * name.  *Note Socket Addresses::.
+                      # *
+  ENETDOWN* = 50              #* A socket operation failed because the network was down.  *
+  ENETUNREACH* = 51 #* A socket operation failed because the subnet containing the remote
+                    # * host was unreachable.
+                    # *
+  ENETRESET* = 52             #* A network connection was reset because the remote host crashed.  *
+  ECONNABORTED* = 53          #* A network connection was aborted locally. *
+  ECONNRESET* = 54 #* A network connection was closed for reasons outside the control of
+                   # * the local host, such as by the remote machine rebooting or an
+                   # * unrecoverable protocol violation.
+                   # *
+  ENOBUFS* = 55 #* The kernel's buffers for I/O operations are all in use.  In GNU,
+                # * this error is always synonymous with `ENOMEM'; you may get one or
+                # * the other from network operations.
+                # *
+  EISCONN* = 56 #* You tried to connect a socket that is already connected.  *Note
+                # * Connecting::.
+                # *
+  ENOTCONN* = 57 #* The socket is not connected to anything.  You get this error when
+                 # * you try to transmit data over a socket, without first specifying a
+                 # * destination for the data.  For a connectionless socket (for
+                 # * datagram protocols, such as UDP), you get `EDESTADDRREQ' instead.
+                 # *
+  ESHUTDOWN* = 58             #* The socket has already been shut down.  *
+  ETOOMANYREFS* = 59          #* ???  *
+  ETIMEDOUT* = 60 #* A socket operation with a specified timeout received no response
+                  # * during the timeout period.
+                  # *
+  ECONNREFUSED* = 61 #* A remote host refused to allow the network connection (typically
+                     # * because it is not running the requested service).
+                     # *
+  ELOOP* = 62 #* Too many levels of symbolic links were encountered in looking up a
+              # * file name.  This often indicates a cycle of symbolic links.
+              # *
+  ENAMETOOLONG* = 63 #* Filename too long (longer than `PATH_MAX'; *note Limits for
+                     # * Files::.) or host name too long (in `gethostname' or
+                     # * `sethostname'; *note Host Identification::.).
+                     # *
+  EHOSTDOWN* = 64             #* The remote host for a requested network connection is down.  *
+  EHOSTUNREACH* = 65 #* The remote host for a requested network connection is not
+                     # * reachable.
+                     # *
+  ENOTEMPTY* = 66 #* Directory not empty, where an empty directory was expected.
+                  # * Typically, this error occurs when you are trying to delete a
+                  # * directory.
+                  # *
+  EPROCLIM* = 67 #* This means that the per-user limit on new process would be
+                 # * exceeded by an attempted `fork'.  *Note Limits on Resources::, for
+                 # * details on the `RLIMIT_NPROC' limit.
+                 # *
+  EUSERS* = 68                #* The file quota system is confused because there are too many users.  *
+  EDQUOT* = 69                #* The user's disk quota was exceeded.  *
+  ESTALE* = 70 #* Stale NFS file handle.  This indicates an internal confusion in
+               # * the NFS system which is due to file system rearrangements on the
+               # * server host.  Repairing this condition usually requires unmounting
+               # * and remounting the NFS file system on the local host.
+               # *
+  EREMOTE* = 71 #* An attempt was made to NFS-mount a remote file system with a file
+                # * name that already specifies an NFS-mounted file.  (This is an
+                # * error on some operating systems, but we expect it to work properly
+                # * on the GNU system, making this error code impossible.)
+                # *
+  EBADRPC* = 72               #* ???  *
+  ERPCMISMATCH* = 73          #* ???  *
+  EPROGUNAVAIL* = 74          #* ???  *
+  EPROGMISMATCH* = 75         #* ???  *
+  EPROCUNAVAIL* = 76          #* ???  *
+  ENOLCK* = 77 #* No locks available.  This is used by the file locking facilities;
+               # * see *Note File Locks::.  This error is never generated by the GNU
+               # * system, but it can result from an operation to an NFS server
+               # * running another operating system.
+               # *
+  ENOSYS* = 78 #* Function not implemented.  Some functions have commands or options
+               # * defined that might not be supported in all implementations, and
+               # * this is the kind of error you get if you request them and they are
+               # * not supported.
+               # *
+  EFTYPE* = 79 #* Inappropriate file type or format.  The file was the wrong type
+               # * for the operation, or a data file had the wrong format.
+               # * On some systems `chmod' returns this error if you try to set the
+               # * sticky bit on a non-directory file; *note Setting Permissions::..
+               # *
+
+type 
+  Tcl_Argv* = cstringArray
+  Tcl_ClientData* = pointer
+  Tcl_FreeProc* = proc (theBlock: pointer){.cdecl.}
+  PTcl_Interp* = ptr Tcl_Interp
+  Tcl_Interp*{.final.} = object  #*  Event Definitions  *
+    result*: cstring #* Do not access this directly. Use
+                     #                          * Tcl_GetStringResult since result
+                     #                          * may be pointing to an object
+                     #                          *
+    freeProc*: Tcl_FreeProc
+    errorLine*: int
+
+  TTcl_EventSetupProc* = proc (clientData: Tcl_ClientData, flags: int){.cdecl.}
+  TTcl_EventCheckProc* = TTcl_EventSetupProc
+  PTcl_Event* = ptr Tcl_Event
+  TTcl_EventProc* = proc (evPtr: PTcl_Event, flags: int): int{.cdecl.}
+  Tcl_Event*{.final.} = object 
+    prc*: TTcl_EventProc
+    nextPtr*: PTcl_Event
+    ClientData*: TObject      #* ClientData is just pointer.*
+  
+  PTcl_Time* = ptr Tcl_Time
+  Tcl_Time*{.final.} = object 
+    sec*: int32               # * Seconds. * 
+    usec*: int32              # * Microseconds. * 
+  
+  Tcl_TimerToken* = pointer
+  PInteger* = ptr int
+  PTcl_HashTable* = pointer
+  PTcl_HashEntry* = ptr Tcl_HashEntry
+  PPTcl_HashEntry* = ptr PTcl_HashEntry
+  Tcl_HashEntry*{.final.} = object  
+    nextPtr*: PTcl_HashEntry
+    tablePtr*: PTcl_HashTable
+    bucketPtr*: PPTcl_HashEntry
+    clientData*: Tcl_ClientData
+    key*: cstring
+
+  Tcl_HashFindProc* = proc (tablePtr: PTcl_HashTable, key: cstring): PTcl_HashEntry{.
+      cdecl.}
+  Tcl_HashCreateProc* = proc (tablePtr: PTcl_HashTable, key: cstring, 
+                              newPtr: PInteger): PTcl_HashEntry{.cdecl.}
+  PHashTable* = ptr Tcl_HashTable
+  Tcl_HashTable*{.final.} = object 
+    buckets*: ppTcl_HashEntry
+    staticBuckets*: array[0..TCL_SMALL_HASH_TABLE - 1, PTcl_HashEntry]
+    numBuckets*: int
+    numEntries*: int
+    rebuildSize*: int
+    downShift*: int
+    mask*: int
+    keyType*: int
+    findProc*: Tcl_HashFindProc
+    createProc*: Tcl_HashCreateProc
+
+  PTcl_HashSearch* = ptr Tcl_HashSearch
+  Tcl_HashSearch*{.final.} = object 
+    tablePtr*: PTcl_HashTable
+    nextIndex*: int
+    nextEntryPtr*: PTcl_HashEntry
+
+  TTclAppInitProc* = proc (interp: pTcl_Interp): int{.cdecl.}
+  TTclPackageInitProc* = proc (interp: pTcl_Interp): int{.cdecl.}
+  TTclCmdProc* = proc (clientData: Tcl_ClientData, interp: pTcl_Interp, 
+                       argc: int, argv: Tcl_Argv): int{.cdecl.}
+  TTclVarTraceProc* = proc (clientData: Tcl_ClientData, interp: pTcl_Interp, 
+                            varName: cstring, elemName: cstring, flags: int): cstring{.
+      cdecl.}
+  TTclFreeProc* = proc (theBlock: pointer){.cdecl.}
+  TTclInterpDeleteProc* = proc (clientData: Tcl_ClientData, interp: pTcl_Interp){.
+      cdecl.}
+  TTclCmdDeleteProc* = proc (clientData: Tcl_ClientData){.cdecl.}
+  TTclNamespaceDeleteProc* = proc (clientData: Tcl_ClientData){.cdecl.}
+
+const 
+  TCL_DSTRING_STATIC_SIZE* = 200
+
+type 
+  PTcl_DString* = ptr Tcl_DString
+  Tcl_DString*{.final.} = object 
+    str*: cstring
+    len*: int
+    spaceAvl*: int
+    staticSpace*: array[0..TCL_DSTRING_STATIC_SIZE - 1, char]
+
+  PTcl_Channel* = ptr Tcl_Channel
+  Tcl_Channel*{.final.} = object 
+  TTclDriverBlockModeProc* = proc (instanceData: Tcl_ClientData, mode: int): int{.
+      cdecl.}
+  TTclDriverCloseProc* = proc (instanceData: Tcl_ClientData, interp: PTcl_Interp): int{.
+      cdecl.}
+  TTclDriverInputProc* = proc (instanceData: Tcl_ClientData, buf: cstring, 
+                               toRead: int, errorCodePtr: PInteger): int{.cdecl.}
+  TTclDriverOutputProc* = proc (instanceData: Tcl_ClientData, buf: cstring, 
+                                toWrite: int, errorCodePtr: PInteger): int{.
+      cdecl.}
+  TTclDriverSeekProc* = proc (instanceData: Tcl_ClientData, offset: int32, 
+                              mode: int, errorCodePtr: PInteger): int{.cdecl.}
+  TTclDriverSetOptionProc* = proc (instanceData: Tcl_ClientData, 
+                                   interp: PTcl_Interp, optionName: cstring, 
+                                   value: cstring): int{.cdecl.}
+  TTclDriverGetOptionProc* = proc (instanceData: Tcl_ClientData, 
+                                   interp: pTcl_Interp, optionName: cstring, 
+                                   dsPtr: PTcl_DString): int{.cdecl.}
+  TTclDriverWatchProc* = proc (instanceData: Tcl_ClientData, mask: int){.cdecl.}
+  TTclDriverGetHandleProc* = proc (instanceData: Tcl_ClientData, direction: int, 
+                                   handlePtr: var Tcl_ClientData): int{.cdecl.}
+  PTcl_ChannelType* = ptr Tcl_ChannelType
+  Tcl_ChannelType*{.final.} = object 
+    typeName*: cstring
+    blockModeProc*: TTclDriverBlockModeProc
+    closeProc*: TTclDriverCloseProc
+    inputProc*: TTclDriverInputProc
+    ouputProc*: TTclDriverOutputProc
+    seekProc*: TTclDriverSeekProc
+    setOptionProc*: TTclDriverSetOptionProc
+    getOptionProc*: TTclDriverGetOptionProc
+    watchProc*: TTclDriverWatchProc
+    getHandleProc*: TTclDriverGetHandleProc
+
+  TTclChannelProc* = proc (clientData: Tcl_ClientData, mask: int){.cdecl.}
+  PTcl_Obj* = ptr Tcl_Obj
+  PPTcl_Obj* = ptr PTcl_Obj
+  Tcl_Obj*{.final.} = object 
+    refCount*: int            # ...
+  
+  TTclObjCmdProc* = proc (clientData: Tcl_ClientData, interp: PTcl_Interp, 
+                          objc: int, PPObj: PPTcl_Obj): int{.cdecl.}
+  PTcl_Namespace* = ptr Tcl_Namespace
+  Tcl_Namespace*{.final.} = object 
+    name*: cstring
+    fullName*: cstring
+    clientData*: Tcl_ClientData
+    deleteProc*: TTclNamespaceDeleteProc
+    parentPtr*: PTcl_Namespace
+
+  PTcl_CallFrame* = ptr Tcl_CallFrame
+  Tcl_CallFrame*{.final.} = object 
+    nsPtr*: PTcl_Namespace
+    dummy1*: int
+    dummy2*: int
+    dummy3*: cstring
+    dummy4*: cstring
+    dummy5*: cstring
+    dummy6*: int
+    dummy7*: cstring
+    dummy8*: cstring
+    dummy9*: int
+    dummy10*: cstring
+
+  PTcl_CmdInfo* = ptr Tcl_CmdInfo
+  Tcl_CmdInfo*{.final.} = object 
+    isNativeObjectProc*: int
+    objProc*: TTclObjCmdProc
+    objClientData*: Tcl_ClientData
+    prc*: TTclCmdProc
+    clientData*: Tcl_ClientData
+    deleteProc*: TTclCmdDeleteProc
+    deleteData*: Tcl_ClientData
+    namespacePtr*: pTcl_Namespace
+
+  pTcl_Command* = ptr Tcl_Command
+  Tcl_Command*{.final.} = object  #       hPtr            : pTcl_HashEntry;
+                                  #        nsPtr           : pTcl_Namespace;
+                                  #        refCount        : integer;
+                                  #        isCmdEpoch      : integer;
+                                  #        compileProc     : pointer;
+                                  #        objProc         : pointer;
+                                  #        objClientData   : Tcl_ClientData;
+                                  #        proc            : pointer;
+                                  #        clientData      : Tcl_ClientData;
+                                  #        deleteProc      : TTclCmdDeleteProc;
+                                  #        deleteData      : Tcl_ClientData;
+                                  #        deleted         : integer;
+                                  #        importRefPtr    : pointer;
+                                  #
+
+type 
+  TTclPanicProc* = proc (fmt, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8: cstring){.
+      cdecl.}                 # 1/15/97 orig. Tcl style
+  TTclClientDataProc* = proc (clientData: Tcl_ClientData){.cdecl.}
+  TTclIdleProc* = proc (clientData: Tcl_ClientData){.cdecl.}
+  TTclTimerProc* = TTclIdleProc
+  TTclCreateCloseHandler* = proc (channel: pTcl_Channel, 
+                                  prc: TTclClientDataProc, 
+                                  clientData: Tcl_ClientData){.cdecl.}
+  TTclDeleteCloseHandler* = TTclCreateCloseHandler
+  TTclEventDeleteProc* = proc (evPtr: pTcl_Event, clientData: Tcl_ClientData): int{.
+      cdecl.}
+
+proc Tcl_Alloc*(size: int): cstring{.cdecl, dynlib: dllName, importc.}
+proc Tcl_CreateInterp*(): pTcl_Interp{.cdecl, dynlib: dllName, importc.}
+proc Tcl_DeleteInterp*(interp: pTcl_Interp){.cdecl, dynlib: dllName, importc.}
+proc Tcl_ResetResult*(interp: pTcl_Interp){.cdecl, dynlib: dllName, importc.}
+proc Tcl_Eval*(interp: pTcl_Interp, script: cstring): int{.cdecl, 
+    dynlib: dllName, importc.}
+proc Tcl_EvalFile*(interp: pTcl_Interp, filename: cstring): int{.cdecl, 
+    dynlib: dllName, importc.}
+proc Tcl_AddErrorInfo*(interp: pTcl_Interp, message: cstring){.cdecl, 
+    dynlib: dllName, importc.}
+proc Tcl_BackgroundError*(interp: pTcl_Interp){.cdecl, dynlib: dllName, 
+    importc.}
+proc Tcl_CreateCommand*(interp: pTcl_Interp, name: cstring, 
+                        cmdProc: TTclCmdProc, clientData: Tcl_ClientData, 
+                        deleteProc: TTclCmdDeleteProc): pTcl_Command{.cdecl, 
+    dynlib: dllName, importc.}
+proc Tcl_DeleteCommand*(interp: pTcl_Interp, name: cstring): int{.cdecl, 
+    dynlib: dllName, importc.}
+proc Tcl_CallWhenDeleted*(interp: pTcl_Interp, prc: TTclInterpDeleteProc, 
+                          clientData: Tcl_ClientData){.cdecl, 
+    dynlib: dllName, importc.}
+proc Tcl_DontCallWhenDeleted*(interp: pTcl_Interp, prc: TTclInterpDeleteProc, 
+                              clientData: Tcl_ClientData){.cdecl, 
+    dynlib: dllName, importc.}
+proc Tcl_CommandComplete*(cmd: cstring): int{.cdecl, dynlib: dllName, 
+    importc.}
+proc Tcl_LinkVar*(interp: pTcl_Interp, varName: cstring, varAddr: pointer, 
+                  typ: int): int{.cdecl, dynlib: dllName, importc.}
+proc Tcl_UnlinkVar*(interp: pTcl_Interp, varName: cstring){.cdecl, 
+    dynlib: dllName, importc.}
+proc Tcl_TraceVar*(interp: pTcl_Interp, varName: cstring, flags: int, 
+                   prc: TTclVarTraceProc, clientData: Tcl_ClientData): int{.
+    cdecl, dynlib: dllName, importc.}
+proc Tcl_TraceVar2*(interp: pTcl_Interp, varName: cstring, elemName: cstring, 
+                    flags: int, prc: TTclVarTraceProc, 
+                    clientData: Tcl_ClientData): int{.cdecl, 
+    dynlib: dllName, importc.}
+proc Tcl_UntraceVar*(interp: pTcl_Interp, varName: cstring, flags: int, 
+                     prc: TTclVarTraceProc, clientData: Tcl_ClientData){.cdecl, 
+    dynlib: dllName, importc.}
+proc Tcl_UntraceVar2*(interp: pTcl_Interp, varName: cstring, elemName: cstring, 
+                      flags: int, prc: TTclVarTraceProc, 
+                      clientData: Tcl_ClientData){.cdecl, dynlib: dllName, 
+    importc.}
+proc Tcl_GetVar*(interp: pTcl_Interp, varName: cstring, flags: int): cstring{.
+    cdecl, dynlib: dllName, importc.}
+proc Tcl_GetVar2*(interp: pTcl_Interp, varName: cstring, elemName: cstring, 
+                  flags: int): cstring{.cdecl, dynlib: dllName, importc.}
+proc Tcl_SetVar*(interp: pTcl_Interp, varName: cstring, newValue: cstring, 
+                 flags: int): cstring{.cdecl, dynlib: dllName, importc.}
+proc Tcl_SetVar2*(interp: pTcl_Interp, varName: cstring, elemName: cstring, 
+                  newValue: cstring, flags: int): cstring{.cdecl, 
+    dynlib: dllName, importc.}
+proc Tcl_UnsetVar*(interp: pTcl_Interp, varName: cstring, flags: int): int{.
+    cdecl, dynlib: dllName, importc.}
+proc Tcl_UnsetVar2*(interp: pTcl_Interp, varName: cstring, elemName: cstring, 
+                    flags: int): int{.cdecl, dynlib: dllName, importc.}
+proc Tcl_SetResult*(interp: pTcl_Interp, newValue: cstring, 
+                    freeProc: TTclFreeProc){.cdecl, dynlib: dllName, importc.}
+proc Tcl_FirstHashEntry*(hashTbl: pTcl_HashTable, searchInfo: var Tcl_HashSearch): pTcl_HashEntry{.
+    cdecl, dynlib: dllName, importc.}
+proc Tcl_NextHashEntry*(searchInfo: var Tcl_HashSearch): pTcl_HashEntry{.cdecl, 
+    dynlib: dllName, importc.}
+proc Tcl_InitHashTable*(hashTbl: pTcl_HashTable, keyType: int){.cdecl, 
+    dynlib: dllName, importc.}
+proc Tcl_StringMatch*(str: cstring, pattern: cstring): int{.cdecl, 
+    dynlib: dllName, importc.}
+
+proc Tcl_GetErrno*(): int{.cdecl, dynlib: dllName, importc.}
+proc Tcl_SetErrno*(val: int){.cdecl, dynlib: dllName, importc.}
+proc Tcl_SetPanicProc*(prc: TTclPanicProc){.cdecl, dynlib: dllName, importc.}
+proc Tcl_PkgProvide*(interp: pTcl_Interp, name: cstring, version: cstring): int{.
+    cdecl, dynlib: dllName, importc.}
+proc Tcl_StaticPackage*(interp: pTcl_Interp, pkgName: cstring, 
+                        initProc: TTclPackageInitProc, 
+                        safeInitProc: TTclPackageInitProc){.cdecl, 
+    dynlib: dllName, importc.}
+proc Tcl_CreateEventSource*(setupProc: TTcl_EventSetupProc, 
+                            checkProc: TTcl_EventCheckProc, 
+                            clientData: Tcl_ClientData){.cdecl, 
+    dynlib: dllName, importc.}
+proc Tcl_DeleteEventSource*(setupProc: TTcl_EventSetupProc, 
+                            checkProc: TTcl_EventCheckProc, 
+                            clientData: Tcl_ClientData){.cdecl, 
+    dynlib: dllName, importc.}
+proc Tcl_QueueEvent*(evPtr: pTcl_Event, pos: int){.cdecl, dynlib: dllName, 
+    importc.}
+proc Tcl_SetMaxBlockTime*(timePtr: pTcl_Time){.cdecl, dynlib: dllName, 
+    importc.}
+proc Tcl_DeleteEvents*(prc: TTclEventDeleteProc, clientData: Tcl_ClientData){.
+    cdecl, dynlib: dllName, importc.}
+proc Tcl_DoOneEvent*(flags: int): int{.cdecl, dynlib: dllName, importc.}
+proc Tcl_DoWhenIdle*(prc: TTclIdleProc, clientData: Tcl_ClientData){.cdecl, 
+    dynlib: dllName, importc.}
+proc Tcl_CancelIdleCall*(prc: TTclIdleProc, clientData: Tcl_ClientData){.cdecl, 
+    dynlib: dllName, importc.}
+proc Tcl_CreateTimerHandler*(milliseconds: int, prc: TTclTimerProc, 
+                             clientData: Tcl_ClientData): Tcl_TimerToken{.cdecl, 
+    dynlib: dllName, importc.}
+proc Tcl_DeleteTimerHandler*(token: Tcl_TimerToken){.cdecl, dynlib: dllName, 
+    importc.}
+  #    procedure Tcl_CreateModalTimeout(milliseconds: integer; prc: TTclTimerProc; clientData: Tcl_ClientData); cdecl; external dllName;
+  #    procedure Tcl_DeleteModalTimeout(prc: TTclTimerProc; clientData: Tcl_ClientData); cdecl; external dllName;
+proc Tcl_SplitList*(interp: pTcl_Interp, list: cstring, argcPtr: var int, 
+                    argvPtr: var Tcl_Argv): int{.cdecl, dynlib: dllName, 
+    importc.}
+proc Tcl_Merge*(argc: int, argv: Tcl_Argv): cstring{.cdecl, dynlib: dllName, 
+    importc.}
+proc Tcl_Free*(p: cstring){.cdecl, dynlib: dllName, importc.}
+proc Tcl_Init*(interp: pTcl_Interp): int{.cdecl, dynlib: dllName, importc.}
+  #    procedure Tcl_InterpDeleteProc(clientData: Tcl_ClientData; interp: pTcl_Interp); cdecl; external dllName;
+proc Tcl_GetAssocData*(interp: pTcl_Interp, key: cstring, 
+                       prc: var TTclInterpDeleteProc): Tcl_ClientData{.cdecl, 
+    dynlib: dllName, importc.}
+proc Tcl_DeleteAssocData*(interp: pTcl_Interp, key: cstring){.cdecl, 
+    dynlib: dllName, importc.}
+proc Tcl_SetAssocData*(interp: pTcl_Interp, key: cstring, 
+                       prc: TTclInterpDeleteProc, clientData: Tcl_ClientData){.
+    cdecl, dynlib: dllName, importc.}
+proc Tcl_IsSafe*(interp: pTcl_Interp): int{.cdecl, dynlib: dllName, importc.}
+proc Tcl_MakeSafe*(interp: pTcl_Interp): int{.cdecl, dynlib: dllName, 
+    importc.}
+proc Tcl_CreateSlave*(interp: pTcl_Interp, slaveName: cstring, isSafe: int): pTcl_Interp{.
+    cdecl, dynlib: dllName, importc.}
+proc Tcl_GetSlave*(interp: pTcl_Interp, slaveName: cstring): pTcl_Interp{.cdecl, 
+    dynlib: dllName, importc.}
+proc Tcl_GetMaster*(interp: pTcl_Interp): pTcl_Interp{.cdecl, 
+    dynlib: dllName, importc.}
+proc Tcl_GetInterpPath*(askingInterp: pTcl_Interp, slaveInterp: pTcl_Interp): int{.
+    cdecl, dynlib: dllName, importc.}
+proc Tcl_CreateAlias*(slaveInterp: pTcl_Interp, srcCmd: cstring, 
+                      targetInterp: pTcl_Interp, targetCmd: cstring, argc: int, 
+                      argv: Tcl_Argv): int{.cdecl, dynlib: dllName, importc.}
+proc Tcl_GetAlias*(interp: pTcl_Interp, srcCmd: cstring, 
+                   targetInterp: var pTcl_Interp, targetCmd: var cstring, 
+                   argc: var int, argv: var Tcl_Argv): int{.cdecl, 
+    dynlib: dllName, importc.}
+proc Tcl_ExposeCommand*(interp: pTcl_Interp, hiddenCmdName: cstring, 
+                        cmdName: cstring): int{.cdecl, dynlib: dllName, 
+    importc.}
+proc Tcl_HideCommand*(interp: pTcl_Interp, cmdName: cstring, 
+                      hiddenCmdName: cstring): int{.cdecl, dynlib: dllName, 
+    importc.}
+proc Tcl_EventuallyFree*(clientData: Tcl_ClientData, freeProc: TTclFreeProc){.
+    cdecl, dynlib: dllName, importc.}
+proc Tcl_Preserve*(clientData: Tcl_ClientData){.cdecl, dynlib: dllName, 
+    importc.}
+proc Tcl_Release*(clientData: Tcl_ClientData){.cdecl, dynlib: dllName, 
+    importc.}
+proc Tcl_InterpDeleted*(interp: pTcl_Interp): int{.cdecl, dynlib: dllName, 
+    importc.}
+proc Tcl_GetCommandInfo*(interp: pTcl_Interp, cmdName: cstring, 
+                         info: var Tcl_CmdInfo): int{.cdecl, 
+    dynlib: dllName, importc.}
+proc Tcl_SetCommandInfo*(interp: pTcl_Interp, cmdName: cstring, 
+                         info: var Tcl_CmdInfo): int{.cdecl, 
+    dynlib: dllName, importc.}
+proc Tcl_FindExecutable*(path: cstring){.cdecl, dynlib: dllName, importc.}
+proc Tcl_GetStringResult*(interp: pTcl_Interp): cstring{.cdecl, 
+    dynlib: dllName, importc.}
+  #v1.0
+proc Tcl_FindCommand*(interp: pTcl_Interp, cmdName: cstring, 
+                      contextNsPtr: pTcl_Namespace, flags: int): Tcl_Command{.
+    cdecl, dynlib: dllName, importc.}
+  #v1.0
+proc Tcl_DeleteCommandFromToken*(interp: pTcl_Interp, cmd: pTcl_Command): int{.
+    cdecl, dynlib: dllName, importc.}
+proc Tcl_CreateNamespace*(interp: pTcl_Interp, name: cstring, 
+                          clientData: Tcl_ClientData, 
+                          deleteProc: TTclNamespaceDeleteProc): pTcl_Namespace{.
+    cdecl, dynlib: dllName, importc.}
+  #v1.0
+proc Tcl_DeleteNamespace*(namespacePtr: pTcl_Namespace){.cdecl, 
+    dynlib: dllName, importc.}
+proc Tcl_FindNamespace*(interp: pTcl_Interp, name: cstring, 
+                        contextNsPtr: pTcl_Namespace, flags: int): pTcl_Namespace{.
+    cdecl, dynlib: dllName, importc.}
+proc Tcl_Export*(interp: pTcl_Interp, namespacePtr: pTcl_Namespace, 
+                 pattern: cstring, resetListFirst: int): int{.cdecl, 
+    dynlib: dllName, importc.}
+proc Tcl_Import*(interp: pTcl_Interp, namespacePtr: pTcl_Namespace, 
+                 pattern: cstring, allowOverwrite: int): int{.cdecl, 
+    dynlib: dllName, importc.}
+proc Tcl_GetCurrentNamespace*(interp: pTcl_Interp): pTcl_Namespace{.cdecl, 
+    dynlib: dllName, importc.}
+proc Tcl_GetGlobalNamespace*(interp: pTcl_Interp): pTcl_Namespace{.cdecl, 
+    dynlib: dllName, importc.}
+proc Tcl_PushCallFrame*(interp: pTcl_Interp, callFramePtr: var Tcl_CallFrame, 
+                        namespacePtr: pTcl_Namespace, isProcCallFrame: int): int{.
+    cdecl, dynlib: dllName, importc.}
+proc Tcl_PopCallFrame*(interp: pTcl_Interp){.cdecl, dynlib: dllName, importc.}
+proc Tcl_VarEval*(interp: pTcl_Interp): int{.cdecl, varargs, 
+    dynlib: dllName, importc.}
+  #* For TkConsole.c *
+proc Tcl_RecordAndEval*(interp: pTcl_Interp, cmd: cstring, flags: int): int{.
+    cdecl, dynlib: dllName, importc.}
+proc Tcl_GlobalEval*(interp: pTcl_Interp, command: cstring): int{.cdecl, 
+    dynlib: dllName, importc.}
+proc Tcl_DStringFree*(dsPtr: pTcl_DString){.cdecl, dynlib: dllName, importc.}
+proc Tcl_DStringAppend*(dsPtr: pTcl_DString, str: cstring, length: int): cstring{.
+    cdecl, dynlib: dllName, importc.}
+proc Tcl_DStringAppendElement*(dsPtr: pTcl_DString, str: cstring): cstring{.
+    cdecl, dynlib: dllName, importc.}
+proc Tcl_DStringInit*(dsPtr: pTcl_DString){.cdecl, dynlib: dllName, importc.}
+proc Tcl_AppendResult*(interp: pTcl_Interp){.cdecl, varargs, 
+    dynlib: dllName, importc.}
+  # actually a "C" var array
+proc Tcl_SetStdChannel*(channel: pTcl_Channel, typ: int){.cdecl, 
+    dynlib: dllName, importc.}
+proc Tcl_SetChannelOption*(interp: pTcl_Interp, chan: pTcl_Channel, 
+                           optionName: cstring, newValue: cstring): int{.cdecl, 
+    dynlib: dllName, importc.}
+proc Tcl_GetChannelOption*(interp: pTcl_Interp, chan: pTcl_Channel, 
+                           optionName: cstring, dsPtr: pTcl_DString): int{.
+    cdecl, dynlib: dllName, importc.}
+proc Tcl_CreateChannel*(typePtr: pTcl_ChannelType, chanName: cstring, 
+                        instanceData: Tcl_ClientData, mask: int): pTcl_Channel{.
+    cdecl, dynlib: dllName, importc.}
+proc Tcl_RegisterChannel*(interp: pTcl_Interp, channel: pTcl_Channel){.cdecl, 
+    dynlib: dllName, importc.}
+proc Tcl_UnregisterChannel*(interp: pTcl_Interp, channel: pTcl_Channel): int{.
+    cdecl, dynlib: dllName, importc.}
+proc Tcl_CreateChannelHandler*(chan: pTcl_Channel, mask: int, 
+                               prc: TTclChannelProc, clientData: Tcl_ClientData){.
+    cdecl, dynlib: dllName, importc.}
+proc Tcl_GetChannel*(interp: pTcl_Interp, chanName: cstring, modePtr: pInteger): pTcl_Channel{.
+    cdecl, dynlib: dllName, importc.}
+proc Tcl_GetStdChannel*(typ: int): pTcl_Channel{.cdecl, dynlib: dllName, 
+    importc.}
+proc Tcl_Gets*(chan: pTcl_Channel, dsPtr: pTcl_DString): int{.cdecl, 
+    dynlib: dllName, importc.}
+proc Tcl_Write*(chan: pTcl_Channel, s: cstring, slen: int): int{.cdecl, 
+    dynlib: dllName, importc.}
+proc Tcl_Flush*(chan: pTcl_Channel): int{.cdecl, dynlib: dllName, importc.}
+  #    TclWinLoadLibrary      = function(name: PChar): HMODULE; cdecl; external dllName;
+proc Tcl_CreateExitHandler*(prc: TTclClientDataProc, clientData: Tcl_ClientData){.
+    cdecl, dynlib: dllName, importc.}
+proc Tcl_DeleteExitHandler*(prc: TTclClientDataProc, clientData: Tcl_ClientData){.
+    cdecl, dynlib: dllName, importc.}
+proc Tcl_GetStringFromObj*(pObj: pTcl_Obj, pLen: pInteger): cstring{.cdecl, 
+    dynlib: dllName, importc.}
+proc Tcl_CreateObjCommand*(interp: pTcl_Interp, name: cstring, 
+                           cmdProc: TTclObjCmdProc, clientData: Tcl_ClientData, 
+                           deleteProc: TTclCmdDeleteProc): pTcl_Command{.cdecl, 
+    dynlib: dllName, importc.}
+proc Tcl_NewStringObj*(bytes: cstring, length: int): pTcl_Obj{.cdecl, 
+    dynlib: dllName, importc.}
+  #    procedure TclFreeObj(pObj: pTcl_Obj); cdecl; external dllName;
+proc Tcl_EvalObj*(interp: pTcl_Interp, pObj: pTcl_Obj): int{.cdecl, 
+    dynlib: dllName, importc.}
+proc Tcl_GlobalEvalObj*(interp: pTcl_Interp, pObj: pTcl_Obj): int{.cdecl, 
+    dynlib: dllName, importc.}
+proc TclRegComp*(exp: cstring): pointer{.cdecl, dynlib: dllName, importc.}
+proc TclRegExec*(prog: pointer, str: cstring, start: cstring): int{.cdecl, 
+    dynlib: dllName, importc.}
+proc TclRegError*(msg: cstring){.cdecl, dynlib: dllName, importc.}
+proc TclGetRegError*(): cstring{.cdecl, dynlib: dllName, importc.}
+proc Tcl_RegExpRange*(prog: pointer, index: int, head: var cstring, 
+                      tail: var cstring){.cdecl, dynlib: dllName, importc.}
+
+proc Tcl_GetCommandTable*(interp: pTcl_Interp): pHashTable =
+  if interp != nil: 
+    result = cast[pHashTable](cast[int](interp) + sizeof(Tcl_Interp) + 
+      sizeof(pointer))
+
+proc Tcl_CreateHashEntry*(tablePtr: pTcl_HashTable, key: cstring, 
+                          newPtr: pInteger): pTcl_HashEntry =
+  result = cast[pHashTable](tablePtr).createProc(tablePtr, key, newPtr)
+                          
+proc Tcl_FindHashEntry*(tablePtr: pTcl_HashTable, 
+                        key: cstring): pTcl_HashEntry =
+  result = cast[pHashTable](tablePtr).findProc(tablePtr, key)
+
+proc Tcl_SetHashValue*(h: pTcl_HashEntry, clientData: Tcl_ClientData) =
+  h.clientData = clientData
+
+proc Tcl_GetHashValue*(h: pTcl_HashEntry): Tcl_ClientData =
+  result = h.clientData
+
+proc Tcl_IncrRefCount*(pObj: pTcl_Obj) =
+  inc(pObj.refCount)
+
+proc Tcl_DecrRefCount*(pObj: pTcl_Obj) =
+  dec(pObj.refCount)
+  if pObj.refCount <= 0: 
+    dealloc(pObj)
+
+proc Tcl_IsShared*(pObj: pTcl_Obj): bool = 
+  return pObj.refCount > 1
+
+proc Tcl_GetHashKey*(hashTbl: pTcl_HashTable, 
+                     hashEntry: pTcl_HashEntry): cstring = 
+  if hashTbl == nil or hashEntry == nil: 
+    result = nil
+  else: 
+    result = hashEntry.key
+  
diff --git a/lib/base/x11/cursorfont.nim b/lib/wrappers/x11/cursorfont.nim
index b262ad7c1..b262ad7c1 100644
--- a/lib/base/x11/cursorfont.nim
+++ b/lib/wrappers/x11/cursorfont.nim
diff --git a/lib/wrappers/x11/keysym.nim b/lib/wrappers/x11/keysym.nim
new file mode 100644
index 000000000..b1fe13b80
--- /dev/null
+++ b/lib/wrappers/x11/keysym.nim
@@ -0,0 +1,1925 @@
+#
+#Converted from X11/keysym.h and X11/keysymdef.h
+#
+#Capital letter consts renamed from XK_... to XKc_...
+# (since Pascal isn't case-sensitive)
+#
+#i.e.
+#C      Pascal
+#XK_a   XK_a
+#XK_A   XKc_A
+#
+
+#* default keysyms *
+
+const 
+  XK_VoidSymbol* = 0x00FFFFFF # void symbol 
+
+when defined(XK_MISCELLANY) or true: 
+  const
+    #*
+    # * TTY Functions, cleverly chosen to map to ascii, for convenience of
+    # * programming, but could have been arbitrary (at the cost of lookup
+    # * tables in client code.
+    # *
+    XK_BackSpace* = 0x0000FF08  # back space, back char 
+    XK_Tab* = 0x0000FF09
+    XK_Linefeed* = 0x0000FF0A   # Linefeed, LF 
+    XK_Clear* = 0x0000FF0B
+    XK_Return* = 0x0000FF0D     # Return, enter 
+    XK_Pause* = 0x0000FF13      # Pause, hold 
+    XK_Scroll_Lock* = 0x0000FF14
+    XK_Sys_Req* = 0x0000FF15
+    XK_Escape* = 0x0000FF1B
+    XK_Delete* = 0x0000FFFF     # Delete, rubout 
+                                # International & multi-key character composition 
+    XK_Multi_key* = 0x0000FF20  # Multi-key character compose 
+    XK_Codeinput* = 0x0000FF37
+    XK_SingleCandidate* = 0x0000FF3C
+    XK_MultipleCandidate* = 0x0000FF3D
+    XK_PreviousCandidate* = 0x0000FF3E # Japanese keyboard support 
+    XK_Kanji* = 0x0000FF21      # Kanji, Kanji convert 
+    XK_Muhenkan* = 0x0000FF22   # Cancel Conversion 
+    XK_Henkan_Mode* = 0x0000FF23 # Start/Stop Conversion 
+    XK_Henkan* = 0x0000FF23     # Alias for Henkan_Mode 
+    XK_Romaji* = 0x0000FF24     # to Romaji 
+    XK_Hiragana* = 0x0000FF25   # to Hiragana 
+    XK_Katakana* = 0x0000FF26   # to Katakana 
+    XK_Hiragana_Katakana* = 0x0000FF27 # Hiragana/Katakana toggle 
+    XK_Zenkaku* = 0x0000FF28    # to Zenkaku 
+    XK_Hankaku* = 0x0000FF29    # to Hankaku 
+    XK_Zenkaku_Hankaku* = 0x0000FF2A # Zenkaku/Hankaku toggle 
+    XK_Touroku* = 0x0000FF2B    # Add to Dictionary 
+    XK_Massyo* = 0x0000FF2C     # Delete from Dictionary 
+    XK_Kana_Lock* = 0x0000FF2D  # Kana Lock 
+    XK_Kana_Shift* = 0x0000FF2E # Kana Shift 
+    XK_Eisu_Shift* = 0x0000FF2F # Alphanumeric Shift 
+    XK_Eisu_toggle* = 0x0000FF30 # Alphanumeric toggle 
+    XK_Kanji_Bangou* = 0x0000FF37 # Codeinput 
+    XK_Zen_Koho* = 0x0000FF3D   # Multiple/All Candidate(s) 
+    XK_Mae_Koho* = 0x0000FF3E   # Previous Candidate 
+                                # = $FF31 thru = $FF3F are under XK_KOREAN 
+                                # Cursor control & motion 
+    XK_Home* = 0x0000FF50
+    XK_Left* = 0x0000FF51       # Move left, left arrow 
+    XK_Up* = 0x0000FF52         # Move up, up arrow 
+    XK_Right* = 0x0000FF53      # Move right, right arrow 
+    XK_Down* = 0x0000FF54       # Move down, down arrow 
+    XK_Prior* = 0x0000FF55      # Prior, previous 
+    XK_Page_Up* = 0x0000FF55
+    XK_Next* = 0x0000FF56       # Next 
+    XK_Page_Down* = 0x0000FF56
+    XK_End* = 0x0000FF57        # EOL 
+    XK_Begin* = 0x0000FF58      # BOL 
+                                # Misc Functions 
+    XK_Select* = 0x0000FF60     # Select, mark 
+    XK_Print* = 0x0000FF61
+    XK_Execute* = 0x0000FF62    # Execute, run, do 
+    XK_Insert* = 0x0000FF63     # Insert, insert here 
+    XK_Undo* = 0x0000FF65       # Undo, oops 
+    XK_Redo* = 0x0000FF66       # redo, again 
+    XK_Menu* = 0x0000FF67
+    XK_Find* = 0x0000FF68       # Find, search 
+    XK_Cancel* = 0x0000FF69     # Cancel, stop, abort, exit 
+    XK_Help* = 0x0000FF6A       # Help 
+    XK_Break* = 0x0000FF6B
+    XK_Mode_switch* = 0x0000FF7E # Character set switch 
+    XK_script_switch* = 0x0000FF7E # Alias for mode_switch 
+    XK_Num_Lock* = 0x0000FF7F   # Keypad Functions, keypad numbers cleverly chosen to map to ascii 
+    XK_KP_Space* = 0x0000FF80   # space 
+    XK_KP_Tab* = 0x0000FF89
+    XK_KP_Enter* = 0x0000FF8D   # enter 
+    XK_KP_F1* = 0x0000FF91      # PF1, KP_A, ... 
+    XK_KP_F2* = 0x0000FF92
+    XK_KP_F3* = 0x0000FF93
+    XK_KP_F4* = 0x0000FF94
+    XK_KP_Home* = 0x0000FF95
+    XK_KP_Left* = 0x0000FF96
+    XK_KP_Up* = 0x0000FF97
+    XK_KP_Right* = 0x0000FF98
+    XK_KP_Down* = 0x0000FF99
+    XK_KP_Prior* = 0x0000FF9A
+    XK_KP_Page_Up* = 0x0000FF9A
+    XK_KP_Next* = 0x0000FF9B
+    XK_KP_Page_Down* = 0x0000FF9B
+    XK_KP_End* = 0x0000FF9C
+    XK_KP_Begin* = 0x0000FF9D
+    XK_KP_Insert* = 0x0000FF9E
+    XK_KP_Delete* = 0x0000FF9F
+    XK_KP_Equal* = 0x0000FFBD   # equals 
+    XK_KP_Multiply* = 0x0000FFAA
+    XK_KP_Add* = 0x0000FFAB
+    XK_KP_Separator* = 0x0000FFAC # separator, often comma 
+    XK_KP_Subtract* = 0x0000FFAD
+    XK_KP_Decimal* = 0x0000FFAE
+    XK_KP_Divide* = 0x0000FFAF
+    XK_KP_0* = 0x0000FFB0
+    XK_KP_1* = 0x0000FFB1
+    XK_KP_2* = 0x0000FFB2
+    XK_KP_3* = 0x0000FFB3
+    XK_KP_4* = 0x0000FFB4
+    XK_KP_5* = 0x0000FFB5
+    XK_KP_6* = 0x0000FFB6
+    XK_KP_7* = 0x0000FFB7
+    XK_KP_8* = 0x0000FFB8
+    XK_KP_9* = 0x0000FFB9 #*
+                          # * Auxilliary Functions; note the duplicate definitions for left and right
+                          # * function keys;  Sun keyboards and a few other manufactures have such
+                          # * function key groups on the left and/or right sides of the keyboard.
+                          # * We've not found a keyboard with more than 35 function keys total.
+                          # *
+    XK_F1* = 0x0000FFBE
+    XK_F2* = 0x0000FFBF
+    XK_F3* = 0x0000FFC0
+    XK_F4* = 0x0000FFC1
+    XK_F5* = 0x0000FFC2
+    XK_F6* = 0x0000FFC3
+    XK_F7* = 0x0000FFC4
+    XK_F8* = 0x0000FFC5
+    XK_F9* = 0x0000FFC6
+    XK_F10* = 0x0000FFC7
+    XK_F11* = 0x0000FFC8
+    XK_L1* = 0x0000FFC8
+    XK_F12* = 0x0000FFC9
+    XK_L2* = 0x0000FFC9
+    XK_F13* = 0x0000FFCA
+    XK_L3* = 0x0000FFCA
+    XK_F14* = 0x0000FFCB
+    XK_L4* = 0x0000FFCB
+    XK_F15* = 0x0000FFCC
+    XK_L5* = 0x0000FFCC
+    XK_F16* = 0x0000FFCD
+    XK_L6* = 0x0000FFCD
+    XK_F17* = 0x0000FFCE
+    XK_L7* = 0x0000FFCE
+    XK_F18* = 0x0000FFCF
+    XK_L8* = 0x0000FFCF
+    XK_F19* = 0x0000FFD0
+    XK_L9* = 0x0000FFD0
+    XK_F20* = 0x0000FFD1
+    XK_L10* = 0x0000FFD1
+    XK_F21* = 0x0000FFD2
+    XK_R1* = 0x0000FFD2
+    XK_F22* = 0x0000FFD3
+    XK_R2* = 0x0000FFD3
+    XK_F23* = 0x0000FFD4
+    XK_R3* = 0x0000FFD4
+    XK_F24* = 0x0000FFD5
+    XK_R4* = 0x0000FFD5
+    XK_F25* = 0x0000FFD6
+    XK_R5* = 0x0000FFD6
+    XK_F26* = 0x0000FFD7
+    XK_R6* = 0x0000FFD7
+    XK_F27* = 0x0000FFD8
+    XK_R7* = 0x0000FFD8
+    XK_F28* = 0x0000FFD9
+    XK_R8* = 0x0000FFD9
+    XK_F29* = 0x0000FFDA
+    XK_R9* = 0x0000FFDA
+    XK_F30* = 0x0000FFDB
+    XK_R10* = 0x0000FFDB
+    XK_F31* = 0x0000FFDC
+    XK_R11* = 0x0000FFDC
+    XK_F32* = 0x0000FFDD
+    XK_R12* = 0x0000FFDD
+    XK_F33* = 0x0000FFDE
+    XK_R13* = 0x0000FFDE
+    XK_F34* = 0x0000FFDF
+    XK_R14* = 0x0000FFDF
+    XK_F35* = 0x0000FFE0
+    XK_R15* = 0x0000FFE0        # Modifiers 
+    XK_Shift_L* = 0x0000FFE1    # Left shift 
+    XK_Shift_R* = 0x0000FFE2    # Right shift 
+    XK_Control_L* = 0x0000FFE3  # Left control 
+    XK_Control_R* = 0x0000FFE4  # Right control 
+    XK_Caps_Lock* = 0x0000FFE5  # Caps lock 
+    XK_Shift_Lock* = 0x0000FFE6 # Shift lock 
+    XK_Meta_L* = 0x0000FFE7     # Left meta 
+    XK_Meta_R* = 0x0000FFE8     # Right meta 
+    XK_Alt_L* = 0x0000FFE9      # Left alt 
+    XK_Alt_R* = 0x0000FFEA      # Right alt 
+    XK_Super_L* = 0x0000FFEB    # Left super 
+    XK_Super_R* = 0x0000FFEC    # Right super 
+    XK_Hyper_L* = 0x0000FFED    # Left hyper 
+    XK_Hyper_R* = 0x0000FFEE    # Right hyper 
+# XK_MISCELLANY 
+#*
+# * ISO 9995 Function and Modifier Keys
+# * Byte 3 = = $FE
+# *
+
+when defined(XK_XKB_KEYS) or true: 
+  const
+    XK_ISO_Lock* = 0x0000FE01
+    XK_ISO_Level2_Latch* = 0x0000FE02
+    XK_ISO_Level3_Shift* = 0x0000FE03
+    XK_ISO_Level3_Latch* = 0x0000FE04
+    XK_ISO_Level3_Lock* = 0x0000FE05
+    XK_ISO_Group_Shift* = 0x0000FF7E # Alias for mode_switch 
+    XK_ISO_Group_Latch* = 0x0000FE06
+    XK_ISO_Group_Lock* = 0x0000FE07
+    XK_ISO_Next_Group* = 0x0000FE08
+    XK_ISO_Next_Group_Lock* = 0x0000FE09
+    XK_ISO_Prev_Group* = 0x0000FE0A
+    XK_ISO_Prev_Group_Lock* = 0x0000FE0B
+    XK_ISO_First_Group* = 0x0000FE0C
+    XK_ISO_First_Group_Lock* = 0x0000FE0D
+    XK_ISO_Last_Group* = 0x0000FE0E
+    XK_ISO_Last_Group_Lock* = 0x0000FE0F
+    XK_ISO_Left_Tab* = 0x0000FE20
+    XK_ISO_Move_Line_Up* = 0x0000FE21
+    XK_ISO_Move_Line_Down* = 0x0000FE22
+    XK_ISO_Partial_Line_Up* = 0x0000FE23
+    XK_ISO_Partial_Line_Down* = 0x0000FE24
+    XK_ISO_Partial_Space_Left* = 0x0000FE25
+    XK_ISO_Partial_Space_Right* = 0x0000FE26
+    XK_ISO_Set_Margin_Left* = 0x0000FE27
+    XK_ISO_Set_Margin_Right* = 0x0000FE28
+    XK_ISO_Release_Margin_Left* = 0x0000FE29
+    XK_ISO_Release_Margin_Right* = 0x0000FE2A
+    XK_ISO_Release_Both_Margins* = 0x0000FE2B
+    XK_ISO_Fast_Cursor_Left* = 0x0000FE2C
+    XK_ISO_Fast_Cursor_Right* = 0x0000FE2D
+    XK_ISO_Fast_Cursor_Up* = 0x0000FE2E
+    XK_ISO_Fast_Cursor_Down* = 0x0000FE2F
+    XK_ISO_Continuous_Underline* = 0x0000FE30
+    XK_ISO_Discontinuous_Underline* = 0x0000FE31
+    XK_ISO_Emphasize* = 0x0000FE32
+    XK_ISO_Center_Object* = 0x0000FE33
+    XK_ISO_Enter* = 0x0000FE34
+    XK_dead_grave* = 0x0000FE50
+    XK_dead_acute* = 0x0000FE51
+    XK_dead_circumflex* = 0x0000FE52
+    XK_dead_tilde* = 0x0000FE53
+    XK_dead_macron* = 0x0000FE54
+    XK_dead_breve* = 0x0000FE55
+    XK_dead_abovedot* = 0x0000FE56
+    XK_dead_diaeresis* = 0x0000FE57
+    XK_dead_abovering* = 0x0000FE58
+    XK_dead_doubleacute* = 0x0000FE59
+    XK_dead_caron* = 0x0000FE5A
+    XK_dead_cedilla* = 0x0000FE5B
+    XK_dead_ogonek* = 0x0000FE5C
+    XK_dead_iota* = 0x0000FE5D
+    XK_dead_voiced_sound* = 0x0000FE5E
+    XK_dead_semivoiced_sound* = 0x0000FE5F
+    XK_dead_belowdot* = 0x0000FE60
+    XK_dead_hook* = 0x0000FE61
+    XK_dead_horn* = 0x0000FE62
+    XK_First_Virtual_Screen* = 0x0000FED0
+    XK_Prev_Virtual_Screen* = 0x0000FED1
+    XK_Next_Virtual_Screen* = 0x0000FED2
+    XK_Last_Virtual_Screen* = 0x0000FED4
+    XK_Terminate_Server* = 0x0000FED5
+    XK_AccessX_Enable* = 0x0000FE70
+    XK_AccessX_Feedback_Enable* = 0x0000FE71
+    XK_RepeatKeys_Enable* = 0x0000FE72
+    XK_SlowKeys_Enable* = 0x0000FE73
+    XK_BounceKeys_Enable* = 0x0000FE74
+    XK_StickyKeys_Enable* = 0x0000FE75
+    XK_MouseKeys_Enable* = 0x0000FE76
+    XK_MouseKeys_Accel_Enable* = 0x0000FE77
+    XK_Overlay1_Enable* = 0x0000FE78
+    XK_Overlay2_Enable* = 0x0000FE79
+    XK_AudibleBell_Enable* = 0x0000FE7A
+    XK_Pointer_Left* = 0x0000FEE0
+    XK_Pointer_Right* = 0x0000FEE1
+    XK_Pointer_Up* = 0x0000FEE2
+    XK_Pointer_Down* = 0x0000FEE3
+    XK_Pointer_UpLeft* = 0x0000FEE4
+    XK_Pointer_UpRight* = 0x0000FEE5
+    XK_Pointer_DownLeft* = 0x0000FEE6
+    XK_Pointer_DownRight* = 0x0000FEE7
+    XK_Pointer_Button_Dflt* = 0x0000FEE8
+    XK_Pointer_Button1* = 0x0000FEE9
+    XK_Pointer_Button2* = 0x0000FEEA
+    XK_Pointer_Button3* = 0x0000FEEB
+    XK_Pointer_Button4* = 0x0000FEEC
+    XK_Pointer_Button5* = 0x0000FEED
+    XK_Pointer_DblClick_Dflt* = 0x0000FEEE
+    XK_Pointer_DblClick1* = 0x0000FEEF
+    XK_Pointer_DblClick2* = 0x0000FEF0
+    XK_Pointer_DblClick3* = 0x0000FEF1
+    XK_Pointer_DblClick4* = 0x0000FEF2
+    XK_Pointer_DblClick5* = 0x0000FEF3
+    XK_Pointer_Drag_Dflt* = 0x0000FEF4
+    XK_Pointer_Drag1* = 0x0000FEF5
+    XK_Pointer_Drag2* = 0x0000FEF6
+    XK_Pointer_Drag3* = 0x0000FEF7
+    XK_Pointer_Drag4* = 0x0000FEF8
+    XK_Pointer_Drag5* = 0x0000FEFD
+    XK_Pointer_EnableKeys* = 0x0000FEF9
+    XK_Pointer_Accelerate* = 0x0000FEFA
+    XK_Pointer_DfltBtnNext* = 0x0000FEFB
+    XK_Pointer_DfltBtnPrev* = 0x0000FEFC
+  #*
+  # * 3270 Terminal Keys
+  # * Byte 3 = = $FD
+  # *
+
+when defined(XK_3270) or true: 
+  const
+    XK_3270_Duplicate* = 0x0000FD01
+    XK_3270_FieldMark* = 0x0000FD02
+    XK_3270_Right2* = 0x0000FD03
+    XK_3270_Left2* = 0x0000FD04
+    XK_3270_BackTab* = 0x0000FD05
+    XK_3270_EraseEOF* = 0x0000FD06
+    XK_3270_EraseInput* = 0x0000FD07
+    XK_3270_Reset* = 0x0000FD08
+    XK_3270_Quit* = 0x0000FD09
+    XK_3270_PA1* = 0x0000FD0A
+    XK_3270_PA2* = 0x0000FD0B
+    XK_3270_PA3* = 0x0000FD0C
+    XK_3270_Test* = 0x0000FD0D
+    XK_3270_Attn* = 0x0000FD0E
+    XK_3270_CursorBlink* = 0x0000FD0F
+    XK_3270_AltCursor* = 0x0000FD10
+    XK_3270_KeyClick* = 0x0000FD11
+    XK_3270_Jump* = 0x0000FD12
+    XK_3270_Ident* = 0x0000FD13
+    XK_3270_Rule* = 0x0000FD14
+    XK_3270_Copy* = 0x0000FD15
+    XK_3270_Play* = 0x0000FD16
+    XK_3270_Setup* = 0x0000FD17
+    XK_3270_Record* = 0x0000FD18
+    XK_3270_ChangeScreen* = 0x0000FD19
+    XK_3270_DeleteWord* = 0x0000FD1A
+    XK_3270_ExSelect* = 0x0000FD1B
+    XK_3270_CursorSelect* = 0x0000FD1C
+    XK_3270_PrintScreen* = 0x0000FD1D
+    XK_3270_Enter* = 0x0000FD1E
+#*
+# *  Latin 1
+# *  Byte 3 = 0
+# *
+
+when defined(XK_LATIN1) or true: 
+  const
+    XK_space* = 0x00000020
+    XK_exclam* = 0x00000021
+    XK_quotedbl* = 0x00000022
+    XK_numbersign* = 0x00000023
+    XK_dollar* = 0x00000024
+    XK_percent* = 0x00000025
+    XK_ampersand* = 0x00000026
+    XK_apostrophe* = 0x00000027
+    XK_quoteright* = 0x00000027 # deprecated 
+    XK_parenleft* = 0x00000028
+    XK_parenright* = 0x00000029
+    XK_asterisk* = 0x0000002A
+    XK_plus* = 0x0000002B
+    XK_comma* = 0x0000002C
+    XK_minus* = 0x0000002D
+    XK_period* = 0x0000002E
+    XK_slash* = 0x0000002F
+    XK_0* = 0x00000030
+    XK_1* = 0x00000031
+    XK_2* = 0x00000032
+    XK_3* = 0x00000033
+    XK_4* = 0x00000034
+    XK_5* = 0x00000035
+    XK_6* = 0x00000036
+    XK_7* = 0x00000037
+    XK_8* = 0x00000038
+    XK_9* = 0x00000039
+    XK_colon* = 0x0000003A
+    XK_semicolon* = 0x0000003B
+    XK_less* = 0x0000003C
+    XK_equal* = 0x0000003D
+    XK_greater* = 0x0000003E
+    XK_question* = 0x0000003F
+    XK_at* = 0x00000040
+    XKc_A* = 0x00000041
+    XKc_B* = 0x00000042
+    XKc_C* = 0x00000043
+    XKc_D* = 0x00000044
+    XKc_E* = 0x00000045
+    XKc_F* = 0x00000046
+    XKc_G* = 0x00000047
+    XKc_H* = 0x00000048
+    XKc_I* = 0x00000049
+    XKc_J* = 0x0000004A
+    XKc_K* = 0x0000004B
+    XKc_L* = 0x0000004C
+    XKc_M* = 0x0000004D
+    XKc_N* = 0x0000004E
+    XKc_O* = 0x0000004F
+    XKc_P* = 0x00000050
+    XKc_Q* = 0x00000051
+    XKc_R* = 0x00000052
+    XKc_S* = 0x00000053
+    XKc_T* = 0x00000054
+    XKc_U* = 0x00000055
+    XKc_V* = 0x00000056
+    XKc_W* = 0x00000057
+    XKc_X* = 0x00000058
+    XKc_Y* = 0x00000059
+    XKc_Z* = 0x0000005A
+    XK_bracketleft* = 0x0000005B
+    XK_backslash* = 0x0000005C
+    XK_bracketright* = 0x0000005D
+    XK_asciicircum* = 0x0000005E
+    XK_underscore* = 0x0000005F
+    XK_grave* = 0x00000060
+    XK_quoteleft* = 0x00000060  # deprecated 
+    XK_a* = 0x00000061
+    XK_b* = 0x00000062
+    XK_c* = 0x00000063
+    XK_d* = 0x00000064
+    XK_e* = 0x00000065
+    XK_f* = 0x00000066
+    XK_g* = 0x00000067
+    XK_h* = 0x00000068
+    XK_i* = 0x00000069
+    XK_j* = 0x0000006A
+    XK_k* = 0x0000006B
+    XK_l* = 0x0000006C
+    XK_m* = 0x0000006D
+    XK_n* = 0x0000006E
+    XK_o* = 0x0000006F
+    XK_p* = 0x00000070
+    XK_q* = 0x00000071
+    XK_r* = 0x00000072
+    XK_s* = 0x00000073
+    XK_t* = 0x00000074
+    XK_u* = 0x00000075
+    XK_v* = 0x00000076
+    XK_w* = 0x00000077
+    XK_x* = 0x00000078
+    XK_y* = 0x00000079
+    XK_z* = 0x0000007A
+    XK_braceleft* = 0x0000007B
+    XK_bar* = 0x0000007C
+    XK_braceright* = 0x0000007D
+    XK_asciitilde* = 0x0000007E
+    XK_nobreakspace* = 0x000000A0
+    XK_exclamdown* = 0x000000A1
+    XK_cent* = 0x000000A2
+    XK_sterling* = 0x000000A3
+    XK_currency* = 0x000000A4
+    XK_yen* = 0x000000A5
+    XK_brokenbar* = 0x000000A6
+    XK_section* = 0x000000A7
+    XK_diaeresis* = 0x000000A8
+    XK_copyright* = 0x000000A9
+    XK_ordfeminine* = 0x000000AA
+    XK_guillemotleft* = 0x000000AB # left angle quotation mark 
+    XK_notsign* = 0x000000AC
+    XK_hyphen* = 0x000000AD
+    XK_registered* = 0x000000AE
+    XK_macron* = 0x000000AF
+    XK_degree* = 0x000000B0
+    XK_plusminus* = 0x000000B1
+    XK_twosuperior* = 0x000000B2
+    XK_threesuperior* = 0x000000B3
+    XK_acute* = 0x000000B4
+    XK_mu* = 0x000000B5
+    XK_paragraph* = 0x000000B6
+    XK_periodcentered* = 0x000000B7
+    XK_cedilla* = 0x000000B8
+    XK_onesuperior* = 0x000000B9
+    XK_masculine* = 0x000000BA
+    XK_guillemotright* = 0x000000BB # right angle quotation mark 
+    XK_onequarter* = 0x000000BC
+    XK_onehalf* = 0x000000BD
+    XK_threequarters* = 0x000000BE
+    XK_questiondown* = 0x000000BF
+    XKc_Agrave* = 0x000000C0
+    XKc_Aacute* = 0x000000C1
+    XKc_Acircumflex* = 0x000000C2
+    XKc_Atilde* = 0x000000C3
+    XKc_Adiaeresis* = 0x000000C4
+    XKc_Aring* = 0x000000C5
+    XKc_AE* = 0x000000C6
+    XKc_Ccedilla* = 0x000000C7
+    XKc_Egrave* = 0x000000C8
+    XKc_Eacute* = 0x000000C9
+    XKc_Ecircumflex* = 0x000000CA
+    XKc_Ediaeresis* = 0x000000CB
+    XKc_Igrave* = 0x000000CC
+    XKc_Iacute* = 0x000000CD
+    XKc_Icircumflex* = 0x000000CE
+    XKc_Idiaeresis* = 0x000000CF
+    XKc_ETH* = 0x000000D0
+    XKc_Ntilde* = 0x000000D1
+    XKc_Ograve* = 0x000000D2
+    XKc_Oacute* = 0x000000D3
+    XKc_Ocircumflex* = 0x000000D4
+    XKc_Otilde* = 0x000000D5
+    XKc_Odiaeresis* = 0x000000D6
+    XK_multiply* = 0x000000D7
+    XKc_Ooblique* = 0x000000D8
+    XKc_Oslash* = XKc_Ooblique
+    XKc_Ugrave* = 0x000000D9
+    XKc_Uacute* = 0x000000DA
+    XKc_Ucircumflex* = 0x000000DB
+    XKc_Udiaeresis* = 0x000000DC
+    XKc_Yacute* = 0x000000DD
+    XKc_THORN* = 0x000000DE
+    XK_ssharp* = 0x000000DF
+    XK_agrave* = 0x000000E0
+    XK_aacute* = 0x000000E1
+    XK_acircumflex* = 0x000000E2
+    XK_atilde* = 0x000000E3
+    XK_adiaeresis* = 0x000000E4
+    XK_aring* = 0x000000E5
+    XK_ae* = 0x000000E6
+    XK_ccedilla* = 0x000000E7
+    XK_egrave* = 0x000000E8
+    XK_eacute* = 0x000000E9
+    XK_ecircumflex* = 0x000000EA
+    XK_ediaeresis* = 0x000000EB
+    XK_igrave* = 0x000000EC
+    XK_iacute* = 0x000000ED
+    XK_icircumflex* = 0x000000EE
+    XK_idiaeresis* = 0x000000EF
+    XK_eth* = 0x000000F0
+    XK_ntilde* = 0x000000F1
+    XK_ograve* = 0x000000F2
+    XK_oacute* = 0x000000F3
+    XK_ocircumflex* = 0x000000F4
+    XK_otilde* = 0x000000F5
+    XK_odiaeresis* = 0x000000F6
+    XK_division* = 0x000000F7
+    XK_oslash* = 0x000000F8
+    XK_ooblique* = XK_oslash
+    XK_ugrave* = 0x000000F9
+    XK_uacute* = 0x000000FA
+    XK_ucircumflex* = 0x000000FB
+    XK_udiaeresis* = 0x000000FC
+    XK_yacute* = 0x000000FD
+    XK_thorn* = 0x000000FE
+    XK_ydiaeresis* = 0x000000FF
+# XK_LATIN1 
+#*
+# *   Latin 2
+# *   Byte 3 = 1
+# *
+
+when defined(XK_LATIN2) or true: 
+  const
+    XKc_Aogonek* = 0x000001A1
+    XK_breve* = 0x000001A2
+    XKc_Lstroke* = 0x000001A3
+    XKc_Lcaron* = 0x000001A5
+    XKc_Sacute* = 0x000001A6
+    XKc_Scaron* = 0x000001A9
+    XKc_Scedilla* = 0x000001AA
+    XKc_Tcaron* = 0x000001AB
+    XKc_Zacute* = 0x000001AC
+    XKc_Zcaron* = 0x000001AE
+    XKc_Zabovedot* = 0x000001AF
+    XK_aogonek* = 0x000001B1
+    XK_ogonek* = 0x000001B2
+    XK_lstroke* = 0x000001B3
+    XK_lcaron* = 0x000001B5
+    XK_sacute* = 0x000001B6
+    XK_caron* = 0x000001B7
+    XK_scaron* = 0x000001B9
+    XK_scedilla* = 0x000001BA
+    XK_tcaron* = 0x000001BB
+    XK_zacute* = 0x000001BC
+    XK_doubleacute* = 0x000001BD
+    XK_zcaron* = 0x000001BE
+    XK_zabovedot* = 0x000001BF
+    XKc_Racute* = 0x000001C0
+    XKc_Abreve* = 0x000001C3
+    XKc_Lacute* = 0x000001C5
+    XKc_Cacute* = 0x000001C6
+    XKc_Ccaron* = 0x000001C8
+    XKc_Eogonek* = 0x000001CA
+    XKc_Ecaron* = 0x000001CC
+    XKc_Dcaron* = 0x000001CF
+    XKc_Dstroke* = 0x000001D0
+    XKc_Nacute* = 0x000001D1
+    XKc_Ncaron* = 0x000001D2
+    XKc_Odoubleacute* = 0x000001D5
+    XKc_Rcaron* = 0x000001D8
+    XKc_Uring* = 0x000001D9
+    XKc_Udoubleacute* = 0x000001DB
+    XKc_Tcedilla* = 0x000001DE
+    XK_racute* = 0x000001E0
+    XK_abreve* = 0x000001E3
+    XK_lacute* = 0x000001E5
+    XK_cacute* = 0x000001E6
+    XK_ccaron* = 0x000001E8
+    XK_eogonek* = 0x000001EA
+    XK_ecaron* = 0x000001EC
+    XK_dcaron* = 0x000001EF
+    XK_dstroke* = 0x000001F0
+    XK_nacute* = 0x000001F1
+    XK_ncaron* = 0x000001F2
+    XK_odoubleacute* = 0x000001F5
+    XK_udoubleacute* = 0x000001FB
+    XK_rcaron* = 0x000001F8
+    XK_uring* = 0x000001F9
+    XK_tcedilla* = 0x000001FE
+    XK_abovedot* = 0x000001FF
+# XK_LATIN2 
+#*
+# *   Latin 3
+# *   Byte 3 = 2
+# *
+
+when defined(XK_LATIN3) or true: 
+  const
+    XKc_Hstroke* = 0x000002A1
+    XKc_Hcircumflex* = 0x000002A6
+    XKc_Iabovedot* = 0x000002A9
+    XKc_Gbreve* = 0x000002AB
+    XKc_Jcircumflex* = 0x000002AC
+    XK_hstroke* = 0x000002B1
+    XK_hcircumflex* = 0x000002B6
+    XK_idotless* = 0x000002B9
+    XK_gbreve* = 0x000002BB
+    XK_jcircumflex* = 0x000002BC
+    XKc_Cabovedot* = 0x000002C5
+    XKc_Ccircumflex* = 0x000002C6
+    XKc_Gabovedot* = 0x000002D5
+    XKc_Gcircumflex* = 0x000002D8
+    XKc_Ubreve* = 0x000002DD
+    XKc_Scircumflex* = 0x000002DE
+    XK_cabovedot* = 0x000002E5
+    XK_ccircumflex* = 0x000002E6
+    XK_gabovedot* = 0x000002F5
+    XK_gcircumflex* = 0x000002F8
+    XK_ubreve* = 0x000002FD
+    XK_scircumflex* = 0x000002FE
+# XK_LATIN3 
+#*
+# *   Latin 4
+# *   Byte 3 = 3
+# *
+
+when defined(XK_LATIN4) or true: 
+  const
+    XK_kra* = 0x000003A2
+    XK_kappa* = 0x000003A2      # deprecated 
+    XKc_Rcedilla* = 0x000003A3
+    XKc_Itilde* = 0x000003A5
+    XKc_Lcedilla* = 0x000003A6
+    XKc_Emacron* = 0x000003AA
+    XKc_Gcedilla* = 0x000003AB
+    XKc_Tslash* = 0x000003AC
+    XK_rcedilla* = 0x000003B3
+    XK_itilde* = 0x000003B5
+    XK_lcedilla* = 0x000003B6
+    XK_emacron* = 0x000003BA
+    XK_gcedilla* = 0x000003BB
+    XK_tslash* = 0x000003BC
+    XKc_ENG* = 0x000003BD
+    XK_eng* = 0x000003BF
+    XKc_Amacron* = 0x000003C0
+    XKc_Iogonek* = 0x000003C7
+    XKc_Eabovedot* = 0x000003CC
+    XKc_Imacron* = 0x000003CF
+    XKc_Ncedilla* = 0x000003D1
+    XKc_Omacron* = 0x000003D2
+    XKc_Kcedilla* = 0x000003D3
+    XKc_Uogonek* = 0x000003D9
+    XKc_Utilde* = 0x000003DD
+    XKc_Umacron* = 0x000003DE
+    XK_amacron* = 0x000003E0
+    XK_iogonek* = 0x000003E7
+    XK_eabovedot* = 0x000003EC
+    XK_imacron* = 0x000003EF
+    XK_ncedilla* = 0x000003F1
+    XK_omacron* = 0x000003F2
+    XK_kcedilla* = 0x000003F3
+    XK_uogonek* = 0x000003F9
+    XK_utilde* = 0x000003FD
+    XK_umacron* = 0x000003FE
+# XK_LATIN4 
+#*
+# * Latin-8
+# * Byte 3 = 18
+# *
+
+when defined(XK_LATIN8) or true: 
+  const
+    XKc_Babovedot* = 0x000012A1
+    XK_babovedot* = 0x000012A2
+    XKc_Dabovedot* = 0x000012A6
+    XKc_Wgrave* = 0x000012A8
+    XKc_Wacute* = 0x000012AA
+    XK_dabovedot* = 0x000012AB
+    XKc_Ygrave* = 0x000012AC
+    XKc_Fabovedot* = 0x000012B0
+    XK_fabovedot* = 0x000012B1
+    XKc_Mabovedot* = 0x000012B4
+    XK_mabovedot* = 0x000012B5
+    XKc_Pabovedot* = 0x000012B7
+    XK_wgrave* = 0x000012B8
+    XK_pabovedot* = 0x000012B9
+    XK_wacute* = 0x000012BA
+    XKc_Sabovedot* = 0x000012BB
+    XK_ygrave* = 0x000012BC
+    XKc_Wdiaeresis* = 0x000012BD
+    XK_wdiaeresis* = 0x000012BE
+    XK_sabovedot* = 0x000012BF
+    XKc_Wcircumflex* = 0x000012D0
+    XKc_Tabovedot* = 0x000012D7
+    XKc_Ycircumflex* = 0x000012DE
+    XK_wcircumflex* = 0x000012F0
+    XK_tabovedot* = 0x000012F7
+    XK_ycircumflex* = 0x000012FE
+# XK_LATIN8 
+#*
+# * Latin-9 (a.k.a. Latin-0)
+# * Byte 3 = 19
+# *
+
+when defined(XK_LATIN9) or true: 
+  const
+    XKc_OE* = 0x000013BC
+    XK_oe* = 0x000013BD
+    XKc_Ydiaeresis* = 0x000013BE
+# XK_LATIN9 
+#*
+# * Katakana
+# * Byte 3 = 4
+# *
+
+when defined(XK_KATAKANA) or true: 
+  const
+    XK_overline* = 0x0000047E
+    XK_kana_fullstop* = 0x000004A1
+    XK_kana_openingbracket* = 0x000004A2
+    XK_kana_closingbracket* = 0x000004A3
+    XK_kana_comma* = 0x000004A4
+    XK_kana_conjunctive* = 0x000004A5
+    XK_kana_middledot* = 0x000004A5 # deprecated 
+    XKc_kana_WO* = 0x000004A6
+    XK_kana_a* = 0x000004A7
+    XK_kana_i* = 0x000004A8
+    XK_kana_u* = 0x000004A9
+    XK_kana_e* = 0x000004AA
+    XK_kana_o* = 0x000004AB
+    XK_kana_ya* = 0x000004AC
+    XK_kana_yu* = 0x000004AD
+    XK_kana_yo* = 0x000004AE
+    XK_kana_tsu* = 0x000004AF
+    XK_kana_tu* = 0x000004AF    # deprecated 
+    XK_prolongedsound* = 0x000004B0
+    XKc_kana_A* = 0x000004B1
+    XKc_kana_I* = 0x000004B2
+    XKc_kana_U* = 0x000004B3
+    XKc_kana_E* = 0x000004B4
+    XKc_kana_O* = 0x000004B5
+    XKc_kana_KA* = 0x000004B6
+    XKc_kana_KI* = 0x000004B7
+    XKc_kana_KU* = 0x000004B8
+    XKc_kana_KE* = 0x000004B9
+    XKc_kana_KO* = 0x000004BA
+    XKc_kana_SA* = 0x000004BB
+    XKc_kana_SHI* = 0x000004BC
+    XKc_kana_SU* = 0x000004BD
+    XKc_kana_SE* = 0x000004BE
+    XKc_kana_SO* = 0x000004BF
+    XKc_kana_TA* = 0x000004C0
+    XKc_kana_CHI* = 0x000004C1
+    XKc_kana_TI* = 0x000004C1   # deprecated 
+    XKc_kana_TSU* = 0x000004C2
+    XKc_kana_TU* = 0x000004C2   # deprecated 
+    XKc_kana_TE* = 0x000004C3
+    XKc_kana_TO* = 0x000004C4
+    XKc_kana_NA* = 0x000004C5
+    XKc_kana_NI* = 0x000004C6
+    XKc_kana_NU* = 0x000004C7
+    XKc_kana_NE* = 0x000004C8
+    XKc_kana_NO* = 0x000004C9
+    XKc_kana_HA* = 0x000004CA
+    XKc_kana_HI* = 0x000004CB
+    XKc_kana_FU* = 0x000004CC
+    XKc_kana_HU* = 0x000004CC   # deprecated 
+    XKc_kana_HE* = 0x000004CD
+    XKc_kana_HO* = 0x000004CE
+    XKc_kana_MA* = 0x000004CF
+    XKc_kana_MI* = 0x000004D0
+    XKc_kana_MU* = 0x000004D1
+    XKc_kana_ME* = 0x000004D2
+    XKc_kana_MO* = 0x000004D3
+    XKc_kana_YA* = 0x000004D4
+    XKc_kana_YU* = 0x000004D5
+    XKc_kana_YO* = 0x000004D6
+    XKc_kana_RA* = 0x000004D7
+    XKc_kana_RI* = 0x000004D8
+    XKc_kana_RU* = 0x000004D9
+    XKc_kana_RE* = 0x000004DA
+    XKc_kana_RO* = 0x000004DB
+    XKc_kana_WA* = 0x000004DC
+    XKc_kana_N* = 0x000004DD
+    XK_voicedsound* = 0x000004DE
+    XK_semivoicedsound* = 0x000004DF
+    XK_kana_switch* = 0x0000FF7E # Alias for mode_switch 
+# XK_KATAKANA 
+#*
+# *  Arabic
+# *  Byte 3 = 5
+# *
+
+when defined(XK_ARABIC) or true: 
+  const
+    XK_Farsi_0* = 0x00000590
+    XK_Farsi_1* = 0x00000591
+    XK_Farsi_2* = 0x00000592
+    XK_Farsi_3* = 0x00000593
+    XK_Farsi_4* = 0x00000594
+    XK_Farsi_5* = 0x00000595
+    XK_Farsi_6* = 0x00000596
+    XK_Farsi_7* = 0x00000597
+    XK_Farsi_8* = 0x00000598
+    XK_Farsi_9* = 0x00000599
+    XK_Arabic_percent* = 0x000005A5
+    XK_Arabic_superscript_alef* = 0x000005A6
+    XK_Arabic_tteh* = 0x000005A7
+    XK_Arabic_peh* = 0x000005A8
+    XK_Arabic_tcheh* = 0x000005A9
+    XK_Arabic_ddal* = 0x000005AA
+    XK_Arabic_rreh* = 0x000005AB
+    XK_Arabic_comma* = 0x000005AC
+    XK_Arabic_fullstop* = 0x000005AE
+    XK_Arabic_0* = 0x000005B0
+    XK_Arabic_1* = 0x000005B1
+    XK_Arabic_2* = 0x000005B2
+    XK_Arabic_3* = 0x000005B3
+    XK_Arabic_4* = 0x000005B4
+    XK_Arabic_5* = 0x000005B5
+    XK_Arabic_6* = 0x000005B6
+    XK_Arabic_7* = 0x000005B7
+    XK_Arabic_8* = 0x000005B8
+    XK_Arabic_9* = 0x000005B9
+    XK_Arabic_semicolon* = 0x000005BB
+    XK_Arabic_question_mark* = 0x000005BF
+    XK_Arabic_hamza* = 0x000005C1
+    XK_Arabic_maddaonalef* = 0x000005C2
+    XK_Arabic_hamzaonalef* = 0x000005C3
+    XK_Arabic_hamzaonwaw* = 0x000005C4
+    XK_Arabic_hamzaunderalef* = 0x000005C5
+    XK_Arabic_hamzaonyeh* = 0x000005C6
+    XK_Arabic_alef* = 0x000005C7
+    XK_Arabic_beh* = 0x000005C8
+    XK_Arabic_tehmarbuta* = 0x000005C9
+    XK_Arabic_teh* = 0x000005CA
+    XK_Arabic_theh* = 0x000005CB
+    XK_Arabic_jeem* = 0x000005CC
+    XK_Arabic_hah* = 0x000005CD
+    XK_Arabic_khah* = 0x000005CE
+    XK_Arabic_dal* = 0x000005CF
+    XK_Arabic_thal* = 0x000005D0
+    XK_Arabic_ra* = 0x000005D1
+    XK_Arabic_zain* = 0x000005D2
+    XK_Arabic_seen* = 0x000005D3
+    XK_Arabic_sheen* = 0x000005D4
+    XK_Arabic_sad* = 0x000005D5
+    XK_Arabic_dad* = 0x000005D6
+    XK_Arabic_tah* = 0x000005D7
+    XK_Arabic_zah* = 0x000005D8
+    XK_Arabic_ain* = 0x000005D9
+    XK_Arabic_ghain* = 0x000005DA
+    XK_Arabic_tatweel* = 0x000005E0
+    XK_Arabic_feh* = 0x000005E1
+    XK_Arabic_qaf* = 0x000005E2
+    XK_Arabic_kaf* = 0x000005E3
+    XK_Arabic_lam* = 0x000005E4
+    XK_Arabic_meem* = 0x000005E5
+    XK_Arabic_noon* = 0x000005E6
+    XK_Arabic_ha* = 0x000005E7
+    XK_Arabic_heh* = 0x000005E7 # deprecated 
+    XK_Arabic_waw* = 0x000005E8
+    XK_Arabic_alefmaksura* = 0x000005E9
+    XK_Arabic_yeh* = 0x000005EA
+    XK_Arabic_fathatan* = 0x000005EB
+    XK_Arabic_dammatan* = 0x000005EC
+    XK_Arabic_kasratan* = 0x000005ED
+    XK_Arabic_fatha* = 0x000005EE
+    XK_Arabic_damma* = 0x000005EF
+    XK_Arabic_kasra* = 0x000005F0
+    XK_Arabic_shadda* = 0x000005F1
+    XK_Arabic_sukun* = 0x000005F2
+    XK_Arabic_madda_above* = 0x000005F3
+    XK_Arabic_hamza_above* = 0x000005F4
+    XK_Arabic_hamza_below* = 0x000005F5
+    XK_Arabic_jeh* = 0x000005F6
+    XK_Arabic_veh* = 0x000005F7
+    XK_Arabic_keheh* = 0x000005F8
+    XK_Arabic_gaf* = 0x000005F9
+    XK_Arabic_noon_ghunna* = 0x000005FA
+    XK_Arabic_heh_doachashmee* = 0x000005FB
+    XK_Farsi_yeh* = 0x000005FC
+    XK_Arabic_farsi_yeh* = XK_Farsi_yeh
+    XK_Arabic_yeh_baree* = 0x000005FD
+    XK_Arabic_heh_goal* = 0x000005FE
+    XK_Arabic_switch* = 0x0000FF7E # Alias for mode_switch 
+# XK_ARABIC 
+#*
+# * Cyrillic
+# * Byte 3 = 6
+# *
+
+when defined(XK_CYRILLIC) or true: 
+  const
+    XKc_Cyrillic_GHE_bar* = 0x00000680
+    XK_Cyrillic_ghe_bar* = 0x00000690
+    XKc_Cyrillic_ZHE_descender* = 0x00000681
+    XK_Cyrillic_zhe_descender* = 0x00000691
+    XKc_Cyrillic_KA_descender* = 0x00000682
+    XK_Cyrillic_ka_descender* = 0x00000692
+    XKc_Cyrillic_KA_vertstroke* = 0x00000683
+    XK_Cyrillic_ka_vertstroke* = 0x00000693
+    XKc_Cyrillic_EN_descender* = 0x00000684
+    XK_Cyrillic_en_descender* = 0x00000694
+    XKc_Cyrillic_U_straight* = 0x00000685
+    XK_Cyrillic_u_straight* = 0x00000695
+    XKc_Cyrillic_U_straight_bar* = 0x00000686
+    XK_Cyrillic_u_straight_bar* = 0x00000696
+    XKc_Cyrillic_HA_descender* = 0x00000687
+    XK_Cyrillic_ha_descender* = 0x00000697
+    XKc_Cyrillic_CHE_descender* = 0x00000688
+    XK_Cyrillic_che_descender* = 0x00000698
+    XKc_Cyrillic_CHE_vertstroke* = 0x00000689
+    XK_Cyrillic_che_vertstroke* = 0x00000699
+    XKc_Cyrillic_SHHA* = 0x0000068A
+    XK_Cyrillic_shha* = 0x0000069A
+    XKc_Cyrillic_SCHWA* = 0x0000068C
+    XK_Cyrillic_schwa* = 0x0000069C
+    XKc_Cyrillic_I_macron* = 0x0000068D
+    XK_Cyrillic_i_macron* = 0x0000069D
+    XKc_Cyrillic_O_bar* = 0x0000068E
+    XK_Cyrillic_o_bar* = 0x0000069E
+    XKc_Cyrillic_U_macron* = 0x0000068F
+    XK_Cyrillic_u_macron* = 0x0000069F
+    XK_Serbian_dje* = 0x000006A1
+    XK_Macedonia_gje* = 0x000006A2
+    XK_Cyrillic_io* = 0x000006A3
+    XK_Ukrainian_ie* = 0x000006A4
+    XK_Ukranian_je* = 0x000006A4 # deprecated 
+    XK_Macedonia_dse* = 0x000006A5
+    XK_Ukrainian_i* = 0x000006A6
+    XK_Ukranian_i* = 0x000006A6 # deprecated 
+    XK_Ukrainian_yi* = 0x000006A7
+    XK_Ukranian_yi* = 0x000006A7 # deprecated 
+    XK_Cyrillic_je* = 0x000006A8
+    XK_Serbian_je* = 0x000006A8 # deprecated 
+    XK_Cyrillic_lje* = 0x000006A9
+    XK_Serbian_lje* = 0x000006A9 # deprecated 
+    XK_Cyrillic_nje* = 0x000006AA
+    XK_Serbian_nje* = 0x000006AA # deprecated 
+    XK_Serbian_tshe* = 0x000006AB
+    XK_Macedonia_kje* = 0x000006AC
+    XK_Ukrainian_ghe_with_upturn* = 0x000006AD
+    XK_Byelorussian_shortu* = 0x000006AE
+    XK_Cyrillic_dzhe* = 0x000006AF
+    XK_Serbian_dze* = 0x000006AF # deprecated 
+    XK_numerosign* = 0x000006B0
+    XKc_Serbian_DJE* = 0x000006B1
+    XKc_Macedonia_GJE* = 0x000006B2
+    XKc_Cyrillic_IO* = 0x000006B3
+    XKc_Ukrainian_IE* = 0x000006B4
+    XKc_Ukranian_JE* = 0x000006B4 # deprecated 
+    XKc_Macedonia_DSE* = 0x000006B5
+    XKc_Ukrainian_I* = 0x000006B6
+    XKc_Ukranian_I* = 0x000006B6 # deprecated 
+    XKc_Ukrainian_YI* = 0x000006B7
+    XKc_Ukranian_YI* = 0x000006B7 # deprecated 
+    XKc_Cyrillic_JE* = 0x000006B8
+    XKc_Serbian_JE* = 0x000006B8 # deprecated 
+    XKc_Cyrillic_LJE* = 0x000006B9
+    XKc_Serbian_LJE* = 0x000006B9 # deprecated 
+    XKc_Cyrillic_NJE* = 0x000006BA
+    XKc_Serbian_NJE* = 0x000006BA # deprecated 
+    XKc_Serbian_TSHE* = 0x000006BB
+    XKc_Macedonia_KJE* = 0x000006BC
+    XKc_Ukrainian_GHE_WITH_UPTURN* = 0x000006BD
+    XKc_Byelorussian_SHORTU* = 0x000006BE
+    XKc_Cyrillic_DZHE* = 0x000006BF
+    XKc_Serbian_DZE* = 0x000006BF # deprecated 
+    XK_Cyrillic_yu* = 0x000006C0
+    XK_Cyrillic_a* = 0x000006C1
+    XK_Cyrillic_be* = 0x000006C2
+    XK_Cyrillic_tse* = 0x000006C3
+    XK_Cyrillic_de* = 0x000006C4
+    XK_Cyrillic_ie* = 0x000006C5
+    XK_Cyrillic_ef* = 0x000006C6
+    XK_Cyrillic_ghe* = 0x000006C7
+    XK_Cyrillic_ha* = 0x000006C8
+    XK_Cyrillic_i* = 0x000006C9
+    XK_Cyrillic_shorti* = 0x000006CA
+    XK_Cyrillic_ka* = 0x000006CB
+    XK_Cyrillic_el* = 0x000006CC
+    XK_Cyrillic_em* = 0x000006CD
+    XK_Cyrillic_en* = 0x000006CE
+    XK_Cyrillic_o* = 0x000006CF
+    XK_Cyrillic_pe* = 0x000006D0
+    XK_Cyrillic_ya* = 0x000006D1
+    XK_Cyrillic_er* = 0x000006D2
+    XK_Cyrillic_es* = 0x000006D3
+    XK_Cyrillic_te* = 0x000006D4
+    XK_Cyrillic_u* = 0x000006D5
+    XK_Cyrillic_zhe* = 0x000006D6
+    XK_Cyrillic_ve* = 0x000006D7
+    XK_Cyrillic_softsign* = 0x000006D8
+    XK_Cyrillic_yeru* = 0x000006D9
+    XK_Cyrillic_ze* = 0x000006DA
+    XK_Cyrillic_sha* = 0x000006DB
+    XK_Cyrillic_e* = 0x000006DC
+    XK_Cyrillic_shcha* = 0x000006DD
+    XK_Cyrillic_che* = 0x000006DE
+    XK_Cyrillic_hardsign* = 0x000006DF
+    XKc_Cyrillic_YU* = 0x000006E0
+    XKc_Cyrillic_A* = 0x000006E1
+    XKc_Cyrillic_BE* = 0x000006E2
+    XKc_Cyrillic_TSE* = 0x000006E3
+    XKc_Cyrillic_DE* = 0x000006E4
+    XKc_Cyrillic_IE* = 0x000006E5
+    XKc_Cyrillic_EF* = 0x000006E6
+    XKc_Cyrillic_GHE* = 0x000006E7
+    XKc_Cyrillic_HA* = 0x000006E8
+    XKc_Cyrillic_I* = 0x000006E9
+    XKc_Cyrillic_SHORTI* = 0x000006EA
+    XKc_Cyrillic_KA* = 0x000006EB
+    XKc_Cyrillic_EL* = 0x000006EC
+    XKc_Cyrillic_EM* = 0x000006ED
+    XKc_Cyrillic_EN* = 0x000006EE
+    XKc_Cyrillic_O* = 0x000006EF
+    XKc_Cyrillic_PE* = 0x000006F0
+    XKc_Cyrillic_YA* = 0x000006F1
+    XKc_Cyrillic_ER* = 0x000006F2
+    XKc_Cyrillic_ES* = 0x000006F3
+    XKc_Cyrillic_TE* = 0x000006F4
+    XKc_Cyrillic_U* = 0x000006F5
+    XKc_Cyrillic_ZHE* = 0x000006F6
+    XKc_Cyrillic_VE* = 0x000006F7
+    XKc_Cyrillic_SOFTSIGN* = 0x000006F8
+    XKc_Cyrillic_YERU* = 0x000006F9
+    XKc_Cyrillic_ZE* = 0x000006FA
+    XKc_Cyrillic_SHA* = 0x000006FB
+    XKc_Cyrillic_E* = 0x000006FC
+    XKc_Cyrillic_SHCHA* = 0x000006FD
+    XKc_Cyrillic_CHE* = 0x000006FE
+    XKc_Cyrillic_HARDSIGN* = 0x000006FF
+# XK_CYRILLIC 
+#*
+# * Greek
+# * Byte 3 = 7
+# *
+
+when defined(XK_GREEK) or true: 
+  const
+    XKc_Greek_ALPHAaccent* = 0x000007A1
+    XKc_Greek_EPSILONaccent* = 0x000007A2
+    XKc_Greek_ETAaccent* = 0x000007A3
+    XKc_Greek_IOTAaccent* = 0x000007A4
+    XKc_Greek_IOTAdieresis* = 0x000007A5
+    XKc_Greek_IOTAdiaeresis* = XKc_Greek_IOTAdieresis # old typo 
+    XKc_Greek_OMICRONaccent* = 0x000007A7
+    XKc_Greek_UPSILONaccent* = 0x000007A8
+    XKc_Greek_UPSILONdieresis* = 0x000007A9
+    XKc_Greek_OMEGAaccent* = 0x000007AB
+    XK_Greek_accentdieresis* = 0x000007AE
+    XK_Greek_horizbar* = 0x000007AF
+    XK_Greek_alphaaccent* = 0x000007B1
+    XK_Greek_epsilonaccent* = 0x000007B2
+    XK_Greek_etaaccent* = 0x000007B3
+    XK_Greek_iotaaccent* = 0x000007B4
+    XK_Greek_iotadieresis* = 0x000007B5
+    XK_Greek_iotaaccentdieresis* = 0x000007B6
+    XK_Greek_omicronaccent* = 0x000007B7
+    XK_Greek_upsilonaccent* = 0x000007B8
+    XK_Greek_upsilondieresis* = 0x000007B9
+    XK_Greek_upsilonaccentdieresis* = 0x000007BA
+    XK_Greek_omegaaccent* = 0x000007BB
+    XKc_Greek_ALPHA* = 0x000007C1
+    XKc_Greek_BETA* = 0x000007C2
+    XKc_Greek_GAMMA* = 0x000007C3
+    XKc_Greek_DELTA* = 0x000007C4
+    XKc_Greek_EPSILON* = 0x000007C5
+    XKc_Greek_ZETA* = 0x000007C6
+    XKc_Greek_ETA* = 0x000007C7
+    XKc_Greek_THETA* = 0x000007C8
+    XKc_Greek_IOTA* = 0x000007C9
+    XKc_Greek_KAPPA* = 0x000007CA
+    XKc_Greek_LAMDA* = 0x000007CB
+    XKc_Greek_LAMBDA* = 0x000007CB
+    XKc_Greek_MU* = 0x000007CC
+    XKc_Greek_NU* = 0x000007CD
+    XKc_Greek_XI* = 0x000007CE
+    XKc_Greek_OMICRON* = 0x000007CF
+    XKc_Greek_PI* = 0x000007D0
+    XKc_Greek_RHO* = 0x000007D1
+    XKc_Greek_SIGMA* = 0x000007D2
+    XKc_Greek_TAU* = 0x000007D4
+    XKc_Greek_UPSILON* = 0x000007D5
+    XKc_Greek_PHI* = 0x000007D6
+    XKc_Greek_CHI* = 0x000007D7
+    XKc_Greek_PSI* = 0x000007D8
+    XKc_Greek_OMEGA* = 0x000007D9
+    XK_Greek_alpha* = 0x000007E1
+    XK_Greek_beta* = 0x000007E2
+    XK_Greek_gamma* = 0x000007E3
+    XK_Greek_delta* = 0x000007E4
+    XK_Greek_epsilon* = 0x000007E5
+    XK_Greek_zeta* = 0x000007E6
+    XK_Greek_eta* = 0x000007E7
+    XK_Greek_theta* = 0x000007E8
+    XK_Greek_iota* = 0x000007E9
+    XK_Greek_kappa* = 0x000007EA
+    XK_Greek_lamda* = 0x000007EB
+    XK_Greek_lambda* = 0x000007EB
+    XK_Greek_mu* = 0x000007EC
+    XK_Greek_nu* = 0x000007ED
+    XK_Greek_xi* = 0x000007EE
+    XK_Greek_omicron* = 0x000007EF
+    XK_Greek_pi* = 0x000007F0
+    XK_Greek_rho* = 0x000007F1
+    XK_Greek_sigma* = 0x000007F2
+    XK_Greek_finalsmallsigma* = 0x000007F3
+    XK_Greek_tau* = 0x000007F4
+    XK_Greek_upsilon* = 0x000007F5
+    XK_Greek_phi* = 0x000007F6
+    XK_Greek_chi* = 0x000007F7
+    XK_Greek_psi* = 0x000007F8
+    XK_Greek_omega* = 0x000007F9
+    XK_Greek_switch* = 0x0000FF7E # Alias for mode_switch 
+# XK_GREEK 
+#*
+# * Technical
+# * Byte 3 = 8
+# *
+
+when defined(XK_TECHNICAL) or true: 
+  const
+    XK_leftradical* = 0x000008A1
+    XK_topleftradical* = 0x000008A2
+    XK_horizconnector* = 0x000008A3
+    XK_topintegral* = 0x000008A4
+    XK_botintegral* = 0x000008A5
+    XK_vertconnector* = 0x000008A6
+    XK_topleftsqbracket* = 0x000008A7
+    XK_botleftsqbracket* = 0x000008A8
+    XK_toprightsqbracket* = 0x000008A9
+    XK_botrightsqbracket* = 0x000008AA
+    XK_topleftparens* = 0x000008AB
+    XK_botleftparens* = 0x000008AC
+    XK_toprightparens* = 0x000008AD
+    XK_botrightparens* = 0x000008AE
+    XK_leftmiddlecurlybrace* = 0x000008AF
+    XK_rightmiddlecurlybrace* = 0x000008B0
+    XK_topleftsummation* = 0x000008B1
+    XK_botleftsummation* = 0x000008B2
+    XK_topvertsummationconnector* = 0x000008B3
+    XK_botvertsummationconnector* = 0x000008B4
+    XK_toprightsummation* = 0x000008B5
+    XK_botrightsummation* = 0x000008B6
+    XK_rightmiddlesummation* = 0x000008B7
+    XK_lessthanequal* = 0x000008BC
+    XK_notequal* = 0x000008BD
+    XK_greaterthanequal* = 0x000008BE
+    XK_integral* = 0x000008BF
+    XK_therefore* = 0x000008C0
+    XK_variation* = 0x000008C1
+    XK_infinity* = 0x000008C2
+    XK_nabla* = 0x000008C5
+    XK_approximate* = 0x000008C8
+    XK_similarequal* = 0x000008C9
+    XK_ifonlyif* = 0x000008CD
+    XK_implies* = 0x000008CE
+    XK_identical* = 0x000008CF
+    XK_radical* = 0x000008D6
+    XK_includedin* = 0x000008DA
+    XK_includes* = 0x000008DB
+    XK_intersection* = 0x000008DC
+    XK_union* = 0x000008DD
+    XK_logicaland* = 0x000008DE
+    XK_logicalor* = 0x000008DF
+    XK_partialderivative* = 0x000008EF
+    XK_function* = 0x000008F6
+    XK_leftarrow* = 0x000008FB
+    XK_uparrow* = 0x000008FC
+    XK_rightarrow* = 0x000008FD
+    XK_downarrow* = 0x000008FE
+# XK_TECHNICAL 
+#*
+# *  Special
+# *  Byte 3 = 9
+# *
+
+when defined(XK_SPECIAL): 
+  const
+    XK_blank* = 0x000009DF
+    XK_soliddiamond* = 0x000009E0
+    XK_checkerboard* = 0x000009E1
+    XK_ht* = 0x000009E2
+    XK_ff* = 0x000009E3
+    XK_cr* = 0x000009E4
+    XK_lf* = 0x000009E5
+    XK_nl* = 0x000009E8
+    XK_vt* = 0x000009E9
+    XK_lowrightcorner* = 0x000009EA
+    XK_uprightcorner* = 0x000009EB
+    XK_upleftcorner* = 0x000009EC
+    XK_lowleftcorner* = 0x000009ED
+    XK_crossinglines* = 0x000009EE
+    XK_horizlinescan1* = 0x000009EF
+    XK_horizlinescan3* = 0x000009F0
+    XK_horizlinescan5* = 0x000009F1
+    XK_horizlinescan7* = 0x000009F2
+    XK_horizlinescan9* = 0x000009F3
+    XK_leftt* = 0x000009F4
+    XK_rightt* = 0x000009F5
+    XK_bott* = 0x000009F6
+    XK_topt* = 0x000009F7
+    XK_vertbar* = 0x000009F8
+# XK_SPECIAL 
+#*
+# *  Publishing
+# *  Byte 3 = a
+# *
+
+when defined(XK_PUBLISHING) or true: 
+  const
+    XK_emspace* = 0x00000AA1
+    XK_enspace* = 0x00000AA2
+    XK_em3space* = 0x00000AA3
+    XK_em4space* = 0x00000AA4
+    XK_digitspace* = 0x00000AA5
+    XK_punctspace* = 0x00000AA6
+    XK_thinspace* = 0x00000AA7
+    XK_hairspace* = 0x00000AA8
+    XK_emdash* = 0x00000AA9
+    XK_endash* = 0x00000AAA
+    XK_signifblank* = 0x00000AAC
+    XK_ellipsis* = 0x00000AAE
+    XK_doubbaselinedot* = 0x00000AAF
+    XK_onethird* = 0x00000AB0
+    XK_twothirds* = 0x00000AB1
+    XK_onefifth* = 0x00000AB2
+    XK_twofifths* = 0x00000AB3
+    XK_threefifths* = 0x00000AB4
+    XK_fourfifths* = 0x00000AB5
+    XK_onesixth* = 0x00000AB6
+    XK_fivesixths* = 0x00000AB7
+    XK_careof* = 0x00000AB8
+    XK_figdash* = 0x00000ABB
+    XK_leftanglebracket* = 0x00000ABC
+    XK_decimalpoint* = 0x00000ABD
+    XK_rightanglebracket* = 0x00000ABE
+    XK_marker* = 0x00000ABF
+    XK_oneeighth* = 0x00000AC3
+    XK_threeeighths* = 0x00000AC4
+    XK_fiveeighths* = 0x00000AC5
+    XK_seveneighths* = 0x00000AC6
+    XK_trademark* = 0x00000AC9
+    XK_signaturemark* = 0x00000ACA
+    XK_trademarkincircle* = 0x00000ACB
+    XK_leftopentriangle* = 0x00000ACC
+    XK_rightopentriangle* = 0x00000ACD
+    XK_emopencircle* = 0x00000ACE
+    XK_emopenrectangle* = 0x00000ACF
+    XK_leftsinglequotemark* = 0x00000AD0
+    XK_rightsinglequotemark* = 0x00000AD1
+    XK_leftdoublequotemark* = 0x00000AD2
+    XK_rightdoublequotemark* = 0x00000AD3
+    XK_prescription* = 0x00000AD4
+    XK_minutes* = 0x00000AD6
+    XK_seconds* = 0x00000AD7
+    XK_latincross* = 0x00000AD9
+    XK_hexagram* = 0x00000ADA
+    XK_filledrectbullet* = 0x00000ADB
+    XK_filledlefttribullet* = 0x00000ADC
+    XK_filledrighttribullet* = 0x00000ADD
+    XK_emfilledcircle* = 0x00000ADE
+    XK_emfilledrect* = 0x00000ADF
+    XK_enopencircbullet* = 0x00000AE0
+    XK_enopensquarebullet* = 0x00000AE1
+    XK_openrectbullet* = 0x00000AE2
+    XK_opentribulletup* = 0x00000AE3
+    XK_opentribulletdown* = 0x00000AE4
+    XK_openstar* = 0x00000AE5
+    XK_enfilledcircbullet* = 0x00000AE6
+    XK_enfilledsqbullet* = 0x00000AE7
+    XK_filledtribulletup* = 0x00000AE8
+    XK_filledtribulletdown* = 0x00000AE9
+    XK_leftpointer* = 0x00000AEA
+    XK_rightpointer* = 0x00000AEB
+    XK_club* = 0x00000AEC
+    XK_diamond* = 0x00000AED
+    XK_heart* = 0x00000AEE
+    XK_maltesecross* = 0x00000AF0
+    XK_dagger* = 0x00000AF1
+    XK_doubledagger* = 0x00000AF2
+    XK_checkmark* = 0x00000AF3
+    XK_ballotcross* = 0x00000AF4
+    XK_musicalsharp* = 0x00000AF5
+    XK_musicalflat* = 0x00000AF6
+    XK_malesymbol* = 0x00000AF7
+    XK_femalesymbol* = 0x00000AF8
+    XK_telephone* = 0x00000AF9
+    XK_telephonerecorder* = 0x00000AFA
+    XK_phonographcopyright* = 0x00000AFB
+    XK_caret* = 0x00000AFC
+    XK_singlelowquotemark* = 0x00000AFD
+    XK_doublelowquotemark* = 0x00000AFE
+    XK_cursor* = 0x00000AFF
+# XK_PUBLISHING 
+#*
+# *  APL
+# *  Byte 3 = b
+# *
+
+when defined(XK_APL) or true: 
+  const
+    XK_leftcaret* = 0x00000BA3
+    XK_rightcaret* = 0x00000BA6
+    XK_downcaret* = 0x00000BA8
+    XK_upcaret* = 0x00000BA9
+    XK_overbar* = 0x00000BC0
+    XK_downtack* = 0x00000BC2
+    XK_upshoe* = 0x00000BC3
+    XK_downstile* = 0x00000BC4
+    XK_underbar* = 0x00000BC6
+    XK_jot* = 0x00000BCA
+    XK_quad* = 0x00000BCC
+    XK_uptack* = 0x00000BCE
+    XK_circle* = 0x00000BCF
+    XK_upstile* = 0x00000BD3
+    XK_downshoe* = 0x00000BD6
+    XK_rightshoe* = 0x00000BD8
+    XK_leftshoe* = 0x00000BDA
+    XK_lefttack* = 0x00000BDC
+    XK_righttack* = 0x00000BFC
+# XK_APL 
+#*
+# * Hebrew
+# * Byte 3 = c
+# *
+
+when defined(XK_HEBREW) or true: 
+  const
+    XK_hebrew_doublelowline* = 0x00000CDF
+    XK_hebrew_aleph* = 0x00000CE0
+    XK_hebrew_bet* = 0x00000CE1
+    XK_hebrew_beth* = 0x00000CE1 # deprecated 
+    XK_hebrew_gimel* = 0x00000CE2
+    XK_hebrew_gimmel* = 0x00000CE2 # deprecated 
+    XK_hebrew_dalet* = 0x00000CE3
+    XK_hebrew_daleth* = 0x00000CE3 # deprecated 
+    XK_hebrew_he* = 0x00000CE4
+    XK_hebrew_waw* = 0x00000CE5
+    XK_hebrew_zain* = 0x00000CE6
+    XK_hebrew_zayin* = 0x00000CE6 # deprecated 
+    XK_hebrew_chet* = 0x00000CE7
+    XK_hebrew_het* = 0x00000CE7 # deprecated 
+    XK_hebrew_tet* = 0x00000CE8
+    XK_hebrew_teth* = 0x00000CE8 # deprecated 
+    XK_hebrew_yod* = 0x00000CE9
+    XK_hebrew_finalkaph* = 0x00000CEA
+    XK_hebrew_kaph* = 0x00000CEB
+    XK_hebrew_lamed* = 0x00000CEC
+    XK_hebrew_finalmem* = 0x00000CED
+    XK_hebrew_mem* = 0x00000CEE
+    XK_hebrew_finalnun* = 0x00000CEF
+    XK_hebrew_nun* = 0x00000CF0
+    XK_hebrew_samech* = 0x00000CF1
+    XK_hebrew_samekh* = 0x00000CF1 # deprecated 
+    XK_hebrew_ayin* = 0x00000CF2
+    XK_hebrew_finalpe* = 0x00000CF3
+    XK_hebrew_pe* = 0x00000CF4
+    XK_hebrew_finalzade* = 0x00000CF5
+    XK_hebrew_finalzadi* = 0x00000CF5 # deprecated 
+    XK_hebrew_zade* = 0x00000CF6
+    XK_hebrew_zadi* = 0x00000CF6 # deprecated 
+    XK_hebrew_qoph* = 0x00000CF7
+    XK_hebrew_kuf* = 0x00000CF7 # deprecated 
+    XK_hebrew_resh* = 0x00000CF8
+    XK_hebrew_shin* = 0x00000CF9
+    XK_hebrew_taw* = 0x00000CFA
+    XK_hebrew_taf* = 0x00000CFA # deprecated 
+    XK_Hebrew_switch* = 0x0000FF7E # Alias for mode_switch 
+# XK_HEBREW 
+#*
+# * Thai
+# * Byte 3 = d
+# *
+
+when defined(XK_THAI) or true: 
+  const
+    XK_Thai_kokai* = 0x00000DA1
+    XK_Thai_khokhai* = 0x00000DA2
+    XK_Thai_khokhuat* = 0x00000DA3
+    XK_Thai_khokhwai* = 0x00000DA4
+    XK_Thai_khokhon* = 0x00000DA5
+    XK_Thai_khorakhang* = 0x00000DA6
+    XK_Thai_ngongu* = 0x00000DA7
+    XK_Thai_chochan* = 0x00000DA8
+    XK_Thai_choching* = 0x00000DA9
+    XK_Thai_chochang* = 0x00000DAA
+    XK_Thai_soso* = 0x00000DAB
+    XK_Thai_chochoe* = 0x00000DAC
+    XK_Thai_yoying* = 0x00000DAD
+    XK_Thai_dochada* = 0x00000DAE
+    XK_Thai_topatak* = 0x00000DAF
+    XK_Thai_thothan* = 0x00000DB0
+    XK_Thai_thonangmontho* = 0x00000DB1
+    XK_Thai_thophuthao* = 0x00000DB2
+    XK_Thai_nonen* = 0x00000DB3
+    XK_Thai_dodek* = 0x00000DB4
+    XK_Thai_totao* = 0x00000DB5
+    XK_Thai_thothung* = 0x00000DB6
+    XK_Thai_thothahan* = 0x00000DB7
+    XK_Thai_thothong* = 0x00000DB8
+    XK_Thai_nonu* = 0x00000DB9
+    XK_Thai_bobaimai* = 0x00000DBA
+    XK_Thai_popla* = 0x00000DBB
+    XK_Thai_phophung* = 0x00000DBC
+    XK_Thai_fofa* = 0x00000DBD
+    XK_Thai_phophan* = 0x00000DBE
+    XK_Thai_fofan* = 0x00000DBF
+    XK_Thai_phosamphao* = 0x00000DC0
+    XK_Thai_moma* = 0x00000DC1
+    XK_Thai_yoyak* = 0x00000DC2
+    XK_Thai_rorua* = 0x00000DC3
+    XK_Thai_ru* = 0x00000DC4
+    XK_Thai_loling* = 0x00000DC5
+    XK_Thai_lu* = 0x00000DC6
+    XK_Thai_wowaen* = 0x00000DC7
+    XK_Thai_sosala* = 0x00000DC8
+    XK_Thai_sorusi* = 0x00000DC9
+    XK_Thai_sosua* = 0x00000DCA
+    XK_Thai_hohip* = 0x00000DCB
+    XK_Thai_lochula* = 0x00000DCC
+    XK_Thai_oang* = 0x00000DCD
+    XK_Thai_honokhuk* = 0x00000DCE
+    XK_Thai_paiyannoi* = 0x00000DCF
+    XK_Thai_saraa* = 0x00000DD0
+    XK_Thai_maihanakat* = 0x00000DD1
+    XK_Thai_saraaa* = 0x00000DD2
+    XK_Thai_saraam* = 0x00000DD3
+    XK_Thai_sarai* = 0x00000DD4
+    XK_Thai_saraii* = 0x00000DD5
+    XK_Thai_saraue* = 0x00000DD6
+    XK_Thai_sarauee* = 0x00000DD7
+    XK_Thai_sarau* = 0x00000DD8
+    XK_Thai_sarauu* = 0x00000DD9
+    XK_Thai_phinthu* = 0x00000DDA
+    XK_Thai_maihanakat_maitho* = 0x00000DDE
+    XK_Thai_baht* = 0x00000DDF
+    XK_Thai_sarae* = 0x00000DE0
+    XK_Thai_saraae* = 0x00000DE1
+    XK_Thai_sarao* = 0x00000DE2
+    XK_Thai_saraaimaimuan* = 0x00000DE3
+    XK_Thai_saraaimaimalai* = 0x00000DE4
+    XK_Thai_lakkhangyao* = 0x00000DE5
+    XK_Thai_maiyamok* = 0x00000DE6
+    XK_Thai_maitaikhu* = 0x00000DE7
+    XK_Thai_maiek* = 0x00000DE8
+    XK_Thai_maitho* = 0x00000DE9
+    XK_Thai_maitri* = 0x00000DEA
+    XK_Thai_maichattawa* = 0x00000DEB
+    XK_Thai_thanthakhat* = 0x00000DEC
+    XK_Thai_nikhahit* = 0x00000DED
+    XK_Thai_leksun* = 0x00000DF0
+    XK_Thai_leknung* = 0x00000DF1
+    XK_Thai_leksong* = 0x00000DF2
+    XK_Thai_leksam* = 0x00000DF3
+    XK_Thai_leksi* = 0x00000DF4
+    XK_Thai_lekha* = 0x00000DF5
+    XK_Thai_lekhok* = 0x00000DF6
+    XK_Thai_lekchet* = 0x00000DF7
+    XK_Thai_lekpaet* = 0x00000DF8
+    XK_Thai_lekkao* = 0x00000DF9
+# XK_THAI 
+#*
+# *   Korean
+# *   Byte 3 = e
+# *
+
+when defined(XK_KOREAN) or true: 
+  const
+    XK_Hangul* = 0x0000FF31     # Hangul start/stop(toggle) 
+    XK_Hangul_Start* = 0x0000FF32 # Hangul start 
+    XK_Hangul_End* = 0x0000FF33 # Hangul end, English start 
+    XK_Hangul_Hanja* = 0x0000FF34 # Start Hangul->Hanja Conversion 
+    XK_Hangul_Jamo* = 0x0000FF35 # Hangul Jamo mode 
+    XK_Hangul_Romaja* = 0x0000FF36 # Hangul Romaja mode 
+    XK_Hangul_Codeinput* = 0x0000FF37 # Hangul code input mode 
+    XK_Hangul_Jeonja* = 0x0000FF38 # Jeonja mode 
+    XK_Hangul_Banja* = 0x0000FF39 # Banja mode 
+    XK_Hangul_PreHanja* = 0x0000FF3A # Pre Hanja conversion 
+    XK_Hangul_PostHanja* = 0x0000FF3B # Post Hanja conversion 
+    XK_Hangul_SingleCandidate* = 0x0000FF3C # Single candidate 
+    XK_Hangul_MultipleCandidate* = 0x0000FF3D # Multiple candidate 
+    XK_Hangul_PreviousCandidate* = 0x0000FF3E # Previous candidate 
+    XK_Hangul_Special* = 0x0000FF3F # Special symbols 
+    XK_Hangul_switch* = 0x0000FF7E # Alias for mode_switch 
+                                   # Hangul Consonant Characters 
+    XK_Hangul_Kiyeog* = 0x00000EA1
+    XK_Hangul_SsangKiyeog* = 0x00000EA2
+    XK_Hangul_KiyeogSios* = 0x00000EA3
+    XK_Hangul_Nieun* = 0x00000EA4
+    XK_Hangul_NieunJieuj* = 0x00000EA5
+    XK_Hangul_NieunHieuh* = 0x00000EA6
+    XK_Hangul_Dikeud* = 0x00000EA7
+    XK_Hangul_SsangDikeud* = 0x00000EA8
+    XK_Hangul_Rieul* = 0x00000EA9
+    XK_Hangul_RieulKiyeog* = 0x00000EAA
+    XK_Hangul_RieulMieum* = 0x00000EAB
+    XK_Hangul_RieulPieub* = 0x00000EAC
+    XK_Hangul_RieulSios* = 0x00000EAD
+    XK_Hangul_RieulTieut* = 0x00000EAE
+    XK_Hangul_RieulPhieuf* = 0x00000EAF
+    XK_Hangul_RieulHieuh* = 0x00000EB0
+    XK_Hangul_Mieum* = 0x00000EB1
+    XK_Hangul_Pieub* = 0x00000EB2
+    XK_Hangul_SsangPieub* = 0x00000EB3
+    XK_Hangul_PieubSios* = 0x00000EB4
+    XK_Hangul_Sios* = 0x00000EB5
+    XK_Hangul_SsangSios* = 0x00000EB6
+    XK_Hangul_Ieung* = 0x00000EB7
+    XK_Hangul_Jieuj* = 0x00000EB8
+    XK_Hangul_SsangJieuj* = 0x00000EB9
+    XK_Hangul_Cieuc* = 0x00000EBA
+    XK_Hangul_Khieuq* = 0x00000EBB
+    XK_Hangul_Tieut* = 0x00000EBC
+    XK_Hangul_Phieuf* = 0x00000EBD
+    XK_Hangul_Hieuh* = 0x00000EBE # Hangul Vowel Characters 
+    XK_Hangul_A* = 0x00000EBF
+    XK_Hangul_AE* = 0x00000EC0
+    XK_Hangul_YA* = 0x00000EC1
+    XK_Hangul_YAE* = 0x00000EC2
+    XK_Hangul_EO* = 0x00000EC3
+    XK_Hangul_E* = 0x00000EC4
+    XK_Hangul_YEO* = 0x00000EC5
+    XK_Hangul_YE* = 0x00000EC6
+    XK_Hangul_O* = 0x00000EC7
+    XK_Hangul_WA* = 0x00000EC8
+    XK_Hangul_WAE* = 0x00000EC9
+    XK_Hangul_OE* = 0x00000ECA
+    XK_Hangul_YO* = 0x00000ECB
+    XK_Hangul_U* = 0x00000ECC
+    XK_Hangul_WEO* = 0x00000ECD
+    XK_Hangul_WE* = 0x00000ECE
+    XK_Hangul_WI* = 0x00000ECF
+    XK_Hangul_YU* = 0x00000ED0
+    XK_Hangul_EU* = 0x00000ED1
+    XK_Hangul_YI* = 0x00000ED2
+    XK_Hangul_I* = 0x00000ED3   # Hangul syllable-final (JongSeong) Characters 
+    XK_Hangul_J_Kiyeog* = 0x00000ED4
+    XK_Hangul_J_SsangKiyeog* = 0x00000ED5
+    XK_Hangul_J_KiyeogSios* = 0x00000ED6
+    XK_Hangul_J_Nieun* = 0x00000ED7
+    XK_Hangul_J_NieunJieuj* = 0x00000ED8
+    XK_Hangul_J_NieunHieuh* = 0x00000ED9
+    XK_Hangul_J_Dikeud* = 0x00000EDA
+    XK_Hangul_J_Rieul* = 0x00000EDB
+    XK_Hangul_J_RieulKiyeog* = 0x00000EDC
+    XK_Hangul_J_RieulMieum* = 0x00000EDD
+    XK_Hangul_J_RieulPieub* = 0x00000EDE
+    XK_Hangul_J_RieulSios* = 0x00000EDF
+    XK_Hangul_J_RieulTieut* = 0x00000EE0
+    XK_Hangul_J_RieulPhieuf* = 0x00000EE1
+    XK_Hangul_J_RieulHieuh* = 0x00000EE2
+    XK_Hangul_J_Mieum* = 0x00000EE3
+    XK_Hangul_J_Pieub* = 0x00000EE4
+    XK_Hangul_J_PieubSios* = 0x00000EE5
+    XK_Hangul_J_Sios* = 0x00000EE6
+    XK_Hangul_J_SsangSios* = 0x00000EE7
+    XK_Hangul_J_Ieung* = 0x00000EE8
+    XK_Hangul_J_Jieuj* = 0x00000EE9
+    XK_Hangul_J_Cieuc* = 0x00000EEA
+    XK_Hangul_J_Khieuq* = 0x00000EEB
+    XK_Hangul_J_Tieut* = 0x00000EEC
+    XK_Hangul_J_Phieuf* = 0x00000EED
+    XK_Hangul_J_Hieuh* = 0x00000EEE # Ancient Hangul Consonant Characters 
+    XK_Hangul_RieulYeorinHieuh* = 0x00000EEF
+    XK_Hangul_SunkyeongeumMieum* = 0x00000EF0
+    XK_Hangul_SunkyeongeumPieub* = 0x00000EF1
+    XK_Hangul_PanSios* = 0x00000EF2
+    XK_Hangul_KkogjiDalrinIeung* = 0x00000EF3
+    XK_Hangul_SunkyeongeumPhieuf* = 0x00000EF4
+    XK_Hangul_YeorinHieuh* = 0x00000EF5 # Ancient Hangul Vowel Characters 
+    XK_Hangul_AraeA* = 0x00000EF6
+    XK_Hangul_AraeAE* = 0x00000EF7 # Ancient Hangul syllable-final (JongSeong) Characters 
+    XK_Hangul_J_PanSios* = 0x00000EF8
+    XK_Hangul_J_KkogjiDalrinIeung* = 0x00000EF9
+    XK_Hangul_J_YeorinHieuh* = 0x00000EFA # Korean currency symbol 
+    XK_Korean_Won* = 0x00000EFF
+# XK_KOREAN 
+#*
+# *   Armenian
+# *   Byte 3 = = $14
+# *
+
+when defined(XK_ARMENIAN) or true: 
+  const
+    XK_Armenian_eternity* = 0x000014A1
+    XK_Armenian_ligature_ew* = 0x000014A2
+    XK_Armenian_full_stop* = 0x000014A3
+    XK_Armenian_verjaket* = 0x000014A3
+    XK_Armenian_parenright* = 0x000014A4
+    XK_Armenian_parenleft* = 0x000014A5
+    XK_Armenian_guillemotright* = 0x000014A6
+    XK_Armenian_guillemotleft* = 0x000014A7
+    XK_Armenian_em_dash* = 0x000014A8
+    XK_Armenian_dot* = 0x000014A9
+    XK_Armenian_mijaket* = 0x000014A9
+    XK_Armenian_separation_mark* = 0x000014AA
+    XK_Armenian_but* = 0x000014AA
+    XK_Armenian_comma* = 0x000014AB
+    XK_Armenian_en_dash* = 0x000014AC
+    XK_Armenian_hyphen* = 0x000014AD
+    XK_Armenian_yentamna* = 0x000014AD
+    XK_Armenian_ellipsis* = 0x000014AE
+    XK_Armenian_exclam* = 0x000014AF
+    XK_Armenian_amanak* = 0x000014AF
+    XK_Armenian_accent* = 0x000014B0
+    XK_Armenian_shesht* = 0x000014B0
+    XK_Armenian_question* = 0x000014B1
+    XK_Armenian_paruyk* = 0x000014B1
+    XKc_Armenian_AYB* = 0x000014B2
+    XK_Armenian_ayb* = 0x000014B3
+    XKc_Armenian_BEN* = 0x000014B4
+    XK_Armenian_ben* = 0x000014B5
+    XKc_Armenian_GIM* = 0x000014B6
+    XK_Armenian_gim* = 0x000014B7
+    XKc_Armenian_DA* = 0x000014B8
+    XK_Armenian_da* = 0x000014B9
+    XKc_Armenian_YECH* = 0x000014BA
+    XK_Armenian_yech* = 0x000014BB
+    XKc_Armenian_ZA* = 0x000014BC
+    XK_Armenian_za* = 0x000014BD
+    XKc_Armenian_E* = 0x000014BE
+    XK_Armenian_e* = 0x000014BF
+    XKc_Armenian_AT* = 0x000014C0
+    XK_Armenian_at* = 0x000014C1
+    XKc_Armenian_TO* = 0x000014C2
+    XK_Armenian_to* = 0x000014C3
+    XKc_Armenian_ZHE* = 0x000014C4
+    XK_Armenian_zhe* = 0x000014C5
+    XKc_Armenian_INI* = 0x000014C6
+    XK_Armenian_ini* = 0x000014C7
+    XKc_Armenian_LYUN* = 0x000014C8
+    XK_Armenian_lyun* = 0x000014C9
+    XKc_Armenian_KHE* = 0x000014CA
+    XK_Armenian_khe* = 0x000014CB
+    XKc_Armenian_TSA* = 0x000014CC
+    XK_Armenian_tsa* = 0x000014CD
+    XKc_Armenian_KEN* = 0x000014CE
+    XK_Armenian_ken* = 0x000014CF
+    XKc_Armenian_HO* = 0x000014D0
+    XK_Armenian_ho* = 0x000014D1
+    XKc_Armenian_DZA* = 0x000014D2
+    XK_Armenian_dza* = 0x000014D3
+    XKc_Armenian_GHAT* = 0x000014D4
+    XK_Armenian_ghat* = 0x000014D5
+    XKc_Armenian_TCHE* = 0x000014D6
+    XK_Armenian_tche* = 0x000014D7
+    XKc_Armenian_MEN* = 0x000014D8
+    XK_Armenian_men* = 0x000014D9
+    XKc_Armenian_HI* = 0x000014DA
+    XK_Armenian_hi* = 0x000014DB
+    XKc_Armenian_NU* = 0x000014DC
+    XK_Armenian_nu* = 0x000014DD
+    XKc_Armenian_SHA* = 0x000014DE
+    XK_Armenian_sha* = 0x000014DF
+    XKc_Armenian_VO* = 0x000014E0
+    XK_Armenian_vo* = 0x000014E1
+    XKc_Armenian_CHA* = 0x000014E2
+    XK_Armenian_cha* = 0x000014E3
+    XKc_Armenian_PE* = 0x000014E4
+    XK_Armenian_pe* = 0x000014E5
+    XKc_Armenian_JE* = 0x000014E6
+    XK_Armenian_je* = 0x000014E7
+    XKc_Armenian_RA* = 0x000014E8
+    XK_Armenian_ra* = 0x000014E9
+    XKc_Armenian_SE* = 0x000014EA
+    XK_Armenian_se* = 0x000014EB
+    XKc_Armenian_VEV* = 0x000014EC
+    XK_Armenian_vev* = 0x000014ED
+    XKc_Armenian_TYUN* = 0x000014EE
+    XK_Armenian_tyun* = 0x000014EF
+    XKc_Armenian_RE* = 0x000014F0
+    XK_Armenian_re* = 0x000014F1
+    XKc_Armenian_TSO* = 0x000014F2
+    XK_Armenian_tso* = 0x000014F3
+    XKc_Armenian_VYUN* = 0x000014F4
+    XK_Armenian_vyun* = 0x000014F5
+    XKc_Armenian_PYUR* = 0x000014F6
+    XK_Armenian_pyur* = 0x000014F7
+    XKc_Armenian_KE* = 0x000014F8
+    XK_Armenian_ke* = 0x000014F9
+    XKc_Armenian_O* = 0x000014FA
+    XK_Armenian_o* = 0x000014FB
+    XKc_Armenian_FE* = 0x000014FC
+    XK_Armenian_fe* = 0x000014FD
+    XK_Armenian_apostrophe* = 0x000014FE
+    XK_Armenian_section_sign* = 0x000014FF
+# XK_ARMENIAN 
+#*
+# *   Georgian
+# *   Byte 3 = = $15
+# *
+
+when defined(XK_GEORGIAN) or true: 
+  const
+    XK_Georgian_an* = 0x000015D0
+    XK_Georgian_ban* = 0x000015D1
+    XK_Georgian_gan* = 0x000015D2
+    XK_Georgian_don* = 0x000015D3
+    XK_Georgian_en* = 0x000015D4
+    XK_Georgian_vin* = 0x000015D5
+    XK_Georgian_zen* = 0x000015D6
+    XK_Georgian_tan* = 0x000015D7
+    XK_Georgian_in* = 0x000015D8
+    XK_Georgian_kan* = 0x000015D9
+    XK_Georgian_las* = 0x000015DA
+    XK_Georgian_man* = 0x000015DB
+    XK_Georgian_nar* = 0x000015DC
+    XK_Georgian_on* = 0x000015DD
+    XK_Georgian_par* = 0x000015DE
+    XK_Georgian_zhar* = 0x000015DF
+    XK_Georgian_rae* = 0x000015E0
+    XK_Georgian_san* = 0x000015E1
+    XK_Georgian_tar* = 0x000015E2
+    XK_Georgian_un* = 0x000015E3
+    XK_Georgian_phar* = 0x000015E4
+    XK_Georgian_khar* = 0x000015E5
+    XK_Georgian_ghan* = 0x000015E6
+    XK_Georgian_qar* = 0x000015E7
+    XK_Georgian_shin* = 0x000015E8
+    XK_Georgian_chin* = 0x000015E9
+    XK_Georgian_can* = 0x000015EA
+    XK_Georgian_jil* = 0x000015EB
+    XK_Georgian_cil* = 0x000015EC
+    XK_Georgian_char* = 0x000015ED
+    XK_Georgian_xan* = 0x000015EE
+    XK_Georgian_jhan* = 0x000015EF
+    XK_Georgian_hae* = 0x000015F0
+    XK_Georgian_he* = 0x000015F1
+    XK_Georgian_hie* = 0x000015F2
+    XK_Georgian_we* = 0x000015F3
+    XK_Georgian_har* = 0x000015F4
+    XK_Georgian_hoe* = 0x000015F5
+    XK_Georgian_fi* = 0x000015F6
+# XK_GEORGIAN 
+#*
+# * Azeri (and other Turkic or Caucasian languages of ex-USSR)
+# * Byte 3 = = $16
+# *
+
+when defined(XK_CAUCASUS) or true: 
+  # latin 
+  const
+    XKc_Ccedillaabovedot* = 0x000016A2
+    XKc_Xabovedot* = 0x000016A3
+    XKc_Qabovedot* = 0x000016A5
+    XKc_Ibreve* = 0x000016A6
+    XKc_IE* = 0x000016A7
+    XKc_UO* = 0x000016A8
+    XKc_Zstroke* = 0x000016A9
+    XKc_Gcaron* = 0x000016AA
+    XKc_Obarred* = 0x000016AF
+    XK_ccedillaabovedot* = 0x000016B2
+    XK_xabovedot* = 0x000016B3
+    XKc_Ocaron* = 0x000016B4
+    XK_qabovedot* = 0x000016B5
+    XK_ibreve* = 0x000016B6
+    XK_ie* = 0x000016B7
+    XK_uo* = 0x000016B8
+    XK_zstroke* = 0x000016B9
+    XK_gcaron* = 0x000016BA
+    XK_ocaron* = 0x000016BD
+    XK_obarred* = 0x000016BF
+    XKc_SCHWA* = 0x000016C6
+    XK_schwa* = 0x000016F6 # those are not really Caucasus, but I put them here for now 
+                           # For Inupiak 
+    XKc_Lbelowdot* = 0x000016D1
+    XKc_Lstrokebelowdot* = 0x000016D2
+    XK_lbelowdot* = 0x000016E1
+    XK_lstrokebelowdot* = 0x000016E2 # For Guarani 
+    XKc_Gtilde* = 0x000016D3
+    XK_gtilde* = 0x000016E3
+# XK_CAUCASUS 
+#*
+# *   Vietnamese
+# *   Byte 3 = = $1e
+# *
+
+when defined(XK_VIETNAMESE) or true:
+  const 
+    XKc_Abelowdot* = 0x00001EA0
+    XK_abelowdot* = 0x00001EA1
+    XKc_Ahook* = 0x00001EA2
+    XK_ahook* = 0x00001EA3
+    XKc_Acircumflexacute* = 0x00001EA4
+    XK_acircumflexacute* = 0x00001EA5
+    XKc_Acircumflexgrave* = 0x00001EA6
+    XK_acircumflexgrave* = 0x00001EA7
+    XKc_Acircumflexhook* = 0x00001EA8
+    XK_acircumflexhook* = 0x00001EA9
+    XKc_Acircumflextilde* = 0x00001EAA
+    XK_acircumflextilde* = 0x00001EAB
+    XKc_Acircumflexbelowdot* = 0x00001EAC
+    XK_acircumflexbelowdot* = 0x00001EAD
+    XKc_Abreveacute* = 0x00001EAE
+    XK_abreveacute* = 0x00001EAF
+    XKc_Abrevegrave* = 0x00001EB0
+    XK_abrevegrave* = 0x00001EB1
+    XKc_Abrevehook* = 0x00001EB2
+    XK_abrevehook* = 0x00001EB3
+    XKc_Abrevetilde* = 0x00001EB4
+    XK_abrevetilde* = 0x00001EB5
+    XKc_Abrevebelowdot* = 0x00001EB6
+    XK_abrevebelowdot* = 0x00001EB7
+    XKc_Ebelowdot* = 0x00001EB8
+    XK_ebelowdot* = 0x00001EB9
+    XKc_Ehook* = 0x00001EBA
+    XK_ehook* = 0x00001EBB
+    XKc_Etilde* = 0x00001EBC
+    XK_etilde* = 0x00001EBD
+    XKc_Ecircumflexacute* = 0x00001EBE
+    XK_ecircumflexacute* = 0x00001EBF
+    XKc_Ecircumflexgrave* = 0x00001EC0
+    XK_ecircumflexgrave* = 0x00001EC1
+    XKc_Ecircumflexhook* = 0x00001EC2
+    XK_ecircumflexhook* = 0x00001EC3
+    XKc_Ecircumflextilde* = 0x00001EC4
+    XK_ecircumflextilde* = 0x00001EC5
+    XKc_Ecircumflexbelowdot* = 0x00001EC6
+    XK_ecircumflexbelowdot* = 0x00001EC7
+    XKc_Ihook* = 0x00001EC8
+    XK_ihook* = 0x00001EC9
+    XKc_Ibelowdot* = 0x00001ECA
+    XK_ibelowdot* = 0x00001ECB
+    XKc_Obelowdot* = 0x00001ECC
+    XK_obelowdot* = 0x00001ECD
+    XKc_Ohook* = 0x00001ECE
+    XK_ohook* = 0x00001ECF
+    XKc_Ocircumflexacute* = 0x00001ED0
+    XK_ocircumflexacute* = 0x00001ED1
+    XKc_Ocircumflexgrave* = 0x00001ED2
+    XK_ocircumflexgrave* = 0x00001ED3
+    XKc_Ocircumflexhook* = 0x00001ED4
+    XK_ocircumflexhook* = 0x00001ED5
+    XKc_Ocircumflextilde* = 0x00001ED6
+    XK_ocircumflextilde* = 0x00001ED7
+    XKc_Ocircumflexbelowdot* = 0x00001ED8
+    XK_ocircumflexbelowdot* = 0x00001ED9
+    XKc_Ohornacute* = 0x00001EDA
+    XK_ohornacute* = 0x00001EDB
+    XKc_Ohorngrave* = 0x00001EDC
+    XK_ohorngrave* = 0x00001EDD
+    XKc_Ohornhook* = 0x00001EDE
+    XK_ohornhook* = 0x00001EDF
+    XKc_Ohorntilde* = 0x00001EE0
+    XK_ohorntilde* = 0x00001EE1
+    XKc_Ohornbelowdot* = 0x00001EE2
+    XK_ohornbelowdot* = 0x00001EE3
+    XKc_Ubelowdot* = 0x00001EE4
+    XK_ubelowdot* = 0x00001EE5
+    XKc_Uhook* = 0x00001EE6
+    XK_uhook* = 0x00001EE7
+    XKc_Uhornacute* = 0x00001EE8
+    XK_uhornacute* = 0x00001EE9
+    XKc_Uhorngrave* = 0x00001EEA
+    XK_uhorngrave* = 0x00001EEB
+    XKc_Uhornhook* = 0x00001EEC
+    XK_uhornhook* = 0x00001EED
+    XKc_Uhorntilde* = 0x00001EEE
+    XK_uhorntilde* = 0x00001EEF
+    XKc_Uhornbelowdot* = 0x00001EF0
+    XK_uhornbelowdot* = 0x00001EF1
+    XKc_Ybelowdot* = 0x00001EF4
+    XK_ybelowdot* = 0x00001EF5
+    XKc_Yhook* = 0x00001EF6
+    XK_yhook* = 0x00001EF7
+    XKc_Ytilde* = 0x00001EF8
+    XK_ytilde* = 0x00001EF9
+    XKc_Ohorn* = 0x00001EFA     # U+01a0 
+    XK_ohorn* = 0x00001EFB      # U+01a1 
+    XKc_Uhorn* = 0x00001EFC     # U+01af 
+    XK_uhorn* = 0x00001EFD      # U+01b0 
+    XK_combining_tilde* = 0x00001E9F # U+0303 
+    XK_combining_grave* = 0x00001EF2 # U+0300 
+    XK_combining_acute* = 0x00001EF3 # U+0301 
+    XK_combining_hook* = 0x00001EFE # U+0309 
+    XK_combining_belowdot* = 0x00001EFF # U+0323 
+# XK_VIETNAMESE 
+
+when defined(XK_CURRENCY) or true: 
+  const
+    XK_EcuSign* = 0x000020A0
+    XK_ColonSign* = 0x000020A1
+    XK_CruzeiroSign* = 0x000020A2
+    XK_FFrancSign* = 0x000020A3
+    XK_LiraSign* = 0x000020A4
+    XK_MillSign* = 0x000020A5
+    XK_NairaSign* = 0x000020A6
+    XK_PesetaSign* = 0x000020A7
+    XK_RupeeSign* = 0x000020A8
+    XK_WonSign* = 0x000020A9
+    XK_NewSheqelSign* = 0x000020AA
+    XK_DongSign* = 0x000020AB
+    XK_EuroSign* = 0x000020AC
+# implementation
diff --git a/lib/base/x11/x.nim b/lib/wrappers/x11/x.nim
index aa6e7f821..aa6e7f821 100644
--- a/lib/base/x11/x.nim
+++ b/lib/wrappers/x11/x.nim
diff --git a/lib/base/x11/xatom.nim b/lib/wrappers/x11/xatom.nim
index b2e1dca91..b2e1dca91 100644
--- a/lib/base/x11/xatom.nim
+++ b/lib/wrappers/x11/xatom.nim
diff --git a/lib/base/x11/xcms.nim b/lib/wrappers/x11/xcms.nim
index 57aad6ae0..57aad6ae0 100644
--- a/lib/base/x11/xcms.nim
+++ b/lib/wrappers/x11/xcms.nim
diff --git a/lib/base/x11/xf86dga.nim b/lib/wrappers/x11/xf86dga.nim
index 376f11861..376f11861 100644
--- a/lib/base/x11/xf86dga.nim
+++ b/lib/wrappers/x11/xf86dga.nim
diff --git a/lib/base/x11/xf86vmode.nim b/lib/wrappers/x11/xf86vmode.nim
index 18a922cab..18a922cab 100644
--- a/lib/base/x11/xf86vmode.nim
+++ b/lib/wrappers/x11/xf86vmode.nim
diff --git a/lib/base/x11/xi.nim b/lib/wrappers/x11/xi.nim
index d1b9f7846..d1b9f7846 100644
--- a/lib/base/x11/xi.nim
+++ b/lib/wrappers/x11/xi.nim
diff --git a/lib/base/x11/xinerama.nim b/lib/wrappers/x11/xinerama.nim
index 96f5d7da3..96f5d7da3 100644
--- a/lib/base/x11/xinerama.nim
+++ b/lib/wrappers/x11/xinerama.nim
diff --git a/lib/base/x11/xkb.nim b/lib/wrappers/x11/xkb.nim
index f1b0448a8..f1b0448a8 100644
--- a/lib/base/x11/xkb.nim
+++ b/lib/wrappers/x11/xkb.nim
diff --git a/lib/base/x11/xkblib.nim b/lib/wrappers/x11/xkblib.nim
index 92d438a60..92d438a60 100644
--- a/lib/base/x11/xkblib.nim
+++ b/lib/wrappers/x11/xkblib.nim
diff --git a/lib/base/x11/xlib.nim b/lib/wrappers/x11/xlib.nim
index 84f9bbfc5..84f9bbfc5 100644
--- a/lib/base/x11/xlib.nim
+++ b/lib/wrappers/x11/xlib.nim
diff --git a/lib/base/x11/xrandr.nim b/lib/wrappers/x11/xrandr.nim
index ebc656260..ebc656260 100644
--- a/lib/base/x11/xrandr.nim
+++ b/lib/wrappers/x11/xrandr.nim
diff --git a/lib/base/x11/xrender.nim b/lib/wrappers/x11/xrender.nim
index c4f817607..c4f817607 100644
--- a/lib/base/x11/xrender.nim
+++ b/lib/wrappers/x11/xrender.nim
diff --git a/lib/base/x11/xresource.nim b/lib/wrappers/x11/xresource.nim
index ddb2a89c2..ddb2a89c2 100644
--- a/lib/base/x11/xresource.nim
+++ b/lib/wrappers/x11/xresource.nim
diff --git a/lib/base/x11/xshm.nim b/lib/wrappers/x11/xshm.nim
index e56bd87b1..e56bd87b1 100644
--- a/lib/base/x11/xshm.nim
+++ b/lib/wrappers/x11/xshm.nim
diff --git a/lib/base/x11/xutil.nim b/lib/wrappers/x11/xutil.nim
index 6cea7fba3..6cea7fba3 100644
--- a/lib/base/x11/xutil.nim
+++ b/lib/wrappers/x11/xutil.nim
diff --git a/lib/base/x11/xv.nim b/lib/wrappers/x11/xv.nim
index 45ab61418..45ab61418 100644
--- a/lib/base/x11/xv.nim
+++ b/lib/wrappers/x11/xv.nim
diff --git a/lib/base/x11/xvlib.nim b/lib/wrappers/x11/xvlib.nim
index 19fd0d000..19fd0d000 100644
--- a/lib/base/x11/xvlib.nim
+++ b/lib/wrappers/x11/xvlib.nim
diff --git a/lib/base/zip/libzip.nim b/lib/wrappers/zip/libzip.nim
index 2f8abc46c..2f8abc46c 100644
--- a/lib/base/zip/libzip.nim
+++ b/lib/wrappers/zip/libzip.nim
diff --git a/lib/base/zip/libzip_all.c b/lib/wrappers/zip/libzip_all.c
index 797374b29..797374b29 100644
--- a/lib/base/zip/libzip_all.c
+++ b/lib/wrappers/zip/libzip_all.c
diff --git a/lib/base/zip/zlib.nim b/lib/wrappers/zip/zlib.nim
index 9b49b9663..9b49b9663 100644
--- a/lib/base/zip/zlib.nim
+++ b/lib/wrappers/zip/zlib.nim
diff --git a/lib/base/zip/zzip.nim b/lib/wrappers/zip/zzip.nim
index a656322ee..a656322ee 100644
--- a/lib/base/zip/zzip.nim
+++ b/lib/wrappers/zip/zzip.nim
diff --git a/nim/ast.pas b/nim/ast.pas
index aa83af4ed..681bf72d5 100644
--- a/nim/ast.pas
+++ b/nim/ast.pas
@@ -97,8 +97,8 @@ type
     nkStmtListExpr, nkBlockExpr, nkStmtListType, nkBlockType, 
     nkVm, nkTypeOfExpr, nkObjectTy, nkTupleTy, 
     nkRecList, nkRecCase, nkRecWhen, nkRefTy, 
-    nkPtrTy, nkVarTy, nkProcTy, nkEnumTy, 
-    nkEnumFieldDef, nkReturnToken);
+    nkPtrTy, nkVarTy, nkAbstractTy, nkProcTy, 
+    nkEnumTy, nkEnumFieldDef, nkReturnToken);
   TNodeKinds = set of TNodeKind;
 const
   NodeKindToStr: array [TNodeKind] of string = (
@@ -132,8 +132,8 @@ const
     'nkStmtListExpr', 'nkBlockExpr', 'nkStmtListType', 'nkBlockType', 
     'nkVm', 'nkTypeOfExpr', 'nkObjectTy', 'nkTupleTy', 
     'nkRecList', 'nkRecCase', 'nkRecWhen', 'nkRefTy', 
-    'nkPtrTy', 'nkVarTy', 'nkProcTy', 'nkEnumTy', 
-    'nkEnumFieldDef', 'nkReturnToken');
+    'nkPtrTy', 'nkVarTy', 'nkAbstractTy', 'nkProcTy', 
+    'nkEnumTy', 'nkEnumFieldDef', 'nkReturnToken');
 type
   TSymFlag = (
     sfUsed, sfStar, sfMinus, sfInInterface, 
@@ -142,7 +142,8 @@ type
     sfResult, sfNoSideEffect, sfMainModule, sfSystemModule, 
     sfNoReturn, sfAddrTaken, sfCompilerProc, sfCppMethod, 
     sfDiscriminant, sfDeprecated, sfInClosure, sfTypeCheck, 
-    sfCompileTime, sfThreadVar, sfMerge, sfDeadCodeElim);
+    sfCompileTime, sfThreadVar, sfMerge, sfDeadCodeElim, 
+    sfBorrow);
   TSymFlags = set of TSymFlag;
 const
   SymFlagToStr: array [TSymFlag] of string = (
@@ -152,30 +153,31 @@ const
     'sfResult', 'sfNoSideEffect', 'sfMainModule', 'sfSystemModule', 
     'sfNoReturn', 'sfAddrTaken', 'sfCompilerProc', 'sfCppMethod', 
     'sfDiscriminant', 'sfDeprecated', 'sfInClosure', 'sfTypeCheck', 
-    'sfCompileTime', 'sfThreadVar', 'sfMerge', 'sfDeadCodeElim');
+    'sfCompileTime', 'sfThreadVar', 'sfMerge', 'sfDeadCodeElim', 
+    'sfBorrow');
 type
   TTypeKind = (
     tyNone, tyBool, tyChar, tyEmpty, 
     tyArrayConstr, tyNil, tyGeneric, tyGenericInst, 
-    tyGenericParam, tyEnum, tyAnyEnum, tyArray, 
-    tyObject, tyTuple, tySet, tyRange, 
-    tyPtr, tyRef, tyVar, tySequence, 
-    tyProc, tyPointer, tyOpenArray, tyString, 
-    tyCString, tyForward, tyInt, tyInt8, 
-    tyInt16, tyInt32, tyInt64, tyFloat, 
-    tyFloat32, tyFloat64, tyFloat128);
+    tyGenericParam, tyAbstract, tyEnum, tyOrdinal, 
+    tyArray, tyObject, tyTuple, tySet, 
+    tyRange, tyPtr, tyRef, tyVar, 
+    tySequence, tyProc, tyPointer, tyOpenArray, 
+    tyString, tyCString, tyForward, tyInt, 
+    tyInt8, tyInt16, tyInt32, tyInt64, 
+    tyFloat, tyFloat32, tyFloat64, tyFloat128);
   TTypeKinds = set of TTypeKind;
 const
   TypeKindToStr: array [TTypeKind] of string = (
     'tyNone', 'tyBool', 'tyChar', 'tyEmpty', 
     'tyArrayConstr', 'tyNil', 'tyGeneric', 'tyGenericInst', 
-    'tyGenericParam', 'tyEnum', 'tyAnyEnum', 'tyArray', 
-    'tyObject', 'tyTuple', 'tySet', 'tyRange', 
-    'tyPtr', 'tyRef', 'tyVar', 'tySequence', 
-    'tyProc', 'tyPointer', 'tyOpenArray', 'tyString', 
-    'tyCString', 'tyForward', 'tyInt', 'tyInt8', 
-    'tyInt16', 'tyInt32', 'tyInt64', 'tyFloat', 
-    'tyFloat32', 'tyFloat64', 'tyFloat128');
+    'tyGenericParam', 'tyAbstract', 'tyEnum', 'tyOrdinal', 
+    'tyArray', 'tyObject', 'tyTuple', 'tySet', 
+    'tyRange', 'tyPtr', 'tyRef', 'tyVar', 
+    'tySequence', 'tyProc', 'tyPointer', 'tyOpenArray', 
+    'tyString', 'tyCString', 'tyForward', 'tyInt', 
+    'tyInt8', 'tyInt16', 'tyInt32', 'tyInt64', 
+    'tyFloat', 'tyFloat32', 'tyFloat64', 'tyFloat128');
 type
   TNodeFlag = (
     nfNone, nfBase2, nfBase8, nfBase16, 
@@ -220,36 +222,36 @@ type
     //cog.outl("m" + magics[-1])
     //]]]
     mNone, mDefined, mLow, mHigh, mSizeOf, mIs, 
-    mSucc, mPred, mInc, mDec, mOrd, mNew, 
-    mNewFinalize, mNewSeq, mRegisterFinalizer, mLengthOpenArray, mLengthStr, mLengthArray, 
-    mLengthSeq, mIncl, mExcl, mCard, mChr, mGCref, 
-    mGCunref, mAddI, mSubI, mMulI, mDivI, mModI, 
-    mAddI64, mSubI64, mMulI64, mDivI64, mModI64, mShrI, 
-    mShlI, mBitandI, mBitorI, mBitxorI, mMinI, mMaxI, 
-    mShrI64, mShlI64, mBitandI64, mBitorI64, mBitxorI64, mMinI64, 
-    mMaxI64, mAddF64, mSubF64, mMulF64, mDivF64, mMinF64, 
-    mMaxF64, mAddU, mSubU, mMulU, mDivU, mModU, 
-    mAddU64, mSubU64, mMulU64, mDivU64, mModU64, mEqI, 
-    mLeI, mLtI, mEqI64, mLeI64, mLtI64, mEqF64, 
-    mLeF64, mLtF64, mLeU, mLtU, mLeU64, mLtU64, 
-    mEqEnum, mLeEnum, mLtEnum, mEqCh, mLeCh, mLtCh, 
-    mEqB, mLeB, mLtB, mEqRef, mEqProc, mEqUntracedRef, 
-    mLePtr, mLtPtr, mEqCString, mXor, mUnaryMinusI, mUnaryMinusI64, 
-    mAbsI, mAbsI64, mNot, mUnaryPlusI, mBitnotI, mUnaryPlusI64, 
-    mBitnotI64, mUnaryPlusF64, mUnaryMinusF64, mAbsF64, mZe8ToI, mZe8ToI64, 
-    mZe16ToI, mZe16ToI64, mZe32ToI64, mZeIToI64, mToU8, mToU16, 
-    mToU32, mToFloat, mToBiggestFloat, mToInt, mToBiggestInt, mCharToStr, 
-    mBoolToStr, mIntToStr, mInt64ToStr, mFloatToStr, mCStrToStr, mStrToStr, 
-    mEnumToStr, mAnd, mOr, mEqStr, mLeStr, mLtStr, 
-    mEqSet, mLeSet, mLtSet, mMulSet, mPlusSet, mMinusSet, 
-    mSymDiffSet, mConStrStr, mConArrArr, mConArrT, mConTArr, mConTT, 
-    mSlice, mAppendStrCh, mAppendStrStr, mAppendSeqElem, mAppendSeqSeq, mInRange, 
-    mInSet, mAsgn, mRepr, mExit, mSetLengthStr, mSetLengthSeq, 
+    mEcho, mSucc, mPred, mInc, mDec, mOrd, 
+    mNew, mNewFinalize, mNewSeq, mRegisterFinalizer, mLengthOpenArray, mLengthStr, 
+    mLengthArray, mLengthSeq, mIncl, mExcl, mCard, mChr, 
+    mGCref, mGCunref, mAddI, mSubI, mMulI, mDivI, 
+    mModI, mAddI64, mSubI64, mMulI64, mDivI64, mModI64, 
+    mShrI, mShlI, mBitandI, mBitorI, mBitxorI, mMinI, 
+    mMaxI, mShrI64, mShlI64, mBitandI64, mBitorI64, mBitxorI64, 
+    mMinI64, mMaxI64, mAddF64, mSubF64, mMulF64, mDivF64, 
+    mMinF64, mMaxF64, mAddU, mSubU, mMulU, mDivU, 
+    mModU, mAddU64, mSubU64, mMulU64, mDivU64, mModU64, 
+    mEqI, mLeI, mLtI, mEqI64, mLeI64, mLtI64, 
+    mEqF64, mLeF64, mLtF64, mLeU, mLtU, mLeU64, 
+    mLtU64, mEqEnum, mLeEnum, mLtEnum, mEqCh, mLeCh, 
+    mLtCh, mEqB, mLeB, mLtB, mEqRef, mEqProc, 
+    mEqUntracedRef, mLePtr, mLtPtr, mEqCString, mXor, mUnaryMinusI, 
+    mUnaryMinusI64, mAbsI, mAbsI64, mNot, mUnaryPlusI, mBitnotI, 
+    mUnaryPlusI64, mBitnotI64, mUnaryPlusF64, mUnaryMinusF64, mAbsF64, mZe8ToI, 
+    mZe8ToI64, mZe16ToI, mZe16ToI64, mZe32ToI64, mZeIToI64, mToU8, 
+    mToU16, mToU32, mToFloat, mToBiggestFloat, mToInt, mToBiggestInt, 
+    mCharToStr, mBoolToStr, mIntToStr, mInt64ToStr, mFloatToStr, mCStrToStr, 
+    mStrToStr, mEnumToStr, mAnd, mOr, mEqStr, mLeStr, 
+    mLtStr, mEqSet, mLeSet, mLtSet, mMulSet, mPlusSet, 
+    mMinusSet, mSymDiffSet, mConStrStr, mConArrArr, mConArrT, mConTArr, 
+    mConTT, mSlice, mAppendStrCh, mAppendStrStr, mAppendSeqElem, mAppendSeqSeq, 
+    mInRange, mInSet, mRepr, mExit, mSetLengthStr, mSetLengthSeq, 
     mAssert, mSwap, mIsNil, mArrToSeq, mCopyStr, mCopyStrLast, 
     mNewString, mArray, mOpenArray, mRange, mSet, mSeq, 
-    mInt, mInt8, mInt16, mInt32, mInt64, mFloat, 
-    mFloat32, mFloat64, mBool, mChar, mString, mCstring, 
-    mPointer, mAnyEnum, mEmptySet, mIntSetBaseType, mNil, mIsMainModule, 
+    mOrdinal, mInt, mInt8, mInt16, mInt32, mInt64, 
+    mFloat, mFloat32, mFloat64, mBool, mChar, mString, 
+    mCstring, mPointer, mEmptySet, mIntSetBaseType, mNil, mIsMainModule, 
     mCompileDate, mCompileTime, mNimrodVersion, mNimrodMajor, mNimrodMinor, mNimrodPatch, 
     mCpuEndian, mHostOS, mHostCPU, mNaN, mInf, mNegInf, 
     mNLen, mNChild, mNSetChild, mNAdd, mNAddMultiple, mNDel, 
@@ -479,36 +481,36 @@ const // "MagicToStr" array:
     //cog.outl("'%s'" % magics[-1])
     //]]]
     'None', 'Defined', 'Low', 'High', 'SizeOf', 'Is', 
-    'Succ', 'Pred', 'Inc', 'Dec', 'Ord', 'New', 
-    'NewFinalize', 'NewSeq', 'RegisterFinalizer', 'LengthOpenArray', 'LengthStr', 'LengthArray', 
-    'LengthSeq', 'Incl', 'Excl', 'Card', 'Chr', 'GCref', 
-    'GCunref', 'AddI', 'SubI', 'MulI', 'DivI', 'ModI', 
-    'AddI64', 'SubI64', 'MulI64', 'DivI64', 'ModI64', 'ShrI', 
-    'ShlI', 'BitandI', 'BitorI', 'BitxorI', 'MinI', 'MaxI', 
-    'ShrI64', 'ShlI64', 'BitandI64', 'BitorI64', 'BitxorI64', 'MinI64', 
-    'MaxI64', 'AddF64', 'SubF64', 'MulF64', 'DivF64', 'MinF64', 
-    'MaxF64', 'AddU', 'SubU', 'MulU', 'DivU', 'ModU', 
-    'AddU64', 'SubU64', 'MulU64', 'DivU64', 'ModU64', 'EqI', 
-    'LeI', 'LtI', 'EqI64', 'LeI64', 'LtI64', 'EqF64', 
-    'LeF64', 'LtF64', 'LeU', 'LtU', 'LeU64', 'LtU64', 
-    'EqEnum', 'LeEnum', 'LtEnum', 'EqCh', 'LeCh', 'LtCh', 
-    'EqB', 'LeB', 'LtB', 'EqRef', 'EqProc', 'EqUntracedRef', 
-    'LePtr', 'LtPtr', 'EqCString', 'Xor', 'UnaryMinusI', 'UnaryMinusI64', 
-    'AbsI', 'AbsI64', 'Not', 'UnaryPlusI', 'BitnotI', 'UnaryPlusI64', 
-    'BitnotI64', 'UnaryPlusF64', 'UnaryMinusF64', 'AbsF64', 'Ze8ToI', 'Ze8ToI64', 
-    'Ze16ToI', 'Ze16ToI64', 'Ze32ToI64', 'ZeIToI64', 'ToU8', 'ToU16', 
-    'ToU32', 'ToFloat', 'ToBiggestFloat', 'ToInt', 'ToBiggestInt', 'CharToStr', 
-    'BoolToStr', 'IntToStr', 'Int64ToStr', 'FloatToStr', 'CStrToStr', 'StrToStr', 
-    'EnumToStr', 'And', 'Or', 'EqStr', 'LeStr', 'LtStr', 
-    'EqSet', 'LeSet', 'LtSet', 'MulSet', 'PlusSet', 'MinusSet', 
-    'SymDiffSet', 'ConStrStr', 'ConArrArr', 'ConArrT', 'ConTArr', 'ConTT', 
-    'Slice', 'AppendStrCh', 'AppendStrStr', 'AppendSeqElem', 'AppendSeqSeq', 'InRange', 
-    'InSet', 'Asgn', 'Repr', 'Exit', 'SetLengthStr', 'SetLengthSeq', 
+    'Echo', 'Succ', 'Pred', 'Inc', 'Dec', 'Ord', 
+    'New', 'NewFinalize', 'NewSeq', 'RegisterFinalizer', 'LengthOpenArray', 'LengthStr', 
+    'LengthArray', 'LengthSeq', 'Incl', 'Excl', 'Card', 'Chr', 
+    'GCref', 'GCunref', 'AddI', 'SubI', 'MulI', 'DivI', 
+    'ModI', 'AddI64', 'SubI64', 'MulI64', 'DivI64', 'ModI64', 
+    'ShrI', 'ShlI', 'BitandI', 'BitorI', 'BitxorI', 'MinI', 
+    'MaxI', 'ShrI64', 'ShlI64', 'BitandI64', 'BitorI64', 'BitxorI64', 
+    'MinI64', 'MaxI64', 'AddF64', 'SubF64', 'MulF64', 'DivF64', 
+    'MinF64', 'MaxF64', 'AddU', 'SubU', 'MulU', 'DivU', 
+    'ModU', 'AddU64', 'SubU64', 'MulU64', 'DivU64', 'ModU64', 
+    'EqI', 'LeI', 'LtI', 'EqI64', 'LeI64', 'LtI64', 
+    'EqF64', 'LeF64', 'LtF64', 'LeU', 'LtU', 'LeU64', 
+    'LtU64', 'EqEnum', 'LeEnum', 'LtEnum', 'EqCh', 'LeCh', 
+    'LtCh', 'EqB', 'LeB', 'LtB', 'EqRef', 'EqProc', 
+    'EqUntracedRef', 'LePtr', 'LtPtr', 'EqCString', 'Xor', 'UnaryMinusI', 
+    'UnaryMinusI64', 'AbsI', 'AbsI64', 'Not', 'UnaryPlusI', 'BitnotI', 
+    'UnaryPlusI64', 'BitnotI64', 'UnaryPlusF64', 'UnaryMinusF64', 'AbsF64', 'Ze8ToI', 
+    'Ze8ToI64', 'Ze16ToI', 'Ze16ToI64', 'Ze32ToI64', 'ZeIToI64', 'ToU8', 
+    'ToU16', 'ToU32', 'ToFloat', 'ToBiggestFloat', 'ToInt', 'ToBiggestInt', 
+    'CharToStr', 'BoolToStr', 'IntToStr', 'Int64ToStr', 'FloatToStr', 'CStrToStr', 
+    'StrToStr', 'EnumToStr', 'And', 'Or', 'EqStr', 'LeStr', 
+    'LtStr', 'EqSet', 'LeSet', 'LtSet', 'MulSet', 'PlusSet', 
+    'MinusSet', 'SymDiffSet', 'ConStrStr', 'ConArrArr', 'ConArrT', 'ConTArr', 
+    'ConTT', 'Slice', 'AppendStrCh', 'AppendStrStr', 'AppendSeqElem', 'AppendSeqSeq', 
+    'InRange', 'InSet', 'Repr', 'Exit', 'SetLengthStr', 'SetLengthSeq', 
     'Assert', 'Swap', 'IsNil', 'ArrToSeq', 'CopyStr', 'CopyStrLast', 
     'NewString', 'Array', 'OpenArray', 'Range', 'Set', 'Seq', 
-    'Int', 'Int8', 'Int16', 'Int32', 'Int64', 'Float', 
-    'Float32', 'Float64', 'Bool', 'Char', 'String', 'Cstring', 
-    'Pointer', 'AnyEnum', 'EmptySet', 'IntSetBaseType', 'Nil', 'IsMainModule', 
+    'Ordinal', 'Int', 'Int8', 'Int16', 'Int32', 'Int64', 
+    'Float', 'Float32', 'Float64', 'Bool', 'Char', 'String', 
+    'Cstring', 'Pointer', 'EmptySet', 'IntSetBaseType', 'Nil', 'IsMainModule', 
     'CompileDate', 'CompileTime', 'NimrodVersion', 'NimrodMajor', 'NimrodMinor', 'NimrodPatch', 
     'CpuEndian', 'HostOS', 'HostCPU', 'NaN', 'Inf', 'NegInf', 
     'NLen', 'NChild', 'NSetChild', 'NAdd', 'NAddMultiple', 'NDel', 
diff --git a/nim/ccgexprs.pas b/nim/ccgexprs.pas
index a7a364a52..bf03365cd 100644
--- a/nim/ccgexprs.pas
+++ b/nim/ccgexprs.pas
@@ -56,7 +56,7 @@ begin
   if ty = nil then internalError(v.info, 'genLiteral: ty is nil');
   case v.kind of
     nkCharLit..nkInt64Lit: begin
-      case skipVarGenericRange(ty).kind of
+      case skipTypes(ty, abstractVarRange).kind of
         tyChar, tyInt64, tyNil: result := intLiteral(v.intVal);
         tyInt8:  
           result := ropef('((NI8) $1)', [intLiteral(biggestInt(int8(v.intVal)))]);
@@ -76,13 +76,13 @@ begin
         end;
         else
           result := ropef('(($1) $2)', [getTypeDesc(p.module,
-            skipVarGenericRange(ty)), intLiteral(v.intVal)])
+            skipTypes(ty, abstractVarRange)), intLiteral(v.intVal)])
       end
     end;
     nkNilLit:
       result := toRope('0'+'');
     nkStrLit..nkTripleStrLit: begin
-      if skipVarGenericRange(ty).kind = tyString then begin
+      if skipTypes(ty, abstractVarRange).kind = tyString then begin
         id := NodeTableTestOrSet(p.module.dataCache, v, gid);
         if id = gid then begin
           // string literal not found in the cache:
@@ -228,7 +228,7 @@ function rdCharLoc(const a: TLoc): PRope;
 // read a location that may need a char-cast:
 begin
   result := rdLoc(a);
-  if skipRange(a.t).kind = tyChar then
+  if skipTypes(a.t, abstractRange).kind = tyChar then
     result := ropef('((NU8)($1))', [result])
 end;
 
@@ -289,7 +289,7 @@ procedure genAssignment(p: BProc; const dest, src: TLoc;
 var
   ty: PType;
 begin;
-  ty := skipVarGenericRange(dest.t);
+  ty := skipTypes(dest.t, abstractVarRange);
   case ty.kind of
     tyRef:
       genRefAssign(p, dest, src, flags);
@@ -531,7 +531,7 @@ begin
   assert(e.sons[2].typ <> nil);
   InitLocExpr(p, e.sons[1], a);
   InitLocExpr(p, e.sons[2], b);
-  t := skipGenericRange(e.typ);
+  t := skipTypes(e.typ, abstractRange);
   if getSize(t) >= platform.IntSize then begin
     if optOverflowCheck in p.options then begin
       useMagic(p.module, prc[m]);
@@ -578,7 +578,7 @@ var
 begin
   assert(e.sons[1].typ <> nil);
   InitLocExpr(p, e.sons[1], a);
-  t := skipGenericRange(e.typ);
+  t := skipTypes(e.typ, abstractRange);
   if optOverflowCheck in p.options then begin
     useMagic(p.module, 'raiseOverflow');
     appf(p.s[cpsStmts], 'if ($1 == $2) raiseOverflow();$n', 
@@ -705,7 +705,7 @@ var
 begin
   assert(e.sons[1].typ <> nil);
   InitLocExpr(p, e.sons[1], a);
-  t := skipGenericRange(e.typ);
+  t := skipTypes(e.typ, abstractRange);
   putIntoDest(p, d, e.typ, ropef(unArithTab[op], 
               [rdLoc(a), toRope(getSize(t)*8)]));
 end;
@@ -718,7 +718,7 @@ begin
     expr(p, e.sons[0], d)
   else begin
     initLocExpr(p, e.sons[0], a);
-    case skipGeneric(a.t).kind of
+    case skipTypes(a.t, abstractInst).kind of
       tyRef: d.s := OnHeap;
       tyVar: d.s := OnUnknown;
       tyPtr: d.s := OnUnknown; // BUGFIX!
@@ -872,7 +872,7 @@ var
 begin
   initLocExpr(p, e.sons[0], a);
   initLocExpr(p, e.sons[1], b);
-  ty := skipPtrsGeneric(skipVarGenericRange(a.t));
+  ty := skipTypes(skipTypes(a.t, abstractVarRange), abstractPtrs);
   first := intLiteral(firstOrd(ty));
   // emit range check:
   if (optBoundsCheck in p.options) then begin
@@ -892,7 +892,7 @@ begin
     end;
   end;
   if d.k = locNone then d.s := a.s;
-  putIntoDest(p, d, elemType(skipVarGeneric(ty)), ropef('$1[($2)-$3]',
+  putIntoDest(p, d, elemType(skipTypes(ty, abstractVar)), ropef('$1[($2)-$3]',
     [rdLoc(a), rdCharLoc(b), first]));
 end;
 
@@ -903,9 +903,9 @@ var
 begin
   initLocExpr(p, e.sons[0], a);
   initLocExpr(p, e.sons[1], b);
-  ty := skipVarGenericRange(a.t);
+  ty := skipTypes(a.t, abstractVarRange);
   if d.k = locNone then d.s := a.s;
-  putIntoDest(p, d, elemType(skipVarGeneric(ty)), ropef('$1[$2]',
+  putIntoDest(p, d, elemType(skipTypes(ty, abstractVar)), ropef('$1[$2]',
     [rdLoc(a), rdCharLoc(b)]));
 end;
 
@@ -923,7 +923,7 @@ begin
     // BUGFIX: ``>=`` and not ``>``!
   end;
   if d.k = locNone then d.s := a.s;
-  putIntoDest(p, d, elemType(skipVarGeneric(a.t)), ropef('$1[$2]',
+  putIntoDest(p, d, elemType(skipTypes(a.t, abstractVar)), ropef('$1[$2]',
     [rdLoc(a), rdCharLoc(b)]));
 end;
 
@@ -934,8 +934,9 @@ var
 begin
   initLocExpr(p, e.sons[0], a);
   initLocExpr(p, e.sons[1], b);
-  ty := skipVarGenericRange(a.t);
-  if ty.kind in [tyRef, tyPtr] then ty := skipVarGenericRange(ty.sons[0]);
+  ty := skipTypes(a.t, abstractVarRange);
+  if ty.kind in [tyRef, tyPtr] then 
+    ty := skipTypes(ty.sons[0], abstractVarRange);
   // emit range check:
   if (optBoundsCheck in p.options) then begin
     useMagic(p.module, 'raiseIndexError');
@@ -949,10 +950,10 @@ begin
         [rdLoc(b), rdLoc(a)])
   end;
   if d.k = locNone then d.s := OnHeap;
-  if skipVarGenericRange(a.t).kind in [tyRef, tyPtr] then
+  if skipTypes(a.t, abstractVar).kind in [tyRef, tyPtr] then
     a.r := ropef('(*$1)', [a.r]);
-  putIntoDest(p, d, elemType(skipVarGeneric(a.t)), ropef('$1->data[$2]',
-    [rdLoc(a), rdCharLoc(b)]));
+  putIntoDest(p, d, elemType(skipTypes(a.t, abstractVar)), 
+    ropef('$1->data[$2]', [rdLoc(a), rdCharLoc(b)]));
 end;
 
 procedure genAndOr(p: BProc; e: PNode; var d: TLoc; m: TMagic);
@@ -1040,6 +1041,20 @@ begin
     genAssignment(p, d, tmp, {@set}[]); // no need for deep copying
 end;
 
+procedure genEcho(p: BProc; n: PNode);
+var 
+  i: int;
+  a: TLoc;
+begin
+  useMagic(p.module, 'rawEcho');
+  useMagic(p.module, 'rawEchoNL');
+  for i := 1 to sonsLen(n)-1 do begin
+    initLocExpr(p, n.sons[i], a);
+    appf(p.s[cpsStmts], 'rawEcho($1);$n', [rdLoc(a)]);
+  end;
+  app(p.s[cpsStmts], 'rawEchoNL();' + tnl);
+end;
+
 procedure genCall(p: BProc; t: PNode; var d: TLoc);
 var
   param: PSym;
@@ -1120,7 +1135,7 @@ begin
   for i := 0 to sonsLen(e)-2 do begin
     // compute the length expression:
     initLocExpr(p, e.sons[i+1], a);
-    if skipVarGenericRange(e.sons[i+1].Typ).kind = tyChar then begin
+    if skipTypes(e.sons[i+1].Typ, abstractVarRange).kind = tyChar then begin
       Inc(L);
       useMagic(p.module, 'appendChar');
       appf(appends, 'appendChar($1, $2);$n', [tmp.r, rdLoc(a)])
@@ -1169,7 +1184,7 @@ begin
   for i := 0 to sonsLen(e)-3 do begin
     // compute the length expression:
     initLocExpr(p, e.sons[i+2], a);
-    if skipVarGenericRange(e.sons[i+2].Typ).kind = tyChar then begin
+    if skipTypes(e.sons[i+2].Typ, abstractVarRange).kind = tyChar then begin
       Inc(L);
       useMagic(p.module, 'appendChar');
       appf(appends, 'appendChar($1, $2);$n',
@@ -1202,8 +1217,8 @@ begin
   InitLocExpr(p, e.sons[2], b);
   appf(p.s[cpsStmts],
     '$1 = ($2) incrSeq(&($1)->Sup, sizeof($3));$n',
-    [rdLoc(a), getTypeDesc(p.module, skipVarGeneric(e.sons[1].typ)),
-    getTypeDesc(p.module, skipVarGeneric(e.sons[2].Typ))]);
+    [rdLoc(a), getTypeDesc(p.module, skipTypes(e.sons[1].typ, abstractVar)),
+    getTypeDesc(p.module, skipTypes(e.sons[2].Typ, abstractVar))]);
   initLoc(dest, locExpr, b.t, OnHeap);
   dest.r := ropef('$1->data[$1->Sup.len-1]', [rdLoc(a)]);
   genAssignment(p, dest, b, {@set}[needToCopy, afDestIsNil]);
@@ -1222,7 +1237,7 @@ begin
       s := t;
       while (s.kind = tyObject) and (s.sons[0] <> nil) do begin
         app(r, '.Sup');
-        s := skipGeneric(s.sons[0]);
+        s := skipTypes(s.sons[0], abstractInst);
       end;    
       appf(p.s[cpsStmts], '$1.m_type = $2;$n', [r, genTypeInfo(p.module, t)])
     end;
@@ -1242,15 +1257,15 @@ var
   reftype, bt: PType;
 begin
   useMagic(p.module, 'newObj');
-  refType := skipVarGenericRange(e.sons[1].typ);
+  refType := skipTypes(e.sons[1].typ, abstractVarRange);
   InitLocExpr(p, e.sons[1], a);
   initLoc(b, locExpr, a.t, OnHeap);
   b.r := ropef('($1) newObj($2, sizeof($3))',
     [getTypeDesc(p.module, reftype), genTypeInfo(p.module, refType),
-    getTypeDesc(p.module, skipGenericRange(reftype.sons[0]))]);
+    getTypeDesc(p.module, skipTypes(reftype.sons[0], abstractRange))]);
   genAssignment(p, a, b, {@set}[]);
   // set the object type:
-  bt := skipGenericRange(refType.sons[0]);
+  bt := skipTypes(refType.sons[0], abstractRange);
   genObjectInit(p, bt, a, false);
 end;
 
@@ -1260,7 +1275,7 @@ var
   seqtype: PType;
 begin
   useMagic(p.module, 'newSeq');
-  seqType := skipVarGenericRange(e.sons[1].typ);
+  seqType := skipTypes(e.sons[1].typ, abstractVarRange);
   InitLocExpr(p, e.sons[1], a);
   InitLocExpr(p, e.sons[2], b);
   initLoc(c, locExpr, a.t, OnHeap);
@@ -1278,20 +1293,20 @@ var
   r, nilcheck: PRope;
 begin
   initLocExpr(p, n.sons[1], a);
-  dest := skipPtrsGeneric(n.sons[2].typ);
+  dest := skipTypes(n.sons[2].typ, abstractPtrs);
   useMagic(p.module, 'isObj');
   r := rdLoc(a);
   nilCheck := nil;
-  t := skipGeneric(a.t);
+  t := skipTypes(a.t, abstractInst);
   while t.kind in [tyVar, tyPtr, tyRef] do begin
     if t.kind <> tyVar then nilCheck := r;
     r := ropef('(*$1)', [r]);
-    t := skipGeneric(t.sons[0])
+    t := skipTypes(t.sons[0], abstractInst)
   end;
   if gCmd <> cmdCompileToCpp then
     while (t.kind = tyObject) and (t.sons[0] <> nil) do begin
       app(r, '.Sup');
-      t := skipGeneric(t.sons[0]);
+      t := skipTypes(t.sons[0], abstractInst)
     end;
   if nilCheck <> nil then
     r := ropef('(($1) && isObj($2.m_type, $3))',
@@ -1310,7 +1325,7 @@ var
   oldModule: BModule;
 begin
   useMagic(p.module, 'newObj');
-  refType := skipVarGenericRange(e.sons[1].typ);
+  refType := skipTypes(e.sons[1].typ, abstractVarRange);
   InitLocExpr(p, e.sons[1], a);
   
   // This is a little hack: 
@@ -1326,11 +1341,11 @@ begin
   appf(gmti.s[cfsTypeInit3], '$1->finalizer = (void*)$2;$n', [
     ti, rdLoc(f)]);
   b.r := ropef('($1) newObj($2, sizeof($3))',
-                   [getTypeDesc(p.module, refType), ti,
-                    getTypeDesc(p.module, skipGenericRange(reftype.sons[0]))]);
+           [getTypeDesc(p.module, refType), ti,
+            getTypeDesc(p.module, skipTypes(reftype.sons[0], abstractRange))]);
   genAssignment(p, a, b, {@set}[]);
   // set the object type:
-  bt := skipGenericRange(refType.sons[0]);
+  bt := skipTypes(refType.sons[0], abstractRange);
   genObjectInit(p, bt, a, false);
 end;
 
@@ -1340,7 +1355,7 @@ var
   t: PType;
 begin
   InitLocExpr(p, e.sons[1], a);
-  t := skipVarGenericRange(e.sons[1].typ);
+  t := skipTypes(e.sons[1].typ, abstractVarRange);
   case t.kind of
     tyInt..tyInt64: begin
       UseMagic(p.module, 'reprInt');
@@ -1358,7 +1373,7 @@ begin
       UseMagic(p.module, 'reprChar');
       putIntoDest(p, d, e.typ, ropef('reprChar($1)', [rdLoc(a)]))
     end;
-    tyEnum, tyAnyEnum: begin
+    tyEnum, tyOrdinal: begin
       UseMagic(p.module, 'reprEnum');
       putIntoDest(p, d, e.typ,
         ropef('reprEnum($1, $2)', [rdLoc(a), genTypeInfo(p.module, t)]))
@@ -1416,7 +1431,7 @@ procedure genArrayLen(p: BProc; e: PNode; var d: TLoc; op: TMagic);
 var
   typ: PType;
 begin
-  typ := skipPtrsGeneric(e.sons[1].Typ);
+  typ := skipTypes(e.sons[1].Typ, abstractPtrs);
   case typ.kind of
     tyOpenArray: begin
       while e.sons[1].kind = nkPassAsOpenArray do
@@ -1457,7 +1472,7 @@ begin
   useMagic(p.module, 'setLengthSeq');
   InitLocExpr(p, e.sons[1], a);
   InitLocExpr(p, e.sons[2], b);
-  t := skipVarGeneric(e.sons[1].typ);
+  t := skipTypes(e.sons[1].typ, abstractVar);
   appf(p.s[cpsStmts],
     '$1 = ($3) setLengthSeq(&($1)->Sup, sizeof($4), $2);$n',
     [rdLoc(a), rdLoc(b), getTypeDesc(p.module, t),
@@ -1477,7 +1492,7 @@ procedure genSwap(p: BProc; e: PNode; var d: TLoc);
 var
   a, b, tmp: TLoc;
 begin
-  getTemp(p, skipVarGeneric(e.sons[1].typ), tmp);
+  getTemp(p, skipTypes(e.sons[1].typ, abstractVar), tmp);
   InitLocExpr(p, e.sons[1], a); // eval a
   InitLocExpr(p, e.sons[2], b); // eval b
   genAssignment(p, tmp, a, {@set}[]);
@@ -1518,7 +1533,7 @@ end;
 
 procedure genInExprAux(p: BProc; e: PNode; var a, b, d: TLoc);
 begin
-  case int(getSize(skipVarGeneric(e.sons[1].typ))) of
+  case int(getSize(skipTypes(e.sons[1].typ, abstractVar))) of
     1: binaryExprIn(p, e, a, b, d, '(($1 &(1<<(($2)&7)))!=0)');
     2: binaryExprIn(p, e, a, b, d, '(($1 &(1<<(($2)&15)))!=0)');
     4: binaryExprIn(p, e, a, b, d, '(($1 &(1<<(($2)&31)))!=0)');
@@ -1591,7 +1606,7 @@ var
   a, b, i: TLoc;
   ts: string;
 begin
-  setType := skipVarGeneric(e.sons[1].Typ);
+  setType := skipTypes(e.sons[1].Typ, abstractVar);
   size := int(getSize(setType));
   case size of
     1, 2, 4, 8: begin
@@ -1676,7 +1691,7 @@ var
   a: TLoc;
 begin
   InitLocExpr(p, e.sons[1], a);
-  if (skipGenericRange(e.typ).kind in ValueTypes)
+  if (skipTypes(e.typ, abstractRange).kind in ValueTypes)
   and not (lfIndirect in a.flags) then
     putIntoDest(p, d, e.typ, ropef('(*($1*) ($2))',
       [getTypeDesc(p.module, e.typ), addrLoc(a)]))
@@ -1690,7 +1705,7 @@ var
   a: TLoc;
   dest: PType;
 begin
-  dest := skipVarGeneric(n.typ);
+  dest := skipTypes(n.typ, abstractVar);
   if not (optRangeCheck in p.options) then begin
     InitLocExpr(p, n.sons[0], a);
     putIntoDest(p, d, n.typ, ropef('(($1) ($2))',
@@ -1720,8 +1735,8 @@ var
 begin
   while n.sons[0].kind = nkPassAsOpenArray do
     n.sons[0] := n.sons[0].sons[0]; // BUGFIX
-  dest := skipVarGeneric(n.typ);
-  case skipVarGeneric(n.sons[0].typ).kind of
+  dest := skipTypes(n.typ, abstractVar);
+  case skipTypes(n.sons[0].typ, abstractVar).kind of
     tyOpenArray: begin
       initLocExpr(p, n.sons[0], a);
       putIntoDest(p, d, dest, ropef('$1, $1Len0', [rdLoc(a)]));
@@ -1744,7 +1759,8 @@ var
   a: TLoc;
 begin
   initLocExpr(p, n.sons[0], a);
-  putIntoDest(p, d, skipVarGeneric(n.typ), ropef('$1->data', [rdLoc(a)]));
+  putIntoDest(p, d, skipTypes(n.typ, abstractVar), 
+              ropef('$1->data', [rdLoc(a)]));
 end;
 
 procedure convCStrToStr(p: BProc; n: PNode; var d: TLoc);
@@ -1753,7 +1769,7 @@ var
 begin
   useMagic(p.module, 'cstrToNimstr');
   initLocExpr(p, n.sons[0], a);
-  putIntoDest(p, d, skipVarGeneric(n.typ),
+  putIntoDest(p, d, skipTypes(n.typ, abstractVar),
               ropef('cstrToNimstr($1)', [rdLoc(a)]));
 end;
 
@@ -1793,7 +1809,7 @@ begin
     genTypeInfo(p.module, t.typ), intLiteral(sonsLen(t))]);
   genAssignment(p, d, newSeq, {@set}[afSrcIsNotNil]);
   for i := 0 to sonsLen(t)-1 do begin
-    initLoc(arr, locExpr, elemType(skipGeneric(t.typ)), OnHeap);
+    initLoc(arr, locExpr, elemType(skipTypes(t.typ, abstractInst)), OnHeap);
     arr.r := ropef('$1->data[$2]', [rdLoc(d), intLiteral(i)]);
     arr.s := OnHeap; // we know that sequences are on the heap
     expr(p, t.sons[i], arr)
@@ -1821,10 +1837,10 @@ begin
   genAssignment(p, d, newSeq, {@set}[afSrcIsNotNil]);
   initLocExpr(p, t.sons[1], a);
   for i := 0 to L-1 do begin
-    initLoc(elem, locExpr, elemType(skipGeneric(t.typ)), OnHeap);
+    initLoc(elem, locExpr, elemType(skipTypes(t.typ, abstractInst)), OnHeap);
     elem.r := ropef('$1->data[$2]', [rdLoc(d), intLiteral(i)]);
     elem.s := OnHeap; // we know that sequences are on the heap
-    initLoc(arr, locExpr, elemType(skipGeneric(t.sons[1].typ)), a.s);
+    initLoc(arr, locExpr, elemType(skipTypes(t.sons[1].typ, abstractInst)), a.s);
     arr.r := ropef('$1[$2]', [rdLoc(a), intLiteral(i)]);
     genAssignment(p, elem, arr, {@set}[afDestIsNil, needToCopy]);
   end
@@ -1841,12 +1857,7 @@ begin
     mUnaryMinusI..mAbsI64: unaryArithOverflow(p, e, d, op);
     mShrI..mXor: binaryArith(p, e, d, op);
     mAddi..mModi64: binaryArithOverflow(p, e, d, op);
-    mRepr: genRepr(p, e, d);
-    mAsgn: begin
-      InitLocExpr(p, e.sons[1], a);
-      assert(a.t <> nil);
-      expr(p, e.sons[2], a);
-    end;
+    mRepr: genRepr(p, e, d); 
     mSwap: genSwap(p, e, d);
     mPred: begin // XXX: range checking?
       if not (optOverflowCheck in p.Options) then
@@ -1900,7 +1911,7 @@ begin
     mInc: begin
       if not (optOverflowCheck in p.Options) then
         binaryStmt(p, e, d, '', '$1 += $2;$n')
-      else if skipVarGeneric(e.sons[1].typ).kind = tyInt64 then
+      else if skipTypes(e.sons[1].typ, abstractVar).kind = tyInt64 then
         binaryStmt(p, e, d, 'addInt64', '$1 = addInt64($1, $2);$n')
       else
         binaryStmt(p, e, d, 'addInt', '$1 = addInt($1, $2);$n')
@@ -1908,7 +1919,7 @@ begin
     ast.mDec: begin
       if not (optOverflowCheck in p.Options) then
         binaryStmt(p, e, d, '', '$1 -= $2;$n')
-      else if skipVarGeneric(e.sons[1].typ).kind = tyInt64 then
+      else if skipTypes(e.sons[1].typ, abstractVar).kind = tyInt64 then
         binaryStmt(p, e, d, 'subInt64', '$1 = subInt64($1, $2);$n')
       else
         binaryStmt(p, e, d, 'subInt', '$1 = subInt($1, $2);$n')
@@ -1919,8 +1930,8 @@ begin
     mSetLengthSeq: genSetLengthSeq(p, e, d);
     mIncl, mExcl, mCard, mLtSet, mLeSet, mEqSet, mMulSet, mPlusSet,
     mMinusSet, mInSet: genSetOp(p, e, d, op);
-    mNewString, mCopyStr, mCopyStrLast: genCall(p, e, d);
-    mExit: genCall(p, e, d);
+    mNewString, mCopyStr, mCopyStrLast, mExit: genCall(p, e, d);
+    mEcho: genEcho(p, e);
     mArrToSeq: genArrToSeq(p, e, d);
     mNLen..mNError:
       liMessage(e.info, errCannotGenerateCodeForX, e.sons[0].sym.name.s);
@@ -2057,7 +2068,7 @@ begin
   if not handleConstExpr(p, n, d) then begin
     if d.k = locNone then getTemp(p, n.typ, d);
     for i := 0 to sonsLen(n)-1 do begin
-      initLoc(arr, locExpr, elemType(skipGeneric(n.typ)), d.s);
+      initLoc(arr, locExpr, elemType(skipTypes(n.typ, abstractInst)), d.s);
       arr.r := ropef('$1[$2]', [rdLoc(d), intLiteral(i)]);
       expr(p, n.sons[i], arr)
     end
@@ -2087,21 +2098,21 @@ var
   r, nilCheck: PRope;
 begin
   initLocExpr(p, n.sons[0], a);
-  dest := skipPtrsGeneric(n.typ);
+  dest := skipTypes(n.typ, abstractPtrs);
   if (optObjCheck in p.options) and not (isPureObject(dest)) then begin
     useMagic(p.module, 'chckObj');
     r := rdLoc(a);
     nilCheck := nil;
-    t := skipGeneric(a.t);
+    t := skipTypes(a.t, abstractInst);
     while t.kind in [tyVar, tyPtr, tyRef] do begin
       if t.kind <> tyVar then nilCheck := r;
       r := ropef('(*$1)', [r]);
-      t := skipGeneric(t.sons[0])
+      t := skipTypes(t.sons[0], abstractInst)
     end;
     if gCmd <> cmdCompileToCpp then
       while (t.kind = tyObject) and (t.sons[0] <> nil) do begin
         app(r, '.Sup');
-        t := skipGeneric(t.sons[0]);
+        t := skipTypes(t.sons[0], abstractInst);
       end;
     if nilCheck <> nil then
       appf(p.s[cpsStmts], 'if ($1) chckObj($2.m_type, $3);$n',
@@ -2128,11 +2139,12 @@ begin
   if gCmd = cmdCompileToCpp then
     expr(p, n.sons[0], d) // downcast does C++ for us
   else begin
-    dest := skipPtrsGeneric(n.typ);
-    src := skipPtrsGeneric(n.sons[0].typ);
+    dest := skipTypes(n.typ, abstractPtrs);
+    src := skipTypes(n.sons[0].typ, abstractPtrs);
     initLocExpr(p, n.sons[0], a);
     r := rdLoc(a);
-    if skipGeneric(n.sons[0].typ).kind in [tyRef, tyPtr, tyVar] then begin
+    if skipTypes(n.sons[0].typ, abstractInst).kind in [tyRef, tyPtr, tyVar] 
+    then begin
       app(r, '->Sup');
       for i := 2 to abs(inheritanceDiff(dest, src)) do app(r, '.Sup');
       r := con('&'+'', r);
@@ -2201,7 +2213,7 @@ begin
     end;
     nkCurly: genSetConstr(p, e, d);
     nkBracket:
-      if (skipVarGenericRange(e.typ).kind = tySequence) then  // BUGFIX
+      if (skipTypes(e.typ, abstractVarRange).kind = tySequence) then
         genSeqConstr(p, e, d)
       else
         genArrayConstr(p, e, d);
@@ -2211,8 +2223,9 @@ begin
     nkHiddenStdConv, nkHiddenSubConv, nkConv: genConv(p, e, d);
     nkHiddenAddr, nkAddr: genAddr(p, e, d);
     nkBracketExpr: begin
-      ty := skipVarGenericRange(e.sons[0].typ);
-      if ty.kind in [tyRef, tyPtr] then ty := skipVarGenericRange(ty.sons[0]);
+      ty := skipTypes(e.sons[0].typ, abstractVarRange);
+      if ty.kind in [tyRef, tyPtr] then 
+        ty := skipTypes(ty.sons[0], abstractVarRange);
       case ty.kind of
         tyArray, tyArrayConstr: genArrayElem(p, e, d);
         tyOpenArray: genOpenArrayElem(p, e, d);
@@ -2253,7 +2266,7 @@ var
 begin
   result := copyNode(n);
   newSons(result, sonsLen(n));
-  t := getUniqueType(skipVarGenericRange(n.Typ));
+  t := getUniqueType(skipTypes(n.Typ, abstractVarRange));
   if t.n = nil then
     InternalError(n.info, 'transformRecordExpr: invalid type');
   for i := 0 to sonsLen(n)-1 do begin
diff --git a/nim/ccgstmts.pas b/nim/ccgstmts.pas
index 6cff9dc8d..90e5c1c77 100644
--- a/nim/ccgstmts.pas
+++ b/nim/ccgstmts.pas
@@ -68,8 +68,8 @@ procedure initVariable(p: BProc; v: PSym);
 begin
   if containsGarbageCollectedRef(v.typ) or (v.ast = nil) then
     // Language change: always initialize variables if v.ast == nil!
-    if not (skipVarGenericRange(v.typ).Kind in [tyArray, tyArrayConstr, tySet,
-                                                tyTuple, tyObject]) then begin
+    if not (skipTypes(v.typ, abstractVarRange).Kind in [tyArray, 
+            tyArrayConstr, tySet, tyTuple, tyObject]) then begin
       if gCmd = cmdCompileToLLVM then
         appf(p.s[cpsStmts], 'store $2 0, $2* $1$n', 
              [addrLoc(v.loc), getTypeDesc(p.module, v.loc.t)])
@@ -618,7 +618,7 @@ end;
 procedure genCaseStmt(p: BProc; t: PNode);
 begin
   genLineDir(p, t);
-  case skipVarGenericRange(t.sons[0].typ).kind of
+  case skipTypes(t.sons[0].typ, abstractVarRange).kind of
     tyString: genStringCase(p, t);
     tyFloat..tyFloat128:
       genCaseGeneric(p, t, 'if ($1 >= $2 && $1 <= $3) goto $4;$n',
diff --git a/nim/ccgtypes.pas b/nim/ccgtypes.pas
index 28db6e009..f9b3a36c1 100644
--- a/nim/ccgtypes.pas
+++ b/nim/ccgtypes.pas
@@ -62,7 +62,7 @@ begin
     app(result, toRope(s.id));
     if optGenMapping in gGlobalOptions then
       if s.owner <> nil then
-        appf(gMapping, '"$1.$2": $3$n',
+        appf(gMapping, 'r"$1.$2": $3$n',
           [toRope(s.owner.Name.s), toRope(s.name.s), result]);
     s.loc.r := result;
   end
@@ -116,8 +116,9 @@ begin
     end;
     tyOpenArray, tyArrayConstr, tyArray: result := ctArray;
     tyObject, tyTuple: result := ctStruct;
-    tyGeneric, tyGenericInst, tyGenericParam: result := mapType(lastSon(typ));
-    tyEnum, tyAnyEnum: begin
+    tyGeneric, tyGenericInst, tyGenericParam, tyAbstract, tyOrdinal: 
+      result := mapType(lastSon(typ));
+    tyEnum: begin
       if firstOrd(typ) < 0 then
         result := ctInt32
       else begin
@@ -150,7 +151,7 @@ end;
 
 function mapReturnType(typ: PType): TCTypeKind;
 begin
-  if skipGeneric(typ).kind = tyArray then result := ctPtr
+  if skipTypes(typ, abstractInst).kind = tyArray then result := ctPtr
   else result := mapType(typ)
 end;
 
@@ -173,8 +174,9 @@ begin
   else begin
     case mapType(rettype) of
       ctArray:
-        result := not (skipGeneric(rettype).kind in [tyVar, tyRef, tyPtr]);
-      ctStruct: result := needsComplexAssignment(skipGeneric(rettype));
+        result := not (skipTypes(rettype, abstractInst).kind in [tyVar, tyRef, tyPtr]);
+      ctStruct: 
+        result := needsComplexAssignment(skipTypes(rettype, abstractInst));
       else result := false;
     end
   end
@@ -285,7 +287,6 @@ begin
   if (t.sons[0] <> nil) and isInvalidReturnType(t.sons[0]) then begin
     if params <> nil then app(params, ', ');
     arr := t.sons[0];
-    //if skipGeneric(arr).kind = tyArray then arr := arr.sons[1];
     app(params, getTypeDescAux(m, arr, check));
     if (mapReturnType(t.sons[0]) <> ctArray) or (gCmd = cmdCompileToLLVM) then 
       app(params, '*'+'');
@@ -612,7 +613,7 @@ begin
       IdTablePut(m.typeCache, t, con(result, '*'+''));
       if not isImportedType(t) then begin
         useMagic(m, 'TGenericSeq');
-        if skipGeneric(t.sons[0]).kind <> tyEmpty then 
+        if skipTypes(t.sons[0], abstractInst).kind <> tyEmpty then 
           appf(m.s[cfsSeqTypes],
             'struct $2 {$n' +
             '  TGenericSeq Sup;$n' +
@@ -663,7 +664,8 @@ begin
         end
       end
     end;
-    tyGenericInst: result := getTypeDescAux(m, lastSon(t), check);
+    tyGenericInst, tyAbstract, tyOrdinal: 
+      result := getTypeDescAux(m, lastSon(t), check);
     else begin
       InternalError('getTypeDescAux(' + typeKindToStr[t.kind] + ')');
       result := nil
diff --git a/nim/ccgutils.pas b/nim/ccgutils.pas
index 49c1a8cee..de5cac13c 100644
--- a/nim/ccgutils.pas
+++ b/nim/ccgutils.pas
@@ -1,7 +1,7 @@
 //
 //
 //           The Nimrod Compiler
-//        (c) Copyright 2008 Andreas Rumpf
+//        (c) Copyright 2009 Andreas Rumpf
 //
 //    See the file "copying.txt", included in this
 //    distribution, for details about the copyright.
@@ -56,7 +56,8 @@ begin
         result := key;
       end
     end;
-    tyGenericInst: result := GetUniqueType(lastSon(key));
+    tyGenericInst, tyAbstract, tyOrdinal: 
+      result := GetUniqueType(lastSon(key));
     tyProc: begin end;
     else begin
       // we have to do a slow linear search because types may need
@@ -75,7 +76,7 @@ begin
     tyInt..tyFloat128, tyProc, tyAnyEnum: begin end;
     tyNone, tyForward: 
       InternalError('GetUniqueType: ' + typeToString(key));
-    tyGenericParam, tyGeneric, tySequence,
+    tyGenericParam, tyGeneric, tyAbstract, tySequence,
     tyOpenArray, tySet, tyVar, tyRef, tyPtr, tyArrayConstr,
     tyArray, tyTuple, tyRange: begin
       // we have to do a slow linear search because types may need
@@ -94,7 +95,7 @@ begin
         result := key;
       end
     end;
-    tyGenericInst: result := GetUniqueType(lastSon(key));
+    tyGenericInst, tyAbstract: result := GetUniqueType(lastSon(key));
   end; *)
 end;
 
diff --git a/nim/cgen.pas b/nim/cgen.pas
index 6a0ab0390..fdae6feb6 100644
--- a/nim/cgen.pas
+++ b/nim/cgen.pas
@@ -1,7 +1,7 @@
 //
 //
 //           The Nimrod Compiler
-//        (c) Copyright 2008 Andreas Rumpf
+//        (c) Copyright 2009 Andreas Rumpf
 //
 //    See the file "copying.txt", included in this
 //    distribution, for details about the copyright.
@@ -232,8 +232,8 @@ end;
 
 function isSimpleConst(typ: PType): bool;
 begin
-  result := not (skipVarGeneric(typ).kind in [tyTuple, tyObject, tyArray,
-                                            tyArrayConstr, tySet, tySequence])
+  result := not (skipTypes(typ, abstractVar).kind in [tyTuple, tyObject, 
+    tyArray, tyArrayConstr, tySet, tySequence])
 end;
 
 procedure useHeader(m: BModule; sym: PSym);
@@ -249,12 +249,6 @@ procedure UseMagic(m: BModule; const name: string); forward;
 {$include 'ccgtypes.pas'}
 
 // ------------------------------ Manager of temporaries ------------------
-(*
-function beEqualTypes(a, b: PType): bool;
-begin
-  // returns whether two type are equal for the backend
-  result := sameType(skipGenericRange(a), skipGenericRange(b))
-end; *)
 
 procedure getTemp(p: BProc; t: PType; var result: TLoc);
 begin
@@ -458,9 +452,35 @@ procedure genProcPrototype(m: BModule; sym: PSym); forward;
 
 // We don't finalize dynamic libs as this does the OS for us.
 
+procedure libCandidates(const s: string; var dest: TStringSeq);
+var
+  prefix, suffix: string;
+  le, ri, i, L: int;
+  temp: TStringSeq;
+begin
+  le := strutils.find(s, '(');
+  ri := strutils.find(s, ')');
+  if (le >= strStart) and (ri > le) then begin
+    prefix := ncopy(s, strStart, le-1);
+    suffix := ncopy(s, ri+1);
+    temp := splitSeq(ncopy(s, le+1, ri-1), {@set}['|']);
+    for i := 0 to high(temp) do 
+      libCandidates(prefix +{&} temp[i] +{&} suffix, dest);
+  end
+  else begin
+    {@ignore} 
+    L := length(dest);
+    setLength(dest, L+1);
+    dest[L] := s;
+    {@emit add(dest, s);}
+  end
+end;
+
 procedure loadDynamicLib(m: BModule; lib: PLib);
 var
-  tmp: PRope;
+  tmp, loadlib: PRope;
+  s: TStringSeq;
+  i: int;
 begin
   assert(lib <> nil);
   if not lib.generated then begin
@@ -471,18 +491,29 @@ begin
     // BUGFIX: useMagic has awful side-effects
     appff(m.s[cfsVars], 'static void* $1;$n', 
                         '$1 = linkonce global i8* zeroinitializer$n', [tmp]);
-    inc(m.labels);
-    appff(m.s[cfsDynLibInit],
-        '$1 = nimLoadLibrary((NimStringDesc*) &$2);$n',
-        '%MOC$4 = call i8* @nimLoadLibrary($3 $2)$n' +
-        'store i8* %MOC$4, i8** $1$n',
-        [tmp, getStrLit(m, lib.path), getTypeDesc(m, getSysType(tyString)),
-         toRope(m.labels)]);
+    {@ignore} s := nil; {@emit s := @[];}
+    libCandidates(lib.path, s);
+    loadlib := nil;
+    for i := 0 to high(s) do begin
+      inc(m.labels);
+      if i > 0 then app(loadlib, '||');
+      appff(loadlib,
+          '($1 = nimLoadLibrary((NimStringDesc*) &$2))$n',
+          '%MOC$4 = call i8* @nimLoadLibrary($3 $2)$n' +
+          'store i8* %MOC$4, i8** $1$n',
+          [tmp, getStrLit(m, s[i]), getTypeDesc(m, getSysType(tyString)),
+           toRope(m.labels)]);
+    end;
+    appff(m.s[cfsDynLibInit], 
+         'if (!($1)) nimLoadLibraryError((NimStringDesc*) &$2);$n', 
+         'XXX too implement',
+         [loadlib, getStrLit(m, lib.path)]);
     //appf(m.s[cfsDynLibDeinit],
     //  'if ($1 != NIM_NIL) nimUnloadLibrary($1);$n', [tmp]);
     useMagic(m, 'nimLoadLibrary');
     useMagic(m, 'nimUnloadLibrary');
     useMagic(m, 'NimStringDesc');
+    useMagic(m, 'nimLoadLibraryError');
   end;
   if lib.name = nil then InternalError('loadDynamicLib');
 end;
@@ -642,7 +673,7 @@ begin
     else begin
       fillResult(res);
       assignParam(p, res);
-      if skipGeneric(res.typ).kind = tyArray then begin
+      if skipTypes(res.typ, abstractInst).kind = tyArray then begin
         include(res.loc.flags, lfIndirect);
         res.loc.s := OnUnknown;
       end;
@@ -745,6 +776,7 @@ end;
 
 procedure genProc(m: BModule; prc: PSym);
 begin
+  if sfBorrow in prc.flags then exit;
   fillProcLoc(prc);
   if [sfForward, sfFromGeneric] * prc.flags <> [] then 
     addForwardedProc(m, prc)
@@ -1148,7 +1180,6 @@ begin
     addFileToCompile(cfilenoext);
   end;
   addFileToLink(cfilenoext);
-  if sfMainModule in m.module.flags then writeMapping(cfile, gMapping);
 end;
 
 function myClose(b: PPassContext; n: PNode): PNode;
@@ -1177,6 +1208,7 @@ begin
         finishModule(gPendingModules[i]);
     for i := 0 to high(gPendingModules) do writeModule(gPendingModules[i]);
     setLength(gPendingModules, 0);
+    writeMapping(gMapping);
   end;
   if not (optDeadCodeElim in gGlobalOptions) and 
       not (sfDeadCodeElim in m.module.flags) then
diff --git a/nim/commands.pas b/nim/commands.pas
index fde2d26c7..df6ab9da7 100644
--- a/nim/commands.pas
+++ b/nim/commands.pas
@@ -150,7 +150,8 @@ begin
   if (pass = passCmd1) and not helpWritten then begin

     // BUGFIX 19

     MessageOut(getCommandLineDesc());

-    helpWritten := true

+    helpWritten := true;
+    halt(0);

   end

 end;

 

diff --git a/nim/condsyms.pas b/nim/condsyms.pas
index 1df513bbc..465bc045e 100644
--- a/nim/condsyms.pas
+++ b/nim/condsyms.pas
@@ -111,8 +111,7 @@ begin
       DefineSymbol('mswindows');
       DefineSymbol('win32');
     end;
-    osLinux, osMorphOS, osSkyOS, osIrix, osPalmOS, osQNX,
-    osAtari, osAix: begin
+    osLinux, osMorphOS, osSkyOS, osIrix, osPalmOS, osQNX, osAtari, osAix: begin
       // these are all 'unix-like'
       DefineSymbol('unix');
       DefineSymbol('posix');
diff --git a/nim/docgen.pas b/nim/docgen.pas
index 784ab6c6c..5e8ecf7a3 100644
--- a/nim/docgen.pas
+++ b/nim/docgen.pas
@@ -235,6 +235,8 @@ begin
 end;
 
 function toXml(const s: string; splitAfter: int = -1): string;
+const
+  splitter = '<wbr />';
 var
   i, j, k, partLen: int;
 begin
@@ -244,9 +246,9 @@ begin
     j := strStart;
     while j < length(s)+strStart do begin
       k := nextSplitPoint(s, j);
-      if partLen + k - j + 1 > splitAfter then begin
+      if (splitter <> ' '+'') or (partLen + k - j + 1 > splitAfter) then begin
         partLen := 0;
-        addChar(result, ' ');
+        add(result, splitter);
       end;
       for i := j to k do addXmlChar(result, s[i]);
       inc(partLen, k - j + 1);
@@ -691,9 +693,10 @@ var
   langstr: string;
   lang: TSourceLanguage;
 begin
+  result := nil;
+  if n.sons[2] = nil then exit;
   m := n.sons[2].sons[0];
   if (m.kind <> rnLeaf) then InternalError('renderCodeBlock');
-  result := nil;
   langstr := strip(getArgument(n));
   if langstr = '' then lang := langNimrod // default language
   else lang := getSourceLanguage(langstr);
@@ -996,7 +999,6 @@ begin
   rst := rstParse(readFile(filen), false, filen, 0, 1, d.hasToc);
   d.modDesc := renderRstToHtml(d, rst);
   code := genHtmlFile(d);
-  assert(ropeInvariant(code));
   writeRope(code, getOutFile(filename, HtmlExt));
   generateIndex(d);
 end;
diff --git a/nim/ecmasgen.pas b/nim/ecmasgen.pas
index 2eecfba71..9ffa550ae 100644
--- a/nim/ecmasgen.pas
+++ b/nim/ecmasgen.pas
@@ -109,7 +109,7 @@ const
 
 function mapType(typ: PType): TEcmasTypeKind;
 begin
-  case skipGeneric(typ).kind of
+  case skipTypes(typ, abstractInst).kind of
     tyVar, tyRef, tyPtr: begin
       if typ.sons[0].kind in mappedToObject then
         result := etyObject
@@ -120,8 +120,8 @@ begin
       // treat a tyPointer like a typed pointer to an array of bytes
       result := etyInt;
     end;
-    tyRange: result := mapType(typ.sons[0]);
-    tyInt..tyInt64, tyEnum, tyAnyEnum, tyChar:
+    tyRange, tyAbstract, tyOrdinal: result := mapType(typ.sons[0]);
+    tyInt..tyInt64, tyEnum, tyChar:
       result := etyInt;
     tyBool: result := etyBool;
     tyFloat..tyFloat128: result := etyFloat;
@@ -298,7 +298,8 @@ begin
   if t.kind = tyGenericInst then t := lastSon(t);
   result := ropef('NTI$1', [toRope(t.id)]);
   if IntSetContainsOrIncl(p.globals.TypeInfoGenerated, t.id) then exit;
-  case t.kind of
+  case t.kind of 
+    tyAbstract: result := genTypeInfo(p, typ.sons[0]);
     tyPointer, tyProc, tyBool, tyChar, tyCString, tyString,
     tyInt..tyFloat128: begin
       s := ropef(
@@ -676,7 +677,7 @@ begin
   if n.sons[0] <> nil then begin
     gen(p, n.sons[0], a);
     if a.com <> nil then appf(r.com, '$1;$n', [a.com]);
-    typ := skipPtrsGeneric(n.sons[0].typ);
+    typ := skipTypes(n.sons[0].typ, abstractPtrs);
     useMagic(p, 'raiseException');
     appf(r.com, 'raiseException($1, $2);$n',
       [a.res, makeCString(typ.sym.name.s)]);
@@ -698,7 +699,7 @@ begin
   gen(p, n.sons[0], cond);
   if cond.com <> nil then
     appf(r.com, '$1;$n', [cond.com]);
-  stringSwitch := skipVarGeneric(n.sons[0].typ).kind = tyString;
+  stringSwitch := skipTypes(n.sons[0].typ, abstractVar).kind = tyString;
   if stringSwitch then begin
     useMagic(p, 'toEcmaStr');
     appf(r.com, 'switch (toEcmaStr($1)) {$n', [cond.res])
@@ -888,12 +889,12 @@ const
                                nkFloatLit..nkFloat64Lit,
                                nkCurly, nkPar, 
                                nkStringToCString, nkCStringToString,
-                               nkCall, nkHiddenCallConv];
+                               nkCall, nkCommand, nkHiddenCallConv];
 
 function needsNoCopy(y: PNode): bool;
 begin
   result := (y.kind in nodeKindsNeedNoCopy)
-      or (skipGeneric(y.typ).kind in [tyRef, tyPtr, tyVar])
+      or (skipTypes(y.typ, abstractInst).kind in [tyRef, tyPtr, tyVar])
 end;
 
 procedure genAsgnAux(var p: TProc; x, y: PNode; var r: TCompRes;
@@ -1014,7 +1015,7 @@ begin
   gen(p, n.sons[0], a);
   gen(p, n.sons[1], b);
   r.com := mergeExpr(a);
-  typ := skipPtrsGeneric(n.sons[0].typ);
+  typ := skipTypes(n.sons[0].typ, abstractPtrs);
   if typ.kind in [tyArray, tyArrayConstr] then first := FirstOrd(typ.sons[0])
   else first := 0;
   if (optBoundsCheck in p.options) and not isConstExpr(n.sons[1]) then begin
@@ -1201,9 +1202,9 @@ var
   i, len, c: int;
   t, e: PType;
 begin
-  t := skipGeneric(typ);
+  t := skipTypes(typ, abstractInst);
   case t.kind of
-    tyInt..tyInt64, tyEnum, tyAnyEnum, tyChar: begin
+    tyInt..tyInt64, tyEnum, tyChar: begin
       result := putToSeq('0'+'', indirect)
     end;
     tyFloat..tyFloat128: result := putToSeq('0.0', indirect);
@@ -1354,15 +1355,15 @@ var
   t: Ptype;
 begin
   gen(p, n.sons[1], a);
-  t := skipVarGeneric(n.sons[1].typ).sons[0];
+  t := skipTypes(n.sons[1].typ, abstractVar).sons[0];
   if a.com <> nil then appf(r.com, '$1;$n', [a.com]);
   appf(r.com, '$1 = $2;$n', [a.res, createVar(p, t, true)]);
 end;
 
 procedure genOrd(var p: TProc; n: PNode; var r: TCompRes);
 begin
-  case skipVarGeneric(n.sons[1].typ).kind of
-    tyEnum, tyAnyEnum, tyInt..tyInt64, tyChar: gen(p, n.sons[1], r);
+  case skipTypes(n.sons[1].typ, abstractVar).kind of
+    tyEnum, tyInt..tyInt64, tyChar: gen(p, n.sons[1], r);
     tyBool: unaryExpr(p, n, r, '', '($1 ? 1:0)');
     else InternalError(n.info, 'genOrd');
   end
@@ -1375,9 +1376,9 @@ begin
   gen(p, n.sons[1], a);
   gen(p, n.sons[2], b);
   r.com := mergeExpr(a.com, b.com);
-  if skipVarGenericRange(n.sons[1].typ).kind = tyChar then
+  if skipTypes(n.sons[1].typ, abstractVarRange).kind = tyChar then
     a.res := ropef('[$1, 0]', [a.res]);
-  if skipVarGenericRange(n.sons[2].typ).kind = tyChar then
+  if skipTypes(n.sons[2].typ, abstractVarRange).kind = tyChar then
     b.res := ropef('[$1, 0]', [b.res]);
   r.res := ropef('($1.slice(0,-1)).concat($2)', [a.res, b.res]);
 end;
@@ -1435,7 +1436,7 @@ begin
     mLengthSeq, mLengthOpenArray, mLengthArray:
       unaryExpr(p, n, r, '', '$1.length');
     mHigh: begin
-      if skipVarGeneric(n.sons[0].typ).kind = tyString then
+      if skipTypes(n.sons[0].typ, abstractVar).kind = tyString then
         unaryExpr(p, n, r, '', '($1.length-2)')
       else
         unaryExpr(p, n, r, '', '($1.length-1)');
@@ -1535,8 +1536,8 @@ procedure genConv(var p: TProc; n: PNode; var r: TCompRes);
 var
   src, dest: PType;
 begin
-  dest := skipVarGenericRange(n.typ);
-  src := skipVarGenericRange(n.sons[1].typ);
+  dest := skipTypes(n.typ, abstractVarRange);
+  src := skipTypes(n.sons[1].typ, abstractVarRange);
   gen(p, n.sons[1], r);
   if (dest.kind <> src.kind) and (src.kind = tyBool) then
     r.res := ropef('(($1)? 1:0)', [r.res])
@@ -1750,7 +1751,7 @@ begin
         r.res := toRope('null');
     end;
     nkStrLit..nkTripleStrLit: begin
-      if skipVarGenericRange(n.typ).kind = tyString then begin
+      if skipTypes(n.typ, abstractVarRange).kind = tyString then begin
         useMagic(p, 'cstrToNimstr');
         r.res := ropef('cstrToNimstr($1)', [makeCString(n.strVal)])
       end
@@ -1771,7 +1772,7 @@ begin
     end;
     nkBlockExpr: genBlock(p, n, r);
     nkIfExpr: genIfExpr(p, n, r);
-    nkCall, nkHiddenCallConv: begin
+    nkCall, nkHiddenCallConv, nkCommand: begin
       if (n.sons[0].kind = nkSym) and (n.sons[0].sym.magic <> mNone) then
         genMagic(p, n, r)
       else
diff --git a/nim/evals.pas b/nim/evals.pas
index 218046c7e..7c443bad6 100644
--- a/nim/evals.pas
+++ b/nim/evals.pas
@@ -27,10 +27,10 @@ type
   PStackFrame = ^TStackFrame;
   TStackFrame = record
     mapping: TIdNodeTable; // mapping from symbols to nodes
-    prc: PSym;        // current prc; proc that is evaluated
+    prc: PSym;             // current prc; proc that is evaluated
     call: PNode;
-    next: PStackFrame;   // for stacking
-    params: TNodeSeq;  // parameters passed to the proc
+    next: PStackFrame;     // for stacking
+    params: TNodeSeq;      // parameters passed to the proc
   end;
   
   TEvalContext = object(passes.TPassContext)
@@ -264,7 +264,7 @@ var
   i: int;
   t: PType;
 begin
-  t := skipGenericRange(typ);
+  t := skipTypes(typ, abstractRange);
   result := emptyNode;
   case t.kind of
     tyBool, tyChar, tyInt..tyInt64: result := newNodeIT(nkIntLit, info, t);
@@ -527,6 +527,27 @@ begin
   result := emptyNode
 end;
 
+function getStrValue(n: PNode): string;
+begin
+  case n.kind of
+    nkStrLit..nkTripleStrLit: result := n.strVal;
+    else begin InternalError(n.info, 'getStrValue'); result := '' end;
+  end
+end;
+
+function evalEcho(c: PEvalContext; n: PNode): PNode;
+var
+  i: int;
+begin
+  for i := 1 to sonsLen(n)-1 do begin
+    result := evalAux(c, n.sons[i]);
+    if result.kind = nkExceptBranch then exit;
+    Write(output, getStrValue(result));
+  end;
+  writeln(output, '');
+  result := emptyNode
+end;
+
 function evalExit(c: PEvalContext; n: PNode): PNode;
 begin
   result := evalAux(c, n.sons[1]);
@@ -555,7 +576,7 @@ function evalNew(c: PEvalContext; n: PNode): PNode;
 var
   t: PType;
 begin
-  t := skipVarGeneric(n.sons[1].typ);
+  t := skipTypes(n.sons[1].typ, abstractVar);
   result := newNodeIT(nkRefTy, n.info, t);
   addSon(result, getNullValue(t.sons[0], n.info));
 end;
@@ -604,8 +625,8 @@ var
 begin
   result := evalAux(c, n.sons[0]);
   if result.kind = nkExceptBranch then exit;
-  dest := skipPtrsGeneric(n.typ);
-  src := skipPtrsGeneric(result.typ);
+  dest := skipTypes(n.typ, abstractPtrs);
+  src := skipTypes(result.typ, abstractPtrs);
   if inheritanceDiff(src, dest) > 0 then
     stackTrace(c, n, errInvalidConversionFromTypeX, typeToString(src));
 end;
@@ -700,7 +721,7 @@ function evalHigh(c: PEvalContext; n: PNode): PNode;
 begin
   result := evalAux(c, n.sons[1]);
   if result.kind = nkExceptBranch then exit;
-  case skipVarGeneric(n.sons[1].typ).kind of
+  case skipTypes(n.sons[1].typ, abstractVar).kind of
     tyOpenArray, tySequence:
       result := newIntNodeT(sonsLen(result), n);
     tyString:
@@ -749,7 +770,7 @@ begin
   oldLen := sonsLen(a);
   setLength(a.sons, newLen);
   for i := oldLen to newLen-1 do
-    a.sons[i] := getNullValue(skipVarGeneric(n.sons[1].typ), n.info);
+    a.sons[i] := getNullValue(skipTypes(n.sons[1].typ, abstractVar), n.info);
   result := emptyNode
 end;
 
@@ -766,7 +787,7 @@ begin
   if result.kind = nkExceptBranch then exit;
   b := result;
 
-  t := skipVarGeneric(n.sons[1].typ);
+  t := skipTypes(n.sons[1].typ, abstractVar);
   if a.kind = nkEmpty then InternalError(n.info, 'first parameter is empty');
   a.kind := nkBracket;
   a.info := n.info;
@@ -835,14 +856,6 @@ begin
   result := emptyNode;
 end;
 
-function getStrValue(n: PNode): string;
-begin
-  case n.kind of
-    nkStrLit..nkTripleStrLit: result := n.strVal;
-    else begin InternalError(n.info, 'getStrValue'); result := '' end;
-  end
-end;
-
 function evalConStrStr(c: PEvalContext; n: PNode): PNode;
 // we cannot use ``evalOp`` for this as we can here have more than 2 arguments
 var
@@ -936,6 +949,7 @@ begin
     mSwap: result := evalSwap(c, n);
     mInc: result := evalIncDec(c, n, 1);
     ast.mDec: result := evalIncDec(c, n, -1);
+    mEcho: result := evalEcho(c, n);
     mSetLengthStr: result := evalSetLengthStr(c, n);
     mSetLengthSeq: result := evalSetLengthSeq(c, n);
     mIncl: result := evalIncl(c, n);
@@ -1237,7 +1251,8 @@ begin
     nkType..pred(nkNilLit): result := copyNode(n);
     nkNilLit: result := n; // end of atoms
 
-    nkCall, nkHiddenCallConv, nkMacroStmt: result := evalMagicOrCall(c, n);
+    nkCall, nkHiddenCallConv, nkMacroStmt, nkCommand: 
+      result := evalMagicOrCall(c, n);
     nkCurly, nkBracket, nkRange: begin
       result := copyNode(n);
       for i := 0 to sonsLen(n)-1 do addSon(result, evalAux(c, n.sons[i]));
diff --git a/nim/extccomp.pas b/nim/extccomp.pas
index a53ad1c10..a3e4ff367 100644
--- a/nim/extccomp.pas
+++ b/nim/extccomp.pas
@@ -288,7 +288,7 @@ function NameToCC(const name: string): TSystemCC;
 procedure initVars;
 
 procedure setCC(const ccname: string);
-procedure writeMapping(const cfile: string; gSymbolMapping: PRope);
+procedure writeMapping(gSymbolMapping: PRope);
 
 implementation
 
@@ -638,12 +638,12 @@ begin
   result := nil;
   it := PStrEntry(list.head);
   while it <> nil do begin
-    appf(result, '--file:"$1"$n', [toRope(AppendFileExt(it.data, cExt))]);
+    appf(result, '--file:r"$1"$n', [toRope(AppendFileExt(it.data, cExt))]);
     it := PStrEntry(it.next);
   end;
 end;
 
-procedure writeMapping(const cfile: string; gSymbolMapping: PRope);
+procedure writeMapping(gSymbolMapping: PRope);
 var
   code: PRope;
 begin
diff --git a/nim/magicsys.pas b/nim/magicsys.pas
index 462912995..db801d5f2 100644
--- a/nim/magicsys.pas
+++ b/nim/magicsys.pas
@@ -76,7 +76,6 @@ begin
       tyString:  result := sysTypeFromName('string');
       tyCstring: result := sysTypeFromName('cstring');
       tyPointer: result := sysTypeFromName('pointer');
-      tyAnyEnum: result := newSysType(tyAnyEnum, 1);
       tyNil: result := newSysType(tyNil, ptrSize);
       else InternalError('request for typekind: ' + typeKindToStr[kind]);
     end;  
diff --git a/nim/msgs.pas b/nim/msgs.pas
index d7f0d9f82..48ffc9ee5 100644
--- a/nim/msgs.pas
+++ b/nim/msgs.pas
@@ -49,557 +49,557 @@ uses
 //cog.out(warns)

 //cog.out(hints)

 //]]]

-type

-  TMsgKind = (

-    errUnknown,

-    errIllFormedAstX,

-    errCannotOpenFile,

-    errInternal,

-    errGenerated,

-    errXCompilerDoesNotSupportCpp,

-    errStringLiteralExpected,

-    errIntLiteralExpected,

-    errInvalidCharacterConstant,

-    errClosingTripleQuoteExpected,

-    errClosingQuoteExpected,

-    errTabulatorsAreNotAllowed,

-    errInvalidToken,

-    errLineTooLong,

-    errInvalidNumber,

-    errNumberOutOfRange,

-    errNnotAllowedInCharacter,

-    errClosingBracketExpected,

-    errMissingFinalQuote,

-    errIdentifierExpected,

-    errOperatorExpected,

-    errTokenExpected,

-    errStringAfterIncludeExpected,

-    errRecursiveInclude,

-    errOnOrOffExpected,

-    errNoneSpeedOrSizeExpected,

-    errInvalidPragma,

-    errUnknownPragma,

-    errPragmaXHereNotAllowed,

-    errUnknownDirective,

-    errInvalidDirective,

-    errAtPopWithoutPush,

-    errEmptyAsm,

-    errAsgnInvalidInExpr,

-    errInvalidIndentation,

-    errExceptionExpected,

-    errExceptionAlreadyHandled,

-    errReturnNotAllowedHere,

-    errYieldNotAllowedHere,

-    errInvalidNumberOfYieldExpr,

-    errReturnInvalidInIterator,

-    errCannotReturnExpr,

-    errAttemptToRedefine,

-    errStmtInvalidAfterReturn,

-    errStmtExpected,

-    errInvalidLabel,

-    errInvalidCmdLineOption,

-    errCmdLineArgExpected,

-    errCmdLineNoArgExpected,

-    errInvalidVarSubstitution,

-    errUnknownVar,

-    errUnknownCcompiler,

-    errOnOrOffExpectedButXFound,

-    errNoneBoehmRefcExpectedButXFound,

-    errNoneSpeedOrSizeExpectedButXFound,

-    errGuiConsoleOrLibExpectedButXFound,

-    errUnknownOS,

-    errUnknownCPU,

-    errGenOutExpectedButXFound,

-    errArgsNeedRunOption,

-    errInvalidMultipleAsgn,

-    errColonOrEqualsExpected,

-    errExprExpected,

-    errUndeclaredIdentifier,

-    errUseQualifier,

-    errTwiceForwarded,

-    errTypeExpected,

-    errSystemNeeds,

-    errExecutionOfProgramFailed,

-    errNotOverloadable,

-    errInvalidArgForX,

-    errStmtHasNoEffect,

-    errXExpectsTypeOrValue,

-    errXExpectsArrayType,

-    errIteratorCannotBeInstantiated,

-    errExprWithNoTypeCannotBeConverted,

-    errExprWithNoTypeCannotBeCasted,

-    errConstantDivisionByZero,

-    errOrdinalTypeExpected,

-    errOrdinalOrFloatTypeExpected,

-    errOverOrUnderflow,

-    errCannotEvalXBecauseIncompletelyDefined,

-    errChrExpectsRange0_255,

-    errStaticAssertFailed,

-    errStaticAssertCannotBeEval,

-    errDotRequiresRecordOrObjectType,

-    errUndeclaredFieldX,

-    errNilAccess,

-    errIndexOutOfBounds,

-    errIndexTypesDoNotMatch,

-    errBracketsInvalidForType,

-    errValueOutOfSetBounds,

-    errFieldInitTwice,

-    errFieldNotInit,

-    errExprCannotBeCalled,

-    errExprHasNoType,

-    errExprXHasNoType,

-    errCastNotInSafeMode,

-    errExprCannotBeCastedToX,

-    errUndefinedPrefixOpr,

-    errCommaOrParRiExpected,

-    errCurlyLeOrParLeExpected,

-    errSectionExpected,

-    errImplemenationExpected,

-    errRangeExpected,

-    errInvalidTypeDescription,

-    errAttemptToRedefineX,

-    errMagicOnlyInSystem,

-    errUnknownOperatorX,

-    errPowerOfTwoExpected,

-    errStringMayNotBeEmpty,

-    errCallConvExpected,

-    errProcOnlyOneCallConv,

-    errSymbolMustBeImported,

-    errExprMustBeBool,

-    errConstExprExpected,

-    errDuplicateCaseLabel,

-    errRangeIsEmpty,

-    errSelectorMustBeOfCertainTypes,

-    errSelectorMustBeOrdinal,

-    errOrdXMustNotBeNegative,

-    errLenXinvalid,

-    errWrongNumberOfVariables,

-    errExprCannotBeRaised,

-    errBreakOnlyInLoop,

-    errTypeXhasUnknownSize,

-    errConstNeedsConstExpr,

-    errConstNeedsValue,

-    errResultCannotBeOpenArray,

-    errSizeTooBig,

-    errSetTooBig,

-    errBaseTypeMustBeOrdinal,

-    errInheritanceOnlyWithNonFinalObjects,

-    errInheritanceOnlyWithEnums,

-    errIllegalRecursionInTypeX,

-    errCannotInstantiateX,

-    errExprHasNoAddress,

-    errVarForOutParamNeeded,

-    errPureTypeMismatch,

-    errTypeMismatch,

-    errButExpected,

-    errButExpectedX,

-    errAmbigiousCallXYZ,

-    errWrongNumberOfTypeParams,

-    errOutParamNoDefaultValue,

-    errInlineProcHasNoAddress,

-    errXCannotBeInParamDecl,

-    errPragmaOnlyInHeaderOfProc,

-    errImportedProcCannotHaveImpl,

-    errImplOfXNotAllowed,

-    errImplOfXexpected,

-    errDiscardValue,

-    errInvalidDiscard,

-    errUnknownPrecedence,

-    errIllegalConvFromXtoY,

-    errTypeMismatchExpectedXGotY,

-    errCannotBindXTwice,

-    errInvalidOrderInEnumX,

-    errEnumXHasWholes,

-    errExceptExpected,

-    errInvalidTry,

-    errEofExpectedButXFound,

-    errOptionExpected,

-    errCannotEvaluateForwardConst,

-    errXisNoLabel,

-    errXNeedsConcreteType,

-    errNotAllCasesCovered,

-    errStringRange,

-    errUnkownSubstitionVar,

-    errComplexStmtRequiresInd,

-    errXisNotCallable,

-    errNoPragmasAllowedForX,

-    errNoGenericParamsAllowedForX,

-    errInvalidParamKindX,

-    errDefaultArgumentInvalid,

-    errNamedParamHasToBeIdent,

-    errNoReturnTypeForX,

-    errConvNeedsOneArg,

-    errInvalidPragmaX,

-    errXNotAllowedHere,

-    errInvalidControlFlowX,

-    errATypeHasNoValue,

-    errXisNoType,

-    errCircumNeedsPointer,

-    errInvalidContextForBuiltinX,

-    errInvalidExpression,

-    errInvalidExpressionX,

-    errEnumHasNoValueX,

-    errNamedExprExpected,

-    errNamedExprNotAllowed,

-    errXExpectsOneTypeParam,

-    errArrayExpectsTwoTypeParams,

-    errInvalidVisibilityX,

-    errInitHereNotAllowed,

-    errXCannotBeAssignedTo,

-    errIteratorNotAllowed,

-    errIteratorNeedsImplementation,

-    errIteratorNeedsReturnType,

-    errInvalidCommandX,

-    errXOnlyAtModuleScope,

-    errTypeXNeedsImplementation,

-    errTemplateInstantiationTooNested,

-    errInstantiationFrom,

-    errInvalidIndexValueForTuple,

-    errCommandExpectsFilename,

-    errXExpected,

-    errInvalidSectionStart,

-    errGridTableNotImplemented,

-    errGeneralParseError,

-    errNewSectionExpected,

-    errWhitespaceExpected,

-    errXisNoValidIndexFile,

-    errCannotRenderX,

-    errVarVarTypeNotAllowed,

-    errIsExpectsTwoArguments,

-    errIsExpectsObjectTypes,

-    errXcanNeverBeOfThisSubtype,

-    errTooManyIterations,

-    errCannotInterpretNodeX,

-    errFieldXNotFound,

-    errInvalidConversionFromTypeX,

-    errAssertionFailed,

-    errCannotGenerateCodeForX,

-    errXNeedsReturnType,

-    errXRequiresOneArgument,

-    errUnhandledExceptionX,

-    errCyclicTree,

-    errXisNoMacroOrTemplate,

-    errUser,

-    warnCannotOpenFile,

-    warnOctalEscape,

-    warnXIsNeverRead,

-    warnXmightNotBeenInit,

-    warnCannotWriteMO2,

-    warnCannotReadMO2,

-    warnDeprecated,

-    warnSmallLshouldNotBeUsed,

-    warnUnknownMagic,

-    warnRedefinitionOfLabel,

-    warnUnknownSubstitutionX,

-    warnLanguageXNotSupported,

-    warnCommentXIgnored,

-    warnUser,

-    hintSuccess,

-    hintSuccessX,

-    hintLineTooLong,

-    hintXDeclaredButNotUsed,

-    hintConvToBaseNotNeeded,

-    hintConvFromXtoItselfNotNeeded,

-    hintExprAlwaysX,

-    hintQuitCalled,

-    hintProcessing,

-    hintCodeBegin,

-    hintCodeEnd,

-    hintConf,

-    hintUser);

-

-const

-  MsgKindToStr: array [TMsgKind] of string = (

-    'unknown error',

-    'illformed AST: $1',

-    'cannot open ''$1''',

-    'internal error: $1',

-    '$1',

-    '''$1'' compiler does not support C++',

-    'string literal expected',

-    'integer literal expected',

-    'invalid character constant',

-    'closing """ expected, but end of file reached',

-    'closing " expected',

-    'tabulators are not allowed',

-    'invalid token: $1',

-    'line too long',

-    '$1 is not a valid number',

-    'number $1 out of valid range',

-    '\n not allowed in character literal',

-    'closing '']'' expected, but end of file reached',

-    'missing final ''',

-    'identifier expected, but found ''$1''',

-    'operator expected, but found ''$1''',

-    '''$1'' expected',

-    'string after ''include'' expected',

-    'recursive include file: ''$1''',

-    '''on'' or ''off'' expected',

-    '''none'', ''speed'' or ''size'' expected',

-    'invalid pragma',

-    'unknown pragma: ''$1''',

-    'pragma ''$1'' here not allowed',

-    'unknown directive: ''$1''',

-    'invalid directive',

-    '''pop'' without a ''push'' pragma',

-    'empty asm statement makes no sense',

-    '''='' invalid in an expression; probably ''=='' meant',

-    'invalid indentation',

-    'exception expected',

-    'exception already handled',

-    '''return'' only allowed in routine',

-    '''yield'' only allowed in a loop of an iterator',

-    'invalid number of ''yield'' expresions',

-    '''return'' not allowed in iterator',

-    'current routine cannot return an expression',

-    'attempt to redefine ''$1''',

-    'statement not allowed after ''return'', ''break'' or ''raise''',

-    'statement expected',

-    '''$1'' is no label',

-    'invalid command line option: ''$1''',

-    'argument for command line option expected: ''$1''',

-    'invalid argument for command line option: ''$1''',

-    'invalid variable substitution in ''$1''',

-    'unknown variable: ''$1''',

-    'unknown C compiler: ''$1''',

-    '''on'' or ''off'' expected, but ''$1'' found',

-    '''none'', ''boehm'' or ''refc'' expected, but ''$1'' found',

-    '''none'', ''speed'' or ''size'' expected, but ''$1'' found',

-    '''gui'', ''console'' or ''lib'' expected, but ''$1'' found',

-    'unknown OS: ''$1''',

-    'unknown CPU: ''$1''',

-    '''c'', ''c++'' or ''yaml'' expected, but ''$1'' found',

-    'arguments can only be given if the ''--run'' option is selected',

-    'multiple assignment is not allowed',

-    ''':'' or ''='' expected, but found ''$1''',

-    'expression expected, but found ''$1''',

-    'undeclared identifier: ''$1''',

-    'ambigious identifier: ''$1'' -- use a qualifier',

-    '''$1'' is forwarded twice',

-    'type expected',

-    'system module needs ''$1''',

-    'execution of an external program failed',

-    'overloaded ''$1'' leads to ambigious calls',

-    'invalid argument for ''$1''',

-    'statement has no effect',

-    '''$1'' expects a type or value',

-    '''$1'' expects an array type',

-    '''$1'' cannot be instantiated because its body has not been compiled yet',

-    'expression with no type cannot be converted',

-    'expression with no type cannot be casted',

-    'constant division by zero',

-    'ordinal type expected',

-    'ordinal or float type expected',

-    'over- or underflow',

-    'cannot evalutate ''$1'' because type is not defined completely',

-    '''chr'' expects an int in the range 0..255',

-    '''staticAssert'' failed: condition is false',

-    'argument to ''staticAssert'' cannot be evaluated at compile time',

-    '''.'' requires a record or object type',

-    'undeclared field: ''$1''',

-    'attempt to access a nil address',

-    'index out of bounds',

-    'index types do not match',

-    '''[]'' operator invalid for this type',

-    'value out of set bounds',

-    'field initialized twice: ''$1''',

-    'field ''$1'' not initialized',

-    'expression cannot be called',

-    'expression has no type',

-    'expression ''$1'' has no type',

-    '''cast'' not allowed in safe mode',

-    'expression cannot be casted to $1',

-    'undefined prefix operator: $1',

-    ''','' or '')'' expected',

-    '''{'' or ''('' expected',

-    'section (''type'', ''proc'', etc.) expected',

-    '''implementation'' or end of file expected',

-    'range expected',

-    'invalid type description',

-    'attempt to redefine ''$1''',

-    '''magic'' only allowed in system module',

-    'unkown operator: ''$1''',

-    'power of two expected',

-    'string literal may not be empty',

-    'calling convention expected',

-    'a proc can only have one calling convention',

-    'symbol must be imported if ''lib'' pragma is used',

-    'expression must be of type ''bool''',

-    'constant expression expected',

-    'duplicate case label',

-    'range is empty',

-    'selector must be of an ordinal type, real or string',

-    'selector must be of an ordinal type',

-    'ord($1) must not be negative',

-    'len($1) must be less than 32768',

-    'wrong number of variables',

-    'only objects can be raised',

-    '''break'' only allowed in loop construct',

-    'type ''$1'' has unknown size',

-    'a constant can only be initialized with a constant expression',

-    'a constant needs a value',

-    'the result type cannot be on open array',

-    'computing the type''s size produced an overflow',

-    'set is too large',

-    'base type of a set must be an ordinal',

-    'inheritance only works with non-final objects',

-    'inheritance only works with an enum',

-    'illegal recursion in type ''$1''',

-    'cannot instantiate: ''$1''',

-    'expression has no address',

-    'for a ''var'' type a variable needs to be passed',

-    'type mismatch',

-    'type mismatch: got (',

-    'but expected one of: ',

-    'but expected ''$1''',

-    'ambigious call; both $1 and $2 match for: $3',

-    'wrong number of type parameters',

-    'out parameters cannot have default values',

-    'an inline proc has no address',

-    '$1 cannot be declared in parameter declaration',

-    'pragmas are only in the header of a proc allowed',

-    'an imported proc cannot have an implementation',

-    'implementation of ''$1'' is not allowed here',

-    'implementation of ''$1'' expected',

-    'value returned by statement has to be discarded',

-    'statement returns no value that can be discarded',

-    'unknown precedence for operator; use ''infix: prec'' pragma',

-    'conversion from $1 to $2 is invalid',

-    'type mismatch: expected ''$1'', but got ''$2''',

-    'cannot bind parameter ''$1'' twice',

-    'invalid order in enum ''$1''',

-    'enum ''$1'' has wholes',

-    '''except'' or ''finally'' expected',

-    'after catch all ''except'' or ''finally'' no section may follow',

-    'end of file expected, but found token ''$1''',

-    'option expected, but found ''$1''',

-    'cannot evaluate forwarded constant',

-    '''$1'' is not a label',

-    '''$1'' needs to be of a non-generic type',

-    'not all cases are covered',

-    'string range in case statement not allowed',

-    'unknown substitution variable: ''$1''',

-    'complex statement requires indentation',

-    '''$1'' is not callable',

-    'no pragmas allowed for $1',

-    'no generic parameters allowed for $1',

-    'invalid param kind: ''$1''',

-    'default argument invalid',

-    'named parameter has to be an identifier',

-    'no return type for $1 allowed',

-    'a type conversion needs exactly one argument',

-    'invalid pragma: $1',

-    '$1 here not allowed',

-    'invalid control flow: $1',

-    'a type has no value',

-    'invalid type: ''$1''',

-    '''^'' needs a pointer or reference type',

-    'invalid context for builtin ''$1''',

-    'invalid expression',

-    'invalid expression: ''$1''',

-    'enum has no value ''$1''',

-    'named expression expected',

-    'named expression here not allowed',

-    '''$1'' expects one type parameter',

-    'array expects two type parameters',

-    'invalid invisibility: ''$1''',

-    'initialization here not allowed',

-    '''$1'' cannot be assigned to',

-    'iterators can only be defined at the module''s top level',

-    'iterator needs an implementation',

-    'iterator needs a return type',

-    'invalid command: ''$1''',

-    '''$1'' is only allowed at top level',

-    'type ''$1'' needs an implementation',

-    'template instantiation too nested',

-    'instantiation from here',

-    'invalid index value for tuple subscript',

-    'command expects a filename argument',

-    '''$1'' expected',

-    'invalid section start',

-    'grid table is not implemented',

-    'general parse error',

-    'new section expected',

-    'whitespace expected, got ''$1''',

-    '''$1'' is no valid index file',

-    'cannot render reStructuredText element ''$1''',

-    'type ''var var'' is not allowed',

-    '''is'' expects two arguments',

-    '''is'' expects object types',

-    '''$1'' can never be of this subtype',

-    'interpretation requires too many iterations',

-    'cannot interpret node kind ''$1''',

-    'field ''$1'' cannot be found',

-    'invalid conversion from type ''$1''',

-    'assertion failed',

-    'cannot generate code for ''$1''',

-    'converter needs return type',

-    'converter requires one parameter',

-    'unhandled exception: $1',

-    'macro returned a cyclic abstract syntax tree',

-    '''$1'' is no macro or template',

-    '$1',

-    'cannot open ''$1'' [CannotOpenFile]',

-    'octal escape sequences do not exist; leading zero is ignored [OctalEscape]',

-    '''$1'' is never read [XIsNeverRead]',

-    '''$1'' might not have been initialized [XmightNotBeenInit]',

-    'cannot write file ''$1'' [CannotWriteMO2]',

-    'cannot read file ''$1'' [CannotReadMO2]',

-    '''$1'' is deprecated [Deprecated]',

-    '''l'' should not be used as an identifier; may look like ''1'' (one) [SmallLshouldNotBeUsed]',

-    'unknown magic ''$1'' might crash the compiler [UnknownMagic]',

-    'redefinition of label ''$1'' [RedefinitionOfLabel]',

-    'unknown substitution ''$1'' [UnknownSubstitutionX]',

-    'language ''$1'' not supported [LanguageXNotSupported]',

-    'comment ''$1'' ignored [CommentXIgnored]',

-    '$1 [User]',

-    'operation successful [Success]',

-    'operation successful ($1 lines compiled; $2 sec total) [SuccessX]',

-    'line too long [LineTooLong]',

-    '''$1'' is declared but not used [XDeclaredButNotUsed]',

-    'conversion to base object is not needed [ConvToBaseNotNeeded]',

-    'conversion from $1 to itself is pointless [ConvFromXtoItselfNotNeeded]',

-    'expression evaluates always to ''$1'' [ExprAlwaysX]',

-    'quit() called [QuitCalled]',

-    '$1 [Processing]',

-    'generated code listing: [CodeBegin]',

-    'end of listing [CodeEnd]',

-    'used config file ''$1'' [Conf]',

-    '$1 [User]'

-  );

-const

-  WarningsToStr: array [0..13] of string = (

-    'CannotOpenFile',

-    'OctalEscape',

-    'XIsNeverRead',

-    'XmightNotBeenInit',

-    'CannotWriteMO2',

-    'CannotReadMO2',

-    'Deprecated',

-    'SmallLshouldNotBeUsed',

-    'UnknownMagic',

-    'RedefinitionOfLabel',

-    'UnknownSubstitutionX',

-    'LanguageXNotSupported',

-    'CommentXIgnored',

-    'User'

-  );

-const

-  HintsToStr: array [0..12] of string = (

-    'Success',

-    'SuccessX',

-    'LineTooLong',

-    'XDeclaredButNotUsed',

-    'ConvToBaseNotNeeded',

-    'ConvFromXtoItselfNotNeeded',

-    'ExprAlwaysX',

-    'QuitCalled',

-    'Processing',

-    'CodeBegin',

-    'CodeEnd',

-    'Conf',

-    'User'

-  );

+type
+  TMsgKind = (
+    errUnknown,
+    errIllFormedAstX,
+    errCannotOpenFile,
+    errInternal,
+    errGenerated,
+    errXCompilerDoesNotSupportCpp,
+    errStringLiteralExpected,
+    errIntLiteralExpected,
+    errInvalidCharacterConstant,
+    errClosingTripleQuoteExpected,
+    errClosingQuoteExpected,
+    errTabulatorsAreNotAllowed,
+    errInvalidToken,
+    errLineTooLong,
+    errInvalidNumber,
+    errNumberOutOfRange,
+    errNnotAllowedInCharacter,
+    errClosingBracketExpected,
+    errMissingFinalQuote,
+    errIdentifierExpected,
+    errOperatorExpected,
+    errTokenExpected,
+    errStringAfterIncludeExpected,
+    errRecursiveInclude,
+    errOnOrOffExpected,
+    errNoneSpeedOrSizeExpected,
+    errInvalidPragma,
+    errUnknownPragma,
+    errPragmaXHereNotAllowed,
+    errUnknownDirective,
+    errInvalidDirective,
+    errAtPopWithoutPush,
+    errEmptyAsm,
+    errAsgnInvalidInExpr,
+    errInvalidIndentation,
+    errExceptionExpected,
+    errExceptionAlreadyHandled,
+    errReturnNotAllowedHere,
+    errYieldNotAllowedHere,
+    errInvalidNumberOfYieldExpr,
+    errReturnInvalidInIterator,
+    errCannotReturnExpr,
+    errAttemptToRedefine,
+    errStmtInvalidAfterReturn,
+    errStmtExpected,
+    errInvalidLabel,
+    errInvalidCmdLineOption,
+    errCmdLineArgExpected,
+    errCmdLineNoArgExpected,
+    errInvalidVarSubstitution,
+    errUnknownVar,
+    errUnknownCcompiler,
+    errOnOrOffExpectedButXFound,
+    errNoneBoehmRefcExpectedButXFound,
+    errNoneSpeedOrSizeExpectedButXFound,
+    errGuiConsoleOrLibExpectedButXFound,
+    errUnknownOS,
+    errUnknownCPU,
+    errGenOutExpectedButXFound,
+    errArgsNeedRunOption,
+    errInvalidMultipleAsgn,
+    errColonOrEqualsExpected,
+    errExprExpected,
+    errUndeclaredIdentifier,
+    errUseQualifier,
+    errTwiceForwarded,
+    errTypeExpected,
+    errSystemNeeds,
+    errExecutionOfProgramFailed,
+    errNotOverloadable,
+    errInvalidArgForX,
+    errStmtHasNoEffect,
+    errXExpectsTypeOrValue,
+    errXExpectsArrayType,
+    errIteratorCannotBeInstantiated,
+    errExprWithNoTypeCannotBeConverted,
+    errExprWithNoTypeCannotBeCasted,
+    errConstantDivisionByZero,
+    errOrdinalTypeExpected,
+    errOrdinalOrFloatTypeExpected,
+    errOverOrUnderflow,
+    errCannotEvalXBecauseIncompletelyDefined,
+    errChrExpectsRange0_255,
+    errStaticAssertFailed,
+    errStaticAssertCannotBeEval,
+    errDotRequiresRecordOrObjectType,
+    errUndeclaredFieldX,
+    errNilAccess,
+    errIndexOutOfBounds,
+    errIndexTypesDoNotMatch,
+    errBracketsInvalidForType,
+    errValueOutOfSetBounds,
+    errFieldInitTwice,
+    errFieldNotInit,
+    errExprCannotBeCalled,
+    errExprHasNoType,
+    errExprXHasNoType,
+    errCastNotInSafeMode,
+    errExprCannotBeCastedToX,
+    errUndefinedPrefixOpr,
+    errCommaOrParRiExpected,
+    errCurlyLeOrParLeExpected,
+    errSectionExpected,
+    errImplemenationExpected,
+    errRangeExpected,
+    errInvalidTypeDescription,
+    errAttemptToRedefineX,
+    errMagicOnlyInSystem,
+    errUnknownOperatorX,
+    errPowerOfTwoExpected,
+    errStringMayNotBeEmpty,
+    errCallConvExpected,
+    errProcOnlyOneCallConv,
+    errSymbolMustBeImported,
+    errExprMustBeBool,
+    errConstExprExpected,
+    errDuplicateCaseLabel,
+    errRangeIsEmpty,
+    errSelectorMustBeOfCertainTypes,
+    errSelectorMustBeOrdinal,
+    errOrdXMustNotBeNegative,
+    errLenXinvalid,
+    errWrongNumberOfVariables,
+    errExprCannotBeRaised,
+    errBreakOnlyInLoop,
+    errTypeXhasUnknownSize,
+    errConstNeedsConstExpr,
+    errConstNeedsValue,
+    errResultCannotBeOpenArray,
+    errSizeTooBig,
+    errSetTooBig,
+    errBaseTypeMustBeOrdinal,
+    errInheritanceOnlyWithNonFinalObjects,
+    errInheritanceOnlyWithEnums,
+    errIllegalRecursionInTypeX,
+    errCannotInstantiateX,
+    errExprHasNoAddress,
+    errVarForOutParamNeeded,
+    errPureTypeMismatch,
+    errTypeMismatch,
+    errButExpected,
+    errButExpectedX,
+    errAmbigiousCallXYZ,
+    errWrongNumberOfTypeParams,
+    errOutParamNoDefaultValue,
+    errInlineProcHasNoAddress,
+    errXCannotBeInParamDecl,
+    errPragmaOnlyInHeaderOfProc,
+    errImplOfXNotAllowed,
+    errImplOfXexpected,
+    errNoSymbolToBorrowFromFound,
+    errDiscardValue,
+    errInvalidDiscard,
+    errUnknownPrecedence,
+    errIllegalConvFromXtoY,
+    errTypeMismatchExpectedXGotY,
+    errCannotBindXTwice,
+    errInvalidOrderInEnumX,
+    errEnumXHasWholes,
+    errExceptExpected,
+    errInvalidTry,
+    errEofExpectedButXFound,
+    errOptionExpected,
+    errCannotEvaluateForwardConst,
+    errXisNoLabel,
+    errXNeedsConcreteType,
+    errNotAllCasesCovered,
+    errStringRange,
+    errUnkownSubstitionVar,
+    errComplexStmtRequiresInd,
+    errXisNotCallable,
+    errNoPragmasAllowedForX,
+    errNoGenericParamsAllowedForX,
+    errInvalidParamKindX,
+    errDefaultArgumentInvalid,
+    errNamedParamHasToBeIdent,
+    errNoReturnTypeForX,
+    errConvNeedsOneArg,
+    errInvalidPragmaX,
+    errXNotAllowedHere,
+    errInvalidControlFlowX,
+    errATypeHasNoValue,
+    errXisNoType,
+    errCircumNeedsPointer,
+    errInvalidContextForBuiltinX,
+    errInvalidExpression,
+    errInvalidExpressionX,
+    errEnumHasNoValueX,
+    errNamedExprExpected,
+    errNamedExprNotAllowed,
+    errXExpectsOneTypeParam,
+    errArrayExpectsTwoTypeParams,
+    errInvalidVisibilityX,
+    errInitHereNotAllowed,
+    errXCannotBeAssignedTo,
+    errIteratorNotAllowed,
+    errIteratorNeedsImplementation,
+    errIteratorNeedsReturnType,
+    errInvalidCommandX,
+    errXOnlyAtModuleScope,
+    errTypeXNeedsImplementation,
+    errTemplateInstantiationTooNested,
+    errInstantiationFrom,
+    errInvalidIndexValueForTuple,
+    errCommandExpectsFilename,
+    errXExpected,
+    errInvalidSectionStart,
+    errGridTableNotImplemented,
+    errGeneralParseError,
+    errNewSectionExpected,
+    errWhitespaceExpected,
+    errXisNoValidIndexFile,
+    errCannotRenderX,
+    errVarVarTypeNotAllowed,
+    errIsExpectsTwoArguments,
+    errIsExpectsObjectTypes,
+    errXcanNeverBeOfThisSubtype,
+    errTooManyIterations,
+    errCannotInterpretNodeX,
+    errFieldXNotFound,
+    errInvalidConversionFromTypeX,
+    errAssertionFailed,
+    errCannotGenerateCodeForX,
+    errXNeedsReturnType,
+    errXRequiresOneArgument,
+    errUnhandledExceptionX,
+    errCyclicTree,
+    errXisNoMacroOrTemplate,
+    errUser,
+    warnCannotOpenFile,
+    warnOctalEscape,
+    warnXIsNeverRead,
+    warnXmightNotBeenInit,
+    warnCannotWriteMO2,
+    warnCannotReadMO2,
+    warnDeprecated,
+    warnSmallLshouldNotBeUsed,
+    warnUnknownMagic,
+    warnRedefinitionOfLabel,
+    warnUnknownSubstitutionX,
+    warnLanguageXNotSupported,
+    warnCommentXIgnored,
+    warnUser,
+    hintSuccess,
+    hintSuccessX,
+    hintLineTooLong,
+    hintXDeclaredButNotUsed,
+    hintConvToBaseNotNeeded,
+    hintConvFromXtoItselfNotNeeded,
+    hintExprAlwaysX,
+    hintQuitCalled,
+    hintProcessing,
+    hintCodeBegin,
+    hintCodeEnd,
+    hintConf,
+    hintUser);
+
+const
+  MsgKindToStr: array [TMsgKind] of string = (
+    'unknown error',
+    'illformed AST: $1',
+    'cannot open ''$1''',
+    'internal error: $1',
+    '$1',
+    '''$1'' compiler does not support C++',
+    'string literal expected',
+    'integer literal expected',
+    'invalid character constant',
+    'closing """ expected, but end of file reached',
+    'closing " expected',
+    'tabulators are not allowed',
+    'invalid token: $1',
+    'line too long',
+    '$1 is not a valid number',
+    'number $1 out of valid range',
+    '\n not allowed in character literal',
+    'closing '']'' expected, but end of file reached',
+    'missing final ''',
+    'identifier expected, but found ''$1''',
+    'operator expected, but found ''$1''',
+    '''$1'' expected',
+    'string after ''include'' expected',
+    'recursive include file: ''$1''',
+    '''on'' or ''off'' expected',
+    '''none'', ''speed'' or ''size'' expected',
+    'invalid pragma',
+    'unknown pragma: ''$1''',
+    'pragma ''$1'' here not allowed',
+    'unknown directive: ''$1''',
+    'invalid directive',
+    '''pop'' without a ''push'' pragma',
+    'empty asm statement makes no sense',
+    '''='' invalid in an expression; probably ''=='' meant',
+    'invalid indentation',
+    'exception expected',
+    'exception already handled',
+    '''return'' only allowed in routine',
+    '''yield'' only allowed in a loop of an iterator',
+    'invalid number of ''yield'' expresions',
+    '''return'' not allowed in iterator',
+    'current routine cannot return an expression',
+    'attempt to redefine ''$1''',
+    'statement not allowed after ''return'', ''break'' or ''raise''',
+    'statement expected',
+    '''$1'' is no label',
+    'invalid command line option: ''$1''',
+    'argument for command line option expected: ''$1''',
+    'invalid argument for command line option: ''$1''',
+    'invalid variable substitution in ''$1''',
+    'unknown variable: ''$1''',
+    'unknown C compiler: ''$1''',
+    '''on'' or ''off'' expected, but ''$1'' found',
+    '''none'', ''boehm'' or ''refc'' expected, but ''$1'' found',
+    '''none'', ''speed'' or ''size'' expected, but ''$1'' found',
+    '''gui'', ''console'' or ''lib'' expected, but ''$1'' found',
+    'unknown OS: ''$1''',
+    'unknown CPU: ''$1''',
+    '''c'', ''c++'' or ''yaml'' expected, but ''$1'' found',
+    'arguments can only be given if the ''--run'' option is selected',
+    'multiple assignment is not allowed',
+    ''':'' or ''='' expected, but found ''$1''',
+    'expression expected, but found ''$1''',
+    'undeclared identifier: ''$1''',
+    'ambigious identifier: ''$1'' -- use a qualifier',
+    '''$1'' is forwarded twice',
+    'type expected',
+    'system module needs ''$1''',
+    'execution of an external program failed',
+    'overloaded ''$1'' leads to ambigious calls',
+    'invalid argument for ''$1''',
+    'statement has no effect',
+    '''$1'' expects a type or value',
+    '''$1'' expects an array type',
+    '''$1'' cannot be instantiated because its body has not been compiled yet',
+    'expression with no type cannot be converted',
+    'expression with no type cannot be casted',
+    'constant division by zero',
+    'ordinal type expected',
+    'ordinal or float type expected',
+    'over- or underflow',
+    'cannot evalutate ''$1'' because type is not defined completely',
+    '''chr'' expects an int in the range 0..255',
+    '''staticAssert'' failed: condition is false',
+    'argument to ''staticAssert'' cannot be evaluated at compile time',
+    '''.'' requires a record or object type',
+    'undeclared field: ''$1''',
+    'attempt to access a nil address',
+    'index out of bounds',
+    'index types do not match',
+    '''[]'' operator invalid for this type',
+    'value out of set bounds',
+    'field initialized twice: ''$1''',
+    'field ''$1'' not initialized',
+    'expression cannot be called',
+    'expression has no type',
+    'expression ''$1'' has no type',
+    '''cast'' not allowed in safe mode',
+    'expression cannot be casted to $1',
+    'undefined prefix operator: $1',
+    ''','' or '')'' expected',
+    '''{'' or ''('' expected',
+    'section (''type'', ''proc'', etc.) expected',
+    '''implementation'' or end of file expected',
+    'range expected',
+    'invalid type description',
+    'attempt to redefine ''$1''',
+    '''magic'' only allowed in system module',
+    'unkown operator: ''$1''',
+    'power of two expected',
+    'string literal may not be empty',
+    'calling convention expected',
+    'a proc can only have one calling convention',
+    'symbol must be imported if ''lib'' pragma is used',
+    'expression must be of type ''bool''',
+    'constant expression expected',
+    'duplicate case label',
+    'range is empty',
+    'selector must be of an ordinal type, real or string',
+    'selector must be of an ordinal type',
+    'ord($1) must not be negative',
+    'len($1) must be less than 32768',
+    'wrong number of variables',
+    'only objects can be raised',
+    '''break'' only allowed in loop construct',
+    'type ''$1'' has unknown size',
+    'a constant can only be initialized with a constant expression',
+    'a constant needs a value',
+    'the result type cannot be on open array',
+    'computing the type''s size produced an overflow',
+    'set is too large',
+    'base type of a set must be an ordinal',
+    'inheritance only works with non-final objects',
+    'inheritance only works with an enum',
+    'illegal recursion in type ''$1''',
+    'cannot instantiate: ''$1''',
+    'expression has no address',
+    'for a ''var'' type a variable needs to be passed',
+    'type mismatch',
+    'type mismatch: got (',
+    'but expected one of: ',
+    'but expected ''$1''',
+    'ambigious call; both $1 and $2 match for: $3',
+    'wrong number of type parameters',
+    'out parameters cannot have default values',
+    'an inline proc has no address',
+    '$1 cannot be declared in parameter declaration',
+    'pragmas are only in the header of a proc allowed',
+    'implementation of ''$1'' is not allowed',
+    'implementation of ''$1'' expected',
+    'no symbol to borrow from found',
+    'value returned by statement has to be discarded',
+    'statement returns no value that can be discarded',
+    'unknown precedence for operator; use ''infix: prec'' pragma',
+    'conversion from $1 to $2 is invalid',
+    'type mismatch: expected ''$1'', but got ''$2''',
+    'cannot bind parameter ''$1'' twice',
+    'invalid order in enum ''$1''',
+    'enum ''$1'' has wholes',
+    '''except'' or ''finally'' expected',
+    'after catch all ''except'' or ''finally'' no section may follow',
+    'end of file expected, but found token ''$1''',
+    'option expected, but found ''$1''',
+    'cannot evaluate forwarded constant',
+    '''$1'' is not a label',
+    '''$1'' needs to be of a non-generic type',
+    'not all cases are covered',
+    'string range in case statement not allowed',
+    'unknown substitution variable: ''$1''',
+    'complex statement requires indentation',
+    '''$1'' is not callable',
+    'no pragmas allowed for $1',
+    'no generic parameters allowed for $1',
+    'invalid param kind: ''$1''',
+    'default argument invalid',
+    'named parameter has to be an identifier',
+    'no return type for $1 allowed',
+    'a type conversion needs exactly one argument',
+    'invalid pragma: $1',
+    '$1 here not allowed',
+    'invalid control flow: $1',
+    'a type has no value',
+    'invalid type: ''$1''',
+    '''^'' needs a pointer or reference type',
+    'invalid context for builtin ''$1''',
+    'invalid expression',
+    'invalid expression: ''$1''',
+    'enum has no value ''$1''',
+    'named expression expected',
+    'named expression here not allowed',
+    '''$1'' expects one type parameter',
+    'array expects two type parameters',
+    'invalid invisibility: ''$1''',
+    'initialization here not allowed',
+    '''$1'' cannot be assigned to',
+    'iterators can only be defined at the module''s top level',
+    'iterator needs an implementation',
+    'iterator needs a return type',
+    'invalid command: ''$1''',
+    '''$1'' is only allowed at top level',
+    'type ''$1'' needs an implementation',
+    'template instantiation too nested',
+    'instantiation from here',
+    'invalid index value for tuple subscript',
+    'command expects a filename argument',
+    '''$1'' expected',
+    'invalid section start',
+    'grid table is not implemented',
+    'general parse error',
+    'new section expected',
+    'whitespace expected, got ''$1''',
+    '''$1'' is no valid index file',
+    'cannot render reStructuredText element ''$1''',
+    'type ''var var'' is not allowed',
+    '''is'' expects two arguments',
+    '''is'' expects object types',
+    '''$1'' can never be of this subtype',
+    'interpretation requires too many iterations',
+    'cannot interpret node kind ''$1''',
+    'field ''$1'' cannot be found',
+    'invalid conversion from type ''$1''',
+    'assertion failed',
+    'cannot generate code for ''$1''',
+    'converter needs return type',
+    'converter requires one parameter',
+    'unhandled exception: $1',
+    'macro returned a cyclic abstract syntax tree',
+    '''$1'' is no macro or template',
+    '$1',
+    'cannot open ''$1'' [CannotOpenFile]',
+    'octal escape sequences do not exist; leading zero is ignored [OctalEscape]',
+    '''$1'' is never read [XIsNeverRead]',
+    '''$1'' might not have been initialized [XmightNotBeenInit]',
+    'cannot write file ''$1'' [CannotWriteMO2]',
+    'cannot read file ''$1'' [CannotReadMO2]',
+    '''$1'' is deprecated [Deprecated]',
+    '''l'' should not be used as an identifier; may look like ''1'' (one) [SmallLshouldNotBeUsed]',
+    'unknown magic ''$1'' might crash the compiler [UnknownMagic]',
+    'redefinition of label ''$1'' [RedefinitionOfLabel]',
+    'unknown substitution ''$1'' [UnknownSubstitutionX]',
+    'language ''$1'' not supported [LanguageXNotSupported]',
+    'comment ''$1'' ignored [CommentXIgnored]',
+    '$1 [User]',
+    'operation successful [Success]',
+    'operation successful ($1 lines compiled; $2 sec total) [SuccessX]',
+    'line too long [LineTooLong]',
+    '''$1'' is declared but not used [XDeclaredButNotUsed]',
+    'conversion to base object is not needed [ConvToBaseNotNeeded]',
+    'conversion from $1 to itself is pointless [ConvFromXtoItselfNotNeeded]',
+    'expression evaluates always to ''$1'' [ExprAlwaysX]',
+    'quit() called [QuitCalled]',
+    '$1 [Processing]',
+    'generated code listing: [CodeBegin]',
+    'end of listing [CodeEnd]',
+    'used config file ''$1'' [Conf]',
+    '$1 [User]'
+  );
+const
+  WarningsToStr: array [0..13] of string = (
+    'CannotOpenFile',
+    'OctalEscape',
+    'XIsNeverRead',
+    'XmightNotBeenInit',
+    'CannotWriteMO2',
+    'CannotReadMO2',
+    'Deprecated',
+    'SmallLshouldNotBeUsed',
+    'UnknownMagic',
+    'RedefinitionOfLabel',
+    'UnknownSubstitutionX',
+    'LanguageXNotSupported',
+    'CommentXIgnored',
+    'User'
+  );
+const
+  HintsToStr: array [0..12] of string = (
+    'Success',
+    'SuccessX',
+    'LineTooLong',
+    'XDeclaredButNotUsed',
+    'ConvToBaseNotNeeded',
+    'ConvFromXtoItselfNotNeeded',
+    'ExprAlwaysX',
+    'QuitCalled',
+    'Processing',
+    'CodeBegin',
+    'CodeEnd',
+    'Conf',
+    'User'
+  );
 //[[[end]]]

 

 const

diff --git a/nim/nimconf.pas b/nim/nimconf.pas
index 8f908bf62..842446ae9 100644
--- a/nim/nimconf.pas
+++ b/nim/nimconf.pas
@@ -335,12 +335,19 @@ end;
 
 procedure LoadConfig(const project: string);
 var
-  conffile: string;
+  conffile, prefix: string;
 begin
   // set default value (can be overwritten):
-  if libpath = '' then
+  if libpath = '' then begin
     // choose default libpath:
-    libpath := joinPath(getPrefixDir(), 'lib');
+    prefix := getPrefixDir();
+    if (prefix = '/usr') then
+      libpath := '/usr/lib/nimrod'
+    else if (prefix = '/usr/local') then
+      libpath := '/usr/local/lib/nimrod'
+    else
+      libpath := joinPath(prefix, 'lib')
+  end;
   // read default config file:
   LoadSpecialConfig('nimrod.cfg');
   // read project config file:
diff --git a/nim/nversion.pas b/nim/nversion.pas
index ae6392db9..e15f88068 100644
--- a/nim/nversion.pas
+++ b/nim/nversion.pas
@@ -31,10 +31,10 @@ const
   //cog.outl('VersionMinor = %s;' % ver[1])

   //cog.outl('VersionPatch = %s;' % ver[2])

   //]]]

-  VersionAsString = '0.7.8';
+  VersionAsString = '0.7.10';
   VersionMajor = 0;
   VersionMinor = 7;
-  VersionPatch = 8;
+  VersionPatch = 10;
   //[[[[end]]]]

 

 implementation

diff --git a/nim/parsecfg.pas b/nim/parsecfg.pas
index 620335aa6..ba6a98679 100644
--- a/nim/parsecfg.pas
+++ b/nim/parsecfg.pas
@@ -1,7 +1,7 @@
 //
 //
 //            Nimrod's Runtime Library
-//        (c) Copyright 2008 Andreas Rumpf
+//        (c) Copyright 2009 Andreas Rumpf
 //
 //    See the file "copying.txt", included in this
 //    distribution, for details about the copyright.
@@ -201,6 +201,7 @@ begin
     inc(pos, 2); // skip ""
     // skip leading newline:
     pos := HandleCRLF(c, pos);
+    buf := c.buf;
     repeat
       case buf[pos] of
         '"': begin
@@ -211,6 +212,7 @@ begin
         end;
         CR, LF: begin
           pos := HandleCRLF(c, pos);
+          buf := c.buf;
           tok.literal := tok.literal +{&} nl;
         end;
         lexbase.EndOfFile: begin
@@ -278,7 +280,10 @@ begin
       ' ': Inc(pos);
       Tabulator: inc(pos);
       '#', ';': while not (buf[pos] in [CR, LF, lexbase.EndOfFile]) do inc(pos);
-      CR, LF: pos := HandleCRLF(c, pos);
+      CR, LF: begin
+        pos := HandleCRLF(c, pos);
+        buf := c.buf;
+      end
       else break // EndOfFile also leaves the loop
     end
   until false;
diff --git a/nim/paslex.pas b/nim/paslex.pas
index da9283163..f3d8daaeb 100644
--- a/nim/paslex.pas
+++ b/nim/paslex.pas
@@ -1,7 +1,7 @@
 //
 //
 //           The Nimrod Compiler
-//        (c) Copyright 2008 Andreas Rumpf
+//        (c) Copyright 2009 Andreas Rumpf
 //
 //    See the file "copying.txt", included in this
 //    distribution, for details about the copyright.
@@ -529,6 +529,7 @@ begin
       addChar(tok.literal, buf[pos]); inc(pos);
     end;
     pos := handleCRLF(L, pos);
+    buf := L.buf;
     indent := 0;
     while buf[pos] = ' ' do begin inc(pos); inc(indent) end;
     if (col = indent) and (buf[pos] = '/') and (buf[pos+1] = '/') then
@@ -552,6 +553,7 @@ begin
     case buf[pos] of
       CR, LF: begin
         pos := HandleCRLF(L, pos);
+        buf := L.buf;
         tok.literal := tok.literal +{&} nl + '#';
       end;
       '}': begin inc(pos); break end;
@@ -578,6 +580,7 @@ begin
     case buf[pos] of
       CR, LF: begin
         pos := HandleCRLF(L, pos);
+        buf := L.buf;
         tok.literal := tok.literal +{&} nl + '#';
       end;
       '*': begin
@@ -606,7 +609,10 @@ begin
     case buf[pos] of
       ' ', Tabulator: Inc(pos);
       // newline is special:
-      CR, LF: pos := HandleCRLF(L, pos);
+      CR, LF: begin
+        pos := HandleCRLF(L, pos);
+        buf := L.buf;
+      end
       else break // EndOfFile also leaves the loop
     end
   until false;
diff --git a/nim/pnimsyn.pas b/nim/pnimsyn.pas
index 95d6e64f9..51c0cd4f5 100644
--- a/nim/pnimsyn.pas
+++ b/nim/pnimsyn.pas
@@ -1,7 +1,7 @@
 //
 //
 //           The Nimrod Compiler
-//        (c) Copyright 2008 Andreas Rumpf
+//        (c) Copyright 2009 Andreas Rumpf
 //
 //    See the file "copying.txt", included in this
 //    distribution, for details about the copyright.
@@ -1663,6 +1663,14 @@ begin
   addSon(result, parseRecordPart(p));
 end;
 
+function parseAbstract(var p: TParser): PNode;
+begin
+  result := newNodeP(nkAbstractTy, p);
+  getTok(p);
+  optInd(p, result);
+  addSon(result, parseTypeDesc(p));
+end;
+
 function parseTypeDef(var p: TParser): PNode;
 var
   a: PNode;
@@ -1676,6 +1684,7 @@ begin
     case p.tok.tokType of
       tkObject: a := parseRecordOrObject(p, nkObjectTy);
       tkEnum: a := parseEnum(p);
+      tkAbstract: a := parseAbstract(p);
       else a := parseTypeDesc(p);
     end;
     addSon(result, a);
diff --git a/nim/pragmas.pas b/nim/pragmas.pas
index df48f27c9..9f4a543c5 100644
--- a/nim/pragmas.pas
+++ b/nim/pragmas.pas
@@ -522,6 +522,10 @@ begin
             if sym.typ = nil then invalidPragma(it);
             include(sym.typ.flags, tfVarargs);
           end;
+          wBorrow: begin
+            noVal(it);
+            include(sym.flags, sfBorrow);
+          end;
           wFinal: begin
             noVal(it);
             if sym.typ = nil then invalidPragma(it);
@@ -595,7 +599,8 @@ begin
   pragma(c, s, n, {@set}[FirstCallConv..LastCallConv,
     wImportc, wExportc, wNodecl, wMagic, wNosideEffect,
     wNoreturn, wDynLib, wHeader, wCompilerProc, wPure,
-    wCppMethod, wDeprecated, wVarargs, wCompileTime, wMerge]);
+    wCppMethod, wDeprecated, wVarargs, wCompileTime, wMerge,
+    wBorrow]);
 end;
 
 procedure pragmaMacro(c: PContext; s: PSym; n: PNode);
@@ -608,7 +613,7 @@ end;
 procedure pragmaIterator(c: PContext; s: PSym; n: PNode);
 begin
   pragma(c, s, n, {@set}[FirstCallConv..LastCallConv,
-         wImportc, wExportc, wNodecl, wMagic, wDeprecated]);
+         wImportc, wExportc, wNodecl, wMagic, wDeprecated, wBorrow]);
 end;
 
 procedure pragmaStmt(c: PContext; s: PSym; n: PNode);
diff --git a/nim/procfind.pas b/nim/procfind.pas
index 9c4786e53..c8792586a 100644
--- a/nim/procfind.pas
+++ b/nim/procfind.pas
@@ -1,7 +1,7 @@
 //
 //
 //           The Nimrod Compiler
-//        (c) Copyright 2008 Andreas Rumpf
+//        (c) Copyright 2009 Andreas Rumpf
 //
 //    See the file "copying.txt", included in this
 //    distribution, for details about the copyright.
@@ -22,6 +22,10 @@ function SearchForProc(c: PContext; fn: PSym; tos: int): PSym;
 // Searchs for the fn in the symbol table. If the parameter lists are exactly
 // the same the sym in the symbol table is returned, else nil.
 
+function SearchForBorrowProc(c: PContext; fn: PSym; tos: int): PSym;
+// Searchs for the fn in the symbol table. If the parameter lists are suitable
+// for borrowing the sym in the symbol table is returned, else nil.
+
 implementation
 
 function equalGenericParams(procA, procB: PNode): Boolean;
@@ -69,4 +73,46 @@ begin
   end
 end;
 
+function paramsFitBorrow(a, b: PNode): bool;
+var
+  i, len: int;
+  m, n: PSym;
+begin
+  len := sonsLen(a);
+  result := false;
+  if len = sonsLen(b) then begin
+    for i := 1 to len-1 do begin
+      m := a.sons[i].sym;
+      n := b.sons[i].sym;
+      assert((m.kind = skParam) and (n.kind = skParam));
+      if not equalOrAbstractOf(m.typ, n.typ) then exit;
+    end;
+    // return type:
+    if not equalOrAbstractOf(a.sons[0].typ, b.sons[0].typ) then exit;
+    result := true
+  end
+end;
+
+function SearchForBorrowProc(c: PContext; fn: PSym; tos: int): PSym;
+// Searchs for the fn in the symbol table. If the parameter lists are suitable
+// for borrowing the sym in the symbol table is returned, else nil.
+var
+  it: TIdentIter;
+  scope: int;
+begin
+  for scope := tos downto 0 do begin
+    result := initIdentIter(it, c.tab.stack[scope], fn.Name);
+    while result <> nil do begin
+      // watchout! result must not be the same as fn!
+      if (result.Kind = fn.kind) and (result.id <> fn.id) then begin
+        if equalGenericParams(result.ast.sons[genericParamsPos], 
+                              fn.ast.sons[genericParamsPos]) then begin
+          if paramsFitBorrow(fn.typ.n, result.typ.n) then exit;
+        end
+      end;
+      result := NextIdentIter(it, c.tab.stack[scope])
+    end
+  end
+end;
+
 end.
diff --git a/nim/rnimsyn.pas b/nim/rnimsyn.pas
index 6cb78efcf..5be10a0f3 100644
--- a/nim/rnimsyn.pas
+++ b/nim/rnimsyn.pas
@@ -16,7 +16,7 @@ unit rnimsyn;
 interface
 
 uses
-  nsystem, charsets, lexbase, scanner, options, idents, strutils, ast, msgs,
+  nsystem, charsets, scanner, options, idents, strutils, ast, msgs,
   lists;
 
 type
@@ -543,6 +543,7 @@ begin
     nkRefTy:          result := lsub(n.sons[0])+length('ref_');
     nkPtrTy:          result := lsub(n.sons[0])+length('ptr_');
     nkVarTy:          result := lsub(n.sons[0])+length('var_');
+    nkAbstractTy:     result := lsub(n.sons[0])+length('abstract_');
     nkTypeDef:        result := lsons(n)+3;
     nkOfInherit:      result := lsub(n.sons[0])+length('of_');
     nkProcTy:         result := lsons(n)+length('proc_');
@@ -1159,6 +1160,10 @@ begin
       putWithSpace(g, tkVar, 'var');
       gsub(g, n.sons[0]);
     end;
+    nkAbstractTy: begin
+      putWithSpace(g, tkAbstract, 'abstract');
+      gsub(g, n.sons[0]);
+    end;
     nkTypeDef: begin
       gsub(g, n.sons[0]);
       gsub(g, n.sons[1]);
diff --git a/nim/rst.pas b/nim/rst.pas
index 6d0d476c9..d2afc7e33 100644
--- a/nim/rst.pas
+++ b/nim/rst.pas
@@ -1991,7 +1991,7 @@ begin
     addSon(n, newRstNode(rnLeaf, readFile(path)));
     result.sons[2] := n;
   end;
-  result.kind := rnCodeBlock
+  result.kind := rnCodeBlock;
 end;
 
 function dirContainer(var p: TRstParser): PRstNode;
diff --git a/nim/scanner.pas b/nim/scanner.pas
index 51532c801..d1f32135c 100644
--- a/nim/scanner.pas
+++ b/nim/scanner.pas
@@ -52,20 +52,20 @@ type
     //  i = i + 1
     //cog.out(idents)
     //]]]
-    tkAddr, tkAnd, tkAs, tkAsm, 
-    tkBlock, tkBreak, tkCase, tkCast, 
-    tkConst, tkContinue, tkConverter, tkDiscard, 
-    tkDiv, tkElif, tkElse, tkEnd, 
-    tkEnum, tkExcept, tkException, tkFinally, 
-    tkFor, tkFrom, tkGeneric, tkIf, 
-    tkImplies, tkImport, tkIn, tkInclude, 
-    tkIs, tkIsnot, tkIterator, tkLambda, 
-    tkMacro, tkMethod, tkMod, tkNil, 
-    tkNot, tkNotin, tkObject, tkOf, 
-    tkOr, tkOut, tkProc, tkPtr, 
-    tkRaise, tkRef, tkReturn, tkShl, 
-    tkShr, tkTemplate, tkTry, tkTuple, 
-    tkType, tkVar, tkWhen, tkWhere, 
+    tkAbstract, tkAddr, tkAnd, tkAs, 
+    tkAsm, tkBlock, tkBreak, tkCase, 
+    tkCast, tkConst, tkContinue, tkConverter, 
+    tkDiscard, tkDiv, tkElif, tkElse, 
+    tkEnd, tkEnum, tkExcept, tkException, 
+    tkFinally, tkFor, tkFrom, tkGeneric, 
+    tkIf, tkImplies, tkImport, tkIn, 
+    tkInclude, tkIs, tkIsnot, tkIterator, 
+    tkLambda, tkMacro, tkMethod, tkMod, 
+    tkNil, tkNot, tkNotin, tkObject, 
+    tkOf, tkOr, tkOut, tkProc, 
+    tkPtr, tkRaise, tkRef, tkReturn, 
+    tkShl, tkShr, tkTemplate, tkTry, 
+    tkTuple, tkType, tkVar, tkWhen, 
     tkWhile, tkWith, tkWithout, tkXor, 
     tkYield, 
     //[[[end]]]
@@ -96,20 +96,20 @@ const
     //[[[cog
     //cog.out(strings)
     //]]]
-    'addr', 'and', 'as', 'asm', 
-    'block', 'break', 'case', 'cast', 
-    'const', 'continue', 'converter', 'discard', 
-    'div', 'elif', 'else', 'end', 
-    'enum', 'except', 'exception', 'finally', 
-    'for', 'from', 'generic', 'if', 
-    'implies', 'import', 'in', 'include', 
-    'is', 'isnot', 'iterator', 'lambda', 
-    'macro', 'method', 'mod', 'nil', 
-    'not', 'notin', 'object', 'of', 
-    'or', 'out', 'proc', 'ptr', 
-    'raise', 'ref', 'return', 'shl', 
-    'shr', 'template', 'try', 'tuple', 
-    'type', 'var', 'when', 'where', 
+    'abstract', 'addr', 'and', 'as', 
+    'asm', 'block', 'break', 'case', 
+    'cast', 'const', 'continue', 'converter', 
+    'discard', 'div', 'elif', 'else', 
+    'end', 'enum', 'except', 'exception', 
+    'finally', 'for', 'from', 'generic', 
+    'if', 'implies', 'import', 'in', 
+    'include', 'is', 'isnot', 'iterator', 
+    'lambda', 'macro', 'method', 'mod', 
+    'nil', 'not', 'notin', 'object', 
+    'of', 'or', 'out', 'proc', 
+    'ptr', 'raise', 'ref', 'return', 
+    'shl', 'shr', 'template', 'try', 
+    'tuple', 'type', 'var', 'when', 
     'while', 'with', 'without', 'xor', 
     'yield', 
     //[[[end]]]
@@ -648,6 +648,7 @@ begin
     inc(pos, 2); // skip ""
     // skip leading newline:
     pos := HandleCRLF(L, pos);
+    buf := L.buf;
     repeat
       case buf[pos] of
         '"': begin
@@ -658,6 +659,7 @@ begin
         end;
         CR, LF: begin
           pos := HandleCRLF(L, pos);
+          buf := L.buf;
           tok.literal := tok.literal +{&} tnl;
         end;
         lexbase.EndOfFile: begin
@@ -842,6 +844,7 @@ begin
       addChar(tok.literal, buf[pos]); inc(pos);
     end;
     pos := handleCRLF(L, pos);
+    buf := L.buf;
     indent := 0;
     while buf[pos] = ' ' do begin inc(pos); inc(indent) end;
     if (buf[pos] = '#') and (col = indent) then begin
@@ -875,6 +878,7 @@ begin
       // newline is special:
       CR, LF: begin
         pos := HandleCRLF(L, pos);
+        buf := L.buf;
         indent := 0;
         while buf[pos] = ' ' do begin
           Inc(pos); Inc(indent)
diff --git a/nim/sem.pas b/nim/sem.pas
index 09f9bf49b..c0826bdbe 100644
--- a/nim/sem.pas
+++ b/nim/sem.pas
@@ -134,6 +134,7 @@ var
   p: PEvalContext;
   s: PStackFrame;
 begin
+  include(sym.flags, sfUsed);
   p := newEvalContext(c.module, '');
   s := newStackFrame();
   s.call := n;
@@ -156,7 +157,8 @@ end;
 
 procedure CheckBool(t: PNode);
 begin
-  if (t.Typ = nil) or (skipVarGeneric(t.Typ).kind <> tyBool) then
+  if (t.Typ = nil) or (skipTypes(t.Typ, {@set}[tyGenericInst, 
+      tyVar, tyOrdinal]).kind <> tyBool) then
     liMessage(t.Info, errExprMustBeBool);
 end;
 
diff --git a/nim/semexprs.pas b/nim/semexprs.pas
index 59d7f969a..74cd44b3d 100644
--- a/nim/semexprs.pas
+++ b/nim/semexprs.pas
@@ -58,8 +58,8 @@ begin
   end;
 
   // common case first (converting of objects)
-  d := skipVarGeneric(castDest);
-  s := skipVarGeneric(src);
+  d := skipTypes(castDest, abstractVar);
+  s := skipTypes(src, abstractVar);
   while (d <> nil) and (d.Kind in [tyPtr, tyRef])
   and (d.Kind = s.Kind) do begin
     d := base(d);
@@ -71,17 +71,20 @@ begin
         [typeToString(src), typeToString(castDest)]));
   if (d.Kind = tyObject) and (s.Kind = tyObject) then
     checkConversionBetweenObjects(info, d, s)
-  else if (skipVarGenericRange(castDest).Kind in IntegralTypes)
-  and (skipVarGenericRange(src).Kind in IntegralTypes) then begin
+  else if (skipTypes(castDest, abstractVarRange).Kind in IntegralTypes)
+  and (skipTypes(src, abstractVarRange).Kind in IntegralTypes) then begin
     // accept conversion between intregral types
   end
-  else begin
+  else begin          
+    // we use d, s here to speed up that operation a bit:
     case cmpTypes(d, s) of
-      isNone, isGeneric:
-        // we use d, s here to speed up that operation a bit
-        liMessage(info, errGenerated,
-          format(MsgKindToString(errIllegalConvFromXtoY),
-            [typeToString(src), typeToString(castDest)]));
+      isNone, isGeneric: begin
+        if not equalOrAbstractOf(castDest, src) and
+           not equalOrAbstractOf(src, castDest) then
+          liMessage(info, errGenerated,
+            format(MsgKindToString(errIllegalConvFromXtoY),
+              [typeToString(src), typeToString(castDest)]));
+      end
       else begin end
     end
   end
@@ -102,8 +105,8 @@ begin
   else if ss < 0 then result := false
   else 
     result := (ds >= ss) or
-      (skipGeneric(dst).kind in [tyInt..tyFloat128]) or
-      (skipGeneric(src).kind in [tyInt..tyFloat128])
+      (skipTypes(dst, abstractInst).kind in [tyInt..tyFloat128]) or
+      (skipTypes(src, abstractInst).kind in [tyInt..tyFloat128])
 end;
 
 function semConv(c: PContext; n: PNode; s: PSym): PNode;
@@ -138,7 +141,7 @@ begin
     liMessage(n.info, errXExpectsTypeOrValue, opToStr[m])
   else begin
     n.sons[1] := semExprWithType(c, n.sons[1], {@set}[efAllowType]);
-    typ := skipVarGenericRange(n.sons[1].typ);
+    typ := skipTypes(n.sons[1].typ, abstractVarRange);
     case typ.Kind of
       tySequence, tyString, tyOpenArray: begin
         n.typ := getSysType(tyInt);
@@ -279,7 +282,8 @@ begin
     addSon(result.typ, newTypeS(tyEmpty, c)) // needs an empty basetype!
   else begin
     addSon(result, semExprWithType(c, n.sons[0]));
-    typ := skipVar(result.sons[0].typ);
+    typ := skipTypes(result.sons[0].typ, 
+                    {@set}[tyGenericInst, tyVar, tyOrdinal]);
     for i := 1 to sonsLen(n)-1 do begin
       n.sons[i] := semExprWithType(c, n.sons[i]);
       addSon(result, fitNode(c, typ, n.sons[i]));
@@ -306,17 +310,18 @@ begin
       nkHiddenStdConv, nkHiddenSubConv: begin
         if it.sons[1].kind = nkBracket then
           it.sons[1] := semArrayConstr(c, it.sons[1]);
-        if skipVarGeneric(it.typ).kind = tyOpenArray then begin
-          s := skipVarGeneric(it.sons[1].typ);
+        if skipTypes(it.typ, abstractVar).kind = tyOpenArray then begin
+          s := skipTypes(it.sons[1].typ, abstractVar);
           if (s.kind = tyArrayConstr) and (s.sons[1].kind = tyEmpty) then begin
             s := copyType(s, getCurrOwner(), false);
-            skipVarGeneric(s).sons[1] := elemType(skipVarGeneric(it.typ));
+            skipTypes(s, abstractVar).sons[1] := elemType(
+              skipTypes(it.typ, abstractVar));
             it.sons[1].typ := s;
           end
         end
-        else if skipVarGeneric(it.sons[1].typ).kind in [tyNil, tyArrayConstr,
-                      tyTuple, tySet] then begin
-          s := skipVarGeneric(it.typ);
+        else if skipTypes(it.sons[1].typ, abstractVar).kind in 
+                  [tyNil, tyArrayConstr, tyTuple, tySet] then begin
+          s := skipTypes(it.typ, abstractVar);
           changeType(it.sons[1], s);
           n.sons[i] := it.sons[1];
         end
@@ -335,7 +340,7 @@ function skipObjConv(n: PNode): PNode;
 begin
   case n.kind of
     nkHiddenStdConv, nkHiddenSubConv, nkConv: begin
-      if skipPtrsGeneric(n.sons[1].typ).kind in [tyTuple, tyObject] then
+      if skipTypes(n.sons[1].typ, abstractPtrs).kind in [tyTuple, tyObject] then
         result := n.sons[1]
       else
         result := n
@@ -352,7 +357,7 @@ begin
     nkSym: result := n.sym.kind in [skVar, skTemp];
     nkDotExpr, nkQualified, nkBracketExpr: begin
       checkMinSonsLen(n, 1);
-      if skipGeneric(n.sons[0].typ).kind in [tyVar, tyPtr, tyRef] then
+      if skipTypes(n.sons[0].typ, abstractInst).kind in [tyVar, tyPtr, tyRef] then
         result := true
       else
         result := isAssignable(n.sons[0]);
@@ -361,7 +366,7 @@ begin
       // Object and tuple conversions are still addressable, so we skip them
       //if skipPtrsGeneric(n.sons[1].typ).kind in [tyOpenArray,
       //                                           tyTuple, tyObject] then
-      if skipPtrsGeneric(n.typ).kind in [tyOpenArray, tyTuple, tyObject] then
+      if skipTypes(n.typ, abstractPtrs).kind in [tyOpenArray, tyTuple, tyObject] then
         result := isAssignable(n.sons[1])
     end;
     nkHiddenDeref, nkDerefExpr: result := true;
@@ -391,7 +396,7 @@ begin
   result := n;
   case n.kind of
     nkSym: begin
-      if skipGeneric(n.sym.typ).kind <> tyVar then begin
+      if skipTypes(n.sym.typ, abstractInst).kind <> tyVar then begin
         include(n.sym.flags, sfAddrTaken);
         result := newHiddenAddrTaken(c, n);
       end
@@ -400,14 +405,14 @@ begin
       checkSonsLen(n, 2);
       if n.sons[1].kind <> nkSym then
         internalError(n.info, 'analyseIfAddressTaken');
-      if skipGeneric(n.sons[1].sym.typ).kind <> tyVar then begin
+      if skipTypes(n.sons[1].sym.typ, abstractInst).kind <> tyVar then begin
         include(n.sons[1].sym.flags, sfAddrTaken);
         result := newHiddenAddrTaken(c, n);
       end
     end;
     nkBracketExpr: begin
       checkMinSonsLen(n, 1);
-      if skipGeneric(n.sons[0].typ).kind <> tyVar then begin
+      if skipTypes(n.sons[0].typ, abstractInst).kind <> tyVar then begin
         if n.sons[0].kind = nkSym then
           include(n.sons[0].sym.flags, sfAddrTaken);
         result := newHiddenAddrTaken(c, n);
@@ -433,7 +438,7 @@ begin
   if (n.sons[0].kind = nkSym)
       and (n.sons[0].sym.magic in FakeVarParams) then exit;
   for i := 1 to sonsLen(n)-1 do
-    if (i < sonsLen(t)) and (skipGeneric(t.sons[i]).kind = tyVar) then
+    if (i < sonsLen(t)) and (skipTypes(t.sons[i], abstractInst).kind = tyVar) then
       n.sons[i] := analyseIfAddressTaken(c, n.sons[i]);
 end;
 
@@ -503,16 +508,16 @@ begin
   fixAbstractType(c, result);
   analyseIfAddressTakenInCall(c, result);
 end;
-
+(*
 function semIncSucc(c: PContext; n: PNode; const opr: string): PNode;
 // handles Inc, Dec, Succ and Pred
 var
   a: PNode;
   typ: PType;
 begin
-  checkMinSonsLen(n, 1);
+  checkMinSonsLen(n, 2);
   n.sons[1] := semExprWithType(c, n.sons[1]);
-  typ := skipVar(n.sons[1].Typ);
+  typ := skipTypes(n.sons[1].Typ, {@set}[tyGenericInst, tyVar]);
   if not isOrdinalType(typ) or enumHasWholes(typ) then
     liMessage(n.sons[1].Info, errOrdinalTypeExpected);
   if sonsLen(n) = 3 then begin
@@ -537,10 +542,27 @@ function semOrd(c: PContext; n: PNode): PNode;
 begin
   checkSonsLen(n, 2);
   n.sons[1] := semExprWithType(c, n.sons[1]);
-  if not isOrdinalType(skipVar(n.sons[1].Typ)) then
+  if not isOrdinalType(skipTypes(n.sons[1].Typ, {@set}[tyGenericInst, tyVar])) then
     liMessage(n.Info, errOrdinalTypeExpected);
   n.typ := getSysType(tyInt);
   result := n
+end; *)
+
+function semEcho(c: PContext; n: PNode): PNode;
+var
+  i: int;
+  call, arg: PNode;
+begin
+  // this really is a macro
+  checkMinSonsLen(n, 1);
+  for i := 1 to sonsLen(n)-1 do begin
+    arg := semExprWithType(c, n.sons[i]);
+    call := newNodeI(nkCall, arg.info);
+    addSon(call, newIdentNode(getIdent('$'+''), n.info));
+    addSon(call, arg);
+    n.sons[i] := semExpr(c, call);
+  end;
+  result := n;
 end;
 
 function LookUpForDefined(c: PContext; n: PNode): PSym;
@@ -609,6 +631,8 @@ begin
     mHigh:    result := semLowHigh(c, setMs(n, s), mHigh);
     mSizeOf:  result := semSizeof(c, setMs(n, s));
     mIs:      result := semIs(c, setMs(n, s));
+    mEcho:    result := semEcho(c, setMs(n, s)); 
+    (*
     mSucc:    begin
       result := semIncSucc(c, setMs(n, s), 'succ');
       result.typ := n.sons[1].typ;
@@ -619,7 +643,7 @@ begin
     end;
     mInc:     result := semIncSucc(c, setMs(n, s), 'inc');
     ast.mDec: result := semIncSucc(c, setMs(n, s), 'dec');
-    mOrd:     result := semOrd(c, setMs(n, s));
+    mOrd:     result := semOrd(c, setMs(n, s)); *)
     else      result := semDirectOp(c, n);
   end;
 end;
@@ -659,7 +683,14 @@ begin
         result.info := n.info;
         result.typ := s.typ;
       end
-    end
+    end;
+    skMacro: result := semMacroExpr(c, n, s);
+    skTemplate: begin
+      // Templates and macros can be invoked without ``()``
+      pushInfoContext(n.info);
+      result := evalTemplate(c, n, s);
+      popInfoContext();
+    end;
     else begin end
   end;
   checkDeprecated(n, s);
@@ -808,7 +839,7 @@ begin
     exit
   end;
 
-  ty := skipPtrsGeneric(ty);
+  ty := skipTypes(ty, {@set}[tyGenericInst, tyVar, tyPtr, tyRef]);
   if ty.kind = tyObject then begin
     while true do begin
       check := nil;
@@ -816,7 +847,7 @@ begin
       //f := lookupInRecord(ty.n, i);
       if f <> nil then break;
       if ty.sons[0] = nil then break;
-      ty := skipGeneric(ty.sons[0]);
+      ty := skipTypes(ty.sons[0], {@set}[tyGenericInst]);
     end;
     if f <> nil then begin
       if ([sfStar, sfMinus] * f.flags <> [])
@@ -883,7 +914,7 @@ begin
   // check if array type:
   checkMinSonsLen(n, 2);
   n.sons[0] := semExprWithType(c, n.sons[0], flags-[efAllowType]);
-  arr := skipPtrsGeneric(n.sons[0].typ);
+  arr := skipTypes(n.sons[0].typ, {@set}[tyGenericInst, tyVar, tyPtr, tyRef]);
   case arr.kind of
     tyArray, tyOpenArray, tyArrayConstr, tySequence, tyString,
     tyCString: begin
@@ -904,7 +935,8 @@ begin
       n.sons[0] := makeDeref(n.sons[0]);
       // [] operator for tuples requires constant expression
       n.sons[1] := semConstExpr(c, n.sons[1]);
-      if skipRange(n.sons[1].typ).kind in [tyInt..tyInt64] then begin
+      if skipTypes(n.sons[1].typ, {@set}[tyGenericInst, tyRange, tyOrdinal]).kind in
+          [tyInt..tyInt64] then begin
         idx := getOrdValue(n.sons[1]);
         if (idx >= 0) and (idx < sonsLen(arr)) then
           n.typ := arr.sons[int(idx)]
@@ -984,12 +1016,15 @@ begin
         checkSonsLen(n.sons[i], 2);
         n.sons[i].sons[0] := semExprWithType(c, n.sons[i].sons[0]);
         n.sons[i].sons[1] := semExprWithType(c, n.sons[i].sons[1]);
-        if typ = nil then typ := skipVar(n.sons[i].sons[0].typ);
+        if typ = nil then 
+          typ := skipTypes(n.sons[i].sons[0].typ, 
+            {@set}[tyGenericInst, tyVar, tyOrdinal]);
         n.sons[i].typ := n.sons[i].sons[1].typ; // range node needs type too
       end
       else begin
         n.sons[i] := semExprWithType(c, n.sons[i]);
-        if typ = nil then typ := skipVar(n.sons[i].typ)
+        if typ = nil then
+          typ := skipTypes(n.sons[i].typ, {@set}[tyGenericInst, tyVar, tyOrdinal])
       end
     end;
     if not isOrdinalType(typ) then begin
@@ -1156,10 +1191,7 @@ begin
   if (s <> nil) then begin
     checkDeprecated(n, s);
     case s.kind of
-      skMacro: begin
-        include(s.flags, sfUsed);
-        result := semMacroExpr(c, n, s);
-      end;
+      skMacro: result := semMacroExpr(c, n, s);
       skTemplate: begin
         include(s.flags, sfUsed);
         // transform
@@ -1234,7 +1266,6 @@ begin
         result := semExpr(c, result, flags)
       end;
     end;
-    // complex expressions
     nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand: begin
       // check if it is an expression macro:
       checkMinSonsLen(n, 1);
@@ -1242,10 +1273,7 @@ begin
       if (s <> nil) then begin
         checkDeprecated(n, s);
         case s.kind of
-          skMacro: begin
-            include(s.flags, sfUsed);
-            result := semMacroExpr(c, n, s);
-          end;
+          skMacro: result := semMacroExpr(c, n, s);
           skTemplate: begin
             include(s.flags, sfUsed);
             pushInfoContext(n.info);
@@ -1307,7 +1335,7 @@ begin
       checkSonsLen(n, 1);
       n.sons[0] := semExprWithType(c, n.sons[0]);
       result := n;
-      case skipVarGeneric(n.sons[0].typ).kind of
+      case skipTypes(n.sons[0].typ, {@set}[tyGenericInst, tyVar]).kind of
         tyRef, tyPtr: n.typ := n.sons[0].typ.sons[0];
         else liMessage(n.sons[0].info, errCircumNeedsPointer);
       end;
diff --git a/nim/semfold.pas b/nim/semfold.pas
index 261e27fd5..556dabe9b 100644
--- a/nim/semfold.pas
+++ b/nim/semfold.pas
@@ -1,7 +1,7 @@
 //
 //
 //           The Nimrod Compiler
-//        (c) Copyright 2008 Andreas Rumpf
+//        (c) Copyright 2009 Andreas Rumpf
 //
 //    See the file "copying.txt", included in this
 //    distribution, for details about the copyright.
@@ -39,7 +39,7 @@ implementation
 
 function newIntNodeT(const intVal: BiggestInt; n: PNode): PNode;
 begin
-  if skipVarGenericRange(n.typ).kind = tyChar then
+  if skipTypes(n.typ, abstractVarRange).kind = tyChar then
     result := newIntNode(nkCharLit, intVal)
   else
     result := newIntNode(nkIntLit, intVal);
@@ -102,7 +102,7 @@ var
   i: int;
 begin
   x := getInt(a);
-  n := a.typ.n;
+  n := skipTypes(a.typ, abstractInst).n;
   for i := 0 to sonsLen(n)-1 do begin
     if n.sons[i].kind <> nkSym then InternalError(a.info, 'enumValToString');
     field := n.sons[i].sym;
@@ -163,7 +163,7 @@ begin
       else result := newIntNodeT(getInt(b), n);
     end;
     mShlI, mShlI64: begin
-      case skipGenericRange(n.typ).kind of
+      case skipTypes(n.typ, abstractRange).kind of
         tyInt8:  result := newIntNodeT(int8(getInt(a)) shl int8(getInt(b)), n);
         tyInt16: result := newIntNodeT(int16(getInt(a)) shl int16(getInt(b)), n);
         tyInt32: result := newIntNodeT(int32(getInt(a)) shl int32(getInt(b)), n);
@@ -173,7 +173,7 @@ begin
       end
     end;
     mShrI, mShrI64: begin
-      case skipGenericRange(n.typ).kind of
+      case skipTypes(n.typ, abstractRange).kind of
         tyInt8:  result := newIntNodeT(int8(getInt(a)) shr int8(getInt(b)), n);
         tyInt16: result := newIntNodeT(int16(getInt(a)) shr int16(getInt(b)), n);
         tyInt32: result := newIntNodeT(int32(getInt(a)) shr int32(getInt(b)), n);
@@ -287,7 +287,7 @@ begin
       result := copyTree(a);
       result.typ := n.typ;
     end;
-    mNewString, mExit, mInc, ast.mDec, mAssert, mSwap,
+    mNewString, mExit, mInc, ast.mDec, mEcho, mAssert, mSwap,
     mAppendStrCh, mAppendStrStr, mAppendSeqElem, mAppendSeqSeq,
     mSetLengthStr, mSetLengthSeq, mNLen..mNError: begin end;
     else InternalError(a.info, 'evalOp(' +{&} magicToStr[m] +{&} ')');
@@ -417,7 +417,7 @@ begin
     end;
     nkCharLit..nkNilLit: result := copyNode(n);
     nkIfExpr: result := getConstIfExpr(module, n);
-    nkCall: begin
+    nkCall, nkCommand: begin
       if (n.sons[0].kind <> nkSym) then exit;
       s := n.sons[0].sym;
       if (s.kind <> skProc) then exit;
@@ -440,9 +440,10 @@ begin
           end;
           mLow:  result := newIntNodeT(firstOrd(n.sons[1].typ), n);
           mHigh: begin
-            if not (skipVarGeneric(n.sons[1].typ).kind in [tyOpenArray,
+            if not (skipTypes(n.sons[1].typ, abstractVar).kind in [tyOpenArray,
                                      tySequence, tyString]) then
-              result := newIntNodeT(lastOrd(skipVarGeneric(n.sons[1].typ)), n);
+              result := newIntNodeT(lastOrd(
+                skipTypes(n.sons[1].typ, abstractVar)), n);
           end;
           else begin
             a := getConstExpr(module, n.sons[1]);
@@ -537,9 +538,9 @@ begin
     nkHiddenStdConv, nkHiddenSubConv, nkConv, nkCast: begin
       a := getConstExpr(module, n.sons[1]);
       if a = nil then exit;
-      case skipRange(n.typ).kind of
+      case skipTypes(n.typ, abstractRange).kind of
         tyInt..tyInt64: begin
-          case skipRange(a.typ).kind of
+          case skipTypes(a.typ, abstractRange).kind of
             tyFloat..tyFloat64: 
               result := newIntNodeT(nsystem.toInt(getFloat(a)), n);
             tyChar: 
@@ -551,7 +552,7 @@ begin
           end
         end;
         tyFloat..tyFloat64: begin
-          case skipRange(a.typ).kind of
+          case skipTypes(a.typ, abstractRange).kind of
             tyInt..tyInt64, tyEnum, tyBool, tyChar: 
               result := newFloatNodeT(toFloat(int(getOrdValue(a))), n);
             else begin
diff --git a/nim/semstmts.pas b/nim/semstmts.pas
index a5242b526..c8b942df8 100644
--- a/nim/semstmts.pas
+++ b/nim/semstmts.pas
@@ -1,7 +1,7 @@
 //
 //
 //           The Nimrod Compiler
-//        (c) Copyright 2008 Andreas Rumpf
+//        (c) Copyright 2009 Andreas Rumpf
 //
 //    See the file "copying.txt", included in this
 //    distribution, for details about the copyright.
@@ -205,7 +205,7 @@ begin
   n.sons[0] := semExprWithType(c, n.sons[0]);
   chckCovered := false;
   covered := 0;
-  case skipVarGenericRange(n.sons[0].Typ).Kind of
+  case skipTypes(n.sons[0].Typ, abstractVarRange).Kind of
     tyInt..tyInt64, tyChar, tyEnum: chckCovered := true;
     tyFloat..tyFloat128, tyString: begin end
     else liMessage(n.info, errSelectorMustBeOfCertainTypes);
@@ -302,7 +302,8 @@ begin
   n.sons[0] := semExprWithType(c, n.sons[0], {@set}[efLValue]);
   n.sons[1] := semExprWithType(c, n.sons[1]);
   le := n.sons[0].typ;
-  if (skipGeneric(le).kind <> tyVar) and not IsAssignable(n.sons[0]) then begin
+  if (skipTypes(le, {@set}[tyGenericInst]).kind <> tyVar) 
+  and not IsAssignable(n.sons[0]) then begin
     liMessage(n.sons[0].info, errXCannotBeAssignedTo,
               renderTree(n.sons[0], {@set}[renderNoComments]));
   end
@@ -410,7 +411,7 @@ begin
       def := nil;
     if not typeAllowed(typ, skVar) then
       liMessage(a.info, errXisNoType, typeToString(typ));
-    tup := skipGeneric(typ);
+    tup := skipTypes(typ, {@set}[tyGenericInst]);
     if a.kind = nkVarTuple then begin
       if tup.kind <> tyTuple then liMessage(a.info, errXExpected, 'tuple');
       if len-2 <> sonsLen(tup) then
@@ -511,7 +512,7 @@ begin
     n.sons[len-2] := countupNode;
   end;
   n.sons[len-2] := semExprWithType(c, n.sons[len-2]);
-  iter := skipGeneric(n.sons[len-2].typ);
+  iter := skipTypes(n.sons[len-2].typ, {@set}[tyGenericInst]);
   if iter.kind <> tyTuple then begin
     if len <> 3 then liMessage(n.info, errWrongNumberOfVariables);
     v := newSymS(skForVar, n.sons[0], c);
@@ -742,6 +743,17 @@ begin
   end
 end;
 
+procedure semBorrow(c: PContext; n: PNode; s: PSym);
+var
+  b: PSym;
+begin
+  // search for the correct alias:
+  b := SearchForBorrowProc(c, s, c.tab.tos-2);
+  if b = nil then liMessage(n.info, errNoSymbolToBorrowFromFound);
+  // store the alias:
+  n.sons[codePos] := newSymNode(b);
+end;
+
 function semIterator(c: PContext; n: PNode): PNode;
 var
   s: PSym;
@@ -774,6 +786,8 @@ begin
     pragmaIterator(c, s, n.sons[pragmasPos]);
   s.options := gOptions;
   if n.sons[codePos] <> nil then begin
+    if sfBorrow in s.flags then
+      liMessage(n.info, errImplOfXNotAllowed, s.name.s);
     if n.sons[genericParamsPos] = nil then begin
       c.p := newProcCon(s);
       openScope(c.tab);
@@ -784,6 +798,8 @@ begin
       n.sons[codePos] := resolveGenericParams(c, n.sons[codePos]);
     end
   end
+  else if (sfBorrow in s.flags) then
+    semBorrow(c, n, s)
   else
     liMessage(n.info, errIteratorNeedsImplementation);
   closeScope(c.tab);
@@ -849,7 +865,7 @@ begin
   s.options := gOptions;
   if n.sons[codePos] <> nil then begin
     if sfImportc in s.flags then
-      liMessage(n.sons[codePos].info, errImportedProcCannotHaveImpl);
+      liMessage(n.sons[codePos].info, errImplOfXNotAllowed, s.name.s);
     c.p := newProcCon(s);
     addResult(c, s.typ.sons[0], n.info);
     n.sons[codePos] := semStmtScope(c, n.sons[codePos]);
@@ -937,8 +953,8 @@ begin
 
   s.options := gOptions;
   if n.sons[codePos] <> nil then begin
-    if sfImportc in s.flags then
-      liMessage(n.sons[codePos].info, errImportedProcCannotHaveImpl);
+    if [sfImportc, sfBorrow] * s.flags <> [] then
+      liMessage(n.sons[codePos].info, errImplOfXNotAllowed, s.name.s);
     if n.sons[genericParamsPos] = nil then begin
       c.p := newProcCon(s);
       addResult(c, s.typ.sons[0], n.info);
@@ -952,7 +968,9 @@ begin
   else begin
     if proto <> nil then
       liMessage(n.info, errImplOfXexpected, proto.name.s);
-    if not (sfImportc in s.flags) then Include(s.flags, sfForward);
+    if [sfImportc, sfBorrow] * s.flags = [] then Include(s.flags, sfForward)
+    else if sfBorrow in s.flags then 
+      semBorrow(c, n, s);
   end;
   closeScope(c.tab); // close scope for parameters
   popOwner();
diff --git a/nim/semtypes.pas b/nim/semtypes.pas
index 014ff0216..c968d4b72 100644
--- a/nim/semtypes.pas
+++ b/nim/semtypes.pas
@@ -1,7 +1,7 @@
 //
 //
 //           The Nimrod Compiler
-//        (c) Copyright 2008 Andreas Rumpf
+//        (c) Copyright 2009 Andreas Rumpf
 //
 //    See the file "copying.txt", included in this
 //    distribution, for details about the copyright.
@@ -140,6 +140,15 @@ begin
     liMessage(n.info, errXExpectsOneTypeParam, 'var');
 end;
 
+function semAbstract(c: PContext; n: PNode; prev: PType): PType;
+begin
+  result := newOrPrevType(tyAbstract, prev, c);
+  if sonsLen(n) = 1 then 
+    addSon(result, semTypeNode(c, n.sons[0], nil))
+  else
+    liMessage(n.info, errXExpectsOneTypeParam, 'abstract');
+end;
+
 function semRangeAux(c: PContext; n: PNode; prev: PType): PType;
 var
   a, b: PNode;
@@ -202,6 +211,23 @@ begin
     liMessage(n.info, errArrayExpectsTwoTypeParams);
 end;
 
+function semOrdinal(c: PContext; n: PNode; prev: PType): PType;
+var
+  base: PType;
+begin
+  result := newOrPrevType(tyOrdinal, prev, c);
+  if sonsLen(n) = 2 then begin
+    base := semTypeNode(c, n.sons[1], nil);
+    if base.kind <> tyGenericParam then begin
+      if not isOrdinalType(base) then
+        liMessage(n.sons[1].info, errOrdinalTypeExpected);
+    end;
+    addSon(result, base);
+  end
+  else
+    liMessage(n.info, errXExpectsOneTypeParam, 'ordinal');
+end;
+
 function semTypeIdent(c: PContext; n: PNode): PSym;
 begin
   result := qualifiedLookup(c, n, true);
@@ -441,7 +467,7 @@ begin
     internalError('semRecordCase: dicriminant is no symbol');
   include(a.sons[0].sym.flags, sfDiscriminant);
   covered := 0;
-  typ := skipVarGeneric(a.sons[0].Typ);
+  typ := skipTypes(a.sons[0].Typ, abstractVar);
   if not isOrdinalType(typ) then
     liMessage(n.info, errSelectorMustBeOrdinal);
   if firstOrd(typ) < 0 then
@@ -740,6 +766,7 @@ begin
         mOpenArray: result := semContainer(c, n, tyOpenArray, 'openarray', prev);
         mRange: result := semRange(c, n, prev);
         mSet: result := semSet(c, n, prev);
+        mOrdinal: result := semOrdinal(c, n, prev);
         mSeq: result := semContainer(c, n, tySequence, 'seq', prev);
         else result := semGeneric(c, n, s, prev);
       end
@@ -774,6 +801,7 @@ begin
     nkRefTy: result := semAnyRef(c, n, tyRef, 'ref', prev);
     nkPtrTy: result := semAnyRef(c, n, tyPtr, 'ptr', prev);
     nkVarTy: result := semVarType(c, n, prev);
+    nkAbstractTy: result := semAbstract(c, n, prev);
     nkProcTy: begin
       checkSonsLen(n, 2);
       result := semProcTypeNode(c, n.sons[0], prev);
@@ -821,7 +849,6 @@ begin
       addSon(m.typ, getSysType(tyChar));
     end;
     mPointer: setMagicType(m, tyPointer, ptrSize);
-    mAnyEnum: setMagicType(m, tyAnyEnum, 1);
     mEmptySet: begin
       setMagicType(m, tySet, 1);
       addSon(m.typ, newTypeS(tyEmpty, c));
@@ -832,7 +859,7 @@ begin
       exit
     end;
     mNil: setMagicType(m, tyNil, ptrSize);
-    mArray, mOpenArray, mRange, mSet, mSeq: exit;
+    mArray, mOpenArray, mRange, mSet, mSeq, mOrdinal: exit;
     else liMessage(m.info, errTypeExpected);
   end;
   //registerSysType(m.typ);
diff --git a/nim/sigmatch.pas b/nim/sigmatch.pas
index 5195de26c..d95745e0c 100644
--- a/nim/sigmatch.pas
+++ b/nim/sigmatch.pas
@@ -122,7 +122,7 @@ begin
   if a.kind = f.kind then
     result := isEqual
   else begin
-    k := skipRange(a).kind;
+    k := skipTypes(a, {@set}[tyRange]).kind;
     if k = f.kind then
       result := isSubtype
     else if (f.kind = tyInt) and (k in [tyInt..tyInt32]) then 
@@ -141,7 +141,7 @@ begin
   if a.kind = f.kind then
     result := isEqual
   else begin
-    k := skipRange(a).kind;
+    k := skipTypes(a, {@set}[tyRange]).kind;
     if k = f.kind then
       result := isSubtype
     else if (k >= tyFloat) and (k <= tyFloat128) then
@@ -203,7 +203,8 @@ begin // is a subtype of f?
   result := isNone;
   assert(f <> nil);
   assert(a <> nil);
-  if (a.kind = tyGenericInst) and (skipVar(f).kind <> tyGeneric) then begin
+  if (a.kind = tyGenericInst) and 
+      (skipTypes(f, {@set}[tyVar]).kind <> tyGeneric) then begin
     result := typeRel(mapping, f, lastSon(a));
     exit
   end;
@@ -214,18 +215,19 @@ begin // is a subtype of f?
   case f.kind of
     tyEnum: begin
       if (a.kind = f.kind) and (a.id = f.id) then result := isEqual
-      else if (skipRange(a).id = f.id) then result := isSubtype
+      else if (skipTypes(a, {@set}[tyRange]).id = f.id) then result := isSubtype
     end;
     tyBool, tyChar: begin
       if (a.kind = f.kind) then result := isEqual
-      else if skipRange(a).kind = f.kind then result := isSubtype
+      else if skipTypes(a, {@set}[tyRange]).kind = f.kind then 
+        result := isSubtype
     end;
     tyRange: begin
       if (a.kind = f.kind) then begin
         result := typeRel(mapping, base(a), base(f));
         if result < isGeneric then result := isNone
       end
-      else if skipRange(f).kind = a.kind then
+      else if skipTypes(f, {@set}[tyRange]).kind = a.kind then
         result := isConvertible // a convertible to f
     end;
     tyInt:   result := handleRange(f, a, tyInt8, tyInt32);
@@ -311,6 +313,13 @@ begin // is a subtype of f?
         else begin end
       end
     end;
+    tyOrdinal: begin
+      if isOrdinalType(a) then begin
+        if a.kind = tyOrdinal then x := a.sons[0] else x := a;
+        result := typeRel(mapping, f.sons[0], x);
+        if result < isGeneric then result := isNone
+      end
+    end;
     tyForward: InternalError('forward type in typeRel()');
     tyNil: begin
       if a.kind = f.kind then result := isEqual
@@ -324,6 +333,9 @@ begin // is a subtype of f?
         else if isObjectSubtype(a, f) then result := isSubtype
       end
     end;
+    tyAbstract: begin
+      if (a.kind = tyAbstract) and (a.id = f.id) then result := isEqual;
+    end;
     tySet: begin
       if a.kind = tySet then begin
         if (f.sons[0].kind <> tyGenericParam) and
@@ -418,8 +430,8 @@ begin // is a subtype of f?
         tyPtr: if a.sons[0].kind = tyChar then result := isConvertible;
         tyArray: begin
           if (firstOrd(a.sons[0]) = 0)
-              and (skipRange(a.sons[0]).kind in [tyInt..tyInt64])
-              and (a.sons[1].kind = tyChar) then
+             and (skipTypes(a.sons[0], {@set}[tyRange]).kind in [tyInt..tyInt64])
+             and (a.sons[1].kind = tyChar) then
             result := isConvertible;
         end
         else begin end
@@ -429,14 +441,6 @@ begin // is a subtype of f?
     tyEmpty: begin
       if a.kind = tyEmpty then result := isEqual;
     end;
-    tyAnyEnum: begin
-      case a.kind of
-        tyRange:   result := typeRel(mapping, f, base(a));
-        tyEnum:    result := isSubtype;
-        tyAnyEnum: result := isEqual;
-        else begin end
-      end
-    end;
     tyGenericInst: begin
       result := typeRel(mapping, lastSon(f), a);
     end;
@@ -572,7 +576,7 @@ begin
       result := copyTree(arg);
       result.typ := getInstantiatedType(c, arg, m, f);
       // BUG: f may not be the right key!
-      if (skipVarGeneric(result.typ).kind in [tyTuple, tyOpenArray]) then
+      if (skipTypes(result.typ, abstractVar).kind in [tyTuple, tyOpenArray]) then
         // BUGFIX: must pass length implicitely
         result := implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c);
       // BUGFIX: use ``result.typ`` and not `f` here
@@ -580,7 +584,7 @@ begin
     isEqual: begin
       inc(m.exactMatches);
       result := copyTree(arg);
-      if (skipVarGeneric(f).kind in [tyTuple, tyOpenArray]) then
+      if (skipTypes(f, abstractVar).kind in [tyTuple, tyOpenArray]) then
         // BUGFIX: must pass length implicitely
         result := implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c);
     end;
@@ -679,7 +683,7 @@ begin
       if f >= formalLen then begin // too many arguments?
         if tfVarArgs in m.callee.flags then begin
           // is ok... but don't increment any counters...
-          if skipVarGeneric(n.sons[a].typ).kind = tyString then
+          if skipTypes(n.sons[a].typ, abstractVar).kind = tyString then
             // conversion to cstring
             addSon(m.call, implicitConv(nkHiddenStdConv,
               getSysType(tyCString), copyTree(n.sons[a]), m, c))
diff --git a/nim/transf.pas b/nim/transf.pas
index 476ee4c33..b1812d52c 100644
--- a/nim/transf.pas
+++ b/nim/transf.pas
@@ -1,7 +1,7 @@
 //
 //
 //           The Nimrod Compiler
-//        (c) Copyright 2008 Andreas Rumpf
+//        (c) Copyright 2009 Andreas Rumpf
 //
 //    See the file "copying.txt", included in this
 //    distribution, for details about the copyright.
@@ -80,7 +80,8 @@ function newTemp(c: PTransf; typ: PType; const info: TLineInfo): PSym;
 begin
   result := newSym(skTemp, getIdent(genPrefix), getCurrOwner(c));
   result.info := info;
-  result.typ := skipGeneric(typ);
+  result.typ := skipTypes(typ, {@set}[tyGenericInst]);
+  // XXX really correct? maybe we need tyGenericInst for generic instantion?
   include(result.flags, sfFromGeneric);
 end;
 
@@ -148,23 +149,34 @@ end;
 function transformSym(c: PTransf; n: PNode): PNode;
 var
   tc: PTransCon;
+  b: PNode;
 begin
   if (n.kind <> nkSym) then internalError(n.info, 'transformSym');
   tc := c.transCon;
+  if sfBorrow in n.sym.flags then begin
+    // simply exchange the symbol:
+    b := n.sym.ast.sons[codePos];
+    if b.kind <> nkSym then 
+      internalError(n.info, 'wrong AST for borrowed symbol');
+    b := newSymNode(b.sym);
+    b.info := n.info;
+  end
+  else 
+    b := n;
   //writeln('transformSym', n.sym.id : 5);
   while tc <> nil do begin
-    result := IdNodeTableGet(tc.mapping, n.sym);
+    result := IdNodeTableGet(tc.mapping, b.sym);
     if result <> nil then exit;
     //write('not found in: ');
     //writeIdNodeTable(tc.mapping);
     tc := tc.next
   end;
-  result := n;
-  case n.sym.kind of
+  result := b;
+  case b.sym.kind of
     skConst, skEnumField: begin // BUGFIX: skEnumField was missing
-      if not (skipGeneric(n.sym.typ).kind in ConstantDataTypes) then begin
-        result := getConstExpr(c.module, n);
-        if result = nil then InternalError(n.info, 'transformSym: const');
+      if not (skipTypes(b.sym.typ, abstractInst).kind in ConstantDataTypes) then begin
+        result := getConstExpr(c.module, b);
+        if result = nil then InternalError(b.info, 'transformSym: const');
       end
     end
     else begin end
@@ -254,7 +266,7 @@ var
 begin
   result := newNodeI(nkStmtList, n.info);
   e := n.sons[0];
-  if skipGeneric(e.typ).kind = tyTuple then begin
+  if skipTypes(e.typ, {@set}[tyGenericInst]).kind = tyTuple then begin
     e := skipConv(e);
     if e.kind = nkPar then begin
       for i := 0 to sonsLen(e)-1 do begin
@@ -366,8 +378,8 @@ begin
   n.sons[1] := transform(c, n.sons[1]);
   result := n;
   // numeric types need range checks:
-  dest := skipVarGenericRange(n.typ);
-  source := skipVarGenericRange(n.sons[1].typ);
+  dest := skipTypes(n.typ, abstractVarRange);
+  source := skipTypes(n.sons[1].typ, abstractVarRange);
   case dest.kind of
     tyInt..tyInt64, tyEnum, tyChar, tyBool: begin
       if (firstOrd(dest) <= firstOrd(source)) and
@@ -381,16 +393,16 @@ begin
           result := newNodeIT(nkChckRange64, n.info, n.typ)
         else
           result := newNodeIT(nkChckRange, n.info, n.typ);
-        dest := skipVarGeneric(n.typ);
+        dest := skipTypes(n.typ, abstractVar);
         addSon(result, n.sons[1]);
         addSon(result, newIntTypeNode(nkIntLit, firstOrd(dest), source));
         addSon(result, newIntTypeNode(nkIntLit,  lastOrd(dest), source));
       end
     end;
     tyFloat..tyFloat128: begin
-      if skipVarGeneric(n.typ).kind = tyRange then begin
+      if skipTypes(n.typ, abstractVar).kind = tyRange then begin
         result := newNodeIT(nkChckRangeF, n.info, n.typ);
-        dest := skipVarGeneric(n.typ);
+        dest := skipTypes(n.typ, abstractVar);
         addSon(result, n.sons[1]);
         addSon(result, copyTree(dest.n.sons[0]));
         addSon(result, copyTree(dest.n.sons[1]));
@@ -413,8 +425,8 @@ begin
       end;
     end;
     tyRef, tyPtr: begin
-      dest := skipPtrsGeneric(dest);
-      source := skipPtrsGeneric(source);
+      dest := skipTypes(dest, abstractPtrs);
+      source := skipTypes(source, abstractPtrs);
       if source.kind = tyObject then begin
         diff := inheritanceDiff(dest, source);
         if diff < 0 then begin
@@ -444,7 +456,7 @@ begin
     tyArray, tySeq: begin
       if skipGeneric(dest
     end; *)
-    tyGenericParam, tyAnyEnum: result := n.sons[1];
+    tyGenericParam, tyOrdinal: result := n.sons[1];
       // happens sometimes for generated assignments, etc.
     else begin end
   end;
@@ -465,7 +477,7 @@ function putArgInto(arg: PNode; formal: PType): TPutArgInto;
 var
   i: int;
 begin
-  if skipGeneric(formal).kind = tyOpenArray then begin
+  if skipTypes(formal, abstractInst).kind = tyOpenArray then begin
     result := paDirectMapping; // XXX really correct?
     // what if ``arg`` has side-effects?
     exit
@@ -480,7 +492,7 @@ begin
       result := paDirectMapping;
     end;
     else begin
-      if skipGeneric(formal).kind = tyVar then
+      if skipTypes(formal, abstractInst).kind = tyVar then
         result := paVarAsgn
       else
         result := paFastAsgn
@@ -516,7 +528,7 @@ begin
   pushTransCon(c, newC);
   for i := 1 to sonsLen(call)-1 do begin
     arg := skipPassAsOpenArray(transform(c, call.sons[i]));
-    formal := skipGeneric(newC.owner.typ).n.sons[i].sym;
+    formal := skipTypes(newC.owner.typ, abstractInst).n.sons[i].sym;
     //if IdentEq(newc.Owner.name, 'items') then 
     //  liMessage(arg.info, warnUser, 'items: ' + nodeKindToStr[arg.kind]);
     case putArgInto(arg, formal.typ) of
@@ -529,7 +541,7 @@ begin
         IdNodeTablePut(newC.mapping, formal, newSymNode(temp));
       end;
       paVarAsgn: begin
-        assert(skipGeneric(formal.typ).kind = tyVar);
+        assert(skipTypes(formal.typ, abstractInst).kind = tyVar);
         InternalError(arg.info, 'not implemented: pass to var parameter');
       end;
     end;
@@ -820,13 +832,15 @@ var
 begin
   result := n;
   if n = nil then exit;
+  //if ToLinenumber(n.info) = 32 then
+  //  MessageOut(RenderTree(n));
   case n.kind of
     nkSym: begin
       result := transformSym(c, n);
       exit
     end;
     nkEmpty..pred(nkSym), succ(nkSym)..nkNilLit: begin
-      // nothing to be done for leafs
+      // nothing to be done for leaves
     end;
     nkBracketExpr: result := transformArrayAccess(c, n);
     nkLambda: result := transformLambda(c, n);
diff --git a/nim/transtmp.pas b/nim/transtmp.pas
index cfec21c98..77ba157f3 100644
--- a/nim/transtmp.pas
+++ b/nim/transtmp.pas
@@ -140,7 +140,7 @@ begin
         addSon(father, newAsgnStmt(dest, src));
       end
     end;
-    nkCall: begin
+    nkCall, nkCommand: begin
     
     end;
     
diff --git a/nim/trees.pas b/nim/trees.pas
index d271bfae8..4df85f6bb 100644
--- a/nim/trees.pas
+++ b/nim/trees.pas
@@ -144,7 +144,7 @@ end;
 
 function getOpSym(op: PNode): PSym;
 begin
-  if not (op.kind in [nkCall, nkGenericCall, nkHiddenCallConv]) then
+  if not (op.kind in [nkCall, nkGenericCall, nkHiddenCallConv, nkCommand]) then
     result := nil
   else begin
     if (sonsLen(op) <= 0) then InternalError(op.info, 'getOpSym');
@@ -158,7 +158,7 @@ end;
 function getMagic(op: PNode): TMagic;
 begin
   case op.kind of
-    nkCall, nkHiddenCallConv: begin
+    nkCall, nkHiddenCallConv, nkCommand: begin
       case op.sons[0].Kind of
         nkSym: begin
           result := op.sons[0].sym.magic;
diff --git a/nim/types.pas b/nim/types.pas
index af19a1671..b4558fe82 100644
--- a/nim/types.pas
+++ b/nim/types.pas
@@ -48,6 +48,7 @@ function mutateType(t: PType; iter: TTypeMutator; closure: PObject): PType;
 
 function SameType(x, y: PType): Boolean;
 function SameTypeOrNil(a, b: PType): Boolean;
+function equalOrAbstractOf(x, y: PType): bool;
 
 type
   TParamsEquality = (paramsNotEqual,      // parameters are not equal
@@ -64,6 +65,7 @@ function equalParams(a, b: PNode): TParamsEquality;
 function isOrdinalType(t: PType): Boolean;
 function enumHasWholes(t: PType): Boolean;
 
+(*
 function skipRange(t: PType): PType;
 function skipGeneric(t: PType): PType;
 function skipGenericRange(t: PType): PType;
@@ -71,6 +73,16 @@ function skipVar(t: PType): PType;
 function skipVarGeneric(t: PType): PType;
 function skipVarGenericRange(t: PType): PType;
 function skipPtrsGeneric(t: PType): PType;
+*)
+
+const
+  abstractPtrs = {@set}[tyVar, tyPtr, tyRef, tyGenericInst, tyAbstract, tyOrdinal];
+  abstractVar = {@set}[tyVar, tyGenericInst, tyAbstract, tyOrdinal];
+  abstractRange = {@set}[tyGenericInst, tyRange, tyAbstract, tyOrdinal];
+  abstractVarRange = {@set}[tyGenericInst, tyRange, tyVar, tyAbstract, tyOrdinal];
+  abstractInst = {@set}[tyGenericInst, tyAbstract, tyOrdinal];
+
+function skipTypes(t: PType; kinds: TTypeKinds): PType;
 
 function elemType(t: PType): PType;
 
@@ -171,7 +183,7 @@ begin
   result := false;
   if a.kind = tyArray then
     if (firstOrd(a.sons[0]) = 0)
-    and (skipRange(a.sons[0]).kind in [tyInt..tyInt64])
+    and (skipTypes(a.sons[0], {@set}[tyRange]).kind in [tyInt..tyInt64])
     and (a.sons[1].kind = tyChar) then
       result := true
 end;
@@ -200,7 +212,7 @@ function elemType(t: PType): PType;
 begin
   assert(t <> nil);
   case t.kind of
-    tyGenericInst: result := elemType(lastSon(t));
+    tyGenericInst, tyAbstract: result := elemType(lastSon(t));
     tyArray, tyArrayConstr: result := t.sons[1];
     else result := t.sons[0];
   end;
@@ -259,11 +271,17 @@ begin
     result := lastSon(result);
 end;
 
+function skipTypes(t: PType; kinds: TTypeKinds): PType;
+begin
+  result := t;
+  while result.kind in kinds do result := lastSon(result);
+end;
+
 function isOrdinalType(t: PType): Boolean;
 begin
   assert(t <> nil);
   result := (t.Kind in [tyChar, tyInt..tyInt64, tyBool, tyEnum])
-    or (t.Kind = tyRange) and isOrdinalType(t.sons[0]);
+    or (t.Kind in [tyRange, tyOrdinal]) and isOrdinalType(t.sons[0]);
 end;
 
 function enumHasWholes(t: PType): Boolean;
@@ -380,7 +398,8 @@ begin
       if not result then
         result := searchTypeNodeForAux(t.n, predicate, marker);
     end;
-    tyGenericInst: result := searchTypeForAux(lastSon(t), predicate, marker);
+    tyGenericInst, tyAbstract:
+      result := searchTypeForAux(lastSon(t), predicate, marker);
     tyArray, tyArrayConstr, tySet, tyTuple: begin
       for i := 0 to sonsLen(t)-1 do begin
         result := searchTypeForAux(t.sons[i], predicate, marker);
@@ -438,7 +457,8 @@ begin
       if result = frNone then
         if isObjectWithTypeFieldPredicate(t) then result := frHeader
     end;
-    tyGenericInst: result := analyseObjectWithTypeFieldAux(lastSon(t), marker);
+    tyGenericInst, tyAbstract: 
+      result := analyseObjectWithTypeFieldAux(lastSon(t), marker);
     tyArray, tyArrayConstr, tyTuple: begin
       for i := 0 to sonsLen(t)-1 do begin
         res := analyseObjectWithTypeFieldAux(t.sons[i], marker);
@@ -511,7 +531,7 @@ begin
   result := false;
   if t = nil then exit;
   if tfAcyclic in t.flags then exit;
-  case skipGeneric(t).kind of 
+  case skipTypes(t, abstractInst).kind of 
     tyTuple, tyObject, tyRef, tySequence, tyArray, tyArrayConstr,
     tyOpenArray: begin
       if not IntSetContainsOrIncl(marker, t.id) then begin
@@ -597,8 +617,8 @@ function TypeToString(typ: PType; prefer: TPreferedDesc = preferName): string;
 const
   typeToStr: array [TTypeKind] of string = (
     'None', 'bool', 'Char', 'empty', 'Array Constructor [$1]', 'nil',
-    'Generic', 'GenericInst', 'GenericParam',
-    'enum', 'anyenum',
+    'Generic', 'GenericInst', 'GenericParam', 'abstract $1',
+    'enum', 'ordinal[$1]',
     'array[$1, $2]', 'object', 'tuple', 'set[$1]', 'range[$1]',
     'ptr ', 'ref ', 'var ', 'seq[$1]', 'proc', 'pointer',
     'OpenArray[$1]', 'string', 'CString', 'Forward',
@@ -631,8 +651,10 @@ begin
       result := 'Array constructor[' +{&} rangeToStr(t.sons[0].n) +{&} ', '
                 +{&} typeToString(t.sons[1]) +{&} ']';
     tySequence: result := 'seq[' +{&} typeToString(t.sons[0]) +{&} ']';
+    tyOrdinal: result := 'ordinal[' +{&} typeToString(t.sons[0]) +{&} ']';
     tySet: result := 'set[' +{&} typeToString(t.sons[0]) +{&} ']';
     tyOpenArray: result := 'openarray[' +{&} typeToString(t.sons[0]) +{&} ']';
+    tyAbstract: result := 'abstract ' +{&} typeToString(t.sons[0], preferName);
     tyTuple: begin
       // we iterate over t.sons here, because t.n may be nil
       result := 'tuple[';
@@ -718,7 +740,7 @@ begin
         result := t.n.sons[0].sym.position;
       end;
     end;
-    tyGenericInst: result := firstOrd(lastSon(t));
+    tyGenericInst, tyAbstract: result := firstOrd(lastSon(t));
     else begin
       InternalError('invalid kind for first(' +{&}
         typeKindToStr[t.kind] +{&} ')');
@@ -754,7 +776,7 @@ begin
       assert(t.n.sons[sonsLen(t.n)-1].kind = nkSym);
       result := t.n.sons[sonsLen(t.n)-1].sym.position;
     end;
-    tyGenericInst: result := firstOrd(lastSon(t));
+    tyGenericInst, tyAbstract: result := firstOrd(lastSon(t));
     else begin
       InternalError('invalid kind for last(' +{&}
         typeKindToStr[t.kind] +{&} ')');
@@ -767,6 +789,7 @@ function lengthOrd(t: PType): biggestInt;
 begin
   case t.kind of
     tyInt64, tyInt32, tyInt: result := lastOrd(t);
+    tyAbstract: result := lengthOrd(t.sons[0]);
     else result := lastOrd(t) - firstOrd(t) + 1;
   end
 end;
@@ -855,7 +878,7 @@ begin
     SameLiteral(a.sons[1], b.sons[1])
 end;
 
-function sameTuple(a, b: PType): boolean;
+function sameTuple(a, b: PType; AbstractOf: bool): boolean;
 // two tuples are equivalent iff the names, types and positions are the same;
 // however, both types may not have any field names (t.n may be nil) which
 // complicates the matter a bit.
@@ -866,7 +889,10 @@ begin
   if sonsLen(a) = sonsLen(b) then begin
     result := true;
     for i := 0 to sonsLen(a)-1 do begin
-      result := SameType(a.sons[i], b.sons[i]);
+      if AbstractOf then 
+        result := equalOrAbstractOf(a.sons[i], b.sons[i])
+      else
+        result := SameType(a.sons[i], b.sons[i]);
       if not result then exit
     end;
     if (a.n <> nil) and (b.n <> nil) then begin
@@ -891,8 +917,8 @@ var
   a, b: PType;
 begin
   if x = y then begin result := true; exit end;
-  a := skipGeneric(x);
-  b := skipGeneric(y);
+  a := skipTypes(x, {@set}[tyGenericInst]);
+  b := skipTypes(y, {@set}[tyGenericInst]);
   assert(a <> nil);
   assert(b <> nil);
   if a.kind <> b.kind then begin result := false; exit end;
@@ -900,13 +926,13 @@ begin
     tyEmpty, tyChar, tyBool, tyNil, tyPointer, tyString, tyCString, 
     tyInt..tyFloat128: 
       result := true;
-    tyEnum, tyForward, tyObject:
+    tyEnum, tyForward, tyObject, tyAbstract:
       result := (a.id = b.id);
     tyTuple: 
-      result := sameTuple(a, b);
+      result := sameTuple(a, b, false);
     tyGenericInst:
       result := sameType(lastSon(a), lastSon(b));
-    tyGenericParam, tyGeneric, tySequence,
+    tyGenericParam, tyGeneric, tySequence, tyOrdinal,
     tyOpenArray, tySet, tyRef, tyPtr, tyVar, tyArrayConstr,
     tyArray, tyProc: begin
       if sonsLen(a) = sonsLen(b) then begin
@@ -926,7 +952,56 @@ begin
         and SameValue(a.n.sons[0], b.n.sons[0])
         and SameValue(a.n.sons[1], b.n.sons[1])
     end;
-    tyNone, tyAnyEnum: result := false;
+    tyNone: result := false;
+  end
+end;
+
+function equalOrAbstractOf(x, y: PType): bool;
+var
+  i: int;
+  a, b: PType;
+begin
+  if x = y then begin result := true; exit end;
+  if (x = nil) or (y = nil) then begin result := false; exit end;
+  a := skipTypes(x, {@set}[tyGenericInst]);
+  b := skipTypes(y, {@set}[tyGenericInst]);
+  assert(a <> nil);
+  assert(b <> nil);
+  if a.kind <> b.kind then begin 
+    if a.kind = tyAbstract then a := a.sons[0];
+    if a.kind <> b.kind then begin result := false; exit end
+  end;
+  case a.Kind of
+    tyEmpty, tyChar, tyBool, tyNil, tyPointer, tyString, tyCString, 
+    tyInt..tyFloat128: 
+      result := true;
+    tyEnum, tyForward, tyObject, tyAbstract:
+      result := (a.id = b.id);
+    tyTuple: 
+      result := sameTuple(a, b, true);
+    tyGenericInst:
+      result := equalOrAbstractOf(lastSon(a), lastSon(b));
+    tyGenericParam, tyGeneric, tySequence, tyOrdinal,
+    tyOpenArray, tySet, tyRef, tyPtr, tyVar, tyArrayConstr,
+    tyArray, tyProc: begin
+      if sonsLen(a) = sonsLen(b) then begin
+        result := true;
+        for i := 0 to sonsLen(a)-1 do begin
+          result := equalOrAbstractOf(a.sons[i], b.sons[i]);
+          if not result then exit
+        end;
+        if result and (a.kind = tyProc) then 
+          result := a.callConv = b.callConv
+      end
+      else
+        result := false;
+    end;
+    tyRange: begin
+      result := equalOrAbstractOf(a.sons[0], b.sons[0])
+        and SameValue(a.n.sons[0], b.n.sons[0])
+        and SameValue(a.n.sons[1], b.n.sons[1])
+    end;
+    tyNone: result := false;
   end
 end;
 
@@ -963,9 +1038,9 @@ begin
   // if we have already checked the type, return true, because we stop the
   // evaluation if something is wrong:
   if IntSetContainsOrIncl(marker, t.id) then exit;
-  case skipGeneric(t).kind of 
+  case skipTypes(t, abstractInst).kind of 
     tyVar: begin
-      case skipGeneric(t.sons[0]).kind of
+      case skipTypes(t.sons[0], abstractInst).kind of
         tyVar: result := false; // ``var var`` is always an invalid type:
         tyOpenArray: result := (kind = skParam) and 
                                 typeAllowedAux(marker, t.sons[0], kind);
@@ -985,9 +1060,11 @@ begin
     tyEmpty, tyNil: result := kind = skConst;
     tyString, tyBool, tyChar, tyEnum, tyInt..tyFloat128, tyCString, tyPointer: 
       result := true;
-    tyAnyEnum: result := kind = skParam;
-    tyGenericInst: result := typeAllowedAux(marker, lastSon(t), kind);
-    tyRange: result := skipGeneric(t.sons[0]).kind in 
+    tyOrdinal: result := kind = skParam;
+    tyGenericInst, tyAbstract: 
+      result := typeAllowedAux(marker, lastSon(t), kind);
+    tyRange: 
+      result := skipTypes(t.sons[0], abstractInst).kind in
                          [tyChar, tyEnum, tyInt..tyFloat128];
     tyOpenArray: 
       result := (kind = skParam) and typeAllowedAux(marker, t.sons[0], skVar);
@@ -1166,7 +1243,7 @@ begin
       if a < maxAlign then a := maxAlign;
       result := align(result, a);
     end;
-    tyGenericInst: begin
+    tyGenericInst, tyAbstract: begin
       result := computeSizeAux(lastSon(typ), a);
     end;
     else begin
diff --git a/nim/wordrecg.pas b/nim/wordrecg.pas
index 7957d354b..cd31a64e4 100644
--- a/nim/wordrecg.pas
+++ b/nim/wordrecg.pas
@@ -39,20 +39,20 @@ type
     //  i = i + 1
     //cog.out(idents)
     //]]]
-    wAddr, wAnd, wAs, wAsm, 
-    wBlock, wBreak, wCase, wCast, 
-    wConst, wContinue, wConverter, wDiscard, 
-    wDiv, wElif, wElse, wEnd, 
-    wEnum, wExcept, wException, wFinally, 
-    wFor, wFrom, wGeneric, wIf, 
-    wImplies, wImport, wIn, wInclude, 
-    wIs, wIsnot, wIterator, wLambda, 
-    wMacro, wMethod, wMod, wNil, 
-    wNot, wNotin, wObject, wOf, 
-    wOr, wOut, wProc, wPtr, 
-    wRaise, wRef, wReturn, wShl, 
-    wShr, wTemplate, wTry, wTuple, 
-    wType, wVar, wWhen, wWhere, 
+    wAbstract, wAddr, wAnd, wAs, 
+    wAsm, wBlock, wBreak, wCase, 
+    wCast, wConst, wContinue, wConverter, 
+    wDiscard, wDiv, wElif, wElse, 
+    wEnd, wEnum, wExcept, wException, 
+    wFinally, wFor, wFrom, wGeneric, 
+    wIf, wImplies, wImport, wIn, 
+    wInclude, wIs, wIsnot, wIterator, 
+    wLambda, wMacro, wMethod, wMod, 
+    wNil, wNot, wNotin, wObject, 
+    wOf, wOr, wOut, wProc, 
+    wPtr, wRaise, wRef, wReturn, 
+    wShl, wShr, wTemplate, wTry, 
+    wTuple, wType, wVar, wWhen, 
     wWhile, wWith, wWithout, wXor, 
     wYield, 
     //[[[end]]]
@@ -78,7 +78,7 @@ type
     wApp, wConsole, wGui, wPassc, wT, wPassl,
     wL, wListcmd, wGendoc, wGenmapping,
     wOs, wCpu, wGenerate, wG, wC, wCpp,
-    wYaml, wRun, wR, wVerbosity, wV, wHelp,
+    wBorrow, wRun, wR, wVerbosity, wV, wHelp,
     wH, wSymbolFiles, wFieldChecks, wX, wVersion, wAdvanced,
     wSkipcfg, wSkipProjCfg, wCc, wGenscript, wCheckPoint, wCheckPoints,
     wMaxErr, wExpr, wStmt, wTypeDesc,
@@ -113,20 +113,20 @@ const
     //[[[cog
     //cog.out(strings)
     //]]]
-    'addr', 'and', 'as', 'asm', 
-    'block', 'break', 'case', 'cast', 
-    'const', 'continue', 'converter', 'discard', 
-    'div', 'elif', 'else', 'end', 
-    'enum', 'except', 'exception', 'finally', 
-    'for', 'from', 'generic', 'if', 
-    'implies', 'import', 'in', 'include', 
-    'is', 'isnot', 'iterator', 'lambda', 
-    'macro', 'method', 'mod', 'nil', 
-    'not', 'notin', 'object', 'of', 
-    'or', 'out', 'proc', 'ptr', 
-    'raise', 'ref', 'return', 'shl', 
-    'shr', 'template', 'try', 'tuple', 
-    'type', 'var', 'when', 'where', 
+    'abstract', 'addr', 'and', 'as', 
+    'asm', 'block', 'break', 'case', 
+    'cast', 'const', 'continue', 'converter', 
+    'discard', 'div', 'elif', 'else', 
+    'end', 'enum', 'except', 'exception', 
+    'finally', 'for', 'from', 'generic', 
+    'if', 'implies', 'import', 'in', 
+    'include', 'is', 'isnot', 'iterator', 
+    'lambda', 'macro', 'method', 'mod', 
+    'nil', 'not', 'notin', 'object', 
+    'of', 'or', 'out', 'proc', 
+    'ptr', 'raise', 'ref', 'return', 
+    'shl', 'shr', 'template', 'try', 
+    'tuple', 'type', 'var', 'when', 
     'while', 'with', 'without', 'xor', 
     'yield', 
     //[[[end]]]
@@ -152,7 +152,7 @@ const
     'app', 'console', 'gui', 'passc', 't'+'', 'passl',
     'l'+'', 'listcmd', 'gendoc', 'genmapping',
     'os', 'cpu', 'generate', 'g'+'', 'c'+'', 'cpp',
-    'yaml', 'run', 'r'+'', 'verbosity', 'v'+'', 'help',
+    'borrow', 'run', 'r'+'', 'verbosity', 'v'+'', 'help',
     'h'+'', 'symbolfiles', 'fieldchecks', 'x'+'', 'version', 'advanced',
     'skipcfg', 'skipprojcfg', 'cc', 'genscript', 'checkpoint', 'checkpoints',
     'maxerr', 'expr', 'stmt', 'typedesc',
diff --git a/rod/nimrod.dot b/rod/nimrod.dot
index 8f77bb60d..920944897 100644
--- a/rod/nimrod.dot
+++ b/rod/nimrod.dot
@@ -2,14 +2,16 @@ digraph nimrod {
 times -> strutils;
 os -> strutils;
 os -> times;
-hashes -> strutils;
-strtabs -> os;
-strtabs -> hashes;
-strtabs -> strutils;
+posix -> times;
+os -> posix;
+nhashes -> strutils;
+nstrtabs -> os;
+nstrtabs -> nhashes;
+nstrtabs -> strutils;
 options -> os;
 options -> lists;
 options -> strutils;
-options -> strtabs;
+options -> nstrtabs;
 msgs -> options;
 msgs -> strutils;
 msgs -> os;
@@ -19,12 +21,12 @@ platform -> strutils;
 ropes -> msgs;
 ropes -> strutils;
 ropes -> platform;
-ropes -> hashes;
+ropes -> nhashes;
 ropes -> crc;
-idents -> hashes;
+idents -> nhashes;
 idents -> strutils;
 ast -> msgs;
-ast -> hashes;
+ast -> nhashes;
 ast -> nversion;
 ast -> options;
 ast -> strutils;
@@ -33,7 +35,7 @@ ast -> ropes;
 ast -> idents;
 ast -> lists;
 astalgo -> ast;
-astalgo -> hashes;
+astalgo -> nhashes;
 astalgo -> strutils;
 astalgo -> options;
 astalgo -> msgs;
@@ -42,19 +44,28 @@ astalgo -> idents;
 condsyms -> ast;
 condsyms -> astalgo;
 condsyms -> msgs;
-condsyms -> hashes;
+condsyms -> nhashes;
 condsyms -> platform;
 condsyms -> strutils;
 condsyms -> idents;
+hashes -> strutils;
+strtabs -> os;
+strtabs -> hashes;
+strtabs -> strutils;
+osproc -> os;
+osproc -> strtabs;
+osproc -> streams;
+osproc -> posix;
 extccomp -> lists;
 extccomp -> ropes;
 extccomp -> os;
 extccomp -> strutils;
+extccomp -> osproc;
 extccomp -> platform;
 extccomp -> condsyms;
 extccomp -> options;
 extccomp -> msgs;
-wordrecg -> hashes;
+wordrecg -> nhashes;
 wordrecg -> strutils;
 wordrecg -> idents;
 commands -> os;
@@ -70,7 +81,7 @@ commands -> wordrecg;
 llstream -> strutils;
 lexbase -> llstream;
 lexbase -> strutils;
-scanner -> hashes;
+scanner -> nhashes;
 scanner -> options;
 scanner -> msgs;
 scanner -> strutils;
@@ -97,7 +108,6 @@ pnimsyn -> idents;
 pnimsyn -> strutils;
 pnimsyn -> ast;
 pnimsyn -> msgs;
-rnimsyn -> lexbase;
 rnimsyn -> scanner;
 rnimsyn -> options;
 rnimsyn -> idents;
@@ -105,7 +115,7 @@ rnimsyn -> strutils;
 rnimsyn -> ast;
 rnimsyn -> msgs;
 rnimsyn -> lists;
-paslex -> hashes;
+paslex -> nhashes;
 paslex -> options;
 paslex -> msgs;
 paslex -> strutils;
@@ -150,7 +160,7 @@ types -> strutils;
 types -> platform;
 magicsys -> ast;
 magicsys -> astalgo;
-magicsys -> hashes;
+magicsys -> nhashes;
 magicsys -> msgs;
 magicsys -> platform;
 magicsys -> nversion;
@@ -187,7 +197,7 @@ passes -> nimsets;
 passes -> pnimsyn;
 passes -> times;
 passes -> rodread;
-treetab -> hashes;
+treetab -> nhashes;
 treetab -> ast;
 treetab -> astalgo;
 treetab -> types;
@@ -344,10 +354,10 @@ rst -> os;
 rst -> msgs;
 rst -> strutils;
 rst -> platform;
-rst -> hashes;
+rst -> nhashes;
 rst -> ropes;
 rst -> options;
-highlite -> hashes;
+highlite -> nhashes;
 highlite -> options;
 highlite -> msgs;
 highlite -> strutils;
@@ -359,7 +369,7 @@ highlite -> scanner;
 docgen -> ast;
 docgen -> astalgo;
 docgen -> strutils;
-docgen -> hashes;
+docgen -> nhashes;
 docgen -> options;
 docgen -> nversion;
 docgen -> msgs;
@@ -378,14 +388,14 @@ ccgutils -> ast;
 ccgutils -> astalgo;
 ccgutils -> ropes;
 ccgutils -> lists;
-ccgutils -> hashes;
+ccgutils -> nhashes;
 ccgutils -> strutils;
 ccgutils -> types;
 ccgutils -> msgs;
 cgen -> ast;
 cgen -> astalgo;
 cgen -> strutils;
-cgen -> hashes;
+cgen -> nhashes;
 cgen -> trees;
 cgen -> platform;
 cgen -> magicsys;
@@ -412,7 +422,7 @@ cgen -> treetab;
 ecmasgen -> ast;
 ecmasgen -> astalgo;
 ecmasgen -> strutils;
-ecmasgen -> hashes;
+ecmasgen -> nhashes;
 ecmasgen -> trees;
 ecmasgen -> platform;
 ecmasgen -> magicsys;
@@ -447,10 +457,11 @@ ptmplsyn -> pnimsyn;
 interact -> llstream;
 interact -> strutils;
 interact -> ropes;
-interact -> strtabs;
+interact -> nstrtabs;
 interact -> msgs;
 passaux -> strutils;
 passaux -> ast;
+passaux -> astalgo;
 passaux -> passes;
 passaux -> msgs;
 passaux -> options;
@@ -477,6 +488,7 @@ transf -> rnimsyn;
 transf -> types;
 transf -> passes;
 transf -> semfold;
+transf -> magicsys;
 main -> llstream;
 main -> strutils;
 main -> ast;
@@ -513,8 +525,10 @@ main -> passaux;
 main -> depends;
 main -> transf;
 main -> evals;
+main -> types;
 parseopt -> os;
 parseopt -> strutils;
+nimrod -> times;
 nimrod -> commands;
 nimrod -> scanner;
 nimrod -> condsyms;
diff --git a/rod/nimrod.ini b/rod/nimrod.ini
index a32c78e57..eaf3aafb2 100644
--- a/rod/nimrod.ini
+++ b/rod/nimrod.ini
@@ -1,8 +1,8 @@
 [Project]
 Name: "Nimrod"
 Version: "$version"
-OS: "linux;macosx;freebsd;netbsd;openbsd;solaris;aix"
-CPU: "i386;amd64;sparc;powerpc"
+OS: "linux;macosx;freebsd;netbsd;openbsd;solaris"
+CPU: "i386;amd64"  # ;sparc;powerpc
 Authors: "Andreas Rumpf"
 Description: """This is the Nimrod Compiler. Nimrod is a new statically typed,
 imperative programming language, that supports procedural, functional, object
@@ -19,20 +19,22 @@ priority)."""
 App: Console
 License: "copying.txt"
 
-[InstallScript]
-[UninstallScript]
+[Config]
+Files: "config/nimdoc.cfg"
+Files: "config/nimrod.cfg"
+
+[Documentation]
+Files: "doc/*.txt"
+Files: "doc/*.html"
+Files: "doc/*.cfg"
 
-[Common]
+[Other]
 Files: "readme.txt;install.txt"
 Files: "configure;makefile"
 Files: "*.html"
 Files: "*.py"
 Files: "*.ini"
 
-Files: "lib/nimbase.h;lib/cycle.h;lib/tlsf.h;lib/target.h;lib/dlmalloc.h"
-Files: "lib/tlsf.c;lib/dlmalloc.c"
-Files: "lib/*.nim"
-
 Files: "rod/readme.txt"
 Files: "rod/nimrod.ini"
 Files: "rod/nimrod.cfg"
@@ -45,13 +47,31 @@ Files: "data/*.txt"
 Files: "obj/*.txt"
 Files: "diff/*.txt"
 
-Files: "config/nimdoc.cfg"
-Files: "config/nimrod.cfg"
+[Lib]
+Files: "lib/nimbase.h;lib/cycle.h"
+Files: "lib/*.nim"
 
-Files: "doc/*.txt"
-Files: "doc/*.html"
-Files: "doc/*.cfg"
+Files: "lib/system/*.nim"
+Files: "lib/pure/*.nim"
+Files: "lib/impure/*.nim"
+Files: "lib/wrappers/*.nim"
+
+Files: "lib/wrappers/cairo/*.nim"
+Files: "lib/wrappers/gtk/*.nim"
+Files: "lib/wrappers/lua/*.nim"
+Files: "lib/wrappers/opengl/*.nim"
+Files: "lib/wrappers/pcre/*.nim"
+Files: "lib/wrappers/pcre/pcre_all.c"
+Files: "lib/wrappers/sdl/*.nim"
+Files: "lib/wrappers/x11/*.nim"
+Files: "lib/wrappers/zip/*.nim"
+Files: "lib/wrappers/zip/libzip_all.c"
+
+Files: "lib/windows/*.nim"
+Files: "lib/posix/*.nim"
+Files: "lib/ecmas/*.nim"
 
+[Other]
 Files: "tests/*.nim"
 Files: "tests/*.html"
 Files: "tests/*.txt"
@@ -65,28 +85,18 @@ Files: "examples/*.txt"
 Files: "examples/*.cfg"
 Files: "examples/*.tmpl"
 
-Files: "lib/base/*.c"
-Files: "lib/base/*.nim"
-Files: "lib/base/gtk/*.nim"
-Files: "lib/base/cairo/*.nim"
-Files: "lib/base/x11/*.nim"
-Files: "lib/base/zip/*.nim"
-Files: "lib/base/zip/libzip_all.c"
-Files: "lib/windows/*.nim"
-Files: "lib/posix/*.nim"
-Files: "lib/ecmas/*.nim"
-Files: "lib/base/sdl/*.nim"
-Files: "lib/base/opengl/*.nim"
-Files: "lib/base/lua/*.nim"
-
 [Windows]
 Files: "bin/nimrod.exe"
-Files: "bin/nimrodd.exe"
 Files: "dist/mingw"
 BinPath: r"bin;dist\mingw\bin"
+InnoSetup: "Yes"
 
-[Unix]
+[UnixBin]
+Files: "bin/nimrod"
 
+[Unix]
+InstallScript: "yes"
+UninstallScript: "yes"
 
 [InnoSetup]
 path = r"c:\programme\innosetup5\iscc.exe"
diff --git a/tests/thallo.nim b/tests/thallo.nim
index f8d3b8a69..86aa89f0a 100644
--- a/tests/thallo.nim
+++ b/tests/thallo.nim
@@ -40,7 +40,7 @@ writeln(stdout, "Hallo", " World", "!")
 
 echo(["a", "b", "c", "d"].len)
 for x in items(["What's", "your", "name", "?", ]):
-  echo(x = x)
+  echo(x)
 var `name` = readLine(stdin)
 {.breakpoint.}
 echo("Hi " & thallo.name & "!\n")
diff --git a/tests/tlibs.nim b/tests/tlibs.nim
index b5c4036a6..9c52621aa 100644
--- a/tests/tlibs.nim
+++ b/tests/tlibs.nim
@@ -12,10 +12,6 @@ import
   cairowin32, cairoxlib,
   odbcsql,
   gl, glut, glu, glx, glext, wingl,
-  zlib
-
-import "lib/base/lua/lua"
-import "lib/base/lua/lualib"
-import "lib/base/lua/lauxlib"
+  zlib, lua, lualib, lauxlib, mysql, sqlite3, python, tcl
 
 writeln(stdout, "test compilation of binding modules")
diff --git a/tests/ttempl3.nim b/tests/ttempl3.nim
index 4ae3e16d2..39262497c 100644
--- a/tests/ttempl3.nim
+++ b/tests/ttempl3.nim
@@ -13,3 +13,13 @@ template withOpenFile(f, filename, mode: expr, actions: stmt): stmt =
 withOpenFile(txt, "ttempl3.txt", fmWrite):
   writeln(txt, "line 1")
   txt.writeln("line 2")
+  
+# Test zero argument template: 
+template ha: expr = myVar[0]
+  
+var
+  myVar: array[0..1, int]
+  
+ha = 1  
+echo(ha)
+
diff --git a/tools/inno.tmpl b/tools/inno.tmpl
index e2d31eb80..3cfc04f2d 100644
--- a/tools/inno.tmpl
+++ b/tools/inno.tmpl
@@ -17,12 +17,11 @@ ChangesEnvironment=yes
 [Languages]
 Name: english; MessagesFile: compiler:Default.isl
 
-[Files]
-  #for f in items(c.commonFiles):
-Source: ${expandFilename(f)}; DestDir: {app}\${extractDir(f)}; Flags: ignoreversion
-  #end for
-  #for f in items(c.windowsFiles):
+[Files] 
+  #for i in low(TFileCategory)..fcWindows:
+  #  for f in items(c.cat[i]):
 Source: ${expandFilename(f)}; DestDir: {app}\${extractDir(f)}; Flags: ignoreversion
+  #  end for
   #end for
 
 [Icons]
diff --git a/tools/install.tmpl b/tools/install.tmpl
index c98cbc8d5..ffefc8281 100644
--- a/tools/install.tmpl
+++ b/tools/install.tmpl
@@ -1,97 +1,105 @@
 #subsChar ?
 #proc GenerateInstallScript(c: TConfigData): string = 
 #  result = "#! /bin/sh\n# Generated by niminst\n"
-CC="gcc"
-LINKER="gcc"
-COMP_FLAGS="-w"
-LINK_FLAGS=""
-#  add(result, "# platform detection\n")
-ucpu=`uname -m`
-uos=`uname`
+#  var proj = c.name.toLower
 
-#  add(result, "# convert to lower case:\n")
-upcu=`echo $ucpu | tr "[:upper:]" "[:lower:]"`
-uos=`echo $uos | tr "[:upper:]" "[:lower:]"`
-
-case $uos in
-  *linux* ) 
-    myos="linux" 
-    LINK_FLAGS="$LINK_FLAGS -ldl -lm"
-    ;;
-  *freebsd* ) 
-    myos="freebsd"
-    LINK_FLAGS="$LINK_FLAGS -lm"
-    ;;
-  *openbsd* )
-    myos="openbsd" 
-    LINK_FLAGS="$LINK_FLAGS -lm"
-    ;;
-  *netbsd* )
-    myos="netbsd"
-    LINK_FLAGS="$LINK_FLAGS -lm"
-    ;;
-  *darwin* ) 
-    myos="macosx"
-    LINK_FLAGS="$LINK_FLAGS -ldl -lm"
-    ;;
-  *aix* )
-    myos="aix"
-    LINK_FLAGS="$LINK_FLAGS -ldl -lm"    
-    ;;
-  *solaris* | *sun* ) 
-    myos="solaris"
-    LINK_FLAGS="$LINK_FLAGS -ldl -lm"
-    ;;
-  *) 
-    echo "Error: unknown operating system: $uos"
-    exit 1
-    ;;
-esac
-
-case $ucpu in
-  *i386* | *i486* | *i586* | *i686* ) 
-    mycpu="i386" ;;
-  *amd*64* | *x86-64* | *x86_64* ) 
-    mycpu="amd64" ;;
-  *sparc*|*sun* ) 
-    mycpu="sparc" ;;
-  *power* ) 
-    mycpu="powerpc" ;;
-  *mips* ) 
-    mycpu="mips" ;;
-  *) 
-    echo "Error: unknown processor: $ucpu"
+if [ $# -eq 1 ] ; then
+# if c.cat[fcUnixBin].len > 0:
+  if test -f ?{c.cat[fcUnixBin][0]}
+  then 
+    echo "?c.name build detected"
+  else
+    echo "Please build ?c.name before installing it"
     exit 1
-    ;;
-esac
-
-#  add(result, "# write ``build/platdef.c`` file\n")
-cat >build/platdef.c <<EOF
-char* nimOS(void) { return "$myos"; }
-char* nimCPU(void) { return "$mycpu"; }
-EOF
-#  add(result, "# call the compiler:\n")
-
-case $myos in
-#  for osA in 1..c.oses.len:
-?{c.oses[osA-1]}) 
-  case $mycpu in
-#    for cpuA in 1..c.cpus.len:
-  ?{c.cpus[cpuA-1]})
-#      var linkCmd = "build/platdef.o"
-#      for f in items(c.cfiles[osA][cpuA]):
-    echo "$CC $COMP_FLAGS -Ibuild -c ?{f} -o ?{changeFileExt(f, "o")}"
-    $CC $COMP_FLAGS -Ibuild -c ?{f} -o ?{changeFileExt(f, "o")} || exit 1
-#        add(linkCmd, " \\\n" & changeFileExt(f, "o"))
-#      end for    
-    $CC $COMP_FLAGS -Ibuild -c build/platdef.c -o build/platdef.o || exit 1
-    echo "$LINKER $LINK_FLAGS -o ?{c.binPaths[0]}/?{toLower(c.name)} ?linkCmd"
-    $LINKER $LINK_FLAGS -o ?{c.binPaths[0]}/?{toLower(c.name)} ?linkCmd || exit 1
-    ;;
-#    end for
+  fi
+#  end if
+  case $1 in
+    "--help"|"-h"|"help"|"h")
+      echo "?c.name installation script"
+      echo "Usage: [sudo] sh install.sh DIR"
+      echo "Where DIR may be:"
+      echo "  /usr/bin"
+      echo "  /usr/local/bin"
+      echo "  /opt"
+      echo "  <some other dir> (treated like '/opt')"
+      echo "To deinstall, use the command:"
+      echo "sh deinstall.sh DIR"
+      exit 1
+      ;;
+    "/usr/bin")
+      bindir=/usr/bin
+      configdir=/etc
+      libdir=/usr/lib/?proj
+      docdir=/usr/share/?proj/doc
+      datadir=/usr/share/?proj/data
+      ;;
+    "/usr/local/bin")
+      bindir=/usr/local/bin
+      configdir=/etc
+      libdir=/usr/local/lib/?proj
+      docdir=/usr/local/share/?proj/doc
+      datadir=/usr/local/share/?proj/data
+      ;;
+    *)
+      bindir="$1/?proj/bin"
+      configdir="$1/?proj/config"
+      libdir="$1/?proj/lib"
+      docdir="$1/?proj/doc"
+      datadir="$1/?proj/data"
+      
+      mkdir -p $1/?proj
+      mkdir -p $bindir
+      mkdir -p $configdir
+      ;;
   esac
-  ;;
+  mkdir -p $libdir
+  mkdir -p $docdir
+  echo "copying files..."
+#var createdDirs = newStringTable()
+#for cat in fcConfig..fcLib:
+#  for f in items(c.cat[cat]):
+#    var mk = extractDir(f.skipRoot)
+#    if mk.len > 0:
+#      mk = unixDirVars[cat] & "/" & mk
+#      if not createdDirs.hasKey(mk):
+#        createdDirs[mk] = "true"
+  mkdir -p ?mk
+#      end if
+#    end if
 #  end for
-esac
+#end for
 
-echo "SUCCESS"
+#for f in items(c.cat[fcUnixBin]):
+  cp ?f $bindir/?f.skipRoot
+  chmod 755 $bindir/?f.skipRoot
+#end for
+#for f in items(c.cat[fcConfig]): 
+  cp ?f $configdir/?f.skipRoot
+  chmod 644 $configdir/?f.skipRoot
+#end for
+#for f in items(c.cat[fcData]): 
+  cp ?f $datadir/?f.skipRoot
+  chmod 644 $datadir/?f.skipRoot
+#end for
+#for f in items(c.cat[fcDoc]): 
+  cp ?f $docdir/?f.skipRoot
+  chmod 644 $docdir/?f.skipRoot
+#end for
+#for f in items(c.cat[fcLib]): 
+  cp ?f $libdir/?f.skipRoot
+  chmod 644 $libdir/?f.skipRoot
+#end for
+  
+  echo "installation successful"
+else
+  echo "?c.name installation script"
+  echo "Usage: [sudo] sh install.sh DIR"
+  echo "Where DIR may be:"
+  echo "  /usr/bin"
+  echo "  /usr/local/bin"
+  echo "  /opt"
+  echo "  <some other dir> (treated like '/opt')"
+  echo "To deinstall, use the command:"
+  echo "sh deinstall.sh DIR"
+  exit 1
+fi
diff --git a/tools/niminst.nim b/tools/niminst.nim
index 2b05e2e68..94ae1b041 100644
--- a/tools/niminst.nim
+++ b/tools/niminst.nim
@@ -1,7 +1,7 @@
 #
 #
 #        The Nimrod Installation Generator
-#        (c) Copyright 2008 Andreas Rumpf
+#        (c) Copyright 2009 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -20,6 +20,8 @@ const
   maxOS = 20 # max number of OSes
   maxCPU = 10 # max number of CPUs
   buildShFile = "build.sh"
+  installShFile = "install.sh"
+  deinstallShFile = "deinstall.sh"
 
 type
   TAppType = enum appConsole, appGUI
@@ -28,10 +30,22 @@ type
     actionCSource # action: create C sources
     actionInno,   # action: create Inno Setup installer
     actionZip     # action: create zip file
+    
+  TFileCategory = enum
+    fcWinBin,     # binaries for Windows
+    fcConfig,     # configuration files
+    fcData,       # data files
+    fcDoc,        # documentation files
+    fcLib,        # library files
+    fcOther,      # other files; will not be copied on UNIX
+    fcWindows,    # files only for Windows
+    fcUnix,       # files only for Unix; must be after ``fcWindows``
+    fcUnixBin     # binaries for Unix
+
   TConfigData = object of TObject
     actions: set[TAction]
-    commonFiles, windowsFiles, unixFiles, binPaths, authors,
-      oses, cpus: seq[string]
+    cat: array[TFileCategory, seq[string]]
+    binPaths, authors, oses, cpus: seq[string]
     cfiles: array[1..maxOS, array[1..maxCPU, seq[string]]]
     ccompiler, innosetup: tuple[path, flags: string]
     name, version, description, license, infile, outdir: string
@@ -40,11 +54,14 @@ type
     app: TAppType
     nimrodArgs: string
 
+const
+  unixDirVars: array[fcConfig..fcLib, string] = [
+    "$configdir", "$datadir", "$docdir", "$libdir"
+  ]
+
 proc initConfigData(c: var TConfigData) =
   c.actions = {}
-  c.commonFiles = @[]
-  c.windowsFiles = @[]
-  c.unixFiles = @[]
+  for i in low(TFileCategory)..high(TFileCategory): c.cat[i] = @[]
   c.binPaths = @[]
   c.authors = @[]
   c.oses = @[]
@@ -63,16 +80,26 @@ proc initConfigData(c: var TConfigData) =
   c.uninstallScript = false
   c.vars = newStringTable(modeStyleInsensitive)
 
+proc skipRoot(f: string): string = 
+  var i = 0
+  result = ""
+  for component in split(f, {dirsep, altsep}): 
+    if i > 0: result = result / component
+    inc i
+  if result.len == 0: result = f
+
 include "inno.tmpl"
+include "build.tmpl"
 include "install.tmpl"
+include "deinstall.tmpl"
 
 # ------------------------- configuration file -------------------------------
 
 const
-  Version = "0.5"
+  Version = "0.6"
   Usage = "niminst - Nimrod Installation Generator Version " & version & """
 
-  (c) 2008 Andreas Rumpf
+  (c) 2009 Andreas Rumpf
 Usage:
   niminst [options] command[;command2...] ini-file[.ini] [compile_options]
 Command:
@@ -146,6 +173,19 @@ proc pathFlags(p: var TCfgParser, k, v: string,
   of "flags": t.flags = v
   else: quit(errorStr(p, "unknown variable: " & k))
 
+proc filesOnly(p: var TCfgParser, k, v: string, dest: var seq[string]) =
+  case normalize(k)
+  of "files": addFiles(dest, splitSeq(v, {';'}))
+  else: quit(errorStr(p, "unknown variable: " & k))
+
+proc yesno(p: var TCfgParser, v: string): bool = 
+  case normalize(v)
+  of "yes", "y", "on", "true": 
+    result = true
+  of "no", "n", "off", "false":
+    result = false
+  else: quit(errorStr(p, "unknown value; use: yes|no"))
+
 proc parseIniFile(c: var TConfigData) =
   var
     p: TCfgParser
@@ -159,13 +199,6 @@ proc parseIniFile(c: var TConfigData) =
       of cfgEof: break
       of cfgSectionStart:
         section = normalize(k.section)
-        case section
-        of "innosetup": c.innoSetupFlag = true
-        of "installscript": c.installScript = true
-        of "uninstallscript": c.uninstallScript = true
-        of "var", "project", "common", "ccompiler", "windows", "unix", "7z": nil
-        else: nil # quit(errorStr(p, "invalid section: " & section))
-
       of cfgKeyValuePair:
         var v = k.value % c.vars
         c.vars[k.key] = v
@@ -187,24 +220,28 @@ proc parseIniFile(c: var TConfigData) =
           of "license": c.license = UnixToNativePath(k.value)
           else: quit(errorStr(p, "unknown variable: " & k.key))
         of "var": nil
-        of "installscript", "uninstallscript":
-          quit(errorStr(p, "unknown variable: " & k.key))
-        of "common":
-          case normalize(k.key)
-          of "files": addFiles(c.commonFiles, splitSeq(v, {';'}))
-          else: quit(errorStr(p, "unknown variable: " & k.key))
-        of "innosetup": pathFlags(p, k.key, v, c.innoSetup)
-        of "ccompiler": pathFlags(p, k.key, v, c.ccompiler)
+        of "winbin": filesOnly(p, k.key, v, c.cat[fcWinBin])
+        of "config": filesOnly(p, k.key, v, c.cat[fcConfig])
+        of "data": filesOnly(p, k.key, v, c.cat[fcData])
+        of "documentation": filesOnly(p, k.key, v, c.cat[fcDoc])
+        of "lib": filesOnly(p, k.key, v, c.cat[fcLib])
+        of "other": filesOnly(p, k.key, v, c.cat[fcOther])
         of "windows":
           case normalize(k.key)
-          of "files": addFiles(c.windowsFiles, splitSeq(v, {';'}))
+          of "files": addFiles(c.cat[fcWindows], splitSeq(v, {';'}))
           of "binpath": c.binPaths = splitSeq(v, {';'})
+          of "innosetup": c.innoSetupFlag = yesno(p, v)
           else: quit(errorStr(p, "unknown variable: " & k.key))
-        of "unix":
+        of "unix": 
           case normalize(k.key)
-          of "files": addFiles(c.unixFiles, splitSeq(v, {';'}))
+          of "files": addFiles(c.cat[fcUnix], splitSeq(v, {';'}))
+          of "installscript": c.installScript = yesno(p, v)
+          of "uninstallscript": c.uninstallScript = yesno(p, v)
           else: quit(errorStr(p, "unknown variable: " & k.key))
-        else: nil
+        of "unixbin": filesOnly(p, k.key, v, c.cat[fcUnixBin])
+        of "innosetup": pathFlags(p, k.key, v, c.innoSetup)
+        of "ccompiler": pathFlags(p, k.key, v, c.ccompiler)
+        else: quit(errorStr(p, "invalid section: " & section))
 
       of cfgOption: quit(errorStr(p, "syntax error"))
       of cfgError: quit(errorStr(p, k.msg))
@@ -242,15 +279,24 @@ proc readCFiles(c: var TConfigData, osA, cpuA: int) =
 proc buildDir(os, cpu: int): string =
   return "build" / ($os & "_" & $cpu)
 
+proc writeFile(filename, content: string) =  
+  var f: TFile
+  if openFile(f, filename, fmWrite):
+    writeln(f, content)
+    closeFile(f)
+  else:
+    quit("Cannot open for writing: " & filename)
+
 proc srcdist(c: var TConfigData) =
   for x in walkFiles("lib/*.h"): CopyFile("build" / extractFilename(x), x)
   for osA in 1..c.oses.len:
     for cpuA in 1..c.cpus.len:
       var dir = buildDir(osA, cpuA)
+      if existsDir(dir): removeDir(dir)
       createDir(dir)
       var cmd = ("nimrod compile -f --symbolfiles:off --compileonly " &
-                 "--gen_mapping $1 " &
-                 " --os:$2 --cpu:$3 $4") %
+                 "--gen_mapping " &
+                 " --os:$2 --cpu:$3 $1 $4") %
                  [c.nimrodArgs, c.oses[osA-1], c.cpus[cpuA-1],
                  changeFileExt(c.infile, "nim")]
       echo("Executing: " & cmd)
@@ -276,39 +322,33 @@ proc srcdist(c: var TConfigData) =
                 # file is identical, so delete duplicate:
                 RemoveFile(dup)
                 c.cfiles[osA][cpuA][i] = orig
-  var scrpt = GenerateInstallScript(c)
-  var f: TFile
-  if openFile(f, buildShFile, fmWrite):
-    writeln(f, scrpt)
-    closeFile(f)
-  else:
-    quit("Cannot open for writing: " & buildShFile)
-
+  writeFile(buildShFile, GenerateBuildScript(c))
+  
 # --------------------- generate inno setup -----------------------------------
 proc setupDist(c: var TConfigData) =
   var scrpt = GenerateInnoSetup(c)
-  var f: TFile
   var n = "build" / "install_$1_$2.iss" % [toLower(c.name), c.version]
-  if openFile(f, n, fmWrite):
-    writeln(f, scrpt)
-    closeFile(f)
-    when defined(windows):
-      if c.innoSetup.path.len == 0:
-        c.innoSetup.path = "iscc.exe"
-      var outcmd = if c.outdir.len == 0: "build" else: c.outdir
-      var cmd = "$1 $2 /O$3 $4" % [c.innoSetup.path, c.innoSetup.flags,
-                                   outcmd, n]
-      Echo("Executing: " & cmd)
-      if executeShellCommand(cmd) == 0:
-        removeFile(n)
-      else:
-        quit("External program failed")
-  else:
-    quit("Cannot open for writing: " & n)
+  writeFile(n, scrpt)
+  when defined(windows):
+    if c.innoSetup.path.len == 0:
+      c.innoSetup.path = "iscc.exe"
+    var outcmd = if c.outdir.len == 0: "build" else: c.outdir
+    var cmd = "$1 $2 /O$3 $4" % [c.innoSetup.path, c.innoSetup.flags,
+                                 outcmd, n]
+    Echo("Executing: " & cmd)
+    if executeShellCommand(cmd) == 0:
+      removeFile(n)
+    else:
+      quit("External program failed")
 
 # ------------------ generate ZIP file ---------------------------------------
 when haveZipLib:
   proc zipDist(c: var TConfigData) =
+    if c.installScript: 
+      writeFile(installShFile, GenerateInstallScript(c))
+    if c.uninstallScript:
+      writeFile(deinstallShFile, GenerateDeinstallScript(c))
+    
     var proj = toLower(c.name)
     var n = "$1_$2.zip" % [proj, c.version]
     if c.outdir.len == 0: n = "build" / n
@@ -316,6 +356,8 @@ when haveZipLib:
     var z: TZipArchive
     if open(z, n, fmWrite):
       addFile(z, proj / buildShFile, buildShFile)
+      addFile(z, proj / installShFile, installShFile)
+      addFile(z, proj / deinstallShFile, deinstallShFile)
       for f in walkFiles("lib/*.h"):
         addFile(z, proj / "build" / extractFilename(f), f)
       for osA in 1..c.oses.len:
@@ -323,8 +365,9 @@ when haveZipLib:
           var dir = buildDir(osA, cpuA)
           for k, f in walkDir(dir):
             if k == pcFile: addFile(z, proj / dir / extractFilename(f), f)
-      for f in items(c.commonFiles): addFile(z, proj / f, f)
-      for f in items(c.unixFiles): addFile(z, proj / f, f)
+
+      for cat in items({fcConfig..fcOther, fcUnix}): 
+        for f in items(c.cat[cat]): addFile(z, proj / f, f)
       close(z)
     else:
       quit("Cannot open for writing: " & n)