summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAndreas Rumpf <andreas@andreas-desktop>2010-07-29 21:30:04 +0200
committerAndreas Rumpf <andreas@andreas-desktop>2010-07-29 21:30:04 +0200
commitff02ce2d50d8a4b445f9fba6076527c3db62425c (patch)
tree065d5ecddb38f871e516b49c333f565b6cba9b31
parent804e2ac89d378b87e0ec8c723f607aa4271c57bb (diff)
downloadNim-ff02ce2d50d8a4b445f9fba6076527c3db62425c.tar.gz
handling of compiler procs improved for DLL generation
-rwxr-xr-xlib/nimrtl.nim39
-rwxr-xr-xlib/pure/strutils.nim41
-rwxr-xr-xlib/system.nim54
-rw-r--r--lib/system/cgprocs.nim14
-rwxr-xr-xlib/system/dyncalls.nim7
-rwxr-xr-xlib/system/gc.nim22
-rwxr-xr-xlib/system/inclrtl.nim45
-rwxr-xr-xlib/system/mmdisp.nim75
-rwxr-xr-xlib/system/repr.nim263
-rwxr-xr-xlib/system/sysio.nim8
-rwxr-xr-xlib/system/sysstr.nim11
-rwxr-xr-xrod/c2nim/cparse.nim46
-rwxr-xr-x[-rw-r--r--]rod/c2nim/manual.txt0
-rwxr-xr-x[-rw-r--r--]rod/c2nim/tests/systest.c0
-rwxr-xr-x[-rw-r--r--]rod/c2nim/tests/systest2.c0
-rwxr-xr-xrod/ccgexprs.nim360
-rwxr-xr-xrod/ccgstmts.nim59
-rwxr-xr-xrod/ccgtypes.nim37
-rwxr-xr-xrod/cgen.nim169
-rwxr-xr-xrod/magicsys.nim5
-rwxr-xr-xrod/nimrod.ini5
-rwxr-xr-xrod/pragmas.nim30
-rwxr-xr-xrod/semstmts.nim6
-rwxr-xr-xrod/wordrecg.nim8
-rwxr-xr-x[-rw-r--r--]tests/accept/compile/tenum3.nim0
-rwxr-xr-x[-rw-r--r--]tests/accept/compile/tuserpragma.nim0
-rwxr-xr-x[-rw-r--r--]tests/accept/run/tarray3.nim0
-rwxr-xr-x[-rw-r--r--]tests/accept/run/tunhandledexc.nim0
-rwxr-xr-x[-rw-r--r--]tests/accept/run/twrongexc.nim0
-rwxr-xr-xtodo.txt3
-rwxr-xr-xtools/buildsh.tmpl (renamed from tools/build.tmpl)10
-rwxr-xr-xtools/niminst.nim44
-rwxr-xr-xweb/news.txt11
33 files changed, 701 insertions, 671 deletions
diff --git a/lib/nimrtl.nim b/lib/nimrtl.nim
new file mode 100755
index 000000000..c61824f49
--- /dev/null
+++ b/lib/nimrtl.nim
@@ -0,0 +1,39 @@
+#
+#
+#            Nimrod's Runtime Library
+#        (c) Copyright 2010 Andreas Rumpf
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+## Main file to generate a DLL from the standard library. 
+## The default Nimrtl does not only contain the ``system`` module, but these 
+## too:
+##
+## * strutils
+## * parseutils
+## * parseopt
+## * parsecfg
+## * strtabs
+## * times
+## * os
+## * osproc
+## * pegs
+## * unicode
+## * ropes
+## * re
+## 
+## So the resulting dynamic library is quite big. However, it is very easy to
+## strip modules out. Just modify the ``import`` statement in
+## ``lib/nimrtl.nim`` and recompile. Note that simply *adding* a module
+## here is not sufficient, though.
+
+when system.appType != "lib":
+  {.error: "This file has to be compiled as a library!".}
+
+when not defined(createNimRtl): 
+  {.error: "This file has to be compiled with '-d:createNimRtl'".}
+
+
+
diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim
index 38f6ffa9a..ee56deab3 100755
--- a/lib/pure/strutils.nim
+++ b/lib/pure/strutils.nim
@@ -125,19 +125,6 @@ proc find*(s: string, chars: set[char], start: int = 0): int {.noSideEffect.}
   ## Searches for `chars` in `s` starting at position `start`. If `s` contains

   ## none of the characters in `chars`, -1 is returned.

 

-proc replaceStr*(s, sub, by: string): string {.noSideEffect, deprecated.}

-  ## Replaces `sub` in `s` by the string `by`.

-  ## **Deprecated since version 0.8.0**: Use `replace` instead.

-

-proc replaceStr*(s: string, sub, by: char): string {.noSideEffect, deprecated.}

-  ## optimized version for characters.

-  ## **Deprecated since version 0.8.0**: Use `replace` instead.

-

-proc deleteStr*(s: var string, first, last: int) {.deprecated.}

-  ## Deletes in `s` the characters at position `first` .. `last`. This modifies

-  ## `s` itself, it does not return a copy.

-  ## **Deprecated since version 0.8.0**: Use `delete` instead.

-

 proc toOctal*(c: char): string

   ## Converts a character `c` to its octal representation. The resulting

   ## string may not have a leading zero. Its length is always exactly 3.

@@ -241,24 +228,6 @@ iterator splitLines*(s: string): string =
     else: break # was '\0'

     first = last

 

-proc splitLinesSeq*(s: string): seq[string] {.noSideEffect, deprecated.} =

-  ## The same as `splitLines`, but is a proc that returns a sequence 

-  ## of substrings.

-  ## **Deprecated since version 0.8.0**: Use `splitLines` instead.

-  accumulateResult(splitLines(s))

-

-proc splitSeq*(s: string, seps: set[char] = Whitespace): seq[string] {.

-  noSideEffect, deprecated.} =

-  ## The same as `split`, but is a proc that returns a sequence of substrings.

-  ## **Deprecated since version 0.8.0**: Use `split` instead.

-  accumulateResult(split(s, seps))

-

-proc splitSeq*(s: string, sep: char): seq[string] {.noSideEffect, 

-                                                    deprecated.} =

-  ## The same as `split`, but is a proc that returns a sequence of substrings.

-  ## **Deprecated since version 0.8.0**: Use `split` instead.

-  accumulateResult(split(s, sep))

-

 proc splitLines*(s: string): seq[string] {.noSideEffect.} =

   ## The same as the `splitLines` iterator, but is a proc that returns a 

   ## sequence of substrings.

@@ -328,12 +297,6 @@ proc ParseHexInt*(s: string): int {.noSideEffect, procvar.}
   ## following optional prefixes: ``0x``, ``0X``, ``#``. 

   ## Underscores within `s` are ignored.

 

-# the stringify and format operators:

-proc toString*[Ty](x: Ty): string {.deprecated.}

-  ## This generic proc is the same as the stringify operator `$`.

-  ##

-  ## **Deprecated since version 0.8.2:** Use `$` instead.

-

 proc repeatChar*(count: int, c: Char = ' '): string

   ## Returns a string of length `count` consisting only of

   ## the character `c`.

@@ -670,10 +633,6 @@ proc delete*(s: var string, first, last: int) =
     inc(j)

   setlen(s, newLen)

 

-proc replaceStr(s, sub, by: string): string = return replace(s, sub, by)

-proc replaceStr(s: string, sub, by: char): string = return replace(s, sub, by)

-proc deleteStr(s: var string, first, last: int) = delete(s, first, last)

-

 # parsing numbers:

 

 proc toHex(x: BiggestInt, len: int): string =

