summary refs log tree commit diff stats
path: root/nim
diff options
context:
space:
mode:
Diffstat (limited to 'nim')
-rw-r--r--nim/ast.pas52
-rw-r--r--nim/astalgo.pas2
-rw-r--r--nim/ccgexprs.pas27
-rw-r--r--nim/ccgstmts.pas4
-rw-r--r--nim/ccgutils.pas2
-rw-r--r--nim/cgen.pas2
-rw-r--r--nim/commands.pas971
-rw-r--r--nim/condsyms.pas2
-rw-r--r--nim/docgen.pas16
-rw-r--r--nim/ecmasgen.pas2
-rw-r--r--nim/evals.pas63
-rw-r--r--nim/extccomp.pas6
-rw-r--r--nim/hashtest.pas2
-rw-r--r--nim/highlite.pas2
-rw-r--r--nim/idents.pas2
-rw-r--r--nim/interact.pas2
-rw-r--r--nim/magicsys.pas2
-rw-r--r--nim/main.pas2
-rw-r--r--nim/msgs.pas10
-rw-r--r--nim/nhashes.pas (renamed from nim/hashes.pas)2
-rw-r--r--nim/nstrtabs.pas (renamed from nim/strtabs.pas)10
-rw-r--r--nim/nversion.pas80
-rw-r--r--nim/options.pas6
-rw-r--r--nim/osproc.pas30
-rw-r--r--nim/parsecfg.pas2
-rw-r--r--nim/paslex.pas2
-rw-r--r--nim/pragmas.pas4
-rw-r--r--nim/ropes.pas2
-rw-r--r--nim/rst.pas24
-rw-r--r--nim/scanner.pas2
-rw-r--r--nim/sem.pas43
-rw-r--r--nim/semdata.pas1
-rw-r--r--nim/semfold.pas28
-rw-r--r--nim/semstmts.pas3
-rw-r--r--nim/tigen.pas2
-rw-r--r--nim/transf.pas2
-rw-r--r--nim/treetab.pas2
-rw-r--r--nim/wordrecg.pas2
38 files changed, 791 insertions, 627 deletions
diff --git a/nim/ast.pas b/nim/ast.pas
index a57632468..0c3137b2b 100644
--- a/nim/ast.pas
+++ b/nim/ast.pas
@@ -15,7 +15,7 @@ interface
 {$include 'config.inc'}

 

 uses

-  nsystem, charsets, msgs, hashes,

+  nsystem, charsets, msgs, nhashes,

   nversion, options, strutils, crc, ropes, idents, lists;

 

 const

@@ -245,18 +245,18 @@ type
     mSymDiffSet, mConStrStr, mConArrArr, mConArrT, mConTArr, mConTT, 
     mSlice, mAppendStrCh, mAppendStrStr, mAppendSeqElem, mAppendSeqSeq, mInRange, 
     mInSet, mAsgn, mRepr, mExit, mSetLengthStr, mSetLengthSeq, 
-    mAssert, mSwap, mIsNil, mArrToSeq, mArray, mOpenArray, 
-    mRange, mSet, mSeq, mInt, mInt8, mInt16, 
-    mInt32, mInt64, mFloat, mFloat32, mFloat64, mBool, 
-    mChar, mString, mCstring, mPointer, mAnyEnum, mEmptySet, 
-    mIntSetBaseType, mNil, mIsMainModule, mCompileDate, mCompileTime, mNimrodVersion, 
-    mNimrodMajor, mNimrodMinor, mNimrodPatch, mCpuEndian, mHostOS, mHostCPU, 
-    mNaN, mInf, mNegInf, mNLen, mNChild, mNSetChild, 
-    mNAdd, mNAddMultiple, mNDel, mNKind, mNIntVal, mNFloatVal, 
-    mNSymbol, mNIdent, mNGetType, mNStrVal, mNSetIntVal, mNSetFloatVal, 
-    mNSetSymbol, mNSetIdent, mNSetType, mNSetStrVal, mNNewNimNode, mNCopyNimNode, 
-    mNCopyNimTree, mStrToIdent, mIdentToStr, mEqIdent, mNHint, mNWarning, 
-    mNError
+    mAssert, mSwap, mIsNil, mArrToSeq, mCopyStr, mCopyStrLast, 
+    mNewString, mArray, mOpenArray, mRange, mSet, mSeq, 
+    mInt, mInt8, mInt16, mInt32, mInt64, mFloat, 
+    mFloat32, mFloat64, mBool, mChar, mString, mCstring, 
+    mPointer, mAnyEnum, mEmptySet, mIntSetBaseType, mNil, mIsMainModule, 
+    mCompileDate, mCompileTime, mNimrodVersion, mNimrodMajor, mNimrodMinor, mNimrodPatch, 
+    mCpuEndian, mHostOS, mHostCPU, mNaN, mInf, mNegInf, 
+    mNLen, mNChild, mNSetChild, mNAdd, mNAddMultiple, mNDel, 
+    mNKind, mNIntVal, mNFloatVal, mNSymbol, mNIdent, mNGetType, 
+    mNStrVal, mNSetIntVal, mNSetFloatVal, mNSetSymbol, mNSetIdent, mNSetType, 
+    mNSetStrVal, mNNewNimNode, mNCopyNimNode, mNCopyNimTree, mStrToIdent, mIdentToStr, 
+    mEqIdent, mNHint, mNWarning, mNError
     //[[[end]]]

   );

 

@@ -327,7 +327,7 @@ type
   );

 

   TLocFlag = (

-    lfIndirect,    // backend introduced a pointer
+    lfIndirect,    // backend introduced a pointer

     lfParamCopy,   // backend introduced a parameter copy (LLVM)

     lfNoDeepCopy,  // no need for a deep copy

     lfNoDecl,      // do not declare it in C

@@ -504,18 +504,18 @@ const // "MagicToStr" array:
     'SymDiffSet', 'ConStrStr', 'ConArrArr', 'ConArrT', 'ConTArr', 'ConTT', 
     'Slice', 'AppendStrCh', 'AppendStrStr', 'AppendSeqElem', 'AppendSeqSeq', 'InRange', 
     'InSet', 'Asgn', 'Repr', 'Exit', 'SetLengthStr', 'SetLengthSeq', 
-    'Assert', 'Swap', 'IsNil', 'ArrToSeq', 'Array', 'OpenArray', 
-    'Range', 'Set', 'Seq', 'Int', 'Int8', 'Int16', 
-    'Int32', 'Int64', 'Float', 'Float32', 'Float64', 'Bool', 
-    'Char', 'String', 'Cstring', 'Pointer', 'AnyEnum', 'EmptySet', 
-    'IntSetBaseType', 'Nil', 'IsMainModule', 'CompileDate', 'CompileTime', 'NimrodVersion', 
-    'NimrodMajor', 'NimrodMinor', 'NimrodPatch', 'CpuEndian', 'HostOS', 'HostCPU', 
-    'NaN', 'Inf', 'NegInf', 'NLen', 'NChild', 'NSetChild', 
-    'NAdd', 'NAddMultiple', 'NDel', 'NKind', 'NIntVal', 'NFloatVal', 
-    'NSymbol', 'NIdent', 'NGetType', 'NStrVal', 'NSetIntVal', 'NSetFloatVal', 
-    'NSetSymbol', 'NSetIdent', 'NSetType', 'NSetStrVal', 'NNewNimNode', 'NCopyNimNode', 
-    'NCopyNimTree', 'StrToIdent', 'IdentToStr', 'EqIdent', 'NHint', 'NWarning', 
-    'NError'
+    'Assert', 'Swap', 'IsNil', 'ArrToSeq', 'CopyStr', 'CopyStrLast', 
+    'NewString', 'Array', 'OpenArray', 'Range', 'Set', 'Seq', 
+    'Int', 'Int8', 'Int16', 'Int32', 'Int64', 'Float', 
+    'Float32', 'Float64', 'Bool', 'Char', 'String', 'Cstring', 
+    'Pointer', 'AnyEnum', 'EmptySet', 'IntSetBaseType', 'Nil', 'IsMainModule', 
+    'CompileDate', 'CompileTime', 'NimrodVersion', 'NimrodMajor', 'NimrodMinor', 'NimrodPatch', 
+    'CpuEndian', 'HostOS', 'HostCPU', 'NaN', 'Inf', 'NegInf', 
+    'NLen', 'NChild', 'NSetChild', 'NAdd', 'NAddMultiple', 'NDel', 
+    'NKind', 'NIntVal', 'NFloatVal', 'NSymbol', 'NIdent', 'NGetType', 
+    'NStrVal', 'NSetIntVal', 'NSetFloatVal', 'NSetSymbol', 'NSetIdent', 'NSetType', 
+    'NSetStrVal', 'NNewNimNode', 'NCopyNimNode', 'NCopyNimTree', 'StrToIdent', 'IdentToStr', 
+    'EqIdent', 'NHint', 'NWarning', 'NError'
     //[[[end]]]

   );

 

diff --git a/nim/astalgo.pas b/nim/astalgo.pas
index f7b6f651d..e5475ddd1 100644
--- a/nim/astalgo.pas
+++ b/nim/astalgo.pas
@@ -17,7 +17,7 @@ interface
 {$include 'config.inc'}
 
 uses
-  nsystem, ast, hashes, charsets, strutils, options, msgs, ropes, idents;
+  nsystem, ast, nhashes, charsets, strutils, options, msgs, ropes, idents;
 
 function hashNode(p: PObject): THash;
 
diff --git a/nim/ccgexprs.pas b/nim/ccgexprs.pas
index 03de5c4de..bd0c520d2 100644
--- a/nim/ccgexprs.pas
+++ b/nim/ccgexprs.pas
@@ -1254,15 +1254,9 @@ begin
   refType := skipVarGenericRange(e.sons[1].typ);
   InitLocExpr(p, e.sons[1], a);
   initLoc(b, locExpr, a.t, OnHeap);
-  
-  if optBoehmGC in gGlobalOptions then 
-    b.r := ropef('($1) newObj(sizeof($2))',
-      [getTypeDesc(p.module, reftype), 
-      getTypeDesc(p.module, skipGenericRange(reftype.sons[0]))])  
-  else
-    b.r := ropef('($1) newObj($2, sizeof($3))',
-      [getTypeDesc(p.module, reftype), genTypeInfo(p.module, refType),
-      getTypeDesc(p.module, skipGenericRange(reftype.sons[0]))]);
+  b.r := ropef('($1) newObj($2, sizeof($3))',
+    [getTypeDesc(p.module, reftype), genTypeInfo(p.module, refType),
+    getTypeDesc(p.module, skipGenericRange(reftype.sons[0]))]);
   genAssignment(p, a, b, {@set}[]);
   // set the object type:
   bt := skipGenericRange(refType.sons[0]);
@@ -1279,16 +1273,10 @@ begin
   InitLocExpr(p, e.sons[1], a);
   InitLocExpr(p, e.sons[2], b);
   initLoc(c, locExpr, a.t, OnHeap);
