Browse Source

Merge remote-tracking branch 'origin/main' into unicodekvm

Nikolay Nikolov 3 years ago
parent
commit
2d5f0fbde0
100 changed files with 9679 additions and 1258 deletions
  1. 1 0
      .gitignore
  2. 0 5
      compiler/constexp.pas
  3. 2 2
      compiler/fpcdefs.inc
  4. 6 2
      compiler/hlcg2ll.pas
  5. 19 1
      compiler/i386/cgcpu.pas
  6. 10 6
      compiler/m68k/cgcpu.pas
  7. 11 3
      compiler/mips/cgcpu.pas
  8. 3 1
      compiler/mips/cpupara.pas
  9. 2 0
      compiler/ncgadd.pas
  10. 1 1
      compiler/ncgvmt.pas
  11. 12 3
      compiler/ogwasm.pas
  12. 2 2
      compiler/options.pas
  13. 1 1
      compiler/pdecsub.pas
  14. 19 3
      compiler/powerpc/cgcpu.pas
  15. 38 49
      compiler/powerpc64/cgcpu.pas
  16. 21 13
      compiler/ppcgen/cgppc.pas
  17. 1 1
      compiler/syscinfo.pas
  18. 5 10
      compiler/systems.pas
  19. 31 31
      compiler/systems/t_atari.pas
  20. 2 2
      compiler/systems/t_linux.pas
  21. 34 19
      compiler/wasm32/nwasmutil.pas
  22. 17 17
      compiler/x86/aasmcpu.pas
  23. 2 1
      compiler/x86/cgx86.pas
  24. 6 1
      compiler/x86_64/cgcpu.pas
  25. 15 0
      compiler/x86_64/cpupara.pas
  26. 3 3
      compiler/x86_64/nx64cal.pas
  27. 8 0
      packages/fcl-base/src/csvdocument.pp
  28. 6 4
      packages/fcl-js/src/jstree.pp
  29. 18 0
      packages/fcl-js/tests/tcwriter.pp
  30. 111 43
      packages/fcl-passrc/src/pasresolver.pp
  31. 110 7
      packages/fcl-passrc/src/pasuseanalyzer.pas
  32. 2 287
      packages/fcl-passrc/tests/tcbaseparser.pas
  33. 1 1
      packages/fcl-passrc/tests/tcexprparser.pas
  34. 30 0
      packages/fcl-passrc/tests/tcgenerics.pas
  35. 32 1
      packages/fcl-passrc/tests/tcresolver.pas
  36. 1 1
      packages/fcl-passrc/tests/tcstatements.pas
  37. 6 1
      packages/fcl-passrc/tests/tcuseanalyzer.pas
  38. 1 1
      packages/fcl-passrc/tests/testpassrc.lpr
  39. 299 0
      packages/fcl-passrc/tests/testpasutils.pas
  40. 0 1
      packages/fcl-web/src/base/fphttpclient.pp
  41. 14 5
      packages/fcl-web/src/base/httproute.pp
  42. 2 2
      packages/ide/Makefile
  43. 1 1
      packages/ide/Makefile.fpc
  44. 10 1
      packages/ide/compiler/Makefile
  45. 14 0
      packages/ide/compiler/Makefile.fpc
  46. 3 1
      packages/ide/fpmake.pp
  47. 181 13
      packages/pastojs/src/fppas2js.pp
  48. 0 3
      packages/pastojs/src/pas2jscompiler.pp
  49. 2 1
      packages/pastojs/src/pas2jsfiler.pp
  50. 5 5
      packages/pastojs/tests/tcconverter.pas
  51. 6 6
      packages/pastojs/tests/tcfiler.pas
  52. 131 7
      packages/pastojs/tests/tcgenerics.pas
  53. 695 69
      packages/pastojs/tests/tcmodules.pas
  54. 2 2
      packages/pastojs/tests/tcoptimizations.pas
  55. 504 0
      packages/pastojs/tests/tcpas2jsanalyzer.pas
  56. 1 1
      packages/pastojs/tests/tcsrcmap.pas
  57. 34 0
      packages/pastojs/tests/tcunitsearch.pas
  58. 12 2
      packages/pastojs/tests/testpas2js.lpi
  59. 2 1
      packages/pastojs/tests/testpas2js.pp
  60. 41 0
      packages/paszlib/examples/testgzstream.pp
  61. 259 0
      packages/paszlib/src/zstream.pp
  62. 1 1
      packages/rtl-extra/fpmake.pp
  63. 29 0
      packages/rtl-extra/src/atari/printer.pp
  64. 3 0
      packages/tosunits/fpmake.pp
  65. 508 301
      packages/tosunits/src/aes.pas
  66. 800 0
      packages/tosunits/src/aestypes.inc
  67. 643 0
      packages/tosunits/src/gem.pas
  68. 46 0
      packages/tosunits/src/gemcommon.pas
  69. 1 0
      packages/tosunits/src/gemdos.pas
  70. 3 2
      packages/tosunits/src/metados.pas
  71. 246 0
      packages/tosunits/src/nf_ops.pas
  72. 43 23
      packages/tosunits/src/tos.pas
  73. 3053 251
      packages/tosunits/src/vdi.pas
  74. 338 0
      packages/tosunits/src/vditypes.inc
  75. 2 2
      rtl/aarch64/aarch64.inc
  76. 48 1
      rtl/atari/dos.pp
  77. 2 0
      rtl/atari/gemdos.inc
  78. 15 2
      rtl/atari/si_prc.pp
  79. 5 5
      rtl/atari/sysfile.inc
  80. 10 10
      rtl/atari/sysos.inc
  81. 43 5
      rtl/atari/system.pp
  82. 2 0
      rtl/i386/cpu.pp
  83. 20 4
      rtl/inc/system.inc
  84. 2 0
      rtl/linux/linuxvcs.pp
  85. 96 0
      rtl/linux/mips64/sighndh.inc
  86. 49 0
      rtl/linux/mips64/stat.inc
  87. 200 0
      rtl/linux/mips64/syscall.inc
  88. 43 0
      rtl/linux/mips64/syscallh.inc
  89. 503 0
      rtl/linux/mips64/sysnr.inc
  90. 1 0
      rtl/linux/mips64el/sighndh.inc
  91. 1 0
      rtl/linux/mips64el/stat.inc
  92. 1 0
      rtl/linux/mips64el/syscall.inc
  93. 1 0
      rtl/linux/mips64el/syscallh.inc
  94. 1 0
      rtl/linux/mips64el/sysnr.inc
  95. 30 7
      rtl/m68k/m68k.inc
  96. 15 0
      rtl/mips64/cpuh.inc
  97. 13 0
      rtl/mips64/math.inc
  98. 13 0
      rtl/mips64/mips64.inc
  99. 26 0
      rtl/mips64/setjumph.inc
  100. 15 0
      rtl/mips64el/cpuh.inc

+ 1 - 0
.gitignore

@@ -27,6 +27,7 @@
 *.diff
 *.diff
 *.lst
 *.lst
 *.app
 *.app
+*.ttp
 fpcmade.*
 fpcmade.*
 *-stamp.*
 *-stamp.*
 build-stamp.*
 build-stamp.*

+ 0 - 5
compiler/constexp.pas

@@ -26,9 +26,6 @@ unit constexp;
 
 
 interface
 interface
 
 
-  uses
-    sfpux80;
-
 type  Tconstexprint=record
 type  Tconstexprint=record
         overflow:boolean;
         overflow:boolean;
         case signed:boolean of
         case signed:boolean of
@@ -40,8 +37,6 @@ type  Tconstexprint=record
 
 
       errorproc=procedure (i:longint);
       errorproc=procedure (i:longint);
 
 
-      TConstExprFloat = float128;
-
 {"Uses verbose" gives a dependency on cpuinfo through globals. This leads
 {"Uses verbose" gives a dependency on cpuinfo through globals. This leads
  build trouble when compiling the directory utils, since the cpu directory
  build trouble when compiling the directory utils, since the cpu directory
  isn't searched there. Therefore we use a procvar and make verbose install
  isn't searched there. Therefore we use a procvar and make verbose install

+ 2 - 2
compiler/fpcdefs.inc

@@ -276,10 +276,10 @@
   {$endif mips}
   {$endif mips}
 {$endif mipsel}
 {$endif mipsel}
 
 
-{$ifdef mips64}
+{$ifdef mips64eb}
   {$define mips}
   {$define mips}
   {$define mips64}
   {$define mips64}
-{$endif mips64}
+{$endif mips64eb}
 
 
 {$ifdef mips64el}
 {$ifdef mips64el}
   {$define mips}
   {$define mips}

+ 6 - 2
compiler/hlcg2ll.pas

@@ -1492,10 +1492,14 @@ implementation
             LOC_CMMREGISTER:
             LOC_CMMREGISTER:
               cg.a_loadmm_ref_cgpara(list,locsize,l.reference,cgpara,mms_movescalar);
               cg.a_loadmm_ref_cgpara(list,locsize,l.reference,cgpara,mms_movescalar);
             { Some targets pass floats in normal registers }
             { Some targets pass floats in normal registers }
+            LOC_REFERENCE,
+            LOC_CREFERENCE:
+              if use_vectorfpu(size) then
+                cg.a_loadmm_ref_cgpara(list,locsize,l.reference,cgpara,mms_movescalar)
+              else
+                cg.a_loadfpu_ref_cgpara(list,locsize,l.reference,cgpara);
             LOC_REGISTER,
             LOC_REGISTER,
             LOC_CREGISTER,
             LOC_CREGISTER,
-            LOC_REFERENCE,
-            LOC_CREFERENCE,
             LOC_FPUREGISTER,
             LOC_FPUREGISTER,
             LOC_CFPUREGISTER:
             LOC_CFPUREGISTER:
               cg.a_loadfpu_ref_cgpara(list,locsize,l.reference,cgpara);
               cg.a_loadfpu_ref_cgpara(list,locsize,l.reference,cgpara);

+ 19 - 1
compiler/i386/cgcpu.pas

@@ -378,6 +378,10 @@ unit cgcpu;
             list.concat(Taicpu.Op_reg(A_POP,S_W,NR_FS));
             list.concat(Taicpu.Op_reg(A_POP,S_W,NR_FS));
             list.concat(Taicpu.Op_reg(A_POP,S_W,NR_GS));
             list.concat(Taicpu.Op_reg(A_POP,S_W,NR_GS));
             { this restores the flags }
             { this restores the flags }
+
+            if current_procinfo.framepointer<>NR_STACK_POINTER_REG then
+              list.concat(tai_regalloc.dealloc(NR_STACK_POINTER_REG,nil));
+
             list.concat(Taicpu.Op_none(A_IRET,S_NO));
             list.concat(Taicpu.Op_none(A_IRET,S_NO));
           end
           end
         { Routines with the poclearstack flag set use only a ret }
         { Routines with the poclearstack flag set use only a ret }
@@ -388,6 +392,9 @@ unit cgcpu;
            { but not on win32 }
            { but not on win32 }
            { and not for safecall with hidden exceptions, because the result }
            { and not for safecall with hidden exceptions, because the result }
            { wich contains the exception is passed in EAX }
            { wich contains the exception is passed in EAX }
+           if current_procinfo.framepointer<>NR_STACK_POINTER_REG then
+             list.concat(tai_regalloc.dealloc(NR_STACK_POINTER_REG,nil));
+
            if ((target_info.system <> system_i386_win32) or
            if ((target_info.system <> system_i386_win32) or
                (target_info.abi=abi_old_win32_gnu)) and
                (target_info.abi=abi_old_win32_gnu)) and
               not ((current_procinfo.procdef.proccalloption = pocall_safecall) and
               not ((current_procinfo.procdef.proccalloption = pocall_safecall) and
@@ -398,16 +405,27 @@ unit cgcpu;
            else
            else
              list.concat(Taicpu.Op_none(A_RET,S_NO));
              list.concat(Taicpu.Op_none(A_RET,S_NO));
          end
          end
+
         { ... also routines with parasize=0 }
         { ... also routines with parasize=0 }
         else if (parasize=0) then
         else if (parasize=0) then
-         list.concat(Taicpu.Op_none(A_RET,S_NO))
+         begin
+           if current_procinfo.framepointer<>NR_STACK_POINTER_REG then
+             list.concat(tai_regalloc.dealloc(NR_STACK_POINTER_REG,nil));
+
+           list.concat(Taicpu.Op_none(A_RET,S_NO))
+         end
         else
         else
          begin
          begin
            { parameters are limited to 65535 bytes because ret allows only imm16 }
            { parameters are limited to 65535 bytes because ret allows only imm16 }
            if (parasize>65535) then
            if (parasize>65535) then
              CGMessage(cg_e_parasize_too_big);
              CGMessage(cg_e_parasize_too_big);
+
+           if current_procinfo.framepointer<>NR_STACK_POINTER_REG then
+             list.concat(tai_regalloc.dealloc(NR_STACK_POINTER_REG,nil));
+
            list.concat(Taicpu.Op_const(A_RET,S_W,parasize));
            list.concat(Taicpu.Op_const(A_RET,S_W,parasize));
          end;
          end;
+
       end;
       end;
 
 
 
 

+ 10 - 6
compiler/m68k/cgcpu.pas

@@ -930,7 +930,13 @@ unit cgcpu;
        opsize: topsize;
        opsize: topsize;
        needsext: boolean;
        needsext: boolean;
       begin
       begin
-         if needs_unaligned(ref.alignment,fromsize) then
+         needsext:=tcgsize2size[fromsize]<tcgsize2size[tosize];
+         if needsext then
+           size:=fromsize
+         else
+           size:=tosize;
+
+         if needs_unaligned(ref.alignment,size) then
            begin
            begin
              //list.concat(tai_comment.create(strpnew('a_load_ref_reg calling unaligned')));
              //list.concat(tai_comment.create(strpnew('a_load_ref_reg calling unaligned')));
              a_load_ref_reg_unaligned(list,fromsize,tosize,ref,register);
              a_load_ref_reg_unaligned(list,fromsize,tosize,ref,register);
@@ -940,11 +946,6 @@ unit cgcpu;
          href:=ref;
          href:=ref;
          fixref(list,href,false);
          fixref(list,href,false);
 
 
-         needsext:=tcgsize2size[fromsize]<tcgsize2size[tosize];
-         if needsext then
-           size:=fromsize
-         else
-           size:=tosize;
          opsize:=TCGSize2OpSize[size];
          opsize:=TCGSize2OpSize[size];
          if isaddressregister(register) and not (opsize in [S_L]) then
          if isaddressregister(register) and not (opsize in [S_L]) then
            hreg:=getintregister(list,OS_ADDR)
            hreg:=getintregister(list,OS_ADDR)
@@ -1771,6 +1772,9 @@ unit cgcpu;
          srcrefp,dstrefp : treference;
          srcrefp,dstrefp : treference;
          srcref,dstref : treference;
          srcref,dstref : treference;
       begin
       begin
+         if (len < 1) then
+           exit;
+
          if (len = 1) or
          if (len = 1) or
             ((len in [2,4]) and
             ((len in [2,4]) and
              not needs_unaligned(source.alignment,lentocgsize[len]) and
              not needs_unaligned(source.alignment,lentocgsize[len]) and

+ 11 - 3
compiler/mips/cgcpu.pas

@@ -550,6 +550,10 @@ begin
         list.concat(taicpu.op_reg_reg_const(A_ANDI, reg2, reg1, $ff));
         list.concat(taicpu.op_reg_reg_const(A_ANDI, reg2, reg1, $ff));
       OS_16:
       OS_16:
         list.concat(taicpu.op_reg_reg_const(A_ANDI, reg2, reg1, $ffff));
         list.concat(taicpu.op_reg_reg_const(A_ANDI, reg2, reg1, $ffff));
+{$ifdef cpu64bitalu}
+      OS_64,
+      OS_S64,
+{$endif cpu64bitalu}
       OS_32,
       OS_32,
       OS_S32:
       OS_S32:
         done:=false;
         done:=false;
@@ -1237,8 +1241,12 @@ begin
   case size of
   case size of
     OS_32:  asmop:=A_MULTU;
     OS_32:  asmop:=A_MULTU;
     OS_S32: asmop:=A_MULT;
     OS_S32: asmop:=A_MULT;
+{$ifdef cpu64bitalu}
+    OS_64:  asmop:=A_DMULTU;
+    OS_S64: asmop:=A_DMULT;
+{$endif cpu64bitalu}
   else
   else
-    InternalError(2014060802);
+    InternalError(2022020901);
   end;
   end;
   list.concat(taicpu.op_reg_reg(asmop,src1,src2));
   list.concat(taicpu.op_reg_reg(asmop,src1,src2));
   if (dstlo<>NR_NO) then
   if (dstlo<>NR_NO) then
@@ -1607,7 +1615,7 @@ begin
         list.concat(taicpu.op_reg_ref(A_SW, tmpreg1, dst));
         list.concat(taicpu.op_reg_ref(A_SW, tmpreg1, dst));
         Inc(src.offset, 4);
         Inc(src.offset, 4);
         Inc(dst.offset, 4);
         Inc(dst.offset, 4);
-	Inc(count2);
+        Inc(count2);
       end;
       end;
       len := len mod 4;
       len := len mod 4;
     end;
     end;
@@ -1679,7 +1687,7 @@ begin
     begin
     begin
       { unrolled loop }
       { unrolled loop }
       tmpreg1 := GetIntRegister(list, OS_INT);
       tmpreg1 := GetIntRegister(list, OS_INT);
-      i:=1;
+      i := 1;
       while i <= len do
       while i <= len do
       begin
       begin
         list.concat(taicpu.op_reg_ref(A_LBU, tmpreg1, src));
         list.concat(taicpu.op_reg_ref(A_LBU, tmpreg1, src));

+ 3 - 1
compiler/mips/cpupara.pas

@@ -365,7 +365,8 @@ implementation
             while paralen>0 do
             while paralen>0 do
               begin
               begin
                 paraloc:=hp.paraloc[side].add_location;
                 paraloc:=hp.paraloc[side].add_location;
-                { We can allocate at maximum 32 bits per register }
+{$ifndef cpu64bitalu}
+                { We can allocate at maximum 32 bits per register on mips32 }
                 if (paracgsize in [OS_64,OS_S64]) or
                 if (paracgsize in [OS_64,OS_S64]) or
                    ((paracgsize in [OS_F32,OS_F64]) and
                    ((paracgsize in [OS_F32,OS_F64]) and
                      not(can_use_float)) then
                      not(can_use_float)) then
@@ -374,6 +375,7 @@ implementation
                     paraloc^.def:=u32inttype;
                     paraloc^.def:=u32inttype;
                   end
                   end
                 else
                 else
+{$endif cpu64bitalu}
                   begin
                   begin
                     paraloc^.size:=paracgsize;
                     paraloc^.size:=paracgsize;
                     paraloc^.def:=locdef;
                     paraloc^.def:=locdef;

+ 2 - 0
compiler/ncgadd.pas

@@ -786,9 +786,11 @@ interface
               if is_boolean(left.resultdef) and
               if is_boolean(left.resultdef) and
                  is_boolean(right.resultdef) then
                  is_boolean(right.resultdef) then
                 second_opboolean
                 second_opboolean
+{$ifndef cpu64bitalu}
               { 64bit operations }
               { 64bit operations }
               else if is_64bit(left.resultdef) then
               else if is_64bit(left.resultdef) then
                 second_op64bit
                 second_op64bit
+{$endif cpu64bitalu}
               else
               else
                 second_opordinal;
                 second_opordinal;
             end;
             end;

+ 1 - 1
compiler/ncgvmt.pas

@@ -1234,7 +1234,7 @@ implementation
           between code fragments that use a different TOC (which has to be
           between code fragments that use a different TOC (which has to be
           executed when that "branch" returns). So we can't use tail call
           executed when that "branch" returns). So we can't use tail call
           branches to routines potentially using a different TOC there }
           branches to routines potentially using a different TOC there }
-        if target_info.system in systems_ppc_toc then
+        if target_info.abi in abis_ppc_toc then
           usehighlevelwrapper:=true
           usehighlevelwrapper:=true
         else
         else
           usehighlevelwrapper:=false;
           usehighlevelwrapper:=false;

+ 12 - 3
compiler/ogwasm.pas

@@ -1025,7 +1025,10 @@ implementation
                       if not assigned(objrel.symbol) then
                       if not assigned(objrel.symbol) then
                         internalerror(2021092509);
                         internalerror(2021092509);
                       objsec.Data.seek(objrel.DataOffset);
                       objsec.Data.seek(objrel.DataOffset);
-                      WriteUleb5(objsec.Data,TWasmObjSymbol(objrel.symbol).FuncIndex);
+                      if TWasmObjSymbol(objrel.symbol).FuncIndex<0 then
+                        internalerror(2022012401)
+                      else
+                        WriteUleb5(objsec.Data,TWasmObjSymbol(objrel.symbol).FuncIndex);
                     end;
                     end;
                   RELOC_MEMORY_ADDR_OR_TABLE_INDEX_SLEB:
                   RELOC_MEMORY_ADDR_OR_TABLE_INDEX_SLEB:
                     begin
                     begin
@@ -1064,14 +1067,20 @@ implementation
                       if not assigned(objrel.symbol) then
                       if not assigned(objrel.symbol) then
                         internalerror(2021092509);
                         internalerror(2021092509);
                       objsec.Data.seek(objrel.DataOffset);
                       objsec.Data.seek(objrel.DataOffset);
-                      WriteUleb5(objsec.Data,TWasmObjSymbol(objrel.symbol).GlobalIndex);
+                      if TWasmObjSymbol(objrel.symbol).GlobalIndex<0 then
+                        internalerror(2022012402)
+                      else
+                        WriteUleb5(objsec.Data,TWasmObjSymbol(objrel.symbol).GlobalIndex);
                     end;
                     end;
                   RELOC_TAG_INDEX_LEB:
                   RELOC_TAG_INDEX_LEB:
                     begin
                     begin
                       if not assigned(objrel.symbol) then
                       if not assigned(objrel.symbol) then
                         internalerror(2021092716);
                         internalerror(2021092716);
                       objsec.Data.seek(objrel.DataOffset);
                       objsec.Data.seek(objrel.DataOffset);
-                      WriteSleb5(objsec.Data,TWasmObjSymbol(objrel.symbol).TagIndex);
+                      if TWasmObjSymbol(objrel.symbol).TagIndex<0 then
+                        internalerror(2022012403)
+                      else
+                        WriteSleb5(objsec.Data,TWasmObjSymbol(objrel.symbol).TagIndex);
                     end;
                     end;
                   else
                   else
                     internalerror(2021092510);
                     internalerror(2021092510);

+ 2 - 2
compiler/options.pas

@@ -4204,7 +4204,7 @@ procedure read_arguments(cmd:TCmdStr);
         def_system_macro('FPC_LOCALS_ARE_STACK_REG_RELATIVE');
         def_system_macro('FPC_LOCALS_ARE_STACK_REG_RELATIVE');
       {$endif mipseb}
       {$endif mipseb}
 
 
-      {$ifdef mips64}
+      {$ifdef mips64eb}
         def_system_macro('CPUMIPS');
         def_system_macro('CPUMIPS');
         def_system_macro('CPUMIPS64');
         def_system_macro('CPUMIPS64');
         def_system_macro('CPUMIPSEB64');
         def_system_macro('CPUMIPSEB64');
@@ -4216,7 +4216,7 @@ procedure read_arguments(cmd:TCmdStr);
         def_system_macro('FPC_REQUIRES_PROPER_ALIGNMENT');
         def_system_macro('FPC_REQUIRES_PROPER_ALIGNMENT');
         { See comment above for mipsel }
         { See comment above for mipsel }
         def_system_macro('FPC_LOCALS_ARE_STACK_REG_RELATIVE');
         def_system_macro('FPC_LOCALS_ARE_STACK_REG_RELATIVE');
-      {$endif mips64}
+      {$endif mips64eb}
 
 
       {$ifdef mips64el}
       {$ifdef mips64el}
         def_system_macro('CPUMIPS');
         def_system_macro('CPUMIPS');

+ 1 - 1
compiler/pdecsub.pas

@@ -2197,7 +2197,7 @@ procedure pd_syscall(pd:tabstractprocdef);
                 system_i386_aros:
                 system_i386_aros:
                     result:='eax';
                     result:='eax';
                 system_x86_64_aros:
                 system_x86_64_aros:
-                    result:='rax';
+                    result:='r12';
                 system_powerpc_morphos:
                 system_powerpc_morphos:
                     result:='r12';
                     result:='r12';
                 else
                 else

+ 19 - 3
compiler/powerpc/cgcpu.pas

@@ -911,9 +911,17 @@ const
               end;
               end;
           end;
           end;
 
 
-        { save the CR if necessary ( !!! never done currently ) }
-{       still need to find out where this has to be done for SystemV
-        a_reg_alloc(list,R_0);
+        { save current RTOC for restoration after calls if necessary }
+        if (pi_do_call in current_procinfo.flags) and
+           (target_info.abi in abis_ppc_toc) then
+          begin
+            reference_reset_base(href,NR_STACK_POINTER_REG,get_rtoc_offset,ctempposinvalid,target_info.stackalign,[]);
+            a_load_reg_ref(list,OS_ADDR,OS_ADDR,NR_RTOC,href);
+          end;
+
+        { save the CR if/when we ever start using caller-save portions of that
+          register}
+{       a_reg_alloc(list,R_0);
         list.concat(taicpu.op_reg_reg(A_MFSPR,R_0,R_CR);
         list.concat(taicpu.op_reg_reg(A_MFSPR,R_0,R_CR);
         list.concat(taicpu.op_reg_ref(A_STW,scratch_register,
         list.concat(taicpu.op_reg_ref(A_STW,scratch_register,
           new_reference(STACK_POINTER_REG,LA_CR)));
           new_reference(STACK_POINTER_REG,LA_CR)));
@@ -1306,6 +1314,14 @@ const
                 a_reg_dealloc(list,href.index);
                 a_reg_dealloc(list,href.index);
               end;
               end;
           end;
           end;
+
+        { save current RTOC for restoration after calls if necessary }
+        if pi_do_call in current_procinfo.flags then
+          begin
+            reference_reset_base(href,NR_STACK_POINTER_REG,get_rtoc_offset,ctempposinvalid,target_info.stackalign,[]);
+            a_load_reg_ref(list,OS_ADDR,OS_ADDR,NR_RTOC,href);
+          end;
+
       end;
       end;
 
 
     procedure tcgppc.g_return_from_proc_mac(list : TAsmList;parasize : tcgint);
     procedure tcgppc.g_return_from_proc_mac(list : TAsmList;parasize : tcgint);

+ 38 - 49
compiler/powerpc64/cgcpu.pas

@@ -305,22 +305,6 @@ begin
 end;
 end;
 
 
 
 
-function get_rtoc_offset: longint;
-begin
-  result:=0;
-  case target_info.abi of
-    abi_powerpc_aix,
-    abi_powerpc_darwin:
-      result:=LA_RTOC_AIX;
-    abi_powerpc_elfv1:
-      result:=LA_RTOC_SYSV;
-    abi_powerpc_elfv2:
-      result:=LA_RTOC_ELFV2;
-    else
-      internalerror(2015021001);
-  end;
-end;
-
 { calling a procedure by address }
 { calling a procedure by address }
 
 
 procedure tcgppc.a_call_reg(list: TAsmList; reg: tregister);
 procedure tcgppc.a_call_reg(list: TAsmList; reg: tregister);
@@ -330,40 +314,44 @@ var
 begin
 begin
   if (target_info.abi<>abi_powerpc_sysv) then
   if (target_info.abi<>abi_powerpc_sysv) then
     inherited a_call_reg(list,reg)
     inherited a_call_reg(list,reg)
-  else if (not (cs_opt_size in current_settings.optimizerswitches)) then begin
-    tempreg := getintregister(list, OS_INT);
-    { load actual function entry (reg contains the reference to the function descriptor)
-    into tempreg }
-    reference_reset_base(tmpref, reg, 0, ctempposinvalid, sizeof(pint), []);
-    a_load_ref_reg(list, OS_ADDR, OS_ADDR, tmpref, tempreg);
-
-    { move actual function pointer to CTR register }
-    list.concat(taicpu.op_reg(A_MTCTR, tempreg));
-
-    { load new TOC pointer from function descriptor into RTOC register }
-    reference_reset_base(tmpref, reg, tcgsize2size[OS_ADDR], ctempposinvalid, 8, []);
+  else
+    begin
+      if (not (cs_opt_size in current_settings.optimizerswitches)) then
+        begin
+          tempreg := getintregister(list, OS_INT);
+          { load actual function entry (reg contains the reference to the function descriptor)
+          into tempreg }
+          reference_reset_base(tmpref, reg, 0, ctempposinvalid, sizeof(pint), []);
+          a_load_ref_reg(list, OS_ADDR, OS_ADDR, tmpref, tempreg);
+
+          { move actual function pointer to CTR register }
+          list.concat(taicpu.op_reg(A_MTCTR, tempreg));
+
+          { load new TOC pointer from function descriptor into RTOC register }
+          reference_reset_base(tmpref, reg, tcgsize2size[OS_ADDR], ctempposinvalid, 8, []);
+          a_load_ref_reg(list, OS_ADDR, OS_ADDR, tmpref, NR_RTOC);
+
+          { load new environment pointer from function descriptor into R11 register }
+          reference_reset_base(tmpref, reg, 2*tcgsize2size[OS_ADDR], ctempposinvalid, 8, []);
+          a_reg_alloc(list, NR_R11);
+          a_load_ref_reg(list, OS_ADDR, OS_ADDR, tmpref, NR_R11);
+          { call function }
+          list.concat(taicpu.op_none(A_BCTRL));
+          a_reg_dealloc(list, NR_R11);
+        end
+    else
+      begin
+        { call ptrgl helper routine which expects the pointer to the function descriptor
+        in R11 }
+        a_reg_alloc(list, NR_R11);
+        a_load_reg_reg(list, OS_ADDR, OS_ADDR, reg, NR_R11);
+        a_call_name_direct(list, A_BL, '.ptrgl', false, false, false);
+        a_reg_dealloc(list, NR_R11);
+      end;
+    { we need to load the old RTOC from stackframe because we changed it}
+    reference_reset_base(tmpref, NR_STACK_POINTER_REG, get_rtoc_offset, ctempposinvalid, 8, []);
     a_load_ref_reg(list, OS_ADDR, OS_ADDR, tmpref, NR_RTOC);
     a_load_ref_reg(list, OS_ADDR, OS_ADDR, tmpref, NR_RTOC);
-
-    { load new environment pointer from function descriptor into R11 register }
-    reference_reset_base(tmpref, reg, 2*tcgsize2size[OS_ADDR], ctempposinvalid, 8, []);
-    a_reg_alloc(list, NR_R11);
-    a_load_ref_reg(list, OS_ADDR, OS_ADDR, tmpref, NR_R11);
-    { call function }
-    list.concat(taicpu.op_none(A_BCTRL));
-    a_reg_dealloc(list, NR_R11);
-  end else begin
-    { call ptrgl helper routine which expects the pointer to the function descriptor
-    in R11 }
-    a_reg_alloc(list, NR_R11);
-    a_load_reg_reg(list, OS_ADDR, OS_ADDR, reg, NR_R11);
-    a_call_name_direct(list, A_BL, '.ptrgl', false, false, false);
-    a_reg_dealloc(list, NR_R11);
   end;
   end;
-
-  { we need to load the old RTOC from stackframe because we changed it}
-  reference_reset_base(tmpref, NR_STACK_POINTER_REG, get_rtoc_offset, ctempposinvalid, 8, []);
-  a_load_ref_reg(list, OS_ADDR, OS_ADDR, tmpref, NR_RTOC);
-
   include(current_procinfo.flags, pi_do_call);
   include(current_procinfo.flags, pi_do_call);
 end;
 end;
 
 
@@ -1270,7 +1258,8 @@ begin
   end;
   end;
 
 
   { save current RTOC for restoration after calls if necessary }
   { save current RTOC for restoration after calls if necessary }
-  if pi_do_call in current_procinfo.flags then
+  if (pi_do_call in current_procinfo.flags) and
+     (target_info.abi in abis_ppc_toc) then
     begin
     begin
       reference_reset_base(href,NR_STACK_POINTER_REG,get_rtoc_offset,ctempposinvalid,target_info.stackalign,[]);
       reference_reset_base(href,NR_STACK_POINTER_REG,get_rtoc_offset,ctempposinvalid,target_info.stackalign,[]);
       a_load_reg_ref(list,OS_ADDR,OS_ADDR,NR_RTOC,href);
       a_load_reg_ref(list,OS_ADDR,OS_ADDR,NR_RTOC,href);

+ 21 - 13
compiler/ppcgen/cgppc.pas

@@ -89,6 +89,8 @@ unit cgppc;
         procedure a_jmp(list: TAsmList; op: tasmop;
         procedure a_jmp(list: TAsmList; op: tasmop;
                         c: tasmcondflag; crval: longint; l: tasmlabel);
                         c: tasmcondflag; crval: longint; l: tasmlabel);
 
 
+        function get_rtoc_offset: longint;
+
         function save_lr_in_prologue: boolean;
         function save_lr_in_prologue: boolean;
 
 
         function load_got_symbol(list : TAsmList; const symbol : string; const flags: tindsymflags) : tregister;
         function load_got_symbol(list : TAsmList; const symbol : string; const flags: tindsymflags) : tregister;
@@ -123,7 +125,6 @@ unit cgppc;
                          C_LT,C_GE,C_LE,C_NE,C_LE,C_LT,C_GE,C_GT);
                          C_LT,C_GE,C_LE,C_NE,C_LE,C_LT,C_GE,C_GT);
     TocSecBaseName = 'toc_table';
     TocSecBaseName = 'toc_table';
 
 
-
 {$ifdef extdebug}
 {$ifdef extdebug}
      function ref2string(const ref : treference) : string;
      function ref2string(const ref : treference) : string;
      function cgop2string(const op : TOpCg) : String;
      function cgop2string(const op : TOpCg) : String;
@@ -473,9 +474,6 @@ unit cgppc;
             { no need to allocate/free R0, is already allocated by call node
             { no need to allocate/free R0, is already allocated by call node
               because it's a volatile register }
               because it's a volatile register }
             reg:=NR_R0;
             reg:=NR_R0;
-            { save current TOC }
-            reference_reset_base(tmpref,NR_STACK_POINTER_REG,LA_RTOC_AIX,ctempposinvalid,sizeof(pint),[]);
-            a_load_reg_ref(list,OS_ADDR,OS_ADDR,NR_RTOC,tmpref);
           end;
           end;
         list.concat(taicpu.op_reg(A_MTCTR,reg));
         list.concat(taicpu.op_reg(A_MTCTR,reg));
         if target_info.system in systems_aix then
         if target_info.system in systems_aix then
@@ -488,9 +486,6 @@ unit cgppc;
           end
           end
         else if target_info.abi=abi_powerpc_elfv2 then
         else if target_info.abi=abi_powerpc_elfv2 then
           begin
           begin
-            { save current TOC }
-            reference_reset_base(tmpref,NR_STACK_POINTER_REG,LA_RTOC_ELFV2,ctempposinvalid,sizeof(pint),[]);
-            a_load_reg_ref(list,OS_ADDR,OS_ADDR,NR_RTOC,tmpref);
             { functions must be called via R12 for this ABI }
             { functions must be called via R12 for this ABI }
             if reg<>NR_R12 then
             if reg<>NR_R12 then
               begin
               begin
@@ -499,17 +494,13 @@ unit cgppc;
               end;
               end;
           end;
           end;
         list.concat(taicpu.op_none(A_BCTRL));
         list.concat(taicpu.op_none(A_BCTRL));
-        if (target_info.system in systems_aix) or
-           (target_info.abi=abi_powerpc_elfv2) then
+        if target_info.abi in abis_ppc_toc then
           begin
           begin
             if (target_info.abi=abi_powerpc_elfv2) and
             if (target_info.abi=abi_powerpc_elfv2) and
                (reg<>NR_R12) then
                (reg<>NR_R12) then
               ungetcpuregister(list,NR_R12);
               ungetcpuregister(list,NR_R12);
             { restore our TOC }
             { restore our TOC }
-            if target_info.system in systems_aix then
-              toc_offset:=LA_RTOC_AIX
-            else
-              toc_offset:=LA_RTOC_ELFV2;
+            toc_offset:=get_rtoc_offset;
             reference_reset_base(tmpref,NR_STACK_POINTER_REG,toc_offset,ctempposinvalid,sizeof(pint),[]);
             reference_reset_base(tmpref,NR_STACK_POINTER_REG,toc_offset,ctempposinvalid,sizeof(pint),[]);
             a_load_ref_reg(list,OS_ADDR,OS_ADDR,tmpref,NR_RTOC);
             a_load_ref_reg(list,OS_ADDR,OS_ADDR,tmpref,NR_RTOC);
           end;
           end;
@@ -743,6 +734,23 @@ unit cgppc;
      list.concat(p)
      list.concat(p)
    end;
    end;
 
 
+ function tcgppcgen.get_rtoc_offset: longint;
+   begin
+     case target_info.abi of
+       abi_powerpc_aix:
+         result:=LA_RTOC_AIX;
+{$ifdef powerpc64}
+       { no TOC on Linux/ppc32 }
+       abi_powerpc_elfv1:
+         result:=LA_RTOC_SYSV;
+{$endif}
+       abi_powerpc_elfv2:
+         result:=LA_RTOC_ELFV2;
+       else
+         internalerror(2015021001);
+     end;
+   end;
+
 
 
 
 
   function tcgppcgen.load_got_symbol(list: TAsmList; const symbol : string; const flags: tindsymflags) : tregister;
   function tcgppcgen.load_got_symbol(list: TAsmList; const symbol : string; const flags: tindsymflags) : tregister;

+ 1 - 1
compiler/syscinfo.pas

@@ -81,7 +81,7 @@ const
       ( system: system_powerpc_morphos; procoption: po_syscall_legacy ),
       ( system: system_powerpc_morphos; procoption: po_syscall_legacy ),
       ( system: system_arm_aros;        procoption: po_syscall_baselast ),
       ( system: system_arm_aros;        procoption: po_syscall_baselast ),
       ( system: system_i386_aros;       procoption: po_syscall_baselast ),
       ( system: system_i386_aros;       procoption: po_syscall_baselast ),
-      ( system: system_x86_64_aros;     procoption: po_syscall_baselast ));
+      ( system: system_x86_64_aros;     procoption: po_syscall_basereg ));
 
 
 var
 var
   default_syscall_convention: tprocoption = po_none;
   default_syscall_convention: tprocoption = po_none;

+ 5 - 10
compiler/systems.pas

@@ -448,14 +448,9 @@ interface
          on the caller side rather than on the callee side }
          on the caller side rather than on the callee side }
        systems_caller_copy_addr_value_para = [system_aarch64_ios,system_aarch64_darwin,system_aarch64_linux,system_aarch64_win64,system_aarch64_freebsd];
        systems_caller_copy_addr_value_para = [system_aarch64_ios,system_aarch64_darwin,system_aarch64_linux,system_aarch64_win64,system_aarch64_freebsd];
 
 
-       { all PPC systems that use a TOC register to address globals }
-       { TODO: not used by Darwin, but don't know about others (JM) }
-       systems_ppc_toc = [
-         system_powerpc_linux,
-         system_powerpc64_linux,
-         system_powerpc_aix,
-         system_powerpc64_aix,
-         system_powerpc_macosclassic
+       { all PPC ABIs that use a TOC register to address globals }
+       abis_ppc_toc = [
+         {$ifdef powerpc32}abi_powerpc_sysv,{$endif}abi_powerpc_aix,abi_powerpc_elfv2
        ];
        ];
 
 
        { pointer checking (requires special code in FPC_CHECKPOINTER,
        { pointer checking (requires special code in FPC_CHECKPOINTER,
@@ -1204,9 +1199,9 @@ begin
   {$endif ndef default_target_set}
   {$endif ndef default_target_set}
 {$endif xtensa}
 {$endif xtensa}
 
 
-{$ifdef mips64}
+{$ifdef mips64eb}
   default_target(system_mips64_linux);
   default_target(system_mips64_linux);
-{$endif mips64}
+{$endif mips64eb}
 
 
 {$ifdef mips64el}
 {$ifdef mips64el}
   default_target(system_mips64el_linux);
   default_target(system_mips64el_linux);

+ 31 - 31
compiler/systems/t_atari.pas

@@ -156,37 +156,37 @@ begin
    end;
    end;
   if (UseVLink) and (ataritos_exe_format = 'aoutmint') then
   if (UseVLink) and (ataritos_exe_format = 'aoutmint') then
    begin
    begin
-	LinkRes.Add('SECTIONS {');
-	LinkRes.Add('  . = 0xe4;');
-	LinkRes.Add('  .text: {');
-	LinkRes.Add('    *(.i* i* I*)');
-	LinkRes.Add('    *(.t* t* T* .c* c* CODE*)');
-	LinkRes.Add('    *(.f* f* F*)');
-	LinkRes.Add('    _etext = .;');
-	LinkRes.Add('    __etext = .;');
-	LinkRes.Add('    . = ALIGN(4);');
-	LinkRes.Add('  }');
-	LinkRes.Add('  .data: {');
-	LinkRes.Add('    PROVIDE(_LinkerDB = . + 0x8000);');
-	LinkRes.Add('    PROVIDE(_SDA_BASE_ = . + 0x8000);');
-	LinkRes.Add('    VBCC_CONSTRUCTORS');
-	LinkRes.Add('    *(.rodata*)');
-	LinkRes.Add('    *(.d* d* D*)');
-	LinkRes.Add('    *(.sdata*)');
-	LinkRes.Add('    *(__MERGED)');
-	LinkRes.Add('    _edata = .;');
-	LinkRes.Add('    __edata = .;');
-	LinkRes.Add('    . = ALIGN(4);');
-	LinkRes.Add('  }');
-	LinkRes.Add('  .bss: {');
-	LinkRes.Add('    *(.sbss*)');
-	LinkRes.Add('    *(.scommon)');
-	LinkRes.Add('    *(.b* b* B* .u* u* U*)');
-	LinkRes.Add('    *(COMMON)');
-	LinkRes.Add('    _end = ALIGN(4);');
-	LinkRes.Add('    __end = ALIGN(4);');
-	LinkRes.Add('  }');
-	LinkRes.Add('}');;
+    LinkRes.Add('SECTIONS {');
+    LinkRes.Add('  . = 0xe4;');
+    LinkRes.Add('  .text: {');
+    LinkRes.Add('    *(.i* i* I*)');
+    LinkRes.Add('    *(.t* t* T* .c* c* CODE*)');
+    LinkRes.Add('    *(.f* f* F*)');
+    LinkRes.Add('    _etext = .;');
+    LinkRes.Add('    __etext = .;');
+    LinkRes.Add('    . = ALIGN(4);');
+    LinkRes.Add('  }');
+    LinkRes.Add('  .data: {');
+    LinkRes.Add('    PROVIDE(_LinkerDB = . + 0x8000);');
+    LinkRes.Add('    PROVIDE(_SDA_BASE_ = . + 0x8000);');
+    LinkRes.Add('    VBCC_CONSTRUCTORS');
+    LinkRes.Add('    *(.rodata*)');
+    LinkRes.Add('    *(.d* d* D*)');
+    LinkRes.Add('    *(.sdata*)');
+    LinkRes.Add('    *(__MERGED)');
+    LinkRes.Add('    _edata = .;');
+    LinkRes.Add('    __edata = .;');
+    LinkRes.Add('    . = ALIGN(4);');
+    LinkRes.Add('  }');
+    LinkRes.Add('  .bss: {');
+    LinkRes.Add('    *(.sbss*)');
+    LinkRes.Add('    *(.scommon)');
+    LinkRes.Add('    *(.b* b* B* .u* u* U*)');
+    LinkRes.Add('    *(COMMON)');
+    LinkRes.Add('    _end = ALIGN(4);');
+    LinkRes.Add('    __end = ALIGN(4);');
+    LinkRes.Add('  }');
+    LinkRes.Add('}');;
    end;
    end;
 
 
   LinkRes.Add('INPUT (');
   LinkRes.Add('INPUT (');

+ 2 - 2
compiler/systems/t_linux.pas

@@ -1316,11 +1316,11 @@ initialization
   RegisterTarget(system_mipseb_linux_info);
   RegisterTarget(system_mipseb_linux_info);
 {$endif MIPSEL}
 {$endif MIPSEL}
 {$endif MIPS32}
 {$endif MIPS32}
-{$ifdef MIPS64}
+{$ifdef MIPS64EB}
   RegisterImport(system_mips64_linux,timportliblinux);
   RegisterImport(system_mips64_linux,timportliblinux);
   RegisterExport(system_mips64_linux,texportliblinux);
   RegisterExport(system_mips64_linux,texportliblinux);
   RegisterTarget(system_mips64_linux_info);
   RegisterTarget(system_mips64_linux_info);
-{$endif MIPS64}
+{$endif MIPS64EB}
 {$ifdef MIPS64EL}
 {$ifdef MIPS64EL}
   RegisterImport(system_mips64el_linux,timportliblinux);
   RegisterImport(system_mips64el_linux,timportliblinux);
   RegisterExport(system_mips64el_linux,texportliblinux);
   RegisterExport(system_mips64el_linux,texportliblinux);

+ 34 - 19
compiler/wasm32/nwasmutil.pas

@@ -58,6 +58,33 @@ implementation
           list.Concat(tai_import_name.create(proc.mangledname,proc.import_name^));
           list.Concat(tai_import_name.create(proc.mangledname,proc.import_name^));
         end;
         end;
 
 
+      procedure InsertUnitInfo(list : TAsmList;cur_unit: tused_unit);
+        var
+          i: Integer;
+          def  : tdef;
+          proc : tprocdef;
+        begin
+          if (cur_unit.u.moduleflags * [mf_init,mf_finalize])<>[] then
+            begin
+              if mf_init in cur_unit.u.moduleflags then
+                list.Concat(tai_functype.create(make_mangledname('INIT$',cur_unit.u.globalsymtable,''),TWasmFuncType.Create([],[])));
+              if mf_finalize in cur_unit.u.moduleflags then
+                list.Concat(tai_functype.create(make_mangledname('FINALIZE$',cur_unit.u.globalsymtable,''),TWasmFuncType.Create([],[])));
+            end;
+          for i:=0 to cur_unit.u.deflist.Count-1 do
+            begin
+              def:=tdef(cur_unit.u.deflist[i]);
+              if assigned(def) and (tdef(def).typ = procdef) then
+                begin
+                  proc := tprocdef(def);
+                  if (po_external in proc.procoptions) and (po_has_importdll in proc.procoptions) then
+                    WriteImportDll(list,proc)
+                  else if not proc.owner.iscurrentunit or (po_external in proc.procoptions) then
+                    thlcgwasm(hlcg).g_procdef(list,proc);
+                end;
+            end;
+        end;
+
     var
     var
       i    : integer;
       i    : integer;
       def  : tdef;
       def  : tdef;
@@ -94,25 +121,13 @@ implementation
       cur_unit:=tused_unit(usedunits.First);
       cur_unit:=tused_unit(usedunits.First);
       while assigned(cur_unit) do
       while assigned(cur_unit) do
         begin
         begin
-          if (cur_unit.u.moduleflags * [mf_init,mf_finalize])<>[] then
-            begin
-              if mf_init in cur_unit.u.moduleflags then
-                list.Concat(tai_functype.create(make_mangledname('INIT$',cur_unit.u.globalsymtable,''),TWasmFuncType.Create([],[])));
-              if mf_finalize in cur_unit.u.moduleflags then
-                list.Concat(tai_functype.create(make_mangledname('FINALIZE$',cur_unit.u.globalsymtable,''),TWasmFuncType.Create([],[])));
-            end;
-          for i:=0 to cur_unit.u.deflist.Count-1 do
-            begin
-              def:=tdef(cur_unit.u.deflist[i]);
-              if assigned(def) and (tdef(def).typ = procdef) then
-                begin
-                  proc := tprocdef(def);
-                  if (po_external in proc.procoptions) and (po_has_importdll in proc.procoptions) then
-                    WriteImportDll(list,proc)
-                  else if not proc.owner.iscurrentunit or (po_external in proc.procoptions) then
-                    thlcgwasm(hlcg).g_procdef(list,proc);
-                end;
-            end;
+          InsertUnitInfo(list,cur_unit);
+          cur_unit:=tused_unit(cur_unit.Next);
+        end;
+      cur_unit:=tused_unit(current_module.used_units.First);
+      while assigned(cur_unit) do
+        begin
+          InsertUnitInfo(list,cur_unit);
           cur_unit:=tused_unit(cur_unit.Next);
           cur_unit:=tused_unit(cur_unit.Next);
         end;
         end;
     end;
     end;

+ 17 - 17
compiler/x86/aasmcpu.pas

@@ -2183,15 +2183,15 @@ implementation
           begin
           begin
             if aInput.typ = top_ref then
             if aInput.typ = top_ref then
             begin
             begin
-	      if aInput.ref^.base <> NR_NO then
-	      begin	      
-	        if (aInput.ref^.offset <> 0) and
+              if aInput.ref^.base <> NR_NO then
+              begin              
+                if (aInput.ref^.offset <> 0) and
                    ((aInput.ref^.offset mod tuplesize) = 0) and
                    ((aInput.ref^.offset mod tuplesize) = 0) and
                    (abs(aInput.ref^.offset) div tuplesize <= 127) then
                    (abs(aInput.ref^.offset) div tuplesize <= 127) then
                 begin
                 begin
                   aInput.ref^.offset := aInput.ref^.offset div tuplesize;
                   aInput.ref^.offset := aInput.ref^.offset div tuplesize;
                   EVEXTupleState := etsIsTuple;
                   EVEXTupleState := etsIsTuple;
-    	        end;  
+                    end;  
               end;
               end;
             end;
             end;
           end;
           end;
@@ -2905,35 +2905,35 @@ implementation
              NR_EAX,
              NR_EAX,
              NR_XMM0,
              NR_XMM0,
              NR_YMM0,
              NR_YMM0,
-	     NR_ZMM0: index:=0;
+             NR_ZMM0: index:=0;
              NR_ECX,
              NR_ECX,
              NR_XMM1,
              NR_XMM1,
              NR_YMM1,
              NR_YMM1,
-	     NR_ZMM1: index:=1;
+             NR_ZMM1: index:=1;
              NR_EDX,
              NR_EDX,
              NR_XMM2,
              NR_XMM2,
              NR_YMM2,
              NR_YMM2,
-	     NR_ZMM2: index:=2;
+             NR_ZMM2: index:=2;
              NR_EBX,
              NR_EBX,
              NR_XMM3,
              NR_XMM3,
              NR_YMM3,
              NR_YMM3,
-	     NR_ZMM3: index:=3;
+             NR_ZMM3: index:=3;
              NR_NO,
              NR_NO,
              NR_XMM4,
              NR_XMM4,
              NR_YMM4,
              NR_YMM4,
-	     NR_ZMM4: index:=4;
+             NR_ZMM4: index:=4;
              NR_EBP,
              NR_EBP,
              NR_XMM5,
              NR_XMM5,
              NR_YMM5,
              NR_YMM5,
-	     NR_ZMM5: index:=5;
+             NR_ZMM5: index:=5;
              NR_ESI,
              NR_ESI,
              NR_XMM6,
              NR_XMM6,
              NR_YMM6,
              NR_YMM6,
-	     NR_ZMM6: index:=6;
+             NR_ZMM6: index:=6;
              NR_EDI,
              NR_EDI,
              NR_XMM7,
              NR_XMM7,
              NR_YMM7,
              NR_YMM7,
-	     NR_ZMM7: index:=7;
+             NR_ZMM7: index:=7;
            else
            else
              exit;
              exit;
            end;
            end;
@@ -3507,7 +3507,7 @@ implementation
        *                 generates no code in the assembler)
        *                 generates no code in the assembler)
        * \331          - instruction not valid with REP prefix.  Hint for
        * \331          - instruction not valid with REP prefix.  Hint for
        *                 disassembler only; for SSE instructions.
        *                 disassembler only; for SSE instructions.
-       * \332	       - disassemble a rep (0xF3 byte) prefix as repe not rep.
+       * \332               - disassemble a rep (0xF3 byte) prefix as repe not rep.
        * \333          - 0xF3 prefix for SSE instructions
        * \333          - 0xF3 prefix for SSE instructions
        * \334          - 0xF2 prefix for SSE instructions
        * \334          - 0xF2 prefix for SSE instructions
        * \335          - Indicates 64-bit operand size with REX.W not necessary / 64-bit scalar vector operand size
        * \335          - Indicates 64-bit operand size with REX.W not necessary / 64-bit scalar vector operand size
@@ -3678,7 +3678,7 @@ implementation
 {$endif i386}
 {$endif i386}
            objdata.writereloc(data,len,p,Reloctype);
            objdata.writereloc(data,len,p,Reloctype);
 {$ifdef x86_64}
 {$ifdef x86_64}
-	   { Computed offset is not yet correct for GOTPC relocation }
+           { Computed offset is not yet correct for GOTPC relocation }
            { RELOC_GOTPCREL, RELOC_REX_GOTPCRELX, RELOC_GOTPCRELX need special handling }
            { RELOC_GOTPCREL, RELOC_REX_GOTPCRELX, RELOC_GOTPCRELX need special handling }
            if assigned(p) and (RelocType in [RELOC_GOTPCREL, RELOC_REX_GOTPCRELX, RELOC_GOTPCRELX]) and
            if assigned(p) and (RelocType in [RELOC_GOTPCREL, RELOC_REX_GOTPCRELX, RELOC_GOTPCRELX]) and
               { These relocations seem to be used only for ELF
               { These relocations seem to be used only for ELF
@@ -5538,14 +5538,14 @@ implementation
             // combination (attsuffix <> "AttSufNONE") and (MemRefSize is not in MemRefMultiples) is not supported =>> check opcode-definition in x86ins.dat
             // combination (attsuffix <> "AttSufNONE") and (MemRefSize is not in MemRefMultiples) is not supported =>> check opcode-definition in x86ins.dat
 
 
             if (AsmOp <> A_CVTSI2SD) and
             if (AsmOp <> A_CVTSI2SD) and
-	       (AsmOp <> A_CVTSI2SS) then
-	    begin	    
+               (AsmOp <> A_CVTSI2SS) then
+            begin            
               inc(iCntOpcodeValError);
               inc(iCntOpcodeValError);
               Str(gas_needsuffix[AsmOp],hs1);
               Str(gas_needsuffix[AsmOp],hs1);
               Str(InsTabMemRefSizeInfoCache^[AsmOp].MemRefSize,hs2);
               Str(InsTabMemRefSizeInfoCache^[AsmOp].MemRefSize,hs2);
               Message3(asmr_e_not_supported_combination_attsuffix_memrefsize_type,
               Message3(asmr_e_not_supported_combination_attsuffix_memrefsize_type,
                        std_op2str[AsmOp],hs1,hs2);
                        std_op2str[AsmOp],hs1,hs2);
-	    end;	       
+            end;               
           end;
           end;
         end;
         end;
       end;
       end;

+ 2 - 1
compiler/x86/cgx86.pas

@@ -3376,6 +3376,7 @@ unit cgx86;
       begin
       begin
         regsize:=0;
         regsize:=0;
         stackmisalignment:=0;
         stackmisalignment:=0;
+        list.concat(tai_regalloc.alloc(NR_STACK_POINTER_REG,nil));
 {$ifdef i8086}
 {$ifdef i8086}
         { Win16 callback/exported proc prologue support.
         { Win16 callback/exported proc prologue support.
           Since callbacks can be called from different modules, DS on entry may be
           Since callbacks can be called from different modules, DS on entry may be
@@ -3500,7 +3501,6 @@ unit cgx86;
           begin
           begin
             { return address }
             { return address }
             inc(stackmisalignment,sizeof(pint));
             inc(stackmisalignment,sizeof(pint));
-            list.concat(tai_regalloc.alloc(current_procinfo.framepointer,nil));
             if current_procinfo.framepointer=NR_STACK_POINTER_REG then
             if current_procinfo.framepointer=NR_STACK_POINTER_REG then
               begin
               begin
 {$ifdef i386}
 {$ifdef i386}
@@ -3511,6 +3511,7 @@ unit cgx86;
               end
               end
             else
             else
               begin
               begin
+                list.concat(tai_regalloc.alloc(current_procinfo.framepointer,nil));
 {$ifdef i8086}
 {$ifdef i8086}
                 if ((ts_x86_far_procs_push_odd_bp in current_settings.targetswitches) or
                 if ((ts_x86_far_procs_push_odd_bp in current_settings.targetswitches) or
                     ((po_exports in current_procinfo.procdef.procoptions) and
                     ((po_exports in current_procinfo.procdef.procoptions) and

+ 6 - 1
compiler/x86_64/cgcpu.pas

@@ -206,12 +206,13 @@ unit cgcpu;
           is expected to be one of those directives, and not generated here. }
           is expected to be one of those directives, and not generated here. }
         suppress_endprologue:=(pi_has_unwind_info in current_procinfo.flags);
         suppress_endprologue:=(pi_has_unwind_info in current_procinfo.flags);
 
 
+        list.concat(tai_regalloc.alloc(NR_STACK_POINTER_REG,nil));
+
         { save old framepointer }
         { save old framepointer }
         if not nostackframe then
         if not nostackframe then
           begin
           begin
             { return address }
             { return address }
             stackmisalignment := sizeof(pint);
             stackmisalignment := sizeof(pint);
-            list.concat(tai_regalloc.alloc(current_procinfo.framepointer,nil));
             if current_procinfo.framepointer=NR_STACK_POINTER_REG then
             if current_procinfo.framepointer=NR_STACK_POINTER_REG then
               begin
               begin
                 push_regs;
                 push_regs;
@@ -219,6 +220,7 @@ unit cgcpu;
               end
               end
             else
             else
               begin
               begin
+                list.concat(tai_regalloc.alloc(current_procinfo.framepointer,nil));
                 { push <frame_pointer> }
                 { push <frame_pointer> }
                 inc(stackmisalignment,sizeof(pint));
                 inc(stackmisalignment,sizeof(pint));
                 push_one_reg(NR_FRAME_POINTER_REG);
                 push_one_reg(NR_FRAME_POINTER_REG);
@@ -427,6 +429,9 @@ unit cgcpu;
               list.Concat(taicpu.op_none(A_VZEROUPPER));
               list.Concat(taicpu.op_none(A_VZEROUPPER));
           end;
           end;
 
 
+        if current_procinfo.framepointer<>NR_STACK_POINTER_REG then
+          list.concat(tai_regalloc.dealloc(NR_STACK_POINTER_REG,nil));
+
         list.concat(Taicpu.Op_none(A_RET,S_NO));
         list.concat(Taicpu.Op_none(A_RET,S_NO));
 
 
         if (pi_has_unwind_info in current_procinfo.flags) then
         if (pi_has_unwind_info in current_procinfo.flags) then

+ 15 - 0
compiler/x86_64/cpupara.pas

@@ -1659,6 +1659,21 @@ unit cpupara;
           begin
           begin
             hp:=tparavarsym(paras[i]);
             hp:=tparavarsym(paras[i]);
             paradef:=hp.vardef;
             paradef:=hp.vardef;
+
+            { in syscalls the libbase might be set as explicit paraloc }
+            if (vo_has_explicit_paraloc in hp.varoptions) then
+              if not (vo_is_syscall_lib in hp.varoptions) then
+                internalerror(2022010501)
+              else
+                begin
+                  paracgsize:=def_cgsize(paradef);
+                  hp.paraloc[side].def:=paradef;
+                  hp.paraloc[side].size:=paracgsize;
+                  hp.paraloc[side].intsize:=tcgsize2size[paracgsize];
+                  hp.paraloc[side].alignment:=sizeof(pint);
+                  continue;
+                end;
+
             { on win64, if a record has only one field and that field is a
             { on win64, if a record has only one field and that field is a
               single or double, it has to be handled like a single/double }
               single or double, it has to be handled like a single/double }
             if use_ms_abi and
             if use_ms_abi and

+ 3 - 3
compiler/x86_64/nx64cal.pas

@@ -61,11 +61,11 @@ implementation
                 begin
                 begin
                   current_asmdata.CurrAsmList.concat(tai_comment.create(strpnew('AROS SysCall')));
                   current_asmdata.CurrAsmList.concat(tai_comment.create(strpnew('AROS SysCall')));
 
 
-                  cg.getcpuregister(current_asmdata.CurrAsmList,NR_RAX);
-                  get_syscall_call_ref(tmpref,NR_RAX);
+                  cg.getcpuregister(current_asmdata.CurrAsmList,NR_R12);
+                  get_syscall_call_ref(tmpref,NR_R12);
 
 
                   current_asmdata.CurrAsmList.concat(taicpu.op_ref(A_CALL,S_NO,tmpref));
                   current_asmdata.CurrAsmList.concat(taicpu.op_ref(A_CALL,S_NO,tmpref));
-                  cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_RAX);
+                  cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_R12);
                   exit;
                   exit;
                 end;
                 end;
               internalerror(2016120101);
               internalerror(2016120101);

+ 8 - 0
packages/fcl-base/src/csvdocument.pp

@@ -56,8 +56,12 @@ type
   {$ENDIF}
   {$ENDIF}
 
 
   // Random access to CSV document. Reads entire document into memory.
   // Random access to CSV document. Reads entire document into memory.
+
+  { TCSVDocument }
+
   TCSVDocument = class(TCSVHandler)
   TCSVDocument = class(TCSVHandler)
   private
   private
+    FDetectBOM: Boolean;
     FRows: TFPObjectList;
     FRows: TFPObjectList;
     FParser: TCSVParser;
     FParser: TCSVParser;
     FBuilder: TCSVBuilder;
     FBuilder: TCSVBuilder;
@@ -130,6 +134,9 @@ type
     // Remove empty cells at end of rows from entire document
     // Remove empty cells at end of rows from entire document
     procedure RemoveTrailingEmptyCells;
     procedure RemoveTrailingEmptyCells;
 
 
+    // Detect bom
+    Property DetectBOM : Boolean Read FDetectBOM Write FDetectBOM;
+
     // Properties
     // Properties
 
 
     // Cell data at column ACol, row ARow.
     // Cell data at column ACol, row ARow.
@@ -428,6 +435,7 @@ begin
   FreeAndNil(FParser);
   FreeAndNil(FParser);
   FParser:=TCSVParser.Create;
   FParser:=TCSVParser.Create;
   FParser.AssignCSVProperties(Self);
   FParser.AssignCSVProperties(Self);
+  FParser.DetectBOM:=Self.DetectBOM;
   with FParser do
   with FParser do
   begin
   begin
     SetSource(AStream);
     SetSource(AStream);

+ 6 - 4
packages/fcl-js/src/jstree.pp

@@ -1000,8 +1000,10 @@ Type
   end;
   end;
 
 
   { TJSExportStatement - e.g. 'export Declaration' }
   { TJSExportStatement - e.g. 'export Declaration' }
-  // 'export * as NameSpaceExport from ModuleName' NameSpaceExport and ModuleName are optional
-  // 'export { ExportNames[1], ExportNames[2], ... } from ModuleName' ModuleName is optional
+  // export [default] Declaration
+  // export [default] NameSpaceExport [from ModuleName]
+  // export [default] * [from ModuleName]
+  // export { ExportNames[1], ExportNames[2], ... } [from ModuleName]
 
 
   TJSExportStatement = class(TJSStatement)
   TJSExportStatement = class(TJSStatement)
   Private
   Private
@@ -1014,9 +1016,9 @@ Type
     function GetNamedExports: TJSExportNameElements;
     function GetNamedExports: TJSExportNameElements;
   Public
   Public
     Destructor Destroy; override;
     Destructor Destroy; override;
-    Property IsDefault : Boolean Read FIsDefault Write FIsDefault;
+    Property IsDefault : Boolean Read FIsDefault Write FIsDefault; // write "default"
     Property Declaration : TJSElement Read FDeclaration Write FDeclaration;
     Property Declaration : TJSElement Read FDeclaration Write FDeclaration;
-    Property NameSpaceExport : TJSString Read FNameSpaceExport Write FNameSpaceExport;
+    Property NameSpaceExport : TJSString Read FNameSpaceExport Write FNameSpaceExport;// can be '*'
     Property ModuleName : TJSString Read FModuleName Write FModuleName;
     Property ModuleName : TJSString Read FModuleName Write FModuleName;
     Property HaveExportNames : Boolean Read GetHaveNamedExports;
     Property HaveExportNames : Boolean Read GetHaveNamedExports;
     Property ExportNames : TJSExportNameElements Read GetNamedExports;
     Property ExportNames : TJSExportNameElements Read GetNamedExports;

+ 18 - 0
packages/fcl-js/tests/tcwriter.pp

@@ -101,6 +101,7 @@ type
     Procedure TestConstDeclarationStatement;
     Procedure TestConstDeclarationStatement;
     Procedure TestDebuggerStatement;
     Procedure TestDebuggerStatement;
     Procedure TestVarListDeclarationStatement;
     Procedure TestVarListDeclarationStatement;
+    Procedure TestConstListDeclarationStatement;
     Procedure TestVarListDeclarationStatement2Vars;
     Procedure TestVarListDeclarationStatement2Vars;
     Procedure TestVarListDeclarationStatement3Vars;
     Procedure TestVarListDeclarationStatement3Vars;
     Procedure TestReturnStatement;
     Procedure TestReturnStatement;
@@ -1058,6 +1059,23 @@ begin
   AssertWrite('simple var','var a',S);
   AssertWrite('simple var','var a',S);
 end;
 end;
 
 
+procedure TTestStatementWriter.TestConstListDeclarationStatement;
+Var
+  S : TJSVariableStatement;
+  V : TJSVarDeclaration;
+  L : TJSVariableDeclarationList;
+
+begin
+  S:=TJSVariableStatement.Create(0,0);
+  L:=TJSVariableDeclarationList.Create(0,0);
+  V:=TJSVarDeclaration.Create(0,0);
+  S.VarType:=vtConst;
+  L.A:=V;
+  S.VarDecl:=L;
+  V.Name:='a';
+  AssertWrite('simple const','const a',S);
+end;
+
 procedure TTestStatementWriter.TestVarListDeclarationStatement2Vars;
 procedure TTestStatementWriter.TestVarListDeclarationStatement2Vars;
 Var
 Var
   S : TJSVariableStatement;
   S : TJSVariableStatement;

+ 111 - 43
packages/fcl-passrc/src/pasresolver.pp

@@ -1254,8 +1254,9 @@ type
     rrfNoImplicitCallWithoutParams, // a TPrimitiveExpr is not an implicit call
     rrfNoImplicitCallWithoutParams, // a TPrimitiveExpr is not an implicit call
     rrfNewInstance, // constructor call (without it call constructor as normal method)
     rrfNewInstance, // constructor call (without it call constructor as normal method)
     rrfFreeInstance, // destructor call (without it call destructor as normal method)
     rrfFreeInstance, // destructor call (without it call destructor as normal method)
-    rrfVMT, // use VMT for call
-    rrfConstInherited // parent is const and this child is too
+    rrfVMT, // use VMT for call (e.g. calling a virtual method)
+    rrfConstInherited, // parent is const and this child is too (e.g. field of a const record argument)
+    rrfUseFields // use record fields too, flag is used by pas2js
     );
     );
   TResolvedReferenceFlags = set of TResolvedReferenceFlag;
   TResolvedReferenceFlags = set of TResolvedReferenceFlag;
 
 
@@ -1414,6 +1415,7 @@ type
   TPRFindGenericData = record
   TPRFindGenericData = record
     Find: TPRFindData;
     Find: TPRFindData;
     TemplateCount: integer;
     TemplateCount: integer;
+    LastProc: TPasProcedure;
   end;
   end;
   PPRFindGenericData = ^TPRFindGenericData;
   PPRFindGenericData = ^TPRFindGenericData;
 
 
@@ -1592,6 +1594,7 @@ type
     procedure OnFindProcDeclaration(El: TPasElement; ElScope, StartScope: TPasScope;
     procedure OnFindProcDeclaration(El: TPasElement; ElScope, StartScope: TPasScope;
       FindProcData: Pointer; var Abort: boolean); virtual;
       FindProcData: Pointer; var Abort: boolean); virtual;
     function IsSameProcContext(ProcParentA, ProcParentB: TPasElement): boolean;
     function IsSameProcContext(ProcParentA, ProcParentB: TPasElement): boolean;
+    function IsProcOverload(LastProc, LastExactProc, CurProc: TPasProcedure): boolean;
     function FindProcSameSignature(const ProcName: string; Proc: TPasProcedure;
     function FindProcSameSignature(const ProcName: string; Proc: TPasProcedure;
       Scope: TPasIdentifierScope; OnlyLocal: boolean): TPasProcedure;
       Scope: TPasIdentifierScope; OnlyLocal: boolean): TPasProcedure;
   protected
   protected
@@ -1734,7 +1737,7 @@ type
       SetReferenceFlags: boolean);
       SetReferenceFlags: boolean);
     procedure ComputeArgumentExpr(const ArgResolved: TPasResolverResult;
     procedure ComputeArgumentExpr(const ArgResolved: TPasResolverResult;
       Access: TArgumentAccess; Expr: TPasExpr; out ExprResolved: TPasResolverResult;
       Access: TArgumentAccess; Expr: TPasExpr; out ExprResolved: TPasResolverResult;
-      SetReferenceFlags: boolean);
+      SetReferenceFlags: boolean); virtual;
     procedure ComputeArrayParams(Params: TParamsExpr;
     procedure ComputeArrayParams(Params: TParamsExpr;
       out ResolvedEl: TPasResolverResult; Flags: TPasResolverComputeFlags;
       out ResolvedEl: TPasResolverResult; Flags: TPasResolverComputeFlags;
       StartEl: TPasElement);
       StartEl: TPasElement);
@@ -2232,7 +2235,7 @@ type
     function HasExactType(const ResolvedEl: TPasResolverResult): boolean; // false if HiTypeEl was guessed, e.g. 1 guessed a btLongint
     function HasExactType(const ResolvedEl: TPasResolverResult): boolean; // false if HiTypeEl was guessed, e.g. 1 guessed a btLongint
     function IndexOfGenericParam(Params: TPasExprArray): integer;
     function IndexOfGenericParam(Params: TPasExprArray): integer;
     procedure CheckUseAsType(aType: TPasElement; id: TMaxPrecInt;
     procedure CheckUseAsType(aType: TPasElement; id: TMaxPrecInt;
-      ErrorEl: TPasElement);
+      PosEl: TPasElement);
     function CheckCallProcCompatibility(ProcType: TPasProcedureType;
     function CheckCallProcCompatibility(ProcType: TPasProcedureType;
       Params: TParamsExpr; RaiseOnError: boolean; SetReferenceFlags: boolean = false): integer;
       Params: TParamsExpr; RaiseOnError: boolean; SetReferenceFlags: boolean = false): integer;
     function CheckCallPropertyCompatibility(PropEl: TPasProperty;
     function CheckCallPropertyCompatibility(PropEl: TPasProperty;
@@ -5008,19 +5011,72 @@ procedure TPasResolver.OnFindFirst_GenericEl(El: TPasElement; ElScope,
 var
 var
   Data: PPRFindGenericData absolute FindFirstGenericData;
   Data: PPRFindGenericData absolute FindFirstGenericData;
   GenericTemplateTypes: TFPList;
   GenericTemplateTypes: TFPList;
+  Proc, LastExactProc: TPasProcedure;
+  ProcScope: TPasProcedureScope;
 begin
 begin
+  Proc:=nil;
   if El is TPasGenericType then
   if El is TPasGenericType then
     GenericTemplateTypes:=TPasGenericType(El).GenericTemplateTypes
     GenericTemplateTypes:=TPasGenericType(El).GenericTemplateTypes
   else if El is TPasProcedure then
   else if El is TPasProcedure then
-    GenericTemplateTypes:=GetProcTemplateTypes(TPasProcedure(El))
+    begin
+    Proc:=TPasProcedure(El);
+    ProcScope:=Proc.CustomData as TPasProcedureScope;
+    if ProcScope.DeclarationProc<>nil then
+      begin
+      // this proc has a forward declaration -> use that instead
+      Proc:=ProcScope.DeclarationProc;
+      El:=Proc;
+      end;
+
+    if (Data^.LastProc<>nil) then
+      begin
+      if Data^.Find.Found is TPasProcedure then
+        LastExactProc:=TPasProcedure(Data^.Find.Found)
+      else
+        LastExactProc:=nil;
+      if not IsProcOverload(Data^.LastProc,LastExactProc,Proc) then
+        begin
+        Abort:=true;
+        exit;
+        end;
+      end;
+    Data^.LastProc:=Proc;
+
+    GenericTemplateTypes:=GetProcTemplateTypes(Proc);
+    end
   else
   else
     exit;
     exit;
+
   if GenericTemplateTypes=nil then exit;
   if GenericTemplateTypes=nil then exit;
   if GenericTemplateTypes.Count<>Data^.TemplateCount then
   if GenericTemplateTypes.Count<>Data^.TemplateCount then
     exit;
     exit;
+
+  if Data^.Find.Found<>nil then
+    begin
+    // there was already a generic proc, but it needed params
+    if ProcNeedsParams(Proc.ProcType) then
+      begin
+      // this one needs params too
+      // -> keep the first found and continue searching
+      exit;
+      end;
+    end;
+
   Data^.Find.Found:=El;
   Data^.Find.Found:=El;
   Data^.Find.ElScope:=ElScope;
   Data^.Find.ElScope:=ElScope;
   Data^.Find.StartScope:=StartScope;
   Data^.Find.StartScope:=StartScope;
+
+  if Proc<>nil then
+    begin
+    if (not Proc.IsOverload) and (msDelphi in ProcScope.ModeSwitches) then
+      // stop searching after this proc
+    else if ProcNeedsParams(Proc.ProcType) then
+      begin
+      // continue searching for an overload proc without params
+      exit;
+      end;
+    end;
+
   Abort:=true;
   Abort:=true;
 end;
 end;
 
 
@@ -5068,30 +5124,6 @@ begin
       // there is already a previous proc
       // there is already a previous proc
       PrevProc:=TPasProcedure(Data^.Found);
       PrevProc:=TPasProcedure(Data^.Found);
 
 
-      if msDelphi in TPasProcedureScope(Data^.LastProc.CustomData).ModeSwitches then
-        begin
-        if (not Data^.LastProc.IsOverload) or (not Proc.IsOverload) then
-          begin
-          Abort:=true;
-          exit;
-          end;
-        end
-      else
-        begin
-        // mode objfpc
-        if IsSameProcContext(Proc.Parent,Data^.LastProc.Parent) then
-          // mode objfpc: procs in same context have implicit overload
-        else
-          begin
-          // mode objfpc, different context
-          if not ProcHasGroupOverload(Data^.LastProc) then
-            begin
-            Abort:=true;
-            exit;
-            end;
-          end;
-        end;
-
       if (Data^.Distance=cExact) and (PrevProc.Parent<>Proc.Parent)
       if (Data^.Distance=cExact) and (PrevProc.Parent<>Proc.Parent)
           and (PrevProc.Parent.ClassType=TPasClassType) then
           and (PrevProc.Parent.ClassType=TPasClassType) then
         begin
         begin
@@ -5100,12 +5132,12 @@ begin
         exit;
         exit;
         end;
         end;
 
 
-      // check if previous found proc is override of found proc
-      if IsProcOverride(Proc,PrevProc) then
+      if not IsProcOverload(Data^.LastProc,PrevProc,Proc) then
         begin
         begin
-        // previous found proc is override of found proc -> skip
+        Abort:=true;
         exit;
         exit;
         end;
         end;
+
       end;
       end;
 
 
     if (msDelphi in ProcScope.ModeSwitches) and not Proc.IsOverload then
     if (msDelphi in ProcScope.ModeSwitches) and not Proc.IsOverload then
@@ -5591,6 +5623,37 @@ begin
   Result:=false;
   Result:=false;
 end;
 end;
 
 
+function TPasResolver.IsProcOverload(LastProc, LastExactProc,
+  CurProc: TPasProcedure): boolean;
+begin
+  if msDelphi in TPasProcedureScope(LastProc.CustomData).ModeSwitches then
+    begin
+    if (not LastProc.IsOverload) or (not CurProc.IsOverload) then
+      exit(false);
+    end
+  else
+    begin
+    // mode objfpc
+    if IsSameProcContext(LastProc.Parent,CurProc.Parent) then
+      // mode objfpc: procs in same context have implicit overload
+    else
+      begin
+      // mode objfpc, different context
+      if not ProcHasGroupOverload(LastProc) then
+        exit(false);
+      end;
+    end;
+
+  // check if previous found proc is override of found proc
+  if (LastExactProc<>nil) and IsProcOverride(CurProc,LastExactProc) then
+    begin
+    // previous found proc is override of found proc -> skip
+    exit(false);
+    end;
+
+  Result:=true;
+end;
+
 function TPasResolver.FindProcSameSignature(const ProcName: string;
 function TPasResolver.FindProcSameSignature(const ProcName: string;
   Proc: TPasProcedure; Scope: TPasIdentifierScope; OnlyLocal: boolean
   Proc: TPasProcedure; Scope: TPasIdentifierScope; OnlyLocal: boolean
   ): TPasProcedure;
   ): TPasProcedure;
@@ -9311,13 +9374,15 @@ var
   ParamAccess: TResolvedRefAccess;
   ParamAccess: TResolvedRefAccess;
   i: Integer;
   i: Integer;
   ArrParams: TPasExprArray;
   ArrParams: TPasExprArray;
+  Args: TFPList;
 begin
 begin
   ArrParams:=Params.Params;
   ArrParams:=Params.Params;
+  Args:=ProcType.Args;
   for i:=0 to length(ArrParams)-1 do
   for i:=0 to length(ArrParams)-1 do
     begin
     begin
     ParamAccess:=rraRead;
     ParamAccess:=rraRead;
-    if i<ProcType.Args.Count then
-      case TPasArgument(ProcType.Args[i]).Access of
+    if i<Args.Count then
+      case TPasArgument(Args[i]).Access of
       argVar: ParamAccess:=rraVarParam;
       argVar: ParamAccess:=rraVarParam;
       argOut: ParamAccess:=rraOutParam;
       argOut: ParamAccess:=rraOutParam;
       end;
       end;
@@ -10419,7 +10484,7 @@ begin
       if ProcNeedsParams(Proc.ProcType) and not ExprIsAddrTarget(El) then
       if ProcNeedsParams(Proc.ProcType) and not ExprIsAddrTarget(El) then
         begin
         begin
         {$IFDEF VerbosePasResolver}
         {$IFDEF VerbosePasResolver}
-        writeln('TPasResolver.ResolveNameExpr ',GetObjPath(El));
+        writeln('TPasResolver.ResolveNameExpr ',GetObjPath(El),' Args.Count=',Proc.ProcType.Args.Count);
         {$ENDIF}
         {$ENDIF}
         RaiseMsg(20170216152138,nWrongNumberOfParametersForCallTo,
         RaiseMsg(20170216152138,nWrongNumberOfParametersForCallTo,
           sWrongNumberOfParametersForCallTo,[Proc.Name],El);
           sWrongNumberOfParametersForCallTo,[Proc.Name],El);
@@ -13519,9 +13584,9 @@ begin
         if (LeftResolved.IdentEl is TPasType)
         if (LeftResolved.IdentEl is TPasType)
             or (not (rrfReadable in LeftResolved.Flags)) then
             or (not (rrfReadable in LeftResolved.Flags)) then
           begin
           begin
-          { $IFDEF VerbosePasResolver}
+          {$IFDEF VerbosePasResolver}
           writeln('TPasResolver.ComputeBinaryExprRes as-operator: left=',GetResolverResultDbg(LeftResolved),' right=',GetResolverResultDbg(RightResolved));
           writeln('TPasResolver.ComputeBinaryExprRes as-operator: left=',GetResolverResultDbg(LeftResolved),' right=',GetResolverResultDbg(RightResolved));
-          { $ENDIF}
+          {$ENDIF}
           RaiseIncompatibleTypeRes(20180204124711,nOperatorIsNotOverloadedAOpB,
           RaiseIncompatibleTypeRes(20180204124711,nOperatorIsNotOverloadedAOpB,
             [OpcodeStrings[Bin.OpCode]],LeftResolved,RightResolved,Bin);
             [OpcodeStrings[Bin.OpCode]],LeftResolved,RightResolved,Bin);
           end;
           end;
@@ -21624,9 +21689,10 @@ begin
   //    ' FindData.Found=',GetObjName(FindData.Found));
   //    ' FindData.Found=',GetObjName(FindData.Found));
   if OnlyTypeMembers then
   if OnlyTypeMembers then
     begin
     begin
+    // only class vars/procs allowed
+
     //writeln('TPasResolver.CheckFoundElOnStartScope ',GetObjName(FindData.Found),' ',(FindData.Found is TPasVariable)
     //writeln('TPasResolver.CheckFoundElOnStartScope ',GetObjName(FindData.Found),' ',(FindData.Found is TPasVariable)
     //    and (vmClass in TPasVariable(FindData.Found).VarModifiers));
     //    and (vmClass in TPasVariable(FindData.Found).VarModifiers));
-    // only class vars/procs allowed
     if FindData.Found.ClassType=TPasConstructor then
     if FindData.Found.ClassType=TPasConstructor then
       // constructor: ok
       // constructor: ok
     else if IsClassMethod(FindData.Found)
     else if IsClassMethod(FindData.Found)
@@ -22905,8 +22971,10 @@ begin
     RaiseMsg(20190210143257,nExprTypeMustBeClassOrRecordTypeGot,sExprTypeMustBeClassOrRecordTypeGot,
     RaiseMsg(20190210143257,nExprTypeMustBeClassOrRecordTypeGot,sExprTypeMustBeClassOrRecordTypeGot,
       [BaseTypeNames[ExprResolved.BaseType]],ErrorEl);
       [BaseTypeNames[ExprResolved.BaseType]],ErrorEl);
 
 
+  if not (rrfReadable in ExprResolved.Flags) then
+    CheckUseAsType(ExprResolved.LoTypeEl,20220210140100,Expr);
+
   Flags:=[];
   Flags:=[];
-  CheckUseAsType(LoType,20190123113957,Expr);
   ClassRecScope:=nil;
   ClassRecScope:=nil;
   ExprScope:=nil;
   ExprScope:=nil;
   if LoType.ClassType=TPasClassOfType then
   if LoType.ClassType=TPasClassOfType then
@@ -28366,7 +28434,7 @@ begin
 end;
 end;
 
 
 procedure TPasResolver.CheckUseAsType(aType: TPasElement; id: TMaxPrecInt;
 procedure TPasResolver.CheckUseAsType(aType: TPasElement; id: TMaxPrecInt;
-  ErrorEl: TPasElement);
+  PosEl: TPasElement);
 begin
 begin
   if aType=nil then exit;
   if aType=nil then exit;
   if aType is TPasGenericType then
   if aType is TPasGenericType then
@@ -28374,18 +28442,18 @@ begin
     if aType.ClassType=TPasClassType then
     if aType.ClassType=TPasClassType then
       begin
       begin
       if TPasClassType(aType).HelperForType<>nil then
       if TPasClassType(aType).HelperForType<>nil then
-        RaiseHelpersCannotBeUsedAsType(id,ErrorEl);
+        RaiseHelpersCannotBeUsedAsType(id,PosEl);
       end;
       end;
     if (TPasGenericType(aType).GenericTemplateTypes<>nil)
     if (TPasGenericType(aType).GenericTemplateTypes<>nil)
         and (TPasGenericType(aType).GenericTemplateTypes.Count>0) then
         and (TPasGenericType(aType).GenericTemplateTypes.Count>0) then
       begin
       begin
       // ref to generic type without specialization
       // ref to generic type without specialization
       if not (msDelphi in CurrentParser.CurrentModeswitches)
       if not (msDelphi in CurrentParser.CurrentModeswitches)
-          and (ErrorEl.HasParent(aType)) then
+          and (PosEl.HasParent(aType)) then
         // ObjFPC allows referring to parent without type params
         // ObjFPC allows referring to parent without type params
       else
       else
         RaiseMsg(id,nGenericsWithoutSpecializationAsType,sGenericsWithoutSpecializationAsType,
         RaiseMsg(id,nGenericsWithoutSpecializationAsType,sGenericsWithoutSpecializationAsType,
-            [ErrorEl.ElementTypeName],ErrorEl);
+            [PosEl.ElementTypeName],PosEl);
       end;
       end;
     end;
     end;
 end;
 end;

+ 110 - 7
packages/fcl-passrc/src/pasuseanalyzer.pas

@@ -257,8 +257,9 @@ type
     function ElementVisited(El: TPasElement; Mode: TPAUseMode): boolean; overload;
     function ElementVisited(El: TPasElement; Mode: TPAUseMode): boolean; overload;
     function ElementVisited(El: TPasElement; OtherCheck: TPAOtherCheckedEl): boolean; overload;
     function ElementVisited(El: TPasElement; OtherCheck: TPAOtherCheckedEl): boolean; overload;
     procedure MarkImplScopeRef(El, RefEl: TPasElement; Access: TPSRefAccess);
     procedure MarkImplScopeRef(El, RefEl: TPasElement; Access: TPSRefAccess);
-    function CanSkipGenericType(El: TPasGenericType): boolean;
-    function CanSkipGenericProc(DeclProc: TPasProcedure): boolean;
+    function IsGenericElement(El: TPasElement): boolean; virtual;
+    function CanSkipGenericType(El: TPasGenericType): boolean; virtual;
+    function CanSkipGenericProc(DeclProc: TPasProcedure): boolean; virtual;
     procedure UseElement(El: TPasElement; Access: TResolvedRefAccess;
     procedure UseElement(El: TPasElement; Access: TResolvedRefAccess;
       UseFull: boolean); virtual;
       UseFull: boolean); virtual;
     procedure UseTypeInfo(El: TPasElement); virtual;
     procedure UseTypeInfo(El: TPasElement); virtual;
@@ -282,8 +283,10 @@ type
     procedure UseVariable(El: TPasVariable; Access: TResolvedRefAccess;
     procedure UseVariable(El: TPasVariable; Access: TResolvedRefAccess;
       UseFull: boolean); virtual;
       UseFull: boolean); virtual;
     procedure UseResourcestring(El: TPasResString); virtual;
     procedure UseResourcestring(El: TPasResString); virtual;
+    procedure UseExportSymbol(El: TPasExportSymbol); virtual;
     procedure UseArgument(El: TPasArgument; Access: TResolvedRefAccess); virtual;
     procedure UseArgument(El: TPasArgument; Access: TResolvedRefAccess); virtual;
     procedure UseResultElement(El: TPasResultElement; Access: TResolvedRefAccess); virtual;
     procedure UseResultElement(El: TPasResultElement; Access: TResolvedRefAccess); virtual;
+    procedure UseRecordFields(El: TPasExpr); virtual;
     // create hints for a unit, program or library
     // create hints for a unit, program or library
     procedure EmitElementHints(El: TPasElement); virtual;
     procedure EmitElementHints(El: TPasElement); virtual;
     procedure EmitSectionHints(Section: TPasSection); virtual;
     procedure EmitSectionHints(Section: TPasSection); virtual;
@@ -1030,6 +1033,19 @@ begin
     CheckImplRef;
     CheckImplRef;
 end;
 end;
 
 
+function TPasAnalyzer.IsGenericElement(El: TPasElement): boolean;
+var
+  C: TClass;
+begin
+  C:=El.ClassType;
+  if C.InheritsFrom(TPasProcedure) then
+    Result:=TPasProcedure(El).NameParts<>nil
+  else if C.InheritsFrom(TPasGenericType) then
+    Result:=TPasGenericType(El).GenericTemplateTypes<>nil
+  else
+    Result:=false;
+end;
+
 function TPasAnalyzer.CanSkipGenericType(El: TPasGenericType): boolean;
 function TPasAnalyzer.CanSkipGenericType(El: TPasGenericType): boolean;
 
 
   procedure RaiseHalfSpecialized;
   procedure RaiseHalfSpecialized;
@@ -1198,6 +1214,7 @@ var
   ClassEl: TPasClassType;
   ClassEl: TPasClassType;
   ArrType: TPasArrayType;
   ArrType: TPasArrayType;
   SpecType: TPasSpecializeType;
   SpecType: TPasSpecializeType;
+  Rec: TPasRecordType;
 begin
 begin
   {$IFDEF VerbosePasAnalyzer}
   {$IFDEF VerbosePasAnalyzer}
   writeln('TPasAnalyzer.UsePublished START ',GetObjName(El));
   writeln('TPasAnalyzer.UsePublished START ',GetObjName(El));
@@ -1258,7 +1275,9 @@ begin
         Member:=TPasElement(Members[i]);
         Member:=TPasElement(Members[i]);
         if Member.ClassType=TPasAttributes then
         if Member.ClassType=TPasAttributes then
           continue;
           continue;
-        if IsUsed(Member) then
+        if IsGenericElement(Member) then
+          continue;
+        if IsUsed(Member) then // only used elements of a class
           UseTypeInfo(Member);
           UseTypeInfo(Member);
         end;
         end;
       end;
       end;
@@ -1266,16 +1285,28 @@ begin
   else if C=TPasClassOfType then
   else if C=TPasClassOfType then
   else if C=TPasRecordType then
   else if C=TPasRecordType then
     begin
     begin
-    // published record: use all members
-    if CanSkipGenericType(TPasRecordType(El)) then exit;
-    Members:=TPasRecordType(El).Members;
+    // published record: use all members (except generic)
+    Rec:=TPasRecordType(El);
+    if CanSkipGenericType(Rec) then exit;
+    Members:=Rec.Members;
     for i:=0 to Members.Count-1 do
     for i:=0 to Members.Count-1 do
       begin
       begin
       Member:=TPasElement(Members[i]);
       Member:=TPasElement(Members[i]);
       if Member.ClassType=TPasAttributes then
       if Member.ClassType=TPasAttributes then
         continue; // attributes are never used directly
         continue; // attributes are never used directly
-      UseSubEl(Member);
+      if IsGenericElement(Member) then
+        continue;
+      if Member.ClassType=TPasVariable then
+        // all fields, even if not used
+        UseSubEl(Member)
+      else if IsUsed(Member) then
+        // all used non fields
+        UseSubEl(Member);
       end;
       end;
+    UseSubEl(Rec.VariantEl);
+    if Rec.Variants<>nil then
+      for i:=0 to Rec.Variants.Count-1 do
+        UseSubEl(TPasVariant(Rec.Variants[i]));
     end
     end
   else if C.InheritsFrom(TPasProcedure) then
   else if C.InheritsFrom(TPasProcedure) then
     UseSubEl(TPasProcedure(El).ProcType)
     UseSubEl(TPasProcedure(El).ProcType)
@@ -1467,6 +1498,8 @@ begin
       end
       end
     else if C=TPasAttributes then
     else if C=TPasAttributes then
       // attributes are never used directly
       // attributes are never used directly
+    else if C=TPasExportSymbol then
+      UseExportSymbol(TPasExportSymbol(Decl))
     else
     else
       RaiseNotSupported(20170306165213,Decl);
       RaiseNotSupported(20170306165213,Decl);
     end;
     end;
@@ -1757,6 +1790,8 @@ begin
           end;
           end;
         end;
         end;
       end;
       end;
+    if rrfUseFields in Ref.Flags then
+      UseRecordFields(El);
 
 
     if Decl is TPasUnresolvedSymbolRef then
     if Decl is TPasUnresolvedSymbolRef then
       begin
       begin
@@ -2622,6 +2657,24 @@ begin
   UseExpr(El.Expr);
   UseExpr(El.Expr);
 end;
 end;
 
 
+procedure TPasAnalyzer.UseExportSymbol(El: TPasExportSymbol);
+var
+  Ref: TResolvedReference;
+  Decl: TPasElement;
+begin
+  if not MarkElementAsUsed(El) then exit;
+  if El.CustomData is TResolvedReference then
+    begin
+    Ref:=TResolvedReference(El.CustomData);
+    Decl:=Ref.Declaration;
+    if Decl<>nil then
+      UseElement(Decl,Ref.Access,false);
+    end;
+  UseExpr(El.NameExpr);
+  UseExpr(El.ExportName);
+  UseExpr(El.ExportIndex);
+end;
+
 procedure TPasAnalyzer.UseArgument(El: TPasArgument; Access: TResolvedRefAccess
 procedure TPasAnalyzer.UseArgument(El: TPasArgument; Access: TResolvedRefAccess
   );
   );
 var
 var
@@ -2690,6 +2743,56 @@ begin
   UpdateAccess(IsWrite, IsRead, Usage);
   UpdateAccess(IsWrite, IsRead, Usage);
 end;
 end;
 
 
+procedure TPasAnalyzer.UseRecordFields(El: TPasExpr);
+
+  procedure UseRec(Rec: TPasRecordType); forward;
+
+  procedure UseVar(V: TPasVariable);
+  var
+    ResolvedEl: TPasResolverResult;
+  begin
+    UseElement(V,rraRead,false);
+
+    // check nested record
+    Resolver.ComputeElement(V.VarType,ResolvedEl,[],V);
+    if ResolvedEl.LoTypeEl is TPasRecordType then
+      UseRec(TPasRecordType(ResolvedEl.LoTypeEl));
+  end;
+
+  procedure UseRec(Rec: TPasRecordType);
+  var
+    Members: TFPList;
+    i: Integer;
+    Member: TPasElement;
+    C: TClass;
+    Variant: TPasVariant;
+  begin
+    Members:=Rec.Members;
+    for i:=0 to Members.Count-1 do
+      begin
+      Member:=TPasElement(Members[i]);
+      C:=Member.ClassType;
+      if C=TPasVariable then
+        UseVar(TPasVariable(Member));
+      end;
+    if Rec.VariantEl is TPasVariable then
+      UseVar(TPasVariable(Rec.VariantEl));
+    if Rec.Variants<>nil then
+      for i:=0 to Rec.Variants.Count-1 do
+        begin
+        Variant:=TPasVariant(Rec.Variants[i]);
+        UseRec(Variant.Members);
+        end;
+  end;
+
+var
+  ResolvedEl: TPasResolverResult;
+begin
+  Resolver.ComputeElement(El,ResolvedEl,[]);
+  if ResolvedEl.LoTypeEl is TPasRecordType then
+    UseRec(TPasRecordType(ResolvedEl.LoTypeEl));
+end;
+
 procedure TPasAnalyzer.EmitElementHints(El: TPasElement);
 procedure TPasAnalyzer.EmitElementHints(El: TPasElement);
 var
 var
   C: TClass;
   C: TClass;

+ 2 - 287
packages/fcl-passrc/tests/tcbaseparser.pas

@@ -5,7 +5,8 @@ unit tcbaseparser;
 interface
 interface
 
 
 uses
 uses
-  Classes, SysUtils, fpcunit, pastree, pscanner, pparser, testregistry;
+  Classes, SysUtils, fpcunit, pastree, pscanner, pparser, TestPasUtils,
+  testregistry;
 
 
 const
 const
   DefaultMainFilename = 'afile.pp';
   DefaultMainFilename = 'afile.pp';
@@ -103,296 +104,10 @@ Type
     Property MainFilename: string read FMainFilename write FMainFilename;
     Property MainFilename: string read FMainFilename write FMainFilename;
   end;
   end;
 
 
-function ExtractFileUnitName(aFilename: string): string;
-function GetPasElementDesc(El: TPasElement): string;
-procedure ReadNextPascalToken(var Position: PChar; out TokenStart: PChar;
-  NestedComments: boolean; SkipDirectives: boolean);
-
 implementation
 implementation
 
 
 uses typinfo;
 uses typinfo;
 
 
-function ExtractFileUnitName(aFilename: string): string;
-var
-  p: Integer;
-begin
-  Result:=ExtractFileName(aFilename);
-  if Result='' then exit;
-  for p:=length(Result) downto 1 do
-    case Result[p] of
-    '/','\': exit;
-    '.':
-      begin
-      Delete(Result,p,length(Result));
-      exit;
-      end;
-    end;
-end;
-
-function GetPasElementDesc(El: TPasElement): string;
-begin
-  if El=nil then exit('nil');
-  Result:=El.Name+':'+El.ClassName+'['+El.SourceFilename+','+IntToStr(El.SourceLinenumber)+']';
-end;
-
-procedure ReadNextPascalToken(var Position: PChar; out TokenStart: PChar;
-  NestedComments: boolean; SkipDirectives: boolean);
-const
-  IdentChars = ['a'..'z','A'..'Z','_','0'..'9'];
-  HexNumberChars = ['0'..'9','a'..'f','A'..'F'];
-var
-  c1:char;
-  CommentLvl: Integer;
-  Src: PChar;
-begin
-  Src:=Position;
-  // read till next atom
-  while true do
-    begin
-    case Src^ of
-    #0: break;
-    #1..#32:  // spaces and special characters
-      inc(Src);
-    #$EF:
-      if (Src[1]=#$BB)
-      and (Src[2]=#$BF) then
-        begin
-        // skip UTF BOM
-        inc(Src,3);
-        end
-      else
-        break;
-    '{':    // comment start or compiler directive
-      if (Src[1]='$') and (not SkipDirectives) then
-        // compiler directive
-        break
-      else begin
-        // Pascal comment => skip
-        CommentLvl:=1;
-        while true do
-          begin
-          inc(Src);
-          case Src^ of
-          #0: break;
-          '{':
-            if NestedComments then
-              inc(CommentLvl);
-          '}':
-            begin
-            dec(CommentLvl);
-            if CommentLvl=0 then
-              begin
-              inc(Src);
-              break;
-              end;
-            end;
-          end;
-        end;
-      end;
-    '/':  // comment or real division
-      if (Src[1]='/') then
-        begin
-        // comment start -> read til line end
-        inc(Src);
-        while not (Src^ in [#0,#10,#13]) do
-          inc(Src);
-        end
-      else
-        break;
-    '(':  // comment, bracket or compiler directive
-      if (Src[1]='*') then
-        begin
-        if (Src[2]='$') and (not SkipDirectives) then
-          // compiler directive
-          break
-        else
-          begin
-          // comment start -> read til comment end
-          inc(Src,2);
-          CommentLvl:=1;
-          while true do
-            begin
-            case Src^ of
-            #0: break;
-            '(':
-              if NestedComments and (Src[1]='*') then
-                inc(CommentLvl);
-            '*':
-              if (Src[1]=')') then
-                begin
-                dec(CommentLvl);
-                if CommentLvl=0 then
-                  begin
-                  inc(Src,2);
-                  break;
-                  end;
-                inc(Position);
-                end;
-            end;
-            inc(Src);
-            end;
-        end;
-      end else
-        // round bracket open
-        break;
-    else
-      break;
-    end;
-    end;
-  // read token
-  TokenStart:=Src;
-  c1:=Src^;
-  case c1 of
-  #0:
-    ;
-  'A'..'Z','a'..'z','_':
-    begin
-    // identifier
-    inc(Src);
-    while Src^ in IdentChars do
-      inc(Src);
-    end;
-  '0'..'9': // number
-    begin
-    inc(Src);
-    // read numbers
-    while (Src^ in ['0'..'9']) do
-      inc(Src);
-    if (Src^='.') and (Src[1]<>'.') then
-      begin
-      // real type number
-      inc(Src);
-      while (Src^ in ['0'..'9']) do
-        inc(Src);
-      end;
-    if (Src^ in ['e','E']) then
-      begin
-      // read exponent
-      inc(Src);
-      if (Src^='-') then inc(Src);
-      while (Src^ in ['0'..'9']) do
-        inc(Src);
-      end;
-    end;
-  '''','#':  // string constant
-    while true do
-      case Src^ of
-      #0: break;
-      '#':
-        begin
-        inc(Src);
-        while Src^ in ['0'..'9'] do
-          inc(Src);
-        end;
-      '''':
-        begin
-        inc(Src);
-        while not (Src^ in ['''',#0]) do
-          inc(Src);
-        if Src^='''' then
-          inc(Src);
-        end;
-      else
-        break;
-      end;
-  '$':  // hex constant
-    begin
-    inc(Src);
-    while Src^ in HexNumberChars do
-      inc(Src);
-    end;
-  '&':  // octal constant or keyword as identifier (e.g. &label)
-    begin
-    inc(Src);
-    if Src^ in ['0'..'7'] then
-      while Src^ in ['0'..'7'] do
-        inc(Src)
-    else
-      while Src^ in IdentChars do
-        inc(Src);
-    end;
-  '{':  // compiler directive (it can't be a comment, because see above)
-    begin
-    CommentLvl:=1;
-    while true do
-      begin
-      inc(Src);
-      case Src^ of
-      #0: break;
-      '{':
-        if NestedComments then
-          inc(CommentLvl);
-      '}':
-        begin
-        dec(CommentLvl);
-        if CommentLvl=0 then
-          begin
-          inc(Src);
-          break;
-          end;
-        end;
-      end;
-      end;
-    end;
-  '(':  // bracket or compiler directive
-    if (Src[1]='*') then
-      begin
-      // compiler directive -> read til comment end
-      inc(Src,2);
-      while (Src^<>#0) and ((Src^<>'*') or (Src[1]<>')')) do
-        inc(Src);
-      inc(Src,2);
-      end
-    else
-      // round bracket open
-      inc(Src);
-  #192..#255:
-    begin
-    // read UTF8 character
-    inc(Src);
-    if ((ord(c1) and %11100000) = %11000000) then
-      begin
-      // could be 2 byte character
-      if (ord(Src[0]) and %11000000) = %10000000 then
-        inc(Src);
-      end
-    else if ((ord(c1) and %11110000) = %11100000) then
-      begin
-      // could be 3 byte character
-      if ((ord(Src[0]) and %11000000) = %10000000)
-      and ((ord(Src[1]) and %11000000) = %10000000) then
-        inc(Src,2);
-      end
-    else if ((ord(c1) and %11111000) = %11110000) then
-      begin
-      // could be 4 byte character
-      if ((ord(Src[0]) and %11000000) = %10000000)
-      and ((ord(Src[1]) and %11000000) = %10000000)
-      and ((ord(Src[2]) and %11000000) = %10000000) then
-        inc(Src,3);
-      end;
-    end;
-  else
-    inc(Src);
-    case c1 of
-    '<': if Src^ in ['>','='] then inc(Src);
-    '.': if Src^='.' then inc(Src);
-    '@':
-      if Src^='@' then
-        begin
-        // @@ label
-        repeat
-          inc(Src);
-        until not (Src^ in IdentChars);
-        end
-    else
-      if (Src^='=') and (c1 in [':','+','-','/','*','<','>']) then
-        inc(Src);
-    end;
-  end;
-  Position:=Src;
-end;
-
 { TTestEngine }
 { TTestEngine }
 
 
 destructor TTestEngine.Destroy;
 destructor TTestEngine.Destroy;

+ 1 - 1
packages/fcl-passrc/tests/tcexprparser.pas

@@ -5,7 +5,7 @@ unit tcexprparser;
 interface
 interface
 
 
 uses
 uses
-  Classes, SysUtils, fpcunit,  testregistry, tcbaseparser, pastree;
+  Classes, SysUtils, fpcunit, testregistry, tcbaseparser, TestPasUtils, pastree;
 
 
 type
 type
 
 

+ 30 - 0
packages/fcl-passrc/tests/tcgenerics.pas

@@ -43,6 +43,7 @@ Type
 
 
     // generic method
     // generic method
     Procedure TestGenericMethod_Program;
     Procedure TestGenericMethod_Program;
+    Procedure TestGenericMethod_OverloadDelphi;
   end;
   end;
 
 
 implementation
 implementation
@@ -384,6 +385,35 @@ begin
   ParseModule;
   ParseModule;
 end;
 end;
 
 
+procedure TTestGenerics.TestGenericMethod_OverloadDelphi;
+begin
+  Add([
+  '{$mode delphi}',
+  'type',
+  '  TObject = class',
+  '    procedure Fly<S>; overload;',
+  '    procedure Fly<T>(val: T); overload;',
+  '  end;',
+  'procedure TObject.Fly<S>;',
+  'begin',
+  'end;',
+  'procedure TObject.Fly<T>(val: word);',
+  'begin',
+  'end;',
+  'var o : TObject;',
+  'begin',
+  '  o.Fly<word>;',
+  '  o.Fly<word>();',
+  '  o.Fly<longint>(3);',
+  '  with o do begin',
+  '    Fly<word>;',
+  '    Fly<word>();',
+  '    Fly<longint>(13);',
+  '  end;',
+  '']);
+  ParseModule;
+end;
+
 initialization
 initialization
   RegisterTest(TTestGenerics);
   RegisterTest(TTestGenerics);
 end.
 end.

+ 32 - 1
packages/fcl-passrc/tests/tcresolver.pas

@@ -20,7 +20,7 @@ interface
 uses
 uses
   Classes, SysUtils, contnrs, strutils, fpcunit, testregistry,
   Classes, SysUtils, contnrs, strutils, fpcunit, testregistry,
   PasTree, PScanner, PParser, PasResolver, PasResolveEval,
   PasTree, PScanner, PParser, PasResolver, PasResolveEval,
-  tcbaseparser;
+  tcbaseparser, TestPasUtils;
 
 
 type
 type
   TSrcMarkerKind = (
   TSrcMarkerKind = (
@@ -568,6 +568,7 @@ type
     Procedure TestClass_MethodInvalidOverload;
     Procedure TestClass_MethodInvalidOverload;
     Procedure TestClass_MethodOverride;
     Procedure TestClass_MethodOverride;
     Procedure TestClass_MethodOverride2;
     Procedure TestClass_MethodOverride2;
+    Procedure TestClass_MethodOverrideAndOverload;
     Procedure TestClass_MethodOverrideFixCase;
     Procedure TestClass_MethodOverrideFixCase;
     Procedure TestClass_MethodOverrideSameResultType;
     Procedure TestClass_MethodOverrideSameResultType;
     Procedure TestClass_MethodOverrideDiffResultTypeFail;
     Procedure TestClass_MethodOverrideDiffResultTypeFail;
@@ -9644,6 +9645,36 @@ begin
   ParseProgram;
   ParseProgram;
 end;
 end;
 
 
+procedure TTestResolver.TestClass_MethodOverrideAndOverload;
+begin
+  StartProgram(false);
+  Add([
+  '{$mode delphi}',
+  'type',
+  '  TObject = class',
+  '  public',
+  '    procedure Fly(b: boolean); virtual; abstract; overload;',
+  '    procedure Fly(c: word); virtual; abstract; overload;',
+  '  end;',
+  '  TBird = class(TObject)',
+  '  public',
+  '    procedure Fly(b: boolean); override; overload;',
+  '    procedure Fly(c: word); override; overload;',
+  '  end;',
+  'procedure TBird.Fly(b: boolean);',
+  'begin end;',
+  'procedure TBird.Fly(c: word);',
+  'begin end;',
+  'var',
+  '  b: TBird;',
+  'begin',
+  '  b.Fly(true);',
+  '  b.Fly(1);',
+  'end.',
+  '']);
+  ParseProgram;
+end;
+
 procedure TTestResolver.TestClass_MethodOverrideFixCase;
 procedure TTestResolver.TestClass_MethodOverrideFixCase;
 
 
   procedure CheckOverrideName(aLabel: string);
   procedure CheckOverrideName(aLabel: string);

+ 1 - 1
packages/fcl-passrc/tests/tcstatements.pas

@@ -10,7 +10,7 @@ interface
 
 
 uses
 uses
   Classes, SysUtils, fpcunit, pastree, pscanner, pparser,
   Classes, SysUtils, fpcunit, pastree, pscanner, pparser,
-  tcbaseparser, testregistry;
+  tcbaseparser, TestPasUtils, testregistry;
 
 
 Type
 Type
   { TTestStatementParser }
   { TTestStatementParser }

+ 6 - 1
packages/fcl-passrc/tests/tcuseanalyzer.pas

@@ -10,7 +10,8 @@ interface
 
 
 uses
 uses
   Classes, SysUtils, fpcunit, PasTree, PScanner, PasResolver, tcbaseparser,
   Classes, SysUtils, fpcunit, PasTree, PScanner, PasResolver, tcbaseparser,
-  testregistry, strutils, tcresolver, PasUseAnalyzer, PasResolveEval;
+  testregistry, strutils, tcresolver, PasUseAnalyzer,
+  PasResolveEval;
 
 
 type
 type
 
 
@@ -280,7 +281,9 @@ begin
   aMarker:=FirstSrcMarker;
   aMarker:=FirstSrcMarker;
   while aMarker<>nil do
   while aMarker<>nil do
     begin
     begin
+    {$IFDEF VerbosePasAnalyzer}
     writeln('TCustomTestUseAnalyzer.CheckUsedMarkers ',aMarker^.Identifier,' Line=',aMarker^.Row,' StartCol=',aMarker^.StartCol,' EndCol=',aMarker^.EndCol);
     writeln('TCustomTestUseAnalyzer.CheckUsedMarkers ',aMarker^.Identifier,' Line=',aMarker^.Row,' StartCol=',aMarker^.StartCol,' EndCol=',aMarker^.EndCol);
+    {$ENDIF}
     p:=RPos('_',aMarker^.Identifier);
     p:=RPos('_',aMarker^.Identifier);
     if p>1 then
     if p>1 then
       begin
       begin
@@ -303,7 +306,9 @@ begin
         for i:=0 to Elements.Count-1 do
         for i:=0 to Elements.Count-1 do
           begin
           begin
           El:=TPasElement(Elements[i]);
           El:=TPasElement(Elements[i]);
+          {$IFDEF VerbosePasAnalyzer}
           writeln('TCustomTestUseAnalyzer.CheckUsedMarkers ',aMarker^.Identifier,' ',i,'/',Elements.Count,' El=',GetObjName(El),' ',GetObjName(El.CustomData));
           writeln('TCustomTestUseAnalyzer.CheckUsedMarkers ',aMarker^.Identifier,' ',i,'/',Elements.Count,' El=',GetObjName(El),' ',GetObjName(El.CustomData));
+          {$ENDIF}
           case ExpectedUsed of
           case ExpectedUsed of
           uUsed,uNotUsed:
           uUsed,uNotUsed:
             if Analyzer.IsUsed(El) then
             if Analyzer.IsUsed(El) then

+ 1 - 1
packages/fcl-passrc/tests/testpassrc.lpr

@@ -7,7 +7,7 @@ uses
   Classes, consoletestrunner, tcscanner,  tctypeparser, tcstatements,
   Classes, consoletestrunner, tcscanner,  tctypeparser, tcstatements,
   tcbaseparser, tcmoduleparser, tconstparser, tcvarparser, tcclasstype,
   tcbaseparser, tcmoduleparser, tconstparser, tcvarparser, tcclasstype,
   tcexprparser, tcprocfunc, tcpassrcutil, tcresolver,
   tcexprparser, tcprocfunc, tcpassrcutil, tcresolver,
-  tcuseanalyzer, pasresolveeval, tcresolvegenerics, tcgenerics;
+  tcuseanalyzer, pasresolveeval, tcresolvegenerics, tcgenerics, TestPasUtils;
 
 
 type
 type
 
 

+ 299 - 0
packages/fcl-passrc/tests/testpasutils.pas

@@ -0,0 +1,299 @@
+unit TestPasUtils;
+
+{$mode ObjFPC}{$H+}
+
+interface
+
+uses
+  Classes, SysUtils, PasTree;
+
+function ExtractFileUnitName(aFilename: string): string;
+function GetPasElementDesc(El: TPasElement): string;
+procedure ReadNextPascalToken(var Position: PChar; out TokenStart: PChar;
+  NestedComments: boolean; SkipDirectives: boolean);
+
+implementation
+
+function ExtractFileUnitName(aFilename: string): string;
+var
+  p: Integer;
+begin
+  Result:=ExtractFileName(aFilename);
+  if Result='' then exit;
+  for p:=length(Result) downto 1 do
+    case Result[p] of
+    '/','\': exit;
+    '.':
+      begin
+      Delete(Result,p,length(Result));
+      exit;
+      end;
+    end;
+end;
+
+function GetPasElementDesc(El: TPasElement): string;
+begin
+  if El=nil then exit('nil');
+  Result:=El.Name+':'+El.ClassName+'['+El.SourceFilename+','+IntToStr(El.SourceLinenumber)+']';
+end;
+
+procedure ReadNextPascalToken(var Position: PChar; out TokenStart: PChar;
+  NestedComments: boolean; SkipDirectives: boolean);
+const
+  IdentChars = ['a'..'z','A'..'Z','_','0'..'9'];
+  HexNumberChars = ['0'..'9','a'..'f','A'..'F'];
+var
+  c1:char;
+  CommentLvl: Integer;
+  Src: PChar;
+begin
+  Src:=Position;
+  // read till next atom
+  while true do
+    begin
+    case Src^ of
+    #0: break;
+    #1..#32:  // spaces and special characters
+      inc(Src);
+    #$EF:
+      if (Src[1]=#$BB)
+      and (Src[2]=#$BF) then
+        begin
+        // skip UTF BOM
+        inc(Src,3);
+        end
+      else
+        break;
+    '{':    // comment start or compiler directive
+      if (Src[1]='$') and (not SkipDirectives) then
+        // compiler directive
+        break
+      else begin
+        // Pascal comment => skip
+        CommentLvl:=1;
+        while true do
+          begin
+          inc(Src);
+          case Src^ of
+          #0: break;
+          '{':
+            if NestedComments then
+              inc(CommentLvl);
+          '}':
+            begin
+            dec(CommentLvl);
+            if CommentLvl=0 then
+              begin
+              inc(Src);
+              break;
+              end;
+            end;
+          end;
+        end;
+      end;
+    '/':  // comment or real division
+      if (Src[1]='/') then
+        begin
+        // comment start -> read til line end
+        inc(Src);
+        while not (Src^ in [#0,#10,#13]) do
+          inc(Src);
+        end
+      else
+        break;
+    '(':  // comment, bracket or compiler directive
+      if (Src[1]='*') then
+        begin
+        if (Src[2]='$') and (not SkipDirectives) then
+          // compiler directive
+          break
+        else
+          begin
+          // comment start -> read til comment end
+          inc(Src,2);
+          CommentLvl:=1;
+          while true do
+            begin
+            case Src^ of
+            #0: break;
+            '(':
+              if NestedComments and (Src[1]='*') then
+                inc(CommentLvl);
+            '*':
+              if (Src[1]=')') then
+                begin
+                dec(CommentLvl);
+                if CommentLvl=0 then
+                  begin
+                  inc(Src,2);
+                  break;
+                  end;
+                inc(Position);
+                end;
+            end;
+            inc(Src);
+            end;
+        end;
+      end else
+        // round bracket open
+        break;
+    else
+      break;
+    end;
+    end;
+  // read token
+  TokenStart:=Src;
+  c1:=Src^;
+  case c1 of
+  #0:
+    ;
+  'A'..'Z','a'..'z','_':
+    begin
+    // identifier
+    inc(Src);
+    while Src^ in IdentChars do
+      inc(Src);
+    end;
+  '0'..'9': // number
+    begin
+    inc(Src);
+    // read numbers
+    while (Src^ in ['0'..'9']) do
+      inc(Src);
+    if (Src^='.') and (Src[1]<>'.') then
+      begin
+      // real type number
+      inc(Src);
+      while (Src^ in ['0'..'9']) do
+        inc(Src);
+      end;
+    if (Src^ in ['e','E']) then
+      begin
+      // read exponent
+      inc(Src);
+      if (Src^='-') then inc(Src);
+      while (Src^ in ['0'..'9']) do
+        inc(Src);
+      end;
+    end;
+  '''','#':  // string constant
+    while true do
+      case Src^ of
+      #0: break;
+      '#':
+        begin
+        inc(Src);
+        while Src^ in ['0'..'9'] do
+          inc(Src);
+        end;
+      '''':
+        begin
+        inc(Src);
+        while not (Src^ in ['''',#0]) do
+          inc(Src);
+        if Src^='''' then
+          inc(Src);
+        end;
+      else
+        break;
+      end;
+  '$':  // hex constant
+    begin
+    inc(Src);
+    while Src^ in HexNumberChars do
+      inc(Src);
+    end;
+  '&':  // octal constant or keyword as identifier (e.g. &label)
+    begin
+    inc(Src);
+    if Src^ in ['0'..'7'] then
+      while Src^ in ['0'..'7'] do
+        inc(Src)
+    else
+      while Src^ in IdentChars do
+        inc(Src);
+    end;
+  '{':  // compiler directive (it can't be a comment, because see above)
+    begin
+    CommentLvl:=1;
+    while true do
+      begin
+      inc(Src);
+      case Src^ of
+      #0: break;
+      '{':
+        if NestedComments then
+          inc(CommentLvl);
+      '}':
+        begin
+        dec(CommentLvl);
+        if CommentLvl=0 then
+          begin
+          inc(Src);
+          break;
+          end;
+        end;
+      end;
+      end;
+    end;
+  '(':  // bracket or compiler directive
+    if (Src[1]='*') then
+      begin
+      // compiler directive -> read til comment end
+      inc(Src,2);
+      while (Src^<>#0) and ((Src^<>'*') or (Src[1]<>')')) do
+        inc(Src);
+      inc(Src,2);
+      end
+    else
+      // round bracket open
+      inc(Src);
+  #192..#255:
+    begin
+    // read UTF8 character
+    inc(Src);
+    if ((ord(c1) and %11100000) = %11000000) then
+      begin
+      // could be 2 byte character
+      if (ord(Src[0]) and %11000000) = %10000000 then
+        inc(Src);
+      end
+    else if ((ord(c1) and %11110000) = %11100000) then
+      begin
+      // could be 3 byte character
+      if ((ord(Src[0]) and %11000000) = %10000000)
+      and ((ord(Src[1]) and %11000000) = %10000000) then
+        inc(Src,2);
+      end
+    else if ((ord(c1) and %11111000) = %11110000) then
+      begin
+      // could be 4 byte character
+      if ((ord(Src[0]) and %11000000) = %10000000)
+      and ((ord(Src[1]) and %11000000) = %10000000)
+      and ((ord(Src[2]) and %11000000) = %10000000) then
+        inc(Src,3);
+      end;
+    end;
+  else
+    inc(Src);
+    case c1 of
+    '<': if Src^ in ['>','='] then inc(Src);
+    '.': if Src^='.' then inc(Src);
+    '@':
+      if Src^='@' then
+        begin
+        // @@ label
+        repeat
+          inc(Src);
+        until not (Src^ in IdentChars);
+        end
+    else
+      if (Src^='=') and (c1 in [':','+','-','/','*','<','>']) then
+        inc(Src);
+    end;
+  end;
+  Position:=Src;
+end;
+
+end.
+

+ 0 - 1
packages/fcl-web/src/base/fphttpclient.pp

@@ -677,7 +677,6 @@ begin
       Aport:=443
       Aport:=443
     else
     else
       Aport:=80;
       Aport:=80;
-  G:=GetSocketHandler(UseSSL);    
   {$ifdef Unix}
   {$ifdef Unix}
   IsUnixSocketConnection := UnixSocketPath <> '';
   IsUnixSocketConnection := UnixSocketPath <> '';
   if IsUnixSocketConnection then
   if IsUnixSocketConnection then

+ 14 - 5
packages/fcl-web/src/base/httproute.pp

@@ -52,6 +52,7 @@ Type
     Procedure DoHandleRequest(ARequest : TRequest; AResponse : TResponse); virtual;
     Procedure DoHandleRequest(ARequest : TRequest; AResponse : TResponse); virtual;
   Public
   Public
     Destructor Destroy; override;
     Destructor Destroy; override;
+    class function NormalizeRoute(AValue: String): String;
     Procedure HandleRequest(ARequest : TRequest; AResponse : TResponse);
     Procedure HandleRequest(ARequest : TRequest; AResponse : TResponse);
     Function Matches(Const APattern : String; AMethod : TRouteMethod; Options : TRouteOptions) : Boolean;
     Function Matches(Const APattern : String; AMethod : TRouteMethod; Options : TRouteOptions) : Boolean;
     Function MatchPattern(Const Path : String; L : TStrings; Options : TRouteOptions) : Boolean;
     Function MatchPattern(Const Path : String; L : TStrings; Options : TRouteOptions) : Boolean;
@@ -457,9 +458,11 @@ procedure THTTPRouter.CheckDuplicate(APattern: String; AMethod: TRouteMethod;
 Var
 Var
   I,DI : Integer;
   I,DI : Integer;
   R : THTTPRoute;
   R : THTTPRoute;
+  aPtrn : String;
 
 
 begin
 begin
   DI:=-1;
   DI:=-1;
+  aPtrn:=THTTPRoute.NormalizeRoute(aPattern);
   Lock;
   Lock;
   try
   try
     For I:=0 to FRoutes.Count-1 do
     For I:=0 to FRoutes.Count-1 do
@@ -467,7 +470,7 @@ begin
       R:=FRoutes[I];
       R:=FRoutes[I];
       if R.Default then
       if R.Default then
         DI:=I;
         DI:=I;
-      if R.Matches(APattern,AMethod,FRouteOptions) then
+      if R.Matches(aPtrn,AMethod,FRouteOptions) then
         Raise EHTTPRoute.CreateFmt(EDuplicateRoute,[APattern,RouteMethodToString(AMethod)]);
         Raise EHTTPRoute.CreateFmt(EDuplicateRoute,[APattern,RouteMethodToString(AMethod)]);
       end;
       end;
   finally
   finally
@@ -866,15 +869,21 @@ end;
 
 
 { THTTPRoute }
 { THTTPRoute }
 
 
+Class Function THTTPRoute.NormalizeRoute(AValue: String) : String;
+
+begin
+  Result:=IncludeHTTPPathDelimiter(AValue);
+  if (Length(Result)>1) and (Result[1]='/') then
+    Delete(Result,1,1);
+end;
+
 procedure THTTPRoute.SetURLPattern(AValue: String);
 procedure THTTPRoute.SetURLPattern(AValue: String);
 
 
 Var
 Var
   V : String;
   V : String;
 
 
 begin
 begin
-  V:=IncludeHTTPPathDelimiter(AValue);
-  if (V<>'') and (V<>'/') and (V[1]='/') then
-    Delete(V,1,1);
+  V:=NormalizeRoute(aValue);
   if FURLPattern=V then Exit;
   if FURLPattern=V then Exit;
   FURLPattern:=V;
   FURLPattern:=V;
 end;
 end;
@@ -899,7 +908,7 @@ function THTTPRoute.Matches(const APattern: String; AMethod: TRouteMethod; Optio
 begin
 begin
   Result:=((Method=rmAll) or (AMethod=Method));
   Result:=((Method=rmAll) or (AMethod=Method));
   if Result then
   if Result then
-    Result:=SameText(URLPattern,APattern) or ((URLPattern='') and (roEmptyMatchesAll in Options))
+    Result:=SameText(URLPattern,NormalizeRoute(APattern)) or ((URLPattern='') and (roEmptyMatchesAll in Options))
 end;
 end;
 
 
 Function THTTPRoute.MatchPattern(Const Path : String; L : TStrings; Options: TRouteOptions) : Boolean;
 Function THTTPRoute.MatchPattern(Const Path : String; L : TStrings; Options: TRouteOptions) : Boolean;

+ 2 - 2
packages/ide/Makefile

@@ -2957,7 +2957,7 @@ ifdef CREATESHARED
 override FPCOPT+=-Cg
 override FPCOPT+=-Cg
 endif
 endif
 ifneq ($(filter $(OS_TARGET),dragonfly freebsd openbsd netbsd linux solaris),)
 ifneq ($(filter $(OS_TARGET),dragonfly freebsd openbsd netbsd linux solaris),)
-ifneq ($(filter $(CPU_TARGET),x86_64 mips mipsel riscv64 powerpc64),)
+ifneq ($(filter $(CPU_TARGET),x86_64 mips mipsel mips64 mips64el riscv64 powerpc64),)
 override FPCOPT+=-Cg
 override FPCOPT+=-Cg
 endif
 endif
 endif
 endif
@@ -3430,7 +3430,7 @@ ifdef NOLLVM
 FPMAKE_OPT+=--NOLLVM=1
 FPMAKE_OPT+=--NOLLVM=1
 endif
 endif
 .NOTPARALLEL:
 .NOTPARALLEL:
-PPC_TARGETS=i386 m68k powerpc sparc arm x86_64 powerpc64 mips mipsel avr jvm i8086 aarch64 sparc64
+PPC_TARGETS=i386 m68k powerpc sparc arm x86_64 powerpc64 mips mipsel avr jvm i8086 aarch64 sparc64 riscv32 riscv64 xtensa wasm32 z80
 CLEAN_TARGETS=$(addsuffix _clean,$(sort $(PPC_TARGETS)))
 CLEAN_TARGETS=$(addsuffix _clean,$(sort $(PPC_TARGETS)))
 DISTCLEAN_TARGETS=$(addsuffix _distclean,$(sort $(PPC_TARGETS)))
 DISTCLEAN_TARGETS=$(addsuffix _distclean,$(sort $(PPC_TARGETS)))
 INSTALL_TARGETS=$(addsuffix _exe_install,$(sort $(PPC_TARGETS)))
 INSTALL_TARGETS=$(addsuffix _exe_install,$(sort $(PPC_TARGETS)))

+ 1 - 1
packages/ide/Makefile.fpc

@@ -100,7 +100,7 @@ endif
 
 
 .NOTPARALLEL:
 .NOTPARALLEL:
 
 
-PPC_TARGETS=i386 m68k powerpc sparc arm x86_64 powerpc64 mips mipsel avr jvm i8086 aarch64 sparc64
+PPC_TARGETS=i386 m68k powerpc sparc arm x86_64 powerpc64 mips mipsel avr jvm i8086 aarch64 sparc64 riscv32 riscv64 xtensa wasm32 z80
 CLEAN_TARGETS=$(addsuffix _clean,$(sort $(PPC_TARGETS)))
 CLEAN_TARGETS=$(addsuffix _clean,$(sort $(PPC_TARGETS)))
 DISTCLEAN_TARGETS=$(addsuffix _distclean,$(sort $(PPC_TARGETS)))
 DISTCLEAN_TARGETS=$(addsuffix _distclean,$(sort $(PPC_TARGETS)))
 INSTALL_TARGETS=$(addsuffix _exe_install,$(sort $(PPC_TARGETS)))
 INSTALL_TARGETS=$(addsuffix _exe_install,$(sort $(PPC_TARGETS)))

+ 10 - 1
packages/ide/compiler/Makefile

@@ -388,6 +388,15 @@ endif
 ifeq ($(PPC_TARGET),sparc64)
 ifeq ($(PPC_TARGET),sparc64)
 override FPCOPT+= -Fu$(COMPILERDIR)/sparcgen -Fi$(COMPILERDIR)/sparcgen
 override FPCOPT+= -Fu$(COMPILERDIR)/sparcgen -Fi$(COMPILERDIR)/sparcgen
 endif
 endif
+ifeq ($(PPC_TARGET),wasm32)
+override FPCOPT+= -dNOOPT
+endif
+ifeq ($(PPC_TARGET),riscv32)
+override LOCALOPT+=-Furiscv
+endif
+ifeq ($(PPC_TARGET),riscv64)
+override LOCALOPT+=-Furiscv
+endif
 ifeq ($(FULL_TARGET),i386-linux)
 ifeq ($(FULL_TARGET),i386-linux)
 override TARGET_UNITS+=compunit
 override TARGET_UNITS+=compunit
 endif
 endif
@@ -3787,7 +3796,7 @@ ifdef CREATESHARED
 override FPCOPT+=-Cg
 override FPCOPT+=-Cg
 endif
 endif
 ifneq ($(filter $(OS_TARGET),dragonfly freebsd openbsd netbsd linux solaris),)
 ifneq ($(filter $(OS_TARGET),dragonfly freebsd openbsd netbsd linux solaris),)
-ifneq ($(filter $(CPU_TARGET),x86_64 mips mipsel riscv64 powerpc64),)
+ifneq ($(filter $(CPU_TARGET),x86_64 mips mipsel mips64 mips64el riscv64 powerpc64),)
 override FPCOPT+=-Cg
 override FPCOPT+=-Cg
 endif
 endif
 endif
 endif

+ 14 - 0
packages/ide/compiler/Makefile.fpc

@@ -75,6 +75,20 @@ endif
 ifeq ($(PPC_TARGET),sparc64)
 ifeq ($(PPC_TARGET),sparc64)
 override FPCOPT+= -Fu$(COMPILERDIR)/sparcgen -Fi$(COMPILERDIR)/sparcgen
 override FPCOPT+= -Fu$(COMPILERDIR)/sparcgen -Fi$(COMPILERDIR)/sparcgen
 endif
 endif
+# wasm32 specific
+ifeq ($(PPC_TARGET),wasm32)
+override FPCOPT+= -dNOOPT
+endif
+# RiscV32 specific
+ifeq ($(PPC_TARGET),riscv32)
+override LOCALOPT+=-Furiscv
+endif
+# RiscV64 specific
+ifeq ($(PPC_TARGET),riscv64)
+override LOCALOPT+=-Furiscv
+endif
+
+
 
 
 
 
 [rules]
 [rules]

+ 3 - 1
packages/ide/fpmake.pp

@@ -248,6 +248,8 @@ begin
         P.Options.Add('-dNOCATCH');
         P.Options.Add('-dNOCATCH');
         P.Options.Add('-dBrowserCol');
         P.Options.Add('-dBrowserCol');
         P.Options.Add('-dGDB');
         P.Options.Add('-dGDB');
+        if CompilerTarget=wasm32 then
+          P.Options.Add('-dNOOPT');
         
         
         CompilerDir:=P.Directory +'../../compiler';
         CompilerDir:=P.Directory +'../../compiler';
 
 
@@ -302,7 +304,7 @@ begin
         T:=P.Targets.AddProgram('fp.pas');
         T:=P.Targets.AddProgram('fp.pas');
         if CompilerTarget<>Defaults.CPU then
         if CompilerTarget<>Defaults.CPU then
           begin
           begin
-            T.SetExeName(CPUToString(CompilerTarget)+'-fp');
+            T.SetExeName(AddProgramExtension(CPUToString(CompilerTarget)+'-fp',Defaults.BuildOS));
             P.SetUnitsOutputDir(P.GetUnitsOutputDir(Defaults.BuildCPU,Defaults.BuildOS)+CPUToString(CompilerTarget));
             P.SetUnitsOutputDir(P.GetUnitsOutputDir(Defaults.BuildCPU,Defaults.BuildOS)+CPUToString(CompilerTarget));
             P.Options.Add('-dCROSSGDB');
             P.Options.Add('-dCROSSGDB');
           end;
           end;

+ 181 - 13
packages/pastojs/src/fppas2js.pp

@@ -677,6 +677,7 @@ type
     pbivnMessageInt,
     pbivnMessageInt,
     pbivnMessageStr,
     pbivnMessageStr,
     pbivnLibrary, // library
     pbivnLibrary, // library
+    pbivnLibraryVars, // library vars
     pbivnLocalModuleRef,
     pbivnLocalModuleRef,
     pbivnLocalProcRef,
     pbivnLocalProcRef,
     pbivnLocalTypeRef,
     pbivnLocalTypeRef,
@@ -865,6 +866,7 @@ const
     '$msgint', // pbivnMessageInt
     '$msgint', // pbivnMessageInt
     '$msgstr', // pbivnMessageStr
     '$msgstr', // pbivnMessageStr
     'library', //  pbivnLibrary  pas.library
     'library', //  pbivnLibrary  pas.library
+    'vars', //  pbivnLibraryVars  vars
     '$lm', // pbivnLocalModuleRef
     '$lm', // pbivnLocalModuleRef
     '$lp', // pbivnLocalProcRef
     '$lp', // pbivnLocalProcRef
     '$lt', // pbivnLocalTypeRef
     '$lt', // pbivnLocalTypeRef
@@ -1552,6 +1554,9 @@ type
     procedure FinishPropertyParamAccess(Params: TParamsExpr; Prop: TPasProperty
     procedure FinishPropertyParamAccess(Params: TParamsExpr; Prop: TPasProperty
       ); override;
       ); override;
     procedure FinishExportSymbol(El: TPasExportSymbol); override;
     procedure FinishExportSymbol(El: TPasExportSymbol); override;
+    procedure ComputeArgumentExpr(const ArgResolved: TPasResolverResult;
+      Access: TArgumentAccess; Expr: TPasExpr; out
+      ExprResolved: TPasResolverResult; SetReferenceFlags: boolean); override;
     procedure FindCreatorArrayOfConst(Args: TFPList; ErrorEl: TPasElement);
     procedure FindCreatorArrayOfConst(Args: TFPList; ErrorEl: TPasElement);
     function FindProc_ArrLitToArrayOfConst(ErrorEl: TPasElement): TPasFunction; virtual;
     function FindProc_ArrLitToArrayOfConst(ErrorEl: TPasElement): TPasFunction; virtual;
     function FindSystemExternalClassType(const aClassName, JSName: string;
     function FindSystemExternalClassType(const aClassName, JSName: string;
@@ -2049,6 +2054,7 @@ type
       AContext: TConvertContext): TJSElement; virtual;
       AContext: TConvertContext): TJSElement; virtual;
     Function CreateCallRTLFreeLoc(Setter, Getter: TJSElement; Src: TPasElement): TJSElement; virtual;
     Function CreateCallRTLFreeLoc(Setter, Getter: TJSElement; Src: TPasElement): TJSElement; virtual;
     Function CreateDotSplit(El: TPasElement; Expr: TJSElement): TJSElement; virtual;
     Function CreateDotSplit(El: TPasElement; Expr: TJSElement): TJSElement; virtual;
+    Function CreateExportStatement(VarType: TJSVarType; AliasName: TJSString; InitJS: TJSElement; PosEl: TPasElement): TJSExportStatement; virtual;
     Function CreatePrecompiledJS(El: TJSElement): string; virtual;
     Function CreatePrecompiledJS(El: TJSElement): string; virtual;
     Procedure AddRTLVersionCheck(FuncContext: TFunctionContext; PosEl: TPasElement);
     Procedure AddRTLVersionCheck(FuncContext: TFunctionContext; PosEl: TPasElement);
     // JS literals
     // JS literals
@@ -2097,6 +2103,7 @@ type
     Function CreateImplementationSection(El: TPasModule; IntfContext: TInterfaceSectionContext): TJSFunctionDeclarationStatement; virtual;
     Function CreateImplementationSection(El: TPasModule; IntfContext: TInterfaceSectionContext): TJSFunctionDeclarationStatement; virtual;
     Procedure CreateInitSection(El: TPasModule; Src: TJSSourceElements; AContext: TConvertContext); virtual;
     Procedure CreateInitSection(El: TPasModule; Src: TJSSourceElements; AContext: TConvertContext); virtual;
     Procedure CreateExportsSection(El: TPasLibrary; Src: TJSSourceElements; AContext: TConvertContext); virtual;
     Procedure CreateExportsSection(El: TPasLibrary; Src: TJSSourceElements; AContext: TConvertContext); virtual;
+    Function AddRTLRun(El: TPasModule; ModuleName: string; Src: TJSSourceElements; AContext: TConvertContext): TJSCallExpression; virtual;
     Procedure AddHeaderStatement(JS: TJSElement; PosEl: TPasElement; aContext: TConvertContext); virtual;
     Procedure AddHeaderStatement(JS: TJSElement; PosEl: TPasElement; aContext: TConvertContext); virtual;
     Procedure AddImplHeaderStatement(JS: TJSElement; PosEl: TPasElement; aContext: TConvertContext); virtual;
     Procedure AddImplHeaderStatement(JS: TJSElement; PosEl: TPasElement; aContext: TConvertContext); virtual;
     function AddDelayedInits(El: TPasModule; Src: TJSSourceElements; AContext: TConvertContext): boolean; virtual;
     function AddDelayedInits(El: TPasModule; Src: TJSSourceElements; AContext: TConvertContext): boolean; virtual;
@@ -4912,6 +4919,7 @@ procedure TPas2JSResolver.FinishExportSymbol(El: TPasExportSymbol);
 var
 var
   ResolvedEl: TPasResolverResult;
   ResolvedEl: TPasResolverResult;
   DeclEl: TPasElement;
   DeclEl: TPasElement;
+  C: TClass;
   Proc: TPasProcedure;
   Proc: TPasProcedure;
   V: TPasVariable;
   V: TPasVariable;
 begin
 begin
@@ -4932,6 +4940,7 @@ begin
       sSymbolCannotBeExportedFromALibrary,[],El);
       sSymbolCannotBeExportedFromALibrary,[],El);
   if DeclEl is TPasResultElement then
   if DeclEl is TPasResultElement then
     DeclEl:=DeclEl.Parent.Parent;
     DeclEl:=DeclEl.Parent.Parent;
+  C:=DeclEl.ClassType;
 
 
   if DeclEl.Parent=nil then
   if DeclEl.Parent=nil then
     RaiseMsg(20220206142534,nSymbolCannotBeExportedFromALibrary,
     RaiseMsg(20220206142534,nSymbolCannotBeExportedFromALibrary,
@@ -4949,14 +4958,14 @@ begin
     RaiseMsg(20211022224239,nSymbolCannotBeExportedFromALibrary,
     RaiseMsg(20211022224239,nSymbolCannotBeExportedFromALibrary,
       sSymbolCannotBeExportedFromALibrary,[],El);
       sSymbolCannotBeExportedFromALibrary,[],El);
 
 
-  if DeclEl is TPasProcedure then
+  if C.InheritsFrom(TPasProcedure) then
     begin
     begin
     Proc:=TPasProcedure(DeclEl);
     Proc:=TPasProcedure(DeclEl);
     if Proc.IsExternal or Proc.IsAbstract then
     if Proc.IsExternal or Proc.IsAbstract then
       RaiseMsg(20211021225630,nSymbolCannotBeExportedFromALibrary,
       RaiseMsg(20211021225630,nSymbolCannotBeExportedFromALibrary,
         sSymbolCannotBeExportedFromALibrary,[],El);
         sSymbolCannotBeExportedFromALibrary,[],El);
     end
     end
-  else if DeclEl is TPasVariable then
+  else if (C=TPasVariable) or (C=TPasConst) then
     begin
     begin
     V:=TPasVariable(DeclEl);
     V:=TPasVariable(DeclEl);
     if vmExternal in V.VarModifiers then
     if vmExternal in V.VarModifiers then
@@ -4964,8 +4973,39 @@ begin
         sSymbolCannotBeExportedFromALibrary,[],El);
         sSymbolCannotBeExportedFromALibrary,[],El);
     end
     end
   else
   else
+    begin
+    {$IFDEF VerbosePas2JS}
+    writeln('TPas2JSResolver.FinishExportSymbol ',GetObjPath(El));
+    {$ENDIF}
     RaiseMsg(20210106223621,nSymbolCannotBeExportedFromALibrary,
     RaiseMsg(20210106223621,nSymbolCannotBeExportedFromALibrary,
       sSymbolCannotBeExportedFromALibrary,[],El);
       sSymbolCannotBeExportedFromALibrary,[],El);
+    end;
+end;
+
+procedure TPas2JSResolver.ComputeArgumentExpr(
+  const ArgResolved: TPasResolverResult; Access: TArgumentAccess;
+  Expr: TPasExpr; out ExprResolved: TPasResolverResult;
+  SetReferenceFlags: boolean);
+var
+  RightEl: TPasExpr;
+  Ref: TResolvedReference;
+begin
+  inherited ComputeArgumentExpr(ArgResolved, Access, Expr, ExprResolved,
+    SetReferenceFlags);
+  if SetReferenceFlags
+      and (Access in [argDefault, argConst])
+      and ((ArgResolved.BaseType=btUntyped)
+         or IsJSBaseType(ArgResolved,pbtJSValue,true{must have rrfReadable}))
+      and (ExprResolved.LoTypeEl is TPasRecordType) then
+    begin
+    // passing a record to an untyped or jsvalue parameter -> mark fields as "read" too
+    RightEl:=GetRightMostExpr(Expr);
+    if RightEl.CustomData is TResolvedReference then
+      begin
+      Ref:=TResolvedReference(RightEl.CustomData);
+      Include(Ref.Flags,rrfUseFields);
+      end;
+    end;
 end;
 end;
 
 
 procedure TPas2JSResolver.FindCreatorArrayOfConst(Args: TFPList;
 procedure TPas2JSResolver.FindCreatorArrayOfConst(Args: TFPList;
@@ -8207,7 +8247,10 @@ Library:
         <initialization>
         <initialization>
         };
         };
     });
     });
-  export1 = pas.unit1.func1;
+  rtl.run('library');
+  var li = pas['library'];
+  export const func1 = pas.unit1.func1;
+  export const var1 = li.var1;
 
 
 Unit without implementation:
 Unit without implementation:
  rtl.module('<unitname>',
  rtl.module('<unitname>',
@@ -8337,7 +8380,6 @@ begin
       if Assigned(Lib.LibrarySection) then
       if Assigned(Lib.LibrarySection) then
         AddToSourceElements(Src,ConvertDeclarations(Lib.LibrarySection,IntfContext));
         AddToSourceElements(Src,ConvertDeclarations(Lib.LibrarySection,IntfContext));
       HasImplCode:=AddDelayedInits(Lib,Src,IntfContext);
       HasImplCode:=AddDelayedInits(Lib,Src,IntfContext);
-      CreateExportsSection(Lib,Src,IntfContext);
       CreateInitSection(Lib,Src,IntfContext);
       CreateInitSection(Lib,Src,IntfContext);
       end
       end
     else
     else
@@ -8387,6 +8429,18 @@ begin
 
 
     if (ModScope<>nil) and (coStoreImplJS in Options) then
     if (ModScope<>nil) and (coStoreImplJS in Options) then
       StoreImplJSLocals(ModScope,IntfContext);
       StoreImplJSLocals(ModScope,IntfContext);
+
+    if El is TPasLibrary then
+      begin
+      // library: rtl.run('library');
+      Lib:=TPasLibrary(El);
+      AddRTLRun(Lib,ModuleName,OuterSrc,AContext);
+      CreateExportsSection(Lib,OuterSrc,AContext);
+      end
+    else if (El is TPasProgram) and (Globals.TargetPlatform in [PlatformNodeJS,PlatformModule]) then
+      // program: rtl.run();
+      AddRTLRun(El,'',OuterSrc,AContext);
+
     ok:=true;
     ok:=true;
   finally
   finally
     IntfContext.Free;
     IntfContext.Free;
@@ -18029,28 +18083,58 @@ end;
 
 
 procedure TPasToJSConverter.CreateExportsSection(El: TPasLibrary;
 procedure TPasToJSConverter.CreateExportsSection(El: TPasLibrary;
   Src: TJSSourceElements; AContext: TConvertContext);
   Src: TJSSourceElements; AContext: TConvertContext);
+// functions:
+//   export const func1 = pas.unit1.func1;
+// variables:
+//   export const vars = {};
+//   Object.defineProperties(vars, {
+//     Var1: {
+//       get: function(){return pas.unit1.Var1;},
+//       set: function(v){pas.unit1.Var1 = v;},
+//     }
+//   });
+
+  procedure AddPropFunction(ObjLit: TJSObjectLiteral; AliasName, Arg1: TJSString;
+    BodyJS: TJSElement; PosEl: TPasElement);
+  var
+    Lit: TJSObjectLiteralElement;
+    FuncSt: TJSFunctionDeclarationStatement;
+  begin
+    Lit:=ObjLit.Elements.AddElement;
+    Lit.Name:=AliasName;
+    FuncSt:=CreateFunctionSt(PosEl,true,false);
+    Lit.Expr:=FuncSt;
+    if Arg1<>'' then
+      FuncSt.AFunction.TypedParams.AddParam(Arg1);
+    FuncSt.AFunction.Body.A:=BodyJS;
+  end;
+
+
 var
 var
   ExportSymbols: TFPList;
   ExportSymbols: TFPList;
   aResolver: TPas2JSResolver;
   aResolver: TPas2JSResolver;
-  ExpSt: TJSExportStatement;
+  VarsExpSt, ExpSt: TJSExportStatement;
   i: Integer;
   i: Integer;
   Symb: TPasExportSymbol;
   Symb: TPasExportSymbol;
   Ref: TResolvedReference;
   Ref: TResolvedReference;
   NamePath: String;
   NamePath: String;
+  AliasName: TJSString;
   EvalValue: TResEvalValue;
   EvalValue: TResEvalValue;
-  ExpNameJS: TJSExportNameElement;
   Decl: TPasElement;
   Decl: TPasElement;
   ResolvedEl: TPasResolverResult;
   ResolvedEl: TPasResolverResult;
+  Call: TJSCallExpression;
+  VarsObjLit, VarObjLit: TJSObjectLiteral;
+  Lit, SubLit: TJSObjectLiteralElement;
+  RetSt: TJSReturnStatement;
+  AssignSt: TJSSimpleAssignStatement;
 begin
 begin
   ExportSymbols:=El.LibrarySection.ExportSymbols;
   ExportSymbols:=El.LibrarySection.ExportSymbols;
   if ExportSymbols.Count=0 then exit;
   if ExportSymbols.Count=0 then exit;
   aResolver:=AContext.Resolver;
   aResolver:=AContext.Resolver;
 
 
-  ExpSt:=TJSExportStatement(CreateElement(TJSExportStatement,El));
-  AddToSourceElements(Src,ExpSt);
+  VarsExpSt:=nil;
   for i:=0 to ExportSymbols.Count-1 do
   for i:=0 to ExportSymbols.Count-1 do
     begin
     begin
-    ExpNameJS:=ExpSt.ExportNames.AddElement;
     Symb:=TObject(ExportSymbols[i]) as TPasExportSymbol;
     Symb:=TObject(ExportSymbols[i]) as TPasExportSymbol;
 
 
     // name
     // name
@@ -18067,9 +18151,9 @@ begin
       Decl:=Ref.Declaration;
       Decl:=Ref.Declaration;
       end;
       end;
     NamePath:=CreateReferencePath(Decl,AContext,rpkPathAndName,true);
     NamePath:=CreateReferencePath(Decl,AContext,rpkPathAndName,true);
-    ExpNameJS.Name:=TJSString(NamePath);
 
 
     // alias
     // alias
+    AliasName:='';
     if Symb.ExportName<>nil then
     if Symb.ExportName<>nil then
       begin
       begin
       EvalValue:=aResolver.Eval(Symb.ExportName,[refConst]);
       EvalValue:=aResolver.Eval(Symb.ExportName,[refConst]);
@@ -18078,10 +18162,10 @@ begin
       case EvalValue.Kind of
       case EvalValue.Kind of
       {$ifdef FPC_HAS_CPSTRING}
       {$ifdef FPC_HAS_CPSTRING}
       revkString:
       revkString:
-        ExpNameJS.Alias:=TJSString(TResEvalString(EvalValue).S);
+        AliasName:=TJSString(TResEvalString(EvalValue).S);
       {$endif}
       {$endif}
       revkUnicodeString:
       revkUnicodeString:
-        ExpNameJS.Alias:=TResEvalUTF16(EvalValue).S;
+        AliasName:=TResEvalUTF16(EvalValue).S;
       else
       else
         RaiseNotSupported(Symb.ExportName,AContext,20211020144404);
         RaiseNotSupported(Symb.ExportName,AContext,20211020144404);
       end;
       end;
@@ -18091,11 +18175,78 @@ begin
       begin
       begin
       if Decl.Name='' then
       if Decl.Name='' then
         RaiseNotSupported(Symb,AContext,20211020144730);
         RaiseNotSupported(Symb,AContext,20211020144730);
-      ExpNameJS.Alias:=TJSString(Decl.Name);
+      AliasName:=TJSString(Decl.Name);
+      end;
+
+    if Decl.ClassType=TPasVariable then
+      begin
+      if VarsExpSt=nil then
+        begin
+        // add "export const vars = {};"
+        VarsExpSt:=CreateExportStatement(vtConst,
+                   TJSString(GetBIName(pbivnLibraryVars)),
+                   TJSObjectLiteral(CreateElement(TJSObjectLiteral,Symb)),Symb);
+        AddToSourceElements(Src,VarsExpSt);
+
+        // add "Object.defineProperties(vars, { });"
+        Call:=CreateCallExpression(Symb);
+        AddToSourceElements(Src,Call);
+        Call.Expr:=CreatePrimitiveDotExpr('Object.defineProperties',Symb);
+        Call.AddArg(CreatePrimitiveDotExpr(GetBIName(pbivnLibraryVars),Symb));
+        VarsObjLit:=TJSObjectLiteral(CreateElement(TJSObjectLiteral,Symb));
+        Call.AddArg(VarsObjLit);
+        end;
+      // add "Var1: {},"
+      Lit:=VarsObjLit.Elements.AddElement;
+      Lit.Name:=AliasName;
+      VarObjLit:=TJSObjectLiteral(CreateElement(TJSObjectLiteral,Symb));
+      Lit.Expr:=VarObjLit;
+
+      // enumerable: true
+      SubLit:=VarObjLit.Elements.AddElement;
+      SubLit.Name:='enumerable';
+      SubLit.Expr:=CreateLiteralBoolean(Symb,true);
+
+      //       get: function(){return pas.unit1.Var1;},
+      RetSt:=TJSReturnStatement(CreateElement(TJSReturnStatement,Symb));
+      RetSt.Expr:=CreatePrimitiveDotExpr(NamePath,Symb);
+      AddPropFunction(VarObjLit,'get','',RetSt,Symb);
+
+      //       set: function(v){pas.unit1.Var1 = v;},
+      AssignSt:=TJSSimpleAssignStatement(CreateElement(TJSSimpleAssignStatement,Symb));
+      AssignSt.LHS:=CreatePrimitiveDotExpr(NamePath,Symb);
+      AssignSt.Expr:=CreatePrimitiveDotExpr(TempRefObjSetterArgName,Symb);
+      AddPropFunction(VarObjLit,'set',TJSString(TempRefObjSetterArgName),AssignSt,Symb);
+
+      end
+    else
+      begin
+      // "export const AliasName = NamePath;"
+      ExpSt:=CreateExportStatement(vtConst,AliasName,CreatePrimitiveDotExpr(NamePath,Symb),Symb);
+      AddToSourceElements(Src,ExpSt);
       end;
       end;
     end;
     end;
 end;
 end;
 
 
+function TPasToJSConverter.AddRTLRun(El: TPasModule; ModuleName: string;
+  Src: TJSSourceElements; AContext: TConvertContext): TJSCallExpression;
+var
+  Call: TJSCallExpression;
+begin
+  if AContext=nil then ;
+
+  // add rtl.run('library');
+  Call:=CreateCallExpression(El);
+  AddToSourceElements(Src,Call);
+  Call.Expr:=CreateMemberExpression([GetBIName(pbivnRTL),'run']);
+
+  if ModuleName<>'' then
+    // add module name parameter
+    Call.AddArg(CreateLiteralString(El,ModuleName));
+
+  Result:=Call;
+end;
+
 procedure TPasToJSConverter.AddHeaderStatement(JS: TJSElement;
 procedure TPasToJSConverter.AddHeaderStatement(JS: TJSElement;
   PosEl: TPasElement; aContext: TConvertContext);
   PosEl: TPasElement; aContext: TConvertContext);
 var
 var
@@ -20038,6 +20189,23 @@ begin
   Result:=Call;
   Result:=Call;
 end;
 end;
 
 
+function TPasToJSConverter.CreateExportStatement(VarType: TJSVarType;
+  AliasName: TJSString; InitJS: TJSElement; PosEl: TPasElement
+  ): TJSExportStatement;
+var
+  VarSt: TJSVariableStatement;
+  VarDecl: TJSVarDeclaration;
+begin
+  Result:=TJSExportStatement(CreateElement(TJSExportStatement,PosEl));
+  VarSt:=TJSVariableStatement(CreateElement(TJSVariableStatement,PosEl));
+  Result.Declaration:=VarSt;
+  VarSt.VarType:=VarType;
+  VarDecl:=TJSVarDeclaration(CreateElement(TJSVarDeclaration,PosEl));
+  VarSt.VarDecl:=VarDecl;
+  VarDecl.Name:=AliasName;
+  VarDecl.Init:=InitJS;
+end;
+
 function TPasToJSConverter.CreatePrecompiledJS(El: TJSElement): string;
 function TPasToJSConverter.CreatePrecompiledJS(El: TJSElement): string;
 var
 var
   aWriter: TBufferWriter;
   aWriter: TBufferWriter;

+ 0 - 3
packages/pastojs/src/pas2jscompiler.pp

@@ -2805,9 +2805,6 @@ begin
     FResources.DoneUnit(aFile.isMainFile);
     FResources.DoneUnit(aFile.isMainFile);
     EmitJavaScript(aFile,aFileWriter);
     EmitJavaScript(aFile,aFileWriter);
 
 
-    if aFile.IsMainFile and (TargetPlatform in [PlatformNodeJS,PlatformModule]) then
-      aFileWriter.WriteFile('rtl.run();'+LineEnding,aFile.UnitFilename);
-
     if isSingleFile or aFile.isMainFile then
     if isSingleFile or aFile.isMainFile then
       begin
       begin
       if aFile.IsMainFile  then
       if aFile.IsMainFile  then

+ 2 - 1
packages/pastojs/src/pas2jsfiler.pp

@@ -565,7 +565,8 @@ const
     'NewInst',
     'NewInst',
     'FreeInst',
     'FreeInst',
     'VMT',
     'VMT',
-    'ConstInh'
+    'ConstInh',
+    'UseFields'
     );
     );
 
 
   PCUResolverWithExprScopeFlagNames: array[TPasWithExprScopeFlag] of string = (
   PCUResolverWithExprScopeFlagNames: array[TPasWithExprScopeFlag] of string = (

+ 5 - 5
packages/pastojs/tests/tcconverter.pas

@@ -394,7 +394,7 @@ begin
 
 
   // "var $l=1, $end=100"
   // "var $l=1, $end=100"
   VS:=TJSVariableStatement(AssertElement('For init is var '+LoopEndVar,TJSVariableStatement,ForSt.Init));
   VS:=TJSVariableStatement(AssertElement('For init is var '+LoopEndVar,TJSVariableStatement,ForSt.Init));
-  VDL:=TJSVariableDeclarationList(AssertElement('For init var has comma',TJSVariableDeclarationList,VS.A));
+  VDL:=TJSVariableDeclarationList(AssertElement('For init var has comma',TJSVariableDeclarationList,VS.VarDecl));
   VD:=TJSVarDeclaration(AssertElement('var '+LoopVar,TJSVarDeclaration,VDL.A));
   VD:=TJSVarDeclaration(AssertElement('var '+LoopVar,TJSVarDeclaration,VDL.A));
   AssertEquals('Correct name for '+LoopVar,LoopVar,VD.Name);
   AssertEquals('Correct name for '+LoopVar,LoopVar,VD.Name);
   AssertLiteral('Correct start value',VD.Init,1);
   AssertLiteral('Correct start value',VD.Init,1);
@@ -455,7 +455,7 @@ begin
 
 
   // "var $l=100, $end=1"
   // "var $l=100, $end=1"
   VS:=TJSVariableStatement(AssertElement('For init is var '+LoopEndVar,TJSVariableStatement,ForSt.Init));
   VS:=TJSVariableStatement(AssertElement('For init is var '+LoopEndVar,TJSVariableStatement,ForSt.Init));
-  VDL:=TJSVariableDeclarationList(AssertElement('For init var has comma',TJSVariableDeclarationList,VS.A));
+  VDL:=TJSVariableDeclarationList(AssertElement('For init var has comma',TJSVariableDeclarationList,VS.VarDecl));
   VD:=TJSVarDeclaration(AssertElement('var '+LoopVar,TJSVarDeclaration,VDL.A));
   VD:=TJSVarDeclaration(AssertElement('var '+LoopVar,TJSVarDeclaration,VDL.A));
   AssertEquals('Correct name for '+LoopVar,LoopVar,VD.Name);
   AssertEquals('Correct name for '+LoopVar,LoopVar,VD.Name);
   AssertLiteral('Correct start value',VD.Init,100);
   AssertLiteral('Correct start value',VD.Init,100);
@@ -704,7 +704,7 @@ begin
   L:=AssertListStatement('On block is always a list',I.BTrue);
   L:=AssertListStatement('On block is always a list',I.BTrue);
   writeln('TTestStatementConverter.TestTryExceptStatementOnE ',L.A.ClassName);
   writeln('TTestStatementConverter.TestTryExceptStatementOnE ',L.A.ClassName);
   VS:=TJSVariableStatement(AssertElement('First statement in list is a var statement',TJSVariableStatement,L.A));
   VS:=TJSVariableStatement(AssertElement('First statement in list is a var statement',TJSVariableStatement,L.A));
-  V:=TJSVarDeclaration(AssertElement('var declaration e=ExceptObject',TJSVarDeclaration,VS.A));
+  V:=TJSVarDeclaration(AssertElement('var declaration e=ExceptObject',TJSVarDeclaration,VS.VarDecl));
   AssertEquals('Variable name is identifier in On A : Ex do','e',V.Name);
   AssertEquals('Variable name is identifier in On A : Ex do','e',V.Name);
   Assertidentifier('Variable init is exception object',V.Init,ExceptObjName);
   Assertidentifier('Variable init is exception object',V.Init,ExceptObjName);
   // check "b = c;"
   // check "b = c;"
@@ -765,7 +765,7 @@ begin
   L:=AssertListStatement('On block is always a list',I.BTrue);
   L:=AssertListStatement('On block is always a list',I.BTrue);
   writeln('TTestStatementConverter.TestTryExceptStatementOnE ',L.A.ClassName);
   writeln('TTestStatementConverter.TestTryExceptStatementOnE ',L.A.ClassName);
   VS:=TJSVariableStatement(AssertElement('First statement in list is a var statement',TJSVariableStatement,L.A));
   VS:=TJSVariableStatement(AssertElement('First statement in list is a var statement',TJSVariableStatement,L.A));
-  V:=TJSVarDeclaration(AssertElement('var declaration e=ExceptObject',TJSVarDeclaration,VS.A));
+  V:=TJSVarDeclaration(AssertElement('var declaration e=ExceptObject',TJSVarDeclaration,VS.VarDecl));
   AssertEquals('Variable name is identifier in On A : Ex do','e',V.Name);
   AssertEquals('Variable name is identifier in On A : Ex do','e',V.Name);
   Assertidentifier('Variable init is exception object',V.Init,ExceptObjName);
   Assertidentifier('Variable init is exception object',V.Init,ExceptObjName);
   R:=TJSThrowStatement(AssertElement('On block is throw statement',TJSThrowStatement,L.B));
   R:=TJSThrowStatement(AssertElement('On block is throw statement',TJSThrowStatement,L.B));
@@ -787,7 +787,7 @@ begin
   S.Variables.Add(V);
   S.Variables.Add(V);
   L:=TJSStatementList(Convert(S,TJSStatementList));
   L:=TJSStatementList(Convert(S,TJSStatementList));
   JV:=TJSVariableStatement(AssertElement('Variable statement',TJSVariableStatement,L.A));
   JV:=TJSVariableStatement(AssertElement('Variable statement',TJSVariableStatement,L.A));
-  JVD:=TJSVarDeclaration(AssertElement('Variable declaration',TJSVarDeclaration,JV.A));
+  JVD:=TJSVarDeclaration(AssertElement('Variable declaration',TJSVarDeclaration,JV.VarDecl));
   AssertEquals('Correct variable name','a',JVD.Name);
   AssertEquals('Correct variable name','a',JVD.Name);
 end;
 end;
 
 

+ 6 - 6
packages/pastojs/tests/tcfiler.pas

@@ -370,7 +370,7 @@ begin
   FInitialFlags:=TPCUInitialFlags.Create;
   FInitialFlags:=TPCUInitialFlags.Create;
   FAnalyzer:=TPas2JSAnalyzer.Create;
   FAnalyzer:=TPas2JSAnalyzer.Create;
   FCheckedElements:=TPasAnalyzerKeySet.Create(@CompareCheckedElementPairs,@CompareElWithCheckedElementPair);
   FCheckedElements:=TPasAnalyzerKeySet.Create(@CompareCheckedElementPairs,@CompareElWithCheckedElementPair);
-  Analyzer.Resolver:=Engine;
+  Analyzer.Resolver:=ResolverEngine;
   Analyzer.Options:=Analyzer.Options+[paoImplReferences];
   Analyzer.Options:=Analyzer.Options+[paoImplReferences];
   Converter.OnIsElementUsed:=@OnConverterIsElementUsed;
   Converter.OnIsElementUsed:=@OnConverterIsElementUsed;
   Converter.OnIsTypeInfoUsed:=@OnConverterIsTypeInfoUsed;
   Converter.OnIsTypeInfoUsed:=@OnConverterIsTypeInfoUsed;
@@ -433,7 +433,7 @@ begin
     try
     try
       PCUWriter.OnGetSrc:=@OnFilerGetSrc;
       PCUWriter.OnGetSrc:=@OnFilerGetSrc;
       PCUWriter.OnIsElementUsed:=@OnConverterIsElementUsed;
       PCUWriter.OnIsElementUsed:=@OnConverterIsElementUsed;
-      PCUWriter.WritePCU(Engine,Converter,InitialFlags,ms,false);
+      PCUWriter.WritePCU(ResolverEngine,Converter,InitialFlags,ms,false);
     except
     except
       on E: Exception do
       on E: Exception do
       begin
       begin
@@ -457,7 +457,7 @@ begin
       RestScanner:=TPas2jsPasScanner.Create(RestFileResolver);
       RestScanner:=TPas2jsPasScanner.Create(RestFileResolver);
       InitScanner(RestScanner);
       InitScanner(RestScanner);
       RestResolver:=TTestEnginePasResolver.Create;
       RestResolver:=TTestEnginePasResolver.Create;
-      RestResolver.Filename:=Engine.Filename;
+      RestResolver.Filename:=ResolverEngine.Filename;
       RestResolver.AddObjFPCBuiltInIdentifiers(btAllJSBaseTypes,bfAllJSBaseProcs);
       RestResolver.AddObjFPCBuiltInIdentifiers(btAllJSBaseTypes,bfAllJSBaseProcs);
       RestResolver.OnFindUnit:=@OnRestResolverFindUnit;
       RestResolver.OnFindUnit:=@OnRestResolverFindUnit;
       RestParser:=TPasParser.Create(RestScanner,RestFileResolver,RestResolver);
       RestParser:=TPasParser.Create(RestScanner,RestFileResolver,RestResolver);
@@ -493,7 +493,7 @@ begin
       end;
       end;
     end;
     end;
     // check parser+resolver+analyzer
     // check parser+resolver+analyzer
-    CheckRestoredResolver(Engine,RestResolver,[]);
+    CheckRestoredResolver(ResolverEngine,RestResolver,[]);
 
 
     // convert using the precompiled procs
     // convert using the precompiled procs
     RestConverter:=CreateConverter;
     RestConverter:=CreateConverter;
@@ -1059,7 +1059,7 @@ begin
     if Orig.ModeSwitches<>Rest.ModeSwitches then
     if Orig.ModeSwitches<>Rest.ModeSwitches then
       Fail(Path+'.ModeSwitches');
       Fail(Path+'.ModeSwitches');
 
 
-    if Engine.ProcCanBePrecompiled(DeclProc) then
+    if ResolverEngine.ProcCanBePrecompiled(DeclProc) then
       begin
       begin
       CheckRestoredScopeRefs(Path+'.References',Orig.References,Rest.References,Flags);
       CheckRestoredScopeRefs(Path+'.References',Orig.References,Rest.References,Flags);
       end;
       end;
@@ -2041,7 +2041,7 @@ begin
   // Body
   // Body
   if Orig.Body<>nil then
   if Orig.Body<>nil then
     begin
     begin
-    if not Engine.ProcCanBePrecompiled(DeclProc) then
+    if not ResolverEngine.ProcCanBePrecompiled(DeclProc) then
       begin
       begin
       // generic body
       // generic body
       if OrigScope.ImplJS<>nil then
       if OrigScope.ImplJS<>nil then

+ 131 - 7
packages/pastojs/tests/tcgenerics.pas

@@ -27,13 +27,13 @@ type
     Procedure TestGen_ClassEmpty;
     Procedure TestGen_ClassEmpty;
     Procedure TestGen_Class_EmptyMethod;
     Procedure TestGen_Class_EmptyMethod;
     Procedure TestGen_Class_TList;
     Procedure TestGen_Class_TList;
-    Procedure TestGen_Class_TCustomList; // ToDo: with Self do Result:=Method()
+    Procedure TestGen_Class_TCustomList;
     Procedure TestGen_ClassAncestor;
     Procedure TestGen_ClassAncestor;
     Procedure TestGen_Class_TypeInfo;
     Procedure TestGen_Class_TypeInfo;
-    Procedure TestGen_Class_TypeOverload; // ToDo TBird, TBird<T>, TBird<S,T>
+    Procedure TestGen_Class_TypeOverload;
     Procedure TestGen_Class_ClassProperty;
     Procedure TestGen_Class_ClassProperty;
     Procedure TestGen_Class_ClassProc;
     Procedure TestGen_Class_ClassProc;
-    //Procedure TestGen_Record_ReferGenClass_DelphiFail; TBird<T> = class x:TBird; end;
+    Procedure TestGen_Class_ReferGenClass_DelphiFail;
     Procedure TestGen_Class_ClassConstructor;
     Procedure TestGen_Class_ClassConstructor;
     Procedure TestGen_Class_TypeCastSpecializesWarn;
     Procedure TestGen_Class_TypeCastSpecializesWarn;
     Procedure TestGen_Class_TypeCastSpecializesJSValueNoWarn;
     Procedure TestGen_Class_TypeCastSpecializesJSValueNoWarn;
@@ -77,11 +77,11 @@ type
     procedure TestGenProc_Infer_Widen;
     procedure TestGenProc_Infer_Widen;
     procedure TestGenProc_Infer_PassAsArg;
     procedure TestGenProc_Infer_PassAsArg;
     procedure TestGenProc_AnonymousProc;
     procedure TestGenProc_AnonymousProc;
-    // ToDo: FuncName:= instead of Result:=
 
 
     // generic methods
     // generic methods
     procedure TestGenMethod_ImplicitSpec_ObjFPC;
     procedure TestGenMethod_ImplicitSpec_ObjFPC;
     procedure TestGenMethod_Delphi;
     procedure TestGenMethod_Delphi;
+    procedure TestGenMethod_Overload_Delphi;
 
 
     // generic array
     // generic array
     procedure TestGen_Array_OtherUnit;
     procedure TestGen_Array_OtherUnit;
@@ -92,6 +92,8 @@ type
     procedure TestGen_ProcType_ProcLocal;
     procedure TestGen_ProcType_ProcLocal;
     procedure TestGen_ProcType_Local_RTTI_Fail;
     procedure TestGen_ProcType_Local_RTTI_Fail;
     procedure TestGen_ProcType_ParamUnitImpl;
     procedure TestGen_ProcType_ParamUnitImpl;
+    // procedure TestGen_ProcType_TemplateCountOverload_ObjFPC; ObjFPC does not support that in FPC
+    procedure TestGen_ProcType_TemplateCountOverload_Delphi;
   end;
   end;
 
 
 implementation
 implementation
@@ -574,7 +576,7 @@ begin
   'begin',
   'begin',
   '  Result:=PrepareAddingItem;',
   '  Result:=PrepareAddingItem;',
   '  Result:=Self.PrepareAddingItem;',
   '  Result:=Self.PrepareAddingItem;',
-  //'  with Self do Result:=PrepareAddingItem;',
+  '  with Self do Result:=PrepareAddingItem;',
   'end;',
   'end;',
   'var l: TWordList;',
   'var l: TWordList;',
   'begin',
   'begin',
@@ -599,6 +601,7 @@ begin
     '    var Result = 0;',
     '    var Result = 0;',
     '    Result = this.PrepareAddingItem();',
     '    Result = this.PrepareAddingItem();',
     '    Result = this.PrepareAddingItem();',
     '    Result = this.PrepareAddingItem();',
+    '    Result = this.PrepareAddingItem();',
     '    return Result;',
     '    return Result;',
     '  };',
     '  };',
     '}, "TList<System.Word>");',
     '}, "TList<System.Word>");',
@@ -688,8 +691,6 @@ end;
 
 
 procedure TTestGenerics.TestGen_Class_TypeOverload;
 procedure TTestGenerics.TestGen_Class_TypeOverload;
 begin
 begin
-  exit;// ToDo
-
   StartProgram(false);
   StartProgram(false);
   Add([
   Add([
   '{$mode delphi}',
   '{$mode delphi}',
@@ -714,6 +715,14 @@ begin
     '  this.$final = function () {',
     '  this.$final = function () {',
     '  };',
     '  };',
     '});',
     '});',
+    'rtl.createClass(this, "TBird$G1", this.TObject, function () {',
+    '  this.$init = function () {',
+    '    $mod.TObject.$init.call(this);',
+    '    this.m = 0;',
+    '  };',
+    '}, "TBird<System.Word>");',
+    'this.b = null;',
+    'this.e = null;',
     '']),
     '']),
     LinesToStr([ // $mod.$main
     LinesToStr([ // $mod.$main
     '']));
     '']));
@@ -820,6 +829,24 @@ begin
     '']));
     '']));
 end;
 end;
 
 
+procedure TTestGenerics.TestGen_Class_ReferGenClass_DelphiFail;
+begin
+  StartProgram(false);
+  Add([
+  '{$mode delphi}',
+  'type',
+  '  TObject = class end;',
+  '  TPoint<T> = class',
+  '    var x: TPoint;', // alowed in objfpc, forbidden in delphi
+  '  end;',
+  'var p: specialize TPoint<word>;',
+  'begin',
+  '']);
+  SetExpectedPasResolverError('Generics without specialization cannot be used as a type for a variable',
+     nGenericsWithoutSpecializationAsType);
+  ConvertProgram;
+end;
+
 procedure TTestGenerics.TestGen_Class_ClassConstructor;
 procedure TTestGenerics.TestGen_Class_ClassConstructor;
 begin
 begin
   StartProgram(false);
   StartProgram(false);
@@ -2501,6 +2528,59 @@ begin
     '']));
     '']));
 end;
 end;
 
 
+procedure TTestGenerics.TestGenMethod_Overload_Delphi;
+begin
+  StartProgram(false);
+  Add([
+  '{$mode delphi}',
+  'type',
+  '  TObject = class',
+  '    procedure Run<S>; overload;',
+  '    procedure Run<T>(w: word); overload;',
+  '  end; ',
+  'procedure TObject.Run<S>;',
+  'begin',
+  'end;',
+  'procedure TObject.Run<T>(w: word);',
+  'begin',
+  'end;',
+  'var o: TObject;',
+  'begin',
+  '  o.Run<word>;',
+  '  o.Run<word>();',
+  '  o.Run<longint>(3);',
+  '  with o do begin',
+  '    Run<word>;',
+  '    Run<word>();',
+  '    Run<longint>(13);',
+  '  end;',
+  '']);
+  ConvertProgram;
+  CheckSource('TestGenMethod_Overload_Delphi',
+    LinesToStr([ // statements
+    'rtl.createClass(this, "TObject", null, function () {',
+    '  this.$init = function () {',
+    '  };',
+    '  this.$final = function () {',
+    '  };',
+    '  this.Run$G1 = function () {',
+    '  };',
+    '  this.Run$1G1 = function (w) {',
+    '  };',
+    '});',
+    'this.o = null;',
+    '']),
+    LinesToStr([ // $mod.$main
+    '$mod.o.Run$G1();',
+    '$mod.o.Run$G1();',
+    '$mod.o.Run$1G1(3);',
+    'var $with = $mod.o;',
+    '$with.Run$G1();',
+    '$with.Run$G1();',
+    '$with.Run$1G1(13);',
+    '']));
+end;
+
 procedure TTestGenerics.TestGen_Array_OtherUnit;
 procedure TTestGenerics.TestGen_Array_OtherUnit;
 begin
 begin
   WithTypeInfo:=true;
   WithTypeInfo:=true;
@@ -2812,6 +2892,50 @@ begin
     '']));
     '']));
 end;
 end;
 
 
+procedure TTestGenerics.TestGen_ProcType_TemplateCountOverload_Delphi;
+begin
+  WithTypeInfo:=true;
+  StartProgram(false);
+  Add([
+  '{$mode delphi}',
+  'type',
+  '  TProc<T> = procedure(a, b: T);',
+  '  TProc<S,T> = procedure(a: S; b: T);',
+  'var',
+  '  p: TProc<word>;',
+  '  q: TProc<char,boolean>;',
+  'procedure Run(x,y: word);',
+  'begin',
+  'end;',
+  'procedure Fly(x: char; y: boolean);',
+  'begin',
+  'end;',
+  'begin',
+  '  p:=Run;',
+  '  q:=Fly;',
+  'end.']);
+  ConvertProgram;
+  CheckSource('TestGen_ProcType_TemplateCountOverload_Delphi',
+    LinesToStr([ // statements
+    'this.$rtti.$ProcVar("TProc<System.Word>", {',
+    '  procsig: rtl.newTIProcSig([["a", rtl.word], ["b", rtl.word]])',
+    '});',
+    'this.p = null;',
+    'this.$rtti.$ProcVar("TProc<System.Char,System.Boolean>", {',
+    '  procsig: rtl.newTIProcSig([["a", rtl.char], ["b", rtl.boolean]])',
+    '});',
+    'this.q = null;',
+    'this.Run = function (x, y) {',
+    '};',
+    'this.Fly = function (x, y) {',
+    '};',
+    '']),
+    LinesToStr([ // $mod.$main
+    '$mod.p = $mod.Run;',
+    '$mod.q = $mod.Fly;',
+    '']));
+end;
+
 Initialization
 Initialization
   RegisterTests([TTestGenerics]);
   RegisterTests([TTestGenerics]);
 end.
 end.

File diff suppressed because it is too large
+ 695 - 69
packages/pastojs/tests/tcmodules.pas


+ 2 - 2
packages/pastojs/tests/tcoptimizations.pas

@@ -160,9 +160,9 @@ begin
   inherited SetUp;
   inherited SetUp;
   FWholeProgramOptimization:=false;
   FWholeProgramOptimization:=false;
   FAnalyzerModule:=TPas2JSAnalyzer.Create;
   FAnalyzerModule:=TPas2JSAnalyzer.Create;
-  FAnalyzerModule.Resolver:=Engine;
+  FAnalyzerModule.Resolver:=ResolverEngine;
   FAnalyzerProgram:=TPas2JSAnalyzer.Create;
   FAnalyzerProgram:=TPas2JSAnalyzer.Create;
-  FAnalyzerProgram.Resolver:=Engine;
+  FAnalyzerProgram.Resolver:=ResolverEngine;
 end;
 end;
 
 
 procedure TCustomTestOptimizations.TearDown;
 procedure TCustomTestOptimizations.TearDown;

+ 504 - 0
packages/pastojs/tests/tcpas2jsanalyzer.pas

@@ -0,0 +1,504 @@
+unit TCPas2JSAnalyzer;
+
+{$mode ObjFPC}{$H+}
+
+interface
+
+uses
+  Classes, SysUtils, fpcunit, testregistry, StrUtils, TCModules, PasTree,
+  PScanner, PasResolver, PasUseAnalyzer, PasResolveEval, Pas2jsUseAnalyzer;
+
+type
+
+  { TCustomTestPas2jsAnalyzer }
+
+  TCustomTestPas2jsAnalyzer = class(TCustomTestModule)
+  private
+    FAnalyzer: TPas2JSAnalyzer;
+    FPAMessages: TFPList; // list of TPAMessage
+    FPAGoodMessages: TFPList;
+    FProcAnalyzer: TPas2JSAnalyzer;
+    function GetPAMessages(Index: integer): TPAMessage;
+    procedure OnAnalyzerMessage(Sender: TObject; Msg: TPAMessage);
+  protected
+    procedure SetUp; override;
+    procedure TearDown; override;
+    procedure ParseModule; override;
+    procedure AnalyzeModule; virtual;
+    procedure AnalyzeProgram; virtual;
+    procedure AnalyzeUnit; virtual;
+    procedure AnalyzeWholeProgram; virtual;
+    procedure CheckUsedMarkers; virtual;
+    procedure CheckUseAnalyzerHint(MsgType: TMessageType; MsgNumber: integer;
+      const MsgText: string); virtual;
+    procedure CheckUseAnalyzerUnexpectedHints; virtual;
+    procedure CheckUnitUsed(const aFilename: string; Used: boolean); virtual;
+    procedure CheckScopeReferences(const ScopeName: string;
+      const RefNames: array of string);
+  public
+    property Analyzer: TPas2JSAnalyzer read FAnalyzer;
+    property ProcAnalyzer: TPas2JSAnalyzer read FProcAnalyzer;
+    function PAMessageCount: integer;
+    property PAMessages[Index: integer]: TPAMessage read GetPAMessages;
+  end;
+
+  { TTestPas2jsAnalyzer }
+
+  TTestPas2jsAnalyzer = class(TCustomTestPas2jsAnalyzer)
+  Published
+    procedure TestM_ProgramLocalVar;
+    procedure TestM_PassRecordToJSValue;
+  end;
+
+
+implementation
+
+{ TTestPas2jsAnalyzer }
+
+procedure TTestPas2jsAnalyzer.TestM_ProgramLocalVar;
+begin
+  StartProgram(false);
+  Add([
+  'procedure {#DoIt_used}DoIt;',
+  'var {#l_notused}l: longint;',
+  'begin',
+  'end;',
+  'begin',
+  '  DoIt;',
+  'end.']);
+  AnalyzeProgram;
+end;
+
+procedure TTestPas2jsAnalyzer.TestM_PassRecordToJSValue;
+begin
+  StartProgram(false);
+  Add([
+  'type',
+  '  {#trec_used}TRec = record',
+  '    {#x_used}x: word;',
+  '  end;',
+  '  {#tbig_used}TBig = record',
+  '    {#r_used}r: TRec;',
+  '  end;',
+  '  {#tnope_used}TNope = record',
+  '    {#a_notused}a: word;',
+  '    {#b_used}b: word;',
+  '  end;',
+  'procedure DoIt(v: JSValue);',
+  'begin',
+  'end;',
+  'var big: TBig;',
+  '  n: TNope;',
+  'begin',
+  '  DoIt(big);',
+  '  DoIt(n.b);',
+  'end.']);
+  AnalyzeProgram;
+end;
+
+{ TCustomTestPas2jsAnalyzer }
+
+function TCustomTestPas2jsAnalyzer.GetPAMessages(Index: integer): TPAMessage;
+begin
+  Result:=TPAMessage(FPAMessages[Index]);
+end;
+
+procedure TCustomTestPas2jsAnalyzer.OnAnalyzerMessage(Sender: TObject;
+  Msg: TPAMessage);
+begin
+  Msg.AddRef;
+  FPAMessages.Add(Msg);
+end;
+
+procedure TCustomTestPas2jsAnalyzer.SetUp;
+begin
+  inherited SetUp;
+  FPAMessages:=TFPList.Create;
+  FPAGoodMessages:=TFPList.Create;
+  FAnalyzer:=TPas2JSAnalyzer.Create;
+  FAnalyzer.Resolver:=ResolverEngine;
+  Analyzer.OnMessage:=@OnAnalyzerMessage;
+end;
+
+procedure TCustomTestPas2jsAnalyzer.TearDown;
+var
+  i: Integer;
+begin
+  FreeAndNil(FPAGoodMessages);
+  for i:=0 to FPAMessages.Count-1 do
+    TPAMessage(FPAMessages[i]).Release;
+  FreeAndNil(FPAMessages);
+  FreeAndNil(FAnalyzer);
+  FreeAndNil(FProcAnalyzer);
+  inherited TearDown;
+end;
+
+procedure TCustomTestPas2jsAnalyzer.ParseModule;
+begin
+  inherited ParseModule;
+  if SkipTests then exit;
+  CheckReferenceDirectives;
+end;
+
+procedure TCustomTestPas2jsAnalyzer.AnalyzeModule;
+begin
+  Analyzer.AnalyzeModule(Module);
+  Analyzer.EmitModuleHints(Module);
+  CheckUsedMarkers;
+end;
+
+procedure TCustomTestPas2jsAnalyzer.AnalyzeProgram;
+begin
+  ParseProgram;
+  AnalyzeModule;
+end;
+
+procedure TCustomTestPas2jsAnalyzer.AnalyzeUnit;
+begin
+  ParseUnit;
+  AnalyzeModule;
+end;
+
+procedure TCustomTestPas2jsAnalyzer.AnalyzeWholeProgram;
+begin
+  ParseProgram;
+  Analyzer.AnalyzeWholeProgram(Module as TPasProgram);
+  CheckUsedMarkers;
+end;
+
+procedure TCustomTestPas2jsAnalyzer.CheckUsedMarkers;
+type
+  TUsed = (
+    uUsed,
+    uNotUsed,
+    uTypeInfo,
+    uNoTypeinfo
+    );
+var
+  aMarker: PSrcMarker;
+  p: SizeInt;
+  Postfix: String;
+  Elements: TFPList;
+  i: Integer;
+  El, FoundEl: TPasElement;
+  ExpectedUsed: TUsed;
+begin
+  aMarker:=FirstSrcMarker;
+  while aMarker<>nil do
+    begin
+    {$IFDEF VerbosePasAnalyzer}
+    writeln('TCustomTestPas2jsAnalyzer.CheckUsedMarkers ',aMarker^.Identifier,' Line=',aMarker^.Row,' StartCol=',aMarker^.StartCol,' EndCol=',aMarker^.EndCol);
+    {$ENDIF}
+    p:=RPos('_',aMarker^.Identifier);
+    if p>1 then
+      begin
+      Postfix:=copy(aMarker^.Identifier,p+1);
+
+      if Postfix='used' then
+        ExpectedUsed:=uUsed
+      else if Postfix='notused' then
+        ExpectedUsed:=uNotUsed
+      else if Postfix='typeinfo' then
+        ExpectedUsed:=uTypeInfo
+      else if Postfix='notypeinfo' then
+        ExpectedUsed:=uNoTypeInfo
+      else
+        RaiseErrorAtSrcMarker('TCustomTestPas2jsAnalyzer.CheckUsedMarkers unknown postfix "'+Postfix+'"',aMarker);
+
+      Elements:=FindElementsAt(aMarker);
+      try
+        FoundEl:=nil;
+        for i:=0 to Elements.Count-1 do
+          begin
+          El:=TPasElement(Elements[i]);
+          {$IFDEF VerbosePasAnalyzer}
+          writeln('TCustomTestPas2jsAnalyzer.CheckUsedMarkers ',aMarker^.Identifier,' ',i,'/',Elements.Count,' El=',GetObjName(El),' ',GetObjName(El.CustomData));
+          {$ENDIF}
+          case ExpectedUsed of
+          uUsed,uNotUsed:
+            if Analyzer.IsUsed(El) then
+              begin
+              FoundEl:=El;
+              break;
+              end;
+          uTypeInfo,uNoTypeinfo:
+            if Analyzer.IsTypeInfoUsed(El) then
+              begin
+              FoundEl:=El;
+              break;
+              end;
+          end;
+          end;
+        if FoundEl<>nil then
+          case ExpectedUsed of
+          uNotUsed:
+            RaiseErrorAtSrcMarker('expected element to be *not* used, but it is marked',aMarker);
+          uNoTypeinfo:
+            RaiseErrorAtSrcMarker('expected element to have *no* typeinfo, but it is marked',aMarker);
+          end
+        else
+          case ExpectedUsed of
+          uUsed:
+            RaiseErrorAtSrcMarker('expected element to be used, but it is not marked',aMarker);
+          uTypeInfo:
+            RaiseErrorAtSrcMarker('expected element to have typeinfo, but it is not marked',aMarker);
+          end;
+      finally
+        Elements.Free;
+      end;
+      end;
+    aMarker:=aMarker^.Next;
+    end;
+end;
+
+procedure TCustomTestPas2jsAnalyzer.CheckUseAnalyzerHint(MsgType: TMessageType;
+  MsgNumber: integer; const MsgText: string);
+var
+  i: Integer;
+  Msg: TPAMessage;
+  s: string;
+begin
+  i:=PAMessageCount-1;
+  while i>=0 do
+    begin
+    Msg:=PAMessages[i];
+    if (Msg.MsgNumber=MsgNumber) then
+      begin
+      if (Msg.MsgType=MsgType) and (Msg.MsgText=MsgText) then
+        begin
+        FPAGoodMessages.Add(Msg);
+        exit;
+        end;
+      end;
+    dec(i);
+    end;
+  // mismatch
+  writeln('TCustomTestPas2jsAnalyzer.CheckHasHint: ');
+  for i:=0 to PAMessageCount-1 do
+    begin
+    Msg:=PAMessages[i];
+    writeln('  ',i,'/',PAMessageCount,': [',Msg.Id,'] ',Msg.MsgType,': (',Msg.MsgNumber,') {',Msg.MsgText,'}');
+    end;
+  s:='';
+  str(MsgType,s);
+  Fail('Analyzer Message not found: '+s+': ('+IntToStr(MsgNumber)+') {'+MsgText+'}');
+end;
+
+procedure TCustomTestPas2jsAnalyzer.CheckUseAnalyzerUnexpectedHints;
+var
+  i: Integer;
+  Msg: TPAMessage;
+  s: String;
+begin
+  for i:=0 to PAMessageCount-1 do
+    begin
+    Msg:=PAMessages[i];
+    if FPAGoodMessages.IndexOf(Msg)>=0 then continue;
+    s:='';
+    str(Msg.MsgType,s);
+    Fail('Unexpected analyzer message found ['+IntToStr(Msg.Id)+'] '+s+': ('+IntToStr(Msg.MsgNumber)+') {'+Msg.MsgText+'}');
+    end;
+end;
+
+procedure TCustomTestPas2jsAnalyzer.CheckUnitUsed(const aFilename: string;
+  Used: boolean);
+var
+  aResolver: TTestEnginePasResolver;
+  PAEl: TPAElement;
+begin
+  aResolver:=FindModuleWithFilename(aFilename);
+  AssertNotNull('unit not found "'+aFilename+'"',aResolver);
+  AssertNotNull('unit module not found "'+aFilename+'"',aResolver.Module);
+  PAEl:=Analyzer.FindElement(aResolver.Module);
+  if PAEl<>nil then
+    begin
+    // unit is used
+    if not Used then
+      Fail('expected unit "'+aFilename+'" not used, but it is used');
+    end
+  else
+    begin
+    // unit is not used
+    if Used then
+      Fail('expected unit "'+aFilename+'" used, but it is not used');
+    end;
+end;
+
+procedure TCustomTestPas2jsAnalyzer.CheckScopeReferences(
+  const ScopeName: string; const RefNames: array of string);
+type
+  TEntry = record
+    Name: string;
+    Access: TPSRefAccess;
+  end;
+
+var
+  Entries: array of TEntry;
+
+  procedure CheckRefs(ScopeRefs: TPasScopeReferences; const Prefix: string);
+
+    procedure DumpRefsAndFail(Refs: TFPList; const Msg: string);
+    var
+      i: Integer;
+      Ref: TPasScopeReference;
+    begin
+      {$IFDEF VerbosePasAnalyzer}
+      if Refs.Count=0 then
+        writeln('DumpRefsAndFail ',Prefix,' NO REFS');
+      {$ENDIF}
+      for i:=0 to Refs.Count-1 do
+        begin
+        Ref:=TPasScopeReference(Refs[i]);
+        if Ref=nil then break;
+        {$IFDEF VerbosePasAnalyzer}
+        writeln('DumpRefsAndFail ',Prefix,' ',i,' ',GetObjName(Ref.Element),' ',Ref.Access);
+        {$ENDIF}
+        end;
+      Fail(Prefix+': '+Msg);
+    end;
+
+  var
+    Refs: TFPList;
+    j, i: Integer;
+    o: TObject;
+    Ref: TPasScopeReference;
+  begin
+    if ScopeRefs=nil then
+      Refs:=TFPList.Create
+    else
+      Refs:=ScopeRefs.GetList;
+    try
+      // check that Refs only contains TPasProcScopeReference
+      for i:=0 to Refs.Count-1 do
+        begin
+        o:=TObject(Refs[i]);
+        if not (o is TPasScopeReference) then
+          Fail(Prefix+': Refs['+IntToStr(i)+'] '+GetObjName(o));
+        end;
+      // check that all Entries are referenced
+      for i:=0 to length(Entries)-1 do
+        begin
+        j:=Refs.Count-1;
+        while (j>=0)
+            and (CompareText(Entries[i].Name,TPasScopeReference(Refs[j]).Element.Name)<>0) do
+          dec(j);
+        if j<0 then
+          DumpRefsAndFail(Refs,'Missing reference "'+Entries[i].Name+'"');
+        Ref:=TPasScopeReference(Refs[j]);
+        if (Entries[i].Access<>psraNone) and (Ref.Access<>Entries[i].Access) then
+          DumpRefsAndFail(Refs,'Wrong reference access "'+Entries[i].Name+'",'
+            +' expected '+dbgs(Entries[i].Access)+', but got '+dbgs(Ref.Access));
+        end;
+      // check that no other references are in Refs
+      for i:=0 to Refs.Count-1 do
+        begin
+        Ref:=TPasScopeReference(Refs[i]);
+        j:=length(Entries)-1;
+        while (j>=0)
+            and (CompareText(Ref.Element.Name,Entries[j].Name)<>0) do
+          dec(j);
+        if j<0 then
+          DumpRefsAndFail(Refs,'Unneeded reference "'+GetObjName(Ref.Element)+'"');
+        end;
+    finally
+      Refs.Free;
+    end;
+  end;
+
+  function FindProc(Section: TPasSection): boolean;
+  var
+    i: Integer;
+    El: TPasElement;
+    Proc: TPasProcedure;
+    Scope: TPasProcedureScope;
+  begin
+    for i:=0 to Section.Declarations.Count-1 do
+      begin
+      El:=TPasElement(Section.Declarations[i]);
+      if CompareText(El.Name,ScopeName)<>0 then continue;
+      if not (El is TPasProcedure) then
+        Fail('El is not proc '+GetObjName(El));
+      Proc:=TPasProcedure(El);
+      Scope:=Proc.CustomData as TPasProcedureScope;
+      if Scope.DeclarationProc<>nil then continue;
+
+      // check references created by AnalyzeModule
+      CheckRefs(Scope.References,'AnalyzeModule');
+
+      exit(true);
+      end;
+    Result:=false;
+  end;
+
+  procedure CheckInitialFinalization(El: TPasImplBlock);
+  var
+    Scope: TPasInitialFinalizationScope;
+  begin
+    Scope:=El.CustomData as TPasInitialFinalizationScope;
+    CheckRefs(Scope.References,'AnalyzeModule');
+  end;
+
+var
+  i: Integer;
+begin
+  Entries:=nil;
+  SetLength(Entries,High(RefNames)-low(RefNames)+1);
+  for i:=low(RefNames) to high(RefNames) do
+    begin
+    Entries[i].Name:=RefNames[i];
+    Entries[i].Access:=psraNone;
+    end;
+
+  if Module is TPasProgram then
+    begin
+    if CompareText(ScopeName,'begin')=0 then
+      begin
+      // check begin-block references created by AnalyzeModule
+      CheckInitialFinalization(Module.InitializationSection);
+      exit;
+      end
+    else if FindProc(TPasProgram(Module).ProgramSection) then
+      exit;
+    end
+  else if Module is TPasLibrary then
+    begin
+    if CompareText(ScopeName,'begin')=0 then
+      begin
+      // check begin-block references created by AnalyzeModule
+      CheckInitialFinalization(Module.InitializationSection);
+      exit;
+      end
+    else if FindProc(TPasLibrary(Module).LibrarySection) then
+      exit;
+    end
+  else if Module.ClassType=TPasModule then
+    begin
+    if CompareText(ScopeName,'initialization')=0 then
+      begin
+      // check initialization references created by AnalyzeModule
+      CheckInitialFinalization(Module.InitializationSection);
+      exit;
+      end
+    else if CompareText(ScopeName,'finalization')=0 then
+      begin
+      // check finalization references created by AnalyzeModule
+      CheckInitialFinalization(Module.FinalizationSection);
+      exit;
+      end
+    else if FindProc(Module.InterfaceSection) then
+      exit
+    else if FindProc(Module.ImplementationSection) then
+      exit;
+    end;
+  Fail('missing proc '+ScopeName);
+end;
+
+function TCustomTestPas2jsAnalyzer.PAMessageCount: integer;
+begin
+  Result:=FPAMessages.Count;
+end;
+
+Initialization
+  RegisterTests([TTestPas2jsAnalyzer]);
+end.
+

+ 1 - 1
packages/pastojs/tests/tcsrcmap.pas

@@ -180,7 +180,7 @@ begin
   // collect markers in Pascal
   // collect markers in Pascal
   PasSrc:=TStringList.Create;
   PasSrc:=TStringList.Create;
   try
   try
-    PasSrc.Text:=Engine.Source;
+    PasSrc.Text:=ResolverEngine.Source;
     for i:=1 to PasSrc.Count do
     for i:=1 to PasSrc.Count do
       begin
       begin
       Line:=PasSrc[i-1];
       Line:=PasSrc[i-1];

+ 34 - 0
packages/pastojs/tests/tcunitsearch.pas

@@ -137,6 +137,7 @@ type
   TTestCLI_UnitSearch = class(TCustomTestCLI)
   TTestCLI_UnitSearch = class(TCustomTestCLI)
   protected
   protected
     procedure CheckLinklibProgramSrc(Msg,Header: string);
     procedure CheckLinklibProgramSrc(Msg,Header: string);
+    procedure CheckFullSource(Msg, Filename, ExpectedSrc: string);
   published
   published
     procedure TestUS_CreateRelativePath;
     procedure TestUS_CreateRelativePath;
 
 
@@ -146,6 +147,7 @@ type
     procedure TestUS_Program_FU;
     procedure TestUS_Program_FU;
     procedure TestUS_Program_FU_o;
     procedure TestUS_Program_FU_o;
     procedure TestUS_Program_FE_o;
     procedure TestUS_Program_FE_o;
+    procedure TestUS_PlatformModule_Program;
 
 
     // include files
     // include files
     procedure TestUS_IncludeSameDir;
     procedure TestUS_IncludeSameDir;
@@ -625,6 +627,8 @@ var
   aFile: TCLIFile;
   aFile: TCLIFile;
 begin
 begin
   aFile:=FindFile('test1.js');
   aFile:=FindFile('test1.js');
+  if aFile=nil then
+    Fail(Msg+' file not found test1.js');
   CheckDiff(Msg,
   CheckDiff(Msg,
     LinesToStr([
     LinesToStr([
     #$EF#$BB#$BF+Header,
     #$EF#$BB#$BF+Header,
@@ -640,6 +644,17 @@ begin
     aFile.Source);
     aFile.Source);
 end;
 end;
 
 
+procedure TTestCLI_UnitSearch.CheckFullSource(Msg, Filename, ExpectedSrc: string
+  );
+var
+  aFile: TCLIFile;
+begin
+  aFile:=FindFile(Filename);
+  if aFile=nil then
+    Fail(Msg+' file not found "'+Filename+'"');
+  CheckDiff(Msg,ExpectedSrc,aFile.Source);
+end;
+
 procedure TTestCLI_UnitSearch.TestUS_CreateRelativePath;
 procedure TTestCLI_UnitSearch.TestUS_CreateRelativePath;
 
 
   procedure DoTest(Filename, BaseDirectory, Expected: string;
   procedure DoTest(Filename, BaseDirectory, Expected: string;
@@ -748,6 +763,25 @@ begin
   AssertNotNull('foo.js not found',FindFile('foo.js'));
   AssertNotNull('foo.js not found',FindFile('foo.js'));
 end;
 end;
 
 
+procedure TTestCLI_UnitSearch.TestUS_PlatformModule_Program;
+begin
+  AddUnit('system.pp',[''],['']);
+  AddFile('test1.pas',[
+    'begin',
+    'end.']);
+  Compile(['-Tmodule','-va','test1.pas']);
+  CheckFullSource('TestUS_PlatformModule_Library','test1.js',
+    LinesToStr([
+    #$EF#$BB#$BF+'rtl.module("program",["system"],function () {',
+    '  "use strict";',
+    '  var $mod = this;',
+    '  $mod.$main = function () {',
+    '  };',
+    '});',
+    'rtl.run();',
+    '']));
+end;
+
 procedure TTestCLI_UnitSearch.TestUS_IncludeSameDir;
 procedure TTestCLI_UnitSearch.TestUS_IncludeSameDir;
 begin
 begin
   AddUnit('system.pp',[''],['']);
   AddUnit('system.pp',[''],['']);

+ 12 - 2
packages/pastojs/tests/testpas2js.lpi

@@ -37,7 +37,7 @@
         <PackageName Value="FCL"/>
         <PackageName Value="FCL"/>
       </Item2>
       </Item2>
     </RequiredPackages>
     </RequiredPackages>
-    <Units Count="13">
+    <Units Count="15">
       <Unit0>
       <Unit0>
         <Filename Value="testpas2js.pp"/>
         <Filename Value="testpas2js.pp"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
@@ -101,6 +101,16 @@
         <Filename Value="tcconverter.pas"/>
         <Filename Value="tcconverter.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
       </Unit12>
       </Unit12>
+      <Unit13>
+        <Filename Value="tcpas2jsanalyzer.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="TCPas2JSAnalyzer"/>
+      </Unit13>
+      <Unit14>
+        <Filename Value="../../fcl-passrc/tests/testpasutils.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="TestPasUtils"/>
+      </Unit14>
     </Units>
     </Units>
   </ProjectOptions>
   </ProjectOptions>
   <CompilerOptions>
   <CompilerOptions>
@@ -110,7 +120,7 @@
     </Target>
     </Target>
     <SearchPaths>
     <SearchPaths>
       <IncludeFiles Value="$(ProjOutDir)"/>
       <IncludeFiles Value="$(ProjOutDir)"/>
-      <OtherUnitFiles Value="../src;../../fcl-js/src;../../fcl-json/src;../../fcl-passrc/src;../../pastojs/tests"/>
+      <OtherUnitFiles Value="../src;../../fcl-js/src;../../fcl-json/src;../../fcl-passrc/src;../../pastojs/tests;../../fcl-passrc/tests"/>
       <UnitOutputDirectory Value="lib"/>
       <UnitOutputDirectory Value="lib"/>
     </SearchPaths>
     </SearchPaths>
     <CodeGeneration>
     <CodeGeneration>

+ 2 - 1
packages/pastojs/tests/testpas2js.pp

@@ -22,7 +22,8 @@ uses
   MemCheck,
   MemCheck,
   {$ENDIF}
   {$ENDIF}
   Classes, consoletestrunner, tcconverter, TCModules, TCSrcMap,
   Classes, consoletestrunner, tcconverter, TCModules, TCSrcMap,
-  TCFiler, TCUnitSearch, TCOptimizations, TCGenerics, TCPrecompile;
+  TCFiler, TCUnitSearch, TCOptimizations, TCGenerics, TCPrecompile, 
+  TCPas2JSAnalyzer, TestPasUtils;
 
 
 type
 type
 
 

+ 41 - 0
packages/paszlib/examples/testgzstream.pp

@@ -0,0 +1,41 @@
+program example;
+
+uses
+  SysUtils, ZStream, Classes;
+
+procedure TestGZip;
+var
+  SS: TStringStream;
+  CS: TGZipCompressionStream;
+  FS: TFileStream;
+begin
+  SS := TStringStream.Create('hello, hello!');
+  FS := TFileStream.Create(GetTempDir+'test.gz', fmCreate);
+  CS := TGZipCompressionStream.Create(FS);
+  CS.CopyFrom(SS, 0);
+  CS.Free;
+  FS.Free;
+  SS.Free;
+end;
+
+procedure TestGUnzip;
+var
+  FS: TFileStream;
+  DS: TGZipDecompressionStream;
+  SS: TStringStream;
+begin
+  FS := TFileStream.Create(GetTempDir+'test.gz', fmOpenRead);
+  DS := TGZipDecompressionStream.Create(FS);
+  SS := TStringStream.Create('');
+  SS.CopyFrom(DS, 0);
+  DS.Free;
+  FS.Free;
+  WriteLn(SS.DataString);
+  SS.Free;
+end;
+
+begin
+  TestGZip;
+  TestGUnZip;
+end. 
+

+ 259 - 0
packages/paszlib/src/zstream.pp

@@ -19,6 +19,8 @@ unit ZStream;
 
 
  **********************************************************************}
  **********************************************************************}
 
 
+{ GZip specs: https://datatracker.ietf.org/doc/html/rfc1952 }
+
 {$mode objfpc}
 {$mode objfpc}
 
 
 {***************************************************************************}
 {***************************************************************************}
@@ -97,6 +99,38 @@ type
           destructor destroy;override;
           destructor destroy;override;
         end;
         end;
 
 
+        TGZipCompressionStream = class(TStream)
+        private
+          FLevel: TCompressionLevel;
+          FCrc32Val: Longword;
+          FUncompressedSize: Cardinal;
+          FDest: TStream;
+          FCompressionStream: TCompressionStream;
+          procedure WriteHeader;
+          procedure WriteFooter;
+        public
+          constructor Create(ADest: TStream); overload;
+          constructor Create(ALevel: TCompressionLevel; ADest: TStream); overload;
+          destructor Destroy; override;
+          function Write(const Buffer; Count: Longint): Longint; override;
+        end;
+
+        TGZipDecompressionStream = class(TStream)
+        private
+          FCrc32Val: Longword;
+          FUncompressedSize: Cardinal;
+          FSource: TStream;
+          FDecompressionStream: TDecompressionStream;
+          procedure Assert(ACond: Boolean; AMsg: string = '');
+          procedure ReadHeader;
+          procedure ReadFooter;
+        public
+          constructor Create(ASource: TStream);
+          destructor Destroy; override;
+          function Read(var Buffer; Count: Longint): Longint; override;
+          function Seek(const Offset: Int64; Origin: TSeekOrigin): Int64; override;
+        end;
+
         Ezliberror=class(Estreamerror)
         Ezliberror=class(Estreamerror)
         end;
         end;
 
 
@@ -117,12 +151,66 @@ uses    zdeflate,zinflate;
 
 
 const   bufsize=16384;     {Size of the buffer used for temporarily storing
 const   bufsize=16384;     {Size of the buffer used for temporarily storing
                             data from the child stream.}
                             data from the child stream.}
+  Crc_32_Tab : Array[0..255] of LongWord = (
+    $00000000, $77073096, $ee0e612c, $990951ba, $076dc419, $706af48f, $e963a535, $9e6495a3,
+    $0edb8832, $79dcb8a4, $e0d5e91e, $97d2d988, $09b64c2b, $7eb17cbd, $e7b82d07, $90bf1d91,
+    $1db71064, $6ab020f2, $f3b97148, $84be41de, $1adad47d, $6ddde4eb, $f4d4b551, $83d385c7,
+    $136c9856, $646ba8c0, $fd62f97a, $8a65c9ec, $14015c4f, $63066cd9, $fa0f3d63, $8d080df5,
+    $3b6e20c8, $4c69105e, $d56041e4, $a2677172, $3c03e4d1, $4b04d447, $d20d85fd, $a50ab56b,
+    $35b5a8fa, $42b2986c, $dbbbc9d6, $acbcf940, $32d86ce3, $45df5c75, $dcd60dcf, $abd13d59,
+    $26d930ac, $51de003a, $c8d75180, $bfd06116, $21b4f4b5, $56b3c423, $cfba9599, $b8bda50f,
+    $2802b89e, $5f058808, $c60cd9b2, $b10be924, $2f6f7c87, $58684c11, $c1611dab, $b6662d3d,
+    $76dc4190, $01db7106, $98d220bc, $efd5102a, $71b18589, $06b6b51f, $9fbfe4a5, $e8b8d433,
+    $7807c9a2, $0f00f934, $9609a88e, $e10e9818, $7f6a0dbb, $086d3d2d, $91646c97, $e6635c01,
+    $6b6b51f4, $1c6c6162, $856530d8, $f262004e, $6c0695ed, $1b01a57b, $8208f4c1, $f50fc457,
+    $65b0d9c6, $12b7e950, $8bbeb8ea, $fcb9887c, $62dd1ddf, $15da2d49, $8cd37cf3, $fbd44c65,
+    $4db26158, $3ab551ce, $a3bc0074, $d4bb30e2, $4adfa541, $3dd895d7, $a4d1c46d, $d3d6f4fb,
+    $4369e96a, $346ed9fc, $ad678846, $da60b8d0, $44042d73, $33031de5, $aa0a4c5f, $dd0d7cc9,
+    $5005713c, $270241aa, $be0b1010, $c90c2086, $5768b525, $206f85b3, $b966d409, $ce61e49f,
+    $5edef90e, $29d9c998, $b0d09822, $c7d7a8b4, $59b33d17, $2eb40d81, $b7bd5c3b, $c0ba6cad,
+    $edb88320, $9abfb3b6, $03b6e20c, $74b1d29a, $ead54739, $9dd277af, $04db2615, $73dc1683,
+    $e3630b12, $94643b84, $0d6d6a3e, $7a6a5aa8, $e40ecf0b, $9309ff9d, $0a00ae27, $7d079eb1,
+    $f00f9344, $8708a3d2, $1e01f268, $6906c2fe, $f762575d, $806567cb, $196c3671, $6e6b06e7,
+    $fed41b76, $89d32be0, $10da7a5a, $67dd4acc, $f9b9df6f, $8ebeeff9, $17b7be43, $60b08ed5,
+    $d6d6a3e8, $a1d1937e, $38d8c2c4, $4fdff252, $d1bb67f1, $a6bc5767, $3fb506dd, $48b2364b,
+    $d80d2bda, $af0a1b4c, $36034af6, $41047a60, $df60efc3, $a867df55, $316e8eef, $4669be79,
+    $cb61b38c, $bc66831a, $256fd2a0, $5268e236, $cc0c7795, $bb0b4703, $220216b9, $5505262f,
+    $c5ba3bbe, $b2bd0b28, $2bb45a92, $5cb36a04, $c2d7ffa7, $b5d0cf31, $2cd99e8b, $5bdeae1d,
+    $9b64c2b0, $ec63f226, $756aa39c, $026d930a, $9c0906a9, $eb0e363f, $72076785, $05005713,
+    $95bf4a82, $e2b87a14, $7bb12bae, $0cb61b38, $92d28e9b, $e5d5be0d, $7cdcefb7, $0bdbdf21,
+    $86d3d2d4, $f1d4e242, $68ddb3f8, $1fda836e, $81be16cd, $f6b9265b, $6fb077e1, $18b74777,
+    $88085ae6, $ff0f6a70, $66063bca, $11010b5c, $8f659eff, $f862ae69, $616bffd3, $166ccf45,
+    $a00ae278, $d70dd2ee, $4e048354, $3903b3c2, $a7672661, $d06016f7, $4969474d, $3e6e77db,
+    $aed16a4a, $d9d65adc, $40df0b66, $37d83bf0, $a9bcae53, $debb9ec5, $47b2cf7f, $30b5ffe9,
+    $bdbdf21c, $cabac28a, $53b39330, $24b4a3a6, $bad03605, $cdd70693, $54de5729, $23d967bf,
+    $b3667a2e, $c4614ab8, $5d681b02, $2a6f2b94, $b40bbe37, $c30c8ea1, $5a05df1b, $2d02ef8d
+  );
 
 
 resourcestring Sgz_open_error='Could not open gzip compressed file %s.';
 resourcestring Sgz_open_error='Could not open gzip compressed file %s.';
                Sgz_read_only='Gzip compressed file was opened for reading.';
                Sgz_read_only='Gzip compressed file was opened for reading.';
                Sgz_write_only='Gzip compressed file was opened for writing.';
                Sgz_write_only='Gzip compressed file was opened for writing.';
+               Sgz_invalid_header='Invalid GZip header';
+               Sgz_invalid_algorithm='Invalid compression algorithm';
+               Sgz_invalid_crc32='Invalid crc32 checksum';
+               Sgz_invalid_output_size='Invalid output size';
                Sseek_failed='Seek in deflate compressed stream failed.';
                Sseek_failed='Seek in deflate compressed stream failed.';
 
 
+function UpdateCrc32(Crc: Longword; const Buffer; Count: Longint): Longword;
+var
+ PBuf: PByte;
+ i: Longint;
+begin
+ PBuf := @Buffer;
+
+ Result := Crc xor $FFFFFFFF;
+ for i := 1 to Count do
+ begin
+   Result := Crc_32_Tab[(Result xor PBuf^) and $ff] xor (Result shr 8);
+   Inc(PBuf);
+ end;
+ Result := Result xor $FFFFFFFF;
+end;
+
 constructor Tcustomzlibstream.create(stream:Tstream);
 constructor Tcustomzlibstream.create(stream:Tstream);
 
 
 begin
 begin
@@ -413,4 +501,175 @@ begin
   inherited destroy;
   inherited destroy;
 end;
 end;
 
 
+{ TGZipCompressionStream }
+
+constructor TGZipCompressionStream.Create(ADest: TStream);
+begin
+  Create(clDefault, ADest);
+end;
+
+constructor TGZipCompressionStream.Create(ALevel: TCompressionLevel; ADest: TStream);
+begin
+  inherited Create;
+  FLevel := ALevel;
+  FCrc32Val := 0;
+  FUncompressedSize := 0;
+  FDest := ADest;
+  WriteHeader;
+  FCompressionStream := TCompressionStream.Create(FLevel, FDest, True);
+end;
+
+destructor TGZipCompressionStream.Destroy;
+begin
+  FCompressionStream.Flush;
+  FCompressionStream.Free;
+  WriteFooter;
+  inherited;
+end;
+
+procedure TGZipCompressionStream.WriteHeader;
+begin
+  FDest.WriteByte($1f);  // signature 1 of 2
+  FDest.WriteByte($8b);  // signature 2 of 2
+  FDest.WriteByte($08);  // deflate algorithm
+  FDest.WriteByte($00);  // no flags
+  FDest.WriteDWord($00); // modification time unknown. Source is stream, not a file
+  if FLevel = clmax then // XFL = extra flags = compression level
+    FDest.WriteByte($02)
+  else if FLevel = clfastest then
+    FDest.WriteByte($04)
+  else
+    FDest.WriteByte($00);
+  FDest.WriteByte($ff);  // OS file system unknown. Source is stream, not a file
+end;
+
+procedure TGZipCompressionStream.WriteFooter;
+var
+  i: Integer;
+begin
+  // write crc32 in 4 bytes, least significant byte first
+  for i := 1 to 4 do
+  begin
+    FDest.WriteByte(FCrc32Val and $ff);
+    FCrc32Val := FCrc32Val shr 8;
+  end;
+
+  // write uncompressed size in 4 bytes, least significant byte first
+  for i := 1 to 4 do
+  begin
+    FDest.WriteByte(FUncompressedSize and $ff);
+    FUncompressedSize := FUncompressedSize shr 8;
+  end;
+end;
+
+function TGZipCompressionStream.Write(const Buffer; Count: Longint): Longint;
+begin
+  FCrc32Val := UpdateCrc32(FCrc32Val, Buffer, Count);
+  Inc(FUncompressedSize, Count);
+  Result := FCompressionStream.Write(Buffer, Count);
+end;
+
+{ TGZipDecompressionStream }
+
+constructor TGZipDecompressionStream.Create(ASource: TStream);
+begin
+  inherited Create;
+  FSource := ASource;
+  FCrc32Val := 0;
+  FUncompressedSize := 0;
+  ReadHeader;
+  FDecompressionStream := TDecompressionStream.Create(FSource, True);
+end;
+
+destructor TGZipDecompressionStream.Destroy;
+begin
+  FDecompressionStream.Free;
+  inherited;
+end;
+
+procedure TGZipDecompressionStream.Assert(ACond: Boolean; AMsg: string = '');
+begin
+  if not ACond then
+    raise EDecompressionError.Create(AMsg);
+end;
+
+procedure TGZipDecompressionStream.ReadHeader;
+var
+  Flags: Byte;
+  XLEN: Cardinal;
+begin
+  Assert(FSource.ReadByte = $1f, Sgz_invalid_header);
+  Assert(FSource.ReadByte = $8b, Sgz_invalid_header);
+  Assert(FSource.ReadByte = $08, Sgz_invalid_algorithm);
+  Flags := FSource.ReadByte;
+  FSource.ReadDWord; // skip modification time. Dest is stream, not a file
+  FSource.ReadByte;  // skip compression level, is not needed
+  FSource.ReadByte;  // skip OS file system. Dest is stream, not a file
+
+  if (Flags and $4) <> 0 then // FLG.FEXTRA
+  begin
+    XLEN := FSource.ReadByte + FSource.ReadByte shl 8; // least significant byte first
+    while XLEN > 0 do
+    begin
+      FSource.ReadByte;
+      Dec(XLEN);
+    end;
+  end;
+
+  if (Flags and $8) <> 0 then // FLG.FNAME
+  begin
+    repeat
+    until FSource.ReadByte = 0; // zero-terminated file name
+  end;
+
+  if (Flags and $10) <> 0 then // FLG.FCOMMENT
+  begin
+    repeat
+    until FSource.ReadByte = 0; // zero-terminated file comment
+  end;
+
+  if (Flags and $2) <> 0 then // FLG.FHCRC
+    FSource.ReadWord; // skip CRC16, check not implemented
+end;
+
+procedure TGZipDecompressionStream.ReadFooter;
+var
+  Crc32: Longword;
+  OrigSize: Longword;
+begin
+  // The TDecompressionStream reads in buffers, so the footer
+  // may already be skipped. Therefore, we need to Seek to the footer.
+  // If FSource is non-seekable, we skip checking Crc32 and OrigSize.
+  try
+    FSource.Seek(-8, soEnd);
+  except
+    Exit;  // skip Crc32 and OrigSize checking
+  end;
+
+  Crc32 := FSource.ReadByte + FSource.ReadByte shl 8 + FSource.ReadByte shl 16 + FSource.ReadByte shl 24;
+  Assert(FCrc32Val = Crc32, Sgz_invalid_crc32);
+  OrigSize := FSource.ReadByte + FSource.ReadByte shl 8 + FSource.ReadByte shl 16 + FSource.ReadByte shl 24;
+  Assert(FUncompressedSize = OrigSize, Sgz_invalid_output_size);
+end;
+
+function TGZipDecompressionStream.Read(var Buffer; Count: Longint): Longint;
+begin
+  Result := FDecompressionStream.Read(Buffer, Count);
+  Inc(FUncompressedSize, Result);
+  FCrc32Val := UpdateCrc32(FCrc32Val, Buffer, Result);
+
+  if Result < Count then
+    ReadFooter;
+end;
+
+function TGZipDecompressionStream.Seek(const Offset: Int64; Origin: TSeekOrigin): Int64;
+begin
+  // accept Seek(0, soBeginning) if nothing read yet
+  // this is needed for the TStream.CopyFrom() method
+  if (Offset = 0) and (Origin = TSeekOrigin.soBeginning) and (FUncompressedSize = 0) then
+    Result := 0
+  else
+    Result := inherited Seek(Offset, Origin);
+end;
+
 end.
 end.

+ 1 - 1
packages/rtl-extra/fpmake.pp

@@ -19,7 +19,7 @@ Const
   IPCBSDs       = [FreeBSD,NetBSD,OpenBSD,DragonFly];
   IPCBSDs       = [FreeBSD,NetBSD,OpenBSD,DragonFly];
 //  IPCcdeclOSes  = [Darwin,iphonesim,ios];
 //  IPCcdeclOSes  = [Darwin,iphonesim,ios];
 
 
-  PrinterOSes   = [go32v2,msdos,os2,win32,win64]+unixlikes-[beos,haiku,morphos];
+  PrinterOSes   = [go32v2,msdos,os2,win32,win64,atari]+unixlikes-[beos,haiku,morphos];
   SerialOSes    = [android,linux,netbsd,openbsd,win32,win64];
   SerialOSes    = [android,linux,netbsd,openbsd,win32,win64];
   UComplexOSes  = [atari,embedded,emx,gba,go32v2,msdos,nativent,nds,netware,netwlibc,os2,sinclairql,symbian,watcom,wii,wince,win32,win64,freertos,wasi]+UnixLikes+AllAmigaLikeOSes;
   UComplexOSes  = [atari,embedded,emx,gba,go32v2,msdos,nativent,nds,netware,netwlibc,os2,sinclairql,symbian,watcom,wii,wince,win32,win64,freertos,wasi]+UnixLikes+AllAmigaLikeOSes;
   MatrixOSes    = [atari,embedded,emx,gba,go32v2,msdos,nativent,nds,netware,netwlibc,os2,sinclairql,symbian,watcom,wii,win32,win64,wince,freertos,wasi]+UnixLikes+AllAmigaLikeOSes;
   MatrixOSes    = [atari,embedded,emx,gba,go32v2,msdos,nativent,nds,netware,netwlibc,os2,sinclairql,symbian,watcom,wii,win32,win64,wince,freertos,wasi]+UnixLikes+AllAmigaLikeOSes;

+ 29 - 0
packages/rtl-extra/src/atari/printer.pp

@@ -0,0 +1,29 @@
+{
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 1999-2000 by Florian Klaempfl
+    member of the Free Pascal development team
+
+    Printer unit for BP7/PurePascal compatible RTL
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+unit printer;
+interface
+
+{$I printerh.inc}
+
+implementation
+
+{$I printer.inc}
+
+begin
+  (* WARNING: has to be checked; do_open('PRN') returns a valid, negative OS handle *)
+  InitPrinter ('PRN:');
+  SetPrinterExit;
+end.

+ 3 - 0
packages/tosunits/fpmake.pp

@@ -34,6 +34,9 @@ begin
     T:=P.Targets.AddUnit('tos.pas');
     T:=P.Targets.AddUnit('tos.pas');
     T:=P.Targets.AddUnit('vdi.pas');
     T:=P.Targets.AddUnit('vdi.pas');
     T:=P.Targets.AddUnit('aes.pas');
     T:=P.Targets.AddUnit('aes.pas');
+    T:=P.Targets.AddUnit('gem.pas');
+    T:=P.Targets.AddUnit('gemcommon.pas');
+    T:=P.Targets.AddUnit('nf_ops.pas');
 
 
     P.ExamplePath.Add('examples');
     P.ExamplePath.Add('examples');
     T:=P.Targets.AddExampleProgram('higem.pas');
     T:=P.Targets.AddExampleProgram('higem.pas');

File diff suppressed because it is too large
+ 508 - 301
packages/tosunits/src/aes.pas


+ 800 - 0
packages/tosunits/src/aestypes.inc

@@ -0,0 +1,800 @@
+{
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 2022 Thorsten Otto
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+type
+  PAESContrl = ^TAESContrl;
+  TAESContrl = record
+    opcode: SmallInt;
+    case boolean of
+      true: (
+        nums: array[0..3] of SmallInt; );
+      false: (
+        num_intin: SmallInt;
+        num_intout: SmallInt;
+        num_addrin: SmallInt;
+        num_addrout: SmallInt; );
+  end;
+
+  PAESGlobal = ^TAESGlobal;
+  TAESGlobal = array[0..14] of SmallInt;
+
+  PAESIntIn = ^TAESIntIn;
+  TAESIntIn = array[0..15] of SmallInt;
+
+  PAESIntOut = ^TAESIntOut;
+  TAESIntOut = array[0..9] of SmallInt;
+
+  PAESAddrIn = ^TAESAddrIn;
+  TAESAddrIn = array[0..7] of Pointer;
+
+  PAESAddrOut = ^TAESAddrOut;
+  TAESAddrOut = array[0..1] of Pointer;
+
+type
+  PAESPB = ^TAESPB;
+  TAESPB = record
+    control: PAESContrl;
+    global: PAESGlobal;
+    intin: PAESIntIn;
+    intout: PAESIntOut;
+    addrin: PAESAddrIn;
+    addrout: PAESAddrOut;
+  end;
+
+const
+  AES_TRAP_MAGIC = $C8;
+
+{ object flags }
+const
+    NONE            = 0;
+    SELECTABLE      = 1;
+    DEFAULT         = 2;
+    F_EXIT          = 4;
+    EDITABLE        = 8;
+    RBUTTON         = 16;
+    LASTOB          = 32;
+    TOUCHEXIT       = 64;
+    HIDETREE        = 128;
+    INDIRECT        = 256;
+    FL3DMASK        = $0600;
+    FL3DNONE        = $0000;
+    FL3DIND         = $0200;
+    FL3DBAK         = $0400;
+    FL3DACT         = $0600;
+    SUBMENU         = $0800;         {* falcon aes hierarchical menus *}
+
+{ object state }
+const
+    NORMAL          = $0000;
+    SELECTED        = $0001;
+    CROSSED         = $0002;
+    CHECKED         = $0004;
+    DISABLED        = $0008;
+    OUTLINED        = $0010;
+    SHADOWED        = $0020;
+    WHITEBAK        = $0040;
+    DRAW3D          = $0080;
+
+{ AES object types }
+const
+    G_BOX           = 20;
+    G_TEXT          = 21;
+    G_BOXTEXT       = 22;
+    G_IMAGE         = 23;
+    G_USERDEF       = 24;
+    G_IBOX          = 25;
+    G_BUTTON        = 26;
+    G_BOXCHAR       = 27;
+    G_STRING        = 28;
+    G_FTEXT         = 29;
+    G_FBOXTEXT      = 30;
+    G_ICON          = 31;
+    G_TITLE         = 32;
+    G_CICON         = 33;
+    G_SWBUTTON      = 34;
+    G_POPUP         = 35;
+    G_WINTITLE      = 36;
+    G_EDIT          = 37;
+    G_SHORTCUT      = 38;
+    G_SLIST         = 39;
+    G_EXTBOX        = 40;
+    G_OBLINK        = 41;
+
+
+type
+    PTEDINFO = ^TTEDINFO;
+    TTEDINFO = record
+        te_ptext        : Pchar;
+        te_ptmplt       : Pchar;
+        te_pvalid       : Pchar;
+        te_font         : smallint;
+        te_resvd1       : smallint;
+        te_just         : smallint;
+        te_color        : smallint;
+        te_resvd2       : smallint;
+        te_thickness    : smallint;
+        te_txtlen       : smallint;
+        te_tmplen       : smallint;
+    end;
+
+    PICONBLK = ^TICONBLK;
+    TICONBLK = record
+        ib_pmask        : Pointer;
+        ib_pdata        : Pointer;
+        ib_ptext        : Pchar;
+        ib_char         : smallint;
+        ib_xchar        : smallint;
+        ib_ychar        : smallint;
+        ib_xicon        : smallint;
+        ib_yicon        : smallint;
+        ib_wicon        : smallint;
+        ib_hicon        : smallint;
+        ib_xtext        : smallint;
+        ib_ytext        : smallint;
+        ib_wtext        : smallint;
+        ib_htext        : smallint;
+    end;
+
+    PCICON = ^TCICON;
+    TCICON = record
+        num_planes      : smallint;
+        col_data        : Pointer;
+        col_mask        : Pointer;
+        sel_data        : Pointer;
+        sel_mask        : Pointer;
+        next_res        : PCICON;
+    end;
+
+    PCICONBLK = ^TCICONBLK;
+    TCICONBLK = record
+        monoblk         : TICONBLK;
+        mainlist        : PCICON;
+    end;
+
+    PBITBLK = ^TBITBLK;
+    TBITBLK = record
+        bi_pdata        : Pointer;
+        bi_wb           : smallint;
+        bi_hl           : smallint;
+        bi_x            : smallint;
+        bi_y            : smallint;
+        bi_color        : smallint;
+    end;
+
+    PUSERBLK = ^TUSERBLK;
+    TUSERBLK = record
+        ub_code         : Pointer;
+        ub_parm         : LongInt;
+    end;
+
+    POBSPEC = ^TOBSPEC;
+    TOBSPEC = record
+        case smallint of
+            0,
+            G_BOX,
+            G_IBOX,
+            G_BOXCHAR:  ( index:        LongInt     );
+            G_BOXTEXT,
+            G_TEXT,
+            G_FTEXT,
+            G_FBOXTEXT: ( ted_info:     PTEDINFO    );
+            G_IMAGE:    ( bit_blk:      PBITBLK );
+            G_USERDEF:  ( user_blk:     PUSERBLK    );
+            G_BUTTON,
+            G_STRING,
+            G_TITLE:    ( free_string:  Pchar       );
+            G_ICON:     ( icon_blk:     PICONBLK    );
+            G_CICON:    ( cicon_blk:    PCICONBLK   );
+
+            INDIRECT:   ( ob_spec:      POBSPEC );
+    end;
+
+type
+  PAESOBJECT = ^TAESOBJECT;
+  TAESOBJECT = record
+    ob_next: smallint;   {* The next object               *}
+    ob_head: smallint;   {* First child                   *}
+    ob_tail: smallint;   {* Last child                    *}
+    ob_type: word;       {* Object type                   *}
+    ob_flags: word;      {* Manipulation flags            *}
+    ob_state: word;      {* Object status                 *}
+    ob_spec: TOBSPEC;    {* More under object type        *}
+    ob_x: smallint;      {* X-coordinate of the object    *}
+    ob_y: smallint;      {* Y-coordinate of the object    *}
+    ob_width: smallint;  {* Width of the object           *}
+    ob_height: smallint; {* Height of the object          *}
+  end;
+
+    PAESTree = ^TAESTree;
+    TAESTree = Array[0..2339] of TAESOBJECT;
+
+    PPARMBLK = ^TPARMBLK;
+    TPARMBLK = record
+        pb_tree         : PAESTree;
+        pb_obj          : smallint;
+        pr_prevstate    : smallint; {* maybe bug in PP; should be pb_prevstate *}
+        pr_currstate    : smallint; {* maybe bug in PP; should be pb_currstate *}
+        pb_x            : smallint;
+        pb_y            : smallint;
+        pb_w            : smallint;
+        pb_h            : smallint;
+        pb_xc           : smallint;
+        pb_yc           : smallint;
+        pb_wc           : smallint;
+        pb_hc           : smallint;
+        pb_parm         : LongInt;
+    end;
+
+    PRSHDR = ^TRSHDR;
+    TRSHDR = record
+        rsh_vrsn:       Word;
+        rsh_object:     Word;
+        rsh_tedinfo:    Word;
+        rsh_iconblk:    Word;
+        rsh_bitblk:     Word;
+        rsh_frstr:      Word;
+        rsh_string:     Word;
+        rsh_imdata:     Word;
+        rsh_frimg:      Word;
+        rsh_trindex:    Word;
+        rsh_nobs:       Word;
+        rsh_ntree:      Word;
+        rsh_nted:       Word;
+        rsh_nib:        Word;
+        rsh_nbb:        Word;
+        rsh_nstring:    Word;
+        rsh_nimages:    Word;
+        rsh_rssize:     Word;
+    end;
+
+type
+    PEVENT = ^TEVENT;
+    TEVENT = record
+        ev_mflags:      smallint;        { input parameters }
+        ev_mbclicks:    smallint;
+        ev_bmask:       smallint;
+        ev_mbstate:     smallint;
+        ev_mm1flags:    smallint;
+        ev_mm1x:        smallint;
+        ev_mm1y:        smallint;
+        ev_mm1width:    smallint;
+        ev_mm1height:   smallint;
+        ev_mm2flags:    smallint;
+        ev_mm2x:        smallint;
+        ev_mm2y:        smallint;
+        ev_mm2width:    smallint;
+        ev_mm2height:   smallint;
+        ev_mtlocount:   smallint;
+        ev_mthicount:   smallint;
+        ev_mwich:       smallint;       { output parameters }
+        ev_mmox:        smallint;
+        ev_mmoy:        smallint;
+        ev_mmobutton:   smallint;
+        ev_mmokstate:   smallint;
+        ev_mkreturn:    smallint;
+        ev_mbreturn:    smallint;
+        ev_mmgpbuf:     ARRAY_8;
+    end;
+
+type
+  PGRECT = ^TGRECT;
+  TGRECT = record
+    case integer of 
+     0: (x: smallint;     {* X-coordinate *}
+         y: smallint;     {* Y-coordinate *}
+         w: smallint;     {* Width        *}
+         h: smallint);    {* Height       *}
+     1: (g_x: smallint;   {* X-coordinate *}
+         g_y: smallint;   {* Y-coordinate *}
+         g_w: smallint;   {* Width        *}
+         g_h: smallint);  {* Height       *}
+  end;
+
+{ kinds, as used by wind_create() }
+const
+  NAME    = $01;   { Window has a title bar. }
+  CLOSER  = $02;   { Window has a close box. }
+  FULLER  = $04;   { Window has a fuller box. }
+  MOVER   = $08;   { Window may be moved by the user. }
+  INFO    = $10;   { Window has an information line. }
+  SIZER   = $20;   { Window has a sizer box. }
+  UPARROW = $40;   { Window has an up arrow. }
+  DNARROW = $80;   { Window has a down arrow. }
+  VSLIDE  = $100;  { Window has a vertical slider. }
+  LFARROW = $200;  { Window has a left arrow. }
+  RTARROW = $400;  { Window has a right arrow. }
+  HSLIDE  = $800;  { Window has a horizontal slider. }
+  MENUBAR = $1000; { Window has a menu bar (XaAES) }
+  SMALLER = $4000; { Window has an iconifier. }
+  ICONIFIER = SMALLER;
+  BORDER  = $8000; { Window has an sizeing border }
+
+{ messages as used by evnt_mesag() }
+const
+  MN_SELECTED   = 10;
+  WM_REDRAW     = 20;
+  WM_TOPPED     = 21;
+  WM_CLOSED     = 22;
+  WM_FULLED     = 23;
+  WM_ARROWED    = 24;
+  WM_HSLID      = 25;
+  WM_VSLID      = 26;
+  WM_SIZED      = 27;
+  WM_MOVED      = 28;
+  WM_NEWTOP     = 29;
+  WM_UNTOPPED   = 30;
+  WM_ONTOP      = 31;
+  WM_OFFTOP     = 32;
+  WM_BOTTOMED   = 33;
+  WM_ICONIFY    = 34;
+  WM_UNICONIFY  = 35;
+  WM_ALLICONIFY = 36;
+  WM_TOOLBAR    = 37;
+  AC_OPEN       = 40;
+  AC_CLOSE      = 41;
+  CT_UPDATE     = 50;
+  CT_MOVE       = 51;
+  CT_NEWTOP     = 52;
+  AP_TERM       = 50;
+  AP_TFAIL      = 51;
+  AP_RESCHG     = 57;
+  SHUT_COMPLETED = 60;
+  RESCHG_COMPLETED = 61;
+  AP_DRAGDROP   = 63;
+  SH_EXIT       = 68;          {* AES 4.0 *}
+  SH_START      = 69;          {* AES 4.0 *}
+  SH_WDRAW      = 72;          {* AES 4.0 *}
+  SC_CHANGED    = 80;
+  PRN_CHANGED   = 82;          {* NVDI *}
+  FNT_CHANGED   = 83;          {* NVDI *}
+  COLORS_CHANGED = 84;         {* NVDI *}
+  THR_EXIT      = 88;          {* MagiC 4.5 *}
+  PA_EXIT       = 89;          {* MagiC 3 *}
+  CH_EXIT       = 90;
+  WM_WHEEL      = 345;         {* XaAES *}
+  WM_MOUSEWHEEL = 2352;
+  WM_SHADED     = 22360;       {* WiNX *}
+  WM_UNSHADED   = 22361;       {* WinX *}
+
+    WA_UPPAGE       = 0;
+    WA_DNPAGE       = 1;
+    WA_UPLINE       = 2;
+    WA_DNLINE       = 3;
+    WA_LFPAGE       = 4;
+    WA_RTPAGE       = 5;
+    WA_LFLINE       = 6;
+    WA_RTLINE       = 7;
+    WA_WHEEL        = 8;
+
+{* AP_DRAGDROP return codes *}
+const
+    DD_OK        = 0;
+    DD_NAK       = 1;
+    DD_EXT       = 2;
+    DD_LEN       = 3;
+    DD_TRASH     = 4;
+    DD_PRINTER   = 5;
+    DD_CLIPBOARD = 6;
+
+    DD_TIMEOUT  = 4000;     {* Timeout in ms *}
+
+    DD_NUMEXTS  = 8;        {* Number of formats *}
+    DD_EXTLEN   = 4;
+    DD_EXTSIZE  = DD_NUMEXTS * DD_EXTLEN;
+
+    DD_FNAME    = 'U:\\PIPE\\DRAGDROP.AA';
+    DD_NAMEMAX  = 128;      {* Maximum length of a format name *}
+    DD_HDRMIN   = 9;            {* Minimum length of Drag&Drop headers *}
+    DD_HDRMAX   = 8 + DD_NAMEMAX;   {* Maximum length *}
+
+{ message flags as used by evnt_multi() }
+const
+  MU_KEYBD  = $0001; { Keyboard event }
+  MU_BUTTON = $0002; { Button event   }
+  MU_M1     = $0004; { Mouse event 1  }
+  MU_M2     = $0008; { Mouse event 2  }
+  MU_MESAG  = $0010; { Messages       }
+  MU_TIMER  = $0020; { Timer events   }
+  MU_WHEEL         = $0040;      {* AES 4.09 & XaAES *}
+  MU_MX            = $0080;      {* XaAES *}
+  MU_NORM_KEYBD    = $0100;      {*   "   *}
+  MU_DYNAMIC_KEYBD = $0200;      {* keybd as a bunch of buttons, includes release of key *}
+
+{ window update flags as used by wind_update() }
+const
+  END_UPDATE = (0);  { Screen redraw is compete and the flag set by BEG_UPDATE is reset }
+  BEG_UPDATE = (1);  { Screen redraw starts, rectangle lists are frozen, flag is set to prevent any other processes updating the screen }
+  END_MCTRL  = (2);  { Application releases control of the mouse to the AES and resumes mouse click message reactions }
+  BEG_MCTRL  = (3);  { The application wants to have sole control over mouse button messages }
+  BEG_CHECK  = $100;
+
+{ window flags as used by wind_set()/wind_get() }
+const
+  WF_KIND      = (1);
+  WF_NAME      = (2);
+  WF_INFO      = (3);
+  WF_WORKXYWH  = (4);
+  WF_CURRXYWH  = (5);
+  WF_PREVXYWH  = (6);
+  WF_FULLXYWH  = (7);
+  WF_HSLIDE    = (8);
+  WF_VSLIDE    = (9);
+  WF_TOP       = (10);
+  WF_FIRSTXYWH = (11);
+  WF_NEXTXYWH  = (12);
+  WF_NEWDESK   = (14);
+  WF_HSLSIZE   = (15);
+  WF_VSLSIZE   = (16);
+  WF_SCREEN    = (17);
+  WF_COLOR     = 18;
+  WF_TATTRB    = 18;
+  WF_DCOLOR    = 19;
+  WF_SIZTOP    = 19;
+  WF_OWNER     = 20;
+  WF_BEVENT    = 24;
+  WF_BOTTOM    = 25;
+  WF_ICONIFY   = 26;
+  WF_UNICONIFY = 27;
+  WF_UNICONIFYXYWH = 28;
+  WF_TOOLBAR   = (30);
+  WF_FTOOLBAR  = 31;
+  WF_NTOOLBAR  = 32;
+  WF_MENU      = 33;
+  WF_WIDGET    = 34;
+  WF_WHEEL     = 40;
+  WF_OPTS      = 41;
+  WF_TOPMOST   = 232;             {* XaAES, MyAES *}
+  WF_WINX      = $5758;
+  WF_WINXCFG   = $5759;
+  WF_DDELAY    = $575a;
+  WF_SHADE     = $575d;
+  WF_STACK     = $575e;
+  WF_TOPALL    = $575f;
+  WF_BOTTOMALL = $5760;
+  WF_XAAES     = $5841;
+
+{ window calculation types as used by wind_calc() }
+const
+  WC_BORDER = 0;
+  WC_WORK   = 1;
+
+{ WF_DCOLOR objects }
+const
+    W_BOX           = 0;
+    W_TITLE         = 1;
+    W_CLOSER        = 2;
+    W_NAME          = 3;
+    W_FULLER        = 4;
+    W_INFO          = 5;
+    W_DATA          = 6;
+    W_WORK          = 7;
+    W_SIZER         = 8;
+    W_VBAR          = 9;
+    W_UPARROW       = 10;
+    W_DNARROW       = 11;
+    W_VSLIDE        = 12;
+    W_VELEV         = 13;
+    W_HBAR          = 14;
+    W_LFARROW       = 15;
+    W_RTARROW       = 16;
+    W_HSLIDE        = 17;
+    W_HELEV         = 18;
+    W_SMALLER       = 19;
+    W_BOTTOMER      = 20;
+    W_HIDER         = 30;
+
+{* wind_set(WF_BEVENT) *}
+    BEVENT_WORK     = $0001;          {* AES 4.0  *}
+    BEVENT_INFO     = $0002;          {* MagiC 6  *}
+
+{* wind_set(WF_OPTS) bitmask flags *}
+    WO0_WHEEL       = $0001;  {* see mt_wind_set() with #WF_OPTS mode *}
+    WO0_FULLREDRAW  = $0002;  {* see mt_wind_set() with #WF_OPTS mode *}
+    WO0_NOBLITW     = $0004;  {* see mt_wind_set() with #WF_OPTS mode *}
+    WO0_NOBLITH     = $0008;  {* see mt_wind_set() with #WF_OPTS mode *}
+    WO0_SENDREPOS   = $0010;  {* see mt_wind_set() with #WF_OPTS mode *}
+    WO1_NONE        = $0000;  {* see mt_wind_set() with #WF_OPTS mode *}
+    WO2_NONE        = $0000;  {* see mt_wind_set() with #WF_OPTS mode *}
+
+{* wind_set(WF_WHEEL) modes *}
+    WHEEL_MESAG     = 0;   {* AES will send #WM_WHEEL messages *}
+    WHEEL_ARROWED   = 1;   {* AES will send #WM_ARROWED messages *}
+    WHEEL_SLIDER    = 2;   {* AES will convert mouse wheel events to slider events *}
+
+
+{ AES standard object colors }
+const
+  WHITE    = (00);  { White          1000, 1000, 1000 }
+  BLACK    = (01);  { Black             0,    0,    0 }
+  RED      = (02);  { Red            1000,    0,    0 }
+  GREEN    = (03);  { Green             0, 1000,    0 }
+  BLUE     = (04);  { Blue              0,    0, 1000 }
+  CYAN     = (05);  { Cyan              0, 1000, 1000 }
+  YELLOW   = (06);  { Yellow         1000, 1000,    0 }
+  MAGENTA  = (07);  { Magenta        1000,    0, 1000 }
+  DWHITE   = (08);  { Light grey      752,  752,  752 }
+  DBLACK   = (09);  { Dark grey       501,  501,  501 }
+  DRED     = (10);  { Dark red        713,    0,    0 }
+  DGREEN   = (11);  { Dark green        0,  713,    0 }
+  DBLUE    = (12);  { Dark blue         0,    0,  713 }
+  DCYAN    = (13);  { Dark cyan         0,  713,  713 }
+  DYELLOW  = (14);  { Dark yellow     713,  713,    0 }
+  DMAGENTA = (15);  { Dark magenta    713,    0,  713 }
+
+{* editable text justification *}
+const
+    TE_LEFT         = 0;
+    TE_RIGHT        = 1;
+    TE_CNTR         = 2;
+    TE_JUST_MASK    = 3;
+
+{* font types *}
+const
+    GDOS_PROP        = 0; {* Speedo GDOS font *}
+    GDOS_MONO        = 1; {* Speedo GDOS font, force monospace output *}
+    GDOS_BITM        = 2; {* GDOS bit map font *}
+    IBM              = 3;
+    SMALL            = 5;
+    TE_FONT_MASK     = 7;
+
+{* editable text field definitions *}
+const
+    ED_START        = 0;
+    ED_INIT         = 1;
+    ED_CHAR         = 2;
+    ED_END          = 3;
+    ED_CRSR         = 100;            {* MAG!X *}
+    ED_DRAW         = 103;            {* MAG!X 2.00 *}
+    EDSTART         = 0;
+    EDINIT          = 1;
+    EDCHAR          = 2;
+    EDEND           = 3;
+
+{$IFNDEF IP_HOLLOW_defined}
+{* inside patterns *}
+    IP_HOLLOW       = 0;
+    IP_1PATT        = 1;
+    IP_2PATT        = 2;
+    IP_3PATT        = 3;
+    IP_4PATT        = 4;
+    IP_5PATT        = 5;
+    IP_6PATT        = 6;
+    IP_SOLID        = 7;
+{$DEFINE IP_HOLLOW_defined}
+{$ENDIF}
+
+    ROOT            = 0;
+    MAX_DEPTH       = 8;
+
+{ AES mouse cursor number }
+const
+  ARROW          = 0;       { Arrow                               }
+  TEXT_CRSR      = 1;       { Text cursor                         }
+  HOURGLASS      = 2;       { Hourglass, bee                      }
+  BUSY_BEE       = 2;       { See HOURGLASS                       }
+  BUSYBEE        = 2;       { See HOURGLASS                       }
+  POINT_HAND     = 3;       { Pointing hand                       }
+  FLAT_HAND      = 4;       { Flat hand                           }
+  THIN_CROSS     = 5;       { Thin crosshairs                     }
+  THICK_CROSS    = 6;       { Thick crosshairs                    }
+  OUTLN_CROSS    = 7;       { Outlined crosshairs                 }
+  USER_DEF       = 255;     { User-defined mouse form             }
+  M_OFF          = 256;     { Switch off mouse pointer            }
+  M_ON           = 257;     { Switch on mouse pointer             }
+  M_SAVE         = 258;     { Save current mouse form             }
+  M_LAST         = 259;     { Restore most recently saved form    }
+  M_PREVIOUS     = 259;     { See M_LAST                          }
+  M_RESTORE      = 260;     { Restore last shape                  }
+  M_FORCE        = $8000;
+  X_MRESET       = 1000;
+  X_MGET         = 1001;
+  X_MSET_SHAPE   = 1100;
+
+{ Menu definitions as used by menu_bar() }
+const
+  MENU_INQUIRE   = -1;
+  MENU_HIDE      = 0;
+  MENU_SHOW      = 1;
+
+{ Form dialog space actions, as used by form_dial() }
+const
+  FMD_START  = 0; { Reserve screen space for a dialog }
+  FMD_GROW   = 1; { Draw several expanding rectangles from the coordinates fo_dilittlx/y/w/hto fo_dibigx/y/w/h }
+  FMD_SHRINK = 2; { Draw several shrinking rectangles from fo_dibigx/y/w/h to fo_dilittlx/y/w/h }
+  FMD_FINISH = 3; { Release the reserved screen space again }
+
+{ Resource structure types as used by rsrc_gaddr()/rsrc_saddr() }
+const
+  R_TREE      = 0;  { Object tree                          }
+  R_OBJECT    = 1;  { Individual OBJECT (TAESOBJECT)       }
+  R_TEDINFO   = 2;  { TEDINFO structure                    }
+  R_ICONBLK   = 3;  { ICONBLK structure                    }
+  R_BITBLK    = 4;  { BITBLK structure                     }
+  R_STRING    = 5;  { Free string data                     }
+  R_IMAGEDATA = 6;  { Free image data                      }
+  R_OBSPEC    = 7;  { ob_spec field in OBJECT (TAESOBJECT) }
+  R_TEPTEXT   = 8;  { te_ptext in TEDINFO                  }
+  R_TEPTMPLT  = 9;  { te_ptmplt in TEDINFO                 }
+  R_TEPVALID  = 10; { te_pvalid in TEDINFO                 }
+  R_IBPMASK   = 11; { ib_pmask in ICONBLK                  }
+  R_IBPDATA   = 12; { ib_pdata in ICONBLK                  }
+  R_IBPTEXT   = 13; { ib_ptext in ICONBLK                  }
+  R_BIPDATA   = 14; { ib_pdate in BITBLK                   }
+  R_FRSTR     = 15; { ad_frstr free string                 }
+  R_FRIMG     = 16; { ad_frimg free image                  }
+
+{* keyboard states (same as in bios) *}
+    K_RSHIFT        = $0001;
+    K_LSHIFT        = $0002;
+    K_SHIFT         = $0003;
+    K_CTRL          = $0004;
+    K_ALT           = $0008;
+    K_CAPSLOCK      = $0010;
+
+{* appl_read modes *}
+    APR_NOWAIT      = -1;   {* Do not wait for message -- see mt_appl_read() *}
+
+{* appl_search modes *}
+    APP_FIRST = 0;
+    APP_NEXT  = 1;
+    APP_DESK  = 2;
+    X_APS_CHILD0    = $7100; {* Geneva *}
+    X_APS_CHILD     = $7101; {* Geneva *}
+    X_APS_CHEXIT    = -1;    {* Geneva *}
+
+{* application type (appl_search return values) *}
+    APP_SYSTEM          = $001;
+    APP_APPLICATION     = $002;
+    APP_ACCESSORY       = $004;
+    APP_SHELL           = $008;
+    APP_AESSYS          = $010;
+    APP_AESTHREAD       = $020;
+    APP_TASKINFO        = $100; {* XaAES extension for taskbar applications. *}
+    APP_HIDDEN          = $100; {* Task is disabled; XaAES only for APP_TASKINFO *}
+    APP_FOCUS           = $200; {* Active application; XaAES only for APP_TASKINFO *}
+
+{* menu_attach modes *}
+    ME_INQUIRE      = 0;
+    ME_ATTACH       = 1;
+    ME_REMOVE       = 2;
+{* menu_attach attributes *}
+    SCROLL_NO       = 0;
+    SCROLL_YES      = 1;
+
+{* menu_popup modes *}
+    SCROLL_LISTBOX      = -1;
+
+{* the objc_sysvar ob_swhich values *}
+    LK3DIND      = 1;
+    LK3DACT      = 2;
+    INDBUTCOL    = 3;
+    ACTBUTCOL    = 4;
+    BACKGRCOL    = 5;
+    AD3DVAL      = 6;
+    MX_ENABLE3D  = 10;
+    MENUCOL      = 11;
+
+    OB_GETVAR = 0;
+    OB_SETVAR = 1;
+
+{* objc_sysvar modes *}
+    SV_INQUIRE      = 0;
+    SV_SET          = 1;
+
+{* scrp_read return values *}
+    SCRAP_CSV       = $0001;
+    SCRAP_TXT       = $0002;
+    SCRAP_GEM       = $0004;
+    SCRAP_IMG       = $0008;
+    SCRAP_DCA       = $0010;
+    SCRAP_DIF       = $0020;
+    SCRAP_USR       = $8000;
+
+{* shel_write modes for parameter "isover" *}
+    SHW_IMMED        = 0;
+    SHW_CHAIN        = 1;
+    SHW_DOS          = 2;
+    SHW_PARALLEL   = 100;
+    SHW_SINGLE     = 101;
+
+{* shel_write sh_wdoex parameter flags in MSB *}
+    SHD_PSETLIM = (1 shl 8);    { MiNT memory allocation limit }
+    SHD_PRENICE = (1 shl 9);    { MiNT Prenice (priority) level }
+    SHD_DFLTDIR = (1 shl 10);   { Default directory string }
+    SHD_ENVIRON = (1 shl 11);   { Environment string }
+    SHD_UID     = (1 shl 12);   { set user id }
+    SHD_GID     = (1 shl 13);   { set group id }
+
+{* shel_write modes for parameter "doex" *}
+    SWM_LAUNCH       = 0;
+    SWM_LAUNCHNOW    = 1;
+    SWM_LAUNCHACC    = 3;
+    SWM_SHUTDOWN     = 4;
+    SWM_REZCHANGE    = 5;
+    SWM_BROADCAST    = 7;
+    SWM_ENVIRON      = 8;
+    SWM_NEWMSG       = 9;
+    SWM_AESMSG      = 10;
+    SWM_THRCREATE   = 20;
+    SWM_THREXIT     = 21;
+    SWM_THRKILL     = 22;
+
+{* shel_write, parameter wisgr *}
+    TOSAPP              = 0;
+    GEMAPP              = 1;
+
+{* command line parser (shel_write: parameter "wiscr") *}
+    CL_NORMAL       = 0;
+    CL_PARSE        = 1;
+
+{* shutdown action (shel_write: mode SWM_SHUTDOWN, parameter "wiscr") *}
+    SD_ABORT        = 0;
+    SD_PARTIAL      = 1;
+    SD_COMPLETE     = 2;
+
+{* shel_write: mode SWM_ENVIRON, parameter 'wisgr' *}
+    ENVIRON_SIZE    = 0;
+    ENVIRON_CHANGE  = 1;
+    ENVIRON_COPY    = 2;
+
+type
+    PMENU = ^TMENU;
+    TMENU = record
+        mn_tree:        PAESTree;
+        mn_menu:        smallint;
+        mn_item:        smallint;
+        mn_scroll:      smallint;
+        mn_keystate:    smallint;
+    end;
+
+    PMN_SET = ^TMN_SET;
+    TMN_SET = record
+        Display:        LongInt;
+        Drag:           LongInt;
+        Delay:          LongInt;
+        Speed:          LongInt;
+        Height:     smallint;
+    end;
+
+{* extended appl_write structure *}
+    PXAESMSG = ^TXAESMSG;
+    TXAESMSG = record
+        dst_apid: smallint;
+        unique_flg: smallint;
+        attached_mem: Pointer;
+        msgbuf: Psmallint;
+    end;
+
+{* tail for default shell *}
+    PSHELTAIL = ^TSHELTAIL;
+    TSHELTAIL = record
+        dummy: smallint;
+        magic: longint;
+        isfirst: smallint;
+        lasterr: longint;
+        wasgr: smallint;
+    end;
+
+{* shel_write alternative structure for sh_wpcmd parameter *}
+    PSHELW = ^TSHELW;
+    TSHELW = record
+        newcmd: Pchar;
+        psetlimit: longint;
+        prenice: longint;
+        defdir: pchar;
+        env: pointer;
+        case boolean of
+          false: (uid, gid: smallint;);
+          true: (flags: longint;);
+    end;
+

+ 643 - 0
packages/tosunits/src/gem.pas

@@ -0,0 +1,643 @@
+{
+    Copyright (c) 2022 by Free Pascal development team
+
+    GEM interface unit for Atari TOS
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+{
+    This is used for Pure-Pascal compatibility. For newly written code,
+    consider using the aes/vdi units instead.
+}
+
+{$MODE FPC}
+{$MODESWITCH OUT+}
+{$PACKRECORDS 2}
+
+unit gem;
+
+interface
+
+uses aes, vdi, gemcommon;
+
+const
+        LWhite          = DWHITE;
+        LBlack          = DBLACK;
+        LRed            = DRED;
+        LGreen          = DGREEN;
+        LBlue           = DBLUE;
+        LCyan           = DCYAN;
+        LYellow         = DYELLOW;
+        LMagenta        = DMAGENTA;
+
+const
+        BackSpace       = $0E08;
+        Tab             = $0F09;
+        S_Delete        = $537F;
+        S_Insert        = $5200;
+        Shift_Ins       = $5230;
+        Return          = $1C0D;
+        Enter           = $720D;
+        Undo            = $6100;
+        Help            = $6200;
+        Home            = $4700;
+        Cur_Up          = $4800;
+        Cur_Down        = $5000;
+        Cur_Left        = $4B00;
+        Cur_Right       = $4D00;
+        Shift_Home      = $4737;
+        Shift_CU        = $4838;
+        Shift_CD        = $5032;
+        Shift_CL        = $4B34;
+        Shift_CR        = $4D36;
+        Esc             = $011B;
+        Ctrl_A          = $1E01;
+        Ctrl_B          = $3002;
+        Ctrl_C          = $2E03;
+        Ctrl_D          = $2004;
+        Ctrl_E          = $1205;
+        Ctrl_F          = $2106;
+        Ctrl_G          = $2207;
+        Ctrl_H          = $2308;
+        Ctrl_I          = $1709;
+        Ctrl_J          = $240A;
+        Ctrl_K          = $250B;
+        Ctrl_L          = $260C;
+        Ctrl_M          = $320D;
+        Ctrl_N          = $310E;
+        Ctrl_O          = $180F;
+        Ctrl_P          = $1910;
+        Ctrl_Q          = $1011;
+        Ctrl_R          = $1312;
+        Ctrl_S          = $1F13;
+        Ctrl_T          = $1414;
+        Ctrl_U          = $1615;
+        Ctrl_V          = $2F16;
+        Ctrl_W          = $1117;
+        Ctrl_X          = $2D18;
+        Ctrl_Y          = $2C19;
+        Ctrl_Z          = $151A;
+        Ctrl_1          = $0211;
+        Ctrl_2          = $0300;
+        Ctrl_3          = $0413;
+        Ctrl_4          = $0514;
+        Ctrl_5          = $0615;
+        Ctrl_6          = $071E;
+        Ctrl_7          = $0817;
+        Ctrl_8          = $0918;
+        Ctrl_9          = $0A19;
+        Ctrl_0          = $0B10;
+        Alt_A           = $1E00;
+        Alt_B           = $3000;
+        Alt_C           = $2E00;
+        Alt_D           = $2000;
+        Alt_E           = $1200;
+        Alt_F           = $2100;
+        Alt_G           = $2200;
+        Alt_H           = $2300;
+        Alt_I           = $1700;
+        Alt_J           = $2400;
+        Alt_K           = $2500;
+        Alt_L           = $2600;
+        Alt_M           = $3200;
+        Alt_N           = $3100;
+        Alt_O           = $1800;
+        Alt_P           = $1900;
+        Alt_Q           = $1000;
+        Alt_R           = $1300;
+        Alt_S           = $1F00;
+        Alt_T           = $1400;
+        Alt_U           = $1600;
+        Alt_V           = $2F00;
+        Alt_W           = $1100;
+        Alt_X           = $2D00;
+        Alt_Y           = $2C00;
+        Alt_Z           = $1500;
+        Alt_1           = $7800;
+        Alt_2           = $7900;
+        Alt_3           = $7A00;
+        Alt_4           = $7B00;
+        Alt_5           = $7C00;
+        Alt_6           = $7D00;
+        Alt_7           = $7E00;
+        Alt_8           = $7F00;
+        Alt_9           = $8000;
+        Alt_0           = $8100;
+        F1              = $3B00;
+        F2              = $3C00;
+        F3              = $3D00;
+        F4              = $3E00;
+        F5              = $3F00;
+        F6              = $4000;
+        F7              = $4100;
+        F8              = $4200;
+        F9              = $4300;
+        F10             = $4400;
+        Shift_F1        = $5400;
+        Shift_F2        = $5500;
+        Shift_F3        = $5600;
+        Shift_F4        = $5700;
+        Shift_F5        = $5800;
+        Shift_F6        = $5900;
+        Shift_F7        = $5A00;
+        Shift_F8        = $5B00;
+        Shift_F9        = $5C00;
+        Shift_F10       = $5D00;
+
+        Ctrl_AE         = $2804;
+        Ctrl_OE         = $2714;
+        Ctrl_UE         = $1A01;
+        Alt_AE          = $285D;
+        Alt_OE          = $275B;
+        Alt_UE          = $1A40;
+        SH_Alt_AE       = $287D;
+        SH_Alt_OE       = $277B;
+        SH_Alt_UE       = $1A5C;
+
+
+
+type
+  control_ARRAY	= ARRAY[0..4] of smallint;
+  AESPBPtr = ^AESPB;
+  AESPB = record
+    control: ^control_ARRAY;
+    global: PAESGlobal;
+    intin: PAESIntIn;
+    intout: PAESIntOut;
+    addrin: PAESAddrIn;
+    addrout: PAESAddrOut;
+  end;
+    AESOBJECT = TAESOBJECT;
+    AESOBJECTPtr = ^TAESOBJECT;
+    VDIPB = TVDIPB;
+    VDIPBPtr = ^VDIPB;
+    TEDINFO = TTEDINFO;
+    TEDINFOPtr = ^TEDINFO;
+    ICONBLK = TICONBLK;
+    ICONBLKPtr = ^ICONBLK;
+    CICON = TCICON;
+    CICONPtr = ^CICON;
+    CICONBLK = TCICONBLK;
+    CICONBLKPtr = ^CICONBLK;
+    BITBLK = TBITBLK;
+    BITBLKPtr = ^BITBLK;
+    MFORM = TMFORM;
+    MFORMPtr = ^MFORM;
+    USERBLK = TUSERBLK;
+    USERBLKPtr = ^USERBLK;
+    OBSPEC = TOBSPEC;
+    OBSPECPtr = ^OBSPEC;
+    PARMBLK = TPARMBLK;
+    PARMBLKPtr = ^PARMBLK;
+    AESTree = TAESTree;
+    AESTreePtr = ^AESTree;
+    RSHDR = TRSHDR;
+    RSHDRPtr = ^RSHDR;
+    EVENT = TEVENT;
+    EVENTPtr = ^EVENT;
+    MENU = TMENU;
+    MENUPtr = ^MENU;
+    MN_SET = TMN_SET;
+    MN_SETPtr = ^MN_SET;
+    FONT_HDR = TFONT_HDR;
+    FONT_HDRPtr = ^FONT_HDR;
+    MFDB = vdi.TMFDB;
+    MFDBPtr = ^MFDB;
+
+    global_ARRAY    = TAESGlobal;
+
+    workout_ARRAY   = ARRAY[0..56] of smallint;
+    workin_ARRAY    = ARRAY[0..10] of smallint;
+    intin_ARRAY     = TVDIIntIn;
+    intout_ARRAY    = TVDIIntOut;
+    ptsin_ARRAY     = TVDIPtsIn;
+    ptsout_ARRAY    = TVDIPtsOut;
+
+(*
+ * PurePascal has all the AES parameter arrays exposed.
+ * We don't want to do that, because various arrays are
+ * implementation specific. For Compatibility we
+ * need to make the global array available however;
+ *)
+type
+        AES_block = record
+            global  : TAESGlobal;
+        end;
+
+var Gem_pb: AES_block; external name 'aes_global';
+
+(*
+ * we also need to make the parameter block available,
+ * so applications can define missing functions
+ * that are not yet implemented here.
+ *)
+
+var
+    AES_pb: AESPB; external name 'aespb';
+    VDI_pb: TVDIPB; external name 'vdipb';
+
+{*
+ * overloaded AES functions that take an AESTreePtr as parameter
+ *}
+function menu_bar(me_btree: AESTreePtr; me_bshow: smallint): smallint; overload;
+function menu_icheck(me_ctree: AESTreePtr; me_citem, me_ccheck: smallint): smallint; overload;
+function menu_ienable(me_etree: AESTreePtr; me_eitem, me_eenable: smallint): smallint; overload;
+function menu_tnormal(me_ntree: AESTreePtr; me_ntitle, me_nnormal: smallint): smallint; overload;
+function menu_text(me_ttree: AESTreePtr; me_titem: smallint; me_ttext: String): smallint; overload;
+function menu_attach(me_flag: smallint; me_tree: AESTreePtr; me_item: smallint; me_mdata: PMENU): smallint; overload;
+function menu_istart(me_flag: smallint; me_tree: AESTreePtr; me_imenu, me_item: smallint): smallint; overload;
+
+function objc_add(ob_atree: AESTreePtr;	ob_aparent, ob_achild: smallint): smallint; overload;
+function objc_delete(ob_dltree: AESTreePtr; ob_dlobject: smallint): smallint; overload;
+function objc_draw(ob_drtree: AESTreePtr;
+	ob_drstartob, ob_drdepth,
+	ob_drxclip, ob_dryclip,
+	ob_drwclip, ob_drhclip: smallint): smallint; overload;
+function objc_find(ob_ftree: AESTreePtr;
+	ob_fstartob, ob_fdepth,
+	ob_fmx, ob_fmy: smallint): smallint; overload;
+function objc_offset(ob_oftree: AESTreePtr;
+	ob_ofobject: smallint;
+	out ob_ofxoff, ob_ofyoff: smallint): smallint; overload;
+function objc_order(ob_ortree: AESTreePtr;
+	ob_orobject, ob_ornewpos: smallint): smallint; overload;
+function objc_edit(ob_edtree: AESTreePtr;
+	ob_edobject, ob_edchar: smallint;
+	var ob_edidx: smallint;
+	ob_edkind: smallint): smallint; overload;
+function objc_change(ob_ctree: AESTreePtr;
+	ob_cobject, ob_cresvd,
+	ob_xclip, ob_yclip,
+	ob_wclip, ob_hclip,
+	ob_cnewstate,
+	ob_credraw: smallint): smallint; overload;
+
+function form_do(fo_dotree: AESTreePtr;	fo_dostartob: smallint): smallint; overload;
+function form_center(fo_ctree: AESTreePtr; out fo_cx, fo_cy, fo_cw, fo_ch: smallint): smallint; overload;
+function form_keybd(fo_ktree: AESTreePtr;
+	fo_kobject, fo_kobnext, fo_kchar: smallint;
+	out fo_knxtobject, fo_knxtchar: smallint): smallint; overload;
+function form_button(fo_btree: AESTreePtr; fo_bobject, fo_bclicks: smallint;
+	out fo_bnxtobj: smallint): smallint; overload;
+
+function rsrc_obfix(re_obtree: AESTreePtr; re_oobject: smallint): smallint; overload;
+
+{*
+ * overloaded VDI functions
+ *}
+procedure v_opnwk(const WorkIn: workin_Array; out handle: smallint; out WorkOut: workout_Array); overload;
+procedure v_opnvwk(const WorkIn: workin_Array; var handle: smallint; out WorkOut: workout_Array); overload;
+procedure vq_extnd(handle, owflag: smallint; out WorkOut: workout_Array); overload;
+procedure vro_cpyfm(handle, vr_mode: smallint; const pxyarray: ARRAY_8; const psrcMFDB, pdesMFDB: TMFDB); overload;
+procedure vrt_cpyfm(handle, vr_mode: smallint; const pxyarray: ARRAY_8; const psrcMFDB, pdesMFDB: TMFDB; const color_index: ARRAY_2); overload;
+procedure vqt_extent(handle: smallint; const calcString: String; out extent: ARRAY_8); overload;
+procedure vqt_f_extent(handle: smallint; const str: String; out extent: ARRAY_8);
+
+{*
+ * Utility functions
+ *}
+procedure SetFreeString(tree: PAESTree; obj: smallint; const str: String);
+procedure GetFreeString(tree: PAESTree; obj: smallint; out str: String);
+procedure SetPtext(tree: PAESTree; obj: smallint; const str: String);
+procedure GetPtext(tree: PAESTree; obj: smallint; out str: String);
+procedure SetPtmplt(tree: PAESTree; obj: smallint; const str: String);
+procedure GetPtmplt(tree: PAESTree; obj: smallint; out str :String);
+procedure SetPvalid(tree: PAESTree; obj: smallint; const str: String);
+procedure GetPvalid(tree: PAESTree; obj: smallint; out str: String);
+procedure SetIcontext(tree: PAESTree; obj: smallint; const str: String);
+procedure GetIcontext(tree: PAESTree; obj: smallint; out str: String);
+procedure WindSetTitle(handle: smallint; const str: String; var buf: String);
+procedure WindSetInfo(handle: smallint; const str: String; var buf: String);
+procedure WindSetNewDesk(tree: PAESTree; firstObj: smallint);
+
+implementation
+
+type
+  aesstr = array[0..255] of char;
+
+
+function string_to_vdi(const src: String; dst: psmallint): smallint;
+var
+  i, len: longint;
+begin
+  len:=length(src);
+  for i:=0 to len-1 do
+    dst[i]:=byte(src[i + 1]);
+
+  string_to_vdi:=len;
+end;
+
+
+procedure v_opnwk(const WorkIn: workin_Array; out handle: smallint; out WorkOut: workout_Array);
+begin
+  vdi.v_opnwk(@workin[0], @handle, @workout[0]);
+end;
+
+
+procedure v_opnvwk(const WorkIn: workin_Array; var handle: smallint; out WorkOut: workout_Array);
+begin
+  vdi.v_opnvwk(@workin[0], @handle, @workout[0]);
+end;
+
+
+procedure vq_extnd(handle, owflag: smallint; out WorkOut: workout_Array);
+begin
+  vdi.vq_extnd(handle, owflag, @workout[0]);
+end;
+
+procedure vro_cpyfm(handle, vr_mode: smallint; const pxyarray: ARRAY_8; const psrcMFDB, pdesMFDB: TMFDB);
+begin
+  vdi.vro_cpyfm(handle, vr_mode, @pxyarray, @psrcMFDB, @pdesMFDB);
+end;
+
+procedure vrt_cpyfm(handle, vr_mode: smallint; const pxyarray: ARRAY_8; const psrcMFDB, pdesMFDB: TMFDB; const color_index: ARRAY_2);
+begin
+  vdi.vrt_cpyfm(handle, vr_mode, @pxyarray, @psrcMFDB, @pdesMFDB, @color_index);
+end;
+
+
+procedure vqt_extent(handle: smallint; const calcString: String; out extent: ARRAY_8);
+var len: smallint;
+begin
+  len:=string_to_vdi(calcstring, @vdi_pb.intin^[0]);
+  vdi_pb.control^[0]:=116;
+  vdi_pb.control^[1]:=0;
+  vdi_pb.control^[3]:=len;
+  vdi_pb.control^[5]:=0;
+  vdi_pb.control^[6]:=handle;
+
+  vdi.vdi;
+
+  extent[0]:=vdi_pb.ptsout^[0];
+  extent[1]:=vdi_pb.ptsout^[1];
+  extent[2]:=vdi_pb.ptsout^[2];
+  extent[3]:=vdi_pb.ptsout^[3];
+  extent[4]:=vdi_pb.ptsout^[4];
+  extent[5]:=vdi_pb.ptsout^[5];
+  extent[6]:=vdi_pb.ptsout^[6];
+  extent[7]:=vdi_pb.ptsout^[7];
+end;
+
+procedure vqt_f_extent(handle: smallint; const str: String;
+                       out extent: ARRAY_8);
+var len: longint;
+begin
+  len:=string_to_vdi(str, @vdi_pb.intin^[0]);
+  vdi_pb.control^[0]:=240;
+  vdi_pb.control^[1]:=0;
+  vdi_pb.control^[3]:=len;
+  vdi_pb.control^[5]:=0;
+  vdi_pb.control^[6]:=handle;
+
+  vdi.vdi;
+
+  extent[0]:=vdi_pb.ptsout^[0];
+  extent[1]:=vdi_pb.ptsout^[1];
+  extent[2]:=vdi_pb.ptsout^[2];
+  extent[3]:=vdi_pb.ptsout^[3];
+  extent[4]:=vdi_pb.ptsout^[4];
+  extent[5]:=vdi_pb.ptsout^[5];
+  extent[6]:=vdi_pb.ptsout^[6];
+  extent[7]:=vdi_pb.ptsout^[7];
+end;
+
+
+function menu_bar(me_btree: AESTreePtr; me_bshow: smallint): smallint;
+begin
+	menu_bar := aes.menu_bar(@me_btree[0], me_bshow);
+end;
+
+function menu_icheck(me_ctree: AESTreePtr; me_citem, me_ccheck: smallint): smallint;
+begin
+	menu_icheck := aes.menu_icheck(@me_ctree[0], me_citem, me_ccheck);
+end;
+
+function menu_ienable(me_etree: AESTreePtr; me_eitem, me_eenable: smallint): smallint;
+begin
+	menu_ienable := aes.menu_ienable(@me_etree[0], me_eitem, me_eenable);
+end;
+
+function menu_tnormal(me_ntree: AESTreePtr; me_ntitle, me_nnormal: smallint): smallint;
+begin
+	menu_tnormal := aes.menu_tnormal(@me_ntree[0], me_ntitle, me_nnormal);
+end;
+
+function menu_text(me_ttree: AESTreePtr; me_titem: smallint; me_ttext: String): smallint;
+var s: aesstr;
+begin
+  menu_text:=aes.menu_text(@me_ttree[0], me_titem, @s);
+end;
+
+function menu_attach(me_flag: smallint; me_tree: AESTreePtr; me_item: smallint; me_mdata: PMENU): smallint;
+begin
+  menu_attach:=aes.menu_attach(me_flag, @me_tree[0], me_item, me_mdata);
+end;
+
+function menu_istart(me_flag: smallint; me_tree: AESTreePtr; me_imenu, me_item: smallint): smallint; overload;
+begin
+  menu_istart:=aes.menu_istart(me_flag, @me_tree[0], me_item, me_item);
+end;
+
+
+function objc_add(ob_atree: AESTreePtr;	ob_aparent, ob_achild: smallint): smallint;
+begin
+  objc_add:=aes.objc_add(@ob_atree[0], ob_aparent, ob_achild);
+end;
+
+function objc_delete(ob_dltree: AESTreePtr; ob_dlobject: smallint): smallint;
+begin
+  objc_delete:=aes.objc_delete(@ob_dltree[0], ob_dlobject);
+end;
+
+function objc_draw(ob_drtree: AESTreePtr;
+	ob_drstartob, ob_drdepth,
+	ob_drxclip, ob_dryclip,
+	ob_drwclip, ob_drhclip: smallint): smallint;
+begin
+  objc_draw:=aes.objc_draw(@ob_drtree[0], ob_drstartob, ob_drdepth, ob_drxclip, ob_dryclip, ob_drwclip, ob_drhclip);
+end;
+
+function objc_find(ob_ftree: AESTreePtr;
+	ob_fstartob, ob_fdepth,
+	ob_fmx, ob_fmy: smallint): smallint;
+begin
+  objc_find:=aes.objc_find(@ob_ftree[0], ob_fstartob, ob_fdepth, ob_fmx, ob_fmy);
+end;
+
+function objc_offset(ob_oftree: AESTreePtr;
+	ob_ofobject: smallint;
+	out ob_ofxoff, ob_ofyoff: smallint): smallint;
+begin
+  objc_offset:=aes.objc_offset(@ob_oftree[0], ob_ofobject, ob_ofxoff, ob_ofyoff);
+end;
+
+function objc_order(ob_ortree: AESTreePtr;
+	ob_orobject, ob_ornewpos: smallint): smallint;
+begin
+  objc_order:=aes.objc_order(@ob_ortree[0], ob_orobject, ob_ornewpos);
+end;
+
+function objc_edit(ob_edtree: AESTreePtr;
+	ob_edobject, ob_edchar: smallint;
+	var ob_edidx: smallint;
+	ob_edkind: smallint): smallint;
+begin
+  objc_edit:=aes.objc_edit(@ob_edtree[0], ob_edobject, ob_edchar, ob_edidx, ob_edkind);
+end;
+
+function objc_change(ob_ctree: AESTreePtr;
+	ob_cobject, ob_cresvd,
+	ob_xclip, ob_yclip,
+	ob_wclip, ob_hclip,
+	ob_cnewstate,
+	ob_credraw: smallint): smallint;
+begin
+  objc_change:=aes.objc_change(@ob_ctree[0], ob_cobject, ob_cresvd, ob_xclip, ob_yclip, ob_wclip, ob_hclip, ob_cnewstate, ob_credraw);
+end;
+
+function form_do(fo_dotree: AESTreePtr;	fo_dostartob: smallint): smallint;
+begin
+  form_do:=aes.form_do(@fo_dotree[0], fo_dostartob);
+end;
+
+function form_center(fo_ctree: AESTreePtr; out fo_cx, fo_cy, fo_cw, fo_ch: smallint): smallint;
+begin
+  form_center:=aes.form_center(@fo_ctree[0], fo_cx, fo_cy, fo_cw, fo_ch);
+end;
+
+function form_keybd(fo_ktree: AESTreePtr;
+	fo_kobject, fo_kobnext, fo_kchar: smallint;
+	out fo_knxtobject, fo_knxtchar: smallint): smallint;
+begin
+  form_keybd:=aes.form_keybd(@fo_ktree[0], fo_kobject, fo_kobnext, fo_kchar, fo_knxtobject, fo_knxtchar);
+end;
+
+function form_button(fo_btree: AESTreePtr; fo_bobject, fo_bclicks: smallint;
+	out fo_bnxtobj: smallint): smallint;
+begin
+  form_button:=aes.form_button(@fo_btree[0], fo_bobject, fo_bclicks, fo_bnxtobj);
+end;
+
+function rsrc_obfix(re_obtree: AESTreePtr; re_oobject: smallint): smallint;
+begin
+  rsrc_obfix:=aes.rsrc_obfix(@re_obtree[0], re_oobject);
+end;
+
+
+procedure SetFreeString(tree: PAESTree; obj: smallint; const str: String);
+var len: SizeInt;
+    p: pchar;
+begin
+  len:=length(str);
+  p:=tree^[obj].ob_spec.free_string;
+  move(str[1], p^, len);
+  p[len]:=#0;
+end;
+
+procedure GetFreeString(tree: PAESTree; obj: smallint; out str: String);
+begin
+  str := tree^[obj].ob_spec.free_string;
+end;
+
+procedure SetPtext(tree: PAESTree; obj: smallint; const str: String);
+var len: SizeInt;
+    p: pchar;
+begin
+  len:=length(str);
+  p:=tree^[obj].ob_spec.ted_info^.te_ptext;
+  if (len >= tree^[obj].ob_spec.ted_info^.te_txtlen) then
+    len := tree^[obj].ob_spec.ted_info^.te_txtlen-1;
+  move(str[1], p^, len);
+  p[len]:=#0;
+end;
+
+procedure GetPtext(tree: PAESTree; obj: smallint; out str: String);
+begin
+  str := tree^[obj].ob_spec.ted_info^.te_ptext;
+end;
+
+procedure SetPtmplt(tree: PAESTree; obj: smallint; const str: String);
+var len: SizeInt;
+    p: pchar;
+begin
+  len:=length(str);
+  p:=tree^[obj].ob_spec.ted_info^.te_ptmplt;
+  if (len >= tree^[obj].ob_spec.ted_info^.te_tmplen) then
+    len := tree^[obj].ob_spec.ted_info^.te_tmplen-1;
+  move(str[1], p^, len);
+  p[len]:=#0;
+end;
+
+procedure GetPtmplt(tree: PAESTree; obj: smallint; out str: String);
+begin
+  str := tree^[obj].ob_spec.ted_info^.te_ptmplt;
+end;
+
+procedure SetPvalid(tree: PAESTree; obj: smallint; const str: String);
+var len: SizeInt;
+    p: pchar;
+begin
+  len:=length(str);
+  p:=tree^[obj].ob_spec.ted_info^.te_pvalid;
+  move(str[1], p^, len);
+  p[len]:=#0;
+end;
+
+procedure GetPvalid(tree: PAESTree; obj: smallint; out str: String);
+begin
+  str := tree^[obj].ob_spec.ted_info^.te_pvalid;
+end;
+
+procedure SetIcontext(tree: PAESTree; obj: smallint; const str: String);
+var len: SizeInt;
+    p: pchar;
+begin
+  len:=length(str);
+  p:=tree^[obj].ob_spec.icon_blk^.ib_ptext;
+  move(str[1], p^, len);
+  p[len]:=#0;
+end;
+
+procedure GetIcontext(tree: PAESTree; obj: smallint; out str: String);
+begin
+  str := tree^[obj].ob_spec.icon_blk^.ib_ptext;
+end;
+
+procedure WindSetTitle(handle: smallint; const str: String; var buf: String);
+var len: SizeInt;
+    pstr: Pchar;
+begin
+  pstr := @buf[0];
+  len:=length(str);
+  move(str[1], pstr^, len);
+  pstr[len]:=#0;
+  wind_set(handle, WF_NAME, Pointer(pstr));
+end;
+
+procedure WindSetInfo(handle: smallint; const str: String; var buf: String);
+var len: SizeInt;
+    pstr: Pchar;
+begin
+  pstr := @buf[0];
+  len:=length(str);
+  move(str[1], pstr^, len);
+  pstr[len]:=#0;
+  wind_set(handle, WF_INFO, Pointer(pstr));
+end;
+
+procedure WindSetNewDesk(tree: PAESTree; firstObj: smallint);
+begin
+{$PUSH}
+{$WARN 4055 OFF} { Conversion between ordinals and pointers is not portable }
+  wind_set(0, WF_NEWDESK, hi(ptruint(tree)), lo(ptruint(tree)), firstObj, 0);
+{$POP}
+end;
+
+end.

+ 46 - 0
packages/tosunits/src/gemcommon.pas

@@ -0,0 +1,46 @@
+{
+    Copyright (c) 2022 by Free Pascal development team
+
+    GEM interface unit for Atari TOS
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+{
+    Shared types between aes/vdi/gem.
+    Only type declarations should go here.
+}
+
+{$MODE FPC}
+{$MODESWITCH OUT+}
+{$PACKRECORDS 2}
+
+unit gemcommon;
+
+interface
+
+type
+    ARRAY_8     = ARRAY[0..7] of smallint;
+
+{ AES/VDI mouse form structure }
+type
+  PMFORM = ^TMFORM;
+  TMFORM = record
+    mf_xhot: smallint;       {* X-position hot-spot *}
+    mf_yhot: smallint;       {* Y-position hot-spot *}
+    mf_nplanes: smallint;    {* Number of planes    *}
+    mf_fg: smallint;         {* Mask colour         *}
+    mf_bg: smallint;         {* Pointer colour      *}
+    mf_mask: array[0..15] of smallint;   {* Mask form           *}
+    mf_data: array[0..15] of smallint;   {* Pointer form        *}
+  end;
+
+implementation
+
+end.

+ 1 - 0
packages/tosunits/src/gemdos.pas

@@ -13,6 +13,7 @@
  **********************************************************************}
  **********************************************************************}
 
 
 {$PACKRECORDS 2}
 {$PACKRECORDS 2}
+{$MODESWITCH OUT+}
 unit gemdos;
 unit gemdos;
 
 
 interface
 interface

+ 3 - 2
packages/tosunits/src/metados.pas

@@ -13,6 +13,7 @@
  **********************************************************************}
  **********************************************************************}
 
 
 {$PACKRECORDS 2}
 {$PACKRECORDS 2}
+{$MODESWITCH OUT+}
 unit metados;
 unit metados;
 
 
 interface
 interface
@@ -42,8 +43,8 @@ type
   end;
   end;
 
 
 
 
-procedure xbios_Metainit(var buffer: TMETAINFO); syscall 14 48;
-function xbios_Metaopen(drive: smallint; var buffer: TMETA_DRVINFO): LongInt; syscall 14 49;
+procedure xbios_Metainit(out buffer: TMETAINFO); syscall 14 48;
+function xbios_Metaopen(drive: smallint; out buffer: TMETA_DRVINFO): LongInt; syscall 14 49;
 function xbios_Metaclose(drive: smallint): LongInt; syscall 14 50;
 function xbios_Metaclose(drive: smallint): LongInt; syscall 14 50;
 function xbios_Metaread(drive: smallint; buffer: Pointer; blockno: LongInt; count: smallint): LongInt; syscall 14 51;
 function xbios_Metaread(drive: smallint; buffer: Pointer; blockno: LongInt; count: smallint): LongInt; syscall 14 51;
 function xbios_Metawrite(drive: smallint; buffer: Pointer; blockno: LongInt; count: smallint): LongInt; syscall 14 52;
 function xbios_Metawrite(drive: smallint; buffer: Pointer; blockno: LongInt; count: smallint): LongInt; syscall 14 52;

+ 246 - 0
packages/tosunits/src/nf_ops.pas

@@ -0,0 +1,246 @@
+{
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 2022 Thorsten Otto
+
+    NatFeats interface unit for Atari TOS
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+{$X+}
+{$I-}
+{$Q-}
+{$R-}
+{$S-}
+{$B-}
+
+unit NF_OPS;
+
+interface
+
+const
+    NF_ID_NAME      : pchar = 'NF_NAME';
+    NF_ID_VERSION   : pchar = 'NF_VERSION';
+    NF_ID_STDERR    : pchar = 'NF_STDERR';
+    NF_ID_SHUTDOWN  : pchar = 'NF_SHUTDOWN';
+    NF_ID_EXIT      : pchar = 'NF_EXIT';
+    NF_ID_DEBUG     : pchar = 'DEBUGPRINTF';
+    NF_ID_ETHERNET  : pchar = 'ETHERNET';
+    NF_ID_HOSTFS    : pchar = 'HOSTFS';
+    NF_ID_AUDIO     : pchar = 'AUDIO';
+    NF_ID_BOOTSTRAP : pchar = 'BOOTSTRAP';
+    NF_ID_CDROM     : pchar = 'CDROM';
+    NF_ID_CLIPBRD   : pchar = 'CLIPBRD';
+    NF_ID_JPEG      : pchar = 'JPEG';
+    NF_ID_OSMESA    : pchar = 'OSMESA';
+    NF_ID_PCI       : pchar = 'PCI';
+    NF_ID_FVDI      : pchar = 'fVDI';
+    NF_ID_USBHOST   : pchar = 'USBHOST';
+    NF_ID_XHDI      : pchar = 'XHDI';
+    NF_ID_SCSI      : pchar = 'NF_SCSIDRV';
+    NF_ID_HOSTEXEC  : pchar = 'HOSTEXEC';
+    NF_ID_CONFIG    : pchar = 'NF_CONFIG';
+
+(*
+ * return the NF id to use for feature_name,
+ *  or zero when not available.
+ *)
+function nf_get_id(feature_name: pchar): longint;
+
+(*
+ * return the version of the NatFeat implementation,
+ *  or zero when not available.
+ *)
+function nf_version: longint;
+
+(*
+ * return the name of the NatFeat implementor,
+ *  or NULL when not available.
+ *)
+procedure nf_get_name(buf: Pchar; bufsize: longint);
+
+(*
+ * return the full name of the NatFeat implementor,
+ *  or NULL when not available.
+ *)
+procedure nf_get_fullname(buf: Pchar; bufsize: longint);
+
+(*
+ * Write a string to the host's terminal.
+ * returns TRUE when available, FALSE otherwise.
+ *)
+function nf_debug(const s: string): boolean;
+
+(*
+ * Shutdown the emulator.
+ * May only be called from Supervisor.
+ *)
+function nf_shutdown(mode: integer): longint;
+
+(*
+ * Shutdown the emulator.
+ * May be called from user mode.
+ *)
+function nf_exit(exitcode: integer): longint;
+
+
+implementation
+
+uses
+    xbios;
+
+const
+    NATFEAT_ID = $7300;
+    NATFEAT_CALL = $7301;
+
+var
+    nf_available: boolean;
+    nf_inited: boolean;
+    nf_stderr: longint;
+
+type
+   Tnf_id = function(id: Pchar): longint; cdecl;
+   Tnf_call = function(id: longint): longint; cdecl; varargs;
+
+var cnf_call: Tnf_call;
+
+var ps: array[0..255] of char;
+
+const nf_id_opcodes: array[0..1] of word = (NATFEAT_ID, $4e75);
+      nf_call_opcodes: array[0..1] of word = (NATFEAT_CALL, $4e75);
+
+function nf_id(id: Pchar): longint;
+var cnf_id: Tnf_id;
+begin
+  cnf_id := Tnf_id(@nf_id_opcodes);
+  nf_id := cnf_id(id);
+end;
+
+
+const nf_version_str: array[0..11] of char = 'NF_VERSION';
+
+function nf_detect: longint; assembler; nostackframe;
+asm
+{$IFDEF CPUCFV4E}
+ (*
+  * on ColdFire, the NATFEAT_ID opcode is actually
+  * "mvs.b d0,d1".
+  * But since there is no emulator that emulates a ColdFire,
+  * this feature isn't available.
+  *)
+  moveq #0,d0
+{$ELSE}
+  pea    nf_version_str
+  moveq  #0,d0      (* assume no NatFeats available *)
+  move.l d0,-(sp)
+  lea    @nf_illegal,a1
+  move.l $0010,a0   (* illegal instruction vector *)
+  move.l a1,$0010
+  move.l sp,a1      (* save the ssp *)
+
+  nop               (* flush pipelines (for 68040+) *)
+
+  dc.w   NATFEAT_ID (* Jump to NATFEAT_ID *)
+  tst.l  d0
+  beq.s  @nf_illegal
+  moveq  #1,d0      (* NatFeats detected *)
+  move.l d0,(sp)
+
+@nf_illegal:
+  move.l a1,sp
+  move.l a0,$0010
+  nop               (* flush pipelines (for 68040+) *)
+  move.l (sp)+,d0
+  addq.l #4,sp      (* pop nf_version argument *)
+{$ENDIF}
+end;
+
+function nf_init: boolean;
+var ret: longint;
+begin
+  if not nf_inited then
+    begin
+      ret := xbios_supexec(@nf_detect);
+      nf_available := ret <> 0;
+      nf_inited := true;
+      cnf_call := Tnf_call(@nf_call_opcodes);
+    end;
+  nf_init := nf_available;
+end;
+
+
+function nf_get_id(feature_name: pchar): longint;
+begin
+  nf_get_id := 0;
+  if nf_init then
+    nf_get_id := nf_id(feature_name);
+end;
+
+function nf_version: longint;
+var id: longint;
+begin
+  nf_version := 0;
+  id := nf_get_id(NF_ID_VERSION);
+  if id <> 0 then
+    nf_version := cnf_call(id);
+end;
+
+procedure nf_get_name(buf: Pchar; bufsize: longint);
+var id: longint;
+begin
+  id := nf_get_id(NF_ID_NAME);
+  if id <> 0 then
+    cnf_call(id or 0, buf, bufsize)
+  else
+    buf^ := #0;
+end;
+
+procedure nf_get_fullname(buf: Pchar; bufsize: longint);
+var id: longint;
+begin
+  id := nf_get_id(NF_ID_NAME);
+  if id <> 0 then
+    cnf_call(id or 1, buf, bufsize)
+  else
+    buf^ := #0;
+end;
+
+function nf_debug(const s: string): boolean;
+begin
+  ps := s;
+  nf_debug := false;
+  if nf_stderr = 0 then
+    nf_stderr := nf_get_id(NF_ID_STDERR);
+  if nf_stderr <> 0 then
+    begin
+      cnf_call(nf_stderr, Addr(ps[0]));
+      nf_debug := true;
+    end;
+end;
+
+function nf_shutdown(mode: integer): longint;
+var id: longint;
+begin
+  nf_shutdown := 0;
+  id := nf_get_id(NF_ID_SHUTDOWN);
+  if id <> 0 then
+    nf_shutdown := cnf_call(id or mode);
+end;
+
+function nf_exit(exitcode: integer): longint;
+var id: longint;
+begin
+  nf_exit := 0;
+  id := nf_get_id(NF_ID_EXIT);
+  if id <> 0 then
+    nf_exit := cnf_call(id or 0, longint(exitcode));
+end;
+
+begin
+end.

+ 43 - 23
packages/tosunits/src/tos.pas

@@ -18,13 +18,14 @@
 }
 }
 
 
 {$MODE FPC}
 {$MODE FPC}
+{$MODESWITCH OUT+}
 {$LONGSTRINGS OFF} { this unit always uses shortstrings }
 {$LONGSTRINGS OFF} { this unit always uses shortstrings }
 {$PACKRECORDS 2}
 {$PACKRECORDS 2}
 unit tos;
 unit tos;
 
 
 interface
 interface
 
 
-uses gemdos, xbios, bios;
+uses gemdos, xbios, bios, metados;
 
 
 const
 const
     FO_READ     = 0;
     FO_READ     = 0;
@@ -85,11 +86,19 @@ type
         d_fname :           String[12];
         d_fname :           String[12];
     end;
     end;
 
 
+    LongIntFunc = xbios.TLongIntFunc;
+
+    METAINFO = metados.TMETAINFO;
+
+{ TOS program need this exported }
+var
+    basepage: PPD; external name '__base';
+
 (* ++++++++++++++++++++++++++++++++++++++++ *)
 (* ++++++++++++++++++++++++++++++++++++++++ *)
 (*                  BIOS                    *)
 (*                  BIOS                    *)
 (* ++++++++++++++++++++++++++++++++++++++++ *)
 (* ++++++++++++++++++++++++++++++++++++++++ *)
 
 
-procedure Getmpb(var p_mpb: TMPB); syscall 13 0;
+procedure Getmpb(out p_mpb: TMPB); syscall 13 0;
 function Bconstat(dev: smallint): smallint; syscall 13 1;
 function Bconstat(dev: smallint): smallint; syscall 13 1;
 function Bconin(dev: smallint): LongInt; syscall 13 2;
 function Bconin(dev: smallint): LongInt; syscall 13 2;
 procedure Bconout(dev, c: smallint); syscall 13 3;
 procedure Bconout(dev, c: smallint); syscall 13 3;
@@ -145,7 +154,7 @@ function Kbdvbase: PKBDVECS; syscall 14 34;
 function Kbrate(initial, speed: smallint): smallint; syscall 14 35;
 function Kbrate(initial, speed: smallint): smallint; syscall 14 35;
 procedure Prtblk(var defptr: TPBDEF); syscall 14 36;
 procedure Prtblk(var defptr: TPBDEF); syscall 14 36;
 procedure vsync; syscall 14 37;
 procedure vsync; syscall 14 37;
-function Supexec(codeptr: TLongIntFunc): LongInt; syscall 14 38;
+function Supexec(codeptr: LongIntFunc): LongInt; syscall 14 38;
 procedure Puntaes; syscall 14 39;
 procedure Puntaes; syscall 14 39;
 function Floprate(drive, seekrate: smallint): smallint; syscall 14 41;
 function Floprate(drive, seekrate: smallint): smallint; syscall 14 41;
 function DMAread(sector: LongInt; count: smallint; buffer: Pointer; devno: smallint): LongInt; syscall 14 42;
 function DMAread(sector: LongInt; count: smallint; buffer: Pointer; devno: smallint): LongInt; syscall 14 42;
@@ -168,19 +177,19 @@ function mon_type: smallint; syscall 14 89;
 procedure VsetSync(flag: smallint); syscall 14 90;
 procedure VsetSync(flag: smallint); syscall 14 90;
 function VgetSize(mode: smallint): LongInt; syscall 14 91;
 function VgetSize(mode: smallint): LongInt; syscall 14 91;
 procedure VsetRGB(index, count: smallint; xrgbArray: Array of TRGB); syscall 14 93;
 procedure VsetRGB(index, count: smallint; xrgbArray: Array of TRGB); syscall 14 93;
-procedure VgetRGB(index, count: smallint; var xrgbArray: Array of TRGB); syscall 14 94;
+procedure VgetRGB(index, count: smallint; out xrgbArray: Array of TRGB); syscall 14 94;
 function Validmode(mode: smallint): smallint; syscall 14 95;
 function Validmode(mode: smallint): smallint; syscall 14 95;
 procedure Dsp_DoBlock(data_in: Pointer; size_in: LongInt; data_out: Pointer; size_out: LongInt); syscall 14 96;
 procedure Dsp_DoBlock(data_in: Pointer; size_in: LongInt; data_out: Pointer; size_out: LongInt); syscall 14 96;
 procedure Dsp_BlkHandShake(data_in: Pointer; size_in: LongInt; data_out: Pointer; size_out: LongInt); syscall 14 97;
 procedure Dsp_BlkHandShake(data_in: Pointer; size_in: LongInt; data_out: Pointer; size_out: LongInt); syscall 14 97;
 procedure Dsp_BlkUnpacked(data_in: Pointer; size_in: LongInt; data_out: Pointer; size_out: LongInt); syscall 14 98;
 procedure Dsp_BlkUnpacked(data_in: Pointer; size_in: LongInt; data_out: Pointer; size_out: LongInt); syscall 14 98;
-procedure Dsp_InStream(data_in: Pointer; block_size, num_blocks: LongInt; var blocks_done: LongInt); syscall 14 99;
-procedure Dsp_OutStream(data_out: Pointer; block_size, num_blocks: LongInt; var blocks_done: LongInt); syscall 14 100;
-procedure Dsp_IOStream(data_in, data_out: Pointer; block_insize, block_outsize, num_blocks: LongInt;var blocks_done: LongInt); syscall 14 101;
+procedure Dsp_InStream(data_in: Pointer; block_size, num_blocks: LongInt; out blocks_done: LongInt); syscall 14 99;
+procedure Dsp_OutStream(data_out: Pointer; block_size, num_blocks: LongInt; out blocks_done: LongInt); syscall 14 100;
+procedure Dsp_IOStream(data_in, data_out: Pointer; block_insize, block_outsize, num_blocks: LongInt; out blocks_done: LongInt); syscall 14 101;
 procedure Dsp_RemoveInterrupts(mask: smallint); syscall 14 102;
 procedure Dsp_RemoveInterrupts(mask: smallint); syscall 14 102;
 function Dsp_GetWordSize: smallint; syscall 14 103;
 function Dsp_GetWordSize: smallint; syscall 14 103;
 function Dsp_Lock: smallint; syscall 14 104;
 function Dsp_Lock: smallint; syscall 14 104;
 procedure Dsp_Unlock; syscall 14 105;
 procedure Dsp_Unlock; syscall 14 105;
-procedure Dsp_Available(var xavailable, yavailable: LongInt); syscall 14 106;
+procedure Dsp_Available(out xavailable, yavailable: LongInt); syscall 14 106;
 function Dsp_Reserve(xreserve, yreserve: LongInt): smallint; syscall 14 107;
 function Dsp_Reserve(xreserve, yreserve: LongInt): smallint; syscall 14 107;
 function Dsp_LoadProg(const filename: String; ability: smallint; buffer: Pointer): smallint;
 function Dsp_LoadProg(const filename: String; ability: smallint; buffer: Pointer): smallint;
 procedure Dsp_ExecProg(codeptr: Pointer; codesize: LongInt; ability: smallint); syscall 14 109;
 procedure Dsp_ExecProg(codeptr: Pointer; codesize: LongInt; ability: smallint); syscall 14 109;
@@ -220,6 +229,16 @@ function buffptr(bptr: Pointer): LongInt; syscall 14 141;
 
 
 procedure VsetMask(ormask, andmask: LongInt; overlay: smallint); syscall 14 150;
 procedure VsetMask(ormask, andmask: LongInt; overlay: smallint); syscall 14 150;
 
 
+procedure Metainit(out buffer: TMETAINFO); syscall 14 48;
+function Metaopen(drive: smallint; out buffer: TMETA_DRVINFO): LongInt; syscall 14 49;
+function Metaclose(drive: smallint): LongInt; syscall 14 50;
+function Metaread(drive: smallint; buffer: Pointer; blockno: LongInt; count: smallint): LongInt; syscall 14 51;
+function Metawrite(drive: smallint; buffer: Pointer; blockno: LongInt; count: smallint): LongInt; syscall 14 52;
+function Metaseek(drive: smallint; dummy, offset: longint): LongInt; syscall 14 53;
+function Metastatus(drive: smallint; buffer: Pointer): LongInt; syscall 14 54;
+function Metaioctl(drive: smallint; magic: LongInt; opcode: smallint; buffer: Pointer): LongInt; syscall 14 55;
+
+
 (* ++++++++++++++++++++++++++++++++++++++++ *)
 (* ++++++++++++++++++++++++++++++++++++++++ *)
 (*                  GEMDOS                  *)
 (*                  GEMDOS                  *)
 (* ++++++++++++++++++++++++++++++++++++++++ *)
 (* ++++++++++++++++++++++++++++++++++++++++ *)
@@ -261,7 +280,7 @@ function sversion: smallint; syscall 1 48;
 procedure ptermres(keepcnt: longint; returncode: smallint); syscall 1 49;
 procedure ptermres(keepcnt: longint; returncode: smallint); syscall 1 49;
 function sconfig(mode: smallint; flags: longint): longint; syscall 1 51;
 function sconfig(mode: smallint; flags: longint): longint; syscall 1 51;
 
 
-function dfree(var buf: TDISKINFO; driveno: smallint): smallint; syscall 1 54;
+function dfree(out buf: TDISKINFO; driveno: smallint): smallint; syscall 1 54;
 
 
 function dcreate(const path: String): longint;
 function dcreate(const path: String): longint;
 function ddelete(const path: String): longint;
 function ddelete(const path: String): longint;
@@ -277,7 +296,7 @@ function fattrib(const filename: String; wflag: smallint; attrib: smallint): sma
 function mxalloc(amount: longint; mode: smallint): pointer; syscall 1 68;
 function mxalloc(amount: longint; mode: smallint): pointer; syscall 1 68;
 function fdup(handle: smallint): smallint; syscall 1 69;
 function fdup(handle: smallint): smallint; syscall 1 69;
 function fforce(stdh: smallint; nonstdh: smallint): smallint; syscall 1 70;
 function fforce(stdh: smallint; nonstdh: smallint): smallint; syscall 1 70;
-function dgetpath(var path: String; driveno: smallint): smallint;
+function dgetpath(out path: String; driveno: smallint): smallint;
 function malloc(number: dword): pointer; syscall 1 72;
 function malloc(number: dword): pointer; syscall 1 72;
 function free(block: pointer): dword; syscall 1 73;
 function free(block: pointer): dword; syscall 1 73;
 function mfree(block: pointer): dword; syscall 1 73;
 function mfree(block: pointer): dword; syscall 1 73;
@@ -294,7 +313,7 @@ procedure fdatime(timeptr: PDOSTIME; handle: smallint; wflag: smallint); syscall
 function Flock(handle, mode: smallint; start, length: LongInt): LongInt; syscall 1 92;
 function Flock(handle, mode: smallint; start, length: LongInt): LongInt; syscall 1 92;
 
 
 function Syield: smallint; syscall 1 255;
 function Syield: smallint; syscall 1 255;
-function Fpipe(var usrh: ARRAY of smallint): smallint; syscall 1 256;
+function Fpipe(out usrh: ARRAY of smallint): smallint; syscall 1 256;
 function Ffchown(fd, uid, gid: smallint): longint; syscall 1 257;
 function Ffchown(fd, uid, gid: smallint): longint; syscall 1 257;
 function Ffchmod(fd: smallint; mode: word): longint; syscall 1 258;
 function Ffchmod(fd: smallint; mode: word): longint; syscall 1 258;
 function Fsync(fd: smallint): longint; syscall 1 259;
 function Fsync(fd: smallint): longint; syscall 1 259;
@@ -322,9 +341,9 @@ function Pusrval(arg: LongInt): LongInt; syscall 1 280;
 function Pdomain(newdom: smallint): smallint; syscall 1 281;
 function Pdomain(newdom: smallint): smallint; syscall 1 281;
 procedure Psigreturn; syscall 1 282;
 procedure Psigreturn; syscall 1 282;
 function Pfork: smallint; syscall 1 283;
 function Pfork: smallint; syscall 1 283;
-function Pwait3(flag: smallint; var rusage: ARRAY of LongInt): LongInt; syscall 1 284;
-function Fselect(timeout: Word; var rfds, wfds, xfds: LongInt): smallint; syscall 1 285;
-function Prusage(var r: ARRAY of LongInt): LongInt; syscall 1 286;
+function Pwait3(flag: smallint; out rusage: ARRAY of LongInt): LongInt; syscall 1 284;
+function Fselect(timeout: Word; out rfds, wfds, xfds: LongInt): smallint; syscall 1 285;
+function Prusage(out r: ARRAY of LongInt): LongInt; syscall 1 286;
 function Psetlimit(lim: smallint; value: LongInt): LongInt; syscall 1 287;
 function Psetlimit(lim: smallint; value: LongInt): LongInt; syscall 1 287;
 function Talarm(secs: LongInt): LongInt; syscall 1 288;
 function Talarm(secs: LongInt): LongInt; syscall 1 288;
 procedure Pause; syscall 1 289;
 procedure Pause; syscall 1 289;
@@ -335,13 +354,13 @@ function Pmsg(mode: smallint; mbox: LongInt; var msg: TMSGTYPE): LongInt; syscal
 function Fmidipipe(pid, inp, outp: smallint): LongInt; syscall 1 294;
 function Fmidipipe(pid, inp, outp: smallint): LongInt; syscall 1 294;
 function Prenice(pid, delta: smallint): smallint; syscall 1 295;
 function Prenice(pid, delta: smallint): smallint; syscall 1 295;
 function Dopendir(const name: String; flag: smallint): LongInt;
 function Dopendir(const name: String; flag: smallint): LongInt;
-function Dreaddir(buflen: smallint; dir: LongInt; var buf: String): LongInt;
+function Dreaddir(buflen: smallint; dir: LongInt; out buf: String): LongInt;
 function Drewinddir(dir: LongInt): LongInt; syscall 1 298;
 function Drewinddir(dir: LongInt): LongInt; syscall 1 298;
 function Dclosedir(dir: LongInt): LongInt; syscall 1 299;
 function Dclosedir(dir: LongInt): LongInt; syscall 1 299;
-function Fxattr(flag: smallint; const name: String; var buf: TXATTR): LongInt;
+function Fxattr(flag: smallint; const name: String; out buf: TXATTR): LongInt;
 function Flink(const oldname: String; const newname: String): LongInt;
 function Flink(const oldname: String; const newname: String): LongInt;
 function Fsymlink(const oldname: String; const newname: String): LongInt;
 function Fsymlink(const oldname: String; const newname: String): LongInt;
-function Freadlink(size: smallint; var buf: String; const name: String): LongInt;
+function Freadlink(size: smallint; out buf: String; const name: String): LongInt;
 function Dcntl(cmd: smallint; const name: String; arg: LongInt): LongInt;
 function Dcntl(cmd: smallint; const name: String; arg: LongInt): LongInt;
 function Fchown(const name: String; uid, gid: smallint): LongInt;
 function Fchown(const name: String; uid, gid: smallint): LongInt;
 function Fchmod(const name: String; mode: smallint): LongInt;
 function Fchmod(const name: String; mode: smallint): LongInt;
@@ -352,12 +371,13 @@ procedure Psigpause(mask: LongInt); syscall 1 310;
 function Psigaction(sig: smallint; act, oact: PSIGACTION): LongInt; syscall 1 311;
 function Psigaction(sig: smallint; act, oact: PSIGACTION): LongInt; syscall 1 311;
 function Pgeteuid: smallint; syscall 1 312;
 function Pgeteuid: smallint; syscall 1 312;
 function Pgetegid: smallint; syscall 1 313;
 function Pgetegid: smallint; syscall 1 313;
-function Pwaitpid(pid, flag: smallint; var rusage: ARRAY of LongInt): LongInt; syscall 1 314;
+function Pwaitpid(pid, flag: smallint; out rusage: ARRAY of LongInt): LongInt; syscall 1 314;
 function Dgetcwd(path: Pchar; drv, size: smallint): LongInt; syscall 1 315;
 function Dgetcwd(path: Pchar; drv, size: smallint): LongInt; syscall 1 315;
 procedure Salert(str: Pchar); syscall 1 316;
 procedure Salert(str: Pchar); syscall 1 316;
 function Tmalarm(time: longint): LongInt; syscall 1 317;
 function Tmalarm(time: longint): LongInt; syscall 1 317;
 { function Psigintr(vec, sig: smallint): LongInt; syscall 1 318; }
 { function Psigintr(vec, sig: smallint): LongInt; syscall 1 318; }
-function Suptime(var uptime: longint; var loadaverage: longint): LongInt; syscall 1 319;
+function Suptime(out uptime: longint; out loadaverage: longint): LongInt; syscall 1 319;
+
 
 
 (* ++++++++++++++++++++++++++++++++++++++++ *)
 (* ++++++++++++++++++++++++++++++++++++++++ *)
 (*              IMPLEMENTATION              *)
 (*              IMPLEMENTATION              *)
@@ -465,7 +485,7 @@ begin
   dsetpath := gemdos_dsetpath(s);
   dsetpath := gemdos_dsetpath(s);
 end;
 end;
 
 
-function dgetpath(var path: String; driveno: smallint): smallint;
+function dgetpath(out path: String; driveno: smallint): smallint;
 var s: array[0..255] of char;
 var s: array[0..255] of char;
 begin
 begin
   Dgetpath := gemdos_dgetpath(s, driveno);
   Dgetpath := gemdos_dgetpath(s, driveno);
@@ -501,7 +521,7 @@ begin
   Dopendir := gemdos_dopendir(s, flag);
   Dopendir := gemdos_dopendir(s, flag);
 end;
 end;
 
 
-function Dreaddir(buflen: smallint; dir: LongInt; var buf: String): LongInt;
+function Dreaddir(buflen: smallint; dir: LongInt; out buf: String): LongInt;
 var s: array[0..255] of char;
 var s: array[0..255] of char;
 begin
 begin
   Dreaddir := gemdos_dreaddir(buflen, dir, s);
   Dreaddir := gemdos_dreaddir(buflen, dir, s);
@@ -509,7 +529,7 @@ begin
     buf := PChar(@s[0]);
     buf := PChar(@s[0]);
 end;
 end;
 
 
-function Fxattr(flag: smallint; const name: String; var buf: TXATTR): LongInt;
+function Fxattr(flag: smallint; const name: String; out buf: TXATTR): LongInt;
 var s: array[0..255] of char;
 var s: array[0..255] of char;
 begin
 begin
   s := name;
   s := name;
@@ -534,7 +554,7 @@ begin
   fsymlink := gemdos_fsymlink(s1, s2);
   fsymlink := gemdos_fsymlink(s1, s2);
 end;
 end;
 
 
-function Freadlink(size: smallint; var buf: String; const name: String): LongInt;
+function Freadlink(size: smallint; out buf: String; const name: String): LongInt;
 var s1: array[0..255] of char;
 var s1: array[0..255] of char;
     s2: array[0..255] of char;
     s2: array[0..255] of char;
 begin
 begin

+ 3053 - 251
packages/tosunits/src/vdi.pas

@@ -12,168 +12,383 @@
 
 
  **********************************************************************}
  **********************************************************************}
 
 
+{$MODE FPC}
+{$MODESWITCH OUT+}
 {$PACKRECORDS 2}
 {$PACKRECORDS 2}
+
 unit vdi;
 unit vdi;
 
 
 interface
 interface
 
 
-{ The API description of this file is based on the information available
-  online at: http://toshyp.atari.org }
-
-type
-  PCOLOR_RGB = ^TCOLOR_RGB;
-  TCOLOR_RGB = record
-      reserved: word;     {* Set to 0 or the index of the entry *}
-      red: word;          {* Red:   0<->65535 *}
-      green: word;        {* Green: 0<->65535 *}
-      blue: word;         {* Blue:  0<->65535 *}
-  end;
-
-{$WARNING type TCOLOR_ENTRY is incomplete}
-type
-  TCOLOR_ENTRY = record
-    case byte of
-      0: ( rgb: TCOLOR_RGB; );
-      1: ( cymk: array[0..1] of longint; ); // dummy
-  end;
-
-type
-  PCOLOR_TAB = ^TCOLOR_TAB;
-  TCOLOR_TAB = record             {* Colour table                    *}
-      magic: array[0..3] of char; {* 'ctab'                          *}
-      length: longint;
-      format: longint;            {* Format (0)                      *}
-      reserved: longint;          {* Reserved, set to 0              *}
-      map_id: longint;            {* Colour table ID                 *}
-      color_space: longint;       {* Colour space (at present only
-                                     CSPACE_RGB)                     *}
-      flags: longint;             {* VDI-internal flags, set to 0    *}
-      no_colors: longint;         {* Number of colour entries        *}
-      reserved1: longint;         {* Reserved, must be 0             *}
-      reserved2: longint;         {* Reserved, must be 0             *}
-      reserved3: longint;         {* Reserved, must be 0             *}
-      reserved4: longint;         {* Reserved, must be 0             *}
-      colors: array[0..0] of TCOLOR_ENTRY; { repeated no_colors times }
-  end;
-
-type
-  PPOINT16 = ^TPOINT16;
-  TPOINT16 = record               {* Point for 16-bit coordinates *}
-      x: smallint;
-      y: smallint;
-  end;
-
-type
-  PPOINT32 = ^TPOINT32;
-  TPOINT32 = record               {* Point for 32-bit coordinates *}
-      x: longint;
-      y: longint;
-  end;
-
-type
-  PRECT16 = ^TRECT16;
-  TRECT16 = record                {* Rectangle for 16-bit coordinates *}
-      x1: smallint;
-      y1: smallint;
-      x2: smallint;
-      y2: smallint;
-  end;
-
-type
-  PRECT32 = ^TRECT32;
-  TRECT32 = record                {* Rectangle for 32-bit coordinates *}
-      x1: longint;
-      y1: longint;
-      x2: longint;
-      y2: longint;
-  end;
-
-type
-  PMFDB = ^TMFDB;
-  TMFDB = record
-      fd_addr: pointer;          {* Pointer to the start of the
-                                    memory block, e.g. the
-                                    screen memory base address  *}
-      fd_w: smallint;            {* Width in pixels             *}
-      fd_h: smallint;            {* Height in pixels            *}
-      fd_wdwidth: smallint;      {* Width of a line in words    *}
-      fd_stand: smallint;        {* 0 = Device-specific format  *}
-                                 {* 1 = Standard format         *}
-      fd_nplanes: smallint;      {* Number of planes            *}
-      fd_r1: smallint;           {* Reserved, must be 0         *}
-      fd_r2: smallint;           {* Reserved, must be 0         *}
-      fd_r3: smallint;           {* Reserved, must be 0         *}
-  end;
-
-type
-  PVDIContrl = ^TVDIContrl;
-  TVDIContrl = array[0..11] of smallint;
-
-  PVDIPtsIn  = ^TVDIPtsIn;
-  TVDIPtsIn  = array[0..1023] of smallint;
+uses gemcommon;
 
 
-  PVDIPtsOut = ^TVDIPtsOut;
-  TVDIPtsOut = array[0..255] of smallint;
-
-  PVDIIntIn  = ^TVDIIntIn;
-  TVDIIntIn  = array[0..1023] of smallint;
+{ The API description of this file is based on the information available
+  online at: https://freemint.github.io/tos.hyp/en/index.html }
 
 
-  PVDIIntOut = ^TVDIIntOut;
-  TVDIIntOut = array[0..511] of smallint;
+{$I vditypes.inc}
 
 
 type
 type
-  PVDIPB = ^TVDIPB;
-  TVDIPB = record
-      contrl: PVDIContrl;        {* Pointer to contrl array *}
-      intin: PVDIIntIn;          {* Pointer to intin array  *}
-      ptsin: PVDIPtsIn;          {* Pointer to ptsin array  *}
-      intout: PVDIIntOut;        {* Pointer to intout array *}
-      ptsout: PVDIPtsOut;        {* Pointer to ptsout array *}
-  end;
-
-const
-  VDI_TRAP_MAGIC = $73;
+   ARRAY_8 = gemcommon.ARRAY_8;
+   PMFORM = gemcommon.PMFORM;
+   TMFORM = gemcommon.TMFORM;
 
 
 procedure vdi;
 procedure vdi;
+procedure vdi(pb: PVDIPB);
+
+function vq_gdos: smallint;
+function vq_vgdos: LongInt;
 
 
 procedure vdi_str_to_pchar(src: psmallint; des: pchar; len: smallint);
 procedure vdi_str_to_pchar(src: psmallint; des: pchar; len: smallint);
 function pchar_str_to_vdi(src: pchar; des: psmallint): longint;
 function pchar_str_to_vdi(src: pchar; des: psmallint): longint;
 
 
 procedure v_opnwk(work_in: psmallint; handle: psmallint; work_out: psmallint);
 procedure v_opnwk(work_in: psmallint; handle: psmallint; work_out: psmallint);
 procedure v_clswk(handle: smallint);
 procedure v_clswk(handle: smallint);
+procedure v_clrwk(handle: smallint);
+procedure v_updwk(handle: smallint);
+
+procedure vq_chcells(handle: smallint; out rows, columns: smallint);
+procedure v_exit_cur(handle: smallint);
+procedure v_enter_cur(handle: smallint);
+procedure v_curup(handle: smallint);
+procedure v_curdown(handle: smallint);
+procedure v_curright(handle: smallint);
+procedure v_curleft(handle: smallint);
+procedure v_curhome(handle: smallint);
+procedure v_eeos(handle: smallint);
+procedure v_eeol(handle: smallint);
+procedure v_curaddress(handle, row, column: smallint);
+procedure v_curtext(handle: smallint; const outString: String);
+procedure v_rvon(handle: smallint);
+procedure v_rvoff(handle: smallint);
+procedure vq_curaddress(handle: smallint; out row, column: smallint);
+function vq_tabstatus(handle: smallint): smallint;
+procedure v_hardcopy(handle: smallint);
+procedure v_dspcur(handle, x, y: smallint);
+procedure v_rmcur(handle: smallint);
+procedure v_form_adv(handle: smallint);
+procedure v_output_window(handle: smallint; xyarray: ARRAY_4);
+procedure v_clear_disp_list(handle: smallint);
+procedure v_bit_image(handle: smallint; const filename: string;
+                aspect, x_scale, y_scale, h_align, v_align: smallint;
+                const xyarray: ARRAY_4);
+procedure vq_scan(handle: smallint; out g_slice, g_page, a_slice, a_page, div_fac: smallint);
+procedure v_alpha_text(handle: smallint; const outString: String);
+function v_orient(handle, orientation: smallint): smallint;
+function v_copies(handle, count: smallint): smallint;
+procedure v_tray(handle, tray: smallint);
+function v_page_size(handle, page_id: smallint): smallint;
+function vs_palette(handle, palette: smallint): smallint;
+procedure v_sound(handle, frequency, duration: smallint);
+function vs_mute(handle, action: smallint): smallint;
+procedure vt_resolution(handle, xres, yres: smallint;
+                        out xset, yset: smallint);
+procedure vt_axis(handle, xres, yres: smallint;
+                  out xset, yset: smallint);
+procedure vt_origin(handle, xorigin, yorigin: smallint);
+procedure vq_tdimensions(handle: smallint; out xdimension, ydimension: smallint);
+procedure vt_alignment(handle, dx, dy: smallint);
+procedure vsp_film(handle, index, lightness: smallint);
+function vqp_filmname(handle, index: smallint; out name: String): smallint;
+procedure vsc_expose(handle, state: smallint);
+procedure v_meta_extents(handle, min_x, min_y, max_x, max_y: smallint);
+procedure v_write_meta(handle, num_intin: smallint; a_intin: Pointer;
+                       num_ptsin: smallint;a_ptsin: Pointer);
+procedure vm_pagesize(handle, pgwidth, pgheight: smallint);
+procedure vm_coords(handle, llx, lly, urx, ury: smallint);
+function v_bez_qual(handle, prcnt: smallint; out actual: smallint): smallint;
+procedure vm_filename(handle: smallint; const filename: String);
+procedure v_offset(handle, offset: smallint);
+procedure v_fontinit(handle: smallint; var fh: TFONT_HDR);
+procedure v_escape2000(handle, times: smallint);
 
 
 procedure v_pline(handle: smallint; count: smallint; pxyarray: psmallint);
 procedure v_pline(handle: smallint; count: smallint; pxyarray: psmallint);
-
-procedure v_gtext(handle: smallint; x: smallint; y: smallint; _string: pchar);
+procedure v_pline(handle, count: smallint; const pxyarray: Array of smallint);
+procedure v_bez(handle, count: smallint; xyarr, bezarr: Pointer;
+                out extent: ARRAY_4;
+                out totpts, totmoves: smallint);
+procedure v_bez_fill(handle, count: smallint;
+                    xyarr, bezarr: Pointer;
+                    out extent: ARRAY_4;
+                    out totpts, totmoves: smallint);
+
+procedure v_pmarker(handle, count: smallint; const pxyarray: Array of smallint);
+procedure v_gtext(handle: smallint; x: smallint; y: smallint; outputstring: pchar);
+procedure v_gtext(handle, x, y: smallint; const outputstring: string);
+procedure v_fillarea(handle, count: smallint; const pxyarray: Array of smallint);
 
 
 procedure v_bar(handle: smallint; pxyarray: psmallint);
 procedure v_bar(handle: smallint; pxyarray: psmallint);
-procedure v_circle (handle: smallint; x: smallint; y: smallint; radius: smallint);
+procedure v_bar(handle: smallint; const pxyarray: ARRAY_4);
+procedure v_arc(handle, x, y, radius, begang, endang: smallint);
+procedure v_pieslice(handle, x, y, radius, begang, endang: smallint);
+procedure v_circle(handle: smallint; x: smallint; y: smallint; radius: smallint);
+procedure v_ellipse(handle, x, y, xradius, yradius: smallint);
+procedure v_ellarc(handle, x, y, xradius, yradius, begang, endang: smallint);
+procedure v_ellpie(handle, x, y, xradius, yradius, begang, endang: smallint);
+procedure v_rbox(handle: smallint; const xyarray: ARRAY_4);
+procedure v_rfbox(handle: smallint; const xyarray: ARRAY_4);
+procedure v_justified(handle, x, y: smallint;
+        const outputstring: string;
+        width, wordspace, charspace: smallint);
+function v_bez_on(handle: smallint): smallint;
+procedure v_bez_off(handle: smallint);
+
+procedure vst_height(handle, height: smallint; out char_width, char_height, cell_width, cell_height: smallint);
+function vst_rotation(handle, angle: smallint): smallint;
 
 
 procedure vs_color(handle: smallint; index: smallint; rgb_in: psmallint);
 procedure vs_color(handle: smallint; index: smallint; rgb_in: psmallint);
+procedure vs_color(handle, index: smallint; const rgb_in: ARRAY_3);
 
 
+function vsl_type(handle, style: smallint): smallint;
+function vsl_width(handle, width: smallint): smallint;
 function vsl_color(handle: smallint; color_index: smallint): smallint;
 function vsl_color(handle: smallint; color_index: smallint): smallint;
+function vsm_type(handle, symbol: smallint): smallint;
+function vsm_height(handle, height: smallint): smallint;
+function vsm_color(handle, color_index: smallint): smallint;
+function vst_font(handle, font: smallint): smallint;
+function vsf_interior(handle, style: smallint): smallint;
+function vsf_style(handle, style_index: smallint): smallint;
+function vq_color(handle, color_index, set_flag: smallint; out rgb: ARRAY_3): smallint;
+procedure vrq_locator(handle, x, y: smallint; out xout, yout, term: smallint);
+function vsm_locator(handle, x, y: smallint; out xout, yout, term: smallint): smallint;
+procedure vrq_valuator(handle, valuator_in: smallint; out valuator_out, terminator: smallint);
+procedure vsm_valuator(handle, val_in: smallint; out val_out, term, status: smallint);
+procedure vrq_choice(handle, ch_in: smallint; out ch_out: smallint);
+function vsm_choice(handle: smallint; out choice: smallint): smallint;
+procedure vrq_string(handle, max_length, echo_mode: smallint; const echo_xy: ARRAY_2; out resString: string);
+function vsm_string(handle, max_length, echo_mode: smallint; const echo_xy: ARRAY_2; out resString: string): smallint;
+
 function vst_color(handle: smallint; color_index: smallint): smallint;
 function vst_color(handle: smallint; color_index: smallint): smallint;
 function vsf_color(handle: smallint; color_index: smallint): smallint;
 function vsf_color(handle: smallint; color_index: smallint): smallint;
 
 
 function vswr_mode(handle: smallint; mode: smallint): smallint;
 function vswr_mode(handle: smallint; mode: smallint): smallint;
-
-procedure v_opnvwk(work_in: psmallint; handle: psmallint; work_out: psmallint);
-procedure v_clsvwk(handle: smallint);
+function vsin_mode(handle, dev_type, mode: smallint): smallint;
+procedure vql_attributes(handle: smallint; out attrib: ARRAY_4);
+procedure vql_attributes(handle: smallint; out attrib: ARRAY_6);
+procedure vqm_attributes(handle: smallint; out attrib: ARRAY_4);
+procedure vqf_attributes(handle: smallint; out attrib: ARRAY_5);
+procedure vqt_attributes(handle: smallint; out attrib: ARRAY_10);
+procedure vst_alignment(handle, hor_in, vert_in: smallint; out hor_out, vert_out: smallint);
+
+procedure v_opnvwk(work_in: psmallint; handle: psmallint; work_out: psmallint); overload;
+procedure v_clsvwk(handle: smallint); overload;
+procedure vq_extnd(handle, owflag: smallint; WorkOut: psmallint); overload;
+procedure vq_scrninfo(handle: smallint; out WorkOut: ARRAY_273);
+procedure v_contourfill(handle, x, y, index: smallint);
+function vsf_perimeter(handle, per_vis: smallint): smallint;
 
 
 procedure v_get_pixel(handle: smallint; x: smallint; y: smallint;
 procedure v_get_pixel(handle: smallint; x: smallint; y: smallint;
                       pel: psmallint; index: psmallint);
                       pel: psmallint; index: psmallint);
+procedure v_get_pixel(handle, x, y: smallint; out pel, index: smallint);
+function vst_effects(handle, effect: smallint): smallint;
+function vst_point(handle, point: smallint; out char_width, char_height, cell_width, cell_height: smallint): smallint;
+procedure vsl_ends(handle, beg_style, end_style: smallint);
 
 
-procedure vro_cpyfm(handle: smallint; vr_mode: smallint; pxyarray: psmallint; psrcMFDB: PMFDB; pdesMFDB: PMFDB);
+procedure vro_cpyfm(handle: smallint; vr_mode: smallint; pxyarray: psmallint; psrcMFDB: PMFDB; pdesMFDB: PMFDB); overload;
+procedure vr_trnfm(handle: smallint; psrcMFDB, pdesMFDB: PMFDB);
+procedure vr_trnfm(handle: smallint; const psrcMFDB, pdesMFDB: TMFDB);
+procedure vsc_form(handle: smallint; pcur_form: PMFORM);
+procedure vsf_udpat(handle: smallint; pfill_pat: Pointer; planes: smallint);
+procedure vsl_udsty(handle, pattern: smallint);
+procedure vr_recfl(handle: smallint; const pxyarray: ARRAY_4);
+procedure vqin_mode(handle, dev_type: smallint; out input_mode: smallint);
+procedure vqt_extent(handle: smallint; calcString: pchar; extent: psmallint); overload;
+function vqt_width(handle, character: smallint; out cell_width, left_delta, right_delta: smallint): smallint;
 
 
-procedure vrt_cpyfm(handle: smallint; vr_mode: smallint; pxyarray: psmallint; psrcMFDB: PMFDB; pdesMFDB: PMFDB; color_index: psmallint);
+procedure vex_timv(handle: smallint; tim_addr: Pointer; out otim_addr: Pointer; out tim_conv: smallint);
+
+function vst_load_fonts(handle, select: smallint): smallint;
+procedure vst_unload_fonts(handle, select: smallint);
+
+procedure vrt_cpyfm(handle: smallint; vr_mode: smallint; pxyarray: psmallint; psrcMFDB: PMFDB; pdesMFDB: PMFDB; color_index: psmallint); overload;
 
 
 procedure v_show_c(handle: smallint; reset: smallint);
 procedure v_show_c(handle: smallint; reset: smallint);
 procedure v_hide_c(handle: smallint);
 procedure v_hide_c(handle: smallint);
+procedure vq_mouse(handle: smallint; out pstatus, x, y: smallint);
+procedure vex_butv(handle: smallint; pusrcode: Pointer; out psavcode: Pointer);
+procedure vex_motv(handle: smallint; pusrcode: Pointer; out psavcode: Pointer);
+procedure vex_curv(handle: smallint; pusrcode: Pointer; out psavcode: Pointer);
+procedure vex_wheelv(handle: smallint; pusrcode: Pointer; out psavcode: Pointer);
+procedure vq_key_s(handle: smallint; out pstatus: smallint);
 
 
 procedure vs_clip(handle: smallint; clip_flag: smallint; pxyarray: psmallint);
 procedure vs_clip(handle: smallint; clip_flag: smallint; pxyarray: psmallint);
+procedure vs_clip(handle, clip_flag: smallint; const pxyarray: ARRAY_4);
+procedure vs_clip_off(handle: smallint);
+
+function vqt_name(handle, element_num: smallint; out name: String33): smallint;
+procedure vqt_fontinfo(handle: smallint;
+        out minADE, maxADE: smallint;
+        out distances: ARRAY_5;
+        out maxwidth: smallint;
+        out effects: ARRAY_3);
+
+procedure vqt_justified(handle, x, y: smallint; const outString: String;
+            length, word_space, char_space: smallint;
+            offsets: Pointer);
+
+procedure vst_width(handle, width: smallint; out char_width, char_height, cell_width, cell_height: smallint);
+procedure vqt_fontheader(handle: smallint; buffer: Pointer;
+                         out pathname: String);
+procedure vqt_trackkern(handle: smallint; out x, y: fix31);
+procedure vqt_pairkern(handle, ch1, ch2: smallint; out x, y: fix31);
+procedure vst_charmap(handle, mode: smallint);
+function vst_map_mode(handle, mode: smallint): smallint;
+procedure vst_kern(handle, tmode, pmode: smallint; out tracks, pairs: smallint);
+procedure vst_track_offset(handle: smallint; offset: fix31; pairmode: smallint; out tracks, pairs: smallint);
+procedure v_getbitmap_info(handle, ch: smallint;
+                           out advx, advy, xoff, yoff: fix31;
+                           out width, height: smallint;
+                           out bitmap: pointer);
+
+procedure v_ftext(handle, x, y: smallint; const str: String);
+procedure v_ftext_offset(handle, x, y: smallint;
+                         const outputstring: string;
+                         const offset: Array of smallint);
+procedure v_killoutline(handle: smallint; component: Pointer);
+procedure v_getoutline(handle, ch: smallint;
+                       const xyarray: Array of smallint;
+                       const bezarray: Array of ShortInt;
+                       maxverts: smallint;
+                       out numverts: smallint);
+procedure vst_scratch(handle, mode: smallint);
+procedure vst_error(handle, mode: smallint; out errorvar: smallint);
+function vst_arbpt(handle, point: smallint;
+                   out chwd, chht, cellwd, cellht: smallint): smallint;
+function vst_arbpt32(handle: smallint; point: fix31;
+                     out chwd, chht, cellwd, cellht: smallint): fix31;
+procedure vqt_advance(handle, ch: smallint; out advx, advy, remx, remy: smallint);
+procedure vqt_advance32(handle, ch: smallint; out advx, advy: fix31);
+function vq_devinfo(handle, devnum: smallint;
+                      out devexists: smallint;
+                      out filename: String;
+                      out devicename: String): smallint;
+procedure vqt_devinfo(handle, devnum: smallint;
+                      out dev_busy: smallint;
+                      out filename: String;
+                      out devicename: String);
+
+function v_savecache(handle: smallint; const filename: String): smallint;
+function v_loadcache(handle: smallint; const filename: String; mode: smallint): smallint;
+function v_flushcache(handle: smallint): smallint;
+function vst_setsize(handle, point: smallint;
+                     out chwd, chht, cellwd, cellht: smallint): smallint;
+function  vst_setsize32(handle: smallint; point: fix31;
+                        out chwd, chht, cellwd, cellht: smallint): fix31;
+function vst_skew(handle, skew: smallint): smallint;
+procedure vqt_get_table(handle: smallint; out map: Pointer);
+procedure vqt_cachesize(handle, which_cache: smallint; out size: LongInt);
+
+procedure v_set_app_buff(handle: smallint; address: Pointer; nparagraphs: smallint);
+
+
+(*
+ * NOT YET IMPLEMENTED:
+fix31_to_point(a) ((_WORD)((((a) + 32768L) >> 16)))
+point_to_fix31(a) (((fix31)(a)) << 16)
+
+v_trays
+
+v_ps_halftone
+vq_calibrate
+vq_page_name
+vq_tray_names
+vs_calibrate
+v_etext
+
+v_setrgbi
+v_xbit_image
+v_topbot
+vs_bkcolor
+v_pat_rotate
+vs_grayoverride
+
+v_opnbm
+v_clsbm
+
+v_get_driver_info
+vqt_real_extent
+
+vq_margins
+vq_driver_info
+vq_bit_image
+vs_page_info
+vs_crop
+vq_image_type
+vs_save_disp_list
+vs_load_disp_list
+
+vqt_xfntinfo
+vq_ext_devinfo
+vqt_ext_name
+vqt_name_and_id
+vst_name
+
+vqt_char_index
+
+vqt_is_char_available
+
+v_color2nearest
+v_color2value
+v_create_ctab
+v_create_itab
+v_ctab_idx2value
+v_ctab_idx2vdi
+v_ctab_vdi2idx
+v_delete_ctab
+v_delete_itab
+v_get_ctab_id
+v_get_outline
+v_open_bm
+v_resize_bm
+v_setrgb
+v_value2color
+vq_ctab
+vq_ctab_entry
+vq_ctab_id
+vq_dflt_ctab
+vq_hilite_color
+vq_margins
+vq_max_color
+vq_min_color
+vq_prn_scaling
+vq_px_format
+vq_weight_color
+vqf_bg_color
+vqf_fg_color
+vql_bg_color
+vql_fg_color
+vqm_bg_color
+vqm_fg_color
+vqr_bg_color
+vqr_fg_color
+vqt_bg_color
+vqt_fg_color
+vr_transfer_bits
+vs_ctab
+vs_ctab_entry
+vs_dflt_ctab
+vs_document_info
+vs_hilite_color
+vs_max_color
+vs_min_color
+vs_weight_color
+vsf_bg_color
+vsf_fg_color
+vsl_bg_color
+vsl_fg_color
+vsm_bg_color
+vsm_fg_color
+vsr_bg_color
+vsr_fg_color
+vst_bg_color
+vst_fg_color
+*)
+
 
 
 implementation
 implementation
 
 
+const
+  VDI_TRAP_MAGIC = $73;
+
 var
 var
   _contrl: TVDIContrl;
   _contrl: TVDIContrl;
   _intin: TVDIIntIn;
   _intin: TVDIIntIn;
@@ -183,19 +398,69 @@ var
 
 
 const
 const
   pblock: TVDIPB = (
   pblock: TVDIPB = (
-    contrl: @_contrl;
+    control: @_contrl;
     intin: @_intin;
     intin: @_intin;
     ptsin: @_ptsin;
     ptsin: @_ptsin;
     intout: @_intout;
     intout: @_intout;
     ptsout: @_ptsout;
     ptsout: @_ptsout;
-  );
+  ); public name 'vdipb';
+
+function string_to_vdi(const src: String; dst: psmallint): smallint;
+var
+  i, len: longint;
+begin
+  len:=length(src);
+  for i:=0 to len-1 do
+    dst[i]:=byte(src[i + 1]);
+
+  string_to_vdi:=len;
+end;
+
+procedure vdi_to_string(src: psmallint; out dst: String; len: longint);
+var
+  i: longint;
+begin
+  for i:=0 to len-1 do
+    dst[i + 1]:=chr(src[i]);
+  setlength(dst, len);
+end;
 
 
-procedure vdi; assembler;
+procedure vdi; assembler; nostackframe;
 asm
 asm
+  pea.l       (a2)
   lea.l pblock, a0
   lea.l pblock, a0
   move.l a0, d1
   move.l a0, d1
   move.w #VDI_TRAP_MAGIC, d0
   move.w #VDI_TRAP_MAGIC, d0
   trap #2
   trap #2
+  movea.l     (a7)+,a2
+end;
+
+procedure vdi(pb: PVDIPB); assembler; nostackframe;
+asm
+  pea.l       (a2)
+  move.l pb,a0
+  move.l a0,d1
+  move.w #VDI_TRAP_MAGIC,d0
+  trap #2
+  movea.l     (a7)+,a2
+end;
+
+function vq_gdos: smallint; assembler; nostackframe;
+asm
+  pea.l       (a2)
+  moveq.l     #-2,d0
+  trap        #2
+  addq.w      #2,d0
+  ext.l       d0
+  movea.l     (a7)+,a2
+end;
+
+function vq_vgdos: LongInt; assembler; assembler; nostackframe;
+asm
+  pea.l       (a2)
+  moveq.l     #-2,d0
+  trap        #2
+  movea.l     (a7)+,a2
 end;
 end;
 
 
 procedure vdi_str_to_pchar(src: psmallint; des: pchar; len: smallint);
 procedure vdi_str_to_pchar(src: psmallint; des: pchar; len: smallint);
@@ -216,7 +481,7 @@ var
 begin
 begin
   len:=0;
   len:=0;
   repeat
   repeat
-    des[len]:=ord(src[len]);
+    des[len]:=byte(src[len]);
     inc(len);
     inc(len);
   until (src[len-1] = #0);
   until (src[len-1] = #0);
 
 
@@ -224,22 +489,26 @@ begin
 end;
 end;
 
 
 procedure v_opnwk(work_in: psmallint; handle: psmallint; work_out: psmallint);
 procedure v_opnwk(work_in: psmallint; handle: psmallint; work_out: psmallint);
+var pb: TVDIPB;
 begin
 begin
+  pb.control := @_contrl;
   // _intin[0..15] = work_in[0..15];
   // _intin[0..15] = work_in[0..15];
-  move(work_in^,_intin,16*sizeof(smallint));
+  pb.intin := PVDIIntIn(work_in);
+  pb.ptsin := @_ptsin;
+  // work_out[0..44] = intout[0..44];
+  pb.intout := PVDIIntOut(work_out);
+  // work_out[45..56] = ptsout[0..11];
+  pb.ptsout := PVDIPtsOut(@work_out[45]);
 
 
   _contrl[0]:=1;
   _contrl[0]:=1;
   _contrl[1]:=0;
   _contrl[1]:=0;
   _contrl[3]:=16;
   _contrl[3]:=16;
+  _contrl[5]:=0;
   _contrl[6]:=0;
   _contrl[6]:=0;
 
 
-  vdi;
+  vdi(@pb);
 
 
   handle^:=_contrl[6];
   handle^:=_contrl[6];
-  // work_out[0..44] = intout[0..44];
-  // work_out[45..56] = ptsout[0..11];
-  move(_intout,work_out[0],45*sizeof(smallint));
-  move(_ptsout,work_out[45],12*sizeof(smallint));
 end;
 end;
 
 
 procedure v_clswk(handle: smallint);
 procedure v_clswk(handle: smallint);
@@ -247,70 +516,74 @@ begin
   _contrl[0]:=2;
   _contrl[0]:=2;
   _contrl[1]:=0;
   _contrl[1]:=0;
   _contrl[3]:=0;
   _contrl[3]:=0;
+  _contrl[5]:=0;
   _contrl[6]:=handle;
   _contrl[6]:=handle;
 
 
   vdi;
   vdi;
 end;
 end;
 
 
-procedure v_pline(handle: smallint; count: smallint; pxyarray: psmallint);
+procedure v_clrwk(handle: smallint);
 begin
 begin
-  // _ptsin[0..2*count-1] = pxyarray[0..2*count-1];
-  move(pxyarray^,_ptsin,count*2*sizeof(smallint));
-
-  _contrl[0]:=6;
-  _contrl[1]:=count;
+  _contrl[0]:=3;
+  _contrl[1]:=0;
   _contrl[3]:=0;
   _contrl[3]:=0;
   _contrl[6]:=handle;
   _contrl[6]:=handle;
 
 
   vdi;
   vdi;
 end;
 end;
 
 
-procedure v_gtext(handle: smallint; x: smallint; y: smallint; _string: pchar);
-var
-  i: smallint;
+procedure v_updwk(handle: smallint);
 begin
 begin
-  _ptsin[0]:=x;
-  _ptsin[1]:=y;
+  _contrl[0]:=4;
+  _contrl[1]:=0;
+  _contrl[3]:=0;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
 
 
-  i:=0;
-  repeat
-    _intin[i]:=byte(_string[i]);
-    inc(i);
-  until (_string[i-1] = #0);
-  dec(i);
+  vdi;
+end;
 
 
-  _contrl[0]:=8;
-  _contrl[1]:=1;
-  _contrl[3]:=-i;
+
+procedure vq_chcells(handle: smallint; out rows, columns: smallint);
+begin
+  _contrl[0]:=5;
+  _contrl[1]:=0;
+  _contrl[3]:=0;
+  _contrl[5]:=1;
   _contrl[6]:=handle;
   _contrl[6]:=handle;
 
 
   vdi;
   vdi;
+
+  rows:=_intout[0];
+  columns:=_intout[1];
 end;
 end;
 
 
-procedure v_bar(handle: smallint; pxyarray: psmallint);
+procedure v_exit_cur(handle: smallint);
 begin
 begin
-  // _ptsin[0..3] = pxyarray[0..3];
-  move(pxyarray^,_ptsin,4*sizeof(smallint));
-  _contrl[0]:=11;
-  _contrl[1]:=2;
+  _contrl[0]:=5;
+  _contrl[1]:=0;
   _contrl[3]:=0;
   _contrl[3]:=0;
-  _contrl[5]:=1;
+  _contrl[5]:=2;
   _contrl[6]:=handle;
   _contrl[6]:=handle;
 
 
   vdi;
   vdi;
 end;
 end;
 
 
-procedure v_circle (handle: smallint; x: smallint; y: smallint; radius: smallint);
+procedure v_enter_cur(handle: smallint);
 begin
 begin
-  _ptsin[0]:=x;
-  _ptsin[1]:=y;
-  _ptsin[2]:=0;
-  _ptsin[3]:=0;
-  _ptsin[4]:=radius;
-  _ptsin[5]:=0;
+  _contrl[0]:=5;
+  _contrl[1]:=0;
+  _contrl[3]:=0;
+  _contrl[5]:=3;
+  _contrl[6]:=handle;
 
 
-  _contrl[0]:=11;
-  _contrl[1]:=3;
+  vdi;
+end;
+
+procedure v_curup(handle: smallint);
+begin
+  _contrl[0]:=5;
+  _contrl[1]:=0;
   _contrl[3]:=0;
   _contrl[3]:=0;
   _contrl[5]:=4;
   _contrl[5]:=4;
   _contrl[6]:=handle;
   _contrl[6]:=handle;
@@ -318,192 +591,2721 @@ begin
   vdi;
   vdi;
 end;
 end;
 
 
-procedure vs_color(handle: smallint; index: smallint; rgb_in: psmallint);
+procedure v_curdown(handle: smallint);
 begin
 begin
-  _intin[0]:=index;
-  _intin[1]:=rgb_in[0];
-  _intin[2]:=rgb_in[1];
-  _intin[3]:=rgb_in[2];
-
-  _contrl[0]:=14;
+  _contrl[0]:=5;
   _contrl[1]:=0;
   _contrl[1]:=0;
-  _contrl[3]:=4;
+  _contrl[3]:=0;
+  _contrl[5]:=5;
   _contrl[6]:=handle;
   _contrl[6]:=handle;
 
 
   vdi;
   vdi;
 end;
 end;
 
 
-function vsl_color(handle: smallint; color_index: smallint): smallint;
+procedure v_curright(handle: smallint);
 begin
 begin
-  _intin[0]:=color_index;
-
-  _contrl[0]:=17;
+  _contrl[0]:=5;
   _contrl[1]:=0;
   _contrl[1]:=0;
-  _contrl[3]:=1;
+  _contrl[3]:=0;
+  _contrl[5]:=6;
   _contrl[6]:=handle;
   _contrl[6]:=handle;
 
 
   vdi;
   vdi;
+end;
 
 
-  vsl_color:=_intout[0];
+procedure v_curleft(handle: smallint);
+begin
+  _contrl[0]:=5;
+  _contrl[1]:=0;
+  _contrl[3]:=0;
+  _contrl[5]:=7;
+  _contrl[6]:=handle;
+
+  vdi;
 end;
 end;
 
 
-function vst_color(handle: smallint; color_index: smallint): smallint;
+procedure v_curhome(handle: smallint);
 begin
 begin
-  _intin[0]:=color_index;
+  _contrl[0]:=5;
+  _contrl[1]:=0;
+  _contrl[3]:=0;
+  _contrl[5]:=8;
+  _contrl[6]:=handle;
 
 
-  _contrl[0]:=22;
+  vdi;
+end;
+
+procedure v_eeos(handle: smallint);
+begin
+  _contrl[0]:=5;
   _contrl[1]:=0;
   _contrl[1]:=0;
-  _contrl[3]:=1;
+  _contrl[3]:=0;
+  _contrl[5]:=9;
   _contrl[6]:=handle;
   _contrl[6]:=handle;
 
 
   vdi;
   vdi;
+end;
 
 
-  vst_color:=_intout[0];
+procedure v_eeol(handle: smallint);
+begin
+  _contrl[0]:=5;
+  _contrl[1]:=0;
+  _contrl[3]:=0;
+  _contrl[5]:=10;
+  _contrl[6]:=handle;
+
+  vdi;
 end;
 end;
 
 
-function vsf_color(handle: smallint; color_index: smallint): smallint;
+procedure v_curaddress(handle, row, column: smallint);
 begin
 begin
-  _intin[0]:=color_index;
+  _intin[0]:=row;
+  _intin[1]:=column;
+  _contrl[0]:=5;
+  _contrl[1]:=0;
+  _contrl[3]:=2;
+  _contrl[5]:=11;
+  _contrl[6]:=handle;
 
 
-  _contrl[0]:=25;
+  vdi;
+end;
+
+procedure v_curtext(handle: smallint; const outString: String);
+var len: longint;
+begin
+  len:=string_to_vdi(outString, @_intin[0]);
+  _contrl[0]:=5;
   _contrl[1]:=0;
   _contrl[1]:=0;
-  _contrl[3]:=1;
+  _contrl[3]:=len;
+  _contrl[5]:=12;
   _contrl[6]:=handle;
   _contrl[6]:=handle;
 
 
   vdi;
   vdi;
+end;
 
 
-  vsf_color:=_intout[0];
+procedure v_rvon(handle: smallint);
+begin
+  _contrl[0]:=5;
+  _contrl[1]:=0;
+  _contrl[3]:=0;
+  _contrl[5]:=13;
+  _contrl[6]:=handle;
+
+  vdi;
 end;
 end;
 
 
-function vswr_mode(handle: smallint; mode: smallint): smallint;
+procedure v_rvoff(handle: smallint);
 begin
 begin
-  _intin[0]:=mode;
+  _contrl[0]:=5;
+  _contrl[1]:=0;
+  _contrl[3]:=0;
+  _contrl[5]:=14;
+  _contrl[6]:=handle;
 
 
-  _contrl[0]:=32;
+  vdi;
+end;
+
+procedure vq_curaddress(handle: smallint; out row, column: smallint);
+begin
+  _contrl[0]:=5;
   _contrl[1]:=0;
   _contrl[1]:=0;
-  _contrl[3]:=1;
+  _contrl[3]:=0;
+  _contrl[5]:=15;
   _contrl[6]:=handle;
   _contrl[6]:=handle;
 
 
   vdi;
   vdi;
 
 
-  vswr_mode:=_intout[0];
+  row:=_intout[0];
+  column:=_intout[1];
 end;
 end;
 
 
-procedure v_opnvwk(work_in: psmallint; handle: psmallint; work_out: psmallint);
+function vq_tabstatus(handle: smallint): smallint;
 begin
 begin
-  // _intin[0..10] = work_in[0..10];
-  move(work_in^,_intin,11*sizeof(smallint));
-
-  _contrl[0]:=100;
+  _contrl[0]:=5;
   _contrl[1]:=0;
   _contrl[1]:=0;
-  _contrl[3]:=11;
-  _contrl[6]:=handle^;
+  _contrl[3]:=0;
+  _contrl[5]:=16;
+  _contrl[6]:=handle;
 
 
   vdi;
   vdi;
 
 
-  handle^:=_contrl[6];
-  // work_out[0..44] = intout[0..44];
-  // work_out[45..56] = ptsout[0..11];
-  move(_intout,work_out[0],45*sizeof(smallint));
-  move(_ptsout,work_out[45],12*sizeof(smallint));
+  vq_tabstatus:=_intout[0];
 end;
 end;
 
 
-procedure v_clsvwk(handle: smallint);
+procedure v_hardcopy(handle: smallint);
 begin
 begin
-  _contrl[0]:=101;
+  _contrl[0]:=5;
   _contrl[1]:=0;
   _contrl[1]:=0;
   _contrl[3]:=0;
   _contrl[3]:=0;
+  _contrl[5]:=17;
   _contrl[6]:=handle;
   _contrl[6]:=handle;
 
 
   vdi;
   vdi;
 end;
 end;
 
 
-procedure v_get_pixel(handle: smallint; x: smallint; y: smallint;
-                      pel: psmallint; index: psmallint);
+procedure v_dspcur(handle, x, y: smallint);
 begin
 begin
-  _ptsin[0]:=x;
   _ptsin[0]:=x;
   _ptsin[0]:=x;
   _ptsin[1]:=y;
   _ptsin[1]:=y;
-  _contrl[0]:=105;
+  _contrl[0]:=5;
   _contrl[1]:=1;
   _contrl[1]:=1;
   _contrl[3]:=0;
   _contrl[3]:=0;
+  _contrl[5]:=18;
   _contrl[6]:=handle;
   _contrl[6]:=handle;
 
 
   vdi;
   vdi;
-
-  pel^:=_intout[0];
-  index^:=_intout[1];
 end;
 end;
 
 
-procedure vro_cpyfm(handle: smallint; vr_mode: smallint; pxyarray: psmallint; psrcMFDB: PMFDB; pdesMFDB: PMFDB);
+procedure v_rmcur(handle: smallint);
 begin
 begin
-  _intin[0]:=vr_mode;
-  // ptsin[0..7] = pxyarray[0..7];
-  move(pxyarray[0],_ptsin[0],8*sizeof(smallint));
+  _contrl[0]:=5;
+  _contrl[1]:=0;
+  _contrl[3]:=0;
+  _contrl[5]:=19;
+  _contrl[6]:=handle;
 
 
-  PPointer(@_contrl[7])^:=psrcMFDB;
-  PPointer(@_contrl[9])^:=pdesMFDB;
+  vdi;
+end;
 
 
-  _contrl[0]:=109;
-  _contrl[1]:=4;
-  _contrl[3]:=1;
+procedure v_form_adv(handle: smallint);
+begin
+  _contrl[0]:=5;
+  _contrl[1]:=0;
+  _contrl[3]:=0;
+  _contrl[5]:=20;
   _contrl[6]:=handle;
   _contrl[6]:=handle;
 
 
   vdi;
   vdi;
 end;
 end;
 
 
-procedure vrt_cpyfm(handle: smallint; vr_mode: smallint; pxyarray: psmallint; psrcMFDB: PMFDB; pdesMFDB: PMFDB; color_index: psmallint);
+procedure v_output_window(handle: smallint; xyarray: ARRAY_4);
 begin
 begin
-  _intin[0]:=vr_mode;
-  _intin[1]:=color_index[0];
-  _intin[2]:=color_index[1];
-  // ptsin[0..7] = pxyarray[0..7];
-  move(pxyarray[0],_ptsin[0],8*sizeof(smallint));
+  _ptsin[0]:=xyarray[0];
+  _ptsin[1]:=xyarray[1];
+  _ptsin[2]:=xyarray[2];
+  _ptsin[3]:=xyarray[3];
+  _contrl[0]:=5;
+  _contrl[1]:=2;
+  _contrl[3]:=0;
+  _contrl[5]:=21;
+  _contrl[6]:=handle;
 
 
-  PPointer(@_contrl[7])^:=psrcMFDB;
-  PPointer(@_contrl[9])^:=pdesMFDB;
+  vdi;
+end;
 
 
-  _contrl[0]:=121;
-  _contrl[1]:=4;
-  _contrl[3]:=3;
+procedure v_clear_disp_list(handle: smallint);
+begin
+  _contrl[0]:=5;
+  _contrl[1]:=0;
+  _contrl[3]:=0;
+  _contrl[5]:=22;
   _contrl[6]:=handle;
   _contrl[6]:=handle;
 
 
   vdi;
   vdi;
 end;
 end;
 
 
-procedure v_show_c(handle: smallint; reset: smallint);
+procedure v_bit_image(handle: smallint; const filename: string;
+                aspect, x_scale, y_scale, h_align, v_align: smallint;
+                const xyarray: ARRAY_4);
+var len: longint;
 begin
 begin
-  _intin[0]:=reset;
-
-  _contrl[0]:=122;
-  _contrl[1]:=0;
-  _contrl[3]:=1;
+  _ptsin[0]:=xyarray[0];
+  _ptsin[1]:=xyarray[1];
+  _ptsin[2]:=xyarray[2];
+  _ptsin[3]:=xyarray[3];
+  _intin[0]:=aspect;
+  _intin[1]:=x_scale;
+  _intin[2]:=y_scale;
+  _intin[3]:=h_align;
+  _intin[4]:=v_align;
+  len:=string_to_vdi(filename, @_intin[5]);
+  _contrl[0]:=5;
+  _contrl[1]:=2;
+  _contrl[3]:=len+5;
+  _contrl[5]:=23;
   _contrl[6]:=handle;
   _contrl[6]:=handle;
 
 
   vdi;
   vdi;
 end;
 end;
 
 
-procedure v_hide_c(handle: smallint);
+procedure vq_scan(handle: smallint; out g_slice, g_page, a_slice, a_page, div_fac: smallint);
 begin
 begin
-  _contrl[0]:=123;
+  _contrl[0]:=5;
   _contrl[1]:=0;
   _contrl[1]:=0;
   _contrl[3]:=0;
   _contrl[3]:=0;
+  _contrl[5]:=24;
   _contrl[6]:=handle;
   _contrl[6]:=handle;
 
 
   vdi;
   vdi;
+
+  g_slice:=_intout[0];
+  g_page:=_intout[1];
+  a_slice:=_intout[2];
+  a_page:=_intout[3];
+  div_fac:=_intout[4];
 end;
 end;
 
 
-procedure vs_clip(handle: smallint; clip_flag: smallint; pxyarray: psmallint);
+procedure v_alpha_text(handle: smallint; const outString: String);
+var len: longint;
 begin
 begin
-  _intin[0]:=clip_flag;
-  _ptsin[0]:=pxyarray[0];
-  _ptsin[1]:=pxyarray[1];
-  _ptsin[2]:=pxyarray[2];
-  _ptsin[3]:=pxyarray[3];
+  len:=string_to_vdi(outString, @_intin[0]);
+  _contrl[0]:=5;
+  _contrl[1]:=0;
+  _contrl[3]:=len;
+  _contrl[5]:=25;
+  _contrl[6]:=handle;
 
 
-  _contrl[0]:=129;
-  _contrl[1]:=2;
+  vdi;
+end;
+
+function v_orient(handle, orientation: smallint): smallint;
+begin
+  _intin[0]:=orientation;
+  _contrl[0]:=5;
+  _contrl[1]:=0;
+  _contrl[3]:=1;
+  _contrl[5]:=27;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  v_orient:=_intout[0];
+end;
+
+function v_copies(handle, count: smallint): smallint;
+begin
+  _intin[0]:=count;
+  _contrl[0]:=5;
+  _contrl[1]:=0;
+  _contrl[3]:=1;
+  _contrl[5]:=28;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  v_copies:=_intout[0];
+end;
+
+procedure v_tray(handle, tray: smallint);
+begin
+  _intin[0]:=tray;
+  _contrl[0]:=5;
+  _contrl[1]:=0;
+  _contrl[3]:=1;
+  _contrl[5]:=29;
+  _contrl[6]:=handle;
+
+  vdi;
+end;
+
+function v_page_size(handle, page_id: smallint): smallint;
+begin
+  _intin[0]:=page_id;
+  _contrl[0]:=5;
+  _contrl[1]:=0;
+  _contrl[3]:=1;
+  _contrl[5]:=37;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  v_page_size:=_intout[0];
+end;
+
+function vs_palette(handle, palette: smallint): smallint;
+begin
+  _intin[0]:=palette;
+  _contrl[0]:=5;
+  _contrl[1]:=0;
+  _contrl[3]:=1;
+  _contrl[5]:=60;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  vs_palette:=_intout[0];
+end;
+
+procedure v_sound(handle, frequency, duration: smallint);
+begin
+  _intin[0]:=frequency;
+  _intin[1]:=duration;
+  _contrl[0]:=5;
+  _contrl[1]:=0;
+  _contrl[3]:=2;
+  _contrl[5]:=61;
+  _contrl[6]:=handle;
+
+  vdi;
+end;
+
+function vs_mute(handle, action: smallint): smallint;
+begin
+  _intin[0]:=action;
+  _contrl[0]:=5;
+  _contrl[1]:=0;
+  _contrl[3]:=1;
+  _contrl[5]:=62;
+  _contrl[6]:=handle;
+
+  vdi;
+end;
+
+procedure vt_resolution(handle, xres, yres: smallint;
+                        out xset, yset: smallint);
+begin
+  _intin[0]:=xres;
+  _intin[1]:=yres;
+  _contrl[0]:=5;
+  _contrl[1]:=0;
+  _contrl[3]:=2;
+  _contrl[5]:=81;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  xset:=_intout[0];
+  yset:=_intout[1];
+end;
+
+procedure vt_axis(handle, xres, yres: smallint;
+                  out xset, yset: smallint);
+begin
+  _intin[0]:=xres;
+  _intin[1]:=yres;
+  _contrl[0]:=5;
+  _contrl[1]:=0;
+  _contrl[3]:=2;
+  _contrl[5]:=82;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  xset:=_intout[0];
+  yset:=_intout[1];
+end;
+
+procedure vt_origin(handle, xorigin, yorigin: smallint);
+begin
+  _intin[0]:=xorigin;
+  _intin[1]:=yorigin;
+  _contrl[0]:=5;
+  _contrl[1]:=0;
+  _contrl[3]:=2;
+  _contrl[5]:=83;
+  _contrl[6]:=handle;
+
+  vdi;
+end;
+
+procedure vq_tdimensions(handle: smallint; out xdimension, ydimension: smallint);
+begin
+  _contrl[0]:=5;
+  _contrl[1]:=0;
+  _contrl[3]:=0;
+  _contrl[5]:=84;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  xdimension:=_intout[0];
+  ydimension:=_intout[1];
+end;
+
+procedure vt_alignment(handle, dx, dy: smallint);
+begin
+  _intin[0]:=dx;
+  _intin[1]:=dy;
+  _contrl[0]:=5;
+  _contrl[1]:=0;
+  _contrl[3]:=2;
+  _contrl[5]:=85;
+  _contrl[6]:=handle;
+
+  vdi;
+end;
+
+procedure vsp_film(handle, index, lightness: smallint);
+begin
+  _intin[0]:=index;
+  _intin[1]:=lightness;
+  _contrl[0]:=5;
+  _contrl[1]:=0;
+  _contrl[3]:=2;
+  _contrl[5]:=91;
+  _contrl[6]:=handle;
+
+  vdi;
+end;
+
+function vqp_filmname(handle, index: smallint; out name: String): smallint;
+begin
+  _intin[0]:=index;
+  _contrl[0]:=5;
+  _contrl[1]:=0;
+  _contrl[3]:=1;
+  _contrl[5]:=92;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  vdi_to_string(@_intout[0], name, _contrl[4]);
+  vqp_filmname:=_contrl[4];
+end;
+
+procedure vsc_expose(handle, state: smallint);
+begin
+  _intin[0]:=state;
+  _contrl[0]:=5;
+  _contrl[1]:=0;
+  _contrl[3]:=1;
+  _contrl[5]:=93;
+  _contrl[6]:=handle;
+
+  vdi;
+end;
+
+procedure v_meta_extents(handle, min_x, min_y, max_x, max_y: smallint);
+begin
+  _ptsin[0]:=min_x;
+  _ptsin[1]:=min_y;
+  _ptsin[2]:=max_x;
+  _ptsin[3]:=max_y;
+  _contrl[0]:=5;
+  _contrl[1]:=2;
+  _contrl[3]:=0;
+  _contrl[5]:=98;
+  _contrl[6]:=handle;
+
+  vdi;
+end;
+
+procedure v_write_meta(handle, num_intin: smallint; a_intin: Pointer;
+                       num_ptsin: smallint;a_ptsin: Pointer);
+var pb: TVDIPB;
+begin
+  pb.control := @_contrl;
+  pb.intin := PVDIIntIn(a_intin);
+  pb.ptsin := PVDIPtsIn(a_ptsin);
+  pb.intout := @_intout;
+  pb.ptsout := @_ptsout;
+  _contrl[0]:=5;
+  _contrl[1]:=num_ptsin;
+  _contrl[3]:=num_intin;
+  _contrl[5]:=99;
+  _contrl[6]:=handle;
+
+  vdi(@pb);
+end;
+
+procedure vm_pagesize(handle, pgwidth, pgheight: smallint);
+begin
+  _intin[0]:=0;
+  _intin[1]:=pgwidth;
+  _intin[2]:=pgheight;
+  _contrl[0]:=5;
+  _contrl[1]:=0;
+  _contrl[3]:=3;
+  _contrl[5]:=99;
+  _contrl[6]:=handle;
+
+  vdi;
+end;
+
+procedure vm_coords(handle, llx, lly, urx, ury: smallint);
+begin
+  _intin[0]:=1;
+  _intin[1]:=llx;
+  _intin[2]:=lly;
+  _intin[3]:=urx;
+  _intin[4]:=ury;
+  _contrl[0]:=5;
+  _contrl[1]:=0;
+  _contrl[3]:=5;
+  _contrl[5]:=99;
+  _contrl[6]:=handle;
+
+  vdi;
+end;
+
+function v_bez_qual(handle, prcnt: smallint; out actual: smallint): smallint;
+begin
+  _intin[0]:=32;
+  _intin[1]:=1;
+  _intin[2]:=prcnt;
+  _contrl[0]:=5;
+  _contrl[1]:=0;
+  _contrl[3]:=3;
+  _contrl[5]:=99;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  actual:=_intout[0];
+  v_bez_qual:=_intout[0];
+end;
+
+procedure vm_filename(handle: smallint; const filename: String);
+var len: longint;
+begin
+  len:=string_to_vdi(filename, @_intin[0]);
+  _contrl[0]:=5;
+  _contrl[1]:=0;
+  _contrl[3]:=len;
+  _contrl[5]:=100;
+  _contrl[6]:=handle;
+
+  vdi;
+end;
+
+procedure v_offset(handle, offset: smallint);
+begin
+  _intin[0]:=offset;
+  _contrl[0]:=5;
+  _contrl[1]:=0;
+  _contrl[3]:=1;
+  _contrl[5]:=101;
+  _contrl[6]:=handle;
+
+  vdi;
+end;
+
+procedure v_fontinit(handle: smallint; var fh: TFONT_HDR);
+begin
+  PPointer(@_intin[0])^:=@fh;
+  _contrl[0]:=5;
+  _contrl[1]:=0;
+  _contrl[3]:=2;
+  _contrl[5]:=102;
+  _contrl[6]:=handle;
+
+  vdi;
+end;
+
+procedure v_escape2000(handle, times: smallint);
+begin
+  _intin[0]:=times;
+  _contrl[0]:=5;
+  _contrl[1]:=0;
+  _contrl[3]:=1;
+  _contrl[5]:=2000;
+  _contrl[6]:=handle;
+
+  vdi;
+end;
+
+
+procedure v_pline(handle: smallint; count: smallint; pxyarray: psmallint);
+var pb: TVDIPB;
+begin
+  pb.control := @_contrl;
+  pb.intin := @_intin;
+  // _ptsin[0..2*count-1] = pxyarray[0..2*count-1];
+  pb.ptsin := PVDIPtsIn(pxyarray);
+  pb.intout := @_intout;
+  pb.ptsout := @_ptsout;
+
+  _contrl[0]:=6;
+  _contrl[1]:=count;
+  _contrl[3]:=0;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi(@pb);
+end;
+
+procedure v_pline(handle, count: smallint; const pxyarray: Array of smallint);
+var pb: TVDIPB;
+begin
+  pb.control := @_contrl;
+  pb.intin := @_intin;
+  // _ptsin[0..2*count-1] = pxyarray[0..2*count-1];
+  pb.ptsin := @pxyarray;
+  pb.intout := @_intout;
+  pb.ptsout := @_ptsout;
+
+  _contrl[0]:=6;
+  _contrl[1]:=count;
+  _contrl[3]:=0;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi(@pb);
+end;
+
+procedure v_bez(handle, count: smallint; xyarr, bezarr: Pointer;
+                out extent: ARRAY_4;
+                out totpts, totmoves: smallint);
+var pb: TVDIPB;
+begin
+  pb.control := @_contrl;
+  pb.intin := PVDIIntIn(bezarr);
+  // _ptsin[0..2*count-1] = pxyarray[0..2*count-1];
+  pb.ptsin := PVDIPtsIn(xyarr);
+  pb.intout := @_intout;
+  pb.ptsout := @_ptsout;
+
+  _contrl[0]:=6;
+  _contrl[1]:=count;
+  _contrl[3]:=(count + 1) shr 1;
+  _contrl[5]:=13;
+  _contrl[6]:=handle;
+
+  vdi(@pb);
+
+  totpts:=_intout[0];
+  totmoves:=_intout[1];
+  extent[0]:=_ptsout[0];
+  extent[1]:=_ptsout[1];
+  extent[2]:=_ptsout[2];
+  extent[3]:=_ptsout[3];
+end;
+
+procedure v_pmarker(handle, count: smallint; const pxyarray: Array of smallint);
+var pb: TVDIPB;
+begin
+  pb.control := @_contrl;
+  pb.intin := @_intin;
+  // _ptsin[0..2*count-1] = pxyarray[0..2*count-1];
+  pb.ptsin := @pxyarray;
+  pb.intout := @_intout;
+  pb.ptsout := @_ptsout;
+
+  _contrl[0]:=7;
+  _contrl[1]:=count;
+  _contrl[3]:=0;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi(@pb);
+end;
+
+procedure v_gtext(handle: smallint; x: smallint; y: smallint; outputstring: pchar);
+var len: smallint;
+begin
+  _ptsin[0]:=x;
+  _ptsin[1]:=y;
+
+  len:=pchar_str_to_vdi(outputstring, @_intin[0]);
+
+  _contrl[0]:=8;
+  _contrl[1]:=1;
+  _contrl[3]:=len;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+end;
+
+procedure v_gtext(handle, x, y: smallint; const outputstring: string);
+var len: smallint;
+begin
+  _ptsin[0]:=x;
+  _ptsin[1]:=y;
+
+  len:=string_to_vdi(outputstring, @_intin[0]);
+
+  _contrl[0]:=8;
+  _contrl[1]:=1;
+  _contrl[3]:=len;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+end;
+
+procedure v_fillarea(handle, count: smallint; const pxyarray: Array of smallint);
+var pb: TVDIPB;
+begin
+  pb.control := @_contrl;
+  pb.intin := @_intin;
+  // _ptsin[0..2*count-1] = pxyarray[0..2*count-1];
+  pb.ptsin := @pxyarray;
+  pb.intout := @_intout;
+  pb.ptsout := @_ptsout;
+
+  _contrl[0]:=9;
+  _contrl[1]:=count;
+  _contrl[3]:=0;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi(@pb);
+end;
+
+procedure v_bez_fill(handle, count: smallint;
+                    xyarr, bezarr: Pointer;
+                    out extent: ARRAY_4;
+                    out totpts, totmoves: smallint);
+var pb: TVDIPB;
+begin
+  pb.control := @_contrl;
+  pb.intin := PVDIIntIn(bezarr);
+  // _ptsin[0..2*count-1] = pxyarray[0..2*count-1];
+  pb.ptsin := PVDIPtsIn(xyarr);
+  pb.intout := @_intout;
+  pb.ptsout := @_ptsout;
+
+  _contrl[0]:=9;
+  _contrl[1]:=count;
+  _contrl[3]:=(count + 1) shr 1;
+  _contrl[5]:=13;
+  _contrl[6]:=handle;
+
+  vdi(@pb);
+
+  totpts:=_intout[0];
+  totmoves:=_intout[1];
+  extent[0]:=_ptsout[0];
+  extent[1]:=_ptsout[1];
+  extent[2]:=_ptsout[2];
+  extent[3]:=_ptsout[3];
+end;
+
+procedure v_bar(handle: smallint; pxyarray: psmallint);
+begin
+  // _ptsin[0..3] = pxyarray[0..3];
+  _ptsin[0]:=pxyarray[0];
+  _ptsin[1]:=pxyarray[1];
+  _ptsin[2]:=pxyarray[2];
+  _ptsin[3]:=pxyarray[3];
+  _contrl[0]:=11;
+  _contrl[1]:=2;
+  _contrl[3]:=0;
+  _contrl[5]:=1;
+  _contrl[6]:=handle;
+
+  vdi;
+end;
+
+procedure v_bar(handle: smallint; const pxyarray: ARRAY_4);
+begin
+  // _ptsin[0..3] = pxyarray[0..3];
+  _ptsin[0]:=pxyarray[0];
+  _ptsin[1]:=pxyarray[1];
+  _ptsin[2]:=pxyarray[2];
+  _ptsin[3]:=pxyarray[3];
+  _contrl[0]:=11;
+  _contrl[1]:=2;
+  _contrl[3]:=0;
+  _contrl[5]:=1;
+  _contrl[6]:=handle;
+
+  vdi;
+end;
+
+procedure v_arc(handle, x, y, radius, begang, endang: smallint);
+begin
+  _intin[0]:=begang;
+  _intin[1]:=endang;
+  _ptsin[0]:=x;
+  _ptsin[1]:=y;
+  _ptsin[2]:=0;
+  _ptsin[3]:=0;
+  _ptsin[4]:=0;
+  _ptsin[5]:=0;
+  _ptsin[6]:=radius;
+  _ptsin[7]:=0;
+  _contrl[0]:=11;
+  _contrl[1]:=4;
+  _contrl[3]:=2;
+  _contrl[5]:=2;
+  _contrl[6]:=handle;
+
+  vdi;
+end;
+
+procedure v_pieslice(handle, x, y, radius, begang, endang: smallint);
+begin
+  _intin[0]:=begang;
+  _intin[1]:=endang;
+  _ptsin[0]:=x;
+  _ptsin[1]:=y;
+  _ptsin[2]:=0;
+  _ptsin[3]:=0;
+  _ptsin[4]:=0;
+  _ptsin[5]:=0;
+  _ptsin[6]:=radius;
+  _ptsin[7]:=0;
+  _contrl[0]:=11;
+  _contrl[1]:=4;
+  _contrl[3]:=2;
+  _contrl[5]:=3;
+  _contrl[6]:=handle;
+
+  vdi;
+end;
+
+
+procedure v_circle (handle: smallint; x: smallint; y: smallint; radius: smallint);
+begin
+  _ptsin[0]:=x;
+  _ptsin[1]:=y;
+  _ptsin[2]:=0;
+  _ptsin[3]:=0;
+  _ptsin[4]:=radius;
+  _ptsin[5]:=0;
+
+  _contrl[0]:=11;
+  _contrl[1]:=3;
+  _contrl[3]:=0;
+  _contrl[5]:=4;
+  _contrl[6]:=handle;
+
+  vdi;
+end;
+
+procedure v_ellipse(handle, x, y, xradius, yradius: smallint);
+begin
+  _ptsin[0]:=x;
+  _ptsin[1]:=y;
+  _ptsin[2]:=xradius;
+  _ptsin[3]:=yradius;
+
+  _contrl[0]:=11;
+  _contrl[1]:=2;
+  _contrl[3]:=0;
+  _contrl[5]:=5;
+  _contrl[6]:=handle;
+
+  vdi;
+end;
+
+procedure v_ellarc(handle, x, y, xradius, yradius, begang, endang: smallint);
+begin
+  _intin[0]:=begang;
+  _intin[1]:=endang;
+  _ptsin[0]:=x;
+  _ptsin[1]:=y;
+  _ptsin[2]:=xradius;
+  _ptsin[3]:=yradius;
+
+  _contrl[0]:=11;
+  _contrl[1]:=2;
+  _contrl[3]:=2;
+  _contrl[5]:=6;
+  _contrl[6]:=handle;
+
+  vdi;
+end;
+
+procedure v_ellpie(handle, x, y, xradius, yradius, begang, endang: smallint);
+begin
+  _intin[0]:=begang;
+  _intin[1]:=endang;
+  _ptsin[0]:=x;
+  _ptsin[1]:=y;
+  _ptsin[2]:=xradius;
+  _ptsin[3]:=yradius;
+
+  _contrl[0]:=11;
+  _contrl[1]:=2;
+  _contrl[3]:=2;
+  _contrl[5]:=7;
+  _contrl[6]:=handle;
+
+  vdi;
+end;
+
+procedure v_rbox(handle: smallint; const xyarray: ARRAY_4);
+begin
+  _ptsin[0]:=xyarray[0];
+  _ptsin[1]:=xyarray[1];
+  _ptsin[2]:=xyarray[2];
+  _ptsin[3]:=xyarray[3];
+
+  _contrl[0]:=11;
+  _contrl[1]:=2;
+  _contrl[3]:=0;
+  _contrl[5]:=8;
+  _contrl[6]:=handle;
+
+  vdi;
+end;
+
+procedure v_rfbox(handle: smallint; const xyarray: ARRAY_4);
+begin
+  _ptsin[0]:=xyarray[0];
+  _ptsin[1]:=xyarray[1];
+  _ptsin[2]:=xyarray[2];
+  _ptsin[3]:=xyarray[3];
+
+  _contrl[0]:=11;
+  _contrl[1]:=2;
+  _contrl[3]:=0;
+  _contrl[5]:=9;
+  _contrl[6]:=handle;
+
+  vdi;
+end;
+
+procedure v_justified(handle, x, y: smallint;
+        const outputstring: string;
+        width, wordspace, charspace: smallint);
+var len: smallint;
+begin
+  {* TODO: handle char_space $8000/$8001 (returns interspace information) *}
+  _intin[0]:=wordspace;
+  _intin[1]:=charspace;
+  _ptsin[0]:=x;
+  _ptsin[1]:=y;
+  _ptsin[2]:=width;
+  _ptsin[3]:=0;
+
+  len:=string_to_vdi(outputstring, @_intin[2]);
+
+  _contrl[0]:=11;
+  _contrl[1]:=2;
+  _contrl[3]:=len+2;
+  _contrl[4]:=0;
+  _contrl[5]:=11;
+  _contrl[6]:=handle;
+
+  vdi;
+end;
+
+function v_bez_on(handle: smallint): smallint;
+begin
+  _contrl[0]:=11;
+  _contrl[1]:=1;
+  _contrl[3]:=0;
+  _contrl[5]:=13;
+  _contrl[6]:=handle;
+  _intout[0]:=0;
+
+  vdi;
+
+  v_bez_on:=_intout[0];
+end;
+
+procedure v_bez_off(handle: smallint);
+begin
+  _contrl[0]:=11;
+  _contrl[1]:=0;
+  _contrl[3]:=0;
+  _contrl[5]:=13;
+  _contrl[6]:=handle;
+
+  vdi;
+end;
+
+procedure vst_height(handle, height: smallint; out char_width, char_height, cell_width, cell_height: smallint);
+begin
+  _ptsin[0]:=0;
+  _ptsin[1]:=height;
+
+  _contrl[0]:=12;
+  _contrl[1]:=1;
+  _contrl[3]:=0;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  char_width:=_ptsout[0];
+  char_height:=_ptsout[1];
+  cell_width:=_ptsout[2];
+  cell_height:=_ptsout[3];
+end;
+
+function vst_rotation(handle, angle: smallint): smallint;
+begin
+  _intin[0]:=angle;
+
+  _contrl[0]:=13;
+  _contrl[1]:=0;
+  _contrl[3]:=1;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  vst_rotation:=_intout[0];
+end;
+
+procedure vs_color(handle: smallint; index: smallint; rgb_in: psmallint);
+begin
+  _intin[0]:=index;
+  _intin[1]:=rgb_in[0];
+  _intin[2]:=rgb_in[1];
+  _intin[3]:=rgb_in[2];
+
+  _contrl[0]:=14;
+  _contrl[1]:=0;
+  _contrl[3]:=4;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+end;
+
+procedure vs_color(handle, index: smallint; const rgb_in: ARRAY_3);
+begin
+  _intin[0]:=index;
+  _intin[1]:=rgb_in[0];
+  _intin[2]:=rgb_in[1];
+  _intin[3]:=rgb_in[2];
+
+  _contrl[0]:=14;
+  _contrl[1]:=0;
+  _contrl[3]:=4;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+end;
+
+function vsl_type(handle, style: smallint): smallint;
+begin
+  _intin[0]:=style;
+
+  _contrl[0]:=15;
+  _contrl[1]:=0;
+  _contrl[3]:=1;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  vsl_type:=_intout[0];
+end;
+
+function vsl_width(handle, width: smallint): smallint;
+begin
+  _ptsin[0]:=width;
+  _ptsin[1]:=0;
+
+  _contrl[0]:=16;
+  _contrl[1]:=1;
+  _contrl[3]:=0;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  vsl_width:=_ptsout[0];
+end;
+
+function vsl_color(handle: smallint; color_index: smallint): smallint;
+begin
+  _intin[0]:=color_index;
+
+  _contrl[0]:=17;
+  _contrl[1]:=0;
+  _contrl[3]:=1;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  vsl_color:=_intout[0];
+end;
+
+function vsm_type(handle, symbol: smallint): smallint;
+begin
+  _intin[0]:=symbol;
+
+  _contrl[0]:=18;
+  _contrl[1]:=0;
+  _contrl[3]:=1;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  vsm_type:=_intout[0];
+end;
+
+function vsm_height(handle, height: smallint): smallint;
+begin
+  _ptsin[0]:=0;
+  _ptsin[1]:=height;
+
+  _contrl[0]:=19;
+  _contrl[1]:=1;
+  _contrl[3]:=0;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  vsm_height:=_ptsout[1];
+end;
+
+function vsm_color(handle, color_index: smallint): smallint;
+begin
+  _intin[0]:=color_index;
+
+  _contrl[0]:=20;
+  _contrl[1]:=0;
+  _contrl[3]:=1;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  vsm_color:=_intout[0];
+end;
+
+function vst_font(handle, font: smallint): smallint;
+begin
+  _intin[0]:=font;
+
+  _contrl[0]:=21;
+  _contrl[1]:=0;
+  _contrl[3]:=1;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  vst_font:=_intout[0];
+end;
+
+function vst_color(handle: smallint; color_index: smallint): smallint;
+begin
+  _intin[0]:=color_index;
+
+  _contrl[0]:=22;
+  _contrl[1]:=0;
+  _contrl[3]:=1;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  vst_color:=_intout[0];
+end;
+
+function vsf_interior(handle, style: smallint): smallint;
+begin
+  _intin[0]:=style;
+
+  _contrl[0]:=23;
+  _contrl[1]:=0;
+  _contrl[3]:=1;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  vsf_interior:=_intout[0];
+end;
+
+function vsf_style(handle, style_index: smallint): smallint;
+begin
+  _intin[0]:=style_index;
+
+  _contrl[0]:=24;
+  _contrl[1]:=0;
+  _contrl[3]:=1;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  vsf_style:=_intout[0];
+end;
+
+function vsf_color(handle: smallint; color_index: smallint): smallint;
+begin
+  _intin[0]:=color_index;
+
+  _contrl[0]:=25;
+  _contrl[1]:=0;
+  _contrl[3]:=1;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  vsf_color:=_intout[0];
+end;
+
+function vq_color(handle, color_index, set_flag: smallint; out rgb: ARRAY_3): smallint;
+begin
+  _intin[0]:=color_index;
+  _intin[1]:=set_flag;
+
+  _contrl[0]:=26;
+  _contrl[1]:=0;
+  _contrl[3]:=2;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  rgb[0]:=_intout[1];
+  rgb[1]:=_intout[2];
+  rgb[2]:=_intout[3];
+  vq_color:=_intout[0];
+end;
+
+procedure vrq_locator(handle, x, y: smallint; out xout, yout, term: smallint);
+begin
+  _ptsin[0]:=x;
+  _ptsin[1]:=y;
+
+  _contrl[0]:=28;
+  _contrl[1]:=1;
+  _contrl[3]:=0;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  xout:=_ptsout[0];
+  yout:=_ptsout[1];
+  term:=_intout[0];
+end;
+
+function vsm_locator(handle, x, y: smallint; out xout, yout, term: smallint): smallint;
+begin
+  _ptsin[0]:=x;
+  _ptsin[1]:=y;
+
+  _contrl[0]:=28;
+  _contrl[1]:=1;
+  _contrl[3]:=0;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  xout:=_ptsout[0];
+  yout:=_ptsout[1];
+  term:=_intout[0];
+
+  vsm_locator:=(_contrl[4] shl 1) or (_contrl[2]);
+end;
+
+procedure vrq_valuator(handle, valuator_in: smallint; out valuator_out, terminator: smallint);
+begin
+  _intin[0]:=valuator_in;
+
+  _contrl[0]:=29;
+  _contrl[1]:=0;
+  _contrl[3]:=1;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  valuator_out:=_intout[0];
+  terminator:=_intout[1];
+end;
+
+procedure vsm_valuator(handle, val_in: smallint; out val_out, term, status: smallint);
+begin
+  _intin[0]:=val_in;
+
+  _contrl[0]:=29;
+  _contrl[1]:=0;
+  _contrl[3]:=1;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  val_out:=_intout[0];
+  term:=_intout[1];
+  status:=_contrl[4];
+end;
+
+procedure vrq_choice(handle, ch_in: smallint; out ch_out: smallint);
+begin
+  _intin[0]:=ch_in;
+
+  _contrl[0]:=30;
+  _contrl[1]:=0;
+  _contrl[3]:=1;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  ch_out:=_intout[0];
+end;
+
+function vsm_choice(handle: smallint; out choice: smallint): smallint;
+begin
+  _intin[0]:=choice;
+
+  _contrl[0]:=30;
+  _contrl[1]:=0;
+  _contrl[3]:=0;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  choice:=_intout[0];
+  vsm_choice:=_contrl[4];
+end;
+
+procedure vrq_string(handle, max_length, echo_mode: smallint; const echo_xy: ARRAY_2; out resString: string);
+begin
+  _intin[0]:=max_length;
+  _intin[1]:=echo_mode;
+  _ptsin[0]:=echo_xy[0];
+  _ptsin[1]:=echo_xy[1];
+
+  _contrl[0]:=31;
+  _contrl[1]:=1;
+  _contrl[3]:=2;
+  _contrl[4]:=0;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  vdi_to_string(@_intout, resString, _contrl[4]);
+end;
+
+function vsm_string(handle, max_length, echo_mode: smallint; const echo_xy: ARRAY_2; out resString: string): smallint;
+begin
+  _intin[0]:=max_length;
+  _intin[1]:=echo_mode;
+  _ptsin[0]:=echo_xy[0];
+  _ptsin[1]:=echo_xy[1];
+
+  _contrl[0]:=31;
+  _contrl[1]:=1;
+  _contrl[3]:=2;
+  _contrl[4]:=0;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  vdi_to_string(@_intout, resString, _contrl[4]);
+  vsm_string:=_contrl[4];
+end;
+
+function vswr_mode(handle: smallint; mode: smallint): smallint;
+begin
+  _intin[0]:=mode;
+
+  _contrl[0]:=32;
+  _contrl[1]:=0;
+  _contrl[3]:=1;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  vswr_mode:=_intout[0];
+end;
+
+function vsin_mode(handle, dev_type, mode: smallint): smallint;
+begin
+  _intin[0]:=mode;
+  _intin[1]:=dev_type;
+
+  _contrl[0]:=33;
+  _contrl[1]:=0;
+  _contrl[3]:=2;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  vsin_mode:=_intout[0];
+end;
+
+procedure vql_attributes(handle: smallint; out attrib: ARRAY_4);
+begin
+  _contrl[0]:=35;
+  _contrl[1]:=0;
+  _contrl[3]:=0;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  attrib[0]:=_intout[0];
+  attrib[1]:=_intout[1];
+  attrib[2]:=_intout[2];
+  attrib[3]:=_ptsout[0];
+end;
+
+procedure vql_attributes(handle: smallint; out attrib: ARRAY_6);
+begin
+  _contrl[0]:=35;
+  _contrl[1]:=0;
+  _contrl[3]:=0;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  attrib[0]:=_intout[0];
+  attrib[1]:=_intout[1];
+  attrib[2]:=_intout[2];
+  attrib[3]:=_ptsout[0];
+  {* TOS/EmuTOS do not return the line end styles in intout[3/4] *}
+  if (_contrl[4] >= 5) then
+    begin
+      attrib[4]:=_intout[3];
+      attrib[5]:=_intout[4];
+    end else begin
+      attrib[4]:=0;
+      attrib[5]:=0;
+    end;
+end;
+
+procedure vqm_attributes(handle: smallint; out attrib: ARRAY_4);
+begin
+  _contrl[0]:=36;
+  _contrl[1]:=0;
+  _contrl[3]:=0;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  attrib[0]:=_intout[0];
+  attrib[1]:=_intout[1];
+  attrib[2]:=_intout[2];
+  attrib[3]:=_ptsout[0];
+end;
+
+procedure vqf_attributes(handle: smallint; out attrib: ARRAY_5);
+begin
+  _contrl[0]:=37;
+  _contrl[1]:=0;
+  _contrl[3]:=0;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  attrib[0]:=_intout[0];
+  attrib[1]:=_intout[1];
+  attrib[2]:=_intout[2];
+  attrib[3]:=_intout[3];
+  attrib[4]:=_intout[4];
+end;
+
+procedure vqt_attributes(handle: smallint; out attrib: ARRAY_10);
+begin
+  _contrl[0]:=38;
+  _contrl[1]:=0;
+  _contrl[3]:=0;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  attrib[0]:=_intout[0];
+  attrib[1]:=_intout[1];
+  attrib[2]:=_intout[2];
+  attrib[3]:=_intout[3];
+  attrib[4]:=_intout[4];
+  attrib[5]:=_intout[5];
+  attrib[6]:=_ptsout[0];
+  attrib[7]:=_ptsout[1];
+  attrib[8]:=_ptsout[2];
+  attrib[9]:=_ptsout[3];
+end;
+
+procedure vst_alignment(handle, hor_in, vert_in: smallint; out hor_out, vert_out: smallint);
+begin
+  _intin[0]:=hor_in;
+  _intin[1]:=vert_in;
+
+  _contrl[0]:=39;
+  _contrl[1]:=0;
+  _contrl[3]:=2;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  hor_out:=_intout[0];
+  vert_out:=_intout[1];
+end;
+
+procedure v_opnvwk(work_in: psmallint; handle: psmallint; work_out: psmallint);
+var pb: TVDIPB;
+begin
+  pb.control := @_contrl;
+  // _intin[0..10] = work_in[0..10];
+  pb.intin := PVDIIntIn(work_in);
+  pb.ptsin := @_ptsin;
+  // work_out[0..44] = intout[0..44];
+  pb.intout := PVDIIntOut(work_out);
+  // work_out[45..56] = ptsout[0..11];
+  pb.ptsout := PVDIPtsOut(@work_out[45]);
+
+  _contrl[0]:=100;
+  _contrl[1]:=0;
+  _contrl[3]:=11;
+  _contrl[5]:=0;
+  _contrl[6]:=handle^;
+
+  vdi(@pb);
+
+  handle^:=_contrl[6];
+end;
+
+procedure v_clsvwk(handle: smallint);
+begin
+  _contrl[0]:=101;
+  _contrl[1]:=0;
+  _contrl[3]:=0;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+end;
+
+procedure vq_extnd(handle, owflag: smallint; WorkOut: psmallint);
+var pb: TVDIPB;
+begin
+  pb.control := @_contrl;
+  pb.intin := @_intin;
+  pb.ptsin := @_ptsin;
+  // work_out[0..44] = intout[0..44];
+  pb.intout := PVDIIntOut(workout);
+  // work_out[45..56] = ptsout[0..11];
+  pb.ptsout := PVDIPtsOut(@workout[45]);
+
+  _intin[0]:=owflag;
+
+  _contrl[0]:=102;
+  _contrl[1]:=0;
+  _contrl[3]:=1;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi(@pb);
+end;
+
+
+procedure vq_scrninfo(handle: smallint; out WorkOut: ARRAY_273);
+var pb: TVDIPB;
+begin
+  pb.control := @_contrl;
+  pb.intin := @_intin;
+  pb.ptsin := @_ptsin;
+  pb.intout := @workout;
+  pb.ptsout := @_ptsout;
+
+  _intin[0]:=2;
+
+  _contrl[0]:=102;
+  _contrl[1]:=0;
+  _contrl[3]:=1;
+  _contrl[5]:=1;
+  _contrl[6]:=handle;
+
+  vdi(@pb);
+end;
+
+procedure v_contourfill(handle, x, y, index: smallint);
+begin
+  _intin[0]:=index;
+  _ptsin[0]:=x;
+  _ptsin[1]:=y;
+  _contrl[0]:=103;
+  _contrl[1]:=1;
+  _contrl[3]:=1;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+end;
+
+function vsf_perimeter(handle, per_vis: smallint): smallint;
+begin
+  _intin[0]:=per_vis;
+  _contrl[0]:=104;
+  _contrl[1]:=0;
+  _contrl[3]:=1;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  vsf_perimeter:=_intout[0];
+end;
+
+procedure v_get_pixel(handle: smallint; x: smallint; y: smallint;
+                      pel: psmallint; index: psmallint);
+begin
+  _ptsin[0]:=x;
+  _ptsin[1]:=y;
+  _contrl[0]:=105;
+  _contrl[1]:=1;
+  _contrl[3]:=0;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  pel^:=_intout[0];
+  index^:=_intout[1];
+end;
+
+procedure v_get_pixel(handle, x, y: smallint; out pel, index: smallint);
+begin
+  _ptsin[0]:=x;
+  _ptsin[1]:=y;
+  _contrl[0]:=105;
+  _contrl[1]:=1;
+  _contrl[3]:=0;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  pel:=_intout[0];
+  index:=_intout[1];
+end;
+
+function vst_effects(handle, effect: smallint): smallint;
+begin
+  _intin[0]:=effect;
+  _contrl[0]:=106;
+  _contrl[1]:=0;
+  _contrl[3]:=1;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  vst_effects:=_intout[0];
+end;
+
+function vst_point(handle, point: smallint; out char_width, char_height, cell_width, cell_height: smallint): smallint;
+begin
+  _intin[0]:=point;
+  _contrl[0]:=107;
+  _contrl[1]:=0;
+  _contrl[3]:=1;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  char_width:=_ptsout[0];
+  char_height:=_ptsout[1];
+  cell_width:=_ptsout[2];
+  cell_height:=_ptsout[3];
+end;
+
+procedure vsl_ends(handle, beg_style, end_style: smallint);
+begin
+  _intin[0]:=beg_style;
+  _intin[1]:=end_style;
+  _contrl[0]:=108;
+  _contrl[1]:=0;
+  _contrl[3]:=2;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+end;
+
+procedure vro_cpyfm(handle: smallint; vr_mode: smallint; pxyarray: psmallint; psrcMFDB: PMFDB; pdesMFDB: PMFDB);
+begin
+  _intin[0]:=vr_mode;
+  _ptsin[0]:=pxyarray[0];
+  _ptsin[1]:=pxyarray[1];
+  _ptsin[2]:=pxyarray[2];
+  _ptsin[3]:=pxyarray[3];
+  _ptsin[4]:=pxyarray[4];
+  _ptsin[5]:=pxyarray[5];
+  _ptsin[6]:=pxyarray[6];
+  _ptsin[7]:=pxyarray[7];
+
+  PPointer(@_contrl[7])^:=psrcMFDB;
+  PPointer(@_contrl[9])^:=pdesMFDB;
+
+  _contrl[0]:=109;
+  _contrl[1]:=4;
+  _contrl[3]:=1;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+end;
+
+procedure vr_trnfm(handle: smallint; psrcMFDB, pdesMFDB: PMFDB);
+begin
+  PPointer(@_contrl[7])^:=psrcMFDB;
+  PPointer(@_contrl[9])^:=pdesMFDB;
+
+  _contrl[0]:=110;
+  _contrl[1]:=0;
+  _contrl[3]:=0;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+end;
+
+procedure vr_trnfm(handle: smallint; const psrcMFDB, pdesMFDB: TMFDB);
+begin
+  PPointer(@_contrl[7])^:=@psrcMFDB;
+  PPointer(@_contrl[9])^:=@pdesMFDB;
+
+  _contrl[0]:=110;
+  _contrl[1]:=0;
+  _contrl[3]:=0;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+end;
+
+procedure vsc_form(handle: smallint; pcur_form: PMFORM);
+var pb: TVDIPB;
+begin
+  {* TODO: NVDI also returns current form in intout *}
+  pb.control := @_contrl;
+  pb.intin := PVDIIntIn(pcur_form);
+  pb.ptsin := @_ptsin;
+  pb.intout := @_intout;
+  pb.ptsout := @_ptsout;
+  _contrl[0]:=111;
+  _contrl[1]:=0;
+  _contrl[3]:=37;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi(@pb);
+end;
+
+procedure vsf_udpat(handle: smallint; pfill_pat: Pointer; planes: smallint);
+var pb: TVDIPB;
+begin
+  pb.control := @_contrl;
+  pb.intin := PVDIIntIn(pfill_pat);
+  pb.ptsin := @_ptsin;
+  pb.intout := @_intout;
+  pb.ptsout := @_ptsout;
+  _contrl[0]:=112;
+  _contrl[1]:=0;
+  _contrl[3]:=planes*16;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi(@pb);
+end;
+
+procedure vsl_udsty(handle, pattern: smallint);
+begin
+  _intin[0]:=pattern;
+  _contrl[0]:=113;
+  _contrl[1]:=0;
+  _contrl[3]:=1;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+end;
+
+procedure vr_recfl(handle: smallint; const pxyarray: ARRAY_4);
+begin
+  _ptsin[0]:=pxyarray[0];
+  _ptsin[1]:=pxyarray[1];
+  _ptsin[2]:=pxyarray[2];
+  _ptsin[3]:=pxyarray[3];
+  _contrl[0]:=114;
+  _contrl[1]:=2;
+  _contrl[3]:=0;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+end;
+
+procedure vqin_mode(handle, dev_type: smallint; out input_mode: smallint);
+begin
+  _intin[0]:=dev_type;
+  _contrl[0]:=115;
+  _contrl[1]:=0;
+  _contrl[3]:=1;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  input_mode:=_intout[0];
+end;
+
+procedure vqt_extent(handle: smallint; calcString: pchar; extent: psmallint);
+var len: smallint;
+begin
+  len:=pchar_str_to_vdi(calcstring, @_intin[0]);
+  _contrl[0]:=116;
+  _contrl[1]:=0;
+  _contrl[3]:=len;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  extent[0]:=_ptsout[0];
+  extent[1]:=_ptsout[1];
+  extent[2]:=_ptsout[2];
+  extent[3]:=_ptsout[3];
+  extent[4]:=_ptsout[4];
+  extent[5]:=_ptsout[5];
+  extent[6]:=_ptsout[6];
+  extent[7]:=_ptsout[7];
+end;
+
+function vqt_width(handle, character: smallint; out cell_width, left_delta, right_delta: smallint): smallint;
+begin
+  _intin[0]:=character;
+  _contrl[0]:=117;
+  _contrl[1]:=0;
+  _contrl[3]:=1;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  cell_width:=_ptsout[0];
+  left_delta:=_ptsout[2];
+  right_delta:=_ptsout[4];
+  vqt_width:=_intout[0];
+end;
+
+procedure vex_timv(handle: smallint; tim_addr: Pointer; out otim_addr: Pointer; out tim_conv: smallint);
+begin
+  _contrl[0]:=118;
+  _contrl[1]:=0;
+  _contrl[3]:=0;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+  PPointer(@_contrl[7])^:=tim_addr;
+
+  vdi;
+
+  otim_addr:=PPointer(@_contrl[9])^;
+  tim_conv:=_intout[0];
+end;
+
+function vst_load_fonts(handle, select: smallint): smallint;
+begin
+  _intin[0]:=select;
+
+  _contrl[0]:=119;
+  _contrl[1]:=0;
+  _contrl[3]:=1;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  vst_load_fonts:=_intout[0];
+end;
+
+procedure vst_unload_fonts(handle, select: smallint);
+begin
+  _intin[0]:=select;
+
+  _contrl[0]:=120;
+  _contrl[1]:=0;
+  _contrl[3]:=1;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+end;
+
+procedure vrt_cpyfm(handle: smallint; vr_mode: smallint; pxyarray: psmallint; psrcMFDB: PMFDB; pdesMFDB: PMFDB; color_index: psmallint);
+begin
+  _intin[0]:=vr_mode;
+  _intin[1]:=color_index[0];
+  _intin[2]:=color_index[1];
+  _ptsin[0]:=pxyarray[0];
+  _ptsin[1]:=pxyarray[1];
+  _ptsin[2]:=pxyarray[2];
+  _ptsin[3]:=pxyarray[3];
+  _ptsin[4]:=pxyarray[4];
+  _ptsin[5]:=pxyarray[5];
+  _ptsin[6]:=pxyarray[6];
+  _ptsin[7]:=pxyarray[7];
+
+  PPointer(@_contrl[7])^:=psrcMFDB;
+  PPointer(@_contrl[9])^:=pdesMFDB;
+
+  _contrl[0]:=121;
+  _contrl[1]:=4;
+  _contrl[3]:=3;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+end;
+
+procedure v_show_c(handle: smallint; reset: smallint);
+begin
+  _intin[0]:=reset;
+
+  _contrl[0]:=122;
+  _contrl[1]:=0;
+  _contrl[3]:=1;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+end;
+
+procedure v_hide_c(handle: smallint);
+begin
+  _contrl[0]:=123;
+  _contrl[1]:=0;
+  _contrl[3]:=0;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+end;
+
+procedure vq_mouse(handle: smallint; out pstatus, x, y: smallint);
+begin
+  _contrl[0]:=124;
+  _contrl[1]:=0;
+  _contrl[3]:=0;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  pstatus:=_intout[0];
+  x:=_ptsout[0];
+  y:=_ptsout[1];
+end;
+
+procedure vex_butv(handle: smallint; pusrcode: Pointer; out psavcode: Pointer);
+begin
+  _contrl[0]:=125;
+  _contrl[1]:=0;
+  _contrl[3]:=0;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+  PPointer(@_contrl[7])^:=pusrcode;
+
+  vdi;
+
+  psavcode:=PPointer(@_contrl[9])^;
+end;
+
+procedure vex_motv(handle: smallint; pusrcode: Pointer; out psavcode: Pointer);
+begin
+  _contrl[0]:=126;
+  _contrl[1]:=0;
+  _contrl[3]:=0;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+  PPointer(@_contrl[7])^:=pusrcode;
+
+  vdi;
+
+  psavcode:=PPointer(@_contrl[9])^;
+end;
+
+procedure vex_curv(handle: smallint; pusrcode: Pointer; out psavcode: Pointer);
+begin
+  _contrl[0]:=127;
+  _contrl[1]:=0;
+  _contrl[3]:=0;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+  PPointer(@_contrl[7])^:=pusrcode;
+
+  vdi;
+
+  psavcode:=PPointer(@_contrl[9])^;
+end;
+
+procedure vq_key_s(handle: smallint; out pstatus: smallint);
+begin
+  _contrl[0]:=128;
+  _contrl[1]:=0;
+  _contrl[3]:=0;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  pstatus:=_intout[0];
+end;
+
+procedure vs_clip(handle: smallint; clip_flag: smallint; pxyarray: psmallint);
+begin
+  _intin[0]:=clip_flag;
+  _ptsin[0]:=pxyarray[0];
+  _ptsin[1]:=pxyarray[1];
+  _ptsin[2]:=pxyarray[2];
+  _ptsin[3]:=pxyarray[3];
+
+  _contrl[0]:=129;
+  _contrl[1]:=2;
+  _contrl[3]:=1;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+end;
+
+procedure vs_clip(handle, clip_flag: smallint; const pxyarray: ARRAY_4);
+begin
+  _intin[0]:=clip_flag;
+  _ptsin[0]:=pxyarray[0];
+  _ptsin[1]:=pxyarray[1];
+  _ptsin[2]:=pxyarray[2];
+  _ptsin[3]:=pxyarray[3];
+
+  _contrl[0]:=129;
+  _contrl[1]:=2;
+  _contrl[3]:=1;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+end;
+
+procedure vs_clip_off(handle: smallint);
+begin
+  _intin[0]:=0;
+  _ptsin[0]:=0;
+  _ptsin[1]:=0;
+  _ptsin[2]:=0;
+  _ptsin[3]:=0;
+
+  _contrl[0]:=129;
+  _contrl[1]:=2;
+  _contrl[3]:=1;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+end;
+
+function vqt_name(handle, element_num: smallint; out name: String33): smallint;
+begin
+  _intin[0]:=element_num;
+
+  _contrl[0]:=130;
+  _contrl[1]:=0;
+  _contrl[3]:=1;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  vdi_to_string(@_intout[1], name, _contrl[4] - 1);
+
+  vqt_name:=_intout[0];
+end;
+
+procedure vqt_fontinfo(handle: smallint;
+        out minADE, maxADE: smallint;
+        out distances: ARRAY_5;
+        out maxwidth: smallint;
+        out effects: ARRAY_3);
+begin
+  _contrl[0]:=131;
+  _contrl[1]:=0;
+  _contrl[3]:=0;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  minADE:=_intout[0];
+  maxADE:=_intout[1];
+  maxwidth:=_ptsout[0];
+  distances[0]:=_ptsout[1];
+  distances[1]:=_ptsout[3];
+  distances[2]:=_ptsout[5];
+  distances[3]:=_ptsout[7];
+  distances[4]:=_ptsout[9];
+  effects[0]:=_ptsout[2];
+  effects[1]:=_ptsout[4];
+  effects[2]:=_ptsout[6];
+end;
+
+procedure vqt_justified(handle, x, y: smallint; const outString: String;
+            length, word_space, char_space: smallint;
+            offsets: Pointer);
+var len: smallint;
+var pb: TVDIPB;
+begin
+  pb.control := @_contrl;
+  pb.intin := @_intin;
+  pb.ptsin := @_ptsin;
+  pb.intout := @_intout;
+  pb.ptsout := PVDIPtsOut(offsets);
+  _intin[0]:=word_space;
+  _intin[1]:=char_space;
+  len:=string_to_vdi(outstring, @_intin[2]);
+  _ptsin[0]:=x;
+  _ptsin[1]:=y;
+  _ptsin[2]:=length;
+  _ptsin[3]:=0;
+  _contrl[0]:=132;
+  _contrl[1]:=2;
+  _contrl[3]:=len+2;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi(@pb);
+end;
+
+procedure vex_wheelv(handle: smallint; pusrcode: Pointer; out psavcode: Pointer);
+begin
+  _contrl[0]:=134;
+  _contrl[1]:=0;
+  _contrl[3]:=0;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+  PPointer(@_contrl[7])^:=pusrcode;
+
+  vdi;
+
+  psavcode:=PPointer(@_contrl[9])^;
+end;
+
+
+procedure vst_width(handle, width: smallint; out char_width, char_height, cell_width, cell_height: smallint);
+begin
+  _intin[0]:=width;
+  _contrl[0]:=231;
+  _contrl[1]:=0;
+  _contrl[3]:=1;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  char_width:=_intout[0];
+  char_height:=_intout[1];
+  cell_width:=_intout[2];
+  cell_height:=_intout[3];
+end;
+
+procedure vqt_fontheader(handle: smallint; buffer: Pointer;
+                         out pathname: String);
+begin
+  Ppointer(@_intin[0])^:=buffer;
+  _contrl[0]:=232;
+  _contrl[1]:=0;
+  _contrl[3]:=2;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  vdi_to_string(@_intout[0], pathname, _contrl[4]);
+end;
+
+procedure vqt_trackkern(handle: smallint; out x, y: fix31);
+begin
+  _contrl[0]:=234;
+  _contrl[1]:=0;
+  _contrl[3]:=0;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  x:=PLongint(@_intout[0])^;
+  y:=PLongint(@_intout[2])^;
+end;
+
+procedure vqt_pairkern(handle, ch1, ch2: smallint; out x, y: fix31);
+begin
+  _intin[0]:=ch1;
+  _intin[2]:=ch2;
+  _contrl[0]:=235;
+  _contrl[1]:=0;
+  _contrl[3]:=2;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  x:=PLongint(@_intout[0])^;
+  y:=PLongint(@_intout[2])^;
+end;
+
+
+procedure vst_charmap(handle, mode: smallint);
+begin
+  _intin[0]:=mode;
+  _contrl[0]:=236;
+  _contrl[1]:=0;
+  _contrl[3]:=1;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+end;
+
+function vst_map_mode(handle, mode: smallint): smallint;
+begin
+  _intin[0]:=mode;
+  _intin[1]:=1;
+  _contrl[0]:=236;
+  _contrl[1]:=0;
+  _contrl[3]:=2;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  vst_map_mode:=_intout[0];
+end;
+
+procedure vst_kern(handle, tmode, pmode: smallint; out tracks, pairs: smallint);
+begin
+  _intin[0]:=tmode;
+  _intin[1]:=pmode;
+  _contrl[0]:=237;
+  _contrl[1]:=0;
+  _contrl[3]:=2;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  tracks:=_intout[0];
+  pairs:=_intout[0];
+end;
+
+procedure vst_track_offset(handle: smallint; offset: fix31; pairmode: smallint; out tracks, pairs: smallint);
+begin
+  _intin[0]:=255;
+  _intin[1]:=pairmode;
+  PLongint(@_intin[2])^:=offset;
+  _contrl[0]:=237;
+  _contrl[1]:=0;
+  _contrl[3]:=4;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  tracks:=_intout[0];
+  pairs:=_intout[0];
+end;
+
+procedure v_getbitmap_info(handle, ch: smallint;
+                           out advx, advy, xoff, yoff: fix31;
+                           out width, height: smallint;
+                           out bitmap: pointer);
+begin
+  _intin[0]:=ch;
+  _contrl[0]:=239;
+  _contrl[1]:=0;
+  _contrl[3]:=1;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  width:=_intout[0];
+  height:=_intout[1];
+  advx:=PLongint(@_intout[2])^;
+  advy:=PLongint(@_intout[4])^;
+  xoff:=PLongint(@_intout[6])^;
+  yoff:=PLongint(@_intout[8])^;
+  if (bitmap <> nil) then
+    bitmap:=PPointer(@_intout[10])^;
+end;
+
+
+procedure v_ftext(handle, x, y: smallint; const str: String);
+var len: longint;
+begin
+  len:=string_to_vdi(str, @_intin[0]);
+  _ptsin[0]:=x;
+  _ptsin[0]:=y;
+  _contrl[0]:=241;
+  _contrl[1]:=1;
+  _contrl[3]:=len;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+end;
+
+procedure v_ftext_offset(handle, x, y: smallint;
+                         const outputstring: string;
+                         const offset: Array of smallint);
+var i, len: longint;
+    src, dst: psmallint;
+begin
+  len:=string_to_vdi(outputstring, @_intin[0]);
+  _ptsin[0]:=x;
+  _ptsin[1]:=y;
+  src:=offset;
+  dst:=@_ptsin[2];
+  for i:=0 to len-1 do
+    begin
+      dst^:=src^;
+      inc(dst);
+      inc(src);
+      dst^:=src^;
+      inc(dst);
+      inc(src);
+    end;
+  _contrl[0]:=241;
+  _contrl[1]:=len+1;
+  _contrl[3]:=len;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+end;
+
+procedure v_killoutline(handle: smallint; component: Pointer);
+begin
+  PPointer(@_intin[0])^:=component;
+  _contrl[0]:=242;
+  _contrl[1]:=0;
+  _contrl[3]:=2;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+end;
+
+procedure v_getoutline(handle, ch: smallint;
+                       const xyarray: Array of smallint;
+                       const bezarray: Array of ShortInt;
+                       maxverts: smallint;
+                       out numverts: smallint);
+begin
+  _intin[0]:=ch;
+  _intin[1]:=maxverts;
+  PPointer(@_intin[2])^:=@xyarray;
+  PPointer(@_intin[4])^:=@bezarray;
+  _contrl[0]:=243;
+  _contrl[1]:=0;
+  _contrl[3]:=6;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  numverts:=_intout[0];
+end;
+
+procedure vst_scratch(handle, mode: smallint);
+begin
+  _intin[0]:=mode;
+  _contrl[0]:=244;
+  _contrl[1]:=0;
+  _contrl[3]:=1;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+end;
+
+procedure vst_error(handle, mode: smallint; out errorvar: smallint);
+begin
+  _intin[0]:=mode;
+  PPointer(@_intin[1])^:=@errorvar;
+  _contrl[0]:=245;
+  _contrl[1]:=0;
+  _contrl[3]:=3;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+end;
+
+function vst_arbpt(handle, point: smallint;
+                   out chwd, chht, cellwd, cellht: smallint): smallint;
+begin
+  _intin[0]:=point;
+  _contrl[0]:=246;
+  _contrl[1]:=0;
+  _contrl[3]:=1;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  chwd:=_ptsout[0];
+  chht:=_ptsout[1];
+  cellwd:=_ptsout[2];
+  cellht:=_ptsout[3];
+
+  vst_arbpt:=_intout[0];
+end;
+
+function vst_arbpt32(handle: smallint; point: fix31;
+                     out chwd, chht, cellwd, cellht: smallint): fix31;
+begin
+  PLongint(@_intin[0])^:=point;
+  _contrl[0]:=246;
+  _contrl[1]:=0;
+  _contrl[3]:=2;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  chwd:=_ptsout[0];
+  chht:=_ptsout[1];
+  cellwd:=_ptsout[2];
+  cellht:=_ptsout[3];
+
+  vst_arbpt32:=PLongint(@_intout[0])^;
+end;
+
+procedure vqt_advance(handle, ch: smallint; out advx, advy, remx, remy: smallint);
+begin
+  _intin[0]:=ch;
+  _contrl[0]:=247;
+  _contrl[1]:=0;
+  _contrl[3]:=1;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  advx:=_ptsout[0];
+  advy:=_ptsout[1];
+  remx:=_ptsout[2];
+  remy:=_ptsout[3];
+end;
+
+procedure vqt_advance32(handle, ch: smallint; out advx, advy: fix31);
+begin
+  _intin[0]:=ch;
+  _contrl[0]:=247;
+  _contrl[1]:=0;
+  _contrl[3]:=1;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  advx:=PLongint(@_ptsout[4])^;
+  advy:=PLongint(@_ptsout[6])^;
+end;
+
+function vq_devinfo(handle, devnum: smallint;
+                      out devexists: smallint;
+                      out filename: String;
+                      out devicename: String): smallint;
+var i, len: smallint;
+    ch: char;
+begin
+  _intin[0]:=devnum;
+  _contrl[0]:=248;
+  _contrl[1]:=0;
+  _contrl[3]:=1;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+  if (_contrl[4] = 0) or (_intout[4] = 0) then
+    begin
+      devexists:= 0;
+      filename := '';
+      devicename := '';
+      vq_devinfo:=0;
+    end
+  else
+    begin
+      (* here, the driver exists *)
+      devexists:=1;
+      (* set the filename. The value in vdi_intout may be "DRIVER.SYS"
+       * or "DRIVER   SYS". vdi_intout is not a nul-terminated string.
+       * In both cases, this binding returns a valid filename: "DRIVER.SYS"
+       * with a null-character to ended the string.
+       *)
+      len := 0;
+      for i:=0 to _contrl[4]-1 do
+        begin
+          ch := chr(_intout[i]);
+          inc(len);
+          filename[len]:=ch;
+          if (ch = ' ') and (chr(_intout[i+1]) <> ' ') then
+            begin
+              inc(len);
+              filename[len]:='.';
+            end
+          else
+            begin
+              inc(len);
+              filename[len]:=ch;
+            end
+        end;
+      setlength(filename, len);
+
+      (* device name in ptsout is a C-String, (a nul-terminated string with 8bits per characters)
+       * each short value (vdi_ptsout[x]) contains 2 characters.
+       * When ptsout contains a device name, NVDI/SpeedoGDOS seems to always write the value "13"
+       * in vdi_control[1] (hey! this should be a read only value from the VDI point of view!!!),
+       * and SpeedoGDOS 5 may set vdi_control[2] == 1 (intead of the size of vdi_ptsout, including
+       * the device_name). It's seems that this value "13" (written in vdi_control[1]) has missed
+       * its target (vdi_control[2]). So, here is a workaround:
+       *)
+       if (_contrl[2] = 1) and (_contrl[1] > 0) then
+         len := _contrl[1] * 2
+       else
+         len := (_contrl[2] - 1) * 2;
+       setlength(devicename, len);
+       move(_ptsout[1], devicename[1], len);
+       vq_devinfo:=_intout[0];;
+    end;
+
+end;
+
+procedure vqt_devinfo(handle, devnum: smallint;
+                      out dev_busy: smallint;
+                      out filename: String;
+                      out devicename: String);
+var dummy: smallint;
+begin
+  dev_busy:=vq_devinfo(handle, devnum, dummy, filename, devicename);
+end;
+
+function v_savecache(handle: smallint; const filename: String): smallint;
+var len: longint;
+begin
+  len:=string_to_vdi(filename, @_intin[0]);
+  _contrl[0]:=249;
+  _contrl[1]:=0;
+  _contrl[3]:=len;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  v_savecache:=_intout[0];
+end;
+
+function v_loadcache(handle: smallint; const filename: String; mode: smallint): smallint;
+var len: longint;
+begin
+  len:=string_to_vdi(filename, @_intin[1]);
+  _intin[0]:=mode;
+  _contrl[0]:=250;
+  _contrl[1]:=0;
+  _contrl[3]:=len+1;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  v_loadcache:=_intout[0];
+end;
+
+function v_flushcache(handle: smallint): smallint;
+begin
+  _contrl[0]:=251;
+  _contrl[1]:=0;
+  _contrl[3]:=0;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  v_flushcache:=_intout[0];
+end;
+
+function vst_setsize(handle, point: smallint;
+                     out chwd, chht, cellwd, cellht: smallint): smallint;
+begin
+  _intin[0]:=point;
+  _contrl[0]:=252;
+  _contrl[1]:=0;
+  _contrl[3]:=1;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  chwd:=_ptsout[0];
+  chht:=_ptsout[1];
+  cellwd:=_ptsout[2];
+  cellht:=_ptsout[3];
+  vst_setsize:=_intout[0];
+end;
+
+function  vst_setsize32(handle: smallint; point: fix31;
+                        out chwd, chht, cellwd, cellht: smallint): fix31;
+begin
+  PLongint(@_intin[0])^:=point;
+  _contrl[0]:=252;
+  _contrl[1]:=0;
+  _contrl[3]:=2;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  chwd:=_ptsout[0];
+  chht:=_ptsout[1];
+  cellwd:=_ptsout[2];
+  cellht:=_ptsout[3];
+  vst_setsize32:=PLongint(@_intout[0])^;
+end;
+
+function vst_skew(handle, skew: smallint): smallint;
+begin
+  _intin[0]:=skew;
+  _contrl[0]:=253;
+  _contrl[1]:=0;
   _contrl[3]:=1;
   _contrl[3]:=1;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+  vst_skew:=_intout[0];
+end;
+
+procedure vqt_get_table(handle: smallint; out map: Pointer);
+begin
+  _contrl[0]:=254;
+  _contrl[1]:=0;
+  _contrl[3]:=0;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  map:=PPointer(@_intout[0])^;
+end;
+
+procedure vqt_cachesize(handle, which_cache: smallint; out size: LongInt);
+begin
+  _intin[0]:=which_cache;
+  _contrl[0]:=255;
+  _contrl[1]:=0;
+  _contrl[3]:=0;
+  _contrl[5]:=0;
+  _contrl[6]:=handle;
+
+  vdi;
+
+  size:=PLongint(@_intout[0])^;
+end;
+
+
+procedure v_set_app_buff(handle: smallint; address: Pointer; nparagraphs: smallint);
+begin
+  PPointer(@_intin[0])^:=address;
+  _intin[2]:=nparagraphs;
+  _contrl[0]:=-1;
+  _contrl[1]:=0;
+  _contrl[3]:=3;
+  _contrl[5]:=6;
   _contrl[6]:=handle;
   _contrl[6]:=handle;
 
 
   vdi;
   vdi;

+ 338 - 0
packages/tosunits/src/vditypes.inc

@@ -0,0 +1,338 @@
+{
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 2022 Thorsten Otto
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+{* return values for vq_vgdos() inquiry *}
+const
+    GDOS_NONE       = -2;           (* no GDOS installed           *)
+    GDOS_FSM        = $5F46534D;    (* '_FSM' - FSMGDOS installed  *)
+    GDOS_FNT        = $5F464E54;    (* '_FNT' - FONTGDOS installed *)
+    GDOS_ATARI      = $0007E88A;    (* GDOS 1.1 von Atari Corp.    *)
+    GDOS_AMC        = $0007E864;    (* AMCGDos von Arnd Beissner   *)
+    GDOS_AMCLIGHT   = $0007E8BA;    (* GEMINI-Spezial-GDos von Arnd Beissner *)
+    GDOS_NVDI       = $00000000;    (* NVDI von Bela GmbH *)
+    GDOS_TTF        = $3e5d0957;    (* TTF-GDOS *)
+
+const
+{* vst_alignment modes *}
+    TA_LEFT         = 0;
+    TA_CENTER       = 1;
+    TA_RIGHT        = 2;
+    TA_BASELINE     = 0;
+    TA_HALF         = 1;
+    TA_ASCENT       = 2;
+    TA_BOTTOM       = 3;
+    TA_DESCENT      = 4;
+    TA_TOP          = 5;
+
+{* gsx modes *}
+    MD_REPLACE      = 1;
+    MD_TRANS        = 2;
+    MD_XOR          = 3;
+    MD_ERASE        = 4;
+
+{$IFNDEF IP_HOLLOW_defined}
+{* patterns (also in AES) *}
+    IP_HOLLOW       = 0;
+    IP_1PATT        = 1;
+    IP_2PATT        = 2;
+    IP_3PATT        = 3;
+    IP_4PATT        = 4;
+    IP_5PATT        = 5;
+    IP_6PATT        = 6;
+    IP_SOLID        = 7;
+{$DEFINE IP_HOLLOW_defined}
+{$ENDIF}
+
+{* gsx styles *}
+    FIS_HOLLOW      = 0;
+    FIS_SOLID       = 1;
+    FIS_PATTERN     = 2;
+    FIS_HATCH       = 3;
+    FIS_USER        = 4;
+
+{* polymarker types *}
+    MT_DOT          = 1;
+    MT_PLUS         = 2;
+    MT_ASTERISK     = 3;
+    MT_SQUARE       = 4;
+    MT_DCROSS       = 5;
+    MT_DIAMOND      = 6;
+
+{* linetypes *}
+    LT_SOLID        = 1;
+    LT_LONGDASH     = 2;
+    LT_DOTTED       = 3;
+    LT_DASHDOT      = 4;
+    LT_DASHED       = 5;
+    LT_DASHDOTDOT   = 6;
+    LT_USERDEF      = 7;
+
+{* line ends *}
+    LE_SQUARED      = 0;
+    LE_ARROWED      = 1;
+    LE_ROUNDED      = 2;
+
+{* text effects *}
+    TF_NORMAL       = 0;
+    TF_THICKENED    = 1;
+    TF_LIGHTENED    = 2;
+    TF_SLANTED      = 4;
+    TF_UNDERLINED   = 8;
+    TF_OUTLINED     = 16;
+    TF_SHADOWED     = 32;
+
+{* bit blt rules *}
+    ALL_WHITE       = 0;
+    S_AND_D         = 1;
+    S_AND_NOTD      = 2;
+    S_ONLY          = 3;
+    NOTS_AND_D      = 4;
+    D_ONLY          = 5;
+    S_XOR_D         = 6;
+    S_OR_D          = 7;
+    NOT_SORD        = 8;
+    NOT_SXORD       = 9;
+    D_INVERT        = 10;
+    S_OR_NOTD       = 11;
+    NOT_D           = 12;
+    NOTS_OR_D       = 13;
+    NOT_SANDD       = 14;
+    ALL_BLACK       = 15;
+
+{* input mode *}
+    MODE_REQUEST    = 1;
+    MODE_SAMPLE     = 2;
+
+{* vqin_mode & vsin_mode modes *}
+    DEV_LOCATOR     = 1;
+    DEV_VALUATOR    = 2;
+    DEV_CHOICE      = 3;
+    DEV_STRING      = 4;
+
+{* v_bez modes *}
+    BEZ_BEZIER      = $01;
+    BEZ_POLYLINE    = $00;
+    BEZ_NODRAW      = $02;
+
+{* v_bit_image modes *}
+    IMAGE_LEFT      = 0;
+    IMAGE_CENTER    = 1;
+    IMAGE_RIGHT     = 2;
+    IMAGE_TOP       = 0;
+    IMAGE_BOTTOM    = 2;
+
+{* vq_color modes *}
+    COLOR_REQUESTED     = 0;
+    COLOR_ACTUAL        = 1;
+
+{* vst_charmap modes *}
+    MAP_BITSTREAM   = 0;
+    MAP_ATARI       = 1;
+    MAP_UNICODE     = 2; {* for vst_map_mode, NVDI 4 *}
+
+{* vst_kern tmodes *}
+    TRACK_NONE      = 0;
+    TRACK_NORMAL    = 1;
+    TRACK_TIGHT     = 2;
+    TRACK_VERYTIGHT = 3;
+
+{* vst_kern pmodes *}
+    PAIR_OFF        = 0;
+    PAIR_ON         = 1;
+
+{* vst_scratch modes *}
+    SCRATCH_BOTH        = 0;
+    SCRATCH_BITMAP      = 1;
+    SCRATCH_NONE        = 2;
+
+{* definitions for vs_mute *}
+    MUTE_RETURN     = -1;
+    MUTE_ENABLE      = 0;
+    MUTE_DISABLE     = 1;
+
+{* definitions for v_orient *}
+    OR_PORTRAIT      = 0;
+    OR_LANDSCAPE     = 1;
+
+{* definitions for v_tray *}
+    TRAY_MANUAL     = -1;
+    TRAY_DEFAULT     = 0;
+    TRAY_FIRSTOPT    = 1;
+
+{* definitions for v_xbit_image *}
+    XBIT_FRACT       = 0;
+    XBIT_INTEGER     = 1;
+
+    XBIT_LEFT        = 0;
+    XBIT_CENTER      = 1;
+    XBIT_RIGHT       = 2;
+
+    XBIT_TOP         = 0;
+    XBIT_MIDDLE      = 1;
+    XBIT_BOTTOM      = 2;
+
+
+type
+  PCOLOR_RGB = ^TCOLOR_RGB;
+  TCOLOR_RGB = record
+      reserved: word;     {* Set to 0 or the index of the entry *}
+      red: word;          {* Red:   0<->65535 *}
+      green: word;        {* Green: 0<->65535 *}
+      blue: word;         {* Blue:  0<->65535 *}
+  end;
+
+{$WARNING type TCOLOR_ENTRY is incomplete}
+type
+  TCOLOR_ENTRY = record
+    case byte of
+      0: ( rgb: TCOLOR_RGB; );
+      1: ( cymk: array[0..1] of longint; ); // dummy
+  end;
+
+type
+  PCOLOR_TAB = ^TCOLOR_TAB;
+  TCOLOR_TAB = record             {* Colour table                    *}
+      magic: array[0..3] of char; {* 'ctab'                          *}
+      length: longint;
+      format: longint;            {* Format (0)                      *}
+      reserved: longint;          {* Reserved, set to 0              *}
+      map_id: longint;            {* Colour table ID                 *}
+      color_space: longint;       {* Colour space (at present only
+                                     CSPACE_RGB)                     *}
+      flags: longint;             {* VDI-internal flags, set to 0    *}
+      no_colors: longint;         {* Number of colour entries        *}
+      reserved1: longint;         {* Reserved, must be 0             *}
+      reserved2: longint;         {* Reserved, must be 0             *}
+      reserved3: longint;         {* Reserved, must be 0             *}
+      reserved4: longint;         {* Reserved, must be 0             *}
+      colors: array[0..0] of TCOLOR_ENTRY; { repeated no_colors times }
+  end;
+
+type
+  PPOINT16 = ^TPOINT16;
+  TPOINT16 = record               {* Point for 16-bit coordinates *}
+      x: smallint;
+      y: smallint;
+  end;
+
+type
+  PPOINT32 = ^TPOINT32;
+  TPOINT32 = record               {* Point for 32-bit coordinates *}
+      x: longint;
+      y: longint;
+  end;
+
+type
+  PRECT16 = ^TRECT16;
+  TRECT16 = record                {* Rectangle for 16-bit coordinates *}
+      x1: smallint;
+      y1: smallint;
+      x2: smallint;
+      y2: smallint;
+  end;
+
+type
+  PRECT32 = ^TRECT32;
+  TRECT32 = record                {* Rectangle for 32-bit coordinates *}
+      x1: longint;
+      y1: longint;
+      x2: longint;
+      y2: longint;
+  end;
+
+type
+  PMFDB = ^TMFDB;
+  TMFDB = record
+      fd_addr: pointer;          {* Pointer to the start of the
+                                    memory block, e.g. the
+                                    screen memory base address  *}
+      fd_w: smallint;            {* Width in pixels             *}
+      fd_h: smallint;            {* Height in pixels            *}
+      fd_wdwidth: smallint;      {* Width of a line in words    *}
+      fd_stand: smallint;        {* 0 = Device-specific format  *}
+                                 {* 1 = Standard format         *}
+      fd_nplanes: smallint;      {* Number of planes            *}
+      fd_r1: smallint;           {* Reserved, must be 0         *}
+      fd_r2: smallint;           {* Reserved, must be 0         *}
+      fd_r3: smallint;           {* Reserved, must be 0         *}
+  end;
+
+type
+    String33    = String[33];
+    String80    = String[80];
+    String125   = String[125];
+
+type
+  PVDIContrl = ^TVDIContrl;
+  TVDIContrl = ARRAY[0..11] of smallint;
+
+  PVDIPtsIn  = ^TVDIPtsIn;
+  TVDIPtsIn  = array[0..1023] of smallint;
+
+  PVDIPtsOut = ^TVDIPtsOut;
+  TVDIPtsOut = array[0..255] of smallint;
+
+  PVDIIntIn  = ^TVDIIntIn;
+  TVDIIntIn  = array[0..1023] of smallint;
+
+  PVDIIntOut = ^TVDIIntOut;
+  TVDIIntOut = array[0..511] of smallint;
+
+type
+  PVDIPB = ^TVDIPB;
+  TVDIPB = record
+      control: PVDIContrl;       {* Pointer to contrl array *}
+      intin: PVDIIntIn;          {* Pointer to intin array  *}
+      ptsin: PVDIPtsIn;          {* Pointer to ptsin array  *}
+      intout: PVDIIntOut;        {* Pointer to intout array *}
+      ptsout: PVDIPtsOut;        {* Pointer to ptsout array *}
+  end;
+
+    PFONT_HDR = ^TFONT_HDR;
+    TFONT_HDR = record
+        font_id         : smallint;
+        point           : smallint;
+        name            : Array[0..31] of Char;
+        first_ade       : Word;
+        last_ade        : Word;
+        top             : Word;
+        ascent          : Word;
+        half            : Word;
+        descent         : Word;
+        bottom          : Word;
+        max_char_width  : Word;
+        max_cell_width  : Word;
+        left_offset     : Word;
+        right_offset    : Word;
+        thicken         : Word;
+        ul_size         : Word;
+        lighten         : Word;
+        skew            : Word;
+        flags           : Word;
+        hor_table       : Pointer;
+        off_table       : Pointer;
+        dat_table       : Pointer;
+        form_width      : Word;
+        form_height     : Word;
+        next_font       : PFONT_HDR;
+    end;
+
+type
+    fix31 = LongInt;
+    ARRAY_2     = ARRAY[0..1] of smallint;
+    ARRAY_3     = ARRAY[0..2] of smallint;
+    ARRAY_4     = ARRAY[0..3] of smallint;
+    ARRAY_5     = ARRAY[0..4] of smallint;
+    ARRAY_6     = ARRAY[0..5] of smallint;
+    ARRAY_10    = ARRAY[0..9] of smallint;
+    ARRAY_273   = ARRAY[0..272] of smallint;

+ 2 - 2
rtl/aarch64/aarch64.inc

@@ -221,7 +221,7 @@ function declocked(var l : longint) : boolean;assembler;nostackframe;
   {$else CPUAARCH64_HAS_LSE}
   {$else CPUAARCH64_HAS_LSE}
   .LDecLockedLoop:
   .LDecLockedLoop:
     ldxr   w1,[x0]
     ldxr   w1,[x0]
-    sub    w1,w1,#1
+    subs   w1,w1,#1
     stxr   w2,w1,[x0]
     stxr   w2,w1,[x0]
     cbnz   w2,.LDecLockedLoop
     cbnz   w2,.LDecLockedLoop
     cset   w0, eq
     cset   w0, eq
@@ -293,7 +293,7 @@ function InterLockedDecrement (var Target: longint) : longint; assembler; nostac
   {$else CPUAARCH64_HAS_LSE}
   {$else CPUAARCH64_HAS_LSE}
   .LInterDecLockedLoop:
   .LInterDecLockedLoop:
     ldxr   w1,[x0]
     ldxr   w1,[x0]
-    sub    w1,w1,#1
+    subs   w1,w1,#1
     stxr   w2,w1,[x0]
     stxr   w2,w1,[x0]
     cbnz   w2,.LInterDecLockedLoop
     cbnz   w2,.LInterDecLockedLoop
     mov    w0,w1
     mov    w0,w1

+ 48 - 1
rtl/atari/dos.pp

@@ -41,6 +41,9 @@ implementation
 
 
 {$i gemdos.inc}
 {$i gemdos.inc}
 
 
+var
+  basepage: PPD; external name '__base';
+
 procedure Error2DosError(errno: longint);
 procedure Error2DosError(errno: longint);
 begin
 begin
   case errno of
   case errno of
@@ -382,18 +385,62 @@ begin
 end;
 end;
 
 
 function EnvCount: Longint;
 function EnvCount: Longint;
+var
+  hp : pchar;
 begin
 begin
   EnvCount:=0;
   EnvCount:=0;
+  hp:=basepage^.p_env;
+  If (Hp<>Nil) then
+    while hp^<>#0 do
+      begin
+      Inc(EnvCount);
+      hp:=hp+strlen(hp)+1;
+      end;
 end;
 end;
 
 
 function EnvStr(Index: LongInt): String;
 function EnvStr(Index: LongInt): String;
+var
+  hp : pchar;
 begin
 begin
   EnvStr:='';
   EnvStr:='';
+  hp:=basepage^.p_env;
+  If (Hp<>Nil) then
+    begin
+      while (hp^<>#0) and (Index>1) do
+        begin
+          Dec(Index);
+          hp:=hp+strlen(hp)+1;
+        end;
+    If (hp^<>#0) then
+      begin
+        EnvStr:=hp;
+      end;
+    end;
 end;
 end;
 
 
 function GetEnv(envvar : String): String;
 function GetEnv(envvar : String): String;
+  var
+    hp : pchar;
+    i : longint;
+    upperenv, str : RawByteString;
 begin
 begin
-  GetEnv:='';
+   GetEnv:='';
+   hp:=basepage^.p_env;
+   if (hp=nil) then
+      exit;
+   upperenv:=upcase(envvar);
+   while hp^<>#0 do
+     begin
+        str:=hp;
+        i:=pos('=',str);
+        if upcase(copy(str,1,i-1))=upperenv then
+          begin
+             GetEnv:=copy(str,i+1,length(str)-i);
+             break;
+          end;
+        { next string entry}
+        hp:=hp+strlen(hp)+1;
+     end;
 end;
 end;
 
 
 
 

+ 2 - 0
rtl/atari/gemdos.inc

@@ -19,12 +19,14 @@
 
 
 const
 const
     E_OK        = 0;       // OK. No error has arisen
     E_OK        = 0;       // OK. No error has arisen
+    ESPIPE      = -6;      // Illegal seek
     EINVFN      = -32;     // Unknown function number
     EINVFN      = -32;     // Unknown function number
     EFILNF      = -33;     // File not found
     EFILNF      = -33;     // File not found
     EPTHNF      = -34;     // Directory (folder) not found
     EPTHNF      = -34;     // Directory (folder) not found
     ENHNDL      = -35;     // No more handles available
     ENHNDL      = -35;     // No more handles available
     EACCDN      = -36;     // Access denied
     EACCDN      = -36;     // Access denied
     EIHNDL      = -37;     // Invalid file handle
     EIHNDL      = -37;     // Invalid file handle
+    EPERM       = -38;     // Permission denied
     ENSMEM      = -39;     // Insufficient memory
     ENSMEM      = -39;     // Insufficient memory
     EIMBA       = -40;     // Invalid memory block address
     EIMBA       = -40;     // Invalid memory block address
     EDRIVE      = -46;     // Invalid drive specification
     EDRIVE      = -46;     // Invalid drive specification

+ 15 - 2
rtl/atari/si_prc.pp

@@ -33,9 +33,22 @@ procedure PascalMain; external name 'PASCALMAIN';
 
 
 { this function must be the first in this unit which contains code }
 { this function must be the first in this unit which contains code }
 {$OPTIMIZATION OFF}
 {$OPTIMIZATION OFF}
-procedure _FPC_proc_start(pd: PPD); cdecl; public name '_start';
+procedure _FPC_proc_start; cdecl; public name '_start';
+var pd: PPD;
 begin
 begin
-  procdesc:=pd;
+  asm
+    move.l a0,d0
+    beq @Lapp
+    moveq #0,d1
+    bra @Lacc
+    @Lapp:
+    move.l 8(a6),a0
+    moveq #1,d1
+    @Lacc:
+    move.b d1,AppFlag
+    move.l a0,procdesc
+  end;
+  pd:=procdesc;
   tpasize:=align(sizeof(pd^) + pd^.p_tlen + pd^.p_dlen + pd^.p_blen + stklen, sizeof(pointer));
   tpasize:=align(sizeof(pd^) + pd^.p_tlen + pd^.p_dlen + pd^.p_blen + stklen, sizeof(pointer));
 
 
   if gemdos_mshrink(0, pd, tpasize) < 0 then
   if gemdos_mshrink(0, pd, tpasize) < 0 then

+ 5 - 5
rtl/atari/sysfile.inc

@@ -245,10 +245,10 @@ end;
 
 
 
 
 function do_isdevice(handle: thandle): boolean;
 function do_isdevice(handle: thandle): boolean;
+var pos, newpos: longint;
 begin
 begin
-  if (handle=StdOutputHandle) or (handle=StdInputHandle) or
-     (handle=StdErrorHandle) then
-    do_isdevice:=True
-  else
-    do_isdevice:=False;
+  pos := gemdos_fseek(0, handle, SEEK_FROM_CURRENT);
+  newpos := gemdos_fseek(1, handle, SEEK_FROM_START);
+  gemdos_fseek(pos, handle, SEEK_FROM_START);
+  do_isdevice := (newpos=0) or (pos=ESPIPE);
 end;
 end;

+ 10 - 10
rtl/atari/sysos.inc

@@ -25,16 +25,16 @@ begin
   else
   else
     begin
     begin
       case errno of
       case errno of
-        -32 : InOutRes:=1;
-        -33 : InOutRes:=2;
-        -34 : InOutRes:=3;
-        -35 : InOutRes:=4;
-        -36 : InOutRes:=5;
-        -37 : InOutRes:=8;
-        -39 : InOutRes:=8;
-        -40 : InOutRes:=9;
-        -46 : InOutRes:=15;
-        -67..-64 : InOutRes:=153;
+        EINVFN : InOutRes:=1;
+        EFILNF : InOutRes:=2;
+        EPTHNF : InOutRes:=3;
+        ENHNDL : InOutRes:=4;
+        EACCDN : InOutRes:=5;
+        EIHNDL : InOutRes:=6;
+        ENSMEM,EGSBF : InOutRes:=8;
+        EIMBA : InOutRes:=9;
+        EDRIVE : InOutRes:=15;
+        EPLFMT,EINTRN,ERANGE : InOutRes:=153;
         -15 : InOutRes:=151;
         -15 : InOutRes:=151;
         -13 : InOutRes:=150;
         -13 : InOutRes:=150;
       else
       else

+ 43 - 5
rtl/atari/system.pp

@@ -63,6 +63,7 @@ var
     argc: LongInt;
     argc: LongInt;
     argv: PPChar;
     argv: PPChar;
     envp: PPChar;
     envp: PPChar;
+    AppFlag: Boolean;			{ Application or Accessory				}
 
 
 
 
     {$if defined(FPUSOFT)}
     {$if defined(FPUSOFT)}
@@ -144,14 +145,51 @@ end;
                          SystemUnit Initialization
                          SystemUnit Initialization
 *****************************************************************************}
 *****************************************************************************}
 
 
+Procedure ConsoleRead(var t:TextRec);
+var
+  dosResult: longint;
+Begin
+  dosResult:=gemdos_fread(t.Handle,t.BufSize,t.Bufptr);
+  t.BufPos:=0;
+  { Reading from console on TOS does not include the terminating CR/LF }
+  if (dosResult >= 0) then
+    begin
+      t.BufEnd := dosResult;
+      if (dosResult>=1) and (t.Bufptr^[dosResult-1] = #10) then
+        begin end
+      else
+      if (t.BufEnd < t.BufSize) then
+        begin
+          t.BufPtr^[t.BufEnd] := #13;
+          inc(t.BufEnd);
+        end;
+      if (t.BufEnd < t.BufSize) then
+        begin
+          t.BufPtr^[t.BufEnd] := #10;
+          inc(t.BufEnd);
+        end;
+    end
+  else
+    Error2InOutRes(dosResult);
+End;
+
+procedure myOpenStdIO(var f:text;mode:longint;hdl:thandle);
+begin
+  OpenStdIO(f, mode, hdl);
+  if (InOutRes=0) and (Mode=fmInput) and Do_Isdevice(hdl) then
+  begin
+    TextRec(f).InOutFunc:=@ConsoleRead;
+  end;
+end;
+
 procedure SysInitStdIO;
 procedure SysInitStdIO;
 begin
 begin
-  OpenStdIO(Input,fmInput,StdInputHandle);
-  OpenStdIO(Output,fmOutput,StdOutputHandle);
-  OpenStdIO(ErrOutput,fmOutput,StdErrorHandle);
+  myOpenStdIO(Input,fmInput,StdInputHandle);
+  myOpenStdIO(Output,fmOutput,StdOutputHandle);
+  myOpenStdIO(ErrOutput,fmOutput,StdErrorHandle);
 {$ifndef FPC_STDOUT_TRUE_ALIAS}
 {$ifndef FPC_STDOUT_TRUE_ALIAS}
-  OpenStdIO(StdOut,fmOutput,StdOutputHandle);
-  OpenStdIO(StdErr,fmOutput,StdErrorHandle);
+  myOpenStdIO(StdOut,fmOutput,StdOutputHandle);
+  myOpenStdIO(StdErr,fmOutput,StdErrorHandle);
 {$endif FPC_STDOUT_TRUE_ALIAS}
 {$endif FPC_STDOUT_TRUE_ALIAS}
 end;
 end;
 
 

+ 2 - 0
rtl/i386/cpu.pp

@@ -253,6 +253,8 @@ unit cpu;
                     movl $0,%ecx
                     movl $0,%ecx
                     cpuid
                     cpuid
                     movl %ebx,_ebx
                     movl %ebx,_ebx
+                    movl %ecx,_ecx
+                    movl %edx,_edx
                     popl %ebx
                     popl %ebx
                   end;
                   end;
                   _AVX2Support:=_AVXSupport and ((_ebx and $20)<>0);
                   _AVX2Support:=_AVXSupport and ((_ebx and $20)<>0);

+ 20 - 4
rtl/inc/system.inc

@@ -266,15 +266,31 @@ function do_isdevice(handle:thandle):boolean;forward;
   { there is no mipsel.inc, we use mips.inc instead }
   { there is no mipsel.inc, we use mips.inc instead }
   {$i mips.inc}  { Case dependent, don't change }
   {$i mips.inc}  { Case dependent, don't change }
   {$define SYSPROCDEFINED}
   {$define SYSPROCDEFINED}
-{$else not cpumipsel}
-{$ifdef cpumips}
+{$endif cpumipsel}
+
+{$ifdef cpumipseb}
   {$ifdef SYSPROCDEFINED}
   {$ifdef SYSPROCDEFINED}
     {$Error Can't determine processor type !}
     {$Error Can't determine processor type !}
   {$endif}
   {$endif}
   {$i mips.inc}  { Case dependent, don't change }
   {$i mips.inc}  { Case dependent, don't change }
   {$define SYSPROCDEFINED}
   {$define SYSPROCDEFINED}
-{$endif cpumips}
-{$endif not cpumipsel}
+{$endif cpumipseb}
+
+{$ifdef cpumips64el}
+  {$ifdef SYSPROCDEFINED}
+    {$Error Can't determine processor type !}
+  {$endif}
+  {$i mips64el.inc}  { Case dependent, don't change }
+  {$define SYSPROCDEFINED}
+{$endif cpumips64el}
+
+{$ifdef cpumips64eb}
+  {$ifdef SYSPROCDEFINED}
+    {$Error Can't determine processor type !}
+  {$endif}
+  {$i mips64.inc}  { Case dependent, don't change }
+  {$define SYSPROCDEFINED}
+{$endif cpumips64eb}
 
 
 {$ifdef cpuaarch64}
 {$ifdef cpuaarch64}
   {$ifdef SYSPROCDEFINED}
   {$ifdef SYSPROCDEFINED}

+ 2 - 0
rtl/linux/linuxvcs.pp

@@ -109,6 +109,7 @@ begin
     fields[fieldct] := 0;
     fields[fieldct] := 0;
     for i := high(statln) downto low(statln) do
     for i := high(statln) downto low(statln) do
       begin
       begin
+{$push}{$R-} {$Q-}
         case statln[i] of
         case statln[i] of
           '-': magnitude := -1;
           '-': magnitude := -1;
           '0'..'9': begin
           '0'..'9': begin
@@ -116,6 +117,7 @@ begin
                                + (magnitude * (ord(statln[i]) - ord('0')));
                                + (magnitude * (ord(statln[i]) - ord('0')));
             magnitude := magnitude * 10;
             magnitude := magnitude * 10;
           end;
           end;
+{$pop}
           ' ': begin
           ' ': begin
             magnitude := 1;
             magnitude := 1;
             fieldct := fieldct + 1;
             fieldct := fieldct + 1;

+ 96 - 0
rtl/linux/mips64/sighndh.inc

@@ -0,0 +1,96 @@
+{
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 1999-2000 by Jonas Maebe,
+    member of the Free Pascal development team.
+
+    TSigContext
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+{$packrecords C}
+
+const
+  __SUNOS_MAXWIN = 31;
+
+type
+  twbuf = record
+    locals : array[0..7] of longint;
+    ins    : array[0..7] of longint;
+  end;
+
+(* MIPS OABI32 structure 
+struct sigcontext {
+  unsigned int sc_regmask;
+  unsigned int sc_status;
+  unsigned long long sc_pc;
+  unsigned long long sc_regs[32];
+  unsigned long long sc_fpregs[32];
+  unsigned int sc_ownedfp;
+  unsigned int sc_fpc_csr;
+  unsigned int sc_fpc_eir;
+  unsigned int sc_used_math;
+  unsigned int sc_dsp;
+  unsigned long long sc_mdhi;
+  unsigned long long sc_mdlo;
+  unsigned long sc_hi1;
+  unsigned long sc_lo1;
+  unsigned long sc_hi2;
+  unsigned long sc_lo2;
+  unsigned long sc_hi3;
+  unsigned long sc_lo3;
+};
+typedef struct ucontext
+  {
+    unsigned long int uc_flags;
+    struct ucontext *uc_link;
+    stack_t uc_stack;
+    mcontext_t uc_mcontext;
+    __sigset_t uc_sigmask;
+  } ucontext_t;
+
+ *)
+  FPReg = record
+   case byte of
+    0 : (fp_dreg : double;);
+    1 : (fp_reg : single;
+         fp_pad : cint; );
+  end;
+
+  PSigContext = ^TSigContext;
+  TSigContext = record
+    sigc_regmask,                   
+    sigc_status: cuint; 
+    sigc_pc : culonglong;    
+    sigc_regs : array[0..31] of culonglong;
+    sigc_fpregs : array[0..31] of fpreg; 
+    sigc_fpc_csr, sigc_fpc_eir : cuint;
+    sigc_used_math : cuint;
+    sigc_dsp : cuint;
+    sigc_mdhi, sigc_mdlo : culonglong;
+    sigc_hi1,sigc_lo1,
+    sigc_hi2,sigc_lo2,
+    sigc_hi3,sigc_lo3 : culong;
+  end;
+
+  TStack = record
+    ss_sp : pointer;
+    ss_size : size_t;
+    ss_flags : cint;
+  end;
+
+  PUContext = ^TUContext;
+  TUContext = record
+    uc_flags : culong;
+    uc_link : PUContext;
+    uc_stack : TStack;
+    uc_mcontext : TSigContext;
+    uc_sigmask : TSigSet;
+  end;
+

+ 49 - 0
rtl/linux/mips64/stat.inc

@@ -0,0 +1,49 @@
+{
+    This file is part of the Free Pascal run time library.
+
+    Copyright (c) 1999-2003 by Jonas Maebe,
+    member of the Free Pascal development team.
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+  Stat = Record
+    st_dev     : culong;
+    st_pad0    : array[0..2] of culong;
+    st_ino     : culonglong;
+    st_mode    : mode_t;
+    st_nlink   : nlink_t;
+    st_uid     : uid_t;
+    st_gid     : gid_t;
+    st_rdev    : culong;
+    st_pad1    : array[0..2] of culong;
+    st_size    : clonglong;
+{$ifdef __USE_MISC}
+    st_atim: timespec;
+    st_mtim: timespec;
+    st_ctim: timespec;
+{$else not __USE_MISC}
+    st_atime: time_t;
+    st_atime_nsec: cint;
+
+    st_mtime: time_t;
+    st_mtime_nsec: cint;
+
+    st_ctime: time_t;
+    st_ctime_nsec: cint;
+{$endif not __USE_MISC}
+    st_blksize : blksize_t;
+    __pad4     : cuint;
+{$ifndef __USE_FILE_OFFSET64}
+    st_blocks  : blkcnt_t;
+{$else __USE_FILE_OFFSET64}
+    st_blocks  : blkcnt64_t;
+{$endif __USE_FILE_OFFSET64}
+    st_pad5: array[0..13] of cint;
+  end;

+ 200 - 0
rtl/linux/mips64/syscall.inc

@@ -0,0 +1,200 @@
+{
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 1999-2009 by Michael Van Canneyt and David Zhang
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+{No debugging for syslinux include !}
+{$IFDEF SYS_LINUX}
+  {$UNDEF SYSCALL_DEBUG}
+{$ENDIF SYS_LINUX}
+
+
+{$define FPC_SYSTEM_HAS_FPFORK}
+{
+  behaviour of result of fork on sparc/linux is different than on other
+  linux flavours
+}
+function Fpfork : pid_t;  [public, alias : 'FPC_SYSC_FORK'];assembler;
+asm
+  li  $2,4002
+  syscall
+  nop
+  beq $7,$0,.LDone
+  nop
+  move  $a0,$2
+  jal   SetErrno
+  nop
+  li    $2,-1
+.LDone:
+end;
+
+
+{*****************************************************************************
+                     --- Main:The System Call Self ---
+*****************************************************************************}
+
+function FpSysCall(sysnr:TSysParam):TSysResult; assembler;[public,alias:'FPC_SYSCALL0'];
+{
+  This function puts the registers in place, does the call, and then
+  copies back the registers as they are after the SysCall.
+}
+asm
+  move  $v0,$a0
+  syscall
+  nop
+  beq $7,$0,.LDone
+  nop
+  move  $a0,$2
+  jal   SetErrno
+  nop
+  li    $2,-1
+.LDone:
+end;
+
+
+function FpSysCall(sysnr,param1:TSysParam):TSysResult; assembler;[public,alias:'FPC_SYSCALL1'];
+{
+  This function puts the registers in place, does the call, and then
+  copies back the registers as they are after the SysCall.
+}
+asm
+  move  $v0,$a0
+  move  $a0,$a1
+  syscall
+  nop
+  beq $7,$0,.LDone
+  nop
+  move  $a0,$2
+  jal   SetErrno
+  nop
+  li    $2,-1
+.LDone:
+end;
+
+
+function FpSysCall(sysnr,param1,param2:TSysParam):TSysResult; assembler;[public,alias:'FPC_SYSCALL2'];
+{
+  This function puts the registers in place, does the call, and then
+  copies back the registers as they are after the SysCall.
+}
+asm
+  move  $v0,$a0
+  move  $a0,$a1
+  move  $a1,$a2
+  syscall
+  nop
+  beq $7,$0,.LDone
+  nop
+  move  $a0,$2
+  jal   SetErrno
+  nop
+  li    $2,-1
+.LDone:
+end;
+
+
+function FpSysCall(sysnr,param1,param2,param3:TSysParam):TSysResult; assembler;[public,alias:'FPC_SYSCALL3'];
+{
+  This function puts the registers in place, does the call, and then
+  copies back the registers as they are after the SysCall.
+}
+asm
+  move  $v0,$a0
+  move  $a0,$a1
+  move  $a1,$a2
+  move  $a2,$a3
+  syscall
+  nop
+  beq $7,$0,.LDone
+  nop
+  move  $a0,$2
+  jal   SetErrno
+  nop
+  li    $2,-1
+.LDone:
+end;
+
+
+function FpSysCall(sysnr,param1,param2,param3,param4:TSysParam):TSysResult; assembler;[public,alias:'FPC_SYSCALL4'];
+{
+  This function puts the registers in place, does the call, and then
+  copies back the registers as they are after the SysCall.
+}
+asm
+  move  $v0,$a0
+  move  $a0,$a1
+  move  $a1,$a2
+  move  $a2,$a3
+  lw    $a3,param4
+  syscall
+  nop
+  beq $7,$0,.LDone
+  nop
+  move  $a0,$2
+  jal   SetErrno
+  nop
+  li    $2,-1
+.LDone:
+end;
+
+
+function FpSysCall(sysnr,param1,param2,param3,param4,param5:TSysParam):TSysResult; assembler;[public,alias:'FPC_SYSCALL5'];
+{
+  This function puts the registers in place, does the call, and then
+  copies back the registers as they are after the SysCall.
+}
+asm
+  move  $v0,$a0
+  move  $a0,$a1
+  move  $a1,$a2
+  move  $a2,$a3
+  lw	$a3,param4
+  lw    $t0,param5
+  sw    $t0,16($sp)
+
+  syscall
+  nop
+  beq $7,$0,.LDone
+  nop
+  move  $a0,$2
+  jal   SetErrno
+  nop
+  li    $2,-1
+.LDone:
+
+end;
+
+
+function FpSysCall(sysnr,param1,param2,param3,param4,param5,param6:TSysParam):TSysResult; assembler;[public,alias:'FPC_SYSCALL6'];
+{
+  This function puts the registers in place, does the call, and then
+  copies back the registers as they are after the SysCall.
+}
+asm
+  move  $v0,$a0
+  move  $a0,$a1
+  move  $a1,$a2
+  move  $a2,$a3
+  lw	$a3,param4
+  lw    $t0,param5
+  sw    $t0,16($sp)
+  lw    $t0,param6
+  sw    $t0,20($sp)
+  syscall
+  nop
+  beq $7,$0,.LDone
+  nop
+  move  $a0,$2
+  jal   SetErrno
+  nop
+  li    $2,-1
+.LDone:
+end;

+ 43 - 0
rtl/linux/mips64/syscallh.inc

@@ -0,0 +1,43 @@
+{
+    Copyright (c) 2002 by Marco van de Voort
+
+    Header for syscall in system unit for mips *nix.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+    MA 02110-1301, USA.
+
+ ****************************************************************************
+
+}
+
+Type
+  TSysResult = longint; // all platforms, cint=32-bit.
+                        // On platforms with off_t =64-bit, people should
+                        // use int64, and typecast all calls that don't
+                        // return off_t to cint.
+
+// I don't think this is going to work on several platforms
+// 64-bit machines don't have only 64-bit params.
+
+  TSysParam  = Longint;
+
+function Do_SysCall(sysnr:TSysParam):TSysResult;  external name 'FPC_SYSCALL0';
+function Do_SysCall(sysnr,param1:TSysParam):TSysResult; external name 'FPC_SYSCALL1';
+function Do_SysCall(sysnr,param1,param2:TSysParam):TSysResult;  external name 'FPC_SYSCALL2';
+function Do_SysCall(sysnr,param1,param2,param3:TSysParam):TSysResult; external name 'FPC_SYSCALL3';
+function Do_SysCall(sysnr,param1,param2,param3,param4:TSysParam):TSysResult; external name 'FPC_SYSCALL4';
+function Do_SysCall(sysnr,param1,param2,param3,param4,param5:TSysParam):TSysResult;  external name 'FPC_SYSCALL5';
+function Do_SysCall(sysnr,param1,param2,param3,param4,param5,param6:TSysParam):TSysResult;  external name 'FPC_SYSCALL6';
+

+ 503 - 0
rtl/linux/mips64/sysnr.inc

@@ -0,0 +1,503 @@
+{
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 2003-2004 by Florian Klaempfl and David Zhang
+
+    Syscall nrs for mips-linux O32
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+
+{
+* This file contains the system call numbers.
+}
+
+Const
+  __nr_Linux                            =  4000;
+  syscall_nr_exit                       =  __nr_linux +  1;
+  syscall_nr_fork                       =  __nr_linux +  2;
+  syscall_nr_read                       =  __nr_linux +  3;
+  syscall_nr_write                      =  __nr_linux +  4;
+  syscall_nr_open                       =  __nr_linux +  5;
+  syscall_nr_close                      =  __nr_linux +  6;
+  syscall_nr_waitpid                    =  __nr_linux +  7;
+  syscall_nr_creat                      =  __nr_linux +  8;
+  syscall_nr_link                       =  __nr_linux +  9;
+  syscall_nr_unlink                     =  __nr_linux + 10;
+  syscall_nr_execve                     =  __nr_linux + 11;
+  syscall_nr_chdir                      =  __nr_linux + 12;
+  syscall_nr_time                       =  __nr_linux + 13;
+  syscall_nr_mknod                      =  __nr_linux + 14;
+  syscall_nr_chmod                      =  __nr_linux + 15;
+  syscall_nr_lchown                     =  __nr_linux + 16;
+  syscall_nr_break                      =  __nr_linux + 17;
+
+  syscall_nr_unused18                   = __nr_Linux +  18;
+
+  syscall_nr_lseek                      =  __nr_linux + 19;
+  syscall_nr_getpid                     =  __nr_linux + 20;
+  syscall_nr_mount                      =  __nr_linux + 21;
+  syscall_nr_umount                     =  __nr_linux + 22;
+  syscall_nr_setuid                     =  __nr_linux + 23;
+  syscall_nr_getuid                     =  __nr_linux + 24;
+  syscall_nr_stime                      =  __nr_linux + 25;
+  syscall_nr_ptrace                     =  __nr_linux + 26;
+  syscall_nr_alarm                      =  __nr_linux + 27;
+
+  syscall_nr_unused28                   = __nr_Linux +  28;
+
+  syscall_nr_pause                      =  __nr_linux + 29;
+  syscall_nr_utime                      =  __nr_linux + 30;
+  syscall_nr_stty                       =  __nr_linux + 31;
+  syscall_nr_gtty                       =  __nr_linux + 32;
+  syscall_nr_access                     =  __nr_linux + 33;
+  syscall_nr_nice                       =  __nr_linux + 34;
+  syscall_nr_ftime                      =  __nr_linux + 35;
+  syscall_nr_sync                       =  __nr_linux + 36;
+  syscall_nr_kill                       =  __nr_linux + 37;
+  syscall_nr_rename                     =  __nr_linux + 38;
+  syscall_nr_mkdir                      =  __nr_linux + 39;
+  syscall_nr_rmdir                      =  __nr_linux + 40;
+  syscall_nr_dup                        =  __nr_linux + 41;
+  syscall_nr_pipe                       =  __nr_linux + 42;
+  syscall_nr_times                      =  __nr_linux + 43;
+  syscall_nr_prof                       =  __nr_linux + 44;
+  syscall_nr_brk                        =  __nr_linux + 45;
+  syscall_nr_setgid                     =  __nr_linux + 46;
+  syscall_nr_getgid                     =  __nr_linux + 47;
+  syscall_nr_signal                     =  __nr_linux + 48;
+  syscall_nr_geteuid                    =  __nr_linux + 49;
+  syscall_nr_getegid                    =  __nr_linux + 50;
+  syscall_nr_acct                       =  __nr_linux + 51;
+  syscall_nr_umount2                    =  __nr_linux + 52;
+  syscall_nr_lock                       =  __nr_linux + 53;
+  syscall_nr_ioctl                      =  __nr_linux + 54;
+  syscall_nr_fcntl                      =  __nr_linux + 55;
+  syscall_nr_mpx                        =  __nr_linux + 56;
+  syscall_nr_setpgid                    =  __nr_linux + 57;
+  syscall_nr_ulimit                     =  __nr_linux + 58;
+
+  syscall_nr_unused59                   = __nr_Linux +  59;
+
+  syscall_nr_umask                      =  __nr_linux + 60;
+  syscall_nr_chroot                     =  __nr_linux + 61;
+  syscall_nr_ustat                      =  __nr_linux + 62;
+  syscall_nr_dup2                       =  __nr_linux + 63;
+  syscall_nr_getppid                    =  __nr_linux + 64;
+  syscall_nr_getpgrp                    =  __nr_linux + 65;
+  syscall_nr_setsid                     =  __nr_linux + 66;
+  syscall_nr_sigaction                  =  __nr_linux + 67;
+  syscall_nr_sgetmask                   =  __nr_linux + 68;
+  syscall_nr_ssetmask                   =  __nr_linux + 69;
+  syscall_nr_setreuid                   =  __nr_linux + 70;
+  syscall_nr_setregid                   =  __nr_linux + 71;
+  syscall_nr_sigsuspend                 =  __nr_linux + 72;
+  syscall_nr_sigpending                 =  __nr_linux + 73;
+  syscall_nr_sethostname                =  __nr_linux + 74;
+  syscall_nr_setrlimit                  =  __nr_linux + 75;
+  syscall_nr_getrlimit                  =  __nr_linux + 76;
+  syscall_nr_getrusage                  =  __nr_linux + 77;
+  syscall_nr_gettimeofday               =  __nr_linux + 78;
+  syscall_nr_settimeofday               =  __nr_linux + 79;
+  syscall_nr_getgroups                  =  __nr_linux + 80;
+  syscall_nr_setgroups                  =  __nr_linux + 81;
+
+//  syscall_nr_select                     =  __nr_linux + 82;
+  syscall_nr_reserved82                 =  __nr_Linux +  82;
+
+  syscall_nr_symlink                    =  __nr_linux + 83;
+
+  syscall_nr_unused84                   = __nr_Linux +  84;
+
+  syscall_nr_readlink                   =  __nr_linux + 85;
+  syscall_nr_uselib                     =  __nr_linux + 86;
+  syscall_nr_swapon                     =  __nr_linux + 87;
+  syscall_nr_reboot                     =  __nr_linux + 88;
+  syscall_nr_readdir                    =  __nr_linux + 89;
+  syscall_nr_mmap                       =  __nr_linux + 90;
+  syscall_nr_munmap                     =  __nr_linux + 91;
+  syscall_nr_truncate                   =  __nr_linux + 92;
+  syscall_nr_ftruncate                  =  __nr_linux + 93;
+  syscall_nr_fchmod                     =  __nr_linux + 94;
+  syscall_nr_fchown                     =  __nr_linux + 95;
+  syscall_nr_getpriority                =  __nr_linux + 96;
+  syscall_nr_setpriority                =  __nr_linux + 97;
+  syscall_nr_profil                     =  __nr_linux + 98;
+  syscall_nr_statfs                     =  __nr_linux + 99;
+  syscall_nr_fstatfs                    = __nr_linux + 100;
+  syscall_nr_ioperm                     = __nr_linux + 101;
+  syscall_nr_socketcall                 = __nr_linux + 102;
+  syscall_nr_syslog                     = __nr_linux + 103;
+  syscall_nr_setitimer                  = __nr_linux + 104;
+  syscall_nr_getitimer                  = __nr_linux + 105;
+  syscall_nr_stat                       = __nr_linux + 106;
+  syscall_nr_lstat                      = __nr_linux + 107;
+  syscall_nr_fstat                      = __nr_linux + 108;
+
+  syscall_nr_unused109                   = __nr_Linux +  109;
+
+
+  syscall_nr_iopl                       = __nr_Linux + 110;
+
+  syscall_nr_vhangup                    = __nr_linux + 111;
+  syscall_nr_idle                       = __nr_linux + 112;
+//  syscall_nr_syscall                    = __nr_linux + 113;
+  syscall_nr_vm86                       = __nr_Linux + 113;
+
+  syscall_nr_wait4                      = __nr_linux + 114;
+  syscall_nr_swapoff                    = __nr_linux + 115;
+  syscall_nr_sysinfo                    = __nr_linux + 116;
+  syscall_nr_ipc                        = __nr_linux + 117;
+  syscall_nr_fsync                      = __nr_linux + 118;
+  syscall_nr_sigreturn                  = __nr_linux + 119;
+  syscall_nr_clone                      = __nr_linux + 120;
+  syscall_nr_setdomainname              = __nr_linux + 121;
+  syscall_nr_uname                      = __nr_linux + 122;
+  syscall_nr_modify_ldt                 = __nr_linux + 123;
+  syscall_nr_adjtimex                   = __nr_linux + 124;
+  syscall_nr_mprotect                   = __nr_linux + 125;
+  syscall_nr_sigprocmask                = __nr_linux + 126;
+  syscall_nr_create_module              = __nr_linux + 127;
+  syscall_nr_init_module                = __nr_linux + 128;
+  syscall_nr_delete_module              = __nr_linux + 129;
+  syscall_nr_get_kernel_syms            = __nr_linux + 130;
+  syscall_nr_quotactl                   = __nr_linux + 131;
+  syscall_nr_getpgid                    = __nr_linux + 132;
+  syscall_nr_fchdir                     = __nr_linux + 133;
+  syscall_nr_bdflush                    = __nr_linux + 134;
+  syscall_nr_sysfs                      = __nr_linux + 135;
+  syscall_nr_personality                = __nr_linux + 136;
+  syscall_nr_afs_syscall                = __nr_linux + 137;
+
+  syscall_nr_setfsuid                   = __nr_linux + 138;
+  syscall_nr_setfsgid                   = __nr_linux + 139;
+  syscall_nr__llseek                    = __nr_linux + 140;
+  syscall_nr_getdents                   = __nr_linux + 141;
+  syscall_nr__newselect                 = __nr_linux + 142;
+  syscall_nr_flock                      = __nr_linux + 143;
+  syscall_nr_msync                      = __nr_linux + 144;
+  syscall_nr_readv                      = __nr_linux + 145;
+  syscall_nr_writev                     = __nr_linux + 146;
+
+
+  syscall_nr_cacheflush                 =  __nr_Linux + 147;
+  syscall_nr_cachectl                   =  __nr_Linux + 148;
+
+
+  syscall_nr_sysmips                    = __nr_Linux + 149;
+
+  syscall_nr_unused150                  = __nr_Linux +  150;
+
+  syscall_nr_getsid                     = __nr_linux +  151; // 147;
+  syscall_nr_fdatasync                  = __nr_linux +  152; // 148;
+  syscall_nr__sysctl                    = __nr_linux +  153; // 149;
+
+  syscall_nr_mlock                      = __nr_linux +  154; // 150;
+
+  syscall_nr_munlock                    = __nr_linux + 155;
+  syscall_nr_mlockall                   = __nr_linux + 156;
+  syscall_nr_munlockall                 = __nr_linux + 157;
+
+  syscall_nr_sched_setparam             = __nr_linux + 158;
+  syscall_nr_sched_getparam             = __nr_linux + 159;
+
+  syscall_nr_sched_setscheduler         = __nr_linux + 160;
+  syscall_nr_sched_getscheduler         = __nr_linux + 161;
+  syscall_nr_sched_yield                = __nr_linux + 162;
+
+
+  syscall_nr_sched_get_priority_max     = __nr_linux + 163;
+  syscall_nr_sched_get_priority_min     = __nr_linux + 164;
+  syscall_nr_sched_rr_get_interval      = __nr_linux + 165;
+
+  syscall_nr_nanosleep                  = __nr_linux + 166; // 162;
+  syscall_nr_mremap                     = __nr_linux + 167;
+
+  syscall_nr_accept      =   __nr_Linux + 168;
+  syscall_nr_bind        =   __nr_Linux + 169;
+  syscall_nr_connect     =   __nr_Linux + 170;
+  syscall_nr_getpeername =   __nr_Linux + 171;
+  syscall_nr_getsockname =   __nr_Linux + 172;
+  syscall_nr_getsockopt  =   __nr_Linux + 173;
+  syscall_nr_listen      =   __nr_Linux + 174;
+  syscall_nr_recv        =   __nr_Linux + 175;
+  syscall_nr_recvfrom    =   __nr_Linux + 176;
+  syscall_nr_recvmsg     =   __nr_Linux + 177;
+  syscall_nr_send        =   __nr_Linux + 178;
+  syscall_nr_sendmsg     =   __nr_Linux + 179;
+  syscall_nr_sendto      =   __nr_Linux + 180;
+  syscall_nr_setsockopt  =   __nr_Linux + 181;
+  syscall_nr_shutdown    =   __nr_Linux + 182;
+  syscall_nr_socket      =   __nr_Linux + 183;
+  syscall_nr_socketpair  =   __nr_Linux + 184;
+
+  syscall_nr_setresuid                  = __nr_linux + 185;
+  syscall_nr_getresuid                  = __nr_linux + 186;
+//  syscall_nr_vm86                       = __nr_linux + 166;
+  syscall_nr_query_module               = __nr_linux + 187;
+  syscall_nr_poll                       = __nr_linux + 188;
+  syscall_nr_nfsservctl                 = __nr_linux + 189;
+  syscall_nr_setresgid                  = __nr_linux + 190;
+  syscall_nr_getresgid                  = __nr_linux + 191;
+  syscall_nr_prctl                      = __nr_linux + 192; // 172;
+  syscall_nr_rt_sigreturn               = __nr_linux + 193;
+  syscall_nr_rt_sigaction               = __nr_linux + 194;
+  syscall_nr_rt_sigprocmask             = __nr_linux + 195;
+  syscall_nr_rt_sigpending              = __nr_linux + 196;
+  syscall_nr_rt_sigtimedwait            = __nr_linux + 197;
+  syscall_nr_rt_sigqueueinfo            = __nr_linux + 198;
+  syscall_nr_rt_sigsuspend              = __nr_linux + 199;
+
+  syscall_nr_pread64                      = __nr_linux + 200;
+  syscall_nr_pwrite64                     = __nr_linux + 201;
+
+  syscall_nr_chown                      = __nr_linux + 202; // 182;
+  syscall_nr_getcwd                     = __nr_linux + 203; // 183;
+  syscall_nr_capget                     = __nr_linux + 204; // 184;
+  syscall_nr_capset                     = __nr_linux + 205; // 185;
+  syscall_nr_sigaltstack                = __nr_linux + 206; // 186;
+  syscall_nr_sendfile                   = __nr_linux + 207; // 187;
+
+
+//  syscall_nr_vfork                      = __nr_linux + 190;
+//  syscall_nr_ugetrlimit                 = __nr_linux + 191;
+
+// the following are new syscall, ......
+  syscall_nr_getpmsg     = __nr_Linux + 208;
+  syscall_nr_putpmsg     = __nr_Linux + 209;
+
+  syscall_nr_mmap2                      = __nr_linux + 210; // 192;
+  syscall_nr_truncate64                 = __nr_linux + 211; // 193;
+  syscall_nr_ftruncate64                = __nr_linux + 212; // 194;
+  syscall_nr_stat64                     = __nr_linux + 213; // 195;
+  syscall_nr_lstat64                    = __nr_linux + 214; // 196;
+  syscall_nr_fstat64                    = __nr_linux + 215; // 197;
+
+{
+  syscall_nr_lchown32                   = __nr_linux + 198;
+  syscall_nr_getuid32                   = __nr_linux + 199;
+  syscall_nr_getgid32                   = __nr_linux + 200;
+  syscall_nr_geteuid32                  = __nr_linux + 201;
+  syscall_nr_getegid32                  = __nr_linux + 202;
+  syscall_nr_setreuid32                 = __nr_linux + 203;
+  syscall_nr_setregid32                 = __nr_linux + 204;
+  syscall_nr_getgroups32                = __nr_linux + 205;
+  syscall_nr_setgroups32                = __nr_linux + 206;
+  syscall_nr_fchown32                   = __nr_linux + 207;
+  syscall_nr_setresuid32                = __nr_linux + 208;
+  syscall_nr_getresuid32                = __nr_linux + 209;
+  syscall_nr_setresgid32                = __nr_linux + 210;
+  syscall_nr_getresgid32                = __nr_linux + 211;
+  syscall_nr_chown32                    = __nr_linux + 212;
+  syscall_nr_setuid32                   = __nr_linux + 213;
+  syscall_nr_setgid32                   = __nr_linux + 214;
+  syscall_nr_setfsuid32                 = __nr_linux + 215;
+  syscall_nr_setfsgid32                 = __nr_linux + 216;
+ }
+
+  syscall_nr_pivot_root                 = __nr_linux + 216; // 218;
+  syscall_nr_mincore                    = __nr_linux + 217; // 219;
+  syscall_nr_madvise                    = __nr_linux + 218; // 220;
+  syscall_nr_getdents64                 = __nr_linux + 219; // 217;
+  syscall_nr_fcntl64                    = __nr_linux + 220; // 221;
+//  syscall_nr_security                   = __nr_linux + 223;
+
+// syscall_nr_reserved221    (__nr_Linux + 221)
+
+  syscall_nr_gettid                     = __nr_linux + 222; // 224;
+  syscall_nr_readahead                  = __nr_linux + 223; // 225;
+  syscall_nr_setxattr                   = __nr_linux + 224; // 226;
+  syscall_nr_lsetxattr                  = __nr_linux + 225; // 227;
+  syscall_nr_fsetxattr                  = __nr_linux + 226; // 228;
+  syscall_nr_getxattr                   = __nr_linux + 227; // 229;
+  syscall_nr_lgetxattr                  = __nr_linux + 228; // 230;
+  syscall_nr_fgetxattr                  = __nr_linux + 229; // 231;
+  syscall_nr_listxattr                  = __nr_linux + 230; // 232;
+  syscall_nr_llistxattr                 = __nr_linux + 231; // 233;
+  syscall_nr_flistxattr                 = __nr_linux + 232; // 234;
+  syscall_nr_removexattr                = __nr_linux + 233; // 235;
+  syscall_nr_lremovexattr               = __nr_linux + 234; // 236;
+  syscall_nr_fremovexattr               = __nr_linux + 235; // 237;
+  syscall_nr_tkill                      = __nr_linux + 236; // 238;
+  syscall_nr_sendfile64                 = __nr_linux + 237; // 239;
+  syscall_nr_futex                      = __nr_linux + 238; // 240;
+  syscall_nr_sched_setaffinity          = __nr_linux + 239; // 241;
+  syscall_nr_sched_getaffinity          = __nr_linux + 240; // 242;
+  syscall_nr_io_setup                   = __nr_linux + 241; // 243;
+  syscall_nr_io_destroy                 = __nr_linux + 242; // 244;
+  syscall_nr_io_getevents               = __nr_linux + 243; // 245;
+  syscall_nr_io_submit                  = __nr_linux + 244; // 246;
+  syscall_nr_io_cancel                  = __nr_linux + 245; // 247;
+  syscall_nr_exit_group                 = __nr_linux + 246; // 248;
+  syscall_nr_lookup_dcookie             = __nr_linux + 247; // 249;
+  syscall_nr_epoll_create               = __nr_linux + 248; // 250;
+  syscall_nr_epoll_ctl                  = __nr_linux + 249; // 251;
+  syscall_nr_epoll_wait                 = __nr_linux + 250; // 252;
+  syscall_nr_remap_file_pages           = __nr_linux + 251; // 253;
+
+  syscall_nr_set_tid_address  = __nr_Linux + 252;
+  syscall_nr_restart_syscall  = __nr_Linux + 253;
+  syscall_nr_fadvise64        = __nr_Linux + 254;
+  syscall_nr_statfs64         = __nr_Linux + 255;
+  syscall_nr_fstatfs64        = __nr_Linux + 256;
+  syscall_nr_timer_create     = __nr_Linux + 257;
+  syscall_nr_timer_settime    = __nr_Linux + 258;
+  syscall_nr_timer_gettime    = __nr_Linux + 259;
+  syscall_nr_timer_getoverrun = __nr_Linux + 260;
+  syscall_nr_timer_delete     = __nr_Linux + 261;
+  syscall_nr_clock_settime    = __nr_Linux + 262;
+  syscall_nr_clock_gettime    = __nr_Linux + 263;
+  syscall_nr_clock_getres     = __nr_Linux + 264;
+  syscall_nr_clock_nanosleep  = __nr_Linux + 265;
+  syscall_nr_tgkill           = __nr_Linux + 266;
+  syscall_nr_utimes           = __nr_Linux + 267;
+  syscall_nr_mbind            = __nr_Linux + 268;
+  syscall_nr_get_mempolicy    = __nr_Linux + 269;
+  syscall_nr_set_mempolicy    = __nr_Linux + 270;
+  syscall_nr_mq_open          = __nr_Linux + 271;
+  syscall_nr_mq_unlink        = __nr_Linux + 272;
+  syscall_nr_mq_timedsend     = __nr_Linux + 273;
+  syscall_nr_mq_timedreceive  = __nr_Linux + 274;
+  syscall_nr_mq_notify        = __nr_Linux + 275;
+  syscall_nr_mq_getsetattr    = __nr_Linux + 276;
+  syscall_nr_vserver          = __nr_Linux + 277;
+  syscall_nr_waitid           = __nr_Linux + 278;
+//  /* syscall_nr_sys_setaltroot    (__nr_Linux + 279) */
+  syscall_nr_add_key          = __nr_Linux + 280;
+  syscall_nr_request_key      = __nr_Linux + 281;
+  syscall_nr_keyctl           = __nr_Linux + 282;
+  syscall_nr_set_thread_area  = __nr_Linux + 283;
+  syscall_nr_inotify_init     = __nr_Linux + 284;
+  syscall_nr_inotify_add_watch =    (__nr_Linux + 285);
+  syscall_nr_inotify_rm_watch = __nr_Linux + 286;
+  syscall_nr_migrate_pages    = __nr_Linux + 287;
+  syscall_nr_openat           = __nr_Linux + 288;
+  syscall_nr_mkdirat          = __nr_Linux + 289;
+  syscall_nr_mknodat          = __nr_Linux + 290;
+  syscall_nr_fchownat         = __nr_Linux + 291;
+  syscall_nr_futimesat        = __nr_Linux + 292;
+  syscall_nr_fstatat          = __nr_Linux + 293;
+  syscall_nr_unlinkat         = __nr_Linux + 294;
+  syscall_nr_renameat         = __nr_Linux + 295;
+  syscall_nr_linkat           = __nr_Linux + 296;
+  syscall_nr_symlinkat        = __nr_Linux + 297;
+  syscall_nr_readlinkat       = __nr_Linux + 298;
+  syscall_nr_fchmodat         = __nr_Linux + 299;
+  syscall_nr_faccessat        = __nr_Linux + 300;
+  syscall_nr_pselect6         = __nr_Linux + 301;
+  syscall_nr_ppoll            = __nr_Linux + 302;
+  syscall_nr_unshare          = __nr_Linux + 303;
+  syscall_nr_splice           = __nr_Linux + 304;
+  syscall_nr_sync_file_range  = __nr_Linux + 305;
+  syscall_nr_tee              = __nr_Linux + 306;
+  syscall_nr_vmsplice         = __nr_Linux + 307;
+  syscall_nr_move_pages       = __nr_Linux + 308;
+  syscall_nr_set_robust_list              = __nr_Linux + 309;
+  syscall_nr_get_robust_list              = __nr_Linux + 310;
+  syscall_nr_kexec_load                   = __nr_Linux + 311;
+  syscall_nr_getcpu                       = __nr_Linux + 312;
+  syscall_nr_epoll_pwait                  = __nr_Linux + 313;
+  syscall_nr_ioprio_set                   = __nr_Linux + 314;
+  syscall_nr_ioprio_get                   = __nr_Linux + 315;
+  syscall_nr_utimensat                    = __nr_Linux + 316;
+  syscall_nr_signalfd                     = __nr_Linux + 317;
+  syscall_nr_timerfd                      = __nr_Linux + 318;
+  syscall_nr_eventfd                      = __nr_Linux + 319;
+  syscall_nr_fallocate                    = __nr_Linux + 320;
+  syscall_nr_timerfd_create               = __nr_Linux + 321;
+  syscall_nr_timerfd_gettime              = __nr_Linux + 322;
+  syscall_nr_timerfd_settime              = __nr_Linux + 323;
+  syscall_nr_signalfd4                    = __nr_Linux + 324;
+  syscall_nr_eventfd2                     = __nr_Linux + 325;
+  syscall_nr_epoll_create1                = __nr_Linux + 326;
+  syscall_nr_dup3                         = __nr_Linux + 327;
+  syscall_nr_pipe2                        = __nr_Linux + 328;
+  syscall_nr_inotify_init1                = __nr_Linux + 329;
+  syscall_nr_preadv                       = __nr_Linux + 330;
+  syscall_nr_pwritev                      = __nr_Linux + 331;
+  syscall_nr_rt_tgsigqueueinfo            = __nr_Linux + 332;
+  syscall_nr_perf_event_open              = __nr_Linux + 333;
+  syscall_nr_accept4                      = __nr_Linux + 334;
+  syscall_nr_recvmmsg                     = __nr_Linux + 335;
+  syscall_nr_fanotify_init                = __nr_Linux + 336;
+  syscall_nr_fanotify_mark                = __nr_Linux + 337;
+  syscall_nr_prlimit64                    = __nr_Linux + 338;
+  syscall_nr_name_to_handle_at            = __nr_Linux + 339;
+  syscall_nr_open_by_handle_at            = __nr_Linux + 340;
+  syscall_nr_clock_adjtime                = __nr_Linux + 341;
+  syscall_nr_syncfs                       = __nr_Linux + 342;
+  syscall_nr_sendmmsg                     = __nr_Linux + 343;
+  syscall_nr_setns                        = __nr_Linux + 344;
+  syscall_nr_process_vm_readv             = __nr_Linux + 345;
+  syscall_nr_process_vm_writev            = __nr_Linux + 346;
+  syscall_nr_kcmp                         = __nr_Linux + 347;
+  syscall_nr_finit_module                 = __nr_Linux + 348;
+  syscall_nr_sched_setattr                = __nr_Linux + 349;
+  syscall_nr_sched_getattr                = __nr_Linux + 350;
+  syscall_nr_renameat2                    = __nr_Linux + 351;
+  syscall_nr_seccomp                      = __nr_Linux + 352;
+  syscall_nr_getrandom                    = __nr_Linux + 353;
+  syscall_nr_memfd_create                 = __nr_Linux + 354;
+  syscall_nr_bpf                          = __nr_Linux + 355;
+  syscall_nr_execveat                     = __nr_Linux + 356;
+  syscall_nr_userfaultfd                  = __nr_Linux + 357;
+  syscall_nr_membarrier                   = __nr_Linux + 358;
+  syscall_nr_mlock2                       = __nr_Linux + 359;
+  syscall_nr_copy_file_range              = __nr_Linux + 360;
+  syscall_nr_preadv2                      = __nr_Linux + 361;
+  syscall_nr_pwritev2                     = __nr_Linux + 362;
+  syscall_nr_pkey_mprotect                = __nr_Linux + 363;
+  syscall_nr_pkey_alloc                   = __nr_Linux + 364;
+  syscall_nr_pkey_free                    = __nr_Linux + 365;
+  syscall_nr_statx                        = __nr_Linux + 366;
+  syscall_nr_rseq                         = __nr_Linux + 367;
+  syscall_nr_io_pgetevents                = __nr_Linux + 368;
+  syscall_nr_semget                       = __nr_Linux + 393;
+  syscall_nr_semctl                       = __nr_Linux + 394;
+  syscall_nr_shmget                       = __nr_Linux + 395;
+  syscall_nr_shmctl                       = __nr_Linux + 396;
+  syscall_nr_shmat                        = __nr_Linux + 397;
+  syscall_nr_shmdt                        = __nr_Linux + 398;
+  syscall_nr_msgget                       = __nr_Linux + 399;
+  syscall_nr_msgsnd                       = __nr_Linux + 400;
+  syscall_nr_msgrcv                       = __nr_Linux + 401;
+  syscall_nr_msgctl                       = __nr_Linux + 402;
+  syscall_nr_clock_gettime64              = __nr_Linux + 403;
+  syscall_nr_clock_settime64              = __nr_Linux + 404;
+  syscall_nr_clock_adjtime64              = __nr_Linux + 405;
+  syscall_nr_clock_getres_time64          = __nr_Linux + 406;
+  syscall_nr_clock_nanosleep_time64       = __nr_Linux + 407;
+  syscall_nr_timer_gettime64              = __nr_Linux + 408;
+  syscall_nr_timer_settime64              = __nr_Linux + 409;
+  syscall_nr_timerfd_gettime64            = __nr_Linux + 410;
+  syscall_nr_timerfd_settime64            = __nr_Linux + 411;
+  syscall_nr_utimensat_time64             = __nr_Linux + 412;
+  syscall_nr_pselect6_time64              = __nr_Linux + 413;
+  syscall_nr_ppoll_time64                 = __nr_Linux + 414;
+  syscall_nr_io_pgetevents_time64         = __nr_Linux + 416;
+  syscall_nr_recvmmsg_time64              = __nr_Linux + 417;
+  syscall_nr_mq_timedsend_time64          = __nr_Linux + 418;
+  syscall_nr_mq_timedreceive_time64       = __nr_Linux + 419;
+  syscall_nr_semtimedop_time64            = __nr_Linux + 420;
+  syscall_nr_rt_sigtimedwait_time64       = __nr_Linux + 421;
+  syscall_nr_futex_time64                 = __nr_Linux + 422;
+  syscall_nr_sched_rr_get_interval_time64 = __nr_Linux + 423;
+  syscall_nr_pidfd_send_signal            = __nr_Linux + 424;
+  syscall_nr_io_uring_setup               = __nr_Linux + 425;
+  syscall_nr_io_uring_enter               = __nr_Linux + 426;
+  syscall_nr_io_uring_register            = __nr_Linux + 427;
+  syscall_nr_open_tree                    = __nr_Linux + 428;
+  syscall_nr_move_mount                   = __nr_Linux + 429;
+  syscall_nr_fsopen                       = __nr_Linux + 430;
+  syscall_nr_fsconfig                     = __nr_Linux + 431;
+  syscall_nr_fsmount                      = __nr_Linux + 432;
+  syscall_nr_fspick                       = __nr_Linux + 433;
+  syscall_nr_pidfd_open                   = __nr_Linux + 434;
+  syscall_nr_clone3                       = __nr_Linux + 435;
+

+ 1 - 0
rtl/linux/mips64el/sighndh.inc

@@ -0,0 +1 @@
+{$i ../mips/sighndh.inc}

+ 1 - 0
rtl/linux/mips64el/stat.inc

@@ -0,0 +1 @@
+{$i ../mips64/stat.inc}

+ 1 - 0
rtl/linux/mips64el/syscall.inc

@@ -0,0 +1 @@
+{$i ../mips64/syscall.inc}

+ 1 - 0
rtl/linux/mips64el/syscallh.inc

@@ -0,0 +1 @@
+{$i ../mips64/syscallh.inc}

+ 1 - 0
rtl/linux/mips64el/sysnr.inc

@@ -0,0 +1 @@
+{$i ../mips64/sysnr.inc}

+ 30 - 7
rtl/m68k/m68k.inc

@@ -467,6 +467,26 @@ end;
 {$endif}
 {$endif}
 
 
 {$IFNDEF FPC_SYSTEM_HAS_INTERLOCKEDFUNCS}
 {$IFNDEF FPC_SYSTEM_HAS_INTERLOCKEDFUNCS}
+{$IFNDEF CPUM68K_HAS_CAS}
+var
+  spinLock: byte;
+
+procedure getSpinLock; assembler; nostackframe;
+asm
+{$IFDEF CPUM68K_HAS_TAS}
+  lea.l spinlock,a0
+@loop:
+  tas (a0)
+  bne @loop
+{$ENDIF}
+end;
+
+procedure releaseSpinLock; assembler; nostackframe;
+asm
+  move.b #0,spinlock
+end;
+{$ENDIF}
+
 function InterLockedDecrement (var Target: longint) : longint;
 function InterLockedDecrement (var Target: longint) : longint;
 {$IFDEF CPUM68K_HAS_CAS}
 {$IFDEF CPUM68K_HAS_CAS}
   register; assembler;
   register; assembler;
@@ -481,13 +501,13 @@ function InterLockedDecrement (var Target: longint) : longint;
   end;
   end;
 {$ELSE}
 {$ELSE}
   begin
   begin
-  {$warning FIX ME}
+    getSpinLock;
     Dec(Target);
     Dec(Target);
     Result := Target;
     Result := Target;
+    releaseSpinLock;
   end;
   end;
 {$ENDIF}
 {$ENDIF}
 
 
-
 function InterLockedIncrement (var Target: longint) : longint;
 function InterLockedIncrement (var Target: longint) : longint;
 {$IFDEF CPUM68K_HAS_CAS}
 {$IFDEF CPUM68K_HAS_CAS}
   register; assembler;
   register; assembler;
@@ -502,9 +522,10 @@ function InterLockedIncrement (var Target: longint) : longint;
   end;
   end;
 {$ELSE}
 {$ELSE}
   begin
   begin
-  {$warning FIX ME}
+    getSpinLock;
     Inc(Target);
     Inc(Target);
     Result := Target;
     Result := Target;
+    releaseSpinLock;
   end;
   end;
 {$ENDIF}
 {$ENDIF}
 
 
@@ -520,13 +541,13 @@ function InterLockedExchange (var Target: longint;Source : longint) : longint;
   end;
   end;
 {$ELSE}
 {$ELSE}
   begin
   begin
-  {$warning FIX ME}
+    getSpinLock;
     Result := Target;
     Result := Target;
     Target := Source;
     Target := Source;
+    releaseSpinLock;
   end;
   end;
 {$ENDIF}
 {$ENDIF}
 
 
-
 function InterLockedExchangeAdd (var Target: longint;Source : longint) : longint;
 function InterLockedExchangeAdd (var Target: longint;Source : longint) : longint;
 {$IFDEF CPUM68K_HAS_CAS}
 {$IFDEF CPUM68K_HAS_CAS}
   register; assembler;
   register; assembler;
@@ -541,9 +562,10 @@ function InterLockedExchangeAdd (var Target: longint;Source : longint) : longint
   end;
   end;
 {$ELSE}
 {$ELSE}
   begin
   begin
-  {$warning FIX ME}
+    getSpinLock;
     Result := Target;
     Result := Target;
     Target := Target + Source;
     Target := Target + Source;
+    releaseSpinLock;
   end;
   end;
 {$ENDIF}
 {$ENDIF}
 
 
@@ -558,10 +580,11 @@ function InterlockedCompareExchange(var Target: longint; NewValue: longint; Comp
   end;
   end;
 {$ELSE}
 {$ELSE}
   begin
   begin
-  {$warning FIX ME}
+    getSpinLock;
     Result := Target;
     Result := Target;
     if Target = Comperand then
     if Target = Comperand then
       Target := NewValue;
       Target := NewValue;
+    releaseSpinLock;
   end;
   end;
 {$ENDIF}
 {$ENDIF}
 {$ENDIF FPC_SYSTEM_HAS_INTERLOCKEDFUNCS}
 {$ENDIF FPC_SYSTEM_HAS_INTERLOCKEDFUNCS}

+ 15 - 0
rtl/mips64/cpuh.inc

@@ -0,0 +1,15 @@
+{
+
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 2016 by the Free Pascal development team.
+
+    CPU specific system unit header file
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}

+ 13 - 0
rtl/mips64/math.inc

@@ -0,0 +1,13 @@
+{
+   This file is part of the Free Pascal run time library.
+   Copyright (c) 2022 by Florian Klaempfl
+   members of the Free Pascal development team.
+
+   See the file COPYING.FPC, included in this distribution,
+   for details about the copyright.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY;without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+**********************************************************************}

+ 13 - 0
rtl/mips64/mips64.inc

@@ -0,0 +1,13 @@
+{
+   This file is part of the Free Pascal run time library.
+   Copyright (c) 2022 by Florian Klaempfl
+   members of the Free Pascal development team.
+
+   See the file COPYING.FPC, included in this distribution,
+   for details about the copyright.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY;without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+**********************************************************************}

+ 26 - 0
rtl/mips64/setjumph.inc

@@ -0,0 +1,26 @@
+{******************************************************************************
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 2000-2002 by Jonas Maebe and David Zhang
+
+    SetJmp/Longjmp declarations MIPS64
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+******************************************************************************}
+
+type
+  jmp_buf=packed record
+    ra,sp,s0,s1,s2,s3,s4,s5,s6,s7,fp,gp: longint;
+{$if defined(FPUMIPS2) or defined(FPUMIPS3)}
+    _fcsr,f20,f21,f22,f23,f24,f25,f26,f27,f28,f29,f30,f31: longint;
+{$endif FPUMIPS2 or FPUMIPS3}
+  end;
+  Pjmp_buf=^jmp_buf;
+
+function setjmp(var S:jmp_buf):longint;[external name 'FPC_SETJMP'];
+procedure longjmp(var S:jmp_buf;value:longint);[external name 'FPC_LONGJMP'];

+ 15 - 0
rtl/mips64el/cpuh.inc

@@ -0,0 +1,15 @@
+{
+   This file is part of the Free Pascal run time library.
+   Copyright (c) 2022 by Florian Klaempfl
+   members of the Free Pascal development team.
+
+   See the file COPYING.FPC, included in this distribution,
+   for details about the copyright.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY;without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+**********************************************************************}
+
+{$I ../mips64/math.inc}

Some files were not shown because too many files changed in this diff