diff --git a/lib/system.nim b/lib/system.nim
index d3450902e..fec31eba0 100755
--- a/lib/system.nim
+++ b/lib/system.nim
@@ -667,6 +667,8 @@ proc `&` * (x: char, y: string): string {.
 proc add*(x: var string, y: char) {.magic: "AppendStrCh", noSideEffect.}
 proc add*(x: var string, y: string) {.magic: "AppendStrStr", noSideEffect.}
 
+include "system/cgprocs"
+
 when not defined(ECMAScript):
   {.push overflow_checks:off}
   proc add* (x: var string, y: cstring) =
@@ -732,7 +734,6 @@ type
     ## is the signed integer type that should be used for converting
     ## pointers to integer addresses for readability.
 
-type
   BiggestInt* = int64
     ## is an alias for the biggest signed integer type the Nimrod compiler
     ## supports. Currently this is ``int64``, but it is platform-dependant
@@ -767,7 +768,7 @@ type # these work for most platforms:
   cstringArray* {.importc: "char**", nodecl.} = ptr array [0..50_000, cstring]
     ## This is binary compatible to the type ``char**`` in *C*. The array's
     ## high value is large enough to disable bounds checking in practice.
-    ## Use cstringArrayToSeq to convert it into a ``seq[string]``.
+    ## Use `cstringArrayToSeq` to convert it into a ``seq[string]``.
 
   TEndian* = enum ## is a type describing the endianness of a processor.
     littleEndian, bigEndian
@@ -823,6 +824,8 @@ const
     ## a string that describes the application type. Possible values:
     ## "console", "gui", "lib".
   
+include "system/inclrtl"
+  
 proc toFloat*(i: int): float {.
   magic: "ToFloat", noSideEffect, importc: "toFloat".}
   ## converts an integer `i` into a ``float``. If the conversion
@@ -897,23 +900,23 @@ proc equalMem*(a, b: Pointer, size: int): bool {.
   ## otherwise. Like any procedure dealing with raw memory this is
   ## *unsafe*.
 
-proc alloc*(size: int): pointer {.noconv.}
+proc alloc*(size: int): pointer {.noconv, rtl.}
   ## allocates a new memory block with at least ``size`` bytes. The
   ## block has to be freed with ``realloc(block, 0)`` or
   ## ``dealloc(block)``. The block is not initialized, so reading
   ## from it before writing to it is undefined behaviour!
-proc alloc0*(size: int): pointer {.noconv.}
+proc alloc0*(size: int): pointer {.noconv, rtl.}
   ## allocates a new memory block with at least ``size`` bytes. The
   ## block has to be freed with ``realloc(block, 0)`` or
   ## ``dealloc(block)``. The block is initialized with all bytes
   ## containing zero, so it is somewhat safer than ``alloc``.
-proc realloc*(p: Pointer, newsize: int): pointer {.noconv.}
+proc realloc*(p: Pointer, newsize: int): pointer {.noconv, rtl.}
   ## grows or shrinks a given memory block. If p is **nil** then a new
   ## memory block is returned. In either way the block has at least
   ## ``newsize`` bytes. If ``newsize == 0`` and p is not **nil**
   ## ``realloc`` calls ``dealloc(p)``. In other cases the block has to
   ## be freed with ``dealloc``.
-proc dealloc*(p: Pointer) {.noconv.}
+proc dealloc*(p: Pointer) {.noconv, rtl.}
   ## frees the memory allocated with ``alloc``, ``alloc0`` or
   ## ``realloc``. This procedure is dangerous! If one forgets to
   ## free the memory a leak occurs; if one tries to access freed
@@ -1009,14 +1012,14 @@ var
 
 # GC interface:
 
-proc getOccupiedMem*(): int
+proc getOccupiedMem*(): int {.rtl.}
   ## returns the number of bytes that are owned by the process and hold data.
 
-proc getFreeMem*(): int
+proc getFreeMem*(): int {.rtl.}
   ## returns the number of bytes that are owned by the process, but do not
   ## hold any meaningful data.
 
-proc getTotalMem*(): int
+proc getTotalMem*(): int {.rtl.}
   ## returns the number of bytes that are owned by the process.
 
 
@@ -1205,15 +1208,15 @@ proc each*[T](data: var openArray[T], op: proc (x: var T)) =
 
 # ----------------- GC interface ---------------------------------------------
 
-proc GC_disable*()
+proc GC_disable*() {.rtl.}
   ## disables the GC. If called n-times, n calls to `GC_enable` are needed to
   ## reactivate the GC. Note that in most circumstances one should only disable
   ## the mark and sweep phase with `GC_disableMarkAndSweep`.
 
-proc GC_enable*()
+proc GC_enable*() {.rtl.}
   ## enables the GC again.
 
-proc GC_fullCollect*()
+proc GC_fullCollect*() {.rtl.}
   ## forces a full garbage collection pass.
   ## Ordinary code does not need to call this (and should not).
 
@@ -1224,18 +1227,18 @@ type
     gcOptimizeTime,    ## optimize for speed
     gcOptimizeSpace    ## optimize for memory footprint
 
-proc GC_setStrategy*(strategy: TGC_Strategy)
+proc GC_setStrategy*(strategy: TGC_Strategy) {.rtl.}
   ## tells the GC the desired strategy for the application.
 
-proc GC_enableMarkAndSweep*()
-proc GC_disableMarkAndSweep*()
+proc GC_enableMarkAndSweep*() {.rtl.}
+proc GC_disableMarkAndSweep*() {.rtl.}
   ## the current implementation uses a reference counting garbage collector
   ## with a seldomly run mark and sweep phase to free cycles. The mark and
   ## sweep phase may take a long time and is not needed if the application
   ## does not create cycles. Thus the mark and sweep phase can be deactivated
   ## and activated separately from the rest of the GC.
 
-proc GC_getStatistics*(): string
+proc GC_getStatistics*(): string {.rtl.}
   ## returns an informative string about the GC's activity. This may be useful
   ## for tweaking.
   
@@ -1372,23 +1375,14 @@ when not defined(EcmaScript) and not defined(NimrodVM):
       ## appropriately. It also annoys people if redirection via ``>output.txt``
       ## does not work because the program writes to ``stderr``.
 
-  proc OpenFile*(f: var TFile, filename: string,
-                 mode: TFileMode = fmRead, 
-                 bufSize: int = -1): Bool {.deprecated.}
-    ## **Deprecated since version 0.8.0**: Use `open` instead.
-
-  proc OpenFile*(f: var TFile, filehandle: TFileHandle,
-                 mode: TFileMode = fmRead): Bool {.deprecated.}
-    ## **Deprecated since version 0.8.0**: Use `open` instead.
-
   proc Open*(f: var TFile, filename: string,
              mode: TFileMode = fmRead, bufSize: int = -1): Bool
     ## Opens a file named `filename` with given `mode`.
     ##
     ## Default mode is readonly. Returns true iff the file could be opened.
     ## This throws no exception if the file could not be opened. The reason is
-    ## that the programmer needs to provide an appropriate error message anyway
-    ## (yes, even in scripts).
+    ## that the programmer needs to provide an appropriate error message 
+    ## anyway.
 
   proc Open*(f: var TFile, filehandle: TFileHandle,
              mode: TFileMode = fmRead): Bool
@@ -1403,10 +1397,6 @@ when not defined(EcmaScript) and not defined(NimrodVM):
     ##
     ## Default mode is readonly. Returns true iff the file could be reopened.
 
-  proc CloseFile*(f: TFile) {.importc: "fclose", nodecl, deprecated.}
-    ## Closes the file.
-    ## **Deprecated since version 0.8.0**: Use `close` instead.
-
   proc Close*(f: TFile) {.importc: "fclose", nodecl.}
     ## Closes the file.
 
@@ -1545,7 +1535,7 @@ when not defined(EcmaScript) and not defined(NimrodVM):
   const
     GenericSeqSize = (2 * sizeof(int))
     
-  proc reprAny(p: pointer, typ: PNimType): string {.compilerproc.}
+  proc reprAny(p: pointer, typ: PNimType): string {.compilerRtl.}
 
   proc getDiscriminant(aa: Pointer, n: ptr TNimNode): int =
     assert(n.kind == nkCase)
diff --git a/lib/system/cgprocs.nim b/lib/system/cgprocs.nim
new file mode 100644
index 000000000..40aca033b
--- /dev/null
+++ b/lib/system/cgprocs.nim
@@ -0,0 +1,14 @@
+#
+#
+#            Nimrod's Runtime Library
+#        (c) Copyright 2010 Andreas Rumpf
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+# Headers for procs that the code generator depends on ("compilerprocs")
+
+proc addChar(s: NimString, c: char): NimString {.compilerProc.}
+
+
diff --git a/lib/system/dyncalls.nim b/lib/system/dyncalls.nim
index 0946ee355..cb665c5cb 100755
--- a/lib/system/dyncalls.nim
+++ b/lib/system/dyncalls.nim
@@ -24,7 +24,12 @@ 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)
+  when true:
+    # carefully written to avoid memory allocation:
+    stdout.write("could not load: ")
+    quit(path)
+  else:
+    raise newException(EInvalidLibrary, "could not load: " & path)
 
 # this code was inspired from Lua's source code:
 # Lua - An Extensible Extension Language
diff --git a/lib/system/gc.nim b/lib/system/gc.nim
index 1e9cd5a4a..f21f5bc01 100755
--- a/lib/system/gc.nim
+++ b/lib/system/gc.nim
@@ -74,13 +74,13 @@ var
     # This is wasteful but safe. This is a lock against recursive garbage
     # collection, not a lock for threads!
 
-proc unsureAsgnRef(dest: ppointer, src: pointer) {.compilerproc.}
+proc unsureAsgnRef(dest: ppointer, src: pointer) {.compilerRtl.}
   # unsureAsgnRef updates the reference counters only if dest is not on the
   # stack. It is used by the code generator if it cannot decide wether a
   # reference is in the stack or not (this can happen for var parameters).
-#proc growObj(old: pointer, newsize: int): pointer {.compilerproc.}
-proc newObj(typ: PNimType, size: int): pointer {.compilerproc.}
-proc newSeq(typ: PNimType, len: int): pointer {.compilerproc.}
+
+proc newObj(typ: PNimType, size: int): pointer {.compilerRtl.}
+proc newSeq(typ: PNimType, len: int): pointer {.compilerRtl.}
 
 proc addZCT(s: var TCellSeq, c: PCell) {.noinline.} =
   if (c.refcount and rcZct) == 0:
@@ -214,8 +214,10 @@ proc prepareDealloc(cell: PCell) =
     (cast[TFinalizer](cell.typ.finalizer))(cellToUsr(cell))
     dec(recGcLock)
 
-proc setStackBottom(theStackBottom: pointer) {.compilerproc.} =
-  stackBottom = theStackBottom
+proc setStackBottom(theStackBottom: pointer) {.compilerRtl.} =
+  # the first init must be the one that defines the stack bottom:
+  if stackBottom == nil:
+    stackBottom = theStackBottom
 
 proc PossibleRoot(gch: var TGcHeap, c: PCell) {.inline.} =
   if canbeCycleRoot(c): incl(gch.cycleRoots, c)
@@ -236,10 +238,10 @@ proc incRef(c: PCell) {.inline.} =
   if canBeCycleRoot(c):
     incl(gch.cycleRoots, c)
 
-proc nimGCref(p: pointer) {.compilerproc, inline.} = incRef(usrToCell(p))
-proc nimGCunref(p: pointer) {.compilerproc, inline.} = decRef(usrToCell(p))
+proc nimGCref(p: pointer) {.compilerRtl, inl.} = incRef(usrToCell(p))
+proc nimGCunref(p: pointer) {.compilerRtl, inl.} = decRef(usrToCell(p))
 
-proc asgnRef(dest: ppointer, src: pointer) {.compilerproc, inline.} =
+proc asgnRef(dest: ppointer, src: pointer) {.compilerRtl, inl.} =
   # the code generator calls this proc!
   assert(not isOnStack(dest))
   # BUGFIX: first incRef then decRef!
@@ -247,7 +249,7 @@ proc asgnRef(dest: ppointer, src: pointer) {.compilerproc, inline.} =
   if dest^ != nil: decRef(usrToCell(dest^))
   dest^ = src
 
-proc asgnRefNoCycle(dest: ppointer, src: pointer) {.compilerproc, inline.} =
+proc asgnRefNoCycle(dest: ppointer, src: pointer) {.compilerRtl, inl.} =
   # the code generator calls this proc if it is known at compile time that no 
   # cycle is possible.
   if src != nil: 
diff --git a/lib/system/inclrtl.nim b/lib/system/inclrtl.nim
new file mode 100755
index 000000000..28965b4b1
--- /dev/null
+++ b/lib/system/inclrtl.nim
@@ -0,0 +1,45 @@
+#
+#
+#            Nimrod's Runtime Library
+#        (c) Copyright 2010 Andreas Rumpf
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+## Pragmas for RTL generation. Has to be an include, because user-defined
+## pragmas cannot be exported.
+
+# There are 3 different usages:
+# 1) Ordinary imported code.
+# 2) Imported from nimrtl.
+#    -> defined(useNimRtl) or appType == "lib" and not defined(createNimRtl)
+# 3) Exported into nimrtl.
+#    -> appType == "lib" and defined(createNimRtl)
+
+when defined(createNimRtl):
+  when defined(useNimRtl): 
+    {.error: "Cannot create and use nimrtl at the same time!".}
+  elif appType != "lib":
+    {.error: "nimrtl must be build as a library!".}
+
+when defined(createNimRtl): 
+  # NOTE: compilerproc cannot make use of name mangling!
+  {.pragma: rtl, exportc: "nimrtl_$1", dynlib.}
+  {.pragma: inl.}
+  {.pragma: compilerRtl, compilerproc, exportc: "nimrtl_$1", dynlib.}
+elif defined(useNimRtl):
+  when hostOS == "windows": 
+    const nimrtl* = "nimrtl.dll"
+  elif hostOS == "macosx":
+    const nimrtl* = "nimrtl.dynlib"
+  else: 
+    const nimrtl* = "libnimrtl.so"
+  {.pragma: rtl, importc: "nimrtl_$1", dynlib: nimrtl.}
+  {.pragma: inl.}
+  {.pragma: compilerRtl, compilerproc, importc: "nimrtl_$1", dynlib: nimrtl.}
+else:
+  {.pragma: rtl.}
+  {.pragma: inl, inline.}
+  {.pragma: compilerRtl, compilerproc.}
+
diff --git a/lib/system/mmdisp.nim b/lib/system/mmdisp.nim
index 44b3f7326..ff61ea1fe 100755
--- a/lib/system/mmdisp.nim
+++ b/lib/system/mmdisp.nim
@@ -187,60 +187,35 @@ elif defined(nogc):
     dest^ = src
 
   include "system/cellsets"
-elif appType == "lib": 
-  {.warning: "gc in a library context may not work".}
-  when hostOS == "windows": 
-    const nimrtl = "nimrtl.dll"
-  elif hostOS == "macosx":
-    const nimrtl = "nimrtl.dynlib"
-  else: 
-    const nimrtl = "libnimrtl.so"
-  
-  when not defined(includeGC):
-    # ordinary client; use the GC from nimrtl.dll:
-    proc initGC() {.cdecl, importc, dynlib: nimrtl.}
-    proc GC_disable() {.cdecl, importc, dynlib: nimrtl.}
-    proc GC_enable() {.cdecl, importc, dynlib: nimrtl.}
-    proc GC_fullCollect() {.cdecl, importc, dynlib: nimrtl.}
-    proc GC_setStrategy(strategy: TGC_Strategy) {.
-      cdecl, importc, dynlib: nimrtl.}
-    proc GC_enableMarkAndSweep() {.cdecl, importc, dynlib: nimrtl.}
-    proc GC_disableMarkAndSweep() {.cdecl, importc, dynlib: nimrtl.}
-    proc GC_getStatistics(): string {.cdecl, importc, dynlib: nimrtl.}
-
-    proc newObj(typ: PNimType, size: int): pointer {.
-      compilerproc, cdecl, importc, dynlib: nimrtl.}
-    proc newSeq(typ: PNimType, len: int): pointer {.
-      compilerproc, cdecl, importc, dynlib: nimrtl.}
-    proc growObj(old: pointer, newsize: int): pointer {.
-      cdecl, importc, dynlib: nimrtl.}
-      
-    proc setStackBottom(theStackBottom: pointer) {.
-      compilerproc, cdecl, importc, dynlib: nimrtl.}
-    proc nimGCref(p: pointer) {.
-      compilerproc, cdecl, importc, dynlib: nimrtl.}
-    proc nimGCunref(p: pointer) {.
-      compilerproc, cdecl, importc, dynlib: nimrtl.}
-    
-    # The write barrier is performance critical!
-    # XXX We should ensure that they are inlined here.
-    # Later implementations will do this.
+elif defined(useNimRtl): 
+  proc initGC() = nil
+
+  proc newObj(typ: PNimType, size: int): pointer {.compilerRtl.}
+  proc newSeq(typ: PNimType, len: int): pointer {.compilerRtl.}
+  proc growObj(old: pointer, newsize: int): pointer {.rtl.}
     
-    proc unsureAsgnRef(dest: ppointer, src: pointer) {.
-      compilerproc, cdecl, importc, dynlib: nimrtl.}
-    proc asgnRef(dest: ppointer, src: pointer) {.
-      compilerproc, cdecl, importc, dynlib: nimrtl.}
-    proc asgnRefNoCycle(dest: ppointer, src: pointer) {.
-      compilerproc, cdecl, importc, dynlib: nimrtl.}
+  proc setStackBottom(theStackBottom: pointer) {.compilerProc, inline.} = 
+    # This happens before setStackBottom has been loaded by dlsym(), so
+    # we simply provide a dummy implemenation here for the code gen. No
+    # harm is done by this.
+    nil
     
-  else:
-    # include the GC and export it!
-    include "system/alloc"
-    include "system/cellsets"
-    assert(sizeof(TCell) == sizeof(TFreeCell))
-    include "system/gc"
+  proc nimGCref(p: pointer) {.compilerRtl.}
+  proc nimGCunref(p: pointer) {.compilerRtl.}
+  
+  # The write barrier is performance critical!
+  # XXX We should ensure that they are inlined here.
+  # Later implementations will do this.
   
+  proc unsureAsgnRef(dest: ppointer, src: pointer) {.
+    compilerRtl.}
+  proc asgnRef(dest: ppointer, src: pointer) {.
+    compilerRtl.}
+  proc asgnRefNoCycle(dest: ppointer, src: pointer) {.
+    compilerRtl.}
+
   include "system/cellsets"    
+
 else:
   include "system/alloc"
   include "system/cellsets"
diff --git a/lib/system/repr.nim b/lib/system/repr.nim
index e340f1d7c..b597cb0ce 100755
--- a/lib/system/repr.nim
+++ b/lib/system/repr.nim
@@ -1,7 +1,7 @@
 #
 #
 #            Nimrod's Runtime Library
-#        (c) Copyright 2009 Andreas Rumpf
+#        (c) Copyright 2010 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -35,15 +35,15 @@ proc reprStrAux(result: var string, s: string) =
     else: result.add(c)
   add result, "\""
 
-proc reprStr(s: string): string {.compilerproc.} =
+proc reprStr(s: string): string {.compilerRtl.} =
   result = ""
   reprStrAux(result, s)
 
-proc reprBool(x: bool): string {.compilerproc.} =
+proc reprBool(x: bool): string {.compilerRtl.} =
   if x: result = "true"
   else: result = "false"
 
-proc reprChar(x: char): string {.compilerproc.} =
+proc reprChar(x: char): string {.compilerRtl.} =
   result = "\'"
   case x
   of '"': add result, "\\\""
@@ -52,7 +52,7 @@ proc reprChar(x: char): string {.compilerproc.} =
   else: add result, x
   add result, "\'"
 
-proc reprEnum(e: int, typ: PNimType): string {.compilerproc.} =
+proc reprEnum(e: int, typ: PNimType): string {.compilerRtl.} =
   if e <% typ.node.len: # BUGFIX
     result = $typ.node.sons[e].name
   else:
@@ -97,7 +97,7 @@ proc reprSetAux(result: var string, p: pointer, typ: PNimType) =
         inc(elemCounter)
   add result, "}"
 
-proc reprSet(p: pointer, typ: PNimType): string {.compilerproc.} =
+proc reprSet(p: pointer, typ: PNimType): string {.compilerRtl.} =
   result = ""
   reprSetAux(result, p, typ)
 
@@ -108,122 +108,123 @@ type
     recdepth: int       # do not recurse endless
     indent: int         # indentation
 
-proc initReprClosure(cl: var TReprClosure) =
-  Init(cl.marked)
-  cl.recdepth = -1      # default is to display everything!
-  cl.indent = 0
-
-proc deinitReprClosure(cl: var TReprClosure) =
-  Deinit(cl.marked)
-
-proc reprBreak(result: var string, cl: TReprClosure) =
-  add result, "\n"
-  for i in 0..cl.indent-1: add result, ' '
-
-proc reprAux(result: var string, p: pointer, typ: PNimType,
-             cl: var TReprClosure)
-
-proc reprArray(result: var string, p: pointer, typ: PNimType,
-               cl: var TReprClosure) =
-  add result, "["
-  var bs = typ.base.size
-  for i in 0..typ.size div bs - 1:
-    if i > 0: add result, ", "
-    reprAux(result, cast[pointer](cast[TAddress](p) + i*bs), typ.base, cl)
-  add result, "]"
-
-proc reprSequence(result: var string, p: pointer, typ: PNimType,
+when not defined(useNimRtl):
+  proc initReprClosure(cl: var TReprClosure) =
+    Init(cl.marked)
+    cl.recdepth = -1      # default is to display everything!
+    cl.indent = 0
+
+  proc deinitReprClosure(cl: var TReprClosure) =
+    Deinit(cl.marked)
+
+  proc reprBreak(result: var string, cl: TReprClosure) =
+    add result, "\n"
+    for i in 0..cl.indent-1: add result, ' '
+
+  proc reprAux(result: var string, p: pointer, typ: PNimType,
+               cl: var TReprClosure)
+
+  proc reprArray(result: var string, p: pointer, typ: PNimType,
+                 cl: var TReprClosure) =
+    add result, "["
+    var bs = typ.base.size
+    for i in 0..typ.size div bs - 1:
+      if i > 0: add result, ", "
+      reprAux(result, cast[pointer](cast[TAddress](p) + i*bs), typ.base, cl)
+    add result, "]"
+
+  proc reprSequence(result: var string, p: pointer, typ: PNimType,
+                    cl: var TReprClosure) =
+    if p == nil:
+      add result, "nil"
+      return
+    result.add(reprPointer(p) & "[")
+    var bs = typ.base.size
+    for i in 0..cast[PGenericSeq](p).len-1:
+      if i > 0: add result, ", "
+      reprAux(result, cast[pointer](cast[TAddress](p) + GenericSeqSize + i*bs),
+              typ.Base, cl)
+    add result, "]"
+
+  proc reprRecordAux(result: var string, p: pointer, n: ptr TNimNode,
+                     cl: var TReprClosure) =
+    case n.kind
+    of nkNone: assert(false)
+    of nkSlot:
+      add result, $n.name
+      add result, " = "
+      reprAux(result, cast[pointer](cast[TAddress](p) + n.offset), n.typ, cl)
+    of nkList:
+      for i in 0..n.len-1:
+        if i > 0: add result, ",\n"
+        reprRecordAux(result, p, n.sons[i], cl)
+    of nkCase:
+      var m = selectBranch(p, n)
+      reprAux(result, cast[pointer](cast[TAddress](p) + n.offset), n.typ, cl)
+      if m != nil: reprRecordAux(result, p, m, cl)
+
+  proc reprRecord(result: var string, p: pointer, typ: PNimType,
                   cl: var TReprClosure) =
-  if p == nil:
-    add result, "nil"
-    return
-  result.add(reprPointer(p) & "[")
-  var bs = typ.base.size
-  for i in 0..cast[PGenericSeq](p).len-1:
-    if i > 0: add result, ", "
-    reprAux(result, cast[pointer](cast[TAddress](p) + GenericSeqSize + i*bs),
-            typ.Base, cl)
-  add result, "]"
-
-proc reprRecordAux(result: var string, p: pointer, n: ptr TNimNode,
-                   cl: var TReprClosure) =
-  case n.kind
-  of nkNone: assert(false)
-  of nkSlot:
-    add result, $n.name
-    add result, " = "
-    reprAux(result, cast[pointer](cast[TAddress](p) + n.offset), n.typ, cl)
-  of nkList:
-    for i in 0..n.len-1:
-      if i > 0: add result, ",\n"
-      reprRecordAux(result, p, n.sons[i], cl)
-  of nkCase:
-    var m = selectBranch(p, n)
-    reprAux(result, cast[pointer](cast[TAddress](p) + n.offset), n.typ, cl)
-    if m != nil: reprRecordAux(result, p, m, cl)
-
-proc reprRecord(result: var string, p: pointer, typ: PNimType,
-                cl: var TReprClosure) =
-  add result, "["
-  reprRecordAux(result, p, typ.node, cl)
-  add result, "]"
+    add result, "["
+    reprRecordAux(result, p, typ.node, cl)
+    add result, "]"
 
-proc reprRef(result: var string, p: pointer, typ: PNimType,
-             cl: var TReprClosure) =
-  # we know that p is not nil here:
-  when defined(boehmGC) or defined(nogc):
-    var cell = cast[PCell](p)
-  else:
-    var cell = usrToCell(p)
-  add result, "ref " & reprPointer(p)
-  if cell notin cl.marked:
-    # only the address is shown:
-    incl(cl.marked, cell)
-    add result, " --> "
-    reprAux(result, p, typ.base, cl)
-
-proc reprAux(result: var string, p: pointer, typ: PNimType,
-             cl: var TReprClosure) =
-  if cl.recdepth == 0:
-    add result, "..."
-    return
-  dec(cl.recdepth)
-  case typ.kind
-  of tySet: reprSetAux(result, p, typ)
-  of tyArray: reprArray(result, p, typ, cl)
-  of tyTuple, tyPureObject: reprRecord(result, p, typ, cl)
-  of tyObject: 
-    var t = cast[ptr PNimType](p)^
-    reprRecord(result, p, t, cl)
-  of tyRef, tyPtr:
-    assert(p != nil)
-    if cast[ppointer](p)^ == nil: add result, "nil"
-    else: reprRef(result, cast[ppointer](p)^, typ, cl)
-  of tySequence:
-    reprSequence(result, cast[ppointer](p)^, typ, cl)
-  of tyInt: add result, $(cast[ptr int](p)^)
-  of tyInt8: add result, $int(cast[ptr Int8](p)^)
-  of tyInt16: add result, $int(cast[ptr Int16](p)^)
-  of tyInt32: add result, $int(cast[ptr Int32](p)^)
-  of tyInt64: add result, $(cast[ptr Int64](p)^)
-  of tyFloat: add result, $(cast[ptr float](p)^)
-  of tyFloat32: add result, $(cast[ptr float32](p)^)
-  of tyFloat64: add result, $(cast[ptr float64](p)^)
-  of tyEnum: add result, reprEnum(cast[ptr int](p)^, typ)
-  of tyBool: add result, reprBool(cast[ptr bool](p)^)
-  of tyChar: add result, reprChar(cast[ptr char](p)^)
-  of tyString: reprStrAux(result, cast[ptr string](p)^)
-  of tyCString: reprStrAux(result, $(cast[ptr cstring](p)^))
-  of tyRange: reprAux(result, p, typ.base, cl)
-  of tyProc, tyPointer:
-    if cast[ppointer](p)^ == nil: add result, "nil"
-    else: add result, reprPointer(cast[ppointer](p)^)
-  else:
-    add result, "(invalid data!)"
-  inc(cl.recdepth)
+  proc reprRef(result: var string, p: pointer, typ: PNimType,
+               cl: var TReprClosure) =
+    # we know that p is not nil here:
+    when defined(boehmGC) or defined(nogc):
+      var cell = cast[PCell](p)
+    else:
+      var cell = usrToCell(p)
+    add result, "ref " & reprPointer(p)
+    if cell notin cl.marked:
+      # only the address is shown:
+      incl(cl.marked, cell)
+      add result, " --> "
+      reprAux(result, p, typ.base, cl)
+
+  proc reprAux(result: var string, p: pointer, typ: PNimType,
+               cl: var TReprClosure) =
+    if cl.recdepth == 0:
+      add result, "..."
+      return
+    dec(cl.recdepth)
+    case typ.kind
+    of tySet: reprSetAux(result, p, typ)
+    of tyArray: reprArray(result, p, typ, cl)
+    of tyTuple, tyPureObject: reprRecord(result, p, typ, cl)
+    of tyObject: 
+      var t = cast[ptr PNimType](p)^
+      reprRecord(result, p, t, cl)
+    of tyRef, tyPtr:
+      assert(p != nil)
+      if cast[ppointer](p)^ == nil: add result, "nil"
+      else: reprRef(result, cast[ppointer](p)^, typ, cl)
+    of tySequence:
+      reprSequence(result, cast[ppointer](p)^, typ, cl)
+    of tyInt: add result, $(cast[ptr int](p)^)
+    of tyInt8: add result, $int(cast[ptr Int8](p)^)
+    of tyInt16: add result, $int(cast[ptr Int16](p)^)
+    of tyInt32: add result, $int(cast[ptr Int32](p)^)
+    of tyInt64: add result, $(cast[ptr Int64](p)^)
+    of tyFloat: add result, $(cast[ptr float](p)^)
+    of tyFloat32: add result, $(cast[ptr float32](p)^)
+    of tyFloat64: add result, $(cast[ptr float64](p)^)
+    of tyEnum: add result, reprEnum(cast[ptr int](p)^, typ)
+    of tyBool: add result, reprBool(cast[ptr bool](p)^)
+    of tyChar: add result, reprChar(cast[ptr char](p)^)
+    of tyString: reprStrAux(result, cast[ptr string](p)^)
+    of tyCString: reprStrAux(result, $(cast[ptr cstring](p)^))
+    of tyRange: reprAux(result, p, typ.base, cl)
+    of tyProc, tyPointer:
+      if cast[ppointer](p)^ == nil: add result, "nil"
+      else: add result, reprPointer(cast[ppointer](p)^)
+    else:
+      add result, "(invalid data!)"
+    inc(cl.recdepth)
 
 proc reprOpenArray(p: pointer, length: int, elemtyp: PNimType): string {.
-                   compilerproc.} =
+                   compilerRtl.} =
   var
     cl: TReprClosure
   initReprClosure(cl)
@@ -235,15 +236,17 @@ proc reprOpenArray(p: pointer, length: int, elemtyp: PNimType): string {.
   add result, "]"
   deinitReprClosure(cl)
 
-proc reprAny(p: pointer, typ: PNimType): string =
-  var
-    cl: TReprClosure
-  initReprClosure(cl)
-  result = ""
-  if typ.kind in {tyObject, tyPureObject, tyTuple, tyArray, tySet}:
-    reprAux(result, p, typ, cl)
-  else:
-    var p = p
-    reprAux(result, addr(p), typ, cl)
-  add result, "\n"
-  deinitReprClosure(cl)
+when not defined(useNimRtl):
+  proc reprAny(p: pointer, typ: PNimType): string =
+    var
+      cl: TReprClosure
+    initReprClosure(cl)
+    result = ""
+    if typ.kind in {tyObject, tyPureObject, tyTuple, tyArray, tySet}:
+      reprAux(result, p, typ, cl)
+    else:
+      var p = p
+      reprAux(result, addr(p), typ, cl)
+    add result, "\n"
+    deinitReprClosure(cl)
+
diff --git a/lib/system/sysio.nim b/lib/system/sysio.nim
index 1dcc2ab3a..e342296c7 100755
--- a/lib/system/sysio.nim
+++ b/lib/system/sysio.nim
@@ -135,14 +135,6 @@ proc open(f: var TFile, filehandle: TFileHandle, mode: TFileMode): bool =
   f = fdopen(filehandle, FormatOpen[mode])
   result = f != nil
 
-proc OpenFile(f: var TFile, filename: string,
-              mode: TFileMode = fmRead,
-              bufSize: int = -1): Bool =
-  result = open(f, filename, mode, bufSize)
-  
-proc openFile(f: var TFile, filehandle: TFileHandle, mode: TFileMode): bool =
-  result = open(f, filehandle, mode)
-
 # C routine that is used here:
 proc fread(buf: Pointer, size, n: int, f: TFile): int {.
   importc: "fread", noDecl.}
diff --git a/lib/system/sysstr.nim b/lib/system/sysstr.nim
index 20a49093b..41efdf431 100755
--- a/lib/system/sysstr.nim
+++ b/lib/system/sysstr.nim
@@ -1,7 +1,7 @@
 #
 #
 #            Nimrod's Runtime Library
-#        (c) Copyright 2009 Andreas Rumpf
+#        (c) Copyright 2010 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -88,7 +88,8 @@ proc copyStrLast(s: NimString, start, last: int): NimString {.exportc.} =
 proc copyStr(s: NimString, start: int): NimString {.exportc.} =
   return copyStrLast(s, start, s.len-1)
 
-proc addChar(s: NimString, c: char): NimString {.compilerProc.} =
+proc addChar(s: NimString, c: char): NimString =
+  # is compilerproc!
   result = s
   if result.len >= result.space:
     result.space = resize(result.space)
@@ -196,7 +197,7 @@ proc incrSeq(seq: PGenericSeq, elemSize: int): PGenericSeq {.compilerProc.} =
     inc(result.len)
 
 proc setLengthSeq(seq: PGenericSeq, elemSize, newLen: int): PGenericSeq {.
-    compilerProc.} =
+    compilerRtl.} =
   when false:
     # broken version:
     result = seq
@@ -223,7 +224,7 @@ proc setLengthSeq(seq: PGenericSeq, elemSize, newLen: int): PGenericSeq {.
     result.len = newLen
 
 # --------------- other string routines ----------------------------------
-proc nimIntToStr(x: int): string {.compilerproc.} =
+proc nimIntToStr(x: int): string {.compilerRtl.} =
   result = newString(sizeof(x)*4)
   var i = 0
   var y = x
@@ -246,7 +247,7 @@ proc nimFloatToStr(x: float): string {.compilerproc.} =
   c_sprintf(buf, "%#g", x)
   return $buf
 
-proc nimInt64ToStr(x: int64): string {.compilerproc.} =
+proc nimInt64ToStr(x: int64): string {.compilerRtl.} =
   # we don't rely on C's runtime here as some C compiler's
   # int64 support is weak
   result = newString(sizeof(x)*4)
diff --git a/rod/c2nim/cparse.nim b/rod/c2nim/cparse.nim
index 5da9f3015..28cad2805 100755
--- a/rod/c2nim/cparse.nim
+++ b/rod/c2nim/cparse.nim
@@ -530,11 +530,10 @@ proc structPragmas(p: TParser, name: PNode, origName: string): PNode =
   result = newNodeP(nkPragmaExpr, p)
   addson(result, exportSym(p, name))
   var pragmas = newNodep(nkPragma, p)
-  addSon(pragmas, newIdentNodeP("pure", p))
-  addSon(pragmas, newIdentNodeP("final", p))
+  addSon(pragmas, newIdentNodeP("pure", p), newIdentNodeP("final", p))
   if p.options.header.len > 0:
-    addSon(pragmas, newIdentStrLitPair("importc", origName, p))
-    addSon(pragmas, newIdentStrLitPair("header", p.options.header, p))
+    addSon(pragmas, newIdentStrLitPair("importc", origName, p),
+                    newIdentStrLitPair("header", p.options.header, p))
   addSon(result, pragmas)
 
 proc enumPragmas(p: TParser, name: PNode): PNode =
@@ -542,15 +541,13 @@ proc enumPragmas(p: TParser, name: PNode): PNode =
   addson(result, name)
   var pragmas = newNodep(nkPragma, p)
   var e = newNodeP(nkExprColonExpr, p)
-  addSon(e, newIdentNodeP("size", p))
-  addSon(e, newIntNodeP(nkIntLit, 4, p))
+  addSon(e, newIdentNodeP("size", p), newIntNodeP(nkIntLit, 4, p))
   addSon(pragmas, e)
   addSon(result, pragmas)
 
 proc parseStruct(p: var TParser, isUnion: bool): PNode = 
   result = newNodeP(nkObjectTy, p)
-  addSon(result, nil) # no pragmas
-  addSon(result, nil) # no inheritance
+  addSon(result, nil, nil) # no pragmas, no inheritance 
   if p.tok.xkind == pxCurlyLe:
     addSon(result, parseStructBody(p, isUnion))
   else: 
@@ -569,8 +566,7 @@ proc parseParam(p: var TParser, params: PNode) =
     name = newIdentNodeP("a" & $idx, p)
   typ = parseTypeSuffix(p, typ)
   var x = newNodeP(nkIdentDefs, p)
-  addSon(x, name)
-  addSon(x, typ)
+  addSon(x, name, typ)
   if p.tok.xkind == pxAsgn: 
     # we support default parameters for C++:
     getTok(p, x)
@@ -621,15 +617,11 @@ proc parseFunctionPointerDecl(p: var TParser, rettyp: PNode): PNode =
   if p.inTypeDef == 0:
     result = newNodeP(nkVarSection, p)
     var def = newNodeP(nkIdentDefs, p)
-    addSon(def, name)
-    addSon(def, procType)
-    addSon(def, nil)
+    addSon(def, name, procType, nil)
     addSon(result, def)    
   else:
     result = newNodeP(nkTypeDef, p)
-    addSon(result, name)
-    addSon(result, nil) # no generics
-    addSon(result, procType)
+    addSon(result, name, nil, procType)
   
 proc addTypeDef(section, name, t: PNode) = 
   var def = newNodeI(nkTypeDef, name.info)
@@ -674,8 +666,7 @@ proc enumFields(p: var TParser): PNode =
       var c = constantExpression(p)
       var a = e
       e = newNodeP(nkEnumFieldDef, p)
-      addSon(e, a)
-      addSon(e, c)
+      addSon(e, a, c)
       skipCom(p, e)
     
     addSon(result, e)
@@ -871,10 +862,8 @@ proc declaration(p: var TParser): PNode =
       addSon(pragmas, newIdentNodeP("cdecl", p))
     elif pfStdcall in p.options.flags:
       addSon(pragmas, newIdentNodeP("stdcall", p))
-    addSon(result, exportSym(p, name))
-    addSon(result, nil) # no generics
-    addSon(result, params)
-    addSon(result, pragmas)
+    addSon(result, exportSym(p, name), nil) # no generics
+    addSon(result, params, pragmas)
     case p.tok.xkind 
     of pxSemicolon: 
       getTok(p)
@@ -1175,17 +1164,14 @@ proc asgnExpr(p: var TParser, opr: string, a: PNode): PNode =
   getTok(p, a)
   var b = assignmentExpression(p)
   result = newNodeP(nkAsgn, p)
-  addSon(result, a)
-  addSon(result, newBinary(opr, copyTree(a), b, p))
+  addSon(result, a, newBinary(opr, copyTree(a), b, p))
   
 proc incdec(p: var TParser, opr: string, a: PNode): PNode =
   closeContext(p)
   getTok(p, a)
   var b = assignmentExpression(p)
   result = newNodeP(nkCall, p)
-  addSon(result, newIdentNodeP(getIdent(opr), p))
-  addSon(result, a)
-  addSon(result, b)
+  addSon(result, newIdentNodeP(getIdent(opr), p), a, b)
   
 proc assignmentExpression(p: var TParser): PNode = 
   saveContext(p)
@@ -1196,8 +1182,7 @@ proc assignmentExpression(p: var TParser): PNode =
     getTok(p, a)
     var b = assignmentExpression(p)
     result = newNodeP(nkAsgn, p)
-    addSon(result, a)
-    addSon(result, b)
+    addSon(result, a, b)
   of pxPlusAsgn: result = incDec(p, "inc", a)    
   of pxMinusAsgn: result = incDec(p, "dec", a)
   of pxStarAsgn: result = asgnExpr(p, "*", a)
@@ -1291,8 +1276,7 @@ proc conditionalExpression(p: var TParser): PNode =
     var c = conditionalExpression(p)
     result = newNodeP(nkIfExpr, p)
     var branch = newNodeP(nkElifExpr, p)
-    addSon(branch, a)
-    addSon(branch, b)
+    addSon(branch, a, b)
     addSon(result, branch)
     branch = newNodeP(nkElseExpr, p)
     addSon(branch, c)
diff --git a/rod/c2nim/manual.txt b/rod/c2nim/manual.txt
index bb89c9567..bb89c9567 100644..100755
--- a/rod/c2nim/manual.txt
+++ b/rod/c2nim/manual.txt
diff --git a/rod/c2nim/tests/systest.c b/rod/c2nim/tests/systest.c
index b2b7646bb..b2b7646bb 100644..100755
--- a/rod/c2nim/tests/systest.c
+++ b/rod/c2nim/tests/systest.c
diff --git a/rod/c2nim/tests/systest2.c b/rod/c2nim/tests/systest2.c
index bf3027cfc..bf3027cfc 100644..100755
--- a/rod/c2nim/tests/systest2.c
+++ b/rod/c2nim/tests/systest2.c
diff --git a/rod/ccgexprs.nim b/rod/ccgexprs.nim
index 1e39508d9..88599f8f4 100755
--- a/rod/ccgexprs.nim
+++ b/rod/ccgexprs.nim
@@ -1,7 +1,7 @@
 #
 #
 #           The Nimrod Compiler
-#        (c) Copyright 2009 Andreas Rumpf
+#        (c) Copyright 2010 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -33,7 +33,7 @@ proc genHexLiteral(v: PNode): PRope =
   result = intLiteral(v.intVal)
 
 proc getStrLit(m: BModule, s: string): PRope =
-  useMagic(m, "TGenericSeq")
+  discard cgsym(m, "TGenericSeq")
   result = con("TMP", toRope(getID()))
   appf(m.s[cfsData], "STRING_LITERAL($1, $2, $3);$n",
        [result, makeCString(s), ToRope(len(s))])
@@ -69,10 +69,10 @@ proc genLiteral(p: BProc, v: PNode, ty: PType): PRope =
       var id = NodeTableTestOrSet(p.module.dataCache, v, gid)
       if id == gid:
         # string literal not found in the cache:
-        useMagic(p.module, "NimStringDesc")
-        result = ropef("((NimStringDesc*) &$1)", [getStrLit(p.module, v.strVal)])
+        result = ropecg(p.module, "((#NimStringDesc*) &$1)", 
+                        [getStrLit(p.module, v.strVal)])
       else:
-        result = ropef("((NimStringDesc*) &TMP$1)", [toRope(id)])
+        result = ropecg(p.module, "((#NimStringDesc*) &TMP$1)", [toRope(id)])
     else:
       result = makeCString(v.strVal)
   of nkFloatLit..nkFloat64Lit:
@@ -119,13 +119,11 @@ proc genRawSetData(cs: TBitSet, size: int): PRope =
     #  result := toRope('0x' + ToHex(bitSetToWord(cs, size), size * 2))
 
 proc genSetNode(p: BProc, n: PNode): PRope =
-  var
-    cs: TBitSet
-    size, id: int
-  size = int(getSize(n.typ))
+  var cs: TBitSet
+  var size = int(getSize(n.typ))
   toBitSet(n, cs)
   if size > 8:
-    id = NodeTableTestOrSet(p.module.dataCache, n, gid)
+    var id = NodeTableTestOrSet(p.module.dataCache, n, gid)
     result = con("TMP", toRope(id))
     if id == gid:
       # not found in cache:
@@ -201,16 +199,13 @@ proc genRefAssign(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
     #    end;
     #    appf(p.s[cpsStmts], '$1 = $2;$n', [rdLoc(dest), rdLoc(src)]);
     if canFormAcycle(dest.t):
-      UseMagic(p.module, "asgnRef")
-      appf(p.s[cpsStmts], "asgnRef((void**) $1, $2);$n",
+      appcg(p.module, p.s[cpsStmts], "#asgnRef((void**) $1, $2);$n",
            [addrLoc(dest), rdLoc(src)])
     else:
-      UseMagic(p.module, "asgnRefNoCycle")
-      appf(p.s[cpsStmts], "asgnRefNoCycle((void**) $1, $2);$n",
+      appcg(p.module, p.s[cpsStmts], "#asgnRefNoCycle((void**) $1, $2);$n",
            [addrLoc(dest), rdLoc(src)])
   else:
-    UseMagic(p.module, "unsureAsgnRef")
-    appf(p.s[cpsStmts], "unsureAsgnRef((void**) $1, $2);$n",
+    appcg(p.module, p.s[cpsStmts], "#unsureAsgnRef((void**) $1, $2);$n",
          [addrLoc(dest), rdLoc(src)])
 
 proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
@@ -224,70 +219,60 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
     if not (needToCopy in flags):
       genRefAssign(p, dest, src, flags)
     else:
-      useMagic(p.module, "genericSeqAssign") # BUGFIX
-      appf(p.s[cpsStmts], "genericSeqAssign($1, $2, $3);$n",
+      appcg(p, cpsStmts, "#genericSeqAssign($1, $2, $3);$n",
            [addrLoc(dest), rdLoc(src), genTypeInfo(p.module, dest.t)])
   of tyString:
     if not (needToCopy in flags):
       genRefAssign(p, dest, src, flags)
     else:
-      useMagic(p.module, "copyString")
       if (dest.s == OnStack) or not (optRefcGC in gGlobalOptions):
-        appf(p.s[cpsStmts], "$1 = copyString($2);$n", [rdLoc(dest), rdLoc(src)])
+        appcg(p, cpsStmts, "$1 = #copyString($2);$n", [rdLoc(dest), rdLoc(src)])
       elif dest.s == OnHeap:
-        useMagic(p.module, "asgnRefNoCycle")
-        useMagic(p.module, "copyString") # BUGFIX
-        appf(p.s[cpsStmts], "asgnRefNoCycle((void**) $1, copyString($2));$n",
+        appcg(p, cpsStmts, "#asgnRefNoCycle((void**) $1, #copyString($2));$n",
              [addrLoc(dest), rdLoc(src)])
       else:
-        useMagic(p.module, "unsureAsgnRef")
-        useMagic(p.module, "copyString") # BUGFIX
-        appf(p.s[cpsStmts], "unsureAsgnRef((void**) $1, copyString($2));$n",
+        appcg(p, cpsStmts, "#unsureAsgnRef((void**) $1, #copyString($2));$n",
              [addrLoc(dest), rdLoc(src)])
   of tyTuple:
     if needsComplexAssignment(dest.t):
-      useMagic(p.module, "genericAssign")
-      appf(p.s[cpsStmts], "genericAssign((void*)$1, (void*)$2, $3);$n",
+      appcg(p, cpsStmts, "#genericAssign((void*)$1, (void*)$2, $3);$n",
            [addrLoc(dest), addrLoc(src), genTypeInfo(p.module, dest.t)])
     else:
-      appf(p.s[cpsStmts], "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
+      appcg(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
   of tyArray, tyArrayConstr:
     if needsComplexAssignment(dest.t):
-      useMagic(p.module, "genericAssign")
-      appf(p.s[cpsStmts], "genericAssign((void*)$1, (void*)$2, $3);$n",
+      appcg(p, cpsStmts, "#genericAssign((void*)$1, (void*)$2, $3);$n",
            [addrLoc(dest), addrLoc(src), genTypeInfo(p.module, dest.t)])
     else:
-      appf(p.s[cpsStmts],
+      appcg(p, cpsStmts,
            "memcpy((void*)$1, (NIM_CONST void*)$2, sizeof($1));$n",
            [rdLoc(dest), rdLoc(src)])
   of tyObject:                # XXX: check for subtyping?
     if needsComplexAssignment(dest.t):
-      useMagic(p.module, "genericAssign")
-      appf(p.s[cpsStmts], "genericAssign((void*)$1, (void*)$2, $3);$n",
+      appcg(p, cpsStmts, "#genericAssign((void*)$1, (void*)$2, $3);$n",
            [addrLoc(dest), addrLoc(src), genTypeInfo(p.module, dest.t)])
     else:
-      appf(p.s[cpsStmts], "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
+      appcg(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
   of tyOpenArray:
     # open arrays are always on the stack - really? What if a sequence is
     # passed to an open array?
     if needsComplexAssignment(dest.t):
-      useMagic(p.module, "genericAssignOpenArray")
-      appf(p.s[cpsStmts],     # XXX: is this correct for arrays?
+      appcg(p, cpsStmts,     # XXX: is this correct for arrays?
            "genericAssignOpenArray((void*)$1, (void*)$2, $1Len0, $3);$n",
            [addrLoc(dest), addrLoc(src), genTypeInfo(p.module, dest.t)])
     else:
-      appf(p.s[cpsStmts],
+      appcg(p, cpsStmts,
            "memcpy((void*)$1, (NIM_CONST void*)$2, sizeof($1[0])*$1Len0);$n",
            [rdLoc(dest), rdLoc(src)])
   of tySet:
     if mapType(ty) == ctArray:
-      appf(p.s[cpsStmts], "memcpy((void*)$1, (NIM_CONST void*)$2, $3);$n",
+      appcg(p, cpsStmts, "memcpy((void*)$1, (NIM_CONST void*)$2, $3);$n",
            [rdLoc(dest), rdLoc(src), toRope(getSize(dest.t))])
     else:
-      appf(p.s[cpsStmts], "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
+      appcg(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
   of tyPtr, tyPointer, tyChar, tyBool, tyProc, tyEnum, tyCString,
      tyInt..tyFloat128, tyRange:
-    appf(p.s[cpsStmts], "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
+    appcg(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
   else: InternalError("genAssignment(" & $ty.kind & ')')
 
 proc expr(p: BProc, e: PNode, d: var TLoc)
@@ -303,7 +288,7 @@ proc putLocIntoDest(p: BProc, d: var TLoc, s: TLoc) =
     if lfNoDeepCopy in d.flags: genAssignment(p, d, s, {})
     else: genAssignment(p, d, s, {needToCopy})
   else:
-    d = s                     # ``d`` is free, so fill it with ``s``
+    d = s # ``d`` is free, so fill it with ``s``
 
 proc putIntoDest(p: BProc, d: var TLoc, t: PType, r: PRope) =
   var a: TLoc
@@ -319,60 +304,53 @@ proc putIntoDest(p: BProc, d: var TLoc, t: PType, r: PRope) =
     d.k = locExpr
     d.t = getUniqueType(t)
     d.r = r
-    d.a = - 1
+    d.a = -1
 
-proc binaryStmt(p: BProc, e: PNode, d: var TLoc, magic, frmt: string) =
+proc binaryStmt(p: BProc, e: PNode, d: var TLoc, frmt: string) =
   var a, b: TLoc
-  if (d.k != locNone): InternalError(e.info, "binaryStmt")
-  if magic != "": useMagic(p.module, magic)
+  if d.k != locNone: InternalError(e.info, "binaryStmt")
   InitLocExpr(p, e.sons[1], a)
   InitLocExpr(p, e.sons[2], b)
-  appf(p.s[cpsStmts], frmt, [rdLoc(a), rdLoc(b)])
+  appcg(p, cpsStmts, frmt, [rdLoc(a), rdLoc(b)])
 
-proc unaryStmt(p: BProc, e: PNode, d: var TLoc, magic, frmt: string) =
+proc unaryStmt(p: BProc, e: PNode, d: var TLoc, frmt: string) =
   var a: TLoc
   if (d.k != locNone): InternalError(e.info, "unaryStmt")
-  if magic != "": useMagic(p.module, magic)
   InitLocExpr(p, e.sons[1], a)
-  appf(p.s[cpsStmts], frmt, [rdLoc(a)])
+  appcg(p, cpsStmts, frmt, [rdLoc(a)])
 
-proc binaryStmtChar(p: BProc, e: PNode, d: var TLoc, magic, frmt: string) =
+proc binaryStmtChar(p: BProc, e: PNode, d: var TLoc, frmt: string) =
   var a, b: TLoc
   if (d.k != locNone): InternalError(e.info, "binaryStmtChar")
-  if magic != "": useMagic(p.module, magic)
   InitLocExpr(p, e.sons[1], a)
   InitLocExpr(p, e.sons[2], b)
-  appf(p.s[cpsStmts], frmt, [rdCharLoc(a), rdCharLoc(b)])
+  appcg(p, cpsStmts, frmt, [rdCharLoc(a), rdCharLoc(b)])
 
-proc binaryExpr(p: BProc, e: PNode, d: var TLoc, magic, frmt: string) =
+proc binaryExpr(p: BProc, e: PNode, d: var TLoc, frmt: string) =
   var a, b: TLoc
-  if magic != "": useMagic(p.module, magic)
   assert(e.sons[1].typ != nil)
   assert(e.sons[2].typ != nil)
   InitLocExpr(p, e.sons[1], a)
   InitLocExpr(p, e.sons[2], b)
-  putIntoDest(p, d, e.typ, ropef(frmt, [rdLoc(a), rdLoc(b)]))
+  putIntoDest(p, d, e.typ, ropecg(p.module, frmt, [rdLoc(a), rdLoc(b)]))
 
-proc binaryExprChar(p: BProc, e: PNode, d: var TLoc, magic, frmt: string) =
+proc binaryExprChar(p: BProc, e: PNode, d: var TLoc, frmt: string) =
   var a, b: TLoc
-  if magic != "": useMagic(p.module, magic)
   assert(e.sons[1].typ != nil)
   assert(e.sons[2].typ != nil)
   InitLocExpr(p, e.sons[1], a)
   InitLocExpr(p, e.sons[2], b)
-  putIntoDest(p, d, e.typ, ropef(frmt, [rdCharLoc(a), rdCharLoc(b)]))
+  putIntoDest(p, d, e.typ, ropecg(p.module, frmt, [rdCharLoc(a), rdCharLoc(b)]))
 
-proc unaryExpr(p: BProc, e: PNode, d: var TLoc, magic, frmt: string) =
+proc unaryExpr(p: BProc, e: PNode, d: var TLoc, frmt: string) =
   var a: TLoc
-  if magic != "": useMagic(p.module, magic)
   InitLocExpr(p, e.sons[1], a)
-  putIntoDest(p, d, e.typ, ropef(frmt, [rdLoc(a)]))
+  putIntoDest(p, d, e.typ, ropecg(p.module, frmt, [rdLoc(a)]))
 
-proc unaryExprChar(p: BProc, e: PNode, d: var TLoc, magic, frmt: string) =
+proc unaryExprChar(p: BProc, e: PNode, d: var TLoc, frmt: string) =
   var a: TLoc
-  if magic != "": useMagic(p.module, magic)
   InitLocExpr(p, e.sons[1], a)
-  putIntoDest(p, d, e.typ, ropef(frmt, [rdCharLoc(a)]))
+  putIntoDest(p, d, e.typ, ropecg(p.module, frmt, [rdCharLoc(a)]))
 
 proc binaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
   const
@@ -389,22 +367,19 @@ proc binaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
   var t = skipTypes(e.typ, abstractRange)
   if getSize(t) >= platform.IntSize:
     if optOverflowCheck in p.options:
-      useMagic(p.module, prc[m])
-      putIntoDest(p, d, e.typ,
-                  ropef("$1($2, $3)", [toRope(prc[m]), rdLoc(a), rdLoc(b)]))
+      putIntoDest(p, d, e.typ, ropecg(p.module, 
+                  "#$1($2, $3)", [toRope(prc[m]), rdLoc(a), rdLoc(b)]))
     else:
       putIntoDest(p, d, e.typ, ropef("(NI$4)($2 $1 $3)", [toRope(opr[m]),
           rdLoc(a), rdLoc(b), toRope(getSize(t) * 8)]))
   else:
     if optOverflowCheck in p.options:
-      useMagic(p.module, "raiseOverflow")
       if (m == mModI) or (m == mDivI):
-        useMagic(p.module, "raiseDivByZero")
-        appf(p.s[cpsStmts], "if (!$1) raiseDivByZero();$n", [rdLoc(b)])
+        appcg(p, cpsStmts, "if (!$1) #raiseDivByZero();$n", [rdLoc(b)])
       a.r = ropef("((NI)($2) $1 (NI)($3))", [toRope(opr[m]), rdLoc(a), rdLoc(b)])
       if d.k == locNone: getTemp(p, getSysType(tyInt), d)
       genAssignment(p, d, a, {})
-      appf(p.s[cpsStmts], "if ($1 < $2 || $1 > $3) raiseOverflow();$n",
+      appcg(p, cpsStmts, "if ($1 < $2 || $1 > $3) #raiseOverflow();$n",
            [rdLoc(d), intLiteral(firstOrd(t)), intLiteral(lastOrd(t))])
       d.t = e.typ
       d.r = ropef("(NI$1)($2)", [toRope(getSize(t) * 8), rdLoc(d)])
@@ -425,8 +400,7 @@ proc unaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
   InitLocExpr(p, e.sons[1], a)
   t = skipTypes(e.typ, abstractRange)
   if optOverflowCheck in p.options:
-    useMagic(p.module, "raiseOverflow")
-    appf(p.s[cpsStmts], "if ($1 == $2) raiseOverflow();$n",
+    appcg(p, cpsStmts, "if ($1 == $2) #raiseOverflow();$n",
          [rdLoc(a), intLiteral(firstOrd(t))])
   putIntoDest(p, d, e.typ, ropef(opr[m], [rdLoc(a), toRope(getSize(t) * 8)]))
 
@@ -623,8 +597,6 @@ proc genCheckedRecordField(p: BProc, e: PNode, d: var TLoc) =
     id: int
     it: PNode
   if optFieldCheck in p.options:
-    useMagic(p.module, "raiseFieldError")
-    useMagic(p.module, "NimStringDesc")
     ty = genRecordFieldAux(p, e.sons[0], d, a)
     r = rdLoc(a)
     f = e.sons[0].sons[1].sym
@@ -655,12 +627,12 @@ proc genCheckedRecordField(p: BProc, e: PNode, d: var TLoc) =
       if id == gid: strLit = getStrLit(p.module, field.name.s)
       else: strLit = con("TMP", toRope(id))
       if op.magic == mNot:
-        appf(p.s[cpsStmts],
-             "if ($1) raiseFieldError(((NimStringDesc*) &$2));$n",
+        appcg(p, cpsStmts,
+             "if ($1) #raiseFieldError(((#NimStringDesc*) &$2));$n",
              [rdLoc(test), strLit])
       else:
-        appf(p.s[cpsStmts],
-             "if (!($1)) raiseFieldError(((NimStringDesc*) &$2));$n",
+        appcg(p, cpsStmts,
+             "if (!($1)) #raiseFieldError(((#NimStringDesc*) &$2));$n",
              [rdLoc(test), strLit])
     appf(r, ".$1", [field.loc.r])
     putIntoDest(p, d, field.typ, r)
@@ -677,13 +649,12 @@ proc genArrayElem(p: BProc, e: PNode, d: var TLoc) =
   if (optBoundsCheck in p.options):
     if not isConstExpr(e.sons[1]):
       # semantic pass has already checked for const index expressions
-      useMagic(p.module, "raiseIndexError")
       if firstOrd(ty) == 0:
         if (firstOrd(b.t) < firstOrd(ty)) or (lastOrd(b.t) > lastOrd(ty)):
-          appf(p.s[cpsStmts], "if ((NU)($1) > (NU)($2)) raiseIndexError();$n",
+          appcg(p, cpsStmts, "if ((NU)($1) > (NU)($2)) #raiseIndexError();$n",
                [rdCharLoc(b), intLiteral(lastOrd(ty))])
       else:
-        appf(p.s[cpsStmts], "if ($1 < $2 || $1 > $3) raiseIndexError();$n",
+        appcg(p, cpsStmts, "if ($1 < $2 || $1 > $3) #raiseIndexError();$n",
              [rdCharLoc(b), first, intLiteral(lastOrd(ty))])
   if d.k == locNone: d.s = a.s
   putIntoDest(p, d, elemType(skipTypes(ty, abstractVar)),
@@ -703,8 +674,7 @@ proc genOpenArrayElem(p: BProc, e: PNode, d: var TLoc) =
   initLocExpr(p, e.sons[0], a)
   initLocExpr(p, e.sons[1], b) # emit range check:
   if (optBoundsCheck in p.options):
-    useMagic(p.module, "raiseIndexError")
-    appf(p.s[cpsStmts], "if ((NU)($1) >= (NU)($2Len0)) raiseIndexError();$n",
+    appcg(p, cpsStmts, "if ((NU)($1) >= (NU)($2Len0)) #raiseIndexError();$n",
          [rdLoc(b), rdLoc(a)]) # BUGFIX: ``>=`` and not ``>``!
   if d.k == locNone: d.s = a.s
   putIntoDest(p, d, elemType(skipTypes(a.t, abstractVar)),
@@ -718,14 +688,13 @@ proc genSeqElem(p: BPRoc, e: PNode, d: var TLoc) =
   if ty.kind in {tyRef, tyPtr}:
     ty = skipTypes(ty.sons[0], abstractVarRange) # emit range check:
   if (optBoundsCheck in p.options):
-    useMagic(p.module, "raiseIndexError")
     if ty.kind == tyString:
-      appf(p.s[cpsStmts],
-           "if ((NU)($1) > (NU)($2->Sup.len)) raiseIndexError();$n",
+      appcg(p, cpsStmts,
+           "if ((NU)($1) > (NU)($2->Sup.len)) #raiseIndexError();$n",
            [rdLoc(b), rdLoc(a)])
     else:
-      appf(p.s[cpsStmts],
-           "if ((NU)($1) >= (NU)($2->Sup.len)) raiseIndexError();$n",
+      appcg(p, cpsStmts,
+           "if ((NU)($1) >= (NU)($2->Sup.len)) #raiseIndexError();$n",
            [rdLoc(b), rdLoc(a)])
   if d.k == locNone: d.s = OnHeap
   if skipTypes(a.t, abstractVar).kind in {tyRef, tyPtr}:
@@ -811,12 +780,10 @@ proc genIfExpr(p: BProc, n: PNode, d: var TLoc) =
 
 proc genEcho(p: BProc, n: PNode) =
   var a: TLoc
-  useMagic(p.module, "rawEcho")
-  useMagic(p.module, "rawEchoNL")
   for i in countup(1, sonsLen(n) - 1):
     initLocExpr(p, n.sons[i], a)
-    appf(p.s[cpsStmts], "rawEcho($1);$n", [rdLoc(a)])
-  app(p.s[cpsStmts], "rawEchoNL();" & tnl)
+    appcg(p, cpsStmts, "#rawEcho($1);$n", [rdLoc(a)])
+  appcg(p, cpsStmts, "#rawEchoNL();$n")
 
 proc genCall(p: BProc, t: PNode, d: var TLoc) =
   var
@@ -879,7 +846,6 @@ proc genStrConcat(p: BProc, e: PNode, d: var TLoc) =
   #    asgn(s, tmp0);
   #  }
   var a, tmp: TLoc
-  useMagic(p.module, "rawNewString")
   getTemp(p, e.typ, tmp)
   var L = 0
   var appends: PRope = nil
@@ -889,16 +855,14 @@ proc genStrConcat(p: BProc, e: PNode, d: var TLoc) =
     initLocExpr(p, e.sons[i + 1], a)
     if skipTypes(e.sons[i + 1].Typ, abstractVarRange).kind == tyChar:
       Inc(L)
-      useMagic(p.module, "appendChar")
-      appf(appends, "appendChar($1, $2);$n", [tmp.r, rdLoc(a)])
+      appcg(p.module, appends, "#appendChar($1, $2);$n", [tmp.r, rdLoc(a)])
     else:
       if e.sons[i + 1].kind in {nkStrLit..nkTripleStrLit}:
         Inc(L, len(e.sons[i + 1].strVal))
       else:
         appf(lens, "$1->Sup.len + ", [rdLoc(a)])
-      useMagic(p.module, "appendString")
-      appf(appends, "appendString($1, $2);$n", [tmp.r, rdLoc(a)])
-  appf(p.s[cpsStmts], "$1 = rawNewString($2$3);$n", [tmp.r, lens, toRope(L)])
+      appcg(p.module, appends, "#appendString($1, $2);$n", [tmp.r, rdLoc(a)])
+  appcg(p, cpsStmts, "$1 = #rawNewString($2$3);$n", [tmp.r, lens, toRope(L)])
   app(p.s[cpsStmts], appends)
   if d.k == locNone:
     d = tmp
@@ -922,7 +886,6 @@ proc genStrAppend(p: BProc, e: PNode, d: var TLoc) =
     L: int
     appends, lens: PRope
   assert(d.k == locNone)
-  useMagic(p.module, "resizeString")
   L = 0
   appends = nil
   lens = nil
@@ -932,16 +895,16 @@ proc genStrAppend(p: BProc, e: PNode, d: var TLoc) =
     initLocExpr(p, e.sons[i + 2], a)
     if skipTypes(e.sons[i + 2].Typ, abstractVarRange).kind == tyChar:
       Inc(L)
-      useMagic(p.module, "appendChar")
-      appf(appends, "appendChar($1, $2);$n", [rdLoc(dest), rdLoc(a)])
+      appcg(p.module, appends, "#appendChar($1, $2);$n", 
+            [rdLoc(dest), rdLoc(a)])
     else:
       if e.sons[i + 2].kind in {nkStrLit..nkTripleStrLit}:
         Inc(L, len(e.sons[i + 2].strVal))
       else:
         appf(lens, "$1->Sup.len + ", [rdLoc(a)])
-      useMagic(p.module, "appendString")
-      appf(appends, "appendString($1, $2);$n", [rdLoc(dest), rdLoc(a)])
-  appf(p.s[cpsStmts], "$1 = resizeString($1, $2$3);$n",
+      appcg(p.module, appends, "#appendString($1, $2);$n",
+            [rdLoc(dest), rdLoc(a)])
+  appcg(p, cpsStmts, "$1 = #resizeString($1, $2$3);$n",
        [rdLoc(dest), lens, toRope(L)])
   app(p.s[cpsStmts], appends)
 
@@ -950,10 +913,10 @@ proc genSeqElemAppend(p: BProc, e: PNode, d: var TLoc) =
   #    seq = (typeof seq) incrSeq(&seq->Sup, sizeof(x));
   #    seq->data[seq->len-1] = x;
   var a, b, dest: TLoc
-  useMagic(p.module, "incrSeq")
   InitLocExpr(p, e.sons[1], a)
   InitLocExpr(p, e.sons[2], b)
-  appf(p.s[cpsStmts], "$1 = ($2) incrSeq(&($1)->Sup, sizeof($3));$n", [rdLoc(a),
+  appcg(p, cpsStmts, "$1 = ($2) #incrSeq(&($1)->Sup, sizeof($3));$n", [
+      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)
@@ -977,20 +940,19 @@ proc genObjectInit(p: BProc, t: PType, a: TLoc, takeAddr: bool) =
     appf(p.s[cpsStmts], "$1.m_type = $2;$n", [r, genTypeInfo(p.module, t)])
   of frEmbedded:
     # worst case for performance:
-    useMagic(p.module, "objectInit")
     if takeAddr: r = addrLoc(a)
     else: r = rdLoc(a)
-    appf(p.s[cpsStmts], "objectInit($1, $2);$n", [r, genTypeInfo(p.module, t)])
+    appcg(p, cpsStmts, "#objectInit($1, $2);$n", [r, genTypeInfo(p.module, t)])
 
 proc genNew(p: BProc, e: PNode) =
   var
     a, b: TLoc
     reftype, bt: PType
-  useMagic(p.module, "newObj")
   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),
+  b.r = ropecg(p.module,
+      "($1) #newObj($2, sizeof($3))", [getTypeDesc(p.module, reftype),
       genTypeInfo(p.module, refType),
       getTypeDesc(p.module, skipTypes(reftype.sons[0], abstractRange))])
   genAssignment(p, a, b, {})  # set the object type:
@@ -1001,13 +963,13 @@ proc genNewSeq(p: BProc, e: PNode) =
   var
     a, b, c: TLoc
     seqtype: PType
-  useMagic(p.module, "newSeq")
   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)
-  c.r = ropef("($1) newSeq($2, $3)", [getTypeDesc(p.module, seqtype),
-                                      genTypeInfo(p.module, seqType), rdLoc(b)])
+  c.r = ropecg(p.module, "($1) #newSeq($2, $3)", [
+               getTypeDesc(p.module, seqtype),
+               genTypeInfo(p.module, seqType), rdLoc(b)])
   genAssignment(p, a, c, {})
 
 proc genIs(p: BProc, x: PNode, typ: PType, d: var TLoc) =
@@ -1017,7 +979,6 @@ proc genIs(p: BProc, x: PNode, typ: PType, d: var TLoc) =
     r, nilcheck: PRope
   initLocExpr(p, x, a)
   dest = skipTypes(typ, abstractPtrs)
-  useMagic(p.module, "isObj")
   r = rdLoc(a)
   nilCheck = nil
   t = skipTypes(a.t, abstractInst)
@@ -1030,10 +991,10 @@ proc genIs(p: BProc, x: PNode, typ: PType, d: var TLoc) =
       app(r, ".Sup")
       t = skipTypes(t.sons[0], abstractInst)
   if nilCheck != nil:
-    r = ropef("(($1) && isObj($2.m_type, $3))",
+    r = ropecg(p.module, "(($1) && #isObj($2.m_type, $3))",
               [nilCheck, r, genTypeInfo(p.module, dest)])
   else:
-    r = ropef("isObj($1.m_type, $2)", [r, genTypeInfo(p.module, dest)])
+    r = ropecg(p.module, "#isObj($1.m_type, $2)", [r, genTypeInfo(p.module, dest)])
   putIntoDest(p, d, getSysType(tyBool), r)
 
 proc genIs(p: BProc, n: PNode, d: var TLoc) =
@@ -1045,7 +1006,6 @@ proc genNewFinalize(p: BProc, e: PNode) =
     refType, bt: PType
     ti: PRope
     oldModule: BModule
-  useMagic(p.module, "newObj")
   refType = skipTypes(e.sons[1].typ, abstractVarRange)
   InitLocExpr(p, e.sons[1], a)
   # This is a little hack:
@@ -1057,7 +1017,8 @@ proc genNewFinalize(p: BProc, e: PNode) =
   initLoc(b, locExpr, a.t, OnHeap)
   ti = genTypeInfo(p.module, refType)
   appf(gNimDat.s[cfsTypeInit3], "$1->finalizer = (void*)$2;$n", [ti, rdLoc(f)])
-  b.r = ropef("($1) newObj($2, sizeof($3))", [getTypeDesc(p.module, refType),
+  b.r = ropecg(p.module, "($1) #newObj($2, sizeof($3))", [
+      getTypeDesc(p.module, refType),
       ti, getTypeDesc(p.module, skipTypes(reftype.sons[0], abstractRange))])
   genAssignment(p, a, b, {})  # set the object type:
   bt = skipTypes(refType.sons[0], abstractRange)
@@ -1069,30 +1030,23 @@ proc genRepr(p: BProc, e: PNode, d: var TLoc) =
   var t = skipTypes(e.sons[1].typ, abstractVarRange)
   case t.kind
   of tyInt..tyInt64:
-    UseMagic(p.module, "reprInt")
-    putIntoDest(p, d, e.typ, ropef("reprInt($1)", [rdLoc(a)]))
+    putIntoDest(p, d, e.typ, ropecg(p.module, "#reprInt($1)", [rdLoc(a)]))
   of tyFloat..tyFloat128:
-    UseMagic(p.module, "reprFloat")
-    putIntoDest(p, d, e.typ, ropef("reprFloat($1)", [rdLoc(a)]))
+    putIntoDest(p, d, e.typ, ropecg(p.module, "#reprFloat($1)", [rdLoc(a)]))
   of tyBool:
-    UseMagic(p.module, "reprBool")
-    putIntoDest(p, d, e.typ, ropef("reprBool($1)", [rdLoc(a)]))
+    putIntoDest(p, d, e.typ, ropecg(p.module, "#reprBool($1)", [rdLoc(a)]))
   of tyChar:
-    UseMagic(p.module, "reprChar")
-    putIntoDest(p, d, e.typ, ropef("reprChar($1)", [rdLoc(a)]))
+    putIntoDest(p, d, e.typ, ropecg(p.module, "#reprChar($1)", [rdLoc(a)]))
   of tyEnum, tyOrdinal:
-    UseMagic(p.module, "reprEnum")
     putIntoDest(p, d, e.typ,
-                ropef("reprEnum($1, $2)", [rdLoc(a), genTypeInfo(p.module, t)]))
+                ropecg(p.module, "#reprEnum($1, $2)", [
+                rdLoc(a), genTypeInfo(p.module, t)]))
   of tyString:
-    UseMagic(p.module, "reprStr")
-    putIntoDest(p, d, e.typ, ropef("reprStr($1)", [rdLoc(a)]))
+    putIntoDest(p, d, e.typ, ropecg(p.module, "#reprStr($1)", [rdLoc(a)]))
   of tySet:
-    useMagic(p.module, "reprSet")
-    putIntoDest(p, d, e.typ,
-                ropef("reprSet($1, $2)", [rdLoc(a), genTypeInfo(p.module, t)]))
+    putIntoDest(p, d, e.typ, ropecg(p.module, "#reprSet($1, $2)", [
+                rdLoc(a), genTypeInfo(p.module, t)]))
   of tyOpenArray:
-    useMagic(p.module, "reprOpenArray")
     var b: TLoc
     case a.t.kind
     of tyOpenArray: putIntoDest(p, b, e.typ, rdLoc(a))
@@ -1102,23 +1056,22 @@ proc genRepr(p: BProc, e: PNode, d: var TLoc) =
       putIntoDest(p, b, e.typ,
                   ropef("$1, $2", [rdLoc(a), toRope(lengthOrd(a.t))]))
     else: InternalError(e.sons[0].info, "genRepr()")
-    putIntoDest(p, d, e.typ, ropef("reprOpenArray($1, $2)", [rdLoc(b),
+    putIntoDest(p, d, e.typ, 
+        ropecg(p.module, "#reprOpenArray($1, $2)", [rdLoc(b),
         genTypeInfo(p.module, elemType(t))]))
   of tyCString, tyArray, tyArrayConstr, tyRef, tyPtr, tyPointer, tyNil,
      tySequence:
-    useMagic(p.module, "reprAny")
     putIntoDest(p, d, e.typ,
-                ropef("reprAny($1, $2)", [rdLoc(a), genTypeInfo(p.module, t)]))
+                ropecg(p.module, "#reprAny($1, $2)", [
+                rdLoc(a), genTypeInfo(p.module, t)]))
   else:
-    useMagic(p.module, "reprAny")
-    putIntoDest(p, d, e.typ, ropef("reprAny($1, $2)",
+    putIntoDest(p, d, e.typ, ropecg(p.module, "#reprAny($1, $2)",
                                    [addrLoc(a), genTypeInfo(p.module, t)]))
 
-proc genDollar(p: BProc, n: PNode, d: var TLoc, magic, frmt: string) =
+proc genDollar(p: BProc, n: PNode, d: var TLoc, frmt: string) =
   var a: TLoc
   InitLocExpr(p, n.sons[1], a)
-  UseMagic(p.module, magic)
-  a.r = ropef(frmt, [rdLoc(a)])
+  a.r = ropecg(p.module, frmt, [rdLoc(a)])
   if d.k == locNone: getTemp(p, n.typ, d)
   genAssignment(p, d, a, {})
 
@@ -1127,14 +1080,14 @@ proc genArrayLen(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
   case typ.kind
   of tyOpenArray:
     while e.sons[1].kind == nkPassAsOpenArray: e.sons[1] = e.sons[1].sons[0]
-    if op == mHigh: unaryExpr(p, e, d, "", "($1Len0-1)")
-    else: unaryExpr(p, e, d, "", "$1Len0")
+    if op == mHigh: unaryExpr(p, e, d, "($1Len0-1)")
+    else: unaryExpr(p, e, d, "$1Len0")
   of tyCstring:
-    if op == mHigh: unaryExpr(p, e, d, "", "(strlen($1)-1)")
-    else: unaryExpr(p, e, d, "", "strlen($1)")
+    if op == mHigh: unaryExpr(p, e, d, "(strlen($1)-1)")
+    else: unaryExpr(p, e, d, "strlen($1)")
   of tyString, tySequence:
-    if op == mHigh: unaryExpr(p, e, d, "", "($1->Sup.len-1)")
-    else: unaryExpr(p, e, d, "", "$1->Sup.len")
+    if op == mHigh: unaryExpr(p, e, d, "($1->Sup.len-1)")
+    else: unaryExpr(p, e, d, "$1->Sup.len")
   of tyArray, tyArrayConstr:
     # YYY: length(sideeffect) is optimized away incorrectly?
     if op == mHigh: putIntoDest(p, d, e.typ, toRope(lastOrd(Typ)))
@@ -1144,16 +1097,15 @@ proc genArrayLen(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
 proc genSetLengthSeq(p: BProc, e: PNode, d: var TLoc) =
   var a, b: TLoc
   assert(d.k == locNone)
-  useMagic(p.module, "setLengthSeq")
   InitLocExpr(p, e.sons[1], a)
   InitLocExpr(p, e.sons[2], b)
   var t = skipTypes(e.sons[1].typ, abstractVar)
-  appf(p.s[cpsStmts], "$1 = ($3) setLengthSeq(&($1)->Sup, sizeof($4), $2);$n", [
+  appcg(p, cpsStmts, "$1 = ($3) #setLengthSeq(&($1)->Sup, sizeof($4), $2);$n", [
       rdLoc(a), rdLoc(b), getTypeDesc(p.module, t),
       getTypeDesc(p.module, t.sons[0])])
 
 proc genSetLengthStr(p: BProc, e: PNode, d: var TLoc) =
-  binaryStmt(p, e, d, "setLengthStr", "$1 = setLengthStr($1, $2);$n")
+  binaryStmt(p, e, d, "$1 = #setLengthStr($1, $2);$n")
 
 proc genSwap(p: BProc, e: PNode, d: var TLoc) =
   # swap(a, b) -->
@@ -1257,15 +1209,15 @@ proc genSetOp(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
       binaryStmtInExcl(p, e, d, "$1 &= ~(1 << ((" & ts & ")($2) % (sizeof(" &
           ts & ")*8)));$n")
     of mCard:
-      if size <= 4: unaryExprChar(p, e, d, "countBits32", "countBits32($1)")
-      else: unaryExprChar(p, e, d, "countBits64", "countBits64($1)")
-    of mLtSet: binaryExprChar(p, e, d, "", "(($1 & ~ $2 ==0)&&($1 != $2))")
-    of mLeSet: binaryExprChar(p, e, d, "", "(($1 & ~ $2)==0)")
-    of mEqSet: binaryExpr(p, e, d, "", "($1 == $2)")
-    of mMulSet: binaryExpr(p, e, d, "", "($1 & $2)")
-    of mPlusSet: binaryExpr(p, e, d, "", "($1 | $2)")
-    of mMinusSet: binaryExpr(p, e, d, "", "($1 & ~ $2)")
-    of mSymDiffSet: binaryExpr(p, e, d, "", "($1 ^ $2)")
+      if size <= 4: unaryExprChar(p, e, d, "#countBits32($1)")
+      else: unaryExprChar(p, e, d, "#countBits64($1)")
+    of mLtSet: binaryExprChar(p, e, d, "(($1 & ~ $2 ==0)&&($1 != $2))")
+    of mLeSet: binaryExprChar(p, e, d, "(($1 & ~ $2)==0)")
+    of mEqSet: binaryExpr(p, e, d, "($1 == $2)")
+    of mMulSet: binaryExpr(p, e, d, "($1 & $2)")
+    of mPlusSet: binaryExpr(p, e, d, "($1 | $2)")
+    of mMinusSet: binaryExpr(p, e, d, "($1 & ~ $2)")
+    of mSymDiffSet: binaryExpr(p, e, d, "($1 ^ $2)")
     of mInSet:
       genInOp(p, e, d)
     else: internalError(e.info, "genSetOp()")
@@ -1273,7 +1225,7 @@ proc genSetOp(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
     case op
     of mIncl: binaryStmtInExcl(p, e, d, "$1[$2/8] |=(1<<($2%8));$n")
     of mExcl: binaryStmtInExcl(p, e, d, "$1[$2/8] &= ~(1<<($2%8));$n")
-    of mCard: unaryExprChar(p, e, d, "cardSet", "cardSet($1, " & $size & ')')
+    of mCard: unaryExprChar(p, e, d, "#cardSet($1, " & $size & ')')
     of mLtSet, mLeSet:
       getTemp(p, getSysType(tyInt), i) # our counter
       initLocExpr(p, e.sons[1], a)
@@ -1282,7 +1234,7 @@ proc genSetOp(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
       appf(p.s[cpsStmts], lookupOpr[op],
            [rdLoc(i), toRope(size), rdLoc(d), rdLoc(a), rdLoc(b)])
     of mEqSet:
-      binaryExprChar(p, e, d, "", "(memcmp($1, $2, " & $(size) & ")==0)")
+      binaryExprChar(p, e, d, "(memcmp($1, $2, " & $(size) & ")==0)")
     of mMulSet, mPlusSet, mMinusSet, mSymDiffSet:
       # we inline the simple for loop for better code generation:
       getTemp(p, getSysType(tyInt), i) # our counter
@@ -1297,7 +1249,7 @@ proc genSetOp(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
     else: internalError(e.info, "genSetOp")
 
 proc genOrd(p: BProc, e: PNode, d: var TLoc) =
-  unaryExprChar(p, e, d, "", "$1")
+  unaryExprChar(p, e, d, "$1")
 
 proc genCast(p: BProc, e: PNode, d: var TLoc) =
   const
@@ -1317,14 +1269,13 @@ proc genCast(p: BProc, e: PNode, d: var TLoc) =
 proc genRangeChck(p: BProc, n: PNode, d: var TLoc, magic: string) =
   var a: TLoc
   var dest = skipTypes(n.typ, abstractVar)
-  if not (optRangeCheck in p.options):
+  if optRangeCheck notin p.options:
     InitLocExpr(p, n.sons[0], a)
     putIntoDest(p, d, n.typ, ropef("(($1) ($2))",
                                    [getTypeDesc(p.module, dest), rdCharLoc(a)]))
   else:
     InitLocExpr(p, n.sons[0], a)
-    useMagic(p.module, magic)
-    putIntoDest(p, d, dest, ropef("(($1)$5($2, $3, $4))", [
+    putIntoDest(p, d, dest, ropecg(p.module, "(($1)#$5($2, $3, $4))", [
         getTypeDesc(p.module, dest), rdCharLoc(a),
         genLiteral(p, n.sons[1], dest), genLiteral(p, n.sons[2], dest),
         toRope(magic)]))
@@ -1356,17 +1307,16 @@ proc convStrToCStr(p: BProc, n: PNode, d: var TLoc) =
 
 proc convCStrToStr(p: BProc, n: PNode, d: var TLoc) =
   var a: TLoc
-  useMagic(p.module, "cstrToNimstr")
   initLocExpr(p, n.sons[0], a)
   putIntoDest(p, d, skipTypes(n.typ, abstractVar),
-              ropef("cstrToNimstr($1)", [rdLoc(a)]))
+              ropecg(p.module, "#cstrToNimstr($1)", [rdLoc(a)]))
 
 proc genStrEquals(p: BProc, e: PNode, d: var TLoc) =
   var x: TLoc
   var a = e.sons[1]
   var b = e.sons[2]
   if (a.kind == nkNilLit) or (b.kind == nkNilLit):
-    binaryExpr(p, e, d, "", "($1 == $2)")
+    binaryExpr(p, e, d, "($1 == $2)")
   elif (a.kind in {nkStrLit..nkTripleStrLit}) and (a.strVal == ""):
     initLocExpr(p, e.sons[2], x)
     putIntoDest(p, d, e.typ, ropef("(($1) && ($1)->Sup.len == 0)", [rdLoc(x)]))
@@ -1374,16 +1324,16 @@ proc genStrEquals(p: BProc, e: PNode, d: var TLoc) =
     initLocExpr(p, e.sons[1], x)
     putIntoDest(p, d, e.typ, ropef("(($1) && ($1)->Sup.len == 0)", [rdLoc(x)]))
   else:
-    binaryExpr(p, e, d, "eqStrings", "eqStrings($1, $2)")
+    binaryExpr(p, e, d, "#eqStrings($1, $2)")
 
 proc genSeqConstr(p: BProc, t: PNode, d: var TLoc) =
   var newSeq, arr: TLoc
-  useMagic(p.module, "newSeq")
   if d.k == locNone:
     getTemp(p, t.typ, d)
   # generate call to newSeq before adding the elements per hand:
   initLoc(newSeq, locExpr, t.typ, OnHeap)
-  newSeq.r = ropef("($1) newSeq($2, $3)", [getTypeDesc(p.module, t.typ),
+  newSeq.r = ropecg(p.module, "($1) #newSeq($2, $3)", 
+      [getTypeDesc(p.module, t.typ),
       genTypeInfo(p.module, t.typ), intLiteral(sonsLen(t))])
   genAssignment(p, d, newSeq, {afSrcIsNotNil})
   for i in countup(0, sonsLen(t) - 1):
@@ -1398,13 +1348,13 @@ proc genArrToSeq(p: BProc, t: PNode, d: var TLoc) =
     t.sons[1].typ = t.typ
     genSeqConstr(p, t.sons[1], d)
     return
-  useMagic(p.module, "newSeq")
   if d.k == locNone:
     getTemp(p, t.typ, d)
   # generate call to newSeq before adding the elements per hand:
   var L = int(lengthOrd(t.sons[1].typ))
   initLoc(newSeq, locExpr, t.typ, OnHeap)
-  newSeq.r = ropef("($1) newSeq($2, $3)", [getTypeDesc(p.module, t.typ),
+  newSeq.r = ropecg(p.module, "($1) #newSeq($2, $3)", 
+      [getTypeDesc(p.module, t.typ),
       genTypeInfo(p.module, t.typ), intLiteral(L)])
   genAssignment(p, d, newSeq, {afSrcIsNotNil})
   initLocExpr(p, t.sons[1], a)
@@ -1427,11 +1377,9 @@ proc binaryFloatArith(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
     putIntoDest(p, d, e.typ, ropef("($2 $1 $3)", [
                 toRope(opr[m]), rdLoc(a), rdLoc(b)]))
     if optNanCheck in p.options:
-      useMagic(p.module, "nanCheck")
-      appf(p.s[cpsStmts], "nanCheck($1);$n", [rdLoc(d)])
+      appcg(p, cpsStmts, "#nanCheck($1);$n", [rdLoc(d)])
     if optInfCheck in p.options:
-      useMagic(p.module, "infCheck")
-      appf(p.s[cpsStmts], "infCheck($1);$n", [rdLoc(d)])
+      appcg(p, cpsStmts, "#infCheck($1);$n", [rdLoc(d)])
   else:
     binaryArith(p, e, d, m)
 
@@ -1448,49 +1396,48 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
   of mSwap: genSwap(p, e, d)
   of mPred:
     # XXX: range checking?
-    if not (optOverflowCheck in p.Options): binaryExpr(p, e, d, "", "$1 - $2")
-    else: binaryExpr(p, e, d, "subInt", "subInt($1, $2)")
+    if not (optOverflowCheck in p.Options): binaryExpr(p, e, d, "$1 - $2")
+    else: binaryExpr(p, e, d, "#subInt($1, $2)")
   of mSucc:
     # XXX: range checking?
-    if not (optOverflowCheck in p.Options): binaryExpr(p, e, d, "", "$1 + $2")
-    else: binaryExpr(p, e, d, "addInt", "addInt($1, $2)")
+    if not (optOverflowCheck in p.Options): binaryExpr(p, e, d, "$1 + $2")
+    else: binaryExpr(p, e, d, "#addInt($1, $2)")
   of mInc:
     if not (optOverflowCheck in p.Options):
-      binaryStmt(p, e, d, "", "$1 += $2;$n")
+      binaryStmt(p, e, d, "$1 += $2;$n")
     elif skipTypes(e.sons[1].typ, abstractVar).kind == tyInt64:
-      binaryStmt(p, e, d, "addInt64", "$1 = addInt64($1, $2);$n")
+      binaryStmt(p, e, d, "$1 = #addInt64($1, $2);$n")
     else:
-      binaryStmt(p, e, d, "addInt", "$1 = addInt($1, $2);$n")
+      binaryStmt(p, e, d, "$1 = #addInt($1, $2);$n")
   of ast.mDec:
     if not (optOverflowCheck in p.Options):
-      binaryStmt(p, e, d, "", "$1 -= $2;$n")
+      binaryStmt(p, e, d, "$1 -= $2;$n")
     elif skipTypes(e.sons[1].typ, abstractVar).kind == tyInt64:
-      binaryStmt(p, e, d, "subInt64", "$1 = subInt64($1, $2);$n")
+      binaryStmt(p, e, d, "$1 = #subInt64($1, $2);$n")
     else:
-      binaryStmt(p, e, d, "subInt", "$1 = subInt($1, $2);$n")
+      binaryStmt(p, e, d, "$1 = #subInt($1, $2);$n")
   of mConStrStr: genStrConcat(p, e, d)
-  of mAppendStrCh: binaryStmt(p, e, d, "addChar", "$1 = addChar($1, $2);$n")
+  of mAppendStrCh: binaryStmt(p, e, d, "$1 = #addChar($1, $2);$n")
   of mAppendStrStr: genStrAppend(p, e, d)
   of mAppendSeqElem: genSeqElemAppend(p, e, d)
   of mEqStr: genStrEquals(p, e, d)
-  of mLeStr: binaryExpr(p, e, d, "cmpStrings", "(cmpStrings($1, $2) <= 0)")
-  of mLtStr: binaryExpr(p, e, d, "cmpStrings", "(cmpStrings($1, $2) < 0)")
-  of mIsNil: unaryExpr(p, e, d, "", "$1 == 0")
-  of mIntToStr: genDollar(p, e, d, "nimIntToStr", "nimIntToStr($1)")
-  of mInt64ToStr: genDollar(p, e, d, "nimInt64ToStr", "nimInt64ToStr($1)")
-  of mBoolToStr: genDollar(p, e, d, "nimBoolToStr", "nimBoolToStr($1)")
-  of mCharToStr: genDollar(p, e, d, "nimCharToStr", "nimCharToStr($1)")
-  of mFloatToStr: genDollar(p, e, d, "nimFloatToStr", "nimFloatToStr($1)")
-  of mCStrToStr: genDollar(p, e, d, "cstrToNimstr", "cstrToNimstr($1)")
+  of mLeStr: binaryExpr(p, e, d, "(#cmpStrings($1, $2) <= 0)")
+  of mLtStr: binaryExpr(p, e, d, "(#cmpStrings($1, $2) < 0)")
+  of mIsNil: unaryExpr(p, e, d, "$1 == 0")
+  of mIntToStr: genDollar(p, e, d, "#nimIntToStr($1)")
+  of mInt64ToStr: genDollar(p, e, d, "#nimInt64ToStr($1)")
+  of mBoolToStr: genDollar(p, e, d, "#nimBoolToStr($1)")
+  of mCharToStr: genDollar(p, e, d, "#nimCharToStr($1)")
+  of mFloatToStr: genDollar(p, e, d, "#nimFloatToStr($1)")
+  of mCStrToStr: genDollar(p, e, d, "#cstrToNimstr($1)")
   of mStrToStr: expr(p, e.sons[1], d)
   of mEnumToStr: genRepr(p, e, d)
   of mAssert:
     if (optAssert in p.Options):
-      useMagic(p.module, "internalAssert")
       expr(p, e.sons[1], d)
       line = toRope(toLinenumber(e.info))
       filen = makeCString(ToFilename(e.info))
-      appf(p.s[cpsStmts], "internalAssert($1, $2, $3);$n",
+      appcg(p, cpsStmts, "#internalAssert($1, $2, $3);$n",
            [filen, line, rdLoc(d)])
   of mIs: genIs(p, e, d)
   of mNew: genNew(p, e)
@@ -1503,8 +1450,8 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
   of mOrd: genOrd(p, e, d)
   of mLengthArray, mHigh, mLengthStr, mLengthSeq, mLengthOpenArray:
     genArrayLen(p, e, d, op)
-  of mGCref: unaryStmt(p, e, d, "nimGCref", "nimGCref($1);$n")
-  of mGCunref: unaryStmt(p, e, d, "nimGCunref", "nimGCunref($1);$n")
+  of mGCref: unaryStmt(p, e, d, "#nimGCref($1);$n")
+  of mGCunref: unaryStmt(p, e, d, "#nimGCunref($1);$n")
   of mSetLengthStr: genSetLengthStr(p, e, d)
   of mSetLengthSeq: genSetLengthSeq(p, e, d)
   of mIncl, mExcl, mCard, mLtSet, mLeSet, mEqSet, mMulSet, mPlusSet, mMinusSet,
@@ -1632,7 +1579,6 @@ proc upConv(p: BProc, n: PNode, d: var TLoc) =
   initLocExpr(p, n.sons[0], a)
   dest = skipTypes(n.typ, abstractPtrs)
   if (optObjCheck in p.options) and not (isPureObject(dest)):
-    useMagic(p.module, "chckObj")
     r = rdLoc(a)
     nilCheck = nil
     t = skipTypes(a.t, abstractInst)
@@ -1645,10 +1591,10 @@ proc upConv(p: BProc, n: PNode, d: var TLoc) =
         app(r, ".Sup")
         t = skipTypes(t.sons[0], abstractInst)
     if nilCheck != nil:
-      appf(p.s[cpsStmts], "if ($1) chckObj($2.m_type, $3);$n",
+      appcg(p, cpsStmts, "if ($1) #chckObj($2.m_type, $3);$n",
            [nilCheck, r, genTypeInfo(p.module, dest)])
     else:
-      appf(p.s[cpsStmts], "chckObj($1.m_type, $2);$n",
+      appcg(p, cpsStmts, "#chckObj($1.m_type, $2);$n",
            [r, genTypeInfo(p.module, dest)])
   if n.sons[0].typ.kind != tyObject:
     putIntoDest(p, d, n.typ,
diff --git a/rod/ccgstmts.nim b/rod/ccgstmts.nim
index 78ef4f24f..9171b5fb8 100755
--- a/rod/ccgstmts.nim
+++ b/rod/ccgstmts.nim
@@ -1,7 +1,7 @@
 #
 #
 #           The Nimrod Compiler
-#        (c) Copyright 2009 Andreas Rumpf
+#        (c) Copyright 2010 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -20,9 +20,7 @@ proc genLineDir(p: BProc, t: PNode) =
           [toRope(toFilename(t.info)), toRope(line)])
   if ({optStackTrace, optEndb} * p.Options == {optStackTrace, optEndb}) and
       ((p.prc == nil) or not (sfPure in p.prc.flags)): 
-    useMagic(p.module, "endb") # new: endb support
-    appff(p.s[cpsStmts], "endb($1);$n", "call void @endb(%NI $1)$n", 
-          [toRope(line)])
+    appcg(p, cpsStmts, "#endb($1);$n", [toRope(line)])
   elif ({optLineTrace, optStackTrace} * p.Options ==
       {optLineTrace, optStackTrace}) and
       ((p.prc == nil) or not (sfPure in p.prc.flags)): 
@@ -262,27 +260,24 @@ proc genAsmStmt(p: BProc, t: PNode) =
 
 proc getRaiseFrmt(p: BProc): string = 
   if gCmd == cmdCompileToCpp: 
-    result = "throw nimException($1, $2);$n"
+    result = "throw #nimException($1, $2);$n"
   else: 
-    useMagic(p.module, "E_Base")
-    result = "raiseException((E_Base*)$1, $2);$n"
+    result = "#raiseException((#E_Base*)$1, $2);$n"
 
 proc genRaiseStmt(p: BProc, t: PNode) = 
   genLineDir(p, t)
   if t.sons[0] != nil: 
-    if gCmd != cmdCompileToCpp: useMagic(p.module, "raiseException")
     var a: TLoc
     InitLocExpr(p, t.sons[0], a)
     var e = rdLoc(a)
     var typ = skipTypes(t.sons[0].typ, abstractPtrs)
-    appf(p.s[cpsStmts], getRaiseFrmt(p), [e, makeCString(typ.sym.name.s)])
+    appcg(p, cpsStmts, getRaiseFrmt(p), [e, makeCString(typ.sym.name.s)])
   else: 
     # reraise the last exception:
     if gCmd == cmdCompileToCpp: 
-      app(p.s[cpsStmts], "throw;" & tnl)
+      appcg(p, cpsStmts, "throw;" & tnl)
     else: 
-      useMagic(p.module, "reraiseException")
-      app(p.s[cpsStmts], "reraiseException();" & tnl)
+      appcg(p, cpsStmts, "#reraiseException();" & tnl)
 
 const 
   stringCaseThreshold = 100000 
@@ -300,11 +295,11 @@ proc genCaseGenericBranch(p: BProc, b: PNode, e: TLoc,
     if b.sons[i].kind == nkRange: 
       initLocExpr(p, b.sons[i].sons[0], x)
       initLocExpr(p, b.sons[i].sons[1], y)
-      appf(p.s[cpsStmts], rangeFormat, 
+      appcg(p, cpsStmts, rangeFormat, 
            [rdCharLoc(e), rdCharLoc(x), rdCharLoc(y), labl])
     else: 
       initLocExpr(p, b.sons[i], x)
-      appf(p.s[cpsStmts], eqFormat, [rdCharLoc(e), rdCharLoc(x), labl])
+      appcg(p, cpsStmts, eqFormat, [rdCharLoc(e), rdCharLoc(x), labl])
 
 proc genCaseSecondPass(p: BProc, t: PNode, labId: int) = 
   var Lend = getLabel(p)
@@ -373,7 +368,7 @@ proc genCaseStringBranch(p: BProc, b: PNode, e: TLoc, labl: TLabel,
     initLocExpr(p, b.sons[i], x)
     assert(b.sons[i].kind in {nkStrLit..nkTripleStrLit})
     j = int(hashString(b.sons[i].strVal) and high(branches))
-    appf(branches[j], "if (eqStrings($1, $2)) goto $3;$n", 
+    appcg(p.module, branches[j], "if (#eqStrings($1, $2)) goto $3;$n", 
          [rdLoc(e), rdLoc(x), labl])
 
 proc genStringCase(p: BProc, t: PNode) = 
@@ -381,13 +376,11 @@ proc genStringCase(p: BProc, t: PNode) =
     strings, bitMask, labId: int
     a: TLoc
     branches: TRopeSeq
-  useMagic(p.module, "eqStrings") 
   # count how many constant strings there are in the case:
   strings = 0
   for i in countup(1, sonsLen(t) - 1): 
     if t.sons[i].kind == nkOfBranch: inc(strings, sonsLen(t.sons[i]) - 1)
   if strings > stringCaseThreshold: 
-    useMagic(p.module, "hashString")
     bitMask = math.nextPowerOfTwo(strings) - 1
     newSeq(branches, bitMask + 1)
     initLocExpr(p, t.sons[0], a) # fist pass: gnerate ifs+goto:
@@ -400,7 +393,7 @@ proc genStringCase(p: BProc, t: PNode) =
       else: 
         # else statement: nothing to do yet
         # but we reserved a label, which we use later
-    appf(p.s[cpsStmts], "switch (hashString($1) & $2) {$n", 
+    appcg(p, cpsStmts, "switch (#hashString($1) & $2) {$n", 
          [rdLoc(a), toRope(bitMask)])
     for j in countup(0, high(branches)): 
       if branches[j] != nil: 
@@ -412,7 +405,7 @@ proc genStringCase(p: BProc, t: PNode) =
     # third pass: generate statements
     genCaseSecondPass(p, t, labId)
   else: 
-    genCaseGeneric(p, t, "", "if (eqStrings($1, $2)) goto $3;$n")
+    genCaseGeneric(p, t, "", "if (#eqStrings($1, $2)) goto $3;$n")
   
 proc branchHasTooBigRange(b: PNode): bool = 
   for i in countup(0, sonsLen(b) - 2): 
@@ -588,11 +581,9 @@ proc genTryStmt(p: BProc, t: PNode) =
   #    longjmp(excHandler->context, sp.status);
   genLineDir(p, t)
   var safePoint = getTempName()
-  useMagic(p.module, "TSafePoint")
-  useMagic(p.module, "E_Base")
-  useMagic(p.module, "excHandler")
-  appf(p.s[cpsLocals], "TSafePoint $1;$n", [safePoint])
-  appf(p.s[cpsStmts], "$1.prev = excHandler;$n" & "excHandler = &$1;$n" &
+  discard cgsym(p.module, "E_Base")
+  appcg(p, cpsLocals, "#TSafePoint $1;$n", [safePoint])
+  appcg(p, cpsStmts, "$1.prev = #excHandler;$n" & "excHandler = &$1;$n" &
       "$1.status = setjmp($1.context);$n", [safePoint])
   if optStackTrace in p.Options: 
     app(p.s[cpsStmts], "framePtr = (TFrame*)&F;" & tnl)
@@ -627,9 +618,8 @@ proc genTryStmt(p: BProc, t: PNode) =
   dec(p.nestedTryStmts)
   if (i < length) and (t.sons[i].kind == nkFinally): 
     genStmts(p, t.sons[i].sons[0])
-  useMagic(p.module, "raiseException")
-  appf(p.s[cpsStmts], "if ($1.status != 0) { " &
-      "raiseException($1.exc, $1.exc->name); }$n", [safePoint])
+  appcg(p, cpsStmts, "if ($1.status != 0) { " &
+      "#raiseException($1.exc, $1.exc->name); }$n", [safePoint])
 
 var 
   breakPointId: int = 0
@@ -643,21 +633,17 @@ proc genBreakPoint(p: BProc, t: PNode) =
       name = normalize(t.sons[1].strVal)
     else: 
       inc(breakPointId)
-      name = "bp" & $(breakPointId)
+      name = "bp" & $breakPointId
     genLineDir(p, t)          # BUGFIX
-    appf(gBreakpoints, 
-         "dbgRegisterBreakpoint($1, (NCSTRING)$2, (NCSTRING)$3);$n", [
+    appcg(p.module, gBreakpoints, 
+         "#dbgRegisterBreakpoint($1, (NCSTRING)$2, (NCSTRING)$3);$n", [
         toRope(toLinenumber(t.info)), makeCString(toFilename(t.info)), 
         makeCString(name)])
 
 proc genPragma(p: BProc, n: PNode) = 
   for i in countup(0, sonsLen(n) - 1): 
     var it = n.sons[i]
-    var key: PNode
-    if it.kind == nkExprColonExpr: 
-      key = it.sons[0]
-    else: 
-      key = it
+    var key = if it.kind == nkExprColonExpr: it.sons[0] else: it
     if key.kind == nkIdent: 
       case whichKeyword(key.ident)
       of wBreakpoint: 
@@ -667,8 +653,7 @@ proc genPragma(p: BProc, n: PNode) =
           # we need to keep track of ``deadCodeElim`` pragma
           if (sfDeadCodeElim in p.module.module.flags): 
             addPendingModule(p.module)
-      else: 
-        nil
+      else: nil
   
 proc genAsgn(p: BProc, e: PNode) = 
   var a: TLoc
diff --git a/rod/ccgtypes.nim b/rod/ccgtypes.nim
index 5034bf67b..ca5b3990e 100755
--- a/rod/ccgtypes.nim
+++ b/rod/ccgtypes.nim
@@ -248,7 +248,7 @@ proc getSimpleTypeDesc(m: BModule, typ: PType): PRope =
         internalError(typ.sym.info, "getSimpleTypeDesc: " & $(getSize(typ)))
         result = nil
   of tyString: 
-    useMagic(m, "NimStringDesc")
+    discard cgsym(m, "NimStringDesc")
     result = typeNameOrLiteral(typ, "NimStringDesc*")
   of tyCstring: result = typeNameOrLiteral(typ, "NCSTRING")
   of tyBool: result = typeNameOrLiteral(typ, "NIM_BOOL")
@@ -342,20 +342,19 @@ proc getRecordDesc(m: BModule, typ: PType, name: PRope,
   # declare the record:
   var hasField = false
   if typ.kind == tyObject: 
-    useMagic(m, "TNimType")
     if typ.sons[0] == nil: 
       if typ.sym != nil and sfPure in typ.sym.flags or tfFinal in typ.flags: 
-        result = ropef("struct $1 {$n", [name])
+        result = ropecg(m, "struct $1 {$n", [name])
       else: 
-        result = ropef("struct $1 {$nTNimType* m_type;$n", [name])
+        result = ropecg(m, "struct $1 {$n#TNimType* m_type;$n", [name])
         hasField = true
     elif gCmd == cmdCompileToCpp: 
-      result = ropef("struct $1 : public $2 {$n", 
-                     [name, getTypeDescAux(m, typ.sons[0], check)])
+      result = ropecg(m, "struct $1 : public $2 {$n", 
+                      [name, getTypeDescAux(m, typ.sons[0], check)])
       hasField = true
     else: 
-      result = ropef("struct $1 {$n  $2 Sup;$n", 
-                     [name, getTypeDescAux(m, typ.sons[0], check)])
+      result = ropecg(m, "struct $1 {$n  $2 Sup;$n", 
+                      [name, getTypeDescAux(m, typ.sons[0], check)])
       hasField = true
   else: 
     result = ropef("struct $1 {$n", [name])
@@ -446,11 +445,12 @@ proc getTypeDescAux(m: BModule, typ: PType, check: var TIntSet): PRope =
     assert(CacheGetType(m.typeCache, t) == nil)
     IdTablePut(m.typeCache, t, con(result, "*"))
     if not isImportedType(t): 
-      useMagic(m, "TGenericSeq")
       if skipTypes(t.sons[0], abstractInst).kind != tyEmpty: 
-        appf(m.s[cfsSeqTypes], "struct $2 {$n" & "  TGenericSeq Sup;$n" &
-            "  $1 data[SEQ_DECL_SIZE];$n" & "};$n", 
-             [getTypeDescAux(m, t.sons[0], check), result])
+        appcg(m, m.s[cfsSeqTypes], 
+            "struct $2 {$n" & 
+            "  #TGenericSeq Sup;$n" &
+            "  $1 data[SEQ_DECL_SIZE];$n" & 
+            "};$n", [getTypeDescAux(m, t.sons[0], check), result])
       else: 
         result = toRope("TGenericSeq")
     app(result, "*")
@@ -595,10 +595,9 @@ proc genObjectFields(m: BModule, typ: PType, n: PNode, expr: PRope) =
     assert(n.sons[0].kind == nkSym)
     field = n.sons[0].sym
     tmp = getTempName()
-    useMagic(m, "chckNil")
     appf(m.s[cfsTypeInit3], "$1.kind = 3;$n" &
         "$1.offset = offsetof($2, $3);$n" & "$1.typ = $4;$n" &
-        "chckNil($1.typ);$n" & "$1.name = $5;$n" & "$1.sons = &$6[0];$n" &
+        "$1.name = $5;$n" & "$1.sons = &$6[0];$n" &
         "$1.len = $7;$n", [expr, getTypeDesc(m, typ), field.loc.r, 
                            genTypeInfo(m, field.typ), makeCString(field.name.s), 
                            tmp, toRope(lengthOrd(field.typ))])
@@ -628,10 +627,9 @@ proc genObjectFields(m: BModule, typ: PType, n: PNode, expr: PRope) =
       else: internalError(n.info, "genObjectFields(nkRecCase)")
   of nkSym: 
     field = n.sym
-    useMagic(m, "chckNil")
     appf(m.s[cfsTypeInit3], "$1.kind = 1;$n" &
         "$1.offset = offsetof($2, $3);$n" & "$1.typ = $4;$n" &
-        "chckNil($1.typ);$n" & "$1.name = $5;$n", [expr, getTypeDesc(m, typ), 
+        "$1.name = $5;$n", [expr, getTypeDesc(m, typ), 
         field.loc.r, genTypeInfo(m, field.typ), makeCString(field.name.s)])
   else: internalError(n.info, "genObjectFields")
   
@@ -658,10 +656,9 @@ proc genTupleInfo(m: BModule, typ: PType, name: PRope) =
       a = typ.sons[i]
       tmp2 = getNimNode(m)
       appf(m.s[cfsTypeInit3], "$1[$2] = &$3;$n", [tmp, toRope(i), tmp2])
-      useMagic(m, "chckNil")
       appf(m.s[cfsTypeInit3], "$1.kind = 1;$n" &
           "$1.offset = offsetof($2, Field$3);$n" & "$1.typ = $4;$n" &
-          "chckNil($1.typ);$n" & "$1.name = \"Field$3\";$n", 
+          "$1.name = \"Field$3\";$n", 
            [tmp2, getTypeDesc(m, typ), toRope(i), genTypeInfo(m, a)])
     appf(m.s[cfsTypeInit3], "$1.len = $2; $1.kind = 2; $1.sons = &$3[0];$n", 
          [expr, toRope(length), tmp])
@@ -735,8 +732,8 @@ proc genTypeInfo(m: BModule, typ: PType): PRope =
   result = ropef("NTI$1", [toRope(id)])
   if not IntSetContainsOrIncl(m.typeInfoMarker, id): 
     # declare type information structures:
-    useMagic(m, "TNimType")
-    useMagic(m, "TNimNode")
+    discard cgsym(m, "TNimType")
+    discard cgsym(m, "TNimNode")
     appf(m.s[cfsVars], "extern TNimType* $1; /* $2 */$n", 
          [result, toRope(typeToString(t))])
   if dataGenerated: return 
diff --git a/rod/cgen.nim b/rod/cgen.nim
index ad322a1dd..dd1878465 100755
--- a/rod/cgen.nim
+++ b/rod/cgen.nim
@@ -169,7 +169,68 @@ proc useHeader(m: BModule, sym: PSym) =
     assert(sym.annex != nil)
     discard lists.IncludeStr(m.headerFiles, getStr(sym.annex.path))
 
-proc UseMagic(m: BModule, name: string)
+proc cgsym(m: BModule, name: string): PRope
+
+proc ropecg(m: BModule, frmt: TFormatStr, args: openarray[PRope]): PRope = 
+  var i, j, length, start, num: int
+  i = 0
+  length = len(frmt)
+  result = nil
+  num = 0
+  while i < length: 
+    if frmt[i] == '$': 
+      inc(i)                  # skip '$'
+      case frmt[i]
+      of '$': 
+        app(result, "$")
+        inc(i)
+      of '#': 
+        inc(i)
+        app(result, args[num])
+        inc(num)
+      of '0'..'9': 
+        j = 0
+        while true: 
+          j = (j * 10) + Ord(frmt[i]) - ord('0')
+          inc(i)
+          if (i > length + 0 - 1) or not (frmt[i] in {'0'..'9'}): break 
+        num = j
+        if j > high(args) + 1: 
+          internalError("ropes: invalid format string $" & $(j))
+        app(result, args[j - 1])
+      of 'N', 'n': 
+        app(result, tnl)
+        inc(i)
+      else: InternalError("ropes: invalid format string $" & frmt[i])
+    elif frmt[i] == '#' and frmt[i+1] in IdentStartChars:
+      inc(i)
+      var j = i
+      while frmt[j] in IdentChars: inc(j)
+      var ident = copy(frmt, i, j-1)
+      i = j
+      app(result, cgsym(m, ident))
+    elif frmt[i] == '#' and frmt[i+1] == '$':
+      inc(i, 2)
+      var j = 0
+      while frmt[i] in Digits: 
+        j = (j * 10) + Ord(frmt[i]) - ord('0')
+        inc(i)
+      app(result, cgsym(m, args[j-1].ropeToStr))
+    start = i
+    while i < length: 
+      if frmt[i] != '$' and frmt[i] != '#': inc(i)
+      else: break 
+    if i - 1 >= start: 
+      app(result, copy(frmt, start, i - 1))
+
+proc appcg(m: BModule, c: var PRope, frmt: TFormatStr, args: openarray[PRope]) = 
+  app(c, ropecg(m, frmt, args))
+
+
+proc appcg(p: BProc, s: TCProcSection, frmt: TFormatStr, 
+           args: openarray[PRope]) = 
+  app(p.s[s], ropecg(p.module, frmt, args))
+
 
 include "ccgtypes.nim"
 
@@ -274,26 +335,21 @@ proc assignLocalVar(p: BProc, s: PSym) =
 proc assignGlobalVar(p: BProc, s: PSym) = 
   if s.loc.k == locNone: 
     fillLoc(s.loc, locGlobalVar, s.typ, mangleName(s), OnHeap)
-  if gCmd == cmdCompileToLLVM: 
-    appf(p.module.s[cfsVars], "$1 = linkonce global $2 zeroinitializer$n", 
-         [s.loc.r, getTypeDesc(p.module, s.loc.t)])
-    incl(s.loc.flags, lfIndirect)
-  else: 
-    useHeader(p.module, s)
-    if lfNoDecl in s.loc.flags: return 
-    if sfImportc in s.flags: app(p.module.s[cfsVars], "extern ")
-    app(p.module.s[cfsVars], getTypeDesc(p.module, s.loc.t))
-    if sfRegister in s.flags: app(p.module.s[cfsVars], " register")
-    if sfVolatile in s.flags: app(p.module.s[cfsVars], " volatile")
-    if sfThreadVar in s.flags: app(p.module.s[cfsVars], " NIM_THREADVAR")
-    appf(p.module.s[cfsVars], " $1;$n", [s.loc.r])
+  useHeader(p.module, s)
+  if lfNoDecl in s.loc.flags: return 
+  if sfImportc in s.flags: app(p.module.s[cfsVars], "extern ")
+  app(p.module.s[cfsVars], getTypeDesc(p.module, s.loc.t))
+  if sfRegister in s.flags: app(p.module.s[cfsVars], " register")
+  if sfVolatile in s.flags: app(p.module.s[cfsVars], " volatile")
+  if sfThreadVar in s.flags: app(p.module.s[cfsVars], " NIM_THREADVAR")
+  appf(p.module.s[cfsVars], " $1;$n", [s.loc.r])
   if {optStackTrace, optEndb} * p.module.module.options ==
       {optStackTrace, optEndb}: 
-    useMagic(p.module, "dbgRegisterGlobal")
-    appff(p.module.s[cfsDebugInit], "dbgRegisterGlobal($1, &$2, $3);$n", 
-          "call void @dbgRegisterGlobal(i8* $1, i8* $2, $4* $3)$n", [cstringLit(
-        p, p.module.s[cfsDebugInit], normalize(s.owner.name.s & '.' & s.name.s)), 
-        s.loc.r, genTypeInfo(p.module, s.typ), getTypeDesc(p.module, "TNimType")])
+    appcg(p.module, p.module.s[cfsDebugInit], 
+          "#dbgRegisterGlobal($1, &$2, $3);$n", 
+         [cstringLit(p, p.module.s[cfsDebugInit], 
+          normalize(s.owner.name.s & '.' & s.name.s)), 
+          s.loc.r, genTypeInfo(p.module, s.typ)])
 
 proc iff(cond: bool, the, els: PRope): PRope = 
   if cond: result = the
@@ -352,11 +408,11 @@ proc loadDynamicLib(m: BModule, lib: PLib) =
       for i in countup(0, high(s)): 
         inc(m.labels)
         if i > 0: app(loadlib, "||")
-        appf(loadlib, "($1 = nimLoadLibrary((NimStringDesc*) &$2))$n", 
-             [tmp, getStrLit(m, s[i])])
-      appf(m.s[cfsDynLibInit], 
-           "if (!($1)) nimLoadLibraryError((NimStringDesc*) &$2);$n", 
-           [loadlib, getStrLit(m, lib.path.strVal)]) 
+        appcg(m, loadlib, "($1 = #nimLoadLibrary((#NimStringDesc*) &$2))$n", 
+              [tmp, getStrLit(m, s[i])])
+      appcg(m, m.s[cfsDynLibInit], 
+            "if (!($1)) #nimLoadLibraryError((#NimStringDesc*) &$2);$n", 
+            [loadlib, getStrLit(m, lib.path.strVal)]) 
     else:
       var p = newProc(nil, m)
       var dest: TLoc
@@ -364,37 +420,38 @@ proc loadDynamicLib(m: BModule, lib: PLib) =
       app(m.s[cfsVars], p.s[cpsLocals])
       app(m.s[cfsDynLibInit], p.s[cpsInit])
       app(m.s[cfsDynLibInit], p.s[cpsStmts])
-      appf(m.s[cfsDynLibInit], 
-           "if (!($1 = nimLoadLibrary($2))) nimLoadLibraryError($2);$n", 
+      appcg(m, m.s[cfsDynLibInit], 
+           "if (!($1 = #nimLoadLibrary($2))) #nimLoadLibraryError($2);$n", 
            [tmp, rdLoc(dest)])
       
-    useMagic(m, "nimLoadLibrary")
-    useMagic(m, "nimUnloadLibrary")
-    useMagic(m, "NimStringDesc")
-    useMagic(m, "nimLoadLibraryError")
   if lib.name == nil: InternalError("loadDynamicLib")
   
+proc mangleDynLibProc(sym: PSym): PRope =
+  if sfCompilerProc in sym.flags: 
+    # NOTE: sym.loc.r is the external name!
+    result = toRope(sym.name.s)
+  else:
+    result = ropef("Dl_$1", [toRope(sym.id)])
+  
 proc SymInDynamicLib(m: BModule, sym: PSym) = 
   var lib = sym.annex
   var extname = sym.loc.r
   loadDynamicLib(m, lib)
-  useMagic(m, "nimGetProcAddr")
+  discard cgsym(m, "nimGetProcAddr")
   if gCmd == cmdCompileToLLVM: incl(sym.loc.flags, lfIndirect)
-  var tmp = ropeff("Dl_$1", "@Dl_$1", [toRope(sym.id)])
+  var tmp = mangleDynLibProc(sym)
   sym.loc.r = tmp             # from now on we only need the internal name
   sym.typ.sym = nil           # generate a new name
   inc(m.labels, 2)
-  appff(m.s[cfsDynLibInit], 
-      "$1 = ($2) nimGetProcAddr($3, $4);$n", "%MOC$5 = load i8* $3$n" &
-      "%MOC$6 = call $2 @nimGetProcAddr(i8* %MOC$5, i8* $4)$n" &
-      "store $2 %MOC$6, $2* $1$n", [tmp, getTypeDesc(m, sym.typ), 
-      lib.name, cstringLit(m, m.s[cfsDynLibInit], ropeToStr(extname)), 
-      toRope(m.labels), toRope(m.labels - 1)])
+  appf(m.s[cfsDynLibInit], 
+      "$1 = ($2) nimGetProcAddr($3, $4);$n", 
+      [tmp, getTypeDesc(m, sym.typ), 
+      lib.name, cstringLit(m, m.s[cfsDynLibInit], ropeToStr(extname))])
   appff(m.s[cfsVars], "$2 $1;$n", 
       "$1 = linkonce global $2 zeroinitializer$n", 
       [sym.loc.r, getTypeDesc(m, sym.loc.t)])
 
-proc UseMagic(m: BModule, name: string) = 
+proc cgsym(m: BModule, name: string): PRope = 
   var sym = magicsys.getCompilerProc(name)
   if sym != nil: 
     case sym.kind
@@ -402,8 +459,16 @@ proc UseMagic(m: BModule, name: string) =
     of skVar: genVarPrototype(m, sym)
     of skType: discard getTypeDesc(m, sym.typ)
     else: InternalError("useMagic: " & name)
-  elif not (sfSystemModule in m.module.flags): 
-    rawMessage(errSystemNeeds, name) # don't be too picky here
+  else:
+    # we used to exclude the system module from this check, but for DLL
+    # generation support this sloppyness leads to hard to detect bugs, so
+    # we're picky here for the system module too:
+    when false:
+      if not (sfSystemModule in m.module.flags): 
+        rawMessage(errSystemNeeds, name) 
+    else:
+      rawMessage(errSystemNeeds, name)
+  result = sym.loc.r
   
 proc generateHeaders(m: BModule) = 
   app(m.s[cfsHeaders], "#include \"nimbase.h\"" & tnl & tnl)
@@ -418,7 +483,7 @@ proc generateHeaders(m: BModule) =
 proc getFrameDecl(p: BProc) = 
   var slots: PRope
   if p.frameLen > 0: 
-    useMagic(p.module, "TVarSlot")
+    discard cgsym(p.module, "TVarSlot")
     slots = ropeff("  TVarSlot s[$1];$n", ", [$1 x %TVarSlot]", 
                    [toRope(p.frameLen)])
   else: 
@@ -507,7 +572,7 @@ proc genProcAux(m: BModule, prc: PSym) =
     if (optProfiler in prc.options) and (gCmd != cmdCompileToLLVM): 
       if gProcProfile >= 64 * 1024: 
         InternalError(prc.info, "too many procedures for profiling")
-      useMagic(m, "profileData")
+      discard cgsym(m, "profileData")
       app(p.s[cpsLocals], "ticks NIM_profilingStart;" & tnl)
       if prc.loc.a < 0: 
         appf(m.s[cfsDebugInit], "profileData[$1].procname = $2;$n", [
@@ -534,9 +599,9 @@ proc genProcPrototype(m: BModule, sym: PSym) =
   if lfDynamicLib in sym.loc.Flags: 
     if (sym.owner.id != m.module.id) and
         not intSetContainsOrIncl(m.declaredThings, sym.id): 
-      appff(m.s[cfsVars], "extern $1 Dl_$2;$n", 
-            "@Dl_$2 = linkonce global $1 zeroinitializer$n", 
-            [getTypeDesc(m, sym.loc.t), toRope(sym.id)])
+      appff(m.s[cfsVars], "extern $1 $2;$n", 
+            "@$2 = linkonce global $1 zeroinitializer$n", 
+            [getTypeDesc(m, sym.loc.t), mangleDynLibProc(sym)])
       if gCmd == cmdCompileToLLVM: incl(sym.loc.flags, lfIndirect)
   else: 
     if not IntSetContainsOrIncl(m.declaredProtos, sym.id): 
@@ -679,7 +744,7 @@ proc genMainProc(m: BModule) =
         "                            i8* %lpvReserved) {$n" &
         "  call void @NimMain()$n" & "  ret i32 1$n" & "}$n"
   var nimMain, otherMain: TFormatStr
-  useMagic(m, "setStackBottom")
+  discard cgsym(m, "setStackBottom")
   if (platform.targetOS == osWindows) and
       (gGlobalOptions * {optGenGuiApp, optGenDynLib} != {}): 
     if optGenGuiApp in gGlobalOptions: 
@@ -704,7 +769,7 @@ proc genMainProc(m: BModule) =
     else: 
       nimMain = PosixNimMain
       otherMain = PosixCMain
-  if gBreakpoints != nil: useMagic(m, "dbgRegisterBreakpoint")
+  if gBreakpoints != nil: discard cgsym(m, "dbgRegisterBreakpoint")
   inc(m.labels)
   appf(m.s[cfsProcs], nimMain, [gBreakpoints, mainModInit, toRope(m.labels)])
   if not (optNoMain in gGlobalOptions): appf(m.s[cfsProcs], otherMain, [])
@@ -730,14 +795,10 @@ proc genInitCode(m: BModule) =
   prc = ropeff("N_NOINLINE(void, $1)(void) {$n", 
                "define void $1() noinline {$n", [initname])
   if m.typeNodes > 0: 
-    useMagic(m, "TNimNode")
-    appff(m.s[cfsTypeInit1], "static TNimNode $1[$2];$n", 
-          "$1 = private alloca [$2 x @TNimNode]$n", 
+    appcg(m, m.s[cfsTypeInit1], "static #TNimNode $1[$2];$n", 
           [m.typeNodesName, toRope(m.typeNodes)])
   if m.nimTypes > 0: 
-    useMagic(m, "TNimType")
-    appff(m.s[cfsTypeInit1], "static TNimType $1[$2];$n", 
-          "$1 = private alloca [$2 x @TNimType]$n", 
+    appcg(m, m.s[cfsTypeInit1], "static #TNimType $1[$2];$n", 
           [m.nimTypesName, toRope(m.nimTypes)])
   if optStackTrace in m.initProc.options: 
     getFrameDecl(m.initProc)
diff --git a/rod/magicsys.nim b/rod/magicsys.nim
index 58de1d795..1d758dcde 100755
--- a/rod/magicsys.nim
+++ b/rod/magicsys.nim
@@ -1,7 +1,7 @@
 #
 #
 #           The Nimrod Compiler
-#        (c) Copyright 2009 Andreas Rumpf
+#        (c) Copyright 2010 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -69,8 +69,7 @@ proc getSysType(kind: TTypeKind): PType =
   if result == nil: InternalError("type not found: " & $kind)
   
 proc getCompilerProc(name: string): PSym = 
-  var ident: PIdent
-  ident = getIdent(name, getNormalizedHash(name))
+  var ident = getIdent(name, getNormalizedHash(name))
   result = StrTableGet(compilerprocs, ident)
   if result == nil: 
     result = StrTableGet(rodCompilerProcs, ident)
diff --git a/rod/nimrod.ini b/rod/nimrod.ini
index 1574721f1..9e3445c44 100755
--- a/rod/nimrod.ini
+++ b/rod/nimrod.ini
@@ -1,8 +1,9 @@
 [Project]
 Name: "Nimrod"
 Version: "$version"
-OS: "linux;macosx;freebsd;netbsd;openbsd;solaris"
-CPU: "i386;amd64"  # ;sparc;powerpc
+; Windows and i386 must be first!
+OS: "windows" ;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
diff --git a/rod/pragmas.nim b/rod/pragmas.nim
index 24c5be923..9f84c7f05 100755
--- a/rod/pragmas.nim
+++ b/rod/pragmas.nim
@@ -21,13 +21,13 @@ const
   procPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl, 
     wMagic, wNosideEffect, wSideEffect, wNoreturn, wDynLib, wHeader, 
     wCompilerProc, wPure, wProcVar, wDeprecated, wVarargs, wCompileTime, wMerge, 
-    wBorrow}
+    wBorrow, wExtern}
   converterPragmas* = procPragmas
   methodPragmas* = procPragmas
   macroPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl, 
-    wMagic, wNosideEffect, wCompilerProc, wDeprecated, wTypeCheck}
+    wMagic, wNosideEffect, wCompilerProc, wDeprecated, wTypeCheck, wExtern}
   iteratorPragmas* = {FirstCallConv..LastCallConv, wNosideEffect, wSideEffect, 
-    wImportc, wExportc, wNodecl, wMagic, wDeprecated, wBorrow}
+    wImportc, wExportc, wNodecl, wMagic, wDeprecated, wBorrow, wExtern}
   stmtPragmas* = {wChecks, wObjChecks, wFieldChecks, wRangechecks, wBoundchecks, 
     wOverflowchecks, wNilchecks, wAssertions, wWarnings, wHints, wLinedir, 
     wStacktrace, wLinetrace, wOptimization, wHint, wWarning, wError, wFatal, 
@@ -35,13 +35,15 @@ const
     wCheckpoint, wPassL, wPassC, wDeadCodeElim, wDeprecated, wFloatChecks,
     wInfChecks, wNanChecks, wPragma}
   lambdaPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl, 
-    wNosideEffect, wSideEffect, wNoreturn, wDynLib, wHeader, wPure, wDeprecated}
+    wNosideEffect, wSideEffect, wNoreturn, wDynLib, wHeader, wPure, 
+    wDeprecated, wExtern}
   typePragmas* = {wImportc, wExportc, wDeprecated, wMagic, wAcyclic, wNodecl, 
-    wPure, wHeader, wCompilerProc, wFinal, wSize}
-  fieldPragmas* = {wImportc, wExportc, wDeprecated}
+    wPure, wHeader, wCompilerProc, wFinal, wSize, wExtern}
+  fieldPragmas* = {wImportc, wExportc, wDeprecated, wExtern}
   varPragmas* = {wImportc, wExportc, wVolatile, wRegister, wThreadVar, wNodecl, 
-    wMagic, wHeader, wDeprecated, wCompilerProc, wDynLib}
-  constPragmas* = {wImportc, wExportc, wHeader, wDeprecated, wMagic, wNodecl}
+    wMagic, wHeader, wDeprecated, wCompilerProc, wDynLib, wExtern}
+  constPragmas* = {wImportc, wExportc, wHeader, wDeprecated, wMagic, wNodecl,
+    wExtern}
   procTypePragmas* = {FirstCallConv..LastCallConv, wVarargs, wNosideEffect}
 
 proc pragma*(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords)
@@ -64,18 +66,17 @@ proc pragmaAsm(c: PContext, n: PNode): char =
         else: invalidPragma(it)
       else: 
         invalidPragma(it)
-  
-const 
-  FirstPragmaWord = wMagic
-  LastPragmaWord = wNoconv
+
+proc setExternName(s: PSym, extname: string) = 
+  s.loc.r = toRope(extname % s.name.s)
 
 proc MakeExternImport(s: PSym, extname: string) = 
-  s.loc.r = toRope(extname)
+  setExternName(s, extname)
   incl(s.flags, sfImportc)
   excl(s.flags, sfForward)
 
 proc MakeExternExport(s: PSym, extname: string) = 
-  s.loc.r = toRope(extname)
+  setExternName(s, extname)
   incl(s.flags, sfExportc)
 
 proc getStrLitNode(c: PContext, n: PNode): PNode =
@@ -356,6 +357,7 @@ proc pragma(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) =
             makeExternExport(sym, getOptionalStr(c, it, sym.name.s))
             incl(sym.flags, sfUsed) # avoid wrong hints
           of wImportc: makeExternImport(sym, getOptionalStr(c, it, sym.name.s))
+          of wExtern: setExternName(sym, expectStrLit(c, it))
           of wAlign: 
             if sym.typ == nil: invalidPragma(it)
             sym.typ.align = expectIntLit(c, it)
diff --git a/rod/semstmts.nim b/rod/semstmts.nim
index fdf931815..e700f8e71 100755
--- a/rod/semstmts.nim
+++ b/rod/semstmts.nim
@@ -688,7 +688,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
   else: 
     if n.sons[pragmasPos] != nil: 
       liMessage(n.sons[pragmasPos].info, errPragmaOnlyInHeaderOfProc)
-    if not (sfForward in proto.flags): 
+    if sfForward notin proto.flags: 
       liMessage(n.info, errAttemptToRedefineX, proto.name.s)
     excl(proto.flags, sfForward)
     closeScope(c.tab)         # close scope with wrong parameter symbols
@@ -715,7 +715,9 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
       c.p = newProcCon(s)
       if (s.typ.sons[0] != nil) and (kind != skIterator): 
         addResult(c, s.typ.sons[0], n.info)
-      n.sons[codePos] = semStmtScope(c, n.sons[codePos])
+      if sfImportc notin s.flags: 
+        # no semantic checking for importc:
+        n.sons[codePos] = semStmtScope(c, n.sons[codePos])
       if (s.typ.sons[0] != nil) and (kind != skIterator): addResultNode(c, n)
     else: 
       if (s.typ.sons[0] != nil) and (kind != skIterator): 
diff --git a/rod/wordrecg.nim b/rod/wordrecg.nim
index ac7265f7d..bf2aa84f7 100755
--- a/rod/wordrecg.nim
+++ b/rod/wordrecg.nim
@@ -34,6 +34,7 @@ type
     
     wColon, wEquals, wDot, wDotDot, wHat, wStar, wMinus, 
     wMagic, wTypeCheck, wFinal, wProfiler, wObjChecks, wImportc, wExportc, 
+    wExtern,
     wAlign, wNodecl, wPure, wVolatile, wRegister, wSideeffect, wHeader, 
     wNosideeffect, wNoreturn, wMerge, wLib, wDynlib, wCompilerproc, wProcVar, 
     wFatal, wError, wWarning, wHint, wLine, wPush, wPop, wDefine, wUndef, 
@@ -54,7 +55,7 @@ type
     wCc, wGenscript, wCheckPoint, wCheckPoints, wNoMain, wSubsChar, 
     wAcyclic, wIndex, 
     wCompileToC, wCompileToCpp, wCompileToEcmaScript, wCompileToLLVM, wPretty, 
-    wDoc, wGenDepend, wListDef, wCheck, wParse, wScan, wBoot, wLazy, 
+    wDoc, wGenDepend, wListDef, wCheck, wParse, wScan, wLazy, 
     wRst2html, wRst2tex, wI,
     wWrite, wPutEnv, wPrependEnv, wAppendEnv, wThreadVar
     
@@ -78,7 +79,8 @@ const
 
     ":", "=", ".", "..", "^", "*", "-",
     "magic", "typecheck", "final", "profiler", "objchecks", "importc", 
-    "exportc", "align", "nodecl", "pure", "volatile", "register", "sideeffect", 
+    "exportc", "extern",
+    "align", "nodecl", "pure", "volatile", "register", "sideeffect", 
     "header", "nosideeffect", "noreturn", "merge", "lib", "dynlib", 
     "compilerproc", "procvar", "fatal", "error", "warning", "hint", "line", 
     "push", "pop", "define", "undef", "linedir", "stacktrace", "linetrace", 
@@ -101,7 +103,7 @@ const
     "nomain", "subschar", "acyclic", "index", 
     "compiletoc", "compiletocpp", "compiletoecmascript", "compiletollvm", 
     "pretty", "doc", "gendepend", "listdef", "check", "parse", "scan", 
-    "boot", "lazy", "rst2html", "rst2tex", "i", 
+    "lazy", "rst2html", "rst2tex", "i", 
     "write", "putenv", "prependenv", "appendenv", "threadvar"]
 
 proc whichKeyword*(id: PIdent): TSpecialWord
diff --git a/tests/accept/compile/tenum3.nim b/tests/accept/compile/tenum3.nim
index 09a516932..09a516932 100644..100755
--- a/tests/accept/compile/tenum3.nim
+++ b/tests/accept/compile/tenum3.nim
diff --git a/tests/accept/compile/tuserpragma.nim b/tests/accept/compile/tuserpragma.nim
index 784baa176..784baa176 100644..100755
--- a/tests/accept/compile/tuserpragma.nim
+++ b/tests/accept/compile/tuserpragma.nim
diff --git a/tests/accept/run/tarray3.nim b/tests/accept/run/tarray3.nim
index 881bb7ba4..881bb7ba4 100644..100755
--- a/tests/accept/run/tarray3.nim
+++ b/tests/accept/run/tarray3.nim
diff --git a/tests/accept/run/tunhandledexc.nim b/tests/accept/run/tunhandledexc.nim
index 36ba5418d..36ba5418d 100644..100755
--- a/tests/accept/run/tunhandledexc.nim
+++ b/tests/accept/run/tunhandledexc.nim
diff --git a/tests/accept/run/twrongexc.nim b/tests/accept/run/twrongexc.nim
index 8ba07bbce..8ba07bbce 100644..100755
--- a/tests/accept/run/twrongexc.nim
+++ b/tests/accept/run/twrongexc.nim
diff --git a/todo.txt b/todo.txt
index 9f6d0625b..496caab4e 100755
--- a/todo.txt
+++ b/todo.txt
@@ -1,10 +1,11 @@
 For version 0.8.10
 ==================
 
+- more robust boot strap process!
+- support for generation of dynamic libraries
 - fix exception handling
 - fix implicit generic routines
 - fix the streams implementation so that they use methods
-- support for generation of dynamic libraries
 
 
 High priority (version 0.9.0)
diff --git a/tools/build.tmpl b/tools/buildsh.tmpl
index 5ba3ca755..c1aa4ba21 100755
--- a/tools/build.tmpl
+++ b/tools/buildsh.tmpl
@@ -1,5 +1,5 @@
 #! stdtmpl(subsChar='?') | standard
-#proc GenerateBuildScript(c: TConfigData): string = 
+#proc GenerateBuildShellScript(c: TConfigData): string = 
 #  result = "#! /bin/sh\n# Generated by niminst\n"
 CC="gcc"
 LINKER="gcc"
@@ -83,8 +83,16 @@ case $myos in
     $LINKER $LINK_FLAGS -o ?{c.binPaths[0]}/?{toLower(c.name)} ?linkCmd || exit 1
     ;;
 #    end for
+  *)
+    echo "Error: no C code generated for: [$myos: $mycpu]"
+    exit 1
+    ;;
   esac
   ;;
+*) 
+  echo "Error: no C code generated for: [$myos: $mycpu]"
+  exit 1
+  ;;
 #  end for
 esac
 
diff --git a/tools/niminst.nim b/tools/niminst.nim
index 2a5b18c38..a93ea2ef8 100755
--- a/tools/niminst.nim
+++ b/tools/niminst.nim
@@ -1,7 +1,7 @@
 #
 #
 #        The Nimrod Installation Generator
-#        (c) Copyright 2009 Andreas Rumpf
+#        (c) Copyright 2010 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -20,6 +20,7 @@ const
   maxOS = 20 # max number of OSes
   maxCPU = 10 # max number of CPUs
   buildShFile = "build.sh"
+  buildBatFile = "build.bat"
   installShFile = "install.sh"
   deinstallShFile = "deinstall.sh"
 
@@ -89,17 +90,18 @@ proc skipRoot(f: string): string =
   if result.len == 0: result = f
 
 include "inno.tmpl"
-include "build.tmpl"
+include "buildsh.tmpl"
+include "buildbat.tmpl"
 include "install.tmpl"
 include "deinstall.tmpl"
 
 # ------------------------- configuration file -------------------------------
 
 const
-  Version = "0.7"
+  Version = "0.8"
   Usage = "niminst - Nimrod Installation Generator Version " & version & """
 
-  (c) 2009 Andreas Rumpf
+  (c) 2010 Andreas Rumpf
 Usage:
   niminst [options] command[;command2...] ini-file[.ini] [compile_options]
 Command:
@@ -289,6 +291,22 @@ proc writeFile(filename, content, newline: string) =
   else:
     quit("Cannot open for writing: " & filename)
 
+proc removeDuplicateFiles(c: var TConfigData) =
+  for osA in countdown(c.oses.len, 1):
+    for cpuA in countdown(c.cpus.len, 1):
+      for i in 0..c.cfiles[osA][cpuA].len-1:
+        var dup = c.cfiles[osA][cpuA][i]
+        var f = extractFilename(dup)
+        for osB in 1..c.oses.len:
+          for cpuB in 1..c.cpus.len:
+            if osB != osA or cpuB != cpuA:
+              var orig = buildDir(osB, cpuB) / f
+              if ExistsFile(orig) and ExistsFile(dup) and
+                  sameFileContent(orig, dup):
+                # file is identical, so delete duplicate:
+                RemoveFile(dup)
+                c.cfiles[osA][cpuA][i] = orig
+
 proc srcdist(c: var TConfigData) =
   for x in walkFiles("lib/*.h"):
     CopyFile(dest="build" / extractFilename(x), source=x)
@@ -311,21 +329,9 @@ proc srcdist(c: var TConfigData) =
         CopyFile(dest=dest, source=c.cfiles[osA][cpuA][i])
         c.cfiles[osA][cpuA][i] = dest
   # second pass: remove duplicate files
-  for osA in countdown(c.oses.len, 1):
-    for cpuA in countdown(c.cpus.len, 1):
-      for i in 0..c.cfiles[osA][cpuA].len-1:
-        var dup = c.cfiles[osA][cpuA][i]
-        var f = extractFilename(dup)
-        for osB in 1..c.oses.len:
-          for cpuB in 1..c.cpus.len:
-            if osB != osA or cpuB != cpuA:
-              var orig = buildDir(osB, cpuB) / f
-              if ExistsFile(orig) and ExistsFile(dup) and
-                  sameFileContent(orig, dup):
-                # file is identical, so delete duplicate:
-                RemoveFile(dup)
-                c.cfiles[osA][cpuA][i] = orig
-  writeFile(buildShFile, GenerateBuildScript(c), "\10")
+  removeDuplicateFiles(c)
+  writeFile(buildShFile, GenerateBuildShellScript(c), "\10")
+  writeFile(buildBatFile, GenerateBuildBatchScript(c), "\13\10")
   if c.installScript: 
     writeFile(installShFile, GenerateInstallScript(c), "\10")
   if c.uninstallScript:
diff --git a/web/news.txt b/web/news.txt
index dd7e330c0..b7f02b5ac 100755
--- a/web/news.txt
+++ b/web/news.txt
@@ -27,6 +27,13 @@ Changes affecting backwards compatibility
   unless they are used in the same module.
 - Deprecated ``times.getStartMilsecs``: Use ``epochTime`` or ``cpuTime`` 
   instead.
+- Removed ``system.OpenFile``.
+- Removed ``system.CloseFile``.
+- Removed ``strutils.replaceStr``.
+- Removed ``strutils.deleteStr``.
+- Removed ``strutils.splitLinesSeq``.
+- Removed ``strutils.splitSeq``.
+- Removed ``strutils.toString``.
 
 
 Additions
@@ -43,6 +50,10 @@ Additions
 - Implemented ``{.size: sizeof(cint).}`` pragma for enum types. This is useful
   for interfacing with C.
 - Implemented ``{.pragma.}`` pragma for user defined pragmas.
+- Implemented ``{.extern.}`` pragma for better control of name mangling.
+- The ``importc`` and ``exportc`` pragmas support format strings: 
+  ``proc p{.exportc: "nim_$1".}`` exports ``p`` as ``nim_p``. This is useful
+  for user defined pragmas.
 
 
 2010-03-14 Version 0.8.8 released