-  if optBoehmGC in gGlobalOptions then 
-    c.r := ropef('($1) newSeq(sizeof($2), $3)',
-      [getTypeDesc(p.module, seqtype), 
-       getTypeDesc(p.module, skipGenericRange(seqtype.sons[0])),
-       rdLoc(b)])
-  else
-    c.r := ropef('($1) newSeq($2, $3)',
-      [getTypeDesc(p.module, seqtype),
-       genTypeInfo(p.module, seqType),
-       rdLoc(b)]);
+  c.r := ropef('($1) newSeq($2, $3)', 
+    [getTypeDesc(p.module, seqtype),
+    genTypeInfo(p.module, seqType),
+    rdLoc(b)]);
   genAssignment(p, a, c, {@set}[]);
 end;
 
@@ -1945,6 +1933,7 @@ begin
     mSetLengthSeq: genSetLengthSeq(p, e, d);
     mIncl, mExcl, mCard, mLtSet, mLeSet, mEqSet, mMulSet, mPlusSet,
     mMinusSet, mInSet: genSetOp(p, e, d, op);
+    mNewString, mCopyStr, mCopyStrLast: genCall(p, e, d);
     mExit: genCall(p, e, d);
     mArrToSeq: genArrToSeq(p, e, d);
     mNLen..mNError:
diff --git a/nim/ccgstmts.pas b/nim/ccgstmts.pas
index 7588f7e15..f3fcdf518 100644
--- a/nim/ccgstmts.pas
+++ b/nim/ccgstmts.pas
@@ -878,7 +878,7 @@ var
   i: int;
   prc: PSym;
 begin
-  assert(t <> nil);
+  //assert(t <> nil);
   if inCheckpoint(t.info) then
     MessageOut(renderTree(t));
   case t.kind of
@@ -913,7 +913,7 @@ begin
     nkRaiseStmt: genRaiseStmt(p, t);
     nkTypeSection: begin
       // we have to emit the type information for object types here to support
-      // seperate compilation:
+      // separate compilation:
       genTypeSection(p.module, t);
     end;
     nkCommentStmt, nkNilLit, nkIteratorDef, nkIncludeStmt, nkImportStmt,
diff --git a/nim/ccgutils.pas b/nim/ccgutils.pas
index 56eff6c9e..49c1a8cee 100644
--- a/nim/ccgutils.pas
+++ b/nim/ccgutils.pas
@@ -16,7 +16,7 @@ interface
 
 uses
   charsets, nsystem,
-  ast, astalgo, ropes, lists, hashes, strutils, types, msgs;
+  ast, astalgo, ropes, lists, nhashes, strutils, types, msgs;
 
 function toCChar(c: Char): string;
 function makeCString(const s: string): PRope;
diff --git a/nim/cgen.pas b/nim/cgen.pas
index 5dcb7f50b..df8431a30 100644
--- a/nim/cgen.pas
+++ b/nim/cgen.pas
@@ -16,7 +16,7 @@ interface
 {$include 'config.inc'}
 
 uses
-  nsystem, ast, astalgo, strutils, hashes, trees, platform, magicsys,
+  nsystem, ast, astalgo, strutils, nhashes, trees, platform, magicsys,
   extccomp, options, nversion, nimsets, msgs, crc, bitsets, idents,
   lists, types, ccgutils, nos, ntime, ropes, nmath, passes, rodread,
   wordrecg, rnimsyn, treetab;
diff --git a/nim/commands.pas b/nim/commands.pas
index 8a4435eb0..fde2d26c7 100644
--- a/nim/commands.pas
+++ b/nim/commands.pas
@@ -1,61 +1,61 @@
-//
-//
-//           The Nimrod Compiler
-//        (c) Copyright 2008 Andreas Rumpf
-//
-//    See the file "copying.txt", included in this
-//    distribution, for details about the copyright.
-//
-
-unit commands;
-
-// This module handles the parsing of command line arguments.
-
-interface
-
-{$include 'config.inc'}
-
-uses
-  nsystem, charsets, nos, msgs, options, nversion, condsyms, strutils, extccomp, 
-  platform, lists, wordrecg;
-
-procedure writeCommandLineUsage;
-
-type
-  TCmdLinePass = (
-    passCmd1,                // first pass over the command line
-    passCmd2,                // second pass over the command line
-    passPP                   // preprocessor called ProcessCommand()
-  );
-
-procedure ProcessCommand(const switch: string; pass: TCmdLinePass);
-procedure processSwitch(const switch, arg: string; pass: TCmdlinePass;
-                        const info: TLineInfo);
-
-implementation
-
-{@ignore}
-const
-{$ifdef fpc}
-  compileDate = {$I %date%};
-{$else}
-  compileDate = '2009-0-0';
-{$endif}
-{@emit}
-
-const
-  HelpMessage = 'Nimrod Compiler Version $1 (' +{&}
-    compileDate +{&} ') [$2: $3]' +{&} nl +{&}
-    'Copyright (c) 2004-2009 by Andreas Rumpf' +{&} nl;
-
-const
-  Usage = ''
-//[[[cog
-//from string import replace
-//def f(x): return "+{&} '" + replace(x, "'", "''")[:-1] + "' +{&} nl"
-//for line in open("data/basicopt.txt").readlines():
-//  cog.outl(f(line))
-//]]]
+//

+//

+//           The Nimrod Compiler

+//        (c) Copyright 2008 Andreas Rumpf

+//

+//    See the file "copying.txt", included in this

+//    distribution, for details about the copyright.

+//

+

+unit commands;

+

+// This module handles the parsing of command line arguments.

+

+interface

+

+{$include 'config.inc'}

+

+uses

+  nsystem, charsets, nos, msgs, options, nversion, condsyms, strutils, extccomp, 

+  platform, lists, wordrecg;

+

+procedure writeCommandLineUsage;

+

+type

+  TCmdLinePass = (

+    passCmd1,                // first pass over the command line

+    passCmd2,                // second pass over the command line

+    passPP                   // preprocessor called ProcessCommand()

+  );

+

+procedure ProcessCommand(const switch: string; pass: TCmdLinePass);

+procedure processSwitch(const switch, arg: string; pass: TCmdlinePass;

+                        const info: TLineInfo);

+

+implementation

+

+{@ignore}

+const

+{$ifdef fpc}

+  compileDate = {$I %date%};

+{$else}

+  compileDate = '2009-0-0';

+{$endif}

+{@emit}

+

+const

+  HelpMessage = 'Nimrod Compiler Version $1 (' +{&}

+    compileDate +{&} ') [$2: $3]' +{&} nl +{&}

+    'Copyright (c) 2004-2009 by Andreas Rumpf' +{&} nl;

+

+const

+  Usage = ''

+//[[[cog

+//from string import replace

+//def f(x): return "+{&} '" + replace(x, "'", "''")[:-1] + "' +{&} nl"

+//for line in open("data/basicopt.txt").readlines():

+//  cog.outl(f(line))

+//]]]

 +{&} 'Usage::' +{&} nl
 +{&} '  nimrod command [options] inputfile [arguments]' +{&} nl
 +{&} 'Command::' +{&} nl
@@ -88,14 +88,14 @@ const
 +{&} '  -r, --run                 run the compiled program with given arguments' +{&} nl
 +{&} '  --advanced                show advanced command line switches' +{&} nl
 +{&} '  -h, --help                show this help' +{&} nl
-//[[[end]]]
-  ;
-
-  AdvancedUsage = ''
-//[[[cog
-//for line in open("data/advopt.txt").readlines():
-//  cog.outl(f(line))
-//]]]
+//[[[end]]]

+  ;

+

+  AdvancedUsage = ''

+//[[[cog

+//for line in open("data/advopt.txt").readlines():

+//  cog.outl(f(line))

+//]]]

 +{&} 'Advanced commands::' +{&} nl
 +{&} '  pas                       convert a Pascal file to Nimrod syntax' +{&} nl
 +{&} '  pretty                    pretty print the inputfile' +{&} nl
@@ -125,401 +125,454 @@ const
 +{&} '  --checkpoints:on|off      turn on|off checkpoints; for debugging Nimrod' +{&} nl
 +{&} '  --skip_cfg                do not read the general configuration file' +{&} nl
 +{&} '  --skip_proj_cfg           do not read the project''s configuration file' +{&} nl
++{&} '  --gc:refc|boehm           use Nimrod''s native GC|Boehm GC' +{&} nl
 +{&} '  --index:FILE              use FILE to generate a documenation index file' +{&} nl
 +{&} '  --putenv:key=value        set an environment variable' +{&} nl
 +{&} '  --list_cmd                list the commands used to execute external programs' +{&} nl
 +{&} '  --verbosity:0|1|2|3       set Nimrod''s verbosity level (0 is default)' +{&} nl
 +{&} '  -v, --version             show detailed version information' +{&} nl
