diff options
author | Andreas Rumpf <rumpf_a@web.de> | 2009-06-08 08:06:25 +0200 |
---|---|---|
committer | Andreas Rumpf <rumpf_a@web.de> | 2009-06-08 08:06:25 +0200 |
commit | 4d4b3b1c04d41868ebb58bd9ccba7b303007e900 (patch) | |
tree | 909ed0aad0b145733521f4ac2bfb938dd4b43785 | |
parent | ce88dc3e67436939b03f97e624c11ca6058fedce (diff) | |
download | Nim-4d4b3b1c04d41868ebb58bd9ccba7b303007e900.tar.gz |
version0.7.10
-rw-r--r-- | .bzrignore | 3 | ||||
-rw-r--r-- | config/nimdoc.cfg | 567 | ||||
-rw-r--r-- | config/nimrod.cfg | 21 | ||||
-rw-r--r-- | data/ast.yml | 9 | ||||
-rw-r--r-- | data/keywords.txt | 4 | ||||
-rw-r--r-- | data/magic.yml | 4 | ||||
-rw-r--r-- | data/messages.yml | 5 | ||||
-rw-r--r-- | doc/grammar.txt | 2 | ||||
-rw-r--r-- | doc/lib.txt | 13 | ||||
-rw-r--r-- | doc/manual.txt | 2 | ||||
-rw-r--r-- | doc/theindex.txt | 722 | ||||
-rw-r--r-- | doc/tut2.txt | 2 | ||||
-rw-r--r-- | install.txt | 4 | ||||
-rw-r--r-- | koch.py | 24 | ||||
-rw-r--r-- | lib/amd64.asm.in | 38 | ||||
-rw-r--r-- | lib/atomic.h | 2716 | ||||
-rw-r--r-- | lib/base/x11/keysym.nim | 1900 | ||||
-rw-r--r-- | lib/contnrs.nim | 11 | ||||
-rw-r--r-- | lib/dlmalloc.c | 5076 | ||||
-rw-r--r-- | lib/dlmalloc.h | 1143 | ||||
-rw-r--r-- | lib/generics.nim | 169 | ||||
-rw-r--r-- | lib/i386.asm.in | 70 | ||||
-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.nim | 71 | ||||
-rw-r--r-- | lib/locks.nim | 18 | ||||
-rw-r--r-- | lib/posix/detect.nim | 824 | ||||
-rw-r--r-- | lib/posix/linux_amd64_consts.nim | 620 | ||||
-rw-r--r-- | lib/posix/linux_consts.nim | 620 | ||||
-rw-r--r-- | lib/posix/posix.nim | 59 | ||||
-rw-r--r-- | lib/powerpc.asm.in | 35 | ||||
-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.nim | 84 | ||||
-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.nim | 245 | ||||
-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.nim | 1333 | ||||
-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.nim | 57 | ||||
-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.h | 12 | ||||
-rw-r--r-- | lib/tlsf.c | 1005 | ||||
-rw-r--r-- | lib/tlsf.h | 39 | ||||
-rw-r--r-- | lib/tlsfnim.nim | 698 | ||||
-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.nim | 1581 | ||||
-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.nim | 855 | ||||
-rw-r--r-- | lib/wrappers/x11/cursorfont.nim (renamed from lib/base/x11/cursorfont.nim) | 0 | ||||
-rw-r--r-- | lib/wrappers/x11/keysym.nim | 1925 | ||||
-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.pas | 154 | ||||
-rw-r--r-- | nim/ccgexprs.pas | 161 | ||||
-rw-r--r-- | nim/ccgstmts.pas | 6 | ||||
-rw-r--r-- | nim/ccgtypes.pas | 20 | ||||
-rw-r--r-- | nim/ccgutils.pas | 9 | ||||
-rw-r--r-- | nim/cgen.pas | 70 | ||||
-rw-r--r-- | nim/commands.pas | 3 | ||||
-rw-r--r-- | nim/condsyms.pas | 3 | ||||
-rw-r--r-- | nim/docgen.pas | 10 | ||||
-rw-r--r-- | nim/ecmasgen.pas | 43 | ||||
-rw-r--r-- | nim/evals.pas | 53 | ||||
-rw-r--r-- | nim/extccomp.pas | 6 | ||||
-rw-r--r-- | nim/magicsys.pas | 1 | ||||
-rw-r--r-- | nim/msgs.pas | 1102 | ||||
-rw-r--r-- | nim/nimconf.pas | 13 | ||||
-rw-r--r-- | nim/nversion.pas | 4 | ||||
-rw-r--r-- | nim/parsecfg.pas | 9 | ||||
-rw-r--r-- | nim/paslex.pas | 10 | ||||
-rw-r--r-- | nim/pnimsyn.pas | 11 | ||||
-rw-r--r-- | nim/pragmas.pas | 9 | ||||
-rw-r--r-- | nim/procfind.pas | 48 | ||||
-rw-r--r-- | nim/rnimsyn.pas | 7 | ||||
-rw-r--r-- | nim/rst.pas | 2 | ||||
-rw-r--r-- | nim/scanner.pas | 60 | ||||
-rw-r--r-- | nim/sem.pas | 4 | ||||
-rw-r--r-- | nim/semexprs.pas | 126 | ||||
-rw-r--r-- | nim/semfold.pas | 25 | ||||
-rw-r--r-- | nim/semstmts.pas | 36 | ||||
-rw-r--r-- | nim/semtypes.pas | 35 | ||||
-rw-r--r-- | nim/sigmatch.pas | 42 | ||||
-rw-r--r-- | nim/transf.pas | 58 | ||||
-rw-r--r-- | nim/transtmp.pas | 2 | ||||
-rw-r--r-- | nim/trees.pas | 4 | ||||
-rw-r--r-- | nim/types.pas | 125 | ||||
-rw-r--r-- | nim/wordrecg.pas | 60 | ||||
-rw-r--r-- | rod/nimrod.dot | 60 | ||||
-rw-r--r-- | rod/nimrod.ini | 70 | ||||
-rw-r--r-- | tests/thallo.nim | 2 | ||||
-rw-r--r-- | tests/tlibs.nim | 6 | ||||
-rw-r--r-- | tests/ttempl3.nim | 10 | ||||
-rw-r--r-- | tools/inno.tmpl | 9 | ||||
-rw-r--r-- | tools/install.tmpl | 186 | ||||
-rw-r--r-- | tools/niminst.nim | 155 |
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) |