-//[[[end]]]
-  ;
-
-function getCommandLineDesc: string;
-begin
-  result := format(HelpMessage, [VersionAsString, 
-    platform.os[platform.hostOS].name, cpu[platform.hostCPU].name]) +{&} Usage
-end;
-
-var
-  helpWritten: boolean;  // BUGFIX 19
-  versionWritten: boolean;
-  advHelpWritten: boolean;
-
-procedure HelpOnError(pass: TCmdLinePass);
-begin
-  if (pass = passCmd1) and not helpWritten then begin
-    // BUGFIX 19
-    MessageOut(getCommandLineDesc());
-    helpWritten := true
-  end
-end;
-
-procedure writeAdvancedUsage(pass: TCmdLinePass);
-begin
-  if (pass = passCmd1) and not advHelpWritten then begin
-    // BUGFIX 19
-    MessageOut(format(HelpMessage, [VersionAsString, 
-                                    platform.os[platform.hostOS].name,
-                                    cpu[platform.hostCPU].name]) +{&}
-                                    AdvancedUsage);
-    advHelpWritten := true;
-    helpWritten := true;
-    halt(0);
-  end
-end;
-
-procedure writeVersionInfo(pass: TCmdLinePass);
-begin
-  if (pass = passCmd1) and not versionWritten then begin
-    versionWritten := true;
-    helpWritten := true;
-    messageOut(format(HelpMessage, [VersionAsString, 
-                                    platform.os[platform.hostOS].name,
-                                    cpu[platform.hostCPU].name]))
-  end
-end;
-
-procedure writeCommandLineUsage;
-begin
-  if not helpWritten then begin
-    messageOut(getCommandLineDesc());
-    helpWritten := true
-  end
-end;
-
-procedure InvalidCmdLineOption(pass: TCmdLinePass; const switch: string;
-                               const info: TLineInfo);
-begin
-  liMessage(info, errInvalidCmdLineOption, switch)
-end;
-
-procedure splitSwitch(const switch: string; out cmd, arg: string;
-                      pass: TCmdLinePass; const info: TLineInfo);
-var
-  i: int;
-begin
-  cmd := '';
-  i := strStart;
-  if (i < length(switch)+strStart) and (switch[i] = '-') then inc(i);
-  if (i < length(switch)+strStart) and (switch[i] = '-') then inc(i);
-  while i < length(switch) + strStart do begin
-    case switch[i] of
-      'a'..'z', 'A'..'Z', '0'..'9', '_', '.':
-        addChar(cmd, switch[i]);
-      else break;
-    end;
-    inc(i);
-  end;
-  if i >= length(switch) + strStart then
-    arg := ''
-  else if switch[i] in [':', '=', '['] then
-    arg := ncopy(switch, i + 1)
-  else
-    InvalidCmdLineOption(pass, switch, info)
-end;
-
-procedure ProcessOnOffSwitch(const op: TOptions; const arg: string;
-                             pass: TCmdlinePass; const info: TLineInfo);
-begin
-  case whichKeyword(arg) of
-    wOn:  gOptions := gOptions + op;
-    wOff: gOptions := gOptions - op;
-    else  liMessage(info, errOnOrOffExpectedButXFound, arg)
-  end
-end;
-
-procedure ProcessOnOffSwitchG(const op: TGlobalOptions; const arg: string;
-                              pass: TCmdlinePass; const info: TLineInfo);
-begin
-  case whichKeyword(arg) of
-    wOn:  gGlobalOptions := gGlobalOptions + op;
-    wOff: gGlobalOptions := gGlobalOptions - op;
-    else  liMessage(info, errOnOrOffExpectedButXFound, arg)
-  end
-end;
-
-procedure ExpectArg(const switch, arg: string; pass: TCmdLinePass;
-                    const info: TLineInfo);
-begin
-  if (arg = '') then
-    liMessage(info, errCmdLineArgExpected, switch)
-end;
-
-procedure ProcessSpecificNote(const arg: string; state: TSpecialWord;
-                              pass: TCmdlinePass; const info: TLineInfo);
-var
-  i, x: int;
-  n: TNoteKind;
-  id: string;
-begin
-  id := '';
-  // arg = "X]:on|off"
-  i := strStart;
-  n := hintMin;
-  while (i < length(arg)+strStart) and (arg[i] <> ']') do begin
-    addChar(id, arg[i]);
-    inc(i)
-  end;
-  if (i < length(arg)+strStart) and (arg[i] = ']') then
-    inc(i)
-  else
-    InvalidCmdLineOption(pass, arg, info);
-  if (i < length(arg)+strStart) and (arg[i] in [':', '=']) then
-    inc(i)
-  else
-    InvalidCmdLineOption(pass, arg, info);
-  if state = wHint then begin
-    x := findStr(msgs.HintsToStr, id);
-    if x >= 0 then
-      n := TNoteKind(x + ord(hintMin))
-    else
-      InvalidCmdLineOption(pass, arg, info)
-  end
-  else begin
-    x := findStr(msgs.WarningsToStr, id);
-    if x >= 0 then
-      n := TNoteKind(x + ord(warnMin))
-    else
-      InvalidCmdLineOption(pass, arg, info)
-  end;
-  case whichKeyword(ncopy(arg, i)) of
-    wOn: include(gNotes, n);
-    wOff: exclude(gNotes, n);
-    else liMessage(info, errOnOrOffExpectedButXFound, arg)
-  end
-end;
-
-function processPath(const path: string): string;
-begin
-  result := UnixToNativePath(format(path,
-    ['nimrod', getPrefixDir(), 'lib', libpath]))
-end;
-
-procedure processCompile(const filename: string);
-var
-  found, trunc, ext: string;
-begin
-  found := findFile(filename);
-  if found = '' then found := filename;
-  splitFilename(found, trunc, ext);
-  extccomp.addExternalFileToCompile(trunc);
-  extccomp.addFileToLink(completeCFilePath(trunc, false));
-end;
-
-procedure processSwitch(const switch, arg: string; pass: TCmdlinePass;
-                        const info: TLineInfo);
-var
-  theOS: TSystemOS;
-  cpu: TSystemCPU;
-  key, val, path: string;
-begin
-  case whichKeyword(switch) of
-    wPath, wP: begin
-      expectArg(switch, arg, pass, info);
-      path := processPath(arg);
-      {@discard} lists.IncludeStr(options.searchPaths, path)
-    end;
-    wOut, wO: begin
-      expectArg(switch, arg, pass, info);
-      options.outFile := arg;
-    end;
-    wDefine, wD: begin
-      expectArg(switch, arg, pass, info);
-      DefineSymbol(arg)
-    end;
-    wUndef, wU: begin
-      expectArg(switch, arg, pass, info);
-      UndefSymbol(arg)
-    end;
-    wCompile: begin
-      expectArg(switch, arg, pass, info);
-      if pass in {@set}[passCmd2, passPP] then
-        processCompile(arg);
-    end;
-    wLink: begin
-      expectArg(switch, arg, pass, info);
-      if pass in {@set}[passCmd2, passPP] then
-        addFileToLink(arg);
-    end;
-    wDebuginfo: include(gGlobalOptions, optCDebug);
-    wCompileOnly, wC: include(gGlobalOptions, optCompileOnly);
-    wNoLinking: include(gGlobalOptions, optNoLinking);
-    wForceBuild, wF: include(gGlobalOptions, optForceFullMake);
-    wGC: begin
-      case whichKeyword(arg) of
-        wBoehm: begin
-          include(gGlobalOptions, optBoehmGC);
-          exclude(gGlobalOptions, optRefcGC);
-          DefineSymbol('boehmgc');
-        end;
-        wRefc: begin
-          exclude(gGlobalOptions, optBoehmGC);
-          include(gGlobalOptions, optRefcGC)
-        end;
-        wNone: begin
-          exclude(gGlobalOptions, optRefcGC);
-          exclude(gGlobalOptions, optBoehmGC);
-          defineSymbol('nogc');
-        end
-        else
-          liMessage(info, errNoneBoehmRefcExpectedButXFound, arg)
-      end
-    end;
-    wWarnings, wW: ProcessOnOffSwitch({@set}[optWarns], arg, pass, info);
-    wWarning: ProcessSpecificNote(arg, wWarning, pass, info);
-    wHint: ProcessSpecificNote(arg, wHint, pass, info);
-    wHints: ProcessOnOffSwitch({@set}[optHints], arg, pass, info);
-    wCheckpoints: ProcessOnOffSwitch({@set}[optCheckpoints], arg, pass, info);
-    wStackTrace: ProcessOnOffSwitch({@set}[optStackTrace], arg, pass, info);
-    wLineTrace: ProcessOnOffSwitch({@set}[optLineTrace], arg, pass, info);
-    wDebugger: begin
-      ProcessOnOffSwitch({@set}[optEndb], arg, pass, info);
-      if optEndb in gOptions then
-        DefineSymbol('endb')
-      else
-        UndefSymbol('endb')
-    end;
-    wProfiler: begin
-      ProcessOnOffSwitch({@set}[optProfiler], arg, pass, info);
-      if optProfiler in gOptions then DefineSymbol('profiler')
-      else UndefSymbol('profiler')
-    end;
-    wChecks, wX: ProcessOnOffSwitch(checksOptions, arg, pass, info);
-    wObjChecks: ProcessOnOffSwitch({@set}[optObjCheck], arg, pass, info);
-    wFieldChecks: ProcessOnOffSwitch({@set}[optFieldCheck], arg, pass, info);
-    wRangeChecks: ProcessOnOffSwitch({@set}[optRangeCheck], arg, pass, info);
-    wBoundChecks: ProcessOnOffSwitch({@set}[optBoundsCheck], arg, pass, info);
-    wOverflowChecks: ProcessOnOffSwitch({@set}[optOverflowCheck], arg, pass, info);
-    wLineDir: ProcessOnOffSwitch({@set}[optLineDir], arg, pass, info);
-    wAssertions, wA: ProcessOnOffSwitch({@set}[optAssert], arg, pass, info);
-    wDeadCodeElim: ProcessOnOffSwitchG({@set}[optDeadCodeElim], arg, pass, info);
-    wOpt: begin
-      case whichKeyword(arg) of
-        wSpeed: begin
-          include(gOptions, optOptimizeSpeed);
-          exclude(gOptions, optOptimizeSize)
-        end;
-        wSize: begin
-          exclude(gOptions, optOptimizeSpeed);
-          include(gOptions, optOptimizeSize)
-        end;
-        wNone: begin
-          exclude(gOptions, optOptimizeSpeed);
-          exclude(gOptions, optOptimizeSize)
-        end
-        else
-          liMessage(info, errNoneSpeedOrSizeExpectedButXFound, arg)
-      end
-    end;
-    wApp: begin
-      case whichKeyword(arg) of
-        wGui: begin
-          include(gGlobalOptions, optGenGuiApp);
-          defineSymbol('guiapp')
-        end;
-        wConsole:
-          exclude(gGlobalOptions, optGenGuiApp);
-        wLib: begin
-          include(gGlobalOptions, optGenDynLib);
-          exclude(gGlobalOptions, optGenGuiApp);
-          defineSymbol('library')
-        end;
-        else
-          liMessage(info, errGuiConsoleOrLibExpectedButXFound, arg)
-      end
-    end;
-    wListDef: begin
-      if pass in {@set}[passCmd2, passPP] then
-        condsyms.listSymbols();
-    end;
-    wPassC, wT: begin
-      expectArg(switch, arg, pass, info);
-      if pass in {@set}[passCmd2, passPP] then
-        extccomp.addCompileOption(arg)
-    end;
-    wPassL, wL: begin
-      expectArg(switch, arg, pass, info);
-      if pass in {@set}[passCmd2, passPP] then
-        extccomp.addLinkOption(arg)
-    end;
-    wIndex: begin
-      expectArg(switch, arg, pass, info);
-      if pass in {@set}[passCmd2, passPP] then
-        gIndexFile := arg
-    end;
-    wImport: begin
-      expectArg(switch, arg, pass, info);
-      options.addImplicitMod(arg);
-    end;
-    wListCmd: include(gGlobalOptions, optListCmd);
-    wGenMapping: include(gGlobalOptions, optGenMapping);
-    wOS: begin
-      if (pass = passCmd1) then begin
-        theOS := platform.NameToOS(arg);
-        if theOS = osNone then
-          liMessage(info, errUnknownOS, arg);
-        if theOS <> platform.hostOS then begin
-          setTarget(theOS, targetCPU);
-          include(gGlobalOptions, optCompileOnly);
-          condsyms.InitDefines()
-        end
-      end
-    end;
-    wCPU: begin
-      if (pass = passCmd1) then begin
-        cpu := platform.NameToCPU(arg);
-        if cpu = cpuNone then
-          liMessage(info, errUnknownCPU, arg);
-        if cpu <> platform.hostCPU then begin
-          setTarget(targetOS, cpu);
-          include(gGlobalOptions, optCompileOnly);
-          condsyms.InitDefines()
-        end
-      end
-    end;
-    wRun, wR: include(gGlobalOptions, optRun);
-    wVerbosity: begin
-      expectArg(switch, arg, pass, info);
-      gVerbosity := parseInt(arg);
-    end;
-    wVersion, wV: writeVersionInfo(pass);
-    wAdvanced: writeAdvancedUsage(pass);
-    wHelp, wH: helpOnError(pass);
-    wSymbolFiles: ProcessOnOffSwitchG({@set}[optSymbolFiles], arg, pass, info);
-    wSkipCfg: include(gGlobalOptions, optSkipConfigFile);
-    wSkipProjCfg: include(gGlobalOptions, optSkipProjConfigFile);
-    wGenScript: include(gGlobalOptions, optGenScript);
-    wLib: begin
-      expectArg(switch, arg, pass, info);
-      libpath := processPath(arg)
-    end;
-    wPutEnv: begin
-      expectArg(switch, arg, pass, info);
-      splitSwitch(arg, key, val, pass, info);
-      nos.putEnv(key, val);
-    end;
-    wCC: begin
-      expectArg(switch, arg, pass, info);
-      setCC(arg)
-    end;
-    wMaxErr: begin
-      expectArg(switch, arg, pass, info);
-      gErrorMax := parseInt(arg);
-    end;
-    else if strutils.find(switch, '.') >= strStart then
-      options.setConfigVar(switch, arg)
-    else
-      InvalidCmdLineOption(pass, switch, info)
-  end
-end;
-
-procedure ProcessCommand(const switch: string; pass: TCmdLinePass);
-var
-  cmd, arg: string;
-  info: TLineInfo;
-begin
-  info := newLineInfo('command line', 1, 1);
-  splitSwitch(switch, cmd, arg, pass, info);
-  ProcessSwitch(cmd, arg, pass, info)
-end;
-
-end.
+//[[[end]]]

+  ;

+

+function getCommandLineDesc: string;

+begin

+  result := format(HelpMessage, [VersionAsString, 

+    platform.os[platform.hostOS].name, cpu[platform.hostCPU].name]) +{&} Usage

+end;

+

+var

+  helpWritten: boolean;  // BUGFIX 19

+  versionWritten: boolean;

+  advHelpWritten: boolean;

+

+procedure HelpOnError(pass: TCmdLinePass);

+begin

+  if (pass = passCmd1) and not helpWritten then begin

+    // BUGFIX 19

+    MessageOut(getCommandLineDesc());

+    helpWritten := true

+  end

+end;

+

+procedure writeAdvancedUsage(pass: TCmdLinePass);

+begin

+  if (pass = passCmd1) and not advHelpWritten then begin

+    // BUGFIX 19

+    MessageOut(format(HelpMessage, [VersionAsString, 

+                                    platform.os[platform.hostOS].name,

+                                    cpu[platform.hostCPU].name]) +{&}

+                                    AdvancedUsage);

+    advHelpWritten := true;

+    helpWritten := true;

+    halt(0);

+  end

+end;

+

+procedure writeVersionInfo(pass: TCmdLinePass);

+begin

+  if (pass = passCmd1) and not versionWritten then begin

+    versionWritten := true;

+    helpWritten := true;

+    messageOut(format(HelpMessage, [VersionAsString, 

+                                    platform.os[platform.hostOS].name,

+                                    cpu[platform.hostCPU].name]))

+  end

+end;

+

+procedure writeCommandLineUsage;

+begin

+  if not helpWritten then begin

+    messageOut(getCommandLineDesc());

+    helpWritten := true

+  end

+end;

+

+procedure InvalidCmdLineOption(pass: TCmdLinePass; const switch: string;

+                               const info: TLineInfo);

+begin

+  liMessage(info, errInvalidCmdLineOption, switch)

+end;

+

+procedure splitSwitch(const switch: string; out cmd, arg: string;

+                      pass: TCmdLinePass; const info: TLineInfo);

+var

+  i: int;

+begin

+  cmd := '';

+  i := strStart;

+  if (i < length(switch)+strStart) and (switch[i] = '-') then inc(i);

+  if (i < length(switch)+strStart) and (switch[i] = '-') then inc(i);

+  while i < length(switch) + strStart do begin

+    case switch[i] of

+      'a'..'z', 'A'..'Z', '0'..'9', '_', '.':

+        addChar(cmd, switch[i]);

+      else break;

+    end;

+    inc(i);

+  end;

+  if i >= length(switch) + strStart then

+    arg := ''

+  else if switch[i] in [':', '=', '['] then

+    arg := ncopy(switch, i + 1)

+  else

+    InvalidCmdLineOption(pass, switch, info)

+end;

+

+procedure ProcessOnOffSwitch(const op: TOptions; const arg: string;

+                             pass: TCmdlinePass; const info: TLineInfo);

+begin

+  case whichKeyword(arg) of

+    wOn:  gOptions := gOptions + op;

+    wOff: gOptions := gOptions - op;

+    else  liMessage(info, errOnOrOffExpectedButXFound, arg)

+  end

+end;

+

+procedure ProcessOnOffSwitchG(const op: TGlobalOptions; const arg: string;

+                              pass: TCmdlinePass; const info: TLineInfo);

+begin

+  case whichKeyword(arg) of

+    wOn:  gGlobalOptions := gGlobalOptions + op;

+    wOff: gGlobalOptions := gGlobalOptions - op;

+    else  liMessage(info, errOnOrOffExpectedButXFound, arg)

+  end

+end;

+

+procedure ExpectArg(const switch, arg: string; pass: TCmdLinePass;

+                    const info: TLineInfo);

+begin

+  if (arg = '') then

+    liMessage(info, errCmdLineArgExpected, switch)

+end;

+

+procedure ExpectNoArg(const switch, arg: string; pass: TCmdLinePass;

+                      const info: TLineInfo);

+begin

+  if (arg <> '') then

+    liMessage(info, errCmdLineNoArgExpected, switch)

+end;

+

+procedure ProcessSpecificNote(const arg: string; state: TSpecialWord;

+                              pass: TCmdlinePass; const info: TLineInfo);

+var

+  i, x: int;

+  n: TNoteKind;

+  id: string;

+begin

+  id := '';

+  // arg = "X]:on|off"

+  i := strStart;

+  n := hintMin;

+  while (i < length(arg)+strStart) and (arg[i] <> ']') do begin

+    addChar(id, arg[i]);

+    inc(i)

+  end;

+  if (i < length(arg)+strStart) and (arg[i] = ']') then

+    inc(i)

+  else

+    InvalidCmdLineOption(pass, arg, info);

+  if (i < length(arg)+strStart) and (arg[i] in [':', '=']) then

+    inc(i)

+  else

+    InvalidCmdLineOption(pass, arg, info);

+  if state = wHint then begin

+    x := findStr(msgs.HintsToStr, id);

+    if x >= 0 then

+      n := TNoteKind(x + ord(hintMin))

+    else

+      InvalidCmdLineOption(pass, arg, info)

+  end

+  else begin

+    x := findStr(msgs.WarningsToStr, id);

+    if x >= 0 then

+      n := TNoteKind(x + ord(warnMin))

+    else

+      InvalidCmdLineOption(pass, arg, info)

+  end;

+  case whichKeyword(ncopy(arg, i)) of

+    wOn: include(gNotes, n);

+    wOff: exclude(gNotes, n);

+    else liMessage(info, errOnOrOffExpectedButXFound, arg)

+  end

+end;

+

+function processPath(const path: string): string;

+begin

+  result := UnixToNativePath(format(path,

+    ['nimrod', getPrefixDir(), 'lib', libpath]))

+end;

+

+procedure processCompile(const filename: string);

+var

+  found, trunc, ext: string;

+begin

+  found := findFile(filename);

+  if found = '' then found := filename;

+  splitFilename(found, trunc, ext);

+  extccomp.addExternalFileToCompile(trunc);

+  extccomp.addFileToLink(completeCFilePath(trunc, false));

+end;

+

+procedure processSwitch(const switch, arg: string; pass: TCmdlinePass;

+                        const info: TLineInfo);

+var

+  theOS: TSystemOS;

+  cpu: TSystemCPU;

+  key, val, path: string;

+begin

+  case whichKeyword(switch) of

+    wPath, wP: begin

+      expectArg(switch, arg, pass, info);

+      path := processPath(arg);

+      {@discard} lists.IncludeStr(options.searchPaths, path)

+    end;

+    wOut, wO: begin

+      expectArg(switch, arg, pass, info);

+      options.outFile := arg;

+    end;

+    wDefine, wD: begin

+      expectArg(switch, arg, pass, info);

+      DefineSymbol(arg)

+    end;

+    wUndef, wU: begin

+      expectArg(switch, arg, pass, info);

+      UndefSymbol(arg)

+    end;

+    wCompile: begin

+      expectArg(switch, arg, pass, info);

+      if pass in {@set}[passCmd2, passPP] then

+        processCompile(arg);

+    end;

+    wLink: begin

+      expectArg(switch, arg, pass, info);

+      if pass in {@set}[passCmd2, passPP] then

+        addFileToLink(arg);

+    end;

+    wDebuginfo: begin

+      expectNoArg(switch, arg, pass, info);

+      include(gGlobalOptions, optCDebug);

+    end;

+    wCompileOnly, wC: begin

+      expectNoArg(switch, arg, pass, info);

+      include(gGlobalOptions, optCompileOnly);

+    end;

+    wNoLinking: begin

+      expectNoArg(switch, arg, pass, info);

+      include(gGlobalOptions, optNoLinking);

+    end;

+    wForceBuild, wF: begin

+      expectNoArg(switch, arg, pass, info);

+      include(gGlobalOptions, optForceFullMake);

+    end;

+    wGC: begin

+      expectArg(switch, arg, pass, info);

+      case whichKeyword(arg) of

+        wBoehm: begin

+          include(gGlobalOptions, optBoehmGC);

+          exclude(gGlobalOptions, optRefcGC);

+          DefineSymbol('boehmgc');

+        end;

+        wRefc: begin

+          exclude(gGlobalOptions, optBoehmGC);

+          include(gGlobalOptions, optRefcGC)

+        end;

+        wNone: begin

+          exclude(gGlobalOptions, optRefcGC);

+          exclude(gGlobalOptions, optBoehmGC);

+          defineSymbol('nogc');

+        end

+        else

+          liMessage(info, errNoneBoehmRefcExpectedButXFound, arg)

+      end

+    end;

+    wWarnings, wW: ProcessOnOffSwitch({@set}[optWarns], arg, pass, info);

+    wWarning: ProcessSpecificNote(arg, wWarning, pass, info);

+    wHint: ProcessSpecificNote(arg, wHint, pass, info);

+    wHints: ProcessOnOffSwitch({@set}[optHints], arg, pass, info);

+    wCheckpoints: ProcessOnOffSwitch({@set}[optCheckpoints], arg, pass, info);

+    wStackTrace: ProcessOnOffSwitch({@set}[optStackTrace], arg, pass, info);

+    wLineTrace: ProcessOnOffSwitch({@set}[optLineTrace], arg, pass, info);

+    wDebugger: begin

+      ProcessOnOffSwitch({@set}[optEndb], arg, pass, info);

+      if optEndb in gOptions then

+        DefineSymbol('endb')

+      else

+        UndefSymbol('endb')

+    end;

+    wProfiler: begin

+      ProcessOnOffSwitch({@set}[optProfiler], arg, pass, info);

+      if optProfiler in gOptions then DefineSymbol('profiler')

+      else UndefSymbol('profiler')

+    end;

+    wChecks, wX: ProcessOnOffSwitch(checksOptions, arg, pass, info);

+    wObjChecks: ProcessOnOffSwitch({@set}[optObjCheck], arg, pass, info);

+    wFieldChecks: ProcessOnOffSwitch({@set}[optFieldCheck], arg, pass, info);

+    wRangeChecks: ProcessOnOffSwitch({@set}[optRangeCheck], arg, pass, info);

+    wBoundChecks: ProcessOnOffSwitch({@set}[optBoundsCheck], arg, pass, info);

+    wOverflowChecks: ProcessOnOffSwitch({@set}[optOverflowCheck], arg, pass, info);

+    wLineDir: ProcessOnOffSwitch({@set}[optLineDir], arg, pass, info);

+    wAssertions, wA: ProcessOnOffSwitch({@set}[optAssert], arg, pass, info);

+    wDeadCodeElim: ProcessOnOffSwitchG({@set}[optDeadCodeElim], arg, pass, info);

+    wOpt: begin

+      expectArg(switch, arg, pass, info);

+      case whichKeyword(arg) of

+        wSpeed: begin

+          include(gOptions, optOptimizeSpeed);

+          exclude(gOptions, optOptimizeSize)

+        end;

+        wSize: begin

+          exclude(gOptions, optOptimizeSpeed);

+          include(gOptions, optOptimizeSize)

+        end;

+        wNone: begin

+          exclude(gOptions, optOptimizeSpeed);

+          exclude(gOptions, optOptimizeSize)

+        end

+        else

+          liMessage(info, errNoneSpeedOrSizeExpectedButXFound, arg)

+      end

+    end;

+    wApp: begin

+      expectArg(switch, arg, pass, info);

+      case whichKeyword(arg) of

+        wGui: begin

+          include(gGlobalOptions, optGenGuiApp);

+          defineSymbol('guiapp')

+        end;

+        wConsole:

+          exclude(gGlobalOptions, optGenGuiApp);

+        wLib: begin

+          include(gGlobalOptions, optGenDynLib);

+          exclude(gGlobalOptions, optGenGuiApp);

+          defineSymbol('library')

+        end;

+        else

+          liMessage(info, errGuiConsoleOrLibExpectedButXFound, arg)

+      end

+    end;

+    wListDef: begin

+      expectNoArg(switch, arg, pass, info);

+      if pass in {@set}[passCmd2, passPP] then

+        condsyms.listSymbols();

+    end;

+    wPassC, wT: begin

+      expectArg(switch, arg, pass, info);

+      if pass in {@set}[passCmd2, passPP] then

+        extccomp.addCompileOption(arg)

+    end;

+    wPassL, wL: begin

+      expectArg(switch, arg, pass, info);

+      if pass in {@set}[passCmd2, passPP] then

+        extccomp.addLinkOption(arg)

+    end;

+    wIndex: begin

+      expectArg(switch, arg, pass, info);

+      if pass in {@set}[passCmd2, passPP] then

+        gIndexFile := arg

+    end;

+    wImport: begin

+      expectArg(switch, arg, pass, info);

+      options.addImplicitMod(arg);

+    end;

+    wListCmd: begin

+      expectNoArg(switch, arg, pass, info);

+      include(gGlobalOptions, optListCmd);

+    end;

+    wGenMapping: begin

+      expectNoArg(switch, arg, pass, info);

+      include(gGlobalOptions, optGenMapping);

+    end;

+    wOS: begin

+      expectArg(switch, arg, pass, info);

+      if (pass = passCmd1) then begin

+        theOS := platform.NameToOS(arg);

+        if theOS = osNone then

+          liMessage(info, errUnknownOS, arg);

+        if theOS <> platform.hostOS then begin

+          setTarget(theOS, targetCPU);

+          include(gGlobalOptions, optCompileOnly);

+          condsyms.InitDefines()

+        end

+      end

+    end;

+    wCPU: begin

+      expectArg(switch, arg, pass, info);

+      if (pass = passCmd1) then begin

+        cpu := platform.NameToCPU(arg);

+        if cpu = cpuNone then

+          liMessage(info, errUnknownCPU, arg);

+        if cpu <> platform.hostCPU then begin

+          setTarget(targetOS, cpu);

+          include(gGlobalOptions, optCompileOnly);

+          condsyms.InitDefines()

+        end

+      end

+    end;

+    wRun, wR: begin

+      expectNoArg(switch, arg, pass, info);

+      include(gGlobalOptions, optRun);

+    end;

+    wVerbosity: begin

+      expectArg(switch, arg, pass, info);

+      gVerbosity := parseInt(arg);

+    end;

+    wVersion, wV: begin

+      expectNoArg(switch, arg, pass, info);

+      writeVersionInfo(pass);

+    end;

+    wAdvanced: begin

+      expectNoArg(switch, arg, pass, info);

+      writeAdvancedUsage(pass);

+    end;

+    wHelp, wH: begin

+      expectNoArg(switch, arg, pass, info);

+      helpOnError(pass);

+    end;

+    wSymbolFiles: ProcessOnOffSwitchG({@set}[optSymbolFiles], arg, pass, info);

+    wSkipCfg: begin

+      expectNoArg(switch, arg, pass, info);

+      include(gGlobalOptions, optSkipConfigFile);

+    end;

+    wSkipProjCfg: begin

+      expectNoArg(switch, arg, pass, info);

+      include(gGlobalOptions, optSkipProjConfigFile);

+    end;

+    wGenScript: begin

+      expectNoArg(switch, arg, pass, info);

+      include(gGlobalOptions, optGenScript);

+    end;

+    wLib: begin

+      expectArg(switch, arg, pass, info);

+      libpath := processPath(arg)

+    end;

+    wPutEnv: begin

+      expectArg(switch, arg, pass, info);

+      splitSwitch(arg, key, val, pass, info);

+      nos.putEnv(key, val);

+    end;

+    wCC: begin

+      expectArg(switch, arg, pass, info);

+      setCC(arg)

+    end;

+    wMaxErr: begin

+      expectArg(switch, arg, pass, info);

+      gErrorMax := parseInt(arg);

+    end;

+    else if strutils.find(switch, '.') >= strStart then

+      options.setConfigVar(switch, arg)

+    else

+      InvalidCmdLineOption(pass, switch, info)

+  end

+end;

+

+procedure ProcessCommand(const switch: string; pass: TCmdLinePass);

+var

+  cmd, arg: string;

+  info: TLineInfo;

+begin

+  info := newLineInfo('command line', 1, 1);

+  splitSwitch(switch, cmd, arg, pass, info);

+  ProcessSwitch(cmd, arg, pass, info)

+end;

+

+end.

diff --git a/nim/condsyms.pas b/nim/condsyms.pas
index 9c5d64d4b..1df513bbc 100644
--- a/nim/condsyms.pas
+++ b/nim/condsyms.pas
@@ -15,7 +15,7 @@ unit condsyms;
 interface
 
 uses
-  nsystem, ast, astalgo, msgs, hashes, platform, strutils, idents;
+  nsystem, ast, astalgo, msgs, nhashes, platform, strutils, idents;
 
 var
   gSymbols: TStrTable;
diff --git a/nim/docgen.pas b/nim/docgen.pas
index 15969f51d..784ab6c6c 100644
--- a/nim/docgen.pas
+++ b/nim/docgen.pas
@@ -18,7 +18,7 @@ interface
 {$include 'config.inc'}
 
 uses
-  nsystem, charsets, ast, astalgo, strutils, hashes, options, nversion, msgs,
+  nsystem, charsets, ast, astalgo, strutils, nhashes, options, nversion, msgs,
   nos, ropes, idents, wordrecg, nmath, pnimsyn, rnimsyn, scanner, rst, ntime,
   highlite;
 
@@ -722,6 +722,16 @@ begin
   end
 end;
 
+function renderContainer(d: PDoc; n: PRstNode): PRope;
+var
+  arg: PRope;
+begin
+  result := renderRstToHtml(d, n.sons[2]);
+  arg := toRope(strip(getArgument(n)));
+  if arg = nil then result := ropef('<div>$1</div>', [result])
+  else result := ropef('<div class="$1">$2</div>', [arg, result])  
+end;
+
 function renderRstToHtml(d: PDoc; n: PRstNode): PRope;
 var
   outer, inner: string;
@@ -811,6 +821,10 @@ begin
       result := renderCodeBlock(d, n);
       exit
     end;
+    rnContainer: begin 
+      result := renderContainer(d, n);
+      exit
+    end;
     rnSubstitutionReferences, rnSubstitutionDef: outer := '|$1|';
     rnDirective: outer := '';
 
diff --git a/nim/ecmasgen.pas b/nim/ecmasgen.pas
index c9dfcfe25..2eecfba71 100644
--- a/nim/ecmasgen.pas
+++ b/nim/ecmasgen.pas
@@ -17,7 +17,7 @@ interface
 {$include 'config.inc'}
 
 uses
-  nsystem, ast, astalgo, strutils, hashes, trees, platform, magicsys,
+  nsystem, ast, astalgo, strutils, nhashes, trees, platform, magicsys,
   extccomp, options, nversion, nimsets, msgs, crc, bitsets, idents,
   lists, types, nos, ntime, ropes, nmath, passes, ccgutils, wordrecg, rnimsyn,
   rodread;
diff --git a/nim/evals.pas b/nim/evals.pas
index f9ca85c8f..218046c7e 100644
--- a/nim/evals.pas
+++ b/nim/evals.pas
@@ -1,7 +1,7 @@
 //
 //
 //           The Nimrod Compiler
-//        (c) Copyright 2008 Andreas Rumpf
+//        (c) Copyright 2009 Andreas Rumpf
 //
 //    See the file "copying.txt", included in this
 //    distribution, for details about the copyright.
@@ -157,7 +157,7 @@ begin
 end;
 
 var
-  gWhileCounter: int;  // Use a counter to prevend endless loops!
+  gWhileCounter: int;  // Use a counter to prevent endless loops!
                        // We make this counter global, because otherwise
                        // nested loops could make the compiler extremely slow.
   gNestedEvals: int;   // count the recursive calls to ``evalAux`` to prevent
@@ -390,7 +390,7 @@ begin
         stackTrace(c, n, errIndexOutOfBounds);
     end;
     else
-      stackTrace(c, n, errIndexNoIntType);
+      stackTrace(c, n, errNilAccess);
   end
 end;
 
@@ -506,7 +506,8 @@ begin
       result := emptyNode
     end
   end;
-  if result = nil then InternalError(n.info, 'evalSym: ' + n.sym.name.s);
+  if result = nil then 
+    stackTrace(c, n, errCannotInterpretNodeX, n.sym.name.s);
 end;
 
 function evalIncDec(c: PEvalContext; n: PNode; sign: biggestInt): PNode;
@@ -563,8 +564,12 @@ function evalDeref(c: PEvalContext; n: PNode): PNode;
 begin
   result := evalAux(c, n.sons[0]);
   if result.kind = nkExceptBranch then exit;
-  if result.kind <> nkRefTy then InternalError(n.info, 'evalDeref');
-  result := result.sons[0];
+  case result.kind of
+    nkExceptBranch: exit;
+    nkNilLit: stackTrace(c, n, errNilAccess);
+    nkRefTy: result := result.sons[0];
+    else InternalError(n.info, 'evalDeref ' + nodeKindToStr[result.kind]);
+  end;
 end;
 
 function evalAddr(c: PEvalContext; n: PNode): PNode;
@@ -574,7 +579,6 @@ var
 begin
   result := evalAux(c, n.sons[0]);
   if result.kind = nkExceptBranch then exit;
-  if result.kind <> nkRefTy then InternalError(n.info, 'evalDeref');
   a := result;
   t := newType(tyPtr, c.module);
   addSon(t, a.typ);
@@ -732,6 +736,7 @@ end;
 function evalSetLengthSeq(c: PEvalContext; n: PNode): PNode;
 var
   a, b: PNode;
+  newLen, oldLen, i: int;
 begin
   result := evalAux(c, n.sons[1]);
   if result.kind = nkExceptBranch then exit;
@@ -739,8 +744,12 @@ begin
   result := evalAux(c, n.sons[2]);
   if result.kind = nkExceptBranch then exit;
   b := result;
-  if a.kind = nkBracket then setLength(a.sons, int(getOrdValue(b)))
-  else InternalError(n.info, 'evalSetLengthSeq');
+  if a.kind <> nkBracket then InternalError(n.info, 'evalSetLengthSeq');
+  newLen := int(getOrdValue(b));
+  oldLen := sonsLen(a);
+  setLength(a.sons, newLen);
+  for i := oldLen to newLen-1 do
+    a.sons[i] := getNullValue(skipVarGeneric(n.sons[1].typ), n.info);
   result := emptyNode
 end;
 
@@ -758,10 +767,13 @@ begin
   b := result;
 
   t := skipVarGeneric(n.sons[1].typ);
-  result := newNodeIT(nkBracket, n.info, t);
+  if a.kind = nkEmpty then InternalError(n.info, 'first parameter is empty');
+  a.kind := nkBracket;
+  a.info := n.info;
+  a.typ := t;
   for i := 0 to int(getOrdValue(b))-1 do
-    addSon(result, getNullValue(t.sons[0], n.info));
-  // XXX: assign to `a`? result := emptyNode
+    addSon(a, getNullValue(t.sons[0], n.info));
+  result := emptyNode
 end;
 
 function evalAssert(c: PEvalContext; n: PNode): PNode;
@@ -907,7 +919,7 @@ end;
 function evalMagicOrCall(c: PEvalContext; n: PNode): PNode;
 var
   m: TMagic;
-  a, b: PNode;
+  a, b, cc: PNode;
   k: biggestInt;
   i: int;
 begin
@@ -1179,22 +1191,35 @@ begin
     mNError: begin
       result := evalAux(c, n.sons[1]);
       if result.kind = nkExceptBranch then exit;
-      liMessage(n.info, errUser, getStrValue(result));
+      stackTrace(c, n, errUser, getStrValue(result));
       result := emptyNode
     end;
     mConStrStr: result := evalConStrStr(c, n);
     mRepr: result := evalRepr(c, n);
+    mNewString: begin
+      result := evalAux(c, n.sons[1]);
+      if result.kind = nkExceptBranch then exit;
+      a := result;
+      result := newNodeIT(nkStrLit, n.info, n.typ);
+      result.strVal := newString(int(getOrdValue(a)));
+    end;
     else begin
       result := evalAux(c, n.sons[1]);
       if result.kind = nkExceptBranch then exit;
       a := result;
+      b := nil;
+      cc := nil;
       if sonsLen(n) > 2 then begin
         result := evalAux(c, n.sons[2]);
         if result.kind = nkExceptBranch then exit;
-      end
-      else
-        result := nil;
-      result := evalOp(m, n, a, result);
+        b := result;
+        if sonsLen(n) > 3 then begin
+          result := evalAux(c, n.sons[3]);
+          if result.kind = nkExceptBranch then exit;
+          cc := result;
+        end
+      end;
+      result := evalOp(m, n, a, b, cc);
     end
   end
 end;
@@ -1213,7 +1238,7 @@ begin
     nkNilLit: result := n; // end of atoms
 
     nkCall, nkHiddenCallConv, nkMacroStmt: result := evalMagicOrCall(c, n);
-    nkCurly, nkBracket: begin
+    nkCurly, nkBracket, nkRange: begin
       result := copyNode(n);
       for i := 0 to sonsLen(n)-1 do addSon(result, evalAux(c, n.sons[i]));
     end;
diff --git a/nim/extccomp.pas b/nim/extccomp.pas
index f51e5f690..a53ad1c10 100644
--- a/nim/extccomp.pas
+++ b/nim/extccomp.pas
@@ -15,8 +15,8 @@ interface
 {$include 'config.inc'}
 
 uses
-  nsystem, charsets, lists, ropes, nos, strutils, platform, condsyms, options,
-  msgs;
+  nsystem, charsets, lists, ropes, nos, strutils, osproc, platform, condsyms, 
+  options, msgs;
 
 // some things are read in from the configuration file
 
@@ -387,7 +387,7 @@ procedure execExternalProgram(const cmd: string);
 begin
   if (optListCmd in gGlobalOptions) or (gVerbosity > 0) then
     MessageOut('Executing: ' +{&} nl +{&} cmd);
-  if executeShellCommand(cmd) <> 0 then
+  if executeCommand(cmd) <> 0 then
     rawMessage(errExecutionOfProgramFailed);
 end;
 
diff --git a/nim/hashtest.pas b/nim/hashtest.pas
index ba7a62372..7e93ca5bf 100644
--- a/nim/hashtest.pas
+++ b/nim/hashtest.pas
@@ -3,7 +3,7 @@ program hashtest;
 {$include 'config.inc'}
 
 uses
-  hashes;
+  nhashes;
 
 begin
   writeln(output, getNormalizedHash(ParamStr(1)));
diff --git a/nim/highlite.pas b/nim/highlite.pas
index 5ef4acc12..ad7a6f724 100644
--- a/nim/highlite.pas
+++ b/nim/highlite.pas
@@ -17,7 +17,7 @@ interface
 {$include 'config.inc'}
 
 uses
-  charsets, nsystem, sysutils, hashes, options, msgs, strutils, platform,
+  charsets, nsystem, sysutils, nhashes, options, msgs, strutils, platform,
   idents, lexbase, wordrecg, scanner;
 
 type
diff --git a/nim/idents.pas b/nim/idents.pas
index c0e4c994f..c1c1755e9 100644
--- a/nim/idents.pas
+++ b/nim/idents.pas
@@ -17,7 +17,7 @@ unit idents;
 interface
 
 uses
-  hashes, nsystem, strutils;
+  nhashes, nsystem, strutils;
 
 type
   TIdObj = object(NObject)
diff --git a/nim/interact.pas b/nim/interact.pas
index ac238107f..aab3c7fc2 100644
--- a/nim/interact.pas
+++ b/nim/interact.pas
@@ -15,7 +15,7 @@ interface
 {$include 'config.inc'}
 
 uses
-  nsystem, llstream, strutils, charsets, ropes, strtabs, msgs;
+  nsystem, llstream, strutils, charsets, ropes, nstrtabs, msgs;
 
 implementation
 
diff --git a/nim/magicsys.pas b/nim/magicsys.pas
index 7a717e61d..462912995 100644
--- a/nim/magicsys.pas
+++ b/nim/magicsys.pas
@@ -16,7 +16,7 @@ interface
 
 uses
   nsystem,
-  ast, astalgo, hashes, msgs, platform, nversion, ntime, idents, rodread;
+  ast, astalgo, nhashes, msgs, platform, nversion, ntime, idents, rodread;
 
 var // magic symbols in the system module:
   SystemModule: PSym;
diff --git a/nim/main.pas b/nim/main.pas
index c888e5c3c..b1c58c2b9 100644
--- a/nim/main.pas
+++ b/nim/main.pas
@@ -152,7 +152,7 @@ begin
   semanticPasses();
   registerPass(cgen.cgenPass());
   registerPass(rodwrite.rodwritePass());
-  registerPass(cleanupPass());
+  //registerPass(cleanupPass());
   compileProject(filename);
   //for i := low(TTypeKind) to high(TTypeKind) do
   //  MessageOut('kind: ' +{&} typeKindToStr[i] +{&} ' = ' +{&} toString(sameTypeA[i]));
diff --git a/nim/msgs.pas b/nim/msgs.pas
index 0eb1651d9..53e1b3388 100644
--- a/nim/msgs.pas
+++ b/nim/msgs.pas
@@ -96,10 +96,10 @@ type
     errAttemptToRedefine,
     errStmtInvalidAfterReturn,
     errStmtExpected,
-    errYieldOnlyInInterators,
     errInvalidLabel,
     errInvalidCmdLineOption,
     errCmdLineArgExpected,
+    errCmdLineNoArgExpected,
     errInvalidVarSubstitution,
     errUnknownVar,
     errUnknownCcompiler,
@@ -138,7 +138,7 @@ type
     errStaticAssertCannotBeEval,
     errDotRequiresRecordOrObjectType,
     errUndeclaredFieldX,
-    errIndexNoIntType,
+    errNilAccess,
     errIndexOutOfBounds,
     errIndexTypesDoNotMatch,
     errBracketsInvalidForType,
@@ -348,17 +348,17 @@ const
     'exception expected',
     'exception already handled',
     '''return'' only allowed in routine',
-    '''yield'' only allowed in iterator',
+    '''yield'' only allowed in a loop of an iterator',
     'invalid number of ''yield'' expresions',
     '''return'' not allowed in iterator',
     'current routine cannot return an expression',
     'attempt to redefine ''$1''',
     'statement not allowed after ''return'', ''break'' or ''raise''',
     'statement expected',
-    '''yield'' statement is only allowed in iterators',
     '''$1'' is no label',
     'invalid command line option: ''$1''',
     'argument for command line option expected: ''$1''',
+    'invalid argument for command line option: ''$1''',
     'invalid variable substitution in ''$1''',
     'unknown variable: ''$1''',
     'unknown C compiler: ''$1''',
@@ -397,7 +397,7 @@ const
     'argument to ''staticAssert'' cannot be evaluated at compile time',
     '''.'' requires a record or object type',
     'undeclared field: ''$1''',
-    'index has to be an integer type',
+    'attempt to access a nil address',
     'index out of bounds',
     'index types do not match',
     '''[]'' operator invalid for this type',
diff --git a/nim/hashes.pas b/nim/nhashes.pas
index 0d7eb205d..0564f6f47 100644
--- a/nim/hashes.pas
+++ b/nim/nhashes.pas
@@ -6,7 +6,7 @@
 //    See the file "copying.txt", included in this
 //    distribution, for details about the copyright.
 //
-unit hashes;
+unit nhashes;
 
 {$include 'config.inc'}
 
diff --git a/nim/strtabs.pas b/nim/nstrtabs.pas
index 4fcf32891..bcb10f2ed 100644
--- a/nim/strtabs.pas
+++ b/nim/nstrtabs.pas
@@ -6,7 +6,7 @@
 //    See the file "copying.txt", included in this
 //    distribution, for details about the copyright.
 //
-unit strtabs;
+unit nstrtabs;
 
 // String tables.
 
@@ -15,7 +15,7 @@ interface
 {$include 'config.inc'}
 
 uses
-  nsystem, nos, hashes, strutils;
+  nsystem, nos, nhashes, strutils;
 
 type
   TStringTableMode = (
@@ -93,9 +93,9 @@ end;
 function myhash(t: PStringTable; const key: string): THash;
 begin
   case t.mode of
-    modeCaseSensitive: result := hashes.GetHashStr(key);
-    modeCaseInsensitive: result := hashes.GetHashStrCI(key);
-    modeStyleInsensitive: result := hashes.getNormalizedHash(key);
+    modeCaseSensitive: result := nhashes.GetHashStr(key);
+    modeCaseInsensitive: result := nhashes.GetHashStrCI(key);
+    modeStyleInsensitive: result := nhashes.getNormalizedHash(key);
   end
 end;
 
diff --git a/nim/nversion.pas b/nim/nversion.pas
index de0ad2b79..ae6392db9 100644
--- a/nim/nversion.pas
+++ b/nim/nversion.pas
@@ -1,42 +1,42 @@
-//
-//
-//           The Nimrod Compiler
-//        (c) Copyright 2008 Andreas Rumpf
-//
-//    See the file "copying.txt", included in this
-//    distribution, for details about the copyright.
-//
-
-unit nversion;
-
-// this unit implements the version handling
-
-interface
-
-{$include 'config.inc'}
-
-uses
-  strutils;
-
-const
-  MaxSetElements = 1 shl 16; // (2^16) to support unicode character sets?
-  defaultAsmMarkerSymbol = '!';
-
-  //[[[cog
-  //from koch import NIMROD_VERSION
-  //from string import split
-  //cog.outl("VersionAsString = '%s';" % NIMROD_VERSION)
-  //ver = split(NIMROD_VERSION, '.')
-  //cog.outl('VersionMajor = %s;' % ver[0])
-  //cog.outl('VersionMinor = %s;' % ver[1])
-  //cog.outl('VersionPatch = %s;' % ver[2])
-  //]]]
-  VersionAsString = '0.7.6';
+//

+//

+//           The Nimrod Compiler

+//        (c) Copyright 2008 Andreas Rumpf

+//

+//    See the file "copying.txt", included in this

+//    distribution, for details about the copyright.

+//

+

+unit nversion;

+

+// this unit implements the version handling

+

+interface

+

+{$include 'config.inc'}

+

+uses

+  strutils;

+

+const

+  MaxSetElements = 1 shl 16; // (2^16) to support unicode character sets?

+  defaultAsmMarkerSymbol = '!';

+

+  //[[[cog

+  //from koch import NIMROD_VERSION

+  //from string import split

+  //cog.outl("VersionAsString = '%s';" % NIMROD_VERSION)

+  //ver = split(NIMROD_VERSION, '.')

+  //cog.outl('VersionMajor = %s;' % ver[0])

+  //cog.outl('VersionMinor = %s;' % ver[1])

+  //cog.outl('VersionPatch = %s;' % ver[2])

+  //]]]

+  VersionAsString = '0.7.8';
   VersionMajor = 0;
   VersionMinor = 7;
-  VersionPatch = 6;
-  //[[[[end]]]]
-
-implementation
-
-end.
+  VersionPatch = 8;
+  //[[[[end]]]]

+

+implementation

+

+end.

diff --git a/nim/options.pas b/nim/options.pas
index d6f6d14da..f84d8458c 100644
--- a/nim/options.pas
+++ b/nim/options.pas
@@ -13,7 +13,7 @@ interface
 {$include 'config.inc'}
 
 uses
-  nsystem, nos, lists, strutils, strtabs;
+  nsystem, nos, lists, strutils, nstrtabs;
 
 type
   // please make sure we have under 32 options
@@ -150,12 +150,12 @@ end;
 
 function getConfigVar(const key: string): string;
 begin
-  result := strtabs.get(gConfigVars, key);
+  result := nstrtabs.get(gConfigVars, key);
 end;
 
 procedure setConfigVar(const key, val: string);
 begin
-  strtabs.put(gConfigVars, key, val);
+  nstrtabs.put(gConfigVars, key, val);
 end;
 
 function getOutFile(const filename, ext: string): string;
diff --git a/nim/osproc.pas b/nim/osproc.pas
new file mode 100644
index 000000000..dd6bd10f0
--- /dev/null
+++ b/nim/osproc.pas
@@ -0,0 +1,30 @@
+//

+//

+//           The Nimrod Compiler

+//        (c) Copyright 2009 Andreas Rumpf

+//

+//    See the file "copying.txt", included in this

+//    distribution, for details about the copyright.

+//

+unit osproc;

+

+// This module provides Nimrod's osproc module in Pascal

+// Note: Only implement what is really needed here!

+

+interface

+

+{$include 'config.inc'}

+

+uses

+  nsystem, nos;

+

+function executeCommand(const cmd: string): int;

+

+implementation

+

+function executeCommand(const cmd: string): int;

+begin

+  result := executeShellCommand(cmd);

+end;

+

+end.

diff --git a/nim/parsecfg.pas b/nim/parsecfg.pas
index 3c10cc8fc..620335aa6 100644
--- a/nim/parsecfg.pas
+++ b/nim/parsecfg.pas
@@ -17,7 +17,7 @@ interface
 {$include 'config.inc'}
 
 uses
-  nsystem, charsets, llstream, sysutils, hashes, strutils, lexbase;
+  nsystem, charsets, llstream, sysutils, nhashes, strutils, lexbase;
 
 type
   TCfgEventKind = (
diff --git a/nim/paslex.pas b/nim/paslex.pas
index c0136e4d8..da9283163 100644
--- a/nim/paslex.pas
+++ b/nim/paslex.pas
@@ -17,7 +17,7 @@ interface
 
 uses
   charsets, nsystem, sysutils,
-  hashes, options, msgs, strutils, platform, idents,
+  nhashes, options, msgs, strutils, platform, idents,
   lexbase, wordrecg, scanner;
 
 const
diff --git a/nim/pragmas.pas b/nim/pragmas.pas
index 9a60e6bd3..df48f27c9 100644
--- a/nim/pragmas.pas
+++ b/nim/pragmas.pas
@@ -1,7 +1,7 @@
 //
 //
 //           The Nimrod Compiler
-//        (c) Copyright 2008 Andreas Rumpf
+//        (c) Copyright 2009 Andreas Rumpf
 //
 //    See the file "copying.txt", included in this
 //    distribution, for details about the copyright.
@@ -143,7 +143,7 @@ begin
   else v := expectStrLit(c, n);
   Include(s.flags, sfImportc); // magics don't need an implementation, so we
   // treat them as imported, instead of modifing a lot of working code
-  Include(s.loc.Flags, lfNoDecl); // magics don't need to be declared!
+  // BUGFIX: magic does not imply ``lfNoDecl`` anymore!
   for m := low(TMagic) to high(TMagic) do
     if magicToStr[m] = v then begin
       s.magic := m; exit
diff --git a/nim/ropes.pas b/nim/ropes.pas
index 864afd5b8..6b6540c24 100644
--- a/nim/ropes.pas
+++ b/nim/ropes.pas
@@ -64,7 +64,7 @@ interface
 {$include 'config.inc'}
 
 uses
-  nsystem, msgs, strutils, platform, hashes, crc;
+  nsystem, msgs, strutils, platform, nhashes, crc;
 
 const
   CacheLeafs = true;
diff --git a/nim/rst.pas b/nim/rst.pas
index 0c5377646..6d0d476c9 100644
--- a/nim/rst.pas
+++ b/nim/rst.pas
@@ -16,7 +16,7 @@ interface
 {$include 'config.inc'}
 
 uses
-  nsystem, nos, msgs, strutils, platform, hashes, ropes, charsets, options;
+  nsystem, nos, msgs, strutils, platform, nhashes, ropes, charsets, options;
 
 type
   TRstNodeKind = (
@@ -79,6 +79,7 @@ type
     rnImage,
     rnFigure,
     rnCodeBlock,
+    rnContainer,   // ``container`` directive
     rnIndex,       // index directve:
                    // .. index::
                    //   key
@@ -111,9 +112,9 @@ const
     'TableRow', 'TableHeaderCell', 'TableDataCell', 'Label', 'Footnote',
     'Citation', 'StandaloneHyperlink', 'Hyperlink', 'Ref', 'Directive',
     'DirArg', 'Raw', 'Title', 'Contents', 'Image', 'Figure', 'CodeBlock',
-    'Index', 'SubstitutionDef', 'GeneralRole', 'Sub', 'Sup', 'Idx',
-    'Emphasis', 'StrongEmphasis', 'InterpretedText', 'InlineLiteral',
-    'SubstitutionReferences', 'Leaf'
+    'Container', 'Index', 'SubstitutionDef', 'GeneralRole', 
+    'Sub', 'Sup', 'Idx', 'Emphasis', 'StrongEmphasis', 'InterpretedText', 
+    'InlineLiteral', 'SubstitutionReferences', 'Leaf'
   );
 
 type
@@ -1178,12 +1179,12 @@ end;
 
 type
   TDirKind = ( // must be ordered alphabetically!
-    dkNone, dkAuthor, dkAuthors, dkCodeBlock,
+    dkNone, dkAuthor, dkAuthors, dkCodeBlock, dkContainer,
     dkContents, dkFigure, dkImage, dkInclude, dkIndex, dkRaw, dkTitle
   );
 const
-  DirIds: array [0..10] of string = (
-    '', 'author', 'authors', 'code-block',
+  DirIds: array [0..11] of string = (
+    '', 'author', 'authors', 'code-block', 'container',
     'contents', 'figure', 'image', 'include', 'index', 'raw', 'title'
   );
 
@@ -1993,6 +1994,14 @@ begin
   result.kind := rnCodeBlock
 end;
 
+function dirContainer(var p: TRstParser): PRstNode;
+begin
+  result := parseDirective(p, {@set}[hasArg], parseSectionWrapper);
+  assert(result.kind = rnDirective);
+  assert(rsonsLen(result) = 3);
+  result.kind := rnContainer;
+end;
+
 function dirImage(var p: TRstParser): PRstNode;
 begin
   result := parseDirective(p, {@set}[hasOptions, hasArg, argIsFile], nil);
@@ -2071,6 +2080,7 @@ begin
       dkImage:      result := dirImage(p);
       dkFigure:     result := dirFigure(p);
       dkTitle:      result := dirTitle(p);
+      dkContainer:  result := dirContainer(p);
       dkContents:   result := dirContents(p);
       dkRaw:        result := dirRaw(p);
       dkCodeblock:  result := dirCodeBlock(p);
diff --git a/nim/scanner.pas b/nim/scanner.pas
index d035b973b..51532c801 100644
--- a/nim/scanner.pas
+++ b/nim/scanner.pas
@@ -21,7 +21,7 @@ interface
 {$include 'config.inc'}
 
 uses
-  charsets, nsystem, sysutils, hashes, options, msgs, strutils, platform,
+  charsets, nsystem, sysutils, nhashes, options, msgs, strutils, platform,
   idents, lexbase, llstream, wordrecg;
 
 const
diff --git a/nim/sem.pas b/nim/sem.pas
index 3494754fd..09f9bf49b 100644
--- a/nim/sem.pas
+++ b/nim/sem.pas
@@ -112,6 +112,23 @@ begin
   end
 end;
 
+function semAfterMacroCall(c: PContext; n, p: PNode): PNode;
+begin
+  result := n;
+  if (p = nil) or (p.kind <> nkIdent) then
+    liMessage(n.info, errInvalidParamKindX, renderTree(p))
+  else begin
+    case p.ident.id of
+      ord(wExpr): result := semExprWithType(c, result);
+      ord(wStmt): result := semStmt(c, result);
+      ord(wTypeDesc): 
+        result.typ := semTypeNode(c, result, nil);
+      else
+        liMessage(p.info, errInvalidParamKindX, p.ident.s)
+    end
+  end
+end;
+
 function semMacroExpr(c: PContext; n: PNode; sym: PSym): PNode;
 var
   p: PEvalContext;
@@ -128,7 +145,7 @@ begin
   result := s.params[0];
   popStackFrame(p);
   if cyclicTree(result) then liMessage(n.info, errCyclicTree);
-  result := semStmt(c, result);
+  result := semAfterMacroCall(c, result, sym.ast.sons[paramsPos].sons[0]);
   // now, that was easy ...
   // and we get more flexibility than in any other programming language
 end;
@@ -137,14 +154,12 @@ end;
 {$include 'seminst.pas'}
 {$include 'sigmatch.pas'}
 
-
 procedure CheckBool(t: PNode);
 begin
   if (t.Typ = nil) or (skipVarGeneric(t.Typ).kind <> tyBool) then
     liMessage(t.Info, errExprMustBeBool);
 end;
 
-
 procedure typeMismatch(n: PNode; formal, actual: PType);
 begin
   liMessage(n.Info, errGenerated,
@@ -167,13 +182,17 @@ var
   prc: PSym;
   it: PNode;
 begin
-  for i := 0 to sonsLen(c.generics)-1 do begin
+  for i := c.lastGenericIdx to sonsLen(c.generics)-1 do begin
     it := c.generics.sons[i].sons[1];
     if it.kind <> nkSym then InternalError('addCodeForGenerics');
     prc := it.sym;
-    if (prc.kind in [skProc, skConverter]) and (prc.magic = mNone) then 
+    if (prc.kind in [skProc, skConverter]) and (prc.magic = mNone) then begin
+      if (prc.ast = nil) or (prc.ast.sons[codePos] = nil) then 
+        InternalError(prc.info, 'no code for ' + prc.name.s);
       addSon(n, prc.ast);
+    end
   end;
+  c.lastGenericIdx := sonsLen(c.generics);
 end;
 
 function myOpen(module: PSym; const filename: string): PPassContext;
@@ -212,10 +231,21 @@ end;
 function myProcess(context: PPassContext; n: PNode): PNode;
 var
   c: PContext;
+  a: PNode;
 begin
   result := nil;
   c := PContext(context);
   result := semStmt(c, n);
+  // BUGFIX: process newly generated generics here, not at the end!
+  if sonsLen(c.generics) > 0 then begin
+    a := newNodeI(nkStmtList, n.info);
+    addCodeForGenerics(c, a);
+    if sonsLen(a) > 0 then begin
+      // a generic has been added to `a`:
+      addSonIfNotNil(a, result);
+      result := a
+    end
+  end
 end;
 
 function myClose(context: PPassContext; n: PNode): PNode;
@@ -226,7 +256,8 @@ begin
   closeScope(c.tab);    // close module's scope
   rawCloseScope(c.tab); // imported symbols; don't check for unused ones!
   if n = nil then result := newNode(nkStmtList)
-  else result := n;
+  else InternalError(n.info, 'n is not nil');
+  //result := n;
   addCodeForGenerics(c, result);
   popOwner();
   c.p := nil;
diff --git a/nim/semdata.pas b/nim/semdata.pas
index 3393ed4b3..acca48376 100644
--- a/nim/semdata.pas
+++ b/nim/semdata.pas
@@ -55,6 +55,7 @@ type
     libs: TLinkedList;       // all libs used by this module
     p: PProcCon;             // procedure context
     fromCache: bool;         // is the module read from a cache?
+    lastGenericIdx: int;     // used for the generics stack
     semConstExpr: function (c: PContext; n: PNode): PNode;
       // for the pragmas module
   end;
diff --git a/nim/semfold.pas b/nim/semfold.pas
index 781c3b97d..fdbad9f4c 100644
--- a/nim/semfold.pas
+++ b/nim/semfold.pas
@@ -24,7 +24,7 @@ function getConstExpr(module: PSym; n: PNode): PNode;
   // evaluates the constant expression or returns nil if it is no constant
   // expression
 
-function evalOp(m: TMagic; n, a, b: PNode): PNode; 
+function evalOp(m: TMagic; n, a, b, c: PNode): PNode; 
 function leValueConv(a, b: PNode): Boolean;
 
 function newIntNodeT(const intVal: BiggestInt; n: PNode): PNode;
@@ -113,8 +113,8 @@ begin
   InternalError(a.info, 'no symbol for ordinal value: ' + toString(x));
 end;
 
-function evalOp(m: TMagic; n, a, b: PNode): PNode;
-// if this is an unary operation, b is nil
+function evalOp(m: TMagic; n, a, b, c: PNode): PNode;
+// b and c may be nil
 begin
   result := nil;
   case m of
@@ -127,8 +127,9 @@ begin
     mBitnotI, mBitnotI64: result := newIntNodeT(not getInt(a), n);
 
     mLengthStr: result := newIntNodeT(length(getStr(a)), n);
-    mLengthSeq, mLengthArray,
-    mLengthOpenArray: result := newIntNodeT(lengthOrd(a.typ), n);
+    mLengthArray: result := newIntNodeT(lengthOrd(a.typ), n);
+    mLengthSeq, mLengthOpenArray: 
+      result := newIntNodeT(sonsLen(a), n); // BUGFIX
 
     mUnaryPlusI, mUnaryPlusI64, mUnaryPlusF64: result := a; // throw `+` away
     mToFloat, mToBiggestFloat:
@@ -273,6 +274,11 @@ begin
       else
         result := newStrNodeT('true', n)
     end;
+    mCopyStr: 
+      result := newStrNodeT(ncopy(getStr(a), int(getOrdValue(b))+strStart), n);
+    mCopyStrLast: 
+      result := newStrNodeT(ncopy(getStr(a), int(getOrdValue(b))+strStart, 
+                                             int(getOrdValue(c))+strStart), n);
     mFloatToStr: result := newStrNodeT(toStringF(getFloat(a)), n);
     mCStrToStr, mCharToStr: result := newStrNodeT(getStrOrChar(a), n);
     mStrToStr: result := a;
@@ -281,7 +287,7 @@ begin
       result := copyTree(a);
       result.typ := n.typ;
     end;
-    mExit, mInc, ast.mDec, mAssert, mSwap,
+    mNewString, mExit, mInc, ast.mDec, mAssert, mSwap,
     mAppendStrCh, mAppendStrStr, mAppendSeqElem, mAppendSeqSeq,
     mSetLengthStr, mSetLengthSeq, mNLen..mNError: begin end;
     else InternalError(a.info, 'evalOp(' +{&} magicToStr[m] +{&} ')');
@@ -376,7 +382,7 @@ end;
 function getConstExpr(module: PSym; n: PNode): PNode;
 var
   s: PSym;
-  a, b: PNode;
+  a, b, c: PNode;
   i: int;
 begin
   result := nil;
@@ -443,10 +449,14 @@ begin
             if a = nil then exit;
             if sonsLen(n) > 2 then begin
               b := getConstExpr(module, n.sons[2]);
-              if b = nil then exit
+              if b = nil then exit;
+              if sonsLen(n) > 3 then begin
+                c := getConstExpr(module, n.sons[3]);
+                if c = nil then exit;
+              end
             end
             else b := nil;
-            result := evalOp(s.magic, n, a, b);
+            result := evalOp(s.magic, n, a, b, c);
           end
         end
       except
diff --git a/nim/semstmts.pas b/nim/semstmts.pas
index ebf14693c..a5242b526 100644
--- a/nim/semstmts.pas
+++ b/nim/semstmts.pas
@@ -354,7 +354,8 @@ var
 begin
   result := n;
   checkSonsLen(n, 1);
-  if (c.p.owner = nil) or (c.p.owner.kind <> skIterator) then
+  if (c.p.owner = nil) or (c.p.owner.kind <> skIterator)
+  or (c.p.nestedLoopCounter <= 0) then
     liMessage(n.info, errYieldNotAllowedHere);
   if (n.sons[0] <> nil) then begin
     n.sons[0] := SemExprWithType(c, n.sons[0]);
diff --git a/nim/tigen.pas b/nim/tigen.pas
index 937883e5e..687b70920 100644
--- a/nim/tigen.pas
+++ b/nim/tigen.pas
@@ -17,7 +17,7 @@ interface
 {$include 'config.inc'}
 
 uses
-  nsystem, ast, astalgo, strutils, hashes, trees, treetab, platform, magicsys,
+  nsystem, ast, astalgo, strutils, nhashes, trees, treetab, platform, magicsys,
   options, msgs, crc, idents, lists, types, rnimsyn;
   
 function gcWalker(t: PType): PNode;
diff --git a/nim/transf.pas b/nim/transf.pas
index 5d9f44143..c4ed5740c 100644
--- a/nim/transf.pas
+++ b/nim/transf.pas
@@ -801,7 +801,7 @@ begin
       inc(j);
       if isConstExpr(a) then 
         while (j < sonsLen(m)) and isConstExpr(m.sons[j]) do begin
-          a := evalOp(op.magic, m, a, m.sons[j]);
+          a := evalOp(op.magic, m, a, m.sons[j], nil);
           inc(j)
         end;
       addSon(result, a);
diff --git a/nim/treetab.pas b/nim/treetab.pas
index dbd7b5276..31d7aa0cf 100644
--- a/nim/treetab.pas
+++ b/nim/treetab.pas
@@ -15,7 +15,7 @@ interface
 {$include 'config.inc'}
 
 uses
-  nsystem, hashes, ast, astalgo, types;
+  nsystem, nhashes, ast, astalgo, types;
 
 function NodeTableGet(const t: TNodeTable; key: PNode): int;
 procedure NodeTablePut(var t: TNodeTable; key: PNode; val: int);
diff --git a/nim/wordrecg.pas b/nim/wordrecg.pas
index dd2df0047..7957d354b 100644
--- a/nim/wordrecg.pas
+++ b/nim/wordrecg.pas
@@ -19,7 +19,7 @@ interface
 {$include 'config.inc'}
 
 uses
-  nsystem, hashes, strutils, idents;
+  nsystem, nhashes, strutils, idents;
 
 type
   TSpecialWord = (wInvalid,