ソースを参照

* synchronised with trunk till r40378

git-svn-id: branches/debug_eh@40379 -
Jonas Maebe 6 年 前
コミット
cf235a36a1
44 ファイル変更1137 行追加307 行削除
  1. 1 0
      .gitattributes
  2. 0 2
      compiler/hlcgobj.pas
  3. 1 3
      compiler/llvm/hlcgllvm.pas
  4. 5 1
      compiler/ncgld.pas
  5. 1 1
      compiler/ncgset.pas
  6. 9 9
      compiler/ngtcon.pas
  7. 19 8
      compiler/nutils.pas
  8. 12 1
      compiler/optcse.pas
  9. 6 3
      compiler/psub.pas
  10. 3 0
      compiler/rgobj.pas
  11. 140 59
      compiler/x86/aoptx86.pas
  12. 5 0
      packages/fcl-base/fpmake.pp
  13. 2 0
      packages/fcl-db/fpmake.pp
  14. 1 0
      packages/fcl-image/fpmake.pp
  15. 17 6
      packages/fcl-js/src/jswriter.pp
  16. 1 0
      packages/fcl-passrc/fpmake.pp
  17. 4 0
      packages/fcl-pdf/fpmake.pp
  18. 1 0
      packages/fcl-web/examples/simpleserver/simpleserver.lpi
  19. 18 3
      packages/fcl-web/examples/simpleserver/simpleserver.pas
  20. 7 0
      packages/fcl-web/fpmake.pp
  21. 2 2
      packages/fcl-web/src/base/fphttpstatus.pas
  22. 54 6
      packages/fpmkunit/src/fpmkunit.pp
  23. 1 0
      packages/mysql/fpmake.pp
  24. 1 0
      packages/openssl/fpmake.pp
  25. 2 0
      packages/pastojs/fpmake.pp
  26. 39 0
      packages/pastojs/src/fppas2js.pp
  27. 343 109
      packages/pastojs/src/pas2jscompiler.pp
  28. 53 2
      packages/pastojs/src/pas2jsfilecache.pp
  29. 90 0
      packages/pastojs/src/pas2jsfileutils.pp
  30. 10 0
      packages/pastojs/src/pas2jsfileutilsnodejs.inc
  31. 9 0
      packages/pastojs/src/pas2jsfileutilsunix.inc
  32. 5 0
      packages/pastojs/src/pas2jsfileutilswin.inc
  33. 1 0
      packages/pastojs/src/pas2jslogger.pp
  34. 25 0
      packages/pastojs/tests/tcmodules.pas
  35. 1 0
      packages/rtl-objpas/fpmake.pp
  36. 1 0
      packages/winunits-base/fpmake.pp
  37. 91 91
      rtl/watcom/Makefile
  38. 1 1
      rtl/watcom/Makefile.fpc
  39. 136 0
      tests/webtbs/tw34605.pp
  40. 4 0
      utils/fpdoc/fpmake.pp
  41. 4 0
      utils/fppkg/fpmake.pp
  42. 4 0
      utils/pas2jni/fpmake.pp
  43. 6 0
      utils/pas2js/docs/translation.html
  44. 1 0
      utils/pas2js/pas2jslib.lpi

+ 1 - 0
.gitattributes

@@ -16426,6 +16426,7 @@ tests/webtbs/tw34442.pp svneol=native#text/plain
 tests/webtbs/tw3456.pp svneol=native#text/plain
 tests/webtbs/tw3457.pp svneol=native#text/plain
 tests/webtbs/tw3460.pp svneol=native#text/plain
+tests/webtbs/tw34605.pp svneol=native#text/plain
 tests/webtbs/tw3467.pp svneol=native#text/plain
 tests/webtbs/tw3470.pp svneol=native#text/plain
 tests/webtbs/tw3474.pp svneol=native#text/plain

+ 0 - 2
compiler/hlcgobj.pas

@@ -4984,8 +4984,6 @@ implementation
                 end
               else
                 begin
-                  { pass proper alignment info }
-                  localcopyloc.reference.alignment:=tparavarsym(p).vardef.alignment;
                   g_concatcopy(list,tparavarsym(p).vardef,href,localcopyloc.reference);
                 end;
               { update localloc of varsym }

+ 1 - 3
compiler/llvm/hlcgllvm.pas

@@ -1128,9 +1128,7 @@ implementation
       a_load_const_cgpara(list,u64inttype,size.size,sizepara);
       maxalign:=newalignment(max(source.alignment,dest.alignment),min(source.alignment,dest.alignment));
       a_load_const_cgpara(list,u32inttype,maxalign,alignpara);
-      { we don't know anything about volatility here, should become an extra
-        parameter to g_concatcopy }
-      a_load_const_cgpara(list,llvmbool1type,0,volatilepara);
+      a_load_const_cgpara(list,llvmbool1type,ord((vol_read in source.volatility) or (vol_write in dest.volatility)),volatilepara);
       g_call_system_proc(list,pd,[@destpara,@sourcepara,@sizepara,@alignpara,@volatilepara],nil).resetiftemp;
       sourcepara.done;
       destpara.done;

+ 5 - 1
compiler/ncgld.pas

@@ -420,6 +420,7 @@ implementation
         href : treference;
         newsize : tcgsize;
         vd : tdef;
+        alignment: longint;
         indirect : boolean;
         name : TSymStr;
       begin
@@ -529,7 +530,10 @@ implementation
                     { assume packed records may always be unaligned }
                     if not(resultdef.typ in [recorddef,objectdef]) or
                        (tabstractrecordsymtable(tabstractrecorddef(resultdef).symtable).usefieldalignment<>1) then
-                      location_reset_ref(location,LOC_REFERENCE,newsize,resultdef.alignment,[])
+                      begin
+                        alignment:=min(min(min(resultdef.alignment,current_settings.alignment.localalignmax),current_settings.alignment.constalignmax),current_settings.alignment.varalignmax);
+                        location_reset_ref(location,LOC_REFERENCE,newsize,alignment,[]);
+                      end
                     else
                       location_reset_ref(location,LOC_REFERENCE,newsize,1,[]);
                     hlcg.reference_reset_base(location.reference,voidpointertype,hregister,0,ctempposinvalid,location.reference.alignment,[]);

+ 1 - 1
compiler/ncgset.pas

@@ -234,7 +234,7 @@ implementation
     procedure tcginnode.pass_generate_code;
        var
          adjustment,
-         setbase    : aint;
+         setbase    : {$ifdef CPU8BITALU}smallint{$else}aint{$endif};
          l, l2      : tasmlabel;
          hr,
          pleftreg   : tregister;

+ 9 - 9
compiler/ngtcon.pas

@@ -361,7 +361,7 @@ function get_next_varsym(def: tabstractrecorddef; const SymList:TFPHashObjectLis
     procedure tasmlisttypedconstbuilder.flush_packed_value(var bp: tbitpackedval);
       var
         bitstowrite: longint;
-        writeval : AInt;
+        writeval : {$ifdef CPU8BITALU}smallint{$else}aint{$endif};
       begin
         if (bp.curbitoffset < AIntBits) then
           begin
@@ -403,7 +403,7 @@ function get_next_varsym(def: tabstractrecorddef; const SymList:TFPHashObjectLis
     { parses a packed array constant }
     procedure tasmlisttypedconstbuilder.parse_packed_array_def(def: tarraydef);
       var
-        i  : aint;
+        i  : {$ifdef CPU8BITALU}smallint{$else}aint{$endif};
         bp : tbitpackedval;
       begin
         if not(def.elementdef.typ in [orddef,enumdef]) then
@@ -455,7 +455,7 @@ function get_next_varsym(def: tabstractrecorddef; const SymList:TFPHashObjectLis
 
     procedure tasmlisttypedconstbuilder.tc_emit_stringdef(def: tstringdef; var node: tnode);
       var
-        strlength : aint;
+        strlength : {$ifdef CPU8BITALU}smallint{$else}aint{$endif};
         strval    : pchar;
         ll        : tasmlabofs;
         ca        : pchar;
@@ -1518,11 +1518,11 @@ function get_next_varsym(def: tabstractrecorddef; const SymList:TFPHashObjectLis
         sorg,s  : TIDString;
         tmpguid : tguid;
         recoffset,
-        fillbytes  : aint;
+        fillbytes  : {$ifdef CPU8BITALU}smallint{$else}aint{$endif};
         bp   : tbitpackedval;
         error,
         is_packed: boolean;
-        startoffset: aword;
+        startoffset: {$ifdef CPU8BITALU}word{$else}aword{$endif};
 
       procedure handle_stringconstn;
         begin
@@ -1733,10 +1733,10 @@ function get_next_varsym(def: tabstractrecorddef; const SymList:TFPHashObjectLis
         obj    : tobjectdef;
         srsym  : tsym;
         st     : tsymtable;
-        objoffset : aint;
+        objoffset : {$ifdef CPU8BITALU}smallint{$else}aint{$endif};
         s,sorg : TIDString;
         vmtwritten : boolean;
-        startoffset:aint;
+        startoffset : {$ifdef CPU8BITALU}smallint{$else}aint{$endif};
       begin
         { no support for packed object }
         if is_packed_record_or_object(def) then
@@ -1926,7 +1926,7 @@ function get_next_varsym(def: tabstractrecorddef; const SymList:TFPHashObjectLis
         recsym,
         srsym   : tsym;
         sorg,s  : TIDString;
-        recoffset : aint;
+        recoffset : {$ifdef CPU8BITALU}smallint{$else}aint{$endif};
         error,
         is_packed: boolean;
 
@@ -2095,7 +2095,7 @@ function get_next_varsym(def: tabstractrecorddef; const SymList:TFPHashObjectLis
         obj    : tobjectdef;
         srsym  : tsym;
         st     : tsymtable;
-        objoffset : aint;
+        objoffset : {$ifdef CPU8BITALU}smallint{$else}aint{$endif};
         s,sorg : TIDString;
       begin
         { no support for packed object }

+ 19 - 8
compiler/nutils.pas

@@ -582,21 +582,32 @@ implementation
         obj_def: tobjectdef;
         self_temp,
         vmt_temp: ttempcreatenode;
-        check_self: tnode;
+        check_self,n: tnode;
         stat: tstatementnode;
         block: tblocknode;
         paras: tcallparanode;
-        docheck: boolean;
+        docheck,is_typecasted_classref: boolean;
       begin
         self_resultdef:=self_node.resultdef;
         case self_resultdef.typ of
           classrefdef:
-            obj_def:=tobjectdef(tclassrefdef(self_resultdef).pointeddef);
+            begin
+              obj_def:=tobjectdef(tclassrefdef(self_resultdef).pointeddef);
+            end;
           objectdef:
             obj_def:=tobjectdef(self_resultdef);
           else
             internalerror(2015052701);
         end;
+        n:=self_node;
+        is_typecasted_classref:=false;
+	if (n.nodetype=typeconvn) then
+          begin
+            while assigned(n) and (n.nodetype=typeconvn) and (nf_explicit in ttypeconvnode(n).flags) do
+              n:=ttypeconvnode(n).left;
+            if assigned(n) and (n.resultdef.typ=classrefdef) then
+              is_typecasted_classref:=true;
+	  end;
         if is_classhelper(obj_def) then
           obj_def:=tobjectdef(tobjectdef(obj_def).extendeddef);
         docheck:=
@@ -639,14 +650,14 @@ implementation
             addstatement(stat,ctempdeletenode.create_normal_temp(self_temp));
             self_node:=ctemprefnode.create(self_temp);
           end;
-        { get the VMT field in case of a class/object }
-        if (self_resultdef.typ=objectdef) and
-           assigned(tobjectdef(self_resultdef).vmt_field) then
-          result:=csubscriptnode.create(tobjectdef(self_resultdef).vmt_field,self_node)
         { in case of a classref, the "instance" is a pointer
           to pointer to a VMT and there is no vmt field }
-        else if self_resultdef.typ=classrefdef then
+        if is_typecasted_classref or (self_resultdef.typ=classrefdef) then
           result:=self_node
+        { get the VMT field in case of a class/object }
+        else if (self_resultdef.typ=objectdef) and
+           assigned(tobjectdef(self_resultdef).vmt_field) then
+          result:=csubscriptnode.create(tobjectdef(self_resultdef).vmt_field,self_node)
         { in case of an interface, the "instance" is a pointer to a pointer
           to a VMT -> dereference once already }
         else

+ 12 - 1
compiler/optcse.pas

@@ -329,7 +329,7 @@ unit optcse;
                    (is_set(n.resultdef))
                    ) then
                   while (n.nodetype=tbinarynode(n).left.nodetype) and
-                    { if node (1) is fully boolean evaluated and node (2) not, we cannot do the swap as is might result in B being evaluated always,
+                    { if node (1) is fully boolean evaluated and node (2) not, we cannot do the swap as this might result in B being evaluated always,
                       the other way round is no problem, C is still evaluated only if needed }
                     (not(is_boolean(n.resultdef)) or not(n.nodetype in [andn,orn]) or doshortbooleval(n) or not(doshortbooleval(tbinarynode(n).left))) and
                         { the resulttypes of the operands we'll swap must be equal,
@@ -347,6 +347,17 @@ unit optcse;
                           foreachnodestatic(pm_postprocess,tbinarynode(tbinarynode(n).left).right,@searchsubdomain,@csedomain);
                           if csedomain then
                             begin
+                              { move the full boolean evaluation of (2) to (1), if it was there (so it again applies to A and
+                                what follows) }
+                              if not(doshortbooleval(tbinarynode(n).left)) and
+                                 doshortbooleval(n) then
+                                begin
+                                  n.localswitches:=n.localswitches+(tbinarynode(n).left.localswitches*[cs_full_boolean_eval]);
+                                  exclude(tbinarynode(n).left.localswitches,cs_full_boolean_eval);
+                                  tbinarynode(n).left.flags:=tbinarynode(n).left.flags+(n.flags*[nf_short_bool]);
+                                  exclude(n.Flags,nf_short_bool);
+                                end;
+
                               hp2:=tbinarynode(tbinarynode(n).left).left;
                               tbinarynode(tbinarynode(n).left).left:=tbinarynode(tbinarynode(n).left).right;
                               tbinarynode(tbinarynode(n).left).right:=tbinarynode(n).right;

+ 6 - 3
compiler/psub.pas

@@ -765,7 +765,8 @@ implementation
                   (cs_implicit_exceptions in current_settings.moduleswitches)) then
                   begin
                     include(tocode.flags,nf_block_with_exit);
-                    addstatement(newstatement,cfinalizetempsnode.create);
+                    if procdef.proctypeoption<>potype_exceptfilter then
+                      addstatement(newstatement,cfinalizetempsnode.create);
                     cnodeutils.procdef_block_add_implicit_finalize_nodes(procdef,newstatement);
                     temps_finalized:=true;
                   end;
@@ -910,7 +911,8 @@ implementation
             current_filepos:=exitpos;
             { Generate code that will be in the try...finally }
             finalcode:=internalstatements(codestatement);
-            addstatement(codestatement,cfinalizetempsnode.create);
+            if procdef.proctypeoption<>potype_exceptfilter then
+              addstatement(codestatement,cfinalizetempsnode.create);
             cnodeutils.procdef_block_add_implicit_finalize_nodes(procdef,codestatement);
             temps_finalized:=true;
 
@@ -943,7 +945,8 @@ implementation
             addstatement(newstatement,bodyexitcode);
             if not is_constructor then
               begin
-                addstatement(newstatement,cfinalizetempsnode.create);
+                if procdef.proctypeoption<>potype_exceptfilter then
+                  addstatement(newstatement,cfinalizetempsnode.create);
                 cnodeutils.procdef_block_add_implicit_finalize_nodes(procdef,newstatement);
                 temps_finalized:=true;
               end;

+ 3 - 0
compiler/rgobj.pas

@@ -1840,6 +1840,9 @@ unit rgobj;
         p : tai;
         i : integer;
         supreg, u: tsuperregister;
+{$ifdef arm}
+        so: pshifterop;
+{$endif arm}
       begin
         { All allocations are available. Now we can generate the
           interference graph. Walk through all instructions, we can

+ 140 - 59
compiler/x86/aoptx86.pas

@@ -1782,75 +1782,156 @@ unit aoptx86;
           (hp1.typ = ait_instruction) and
           GetNextInstruction(hp1, hp2) and
           MatchInstruction(hp2,A_MOV,[]) and
-          OpsEqual(taicpu(hp2).oper[1]^, taicpu(p).oper[0]^) and
-          (taicpu(hp2).oper[0]^.typ=top_reg) and
           (SuperRegistersEqual(taicpu(hp2).oper[0]^.reg,taicpu(p).oper[1]^.reg)) and
           (IsFoldableArithOp(taicpu(hp1), taicpu(p).oper[1]^.reg) or
            ((taicpu(p).opsize=S_L) and (taicpu(hp1).opsize=S_Q) and (taicpu(hp2).opsize=S_L) and
             IsFoldableArithOp(taicpu(hp1), newreg(R_INTREGISTER,getsupreg(taicpu(p).oper[1]^.reg),R_SUBQ)))
           ) then
-          { change   movsX/movzX    reg/ref, reg2
-                     add/sub/or/... reg3/$const, reg2
-                     mov            reg2 reg/ref
-            to       add/sub/or/... reg3/$const, reg/ref      }
           begin
-            CopyUsedRegs(TmpUsedRegs);
-            UpdateUsedRegs(TmpUsedRegs, tai(p.next));
-            UpdateUsedRegs(TmpUsedRegs, tai(hp1.next));
-            If not(RegUsedAfterInstruction(taicpu(p).oper[1]^.reg,hp2,TmpUsedRegs)) then
+            if OpsEqual(taicpu(hp2).oper[1]^, taicpu(p).oper[0]^) and
+              (taicpu(hp2).oper[0]^.typ=top_reg) then
+              { change   movsX/movzX    reg/ref, reg2
+                         add/sub/or/... reg3/$const, reg2
+                         mov            reg2 reg/ref
+                         dealloc        reg2
+                to
+                         add/sub/or/... reg3/$const, reg/ref      }
               begin
-                { by example:
-                    movswl  %si,%eax        movswl  %si,%eax      p
-                    decl    %eax            addl    %edx,%eax     hp1
-                    movw    %ax,%si         movw    %ax,%si       hp2
-                  ->
-                    movswl  %si,%eax        movswl  %si,%eax      p
-                    decw    %eax            addw    %edx,%eax     hp1
-                    movw    %ax,%si         movw    %ax,%si       hp2
-                }
-                DebugMsg(SPeepholeOptimization + 'MovOpMov2Op ('+
-                      debug_op2str(taicpu(p).opcode)+debug_opsize2str(taicpu(p).opsize)+' '+
-                      debug_op2str(taicpu(hp1).opcode)+debug_opsize2str(taicpu(hp1).opsize)+' '+
-                      debug_op2str(taicpu(hp2).opcode)+debug_opsize2str(taicpu(hp2).opsize),p);
-                taicpu(hp1).changeopsize(taicpu(hp2).opsize);
-                {
-                  ->
-                    movswl  %si,%eax        movswl  %si,%eax      p
-                    decw    %si             addw    %dx,%si       hp1
-                    movw    %ax,%si         movw    %ax,%si       hp2
-                }
-                case taicpu(hp1).ops of
-                  1:
-                    begin
-                      taicpu(hp1).loadoper(0, taicpu(hp2).oper[1]^);
-                      if taicpu(hp1).oper[0]^.typ=top_reg then
-                        setsubreg(taicpu(hp1).oper[0]^.reg,getsubreg(taicpu(hp2).oper[0]^.reg));
+                CopyUsedRegs(TmpUsedRegs);
+                UpdateUsedRegs(TmpUsedRegs, tai(p.next));
+                UpdateUsedRegs(TmpUsedRegs, tai(hp1.next));
+                If not(RegUsedAfterInstruction(taicpu(p).oper[1]^.reg,hp2,TmpUsedRegs)) then
+                  begin
+                    { by example:
+                        movswl  %si,%eax        movswl  %si,%eax      p
+                        decl    %eax            addl    %edx,%eax     hp1
+                        movw    %ax,%si         movw    %ax,%si       hp2
+                      ->
+                        movswl  %si,%eax        movswl  %si,%eax      p
+                        decw    %eax            addw    %edx,%eax     hp1
+                        movw    %ax,%si         movw    %ax,%si       hp2
+                    }
+                    DebugMsg(SPeepholeOptimization + 'MovOpMov2Op ('+
+                          debug_op2str(taicpu(p).opcode)+debug_opsize2str(taicpu(p).opsize)+' '+
+                          debug_op2str(taicpu(hp1).opcode)+debug_opsize2str(taicpu(hp1).opsize)+' '+
+                          debug_op2str(taicpu(hp2).opcode)+debug_opsize2str(taicpu(hp2).opsize),p);
+                    taicpu(hp1).changeopsize(taicpu(hp2).opsize);
+                    {
+                      ->
+                        movswl  %si,%eax        movswl  %si,%eax      p
+                        decw    %si             addw    %dx,%si       hp1
+                        movw    %ax,%si         movw    %ax,%si       hp2
+                    }
+                    case taicpu(hp1).ops of
+                      1:
+                        begin
+                          taicpu(hp1).loadoper(0, taicpu(hp2).oper[1]^);
+                          if taicpu(hp1).oper[0]^.typ=top_reg then
+                            setsubreg(taicpu(hp1).oper[0]^.reg,getsubreg(taicpu(hp2).oper[0]^.reg));
+                        end;
+                      2:
+                        begin
+                          taicpu(hp1).loadoper(1, taicpu(hp2).oper[1]^);
+                          if (taicpu(hp1).oper[0]^.typ=top_reg) and
+                            (taicpu(hp1).opcode<>A_SHL) and
+                            (taicpu(hp1).opcode<>A_SHR) and
+                            (taicpu(hp1).opcode<>A_SAR) then
+                            setsubreg(taicpu(hp1).oper[0]^.reg,getsubreg(taicpu(hp2).oper[0]^.reg));
+                        end;
+                      else
+                        internalerror(2008042701);
                     end;
-                  2:
-                    begin
-                      taicpu(hp1).loadoper(1, taicpu(hp2).oper[1]^);
-                      if (taicpu(hp1).oper[0]^.typ=top_reg) and
-                        (taicpu(hp1).opcode<>A_SHL) and
-                        (taicpu(hp1).opcode<>A_SHR) and
-                        (taicpu(hp1).opcode<>A_SAR) then
-                        setsubreg(taicpu(hp1).oper[0]^.reg,getsubreg(taicpu(hp2).oper[0]^.reg));
+                    {
+                      ->
+                        decw    %si             addw    %dx,%si       p
+                    }
+                    asml.remove(p);
+                    asml.remove(hp2);
+                    p.Free;
+                    hp2.Free;
+                    p := hp1;
+                  end;
+                ReleaseUsedRegs(TmpUsedRegs);
+              end
+{$ifndef x86_64}
+            else if MatchOpType(taicpu(hp2),top_reg,top_reg) and
+              not(SuperRegistersEqual(taicpu(hp1).oper[0]^.reg,taicpu(hp2).oper[1]^.reg))
+{$ifdef i386}
+              { byte registers of esi, edi, ebp, esp are not available on i386 }
+              and ((taicpu(hp2).opsize<>S_B) or not(getsupreg(taicpu(hp1).oper[0]^.reg) in [RS_ESI,RS_EDI,RS_EBP,RS_ESP]))
+              and ((taicpu(hp2).opsize<>S_B) or not(getsupreg(taicpu(p).oper[0]^.reg) in [RS_ESI,RS_EDI,RS_EBP,RS_ESP]))
+{$endif i386}
+              then
+              { change   movsX/movzX    reg/ref, reg2
+                         add/sub/or/... regX/$const, reg2
+                         mov            reg2, reg3
+                         dealloc        reg2
+                to
+                         movsX/movzX    reg/ref, reg3
+                         add/sub/or/... reg3/$const, reg3
+              }
+              begin
+                CopyUsedRegs(TmpUsedRegs);
+                UpdateUsedRegs(TmpUsedRegs, tai(p.next));
+                UpdateUsedRegs(TmpUsedRegs, tai(hp1.next));
+                If not(RegUsedAfterInstruction(taicpu(p).oper[1]^.reg,hp2,TmpUsedRegs)) then
+                  begin
+                    { by example:
+                        movswl  %si,%eax        movswl  %si,%eax      p
+                        decl    %eax            addl    %edx,%eax     hp1
+                        movw    %ax,%si         movw    %ax,%si       hp2
+                      ->
+                        movswl  %si,%eax        movswl  %si,%eax      p
+                        decw    %eax            addw    %edx,%eax     hp1
+                        movw    %ax,%si         movw    %ax,%si       hp2
+                    }
+                    DebugMsg(SPeepholeOptimization + 'MovOpMov2MovOp ('+
+                          debug_op2str(taicpu(p).opcode)+debug_opsize2str(taicpu(p).opsize)+' '+
+                          debug_op2str(taicpu(hp1).opcode)+debug_opsize2str(taicpu(hp1).opsize)+' '+
+                          debug_op2str(taicpu(hp2).opcode)+debug_opsize2str(taicpu(hp2).opsize),p);
+                    taicpu(hp1).changeopsize(taicpu(hp2).opsize);
+                    taicpu(p).changeopsize(taicpu(hp2).opsize);
+                    if taicpu(p).oper[0]^.typ=top_reg then
+                      setsubreg(taicpu(p).oper[0]^.reg,getsubreg(taicpu(hp2).oper[0]^.reg));
+                    taicpu(p).loadoper(1, taicpu(hp2).oper[1]^);
+                    AllocRegBetween(taicpu(p).oper[1]^.reg,p,hp1,usedregs);
+                    {
+                      ->
+                        movswl  %si,%eax        movswl  %si,%eax      p
+                        decw    %si             addw    %dx,%si       hp1
+                        movw    %ax,%si         movw    %ax,%si       hp2
+                    }
+                    case taicpu(hp1).ops of
+                      1:
+                        begin
+                          taicpu(hp1).loadoper(0, taicpu(hp2).oper[1]^);
+                          if taicpu(hp1).oper[0]^.typ=top_reg then
+                            setsubreg(taicpu(hp1).oper[0]^.reg,getsubreg(taicpu(hp2).oper[0]^.reg));
+                        end;
+                      2:
+                        begin
+                          taicpu(hp1).loadoper(1, taicpu(hp2).oper[1]^);
+                          if (taicpu(hp1).oper[0]^.typ=top_reg) and
+                            (taicpu(hp1).opcode<>A_SHL) and
+                            (taicpu(hp1).opcode<>A_SHR) and
+                            (taicpu(hp1).opcode<>A_SAR) then
+                            setsubreg(taicpu(hp1).oper[0]^.reg,getsubreg(taicpu(hp2).oper[0]^.reg));
+                        end;
+                      else
+                        internalerror(2018111801);
                     end;
-                  else
-                    internalerror(2008042701);
-                end;
-                {
-                  ->
-                    decw    %si             addw    %dx,%si       p
-                }
-                asml.remove(p);
-                asml.remove(hp2);
-                p.Free;
-                hp2.Free;
-                p := hp1;
+                    {
+                      ->
+                        decw    %si             addw    %dx,%si       p
+                    }
+                    asml.remove(hp2);
+                    hp2.Free;
+//                    p := hp1;
+                  end;
+                ReleaseUsedRegs(TmpUsedRegs);
               end;
-            ReleaseUsedRegs(TmpUsedRegs);
+{$endif x86_64}
           end
-
         else if GetNextInstruction_p and
           MatchInstruction(hp1,A_BTS,A_BTR,[Taicpu(p).opsize]) and
           GetNextInstruction(hp1, hp2) and
@@ -1904,7 +1985,7 @@ unit aoptx86;
       end;
 
 
-    function TX86AsmOptimizer.OptPass1MOVXX(var p : tai) : boolean;
+   function TX86AsmOptimizer.OptPass1MOVXX(var p : tai) : boolean;
       var
         hp1 : tai;
       begin

+ 5 - 0
packages/fcl-base/fpmake.pp

@@ -78,12 +78,14 @@ begin
           AddUnit('inifiles');
         end;
     T:=P.Targets.AddUnit('inifiles.pp');
+      T.ResourceStrings:=true;
       with T.Dependencies do
         begin
           AddUnit('contnrs');
         end;
     T:=P.Targets.AddUnit('iostream.pp');
     T:=P.Targets.AddUnit('nullstream.pp');
+      T.ResourceStrings:=true;
     T:=P.Targets.AddUnit('maskutils.pp');
       T.ResourceStrings:=true;
     T:=P.Targets.AddUnit('pooledmm.pp');
@@ -96,11 +98,13 @@ begin
     T:=P.Targets.AddUnit('streamcoll.pp');
       T.ResourceStrings:=true;
     T:=P.Targets.AddUnit('streamex.pp');
+      T.ResourceStrings:=true;
     T:=P.Targets.AddUnit('streamio.pp');
       T.ResourceStrings:=true;
     T:=P.Targets.AddUnit('fptemplate.pp');
       T.ResourceStrings:=true;
     T:=P.Targets.AddUnit('syncobjs.pp',AllOSes-[go32v2,nativent,atari]);
+      T.ResourceStrings:=true;
     T:=P.Targets.AddUnit('uriparser.pp');
     T:=P.Targets.AddUnit('wformat.pp');
     T:=P.Targets.AddUnit('whtml.pp');
@@ -117,6 +121,7 @@ begin
       T.ResourceStrings:=true;
 
     T:=P.Targets.AddUnit('fileinfo.pp');
+      T.ResourceStrings:=true;
     T:=P.Targets.addUnit('fpmimetypes.pp');
     T:=P.Targets.AddUnit('csvreadwrite.pp');
     T:=P.Targets.addUnit('csvdocument.pp');

+ 2 - 0
packages/fcl-db/fpmake.pp

@@ -749,6 +749,7 @@ begin
           AddUnit('bufdataset');
         end;
     T:=P.Targets.AddUnit('pqeventmonitor.pp', SqldbConnectionOSes);
+      T.ResourceStrings:=true;
       with T.Dependencies do
         begin
           AddUnit('sqldb');
@@ -780,6 +781,7 @@ begin
           AddUnit('sqltypes');
         end;
     T:=P.Targets.AddUnit('sqldblib.pp');
+      T.ResourceStrings:=true;
       with T.Dependencies do
         begin
           AddUnit('sqldb');

+ 1 - 0
packages/fcl-image/fpmake.pp

@@ -227,6 +227,7 @@ begin
     T:=P.Targets.AddUnit('freetypeh.pp',[solaris,iphonesim,darwin,freebsd,openbsd,netbsd,linux,haiku,beos,win32,win64,aix,dragonfly]);
     T.Dependencies.AddInclude('libfreetype.inc');
     T:=P.Targets.AddUnit('freetypehdyn.pp',[solaris,iphonesim,darwin,freebsd,openbsd,netbsd,linux,haiku,beos,win32,win64,aix,dragonfly]);
+      T.ResourceStrings:=true;
     T.Dependencies.AddInclude('libfreetype.inc');
     T:=P.Targets.AddUnit('freetype.pp',[solaris,iphonesim,darwin,freebsd,openbsd,netbsd,linux,haiku,beos,win32,win64,aix,dragonfly]);
       with T.Dependencies do

+ 17 - 6
packages/fcl-js/src/jswriter.pp

@@ -109,7 +109,7 @@ Type
   private
     FBufPos,
     FCapacity: Cardinal;
-    FBuffer : TBuffer;
+    FBuffer: TBuffer;
     function GetAsString: TJSWriterString;
     {$ifdef fpc}
     function GetBuffer: Pointer;
@@ -119,6 +119,7 @@ Type
     {$ifdef FPC_HAS_CPSTRING}
     function GetUnicodeString: UnicodeString;
     {$endif}
+    procedure SetAsString(const AValue: TJSWriterString);
     procedure SetCapacity(AValue: Cardinal);
   Protected
     Function DoWrite(Const S : TJSWriterString) : integer; override;
@@ -136,7 +137,7 @@ Type
     {$endif}
     Property BufferLength : Integer Read GetBufferLength;
     Property Capacity : Cardinal Read GetCapacity Write SetCapacity;
-    Property AsString : TJSWriterString Read GetAsString;
+    Property AsString : TJSWriterString Read GetAsString Write SetAsString;
     {$ifdef FPC_HAS_CPSTRING}
     Property AsAnsiString : AnsiString Read GetAsString; deprecated 'use AsString instead, fpc 3.3.1';
     Property AsUnicodeString : UnicodeString Read GetUnicodeString;
@@ -320,6 +321,16 @@ begin
 end;
 {$endif}
 
+procedure TBufferWriter.SetAsString(const AValue: TJSWriterString);
+begin
+  {$ifdef pas2js}
+  SetLength(FBuffer,0);
+  FCapacity:=0;
+  {$endif}
+  FBufPos:=0;
+  DoWrite(AValue);
+end;
+
 procedure TBufferWriter.SetCapacity(AValue: Cardinal);
 begin
   if FCapacity=AValue then Exit;
@@ -328,7 +339,7 @@ begin
     FBufPos:=Capacity;
 end;
 
-Function TBufferWriter.DoWrite(Const S: TJSWriterString): integer;
+function TBufferWriter.DoWrite(const S: TJSWriterString): integer;
 {$ifdef pas2js}
 begin
   Result:=Length(S)*2;
@@ -358,7 +369,7 @@ end;
 {$endif}
 
 {$ifdef FPC_HAS_CPSTRING}
-Function TBufferWriter.DoWrite(Const S: UnicodeString): integer;
+function TBufferWriter.DoWrite(const S: UnicodeString): integer;
 
 Var
   DesLen,MinLen : Integer;
@@ -379,14 +390,14 @@ begin
 end;
 {$endif}
 
-Constructor TBufferWriter.Create(Const ACapacity: Cardinal);
+constructor TBufferWriter.Create(const ACapacity: Cardinal);
 begin
   inherited Create;
   Capacity:=ACapacity;
 end;
 
 {$ifdef fpc}
-Procedure TBufferWriter.SaveToFile(Const AFileName: String);
+procedure TBufferWriter.SaveToFile(const AFileName: String);
 Var
   F : File;
 

+ 1 - 0
packages/fcl-passrc/fpmake.pp

@@ -36,6 +36,7 @@ begin
     T:=P.Targets.AddUnit('pscanner.pp');
     T.ResourceStrings := True;
     T:=P.Targets.AddUnit('pparser.pp');
+      T.ResourceStrings:=true;
       with T.Dependencies do
         begin
           AddUnit('pastree');

+ 4 - 0
packages/fcl-pdf/fpmake.pp

@@ -37,17 +37,21 @@ begin
     P.Version:='3.3.1';
     T:=P.Targets.AddUnit('src/fpttfencodings.pp');
     T:=P.Targets.AddUnit('src/fpparsettf.pp');
+      T.ResourceStrings:=true;
     T:=P.Targets.AddUnit('src/fpfonttextmapping.pp');
     With T do
       Dependencies.AddUnit('fpttfencodings');
     T:=P.Targets.AddUnit('src/fpttfsubsetter.pp');
+      T.ResourceStrings:=true;
     With T do
       begin
       Dependencies.AddUnit('fpparsettf');
       Dependencies.AddUnit('fpfonttextmapping');
       end;
     T:=P.Targets.AddUnit('src/fpttf.pp');
+      T.ResourceStrings:=true;
     T:=P.Targets.AddUnit('src/fppdf.pp');
+      T.ResourceStrings:=true;
     With T do
       begin
       Dependencies.AddUnit('fpparsettf');

+ 1 - 0
packages/fcl-web/examples/simpleserver/simpleserver.lpi

@@ -39,6 +39,7 @@
     </Target>
     <SearchPaths>
       <IncludeFiles Value="$(ProjOutDir)"/>
+      <OtherUnitFiles Value="../../src/base"/>
       <UnitOutputDirectory Value="lib/$(TargetCPU)-$(TargetOS)"/>
     </SearchPaths>
   </CompilerOptions>

+ 18 - 3
packages/fcl-web/examples/simpleserver/simpleserver.pas

@@ -46,6 +46,7 @@ begin
   Writeln('-i --indexpage=name Directory index page to use (default: index.html)');
   Writeln('-n --noindexpage    Do not allow index page.');
   Writeln('-p --port=NNNN      TCP/IP port to listen on (default is 3000)');
+  Writeln('-m --mimetypes=file path of mime.types, default under unix: /etc/mime.types');
   Writeln('-q --quiet          Do not write diagnostic messages');
   Halt(Ord(Msg<>''));
 end;
@@ -65,10 +66,24 @@ begin
   if D='' then
     D:=GetCurrentDir;
   Log(etInfo,'Listening on port %d, serving files from directory: %s',[Port,D]);
+
+  if HasOption('m','mimetypes') then
+    MimeTypesFile:=GetOptionValue('m','mimetypes');
 {$ifdef unix}
-  MimeTypesFile:='/etc/mime.types';
-  if not FileExists(MimeTypesFile) then
-    MimeTypesFile:='';
+  if MimeTypesFile='' then
+    begin
+    MimeTypesFile:='/etc/mime.types';
+    if not FileExists(MimeTypesFile) then
+      begin
+      {$ifdef darwin}
+      MimeTypesFile:='/private/etc/apache2/mime.types';
+      if not FileExists(MimeTypesFile) then
+      {$endif}
+        MimeTypesFile:='';
+      end;
+    end;
+  if (MimeTypesFile<>'') and not FileExists(MimeTypesFile) then
+    Log(etWarning,'mimetypes file not found: '+MimeTypesFile);
 {$endif}
   TSimpleFileModule.BaseDir:=IncludeTrailingPathDelimiter(D);
   TSimpleFileModule.OnLog:=@Log;

+ 7 - 0
packages/fcl-web/fpmake.pp

@@ -50,6 +50,7 @@ begin
     T.Dependencies.AddUnit('httpprotocol');
 
     T:=P.Targets.AddUnit('httproute.pp');
+      T.ResourceStrings:=true;
     T.Dependencies.AddUnit('httpdefs');
 
     T:=P.Targets.AddUnit('cgiapp.pp');
@@ -182,6 +183,11 @@ begin
         OSes:=[Win32,Win64];
         Dependencies.AddUnit('custhttpsys');
       end;
+    with P.Targets.AddUnit('fphttpstatus.pas') do
+      begin
+        Dependencies.AddUnit('fphttpserver');
+        Dependencies.AddUnit('HTTPDefs');
+      end;
     T:=P.Targets.AddUnit('fcgigate.pp');
     T.ResourceStrings:=true;
     With T.Dependencies do
@@ -264,6 +270,7 @@ begin
     T:=P.Targets.AddUnit('fpwebclient.pp');
     T:=P.Targets.AddUnit('fpjwt.pp');
     T:=P.Targets.AddUnit('fpoauth2.pp');
+      T.ResourceStrings:=true;
     T.Dependencies.AddUnit('fpwebclient');
     T.Dependencies.AddUnit('fpjwt');
     T:=P.Targets.AddUnit('fpoauth2ini.pp');

+ 2 - 2
packages/fcl-web/src/base/fphttpstatus.pas

@@ -171,13 +171,13 @@ begin
       HTTPEncode(ARequest.Connection.Server.AdminMail) +
       '">' +
       HTTPEncode(name) +
-      '</a> Port ' + ARequest.ServerPort +
+      '</a> Port ' + IntToStr(ARequest.ServerPort) +
       '</address>'
   else
     Result := prefix + '<address>' + ARequest.Connection.Server.ServerBanner +
       ' Server at ' +
       ARequest.Connection.Server.AdminMail +
-      ' Port ' + ARequest.ServerPort +
+      ' Port ' + IntToStr(ARequest.ServerPort) +
       '</address>';
 end;
 

+ 54 - 6
packages/fpmkunit/src/fpmkunit.pp

@@ -19,6 +19,7 @@ unit fpmkunit;
 {$Mode objfpc}
 {$H+}
 {$inline on}
+{$MODESWITCH TYPEHELPERS} 
 
 { For target or cpu dependent dependencies also add an overload where you
   can pass only a set of cpus. This is disabled for now because it creates
@@ -1683,6 +1684,7 @@ ResourceString
   SWarnNoFCLProcessSupport= 'No FCL-Process support';
   SWarnRetryRemDirectory     = 'Failed to remove directory "%s". Retry after a short delay';
   SWarnCombinedPathAndUDir= 'Warning: Better do not combine the SearchPath and Global/Local-UnitDir parameters';
+  SWarnRemovedNonEmptyDirectory = 'Warning: Removed non empty directory "%s"';
 
   SInfoPackageAlreadyProcessed = 'Package %s is already processed';
   SInfoCompilingTarget    = 'Compiling target %s';
@@ -1749,6 +1751,7 @@ ResourceString
   SDbgTargetHasToBeCompiled = 'At least one of the targets in the package has to be compiled.';
   SDbgDeletedFile           = 'Recursively deleted file "%s"';
   SDbgRemovedDirectory      = 'Recursively removed directory "%s"';
+  SDbgUnregisteredResource  = 'Adding resource file "%s", which is not registered.';
 
 
   // Help messages for usage
@@ -8000,10 +8003,29 @@ begin
         CmdRemoveDirs(DirectoryList);
 
         DirectoryList.Clear;
-        if DirectoryExists(ExtractFileDir(APackage.GetBinOutputDir(ACPU,AOS))) then
-          DirectoryList.Add(ExtractFileDir(APackage.GetBinOutputDir(ACPU,AOS)));
-        if DirectoryExists(ExtractFileDir(APackage.GetUnitsOutputDir(ACPU,AOS))) then
-          DirectoryList.Add(ExtractFileDir(APackage.GetUnitsOutputDir(ACPU,AOS)));
+
+        { force directory removal for units and bin dir if it ends with /$fpc_target }
+        if DirectoryExists(APackage.GetBinOutputDir(ACPU,AOS)) and
+           (MakeTargetString(ACPU,AOS)=ExtractFileName(ExcludeTrailingPathDelimiter(APackage.GetBinOutputDir(ACPU,AOS)))) then
+          begin
+            Installer.Log(vlWarning,Format(SWarnRemovedNonEmptyDirectory,[APackage.Directory+APackage.GetBinOutputDir(ACPU,AOS)]));
+            DirectoryList.Add(APackage.GetBinOutputDir(ACPU,AOS));
+            CmdRemoveTrees(DirectoryList);
+            DirectoryList.Clear;
+          end;
+        if DirectoryExists(APackage.GetUnitsOutputDir(ACPU,AOS)) and
+           (MakeTargetString(ACPU,AOS)=ExtractFileName(ExcludeTrailingPathDelimiter(APackage.GetUnitsOutputDir(ACPU,AOS)))) then
+          begin
+            Installer.Log(vlWarning,Format(SWarnRemovedNonEmptyDirectory,[APackage.Directory+APackage.GetUnitsOutputDir(ACPU,AOS)]));
+            DirectoryList.Add(APackage.GetUnitsOutputDir(ACPU,AOS));
+            CmdRemoveTrees(DirectoryList);
+            DirectoryList.Clear;
+          end;
+        { Also remove units/ or bin/ directory if empty }
+        if IsDirectoryEmpty(ExtractFileDir(ExcludeTrailingPathDelimiter(APackage.GetBinOutputDir(ACPU,AOS)))) then
+          DirectoryList.Add(ExtractFileDir(ExcludeTrailingPathDelimiter(APackage.GetBinOutputDir(ACPU,AOS))));
+        if IsDirectoryEmpty(ExtractFileDir(ExcludeTrailingPathDelimiter(APackage.GetUnitsOutputDir(ACPU,AOS)))) then
+          DirectoryList.Add(ExtractFileDir(ExcludeTrailingPathDelimiter(APackage.GetUnitsOutputDir(ACPU,AOS))));
         CmdRemoveDirs(DirectoryList);
       finally
         DirectoryList.Free;
@@ -8694,7 +8716,20 @@ begin
         List.Add(APrefixU + RSJFileName)
       else
         List.Add(APrefixU + RSTFileName);
-    end;
+    end
+  else
+    begin
+      if FileExists(APrefixU + RSJFileName) then
+        begin
+          Installer.Log(VlDebug,Format(SDbgUnregisteredResource,[APrefixU + RSJFileName]));
+          List.Add(APrefixU + RSJFileName);
+        end
+      else if FileExists(APrefixU + RSTFileName) then
+        begin
+          Installer.Log(VlDebug,Format(SDbgUnregisteredResource,[APrefixU + RSTFileName]));
+          List.Add(APrefixU + RSTFileName);
+        end;
+     end;
   // Maybe add later ?  AddConditionalStrings(List,CleanFiles);
 end;
 
@@ -8726,7 +8761,20 @@ begin
         List.Add(APrefixU + RSJFileName)
       else
         List.Add(APrefixU + RSTFileName);
-    end;
+    end
+  else
+    begin
+      if FileExists(UnitsDir + RSJFileName) then
+        begin
+          Installer.Log(VlDebug,Format(SDbgUNregisteredResource,[APrefixU + RSJFileName]));
+          List.Add(APrefixU + RSJFileName);
+        end
+      else if FileExists(UnitsDir + RSTFileName) then
+        begin
+          Installer.Log(VlDebug,Format(SDbgUNregisteredResource,[APrefixU + RSTFileName]));
+          List.Add(APrefixU + RSTFileName);
+        end;
+     end;
 end;
 
 

+ 1 - 0
packages/mysql/fpmake.pp

@@ -120,6 +120,7 @@ begin
           AddInclude('mysql.inc');
         end;
     T:=P.Targets.AddUnit('mysql51dyn.pp');
+      T.ResourceStrings:=true;
       with T.Dependencies do
         begin
           AddInclude('mysql.inc');

+ 1 - 0
packages/openssl/fpmake.pp

@@ -28,6 +28,7 @@ begin
 
     T:=P.Targets.AddUnit('openssl.pas');
     T:=P.Targets.AddUnit('fpopenssl.pp');
+      T.ResourceStrings:=true;
 
     P.ExamplePath.Add('examples');
     P.Targets.AddExampleProgram('test1.pas');

+ 2 - 0
packages/pastojs/fpmake.pp

@@ -27,6 +27,7 @@ begin
     P.Dependencies.Add('fcl-js');
     P.Dependencies.Add('fcl-json');
     P.Dependencies.Add('fcl-passrc');
+    P.Dependencies.Add('fcl-process');
     Defaults.Options.Add('-Sc');
 
     P.Author := 'Free Pascal development team';
@@ -41,6 +42,7 @@ begin
 
     T:=P.Targets.AddUnit('pas2jsfiler.pp');
     T:=P.Targets.AddUnit('fppas2js.pp');
+      T.ResourceStrings:=true;
     T:=P.Targets.AddUnit('fppjssrcmap.pp');
     T:=P.Targets.AddUnit('pas2jsfilecache.pp');
     T:=P.Targets.AddUnit('pas2jsfileutils.pp');

+ 39 - 0
packages/pastojs/src/fppas2js.pp

@@ -353,9 +353,12 @@ Works:
   - dispose, new
 - typecast byte(longword) -> value & $ff
 - typecast TJSFunction(func)
+- modeswitch OmitRTTI
+- debugger;
 
 ToDos:
 - do not rename property Date
+- cmd line param to set modeswitch
 - bug: DoIt(typeinfo(i))  where DoIt is in another unit and has TTypeInfo
 - bug:
   v:=a[0]  gives Local variable "a" is assigned but never used
@@ -1260,8 +1263,11 @@ type
     procedure ComputeBinaryExprRes(Bin: TBinaryExpr; out
       ResolvedEl: TPasResolverResult; Flags: TPasResolverComputeFlags;
       var LeftResolved, RightResolved: TPasResolverResult); override;
+    // built-in functions
     procedure BI_TypeInfo_OnGetCallResult(Proc: TResElDataBuiltInProc;
       Params: TParamsExpr; out ResolvedEl: TPasResolverResult); override;
+    function BI_Debugger_OnGetCallCompatibility(Proc: TResElDataBuiltInProc;
+      Expr: TPasExpr; RaiseOnError: boolean): integer; virtual;
   public
     constructor Create; reintroduce;
     destructor Destroy; override;
@@ -1746,6 +1752,7 @@ type
     Function ConvertBuiltIn_New(El: TParamsExpr; AContext: TConvertContext): TJSElement; virtual;
     Function ConvertBuiltIn_Dispose(El: TParamsExpr; AContext: TConvertContext): TJSElement; virtual;
     Function ConvertBuiltIn_Default(El: TParamsExpr; AContext: TConvertContext): TJSElement; virtual;
+    Function ConvertBuiltIn_Debugger(El: TPasExpr; AContext: TConvertContext): TJSElement; virtual;
     Function ConvertRecordValues(El: TRecordValues; AContext: TConvertContext): TJSElement; virtual;
     Function ConvertSelfExpression(El: TSelfExpr; AContext: TConvertContext): TJSElement; virtual;
     Function ConvertBinaryExpression(El: TBinaryExpr; AContext: TConvertContext): TJSElement; virtual;
@@ -4229,6 +4236,16 @@ begin
   if Proc=nil then ;
 end;
 
+function TPas2JSResolver.BI_Debugger_OnGetCallCompatibility(
+  Proc: TResElDataBuiltInProc; Expr: TPasExpr; RaiseOnError: boolean): integer;
+// debugger;
+begin
+  if Expr is TParamsExpr then
+    Result:=CheckBuiltInMaxParamCount(Proc,TParamsExpr(Expr),0,RaiseOnError)
+  else
+    Result:=cExact;
+end;
+
 constructor TPas2JSResolver.Create;
 var
   bt: TPas2jsBaseType;
@@ -4319,6 +4336,9 @@ begin
     AddBaseType(Pas2JSBuiltInNames[pbitnUIntDouble],btUIntDouble);
   if btIntDouble in TheBaseTypes then
     AddBaseType(Pas2JSBuiltInNames[pbitnIntDouble],btIntDouble);
+  AddBuiltInProc('Debugger','procedure Debugger',
+      @BI_Debugger_OnGetCallCompatibility,nil,
+      nil,nil,bfCustom,[bipfCanBeStatement]);
 end;
 
 function TPas2JSResolver.CheckTypeCastRes(const FromResolved,
@@ -7282,6 +7302,12 @@ begin
       bfBreak: Result:=ConvertBuiltInBreak(El,AContext);
       bfContinue: Result:=ConvertBuiltInContinue(El,AContext);
       bfExit: Result:=ConvertBuiltIn_Exit(El,AContext);
+      bfCustom:
+        case BuiltInProc.Element.Name of
+        'Debugger': Result:=ConvertBuiltIn_Debugger(El,AContext);
+        else
+          RaiseNotSupported(El,AContext,20181126102554,'built in custom proc '+BuiltInProc.Element.Name);
+        end
     else
       RaiseNotSupported(El,AContext,20161130164955,'built in proc '+ResolverBuiltInProcNames[BuiltInProc.BuiltIn]);
     end;
@@ -8381,6 +8407,12 @@ begin
             if Result=nil then exit;
             end;
           bfDefault: Result:=ConvertBuiltIn_Default(El,AContext);
+          bfCustom:
+            case BuiltInProc.Element.Name of
+            'Debugger': Result:=ConvertBuiltIn_Debugger(El,AContext);
+            else
+              RaiseNotSupported(El,AContext,20181126101801,'built in custom proc '+BuiltInProc.Element.Name);
+            end;
         else
           RaiseNotSupported(El,AContext,20161130164955,'built in proc '+ResolverBuiltInProcNames[BuiltInProc.BuiltIn]);
         end;
@@ -10971,6 +11003,13 @@ begin
     AContext.Resolver.GetResolverResultDescription(ResolvedEl)],Param);
 end;
 
+function TPasToJSConverter.ConvertBuiltIn_Debugger(El: TPasExpr;
+  AContext: TConvertContext): TJSElement;
+begin
+  Result:=CreateLiteralCustomValue(El,'debugger');
+  if AContext=nil then ;
+end;
+
 function TPasToJSConverter.ConvertRecordValues(El: TRecordValues;
   AContext: TConvertContext): TJSElement;
 var

+ 343 - 109
packages/pastojs/src/pas2jscompiler.pp

@@ -22,7 +22,7 @@ uses
   {$IFDEF Pas2js}
   JS, NodeJSFS,
   {$ELSE}
-  RtlConsts,
+  RtlConsts, process,
   {$ENDIF}
   Classes, SysUtils, contnrs,
   jstree, jswriter, JSSrcMap,
@@ -81,6 +81,11 @@ const
   nUnitFileNotFound = 136; sUnitFileNotFound = 'unit file not found %s';
   nClassInterfaceStyleIs = 137; sClassInterfaceStyleIs = 'Class interface style is %s';
   nMacroXSetToY = 138; sMacroXSetToY = 'Macro %s set to %s';
+  nPostProcessorInfoX = 139; sPostProcessorInfoX = 'Post processor: %s';
+  nPostProcessorRunX = 140; sPostProcessorRunX = 'Run post processor: %s';
+  nPostProcessorFailX = 141; sPostProcessorFailX = 'Post processor failed: %s';
+  nPostProcessorWarnX = 142; sPostProcessorWarnX = 'Post processor: %s';
+  nPostProcessorFinished = 143; sPostProcessorFinished = 'Post processor finished';
   // Note: error numbers 201+ are used by Pas2jsFileCache
 
 //------------------------------------------------------------------------------
@@ -401,6 +406,7 @@ type
     FMode: TP2jsMode;
     FOptions: TP2jsCompilerOptions;
     FParamMacros: TPas2jsMacroEngine;
+    FPostProcs: TObjectList;
     FSrcMapSourceRoot: string;
     FTargetPlatform: TPasToJsPlatform;
     FTargetProcessor: TPasToJsProcessor;
@@ -473,6 +479,8 @@ type
     procedure RegisterMessages;
   protected
     // DoWriteJSFile: return false to use the default write function.
+    procedure CallPostProcessors(const JSFilename: String; aWriter: TPas2JSMapper); virtual;
+    function CallPostProcessor(const JSFilename: String; Cmd: TStringList; JS: TJSWriterString): TJSWriterString; virtual;
     function DoWriteJSFile(const DestFilename: String; aWriter: TPas2JSMapper): Boolean; virtual;
     procedure Compile(StartTime: TDateTime);
     procedure ProcessQueue;
@@ -516,9 +524,11 @@ type
     procedure WriteVersionLine;
     procedure WriteOptions;
     procedure WriteDefines;
+    procedure WriteUsedTools;
     procedure WriteFoldersAndSearchPaths;
     procedure WriteInfo;
     function GetShownMsgTypes: TMessageTypes;
+    function CmdListAsStr(CmdList: TStrings): string;
 
     procedure AddDefine(const aName: String);
     procedure AddDefine(const aName, Value: String);
@@ -556,6 +566,7 @@ type
     property PrecompileGUID: TGUID read FPrecompileGUID write FPrecompileGUID;
     property PrecompileInitialFlags: TPCUInitialFlags read FPrecompileInitialFlags;
     {$ENDIF}
+    property PostProcs: TObjectList read FPostProcs; // list of TStrings
     property RTLVersionCheck: TP2jsRTLVersionCheck read FRTLVersionCheck write FRTLVersionCheck;
     property SrcMapEnable: boolean read GetSrcMapEnable write SetSrcMapEnable;
     property SrcMapSourceRoot: string read FSrcMapSourceRoot write FSrcMapSourceRoot;
@@ -2556,115 +2567,54 @@ begin
     if aFile.IsMainFile and (TargetPlatform=PlatformNodeJS) then
       aFileWriter.WriteFile('rtl.run();'+LineEnding,aFile.PasFilename);
 
-    // Give chance to descendants to write file
-    if DoWriteJSFile(aFile.JSFilename,aFileWriter) then
-      exit;// descendant has written -> finished
-
-    if (aFile.JSFilename='') and (FileCache.MainJSFile='.') then
+    if FreeWriter then
     begin
-      // write to stdout
-      if FreeWriter then
+      CallPostProcessors(aFile.JSFilename,aFileWriter);
+
+      // Give chance to descendants to write file
+      if DoWriteJSFile(aFile.JSFilename,aFileWriter) then
+        exit;// descendant has written -> finished
+
+      if (aFile.JSFilename='') and (FileCache.MainJSFile='.') then
       begin
-        {$IFDEF HasStdErr}
-        Log.WriteMsgToStdErr:=false;
-        {$ENDIF}
-        try
-          Log.LogRaw(aFileWriter.AsString);
-        finally
+        // write to stdout
+        if FreeWriter then
+        begin
           {$IFDEF HasStdErr}
-          Log.WriteMsgToStdErr:=coWriteMsgToStdErr in Options;
+          Log.WriteMsgToStdErr:=false;
           {$ENDIF}
+          try
+            Log.LogRaw(aFileWriter.AsString);
+          finally
+            {$IFDEF HasStdErr}
+            Log.WriteMsgToStdErr:=coWriteMsgToStdErr in Options;
+            {$ENDIF}
+          end;
         end;
-      end;
-    end else if FreeWriter then
-    begin
-      // write to file
-
-      //writeln('TPas2jsCompiler.WriteJSFiles ',aFile.PasFilename,' ',aFile.JSFilename);
-      Log.LogMsg(nWritingFile,[QuoteStr(FileCache.FormatPath(DestFilename))],'',0,0,
-                 not (coShowLineNumbers in Options));
-
-      // check output directory
-      DestDir:=ChompPathDelim(ExtractFilePath(DestFilename));
-      if (DestDir<>'') and not DirectoryExists(DestDir) then
-      begin
-        Log.LogMsg(nOutputDirectoryNotFound,[QuoteStr(FileCache.FormatPath(DestDir))]);
-        Terminate(ExitCodeFileNotFound);
-      end;
-      if DirectoryExists(DestFilename) then
+      end else if FreeWriter then
       begin
-        Log.LogMsg(nFileIsFolder,[QuoteStr(FileCache.FormatPath(DestFilename))]);
-        Terminate(ExitCodeWriteError);
-      end;
+        // write to file
 
-      MapFilename:=DestFilename+'.map';
+        //writeln('TPas2jsCompiler.WriteJSFiles ',aFile.PasFilename,' ',aFile.JSFilename);
+        Log.LogMsg(nWritingFile,[QuoteStr(FileCache.FormatPath(DestFilename))],'',0,0,
+                   not (coShowLineNumbers in Options));
 
-      // write js
-      try
-        {$IFDEF Pas2js}
-        buf:=TJSArray.new;
-        {$ELSE}
-        buf:=TMemoryStream.Create;
-        {$ENDIF}
-        try
-          {$IFDEF FPC_HAS_CPSTRING}
-          // UTF8-BOM
-          if (Log.Encoding='') or (Log.Encoding='utf8') then
-          begin
-            Src:=String(UTF8BOM);
-            buf.Write(Src[1],length(Src));
-          end;
-          {$ENDIF}
-          // JS source
-          {$IFDEF Pas2js}
-          buf:=TJSArray(aFileWriter.Buffer).slice();
-          {$ELSE}
-          buf.Write(aFileWriter.Buffer^,aFileWriter.BufferLength);
-          {$ENDIF}
-          // source map comment
-          if aFileWriter.SrcMap<>nil then
-          begin
-            Src:='//# sourceMappingURL='+ExtractFilename(MapFilename)+LineEnding;
-            {$IFDEF Pas2js}
-            buf.push(Src);
-            {$ELSE}
-            buf.Write(Src[1],length(Src));
-            {$ENDIF}
-          end;
-          {$IFDEF Pas2js}
-          {$ELSE}
-          buf.Position:=0;
-          {$ENDIF}
-          FileCache.SaveToFile(buf,DestFilename);
-        finally
-          {$IFDEF Pas2js}
-          buf:=nil;
-          {$ELSE}
-          buf.Free;
-          {$ENDIF}
+        // check output directory
+        DestDir:=ChompPathDelim(ExtractFilePath(DestFilename));
+        if (DestDir<>'') and not DirectoryExists(DestDir) then
+        begin
+          Log.LogMsg(nOutputDirectoryNotFound,[QuoteStr(FileCache.FormatPath(DestDir))]);
+          Terminate(ExitCodeFileNotFound);
         end;
-      except
-        on E: Exception do begin
-          if ShowDebug then
-            Log.LogExceptionBackTrace(E);
-          {$IFDEF FPC}
-          if E.Message<>SafeFormat(SFCreateError,[DestFileName]) then
-          {$ENDIF}
-            Log.LogPlain('Error: '+E.Message);
-          Log.LogMsg(nUnableToWriteFile,[QuoteStr(FileCache.FormatPath(DestFilename))]);
+        if DirectoryExists(DestFilename) then
+        begin
+          Log.LogMsg(nFileIsFolder,[QuoteStr(FileCache.FormatPath(DestFilename))]);
           Terminate(ExitCodeWriteError);
-        end
-        {$IFDEF Pas2js}
-        else HandleJSException('[20181031190637] TPas2jsCompiler.WriteJSFiles',JSExceptValue,true);
-        {$ENDIF}
-      end;
+        end;
 
-      // write source map
-      if aFileWriter.SrcMap<>nil then
-      begin
-        Log.LogMsg(nWritingFile,[QuoteStr(FileCache.FormatPath(MapFilename))],'',0,0,
-                   not (coShowLineNumbers in Options));
-        FinishSrcMap(aFileWriter.SrcMap);
+        MapFilename:=DestFilename+'.map';
+
+        // write js
         try
           {$IFDEF Pas2js}
           buf:=TJSArray.new;
@@ -2672,13 +2622,35 @@ begin
           buf:=TMemoryStream.Create;
           {$ENDIF}
           try
-            // Note: No UTF-8 BOM in source map, Chrome 59 gives an error
-            aFileWriter.SrcMap.SaveToStream(buf);
+            {$IFDEF FPC_HAS_CPSTRING}
+            // UTF8-BOM
+            if (Log.Encoding='') or (Log.Encoding='utf8') then
+            begin
+              Src:=String(UTF8BOM);
+              buf.Write(Src[1],length(Src));
+            end;
+            {$ENDIF}
+            // JS source
+            {$IFDEF Pas2js}
+            buf:=TJSArray(aFileWriter.Buffer).slice();
+            {$ELSE}
+            buf.Write(aFileWriter.Buffer^,aFileWriter.BufferLength);
+            {$ENDIF}
+            // source map comment
+            if aFileWriter.SrcMap<>nil then
+            begin
+              Src:='//# sourceMappingURL='+ExtractFilename(MapFilename)+LineEnding;
+              {$IFDEF Pas2js}
+              buf.push(Src);
+              {$ELSE}
+              buf.Write(Src[1],length(Src));
+              {$ENDIF}
+            end;
             {$IFDEF Pas2js}
             {$ELSE}
             buf.Position:=0;
             {$ENDIF}
-            FileCache.SaveToFile(buf,MapFilename);
+            FileCache.SaveToFile(buf,DestFilename);
           finally
             {$IFDEF Pas2js}
             buf:=nil;
@@ -2694,13 +2666,57 @@ begin
             if E.Message<>SafeFormat(SFCreateError,[DestFileName]) then
             {$ENDIF}
               Log.LogPlain('Error: '+E.Message);
-            Log.LogMsg(nUnableToWriteFile,[QuoteStr(FileCache.FormatPath(MapFilename))]);
+            Log.LogMsg(nUnableToWriteFile,[QuoteStr(FileCache.FormatPath(DestFilename))]);
             Terminate(ExitCodeWriteError);
           end
           {$IFDEF Pas2js}
-          else HandleJSException('[20181031190737] TPas2jsCompiler.WriteJSFiles',JSExceptValue);
+          else HandleJSException('[20181031190637] TPas2jsCompiler.WriteJSFiles',JSExceptValue,true);
           {$ENDIF}
         end;
+
+        // write source map
+        if aFileWriter.SrcMap<>nil then
+        begin
+          Log.LogMsg(nWritingFile,[QuoteStr(FileCache.FormatPath(MapFilename))],'',0,0,
+                     not (coShowLineNumbers in Options));
+          FinishSrcMap(aFileWriter.SrcMap);
+          try
+            {$IFDEF Pas2js}
+            buf:=TJSArray.new;
+            {$ELSE}
+            buf:=TMemoryStream.Create;
+            {$ENDIF}
+            try
+              // Note: No UTF-8 BOM in source map, Chrome 59 gives an error
+              aFileWriter.SrcMap.SaveToStream(buf);
+              {$IFDEF Pas2js}
+              {$ELSE}
+              buf.Position:=0;
+              {$ENDIF}
+              FileCache.SaveToFile(buf,MapFilename);
+            finally
+              {$IFDEF Pas2js}
+              buf:=nil;
+              {$ELSE}
+              buf.Free;
+              {$ENDIF}
+            end;
+          except
+            on E: Exception do begin
+              if ShowDebug then
+                Log.LogExceptionBackTrace(E);
+              {$IFDEF FPC}
+              if E.Message<>SafeFormat(SFCreateError,[DestFileName]) then
+              {$ENDIF}
+                Log.LogPlain('Error: '+E.Message);
+              Log.LogMsg(nUnableToWriteFile,[QuoteStr(FileCache.FormatPath(MapFilename))]);
+              Terminate(ExitCodeWriteError);
+            end
+            {$IFDEF Pas2js}
+            else HandleJSException('[20181031190737] TPas2jsCompiler.WriteJSFiles',JSExceptValue);
+            {$ENDIF}
+          end;
+        end;
       end;
     end;
 
@@ -3067,7 +3083,7 @@ var
   Skip: TSkip;
   CacheFile: TPas2jsCachedFile;
 begin
-  if ShowTriedUsedFiles then
+  if ShowDebug or ShowTriedUsedFiles then
     Log.LogMsgIgnoreFilter(nReadingOptionsFromFile,[QuoteStr(CfgFilename)]);
   IfLvl:=0;
   SkipLvl:=0;
@@ -3221,7 +3237,7 @@ begin
     FCurrentCfgLineNumber:=OldCfgLineNumber;
     aFile.Free;
   end;
-  if ShowTriedUsedFiles then
+  if ShowDebug or ShowTriedUsedFiles then
     Log.LogMsgIgnoreFilter(nEndOfReadingConfigFile,[QuoteStr(CfgFilename)]);
 end;
 
@@ -3232,7 +3248,7 @@ procedure TPas2jsCompiler.LoadDefaultConfig;
     Result:=false;
     if aFilename='' then exit;
     aFilename:=ExpandFileName(aFilename);
-    if ShowTriedUsedFiles then
+    if ShowDebug or ShowTriedUsedFiles then
       Log.LogMsgIgnoreFilter(nConfigFileSearch,[aFilename]);
     if not DirectoryCache.FileExists(aFilename) then exit;
     Result:=true;
@@ -3269,7 +3285,10 @@ end;
 
 procedure TPas2jsCompiler.ParamFatal(Msg: string);
 begin
-  Log.LogPlain(['Fatal: ',Msg]);
+  if CurrentCfgFilename<>'' then
+    Log.Log(mtFatal,Msg,0,CurrentCfgFilename,CurrentCfgLineNumber,0)
+  else
+    Log.LogPlain(['Fatal: ',Msg]);
   Terminate(ExitCodeErrorInParams);
 end;
 
@@ -3294,6 +3313,7 @@ var
   aProc, pr: TPasToJsProcessor;
   Enable: Boolean;
   aPlatform, pl: TPasToJsPlatform;
+  PostProc: TStringList;
   {$IFDEF HasPas2jsFiler}
   Found: Boolean;
   PF: TPas2JSPrecompileFormat;
@@ -3584,6 +3604,27 @@ begin
               else
                 UnknownParam;
             end;
+          'p':
+            // -Jp<...>
+            if copy(Param,p,3)='cmd' then
+            begin
+              inc(p,3);
+              if not Quick then
+              begin
+                PostProc:=TStringList.Create;
+                PostProcs.Add(PostProc);
+                SplitCmdLineParams(copy(Param,p,length(Param)),PostProc);
+                if PostProc.Count<1 then
+                  ParamFatal('-Jpcmd executable missing');
+                // check executable
+                Value:=PostProc[0];
+                aFilename:=FileCache.ExpandExecutable(PostProc[0],'');
+                if aFilename='' then
+                  ParamFatal('-Jpcmd executable "'+Value+'" not found');
+                PostProc[0]:=aFilename;
+              end;
+            end else
+              UnknownParam;
           'u':
             if not Quick then
               if not FileCache.AddSrcUnitPaths(copy(Param,p,length(Param)),FromCmdLine,ErrorMsg) then
@@ -3999,9 +4040,170 @@ begin
   r(mtFatal,nUnitFileNotFound,sUnitFileNotFound);
   r(mtInfo,nClassInterfaceStyleIs,sClassInterfaceStyleIs);
   r(mtInfo,nMacroXSetToY,sMacroXSetToY);
+  r(mtInfo,nPostProcessorInfoX,sPostProcessorInfoX);
+  r(mtInfo,nPostProcessorRunX,sPostProcessorRunX);
+  r(mtError,nPostProcessorFailX,sPostProcessorFailX);
+  r(mtWarning,nPostProcessorWarnX,sPostProcessorWarnX);
+  r(mtInfo,nPostProcessorFinished,sPostProcessorFinished);
   Pas2jsPParser.RegisterMessages(Log);
 end;
 
+procedure TPas2jsCompiler.CallPostProcessors(const JSFilename: String;
+  aWriter: TPas2JSMapper);
+var
+  i: Integer;
+  JS, OrigJS: TJSWriterString;
+begin
+  if PostProcs.Count=0 then exit;
+  OrigJS:=aWriter.AsString;
+  JS:=OrigJS;
+  for i:=0 to PostProcs.Count-1 do
+    JS:=CallPostProcessor(JSFilename,TStringList(PostProcs[i]),JS);
+  if JS<>OrigJS then
+  begin
+    aWriter.AsString:=JS;
+    if aWriter.SrcMap<>nil then
+      aWriter.SrcMap.Clear;
+  end;
+end;
+
+function TPas2jsCompiler.CallPostProcessor(const JSFilename: String;
+  Cmd: TStringList; JS: TJSWriterString): TJSWriterString;
+{$IFDEF pas2js}
+begin
+  Result:='';
+  if ShowDebug or ShowUsedTools then
+    Log.LogMsgIgnoreFilter(nPostProcessorRunX,[QuoteStr(JSFilename)+' | '+CmdListAsStr(Cmd)]);
+  raise EFOpenError.Create('post processing is not yet implemented in platform nodejs');
+  if JSFilename='' then ;
+  if Cmd=nil then ;
+  if JS='' then ;
+end;
+{$ELSE}
+const
+  BufSize = 65536;
+var
+  Exe: String;
+  TheProcess: TProcess;
+  WrittenBytes, ReadBytes: LongInt;
+  Buf, s, ErrBuf: string;
+  OutputChunks: TStringList;
+  CurExitCode, i, InPos: Integer;
+begin
+  Result:='';
+  Exe:=Cmd[0];
+  if ShowDebug or ShowUsedTools then
+    Log.LogMsgIgnoreFilter(nPostProcessorRunX,[QuoteStr(JSFilename)+' | '+CmdListAsStr(Cmd)]);
+  if DirectoryCache.DirectoryExists(Exe) then
+    raise EFOpenError.Create('post processor "'+Exe+'" is a directory');
+  if not FileIsExecutable(Exe) then
+    raise EFOpenError.Create('post processor "'+Exe+'" is a not executable');
+  try
+    TheProcess := TProcess.Create(nil);
+    OutputChunks:=TStringList.Create;
+    try
+      TheProcess.Executable := Exe;
+      for i:=1 to Cmd.Count-1 do
+        TheProcess.Parameters.Add(Cmd[i]);
+      TheProcess.Options:= [poUsePipes];
+      TheProcess.ShowWindow := swoHide;
+      //TheProcess.CurrentDirectory:=WorkingDirectory;
+      TheProcess.Execute;
+      ErrBuf:='';
+      SetLength(Buf,BufSize);
+      InPos:=1;
+      repeat
+        // read stderr and log immediately as warnings
+        repeat
+          if TheProcess.Stderr.NumBytesAvailable=0 then break;
+          ReadBytes:=TheProcess.Stderr.Read(Buf[1],BufSize);
+          if ReadBytes=0 then break;
+          ErrBuf+=LeftStr(Buf,ReadBytes);
+          repeat
+            i:=1;
+            while (i<=length(ErrBuf)) and (i<128) and not (ErrBuf[i] in [#10,#13]) do
+              inc(i);
+            if i>length(ErrBuf) then break;
+            Log.LogMsg(nPostProcessorWarnX,[LeftStr(ErrBuf,i)]);
+            if (i<=length(ErrBuf)) and (ErrBuf[i] in [#10,#13]) then
+            begin
+              // skip linebreak
+              if (i<length(ErrBuf)) and (ErrBuf[i+1] in [#10,#13])
+                  and (ErrBuf[i]<>ErrBuf[i+1]) then
+                inc(i,2)
+              else
+                inc(i);
+            end;
+            Delete(ErrBuf,1,i-1);
+          until false;
+        until false;
+        // write to stdin
+        if InPos<length(JS) then
+        begin
+          i:=length(JS)-InPos+1;
+          if i>BufSize then i:=BufSize;
+          WrittenBytes:=TheProcess.Input.Write(JS[InPos],i);
+          inc(InPos,WrittenBytes);
+          if InPos>length(JS) then
+            TheProcess.CloseInput;
+        end else
+          WrittenBytes:=0;
+        // read stdout
+        if TheProcess.Output.NumBytesAvailable=0 then
+          ReadBytes:=0
+        else
+          ReadBytes:=TheProcess.Output.Read(Buf[1],BufSize);
+        if ReadBytes>0 then
+          OutputChunks.Add(LeftStr(Buf,ReadBytes));
+
+        if (WrittenBytes=0) and (ReadBytes=0) then
+        begin
+          if not TheProcess.Running then break;
+          Sleep(10); // give tool some time
+        end;
+      until false;
+      TheProcess.WaitOnExit;
+      CurExitCode:=TheProcess.ExitCode;
+
+      // concatenate output chunks
+      ReadBytes:=0;
+      for i:=0 to OutputChunks.Count-1 do
+        inc(ReadBytes,length(OutputChunks[i]));
+      SetLength(Result,ReadBytes);
+      ReadBytes:=0;
+      for i:=0 to OutputChunks.Count-1 do
+      begin
+        s:=OutputChunks[i];
+        if s='' then continue;
+        System.Move(s[1],Result[ReadBytes+1],length(s));
+        inc(ReadBytes,length(s));
+      end;
+    finally
+      OutputChunks.Free;
+      TheProcess.Free;
+    end;
+  except
+    on E: Exception do begin
+      if ShowDebug then
+        Log.LogExceptionBackTrace(E);
+      Log.LogPlain('Error: '+E.Message);
+      Log.LogMsg(nPostProcessorFailX,[CmdListAsStr(Cmd)]);
+      Terminate(ExitCodeToolError);
+    end
+    {$IFDEF Pas2js}
+    else HandleJSException('[20181118170506] TPas2jsCompiler.CallPostProcessor Cmd: '+CmdListAsStr(Cmd),JSExceptValue,true);
+    {$ENDIF}
+  end;
+  if CurExitCode<>0 then
+  begin
+    Log.LogMsg(nPostProcessorFailX,[CmdListAsStr(Cmd)]);
+    Terminate(ExitCodeToolError);
+  end;
+  if ShowDebug or ShowUsedTools then
+    Log.LogMsgIgnoreFilter(nPostProcessorFinished,[]);
+end;
+{$ENDIF}
+
 constructor TPas2jsCompiler.Create;
 begin
   FOptions:=DefaultP2jsCompilerOptions;
@@ -4014,6 +4216,7 @@ begin
   FFileCacheAutoFree:=true;
   FDirectoryCache:=FFileCache.DirectoryCache;
   FLog.OnFormatPath:[email protected];
+  FPostProcs:=TObjectList.Create(true);
 
   FDefines:=TStringList.Create;
   // Done by Reset: TStringList(FDefines).Sorted:=True;
@@ -4059,6 +4262,7 @@ destructor TPas2jsCompiler.Destroy;
     FreeAndNil(FDefines);
     FreeAndNil(FConditionEval);
 
+    FreeAndNil(FPostProcs);
     FLog.OnFormatPath:=nil;
     if FFileCacheAutoFree then
       FreeAndNil(FFileCache)
@@ -4168,6 +4372,7 @@ begin
   FReadingModules.Clear;
   FFiles.FreeItems;
 
+  FPostProcs.Clear;
   FCompilerExe:='';
   FOptions:=DefaultP2jsCompilerOptions;
   FRTLVersionCheck:=DefaultP2jsRTLVersionCheck;
@@ -4255,6 +4460,8 @@ begin
       WriteOptions;
       WriteDefines;
     end;
+    if ShowDebug or ShowUsedTools then
+      WriteUsedTools;
     if ShowDebug or ShowTriedUsedFiles then
       WriteFoldersAndSearchPaths;
 
@@ -4272,13 +4479,14 @@ begin
     on E: Exception do begin
       if ShowDebug then
         Log.LogExceptionBackTrace(E);
+      raise; // reraise unexpected exception
     end else begin
       if ShowDebug then
         Log.LogExceptionBackTrace(nil);
       {$IFDEF Pas2js}
       HandleJSException('[20181031190933] TPas2jsCompiler.Run',JSExceptValue,false);
       {$ENDIF}
-      raise;
+      raise; // reraise unexpected exception
     end;
   end;
 end;
@@ -4416,6 +4624,7 @@ begin
   w('     -JoCheckVersion=main : insert rtl version check into main.');
   w('     -JoCheckVersion=system : insert rtl version check into system unit init.');
   w('     -JoCheckVersion=unit : insert rtl version check into every unit init.');
+  w('   -Jpcmd<command> : Run postprocessor. For each generated js execute command passing the js as stdin and read the new js from stdout. This option can be added multiple times to call several postprocessors in succession.');
   w('   -Ju<x> : Add <x> to foreign unit paths. Foreign units are not compiled.');
   {$IFDEF HasPas2jsFiler}
   if PrecompileFormats.Count>0 then
@@ -4559,6 +4768,19 @@ begin
     end;
 end;
 
+procedure TPas2jsCompiler.WriteUsedTools;
+var
+  i: Integer;
+  PostProc: TStringList;
+begin
+  // post processors
+  for i:=0 to PostProcs.Count-1 do
+  begin
+    PostProc:=TStringList(PostProcs[i]);
+    Log.LogMsgIgnoreFilter(nPostProcessorInfoX,[CmdListAsStr(PostProc)]);
+  end;
+end;
+
 procedure TPas2jsCompiler.WriteFoldersAndSearchPaths;
 
   procedure WriteFolder(aName, Folder: string);
@@ -4633,6 +4855,18 @@ begin
   if coShowDebug in FOptions then Include(Result,mtDebug);
 end;
 
+function TPas2jsCompiler.CmdListAsStr(CmdList: TStrings): string;
+var
+  i: Integer;
+begin
+  Result:='';
+  for i:=0 to CmdList.Count-1 do
+  begin
+    if Result<>'' then Result+=' ';
+    Result+=QuoteStr(CmdList[i]);
+  end;
+end;
+
 procedure TPas2jsCompiler.SetOption(Flag: TP2jsCompilerOption; Enable: boolean);
 begin
   if Enable then

+ 53 - 2
packages/pastojs/src/pas2jsfilecache.pp

@@ -342,6 +342,7 @@ type
     procedure RaiseDuplicateFile(aFilename: string);
     procedure SaveToFile(ms: TFPJSStream; Filename: string);
     function ExpandDirectory(const Filename, BaseDir: string): string;
+    function ExpandExecutable(const Filename, BaseDir: string): string;
   public
     property AllJSIntoMainJS: Boolean read GetAllJSIntoMainJS write SetAllJSIntoMainJS;
     property BaseDirectory: string read FBaseDirectory write SetBaseDirectory; // includes trailing pathdelim
@@ -2216,9 +2217,9 @@ begin
         i:=GetLastOSError;
         if i<>0 then
           Log.LogPlain('Note: '+SysErrorMessage(i));
-        if not SysUtils.DirectoryExists(ChompPathDelim(ExtractFilePath(Filename))) then
+        if not DirectoryCache.DirectoryExists(ChompPathDelim(ExtractFilePath(Filename))) then
           Log.LogPlain('Note: file cache inconsistency: folder does not exist "'+ChompPathDelim(ExtractFilePath(Filename))+'"');
-        if SysUtils.FileExists(Filename) and not FileIsWritable(Filename) then
+        if DirectoryCache.FileExists(Filename) and not FileIsWritable(Filename) then
           Log.LogPlain('Note: file is not writable "'+Filename+'"');
         raise;
       end;
@@ -2239,5 +2240,55 @@ begin
   Result:=IncludeTrailingPathDelimiter(Result);
 end;
 
+function TPas2jsFilesCache.ExpandExecutable(const Filename, BaseDir: string
+  ): string;
+
+  function TryFile(CurFilename: string): boolean;
+  begin
+    Result:=false;
+    CurFilename:=ResolveDots(CurFilename);
+    if not DirectoryCache.FileExists(CurFilename) then exit;
+    ExpandExecutable:=CurFilename;
+    Result:=true;
+  end;
+
+var
+  PathVar, CurPath: String;
+  p, StartPos: Integer;
+begin
+  if Filename='' then exit('');
+  if ExtractFilePath(Filename)='' then
+  begin
+    // no file path -> search
+    {$IFDEF Windows}
+    // search in BaseDir
+    if BaseDir<>'' then
+    begin
+      if TryFile(IncludeTrailingPathDelimiter(BaseDir)+Filename) then exit;
+    end else if BaseDirectory<>'' then
+    begin
+      if TryFile(IncludeTrailingPathDelimiter(BaseDirectory)+Filename) then exit;
+    end;
+    {$ENDIF}
+    // search in PATH
+    PathVar:=GetEnvironmentVariablePJ('PATH');
+    p:=1;
+    while p<=length(PathVar) do
+    begin
+      while (p<=length(PathVar)) and (PathVar[p]=PathSeparator) do inc(p);
+      StartPos:=p;
+      while (p<=length(PathVar)) and (PathVar[p]<>PathSeparator) do inc(p);
+      CurPath:=copy(PathVar,StartPos,p-StartPos);
+      if CurPath='' then continue;
+      CurPath:=ExpandFileNamePJ(CurPath);
+      if CurPath='' then continue;
+      if TryFile(IncludeTrailingPathDelimiter(CurPath)+Filename) then exit;
+    end;
+  end else if BaseDir<>'' then
+    Result:=ExpandFileNamePJ(Filename,BaseDir)
+  else
+    Result:=ExpandFileNamePJ(Filename,BaseDirectory);
+end;
+
 end.
 

+ 90 - 0
packages/pastojs/src/pas2jsfileutils.pp

@@ -58,6 +58,7 @@ function ResolveSymLinks(const Filename: string;
                  {%H-}ExceptionOnError: boolean): string; // if a link is broken returns ''
 function MatchGlobbing(Mask, Name: string): boolean;
 function FileIsWritable(const AFilename: string): boolean;
+function FileIsExecutable(const AFilename: string): boolean;
 
 function GetEnvironmentVariableCountPJ: Integer;
 function GetEnvironmentStringPJ(Index: Integer): string;
@@ -65,6 +66,8 @@ function GetEnvironmentVariablePJ(const EnvVar: string): String;
 
 function GetNextDelimitedItem(const List: string; Delimiter: char;
                               var Position: integer): string;
+procedure SplitCmdLineParams(const Params: string; ParamList: TStrings;
+                             ReadBackslash: boolean = false);
 
 type TChangeStamp = SizeInt;
 const InvalidChangeStamp = low(TChangeStamp);
@@ -729,6 +732,93 @@ begin
   if Position<=length(List) then inc(Position); // skip Delimiter
 end;
 
+procedure SplitCmdLineParams(const Params: string; ParamList: TStrings;
+                             ReadBackslash: boolean = false);
+// split spaces, quotes are parsed as single parameter
+// if ReadBackslash=true then \" is replaced to " and not treated as quote
+// #0 is always end
+type
+  TMode = (mNormal,mApostrophe,mQuote);
+var
+  p: Integer;
+  Mode: TMode;
+  Param: String;
+begin
+  p:=1;
+  while p<=length(Params) do
+  begin
+    // skip whitespace
+    while (p<=length(Params)) and (Params[p] in [' ',#9,#10,#13]) do inc(p);
+    if (p>length(Params)) or (Params[p]=#0) then
+      break;
+    // read param
+    Param:='';
+    Mode:=mNormal;
+    while p<=length(Params) do
+    begin
+      case Params[p] of
+      #0:
+        break;
+      '\':
+        begin
+          inc(p);
+          if ReadBackslash then
+            begin
+            // treat next character as normal character
+            if (p>length(Params)) or (Params[p]=#0) then
+              break;
+            if ord(Params[p])<128 then
+            begin
+              Param+=Params[p];
+              inc(p);
+            end else begin
+              // next character is already a normal character
+            end;
+          end else begin
+            // treat backslash as normal character
+            Param+='\';
+          end;
+        end;
+      '''':
+        begin
+          inc(p);
+          case Mode of
+          mNormal:
+            Mode:=mApostrophe;
+          mApostrophe:
+            Mode:=mNormal;
+          mQuote:
+            Param+='''';
+          end;
+        end;
+      '"':
+        begin
+          inc(p);
+          case Mode of
+          mNormal:
+            Mode:=mQuote;
+          mApostrophe:
+            Param+='"';
+          mQuote:
+            Mode:=mNormal;
+          end;
+        end;
+      ' ',#9,#10,#13:
+        begin
+          if Mode=mNormal then break;
+          Param+=Params[p];
+          inc(p);
+        end;
+      else
+        Param+=Params[p];
+        inc(p);
+      end;
+    end;
+    //writeln('SplitCmdLineParams Param=#'+Param+'#');
+    ParamList.Add(Param);
+  end;
+end;
+
 procedure IncreaseChangeStamp(var Stamp: TChangeStamp);
 begin
   if Stamp<High(TChangeStamp) then

+ 10 - 0
packages/pastojs/src/pas2jsfileutilsnodejs.inc

@@ -152,6 +152,16 @@ begin
   Result:=true;
 end;
 
+function FileIsExecutable(const AFilename: string): boolean;
+begin
+  try
+    NJS_FS.accessSync(AFilename,X_OK);
+  except
+    exit(false);
+  end;
+  Result:=true;
+end;
+
 function GetEnvironmentVariableCountPJ: Integer;
 begin
   Result:=GetEnvironmentVariableCount;

+ 9 - 0
packages/pastojs/src/pas2jsfileutilsunix.inc

@@ -148,6 +148,15 @@ begin
   Result := BaseUnix.FpAccess(AFilename, BaseUnix.W_OK) = 0;
 end;
 
+function FileIsExecutable(const AFilename: string): boolean;
+var
+  Info : Stat;
+begin
+  // first check AFilename is not a directory and then check if executable
+  Result:= (FpStat(AFilename,info{%H-})<>-1) and FPS_ISREG(info.st_mode) and
+           (BaseUnix.FpAccess(AFilename,BaseUnix.X_OK)=0);
+end;
+
 function GetEnvironmentVariableCountPJ: Integer;
 begin
   Result:=GetEnvironmentVariableCount;

+ 5 - 0
packages/pastojs/src/pas2jsfileutilswin.inc

@@ -421,6 +421,11 @@ begin
   Result:=((FileGetAttrUTF8(AFilename) and faReadOnly) = 0);
 end;
 
+function FileIsExecutable(const AFilename: string): boolean;
+begin
+  Result:=FileExists(AFilename);
+end;
+
 function GetEnvironmentVariableCountPJ: Integer;
 var
   hp,p : PWideChar;

+ 1 - 0
packages/pastojs/src/pas2jslogger.pp

@@ -42,6 +42,7 @@ const
   ExitCodeSyntaxError = 6;
   ExitCodeConverterError = 7;
   ExitCodePCUError = 8;
+  ExitCodeToolError = 9;
 
 const
   DefaultLogMsgTypes = [mtFatal..mtDebug]; // by default show everything

+ 25 - 0
packages/pastojs/tests/tcmodules.pas

@@ -381,6 +381,7 @@ type
     Procedure TestCaseOfRange;
     Procedure TestCaseOfString;
     Procedure TestCaseOfExternalClassConst;
+    Procedure TestDebugger;
 
     // arrays
     Procedure TestArray_Dynamic;
@@ -7081,6 +7082,30 @@ begin
     ]));
 end;
 
+procedure TTestModule.TestDebugger;
+begin
+  StartProgram(false);
+  Add([
+  'procedure DoIt;',
+  'begin',
+  '  deBugger;',
+  '  DeBugger();',
+  'end;',
+  'begin',
+  '  Debugger;']);
+  ConvertProgram;
+  CheckSource('TestDebugger',
+    LinesToStr([ // statements
+    'this.DoIt = function () {',
+    '  debugger;',
+    '  debugger;',
+    '};',
+    '']),
+    LinesToStr([ // $mod.$main
+    'debugger;',
+    '']));
+end;
+
 procedure TTestModule.TestArray_Dynamic;
 begin
   StartProgram(false);

+ 1 - 0
packages/rtl-objpas/fpmake.pp

@@ -64,6 +64,7 @@ begin
     P.IncludePath.Add('src/common',CommonSrcOSes);
 
     T:=P.Targets.AddUnit('strutils.pp',StrUtilsOses);
+      T.ResourceStrings:=true;
     T:=P.Targets.AddUnit('widestrutils.pp',StrUtilsOses-ConvUtilOSes);
     T:=P.Targets.AddUnit('varutils.pp',VarUtilsOses);
     with T.Dependencies do

+ 1 - 0
packages/winunits-base/fpmake.pp

@@ -77,6 +77,7 @@ begin
     T:=P.Targets.AddImplicitUnit('activex.pp');
     T:=P.Targets.AddImplicitUnit('urlmon.pp');
     T:=P.Targets.AddImplicitUnit('comconst.pp');
+      T.ResourceStrings:=true;
     T:=P.Targets.AddImplicitUnit('commctrl.pp');
     T:=P.Targets.AddImplicitUnit('commdlg.pp');
     T:=P.Targets.AddImplicitUnit('comobj.pp');

+ 91 - 91
rtl/watcom/Makefile

@@ -348,277 +348,277 @@ override FPCOPT+=-dEXCEPTIONS_IN_SYSTEM
 endif
 override FPCOPT+=-dNO_EXCEPTIONS_IN_SYSTEM
 ifeq ($(FULL_TARGET),i386-linux)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),i386-go32v2)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),i386-win32)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),i386-os2)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),i386-freebsd)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),i386-beos)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),i386-haiku)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),i386-netbsd)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),i386-solaris)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),i386-netware)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),i386-openbsd)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),i386-wdosx)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),i386-darwin)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),i386-emx)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),i386-watcom)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),i386-netwlibc)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),i386-wince)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),i386-embedded)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),i386-symbian)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),i386-nativent)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),i386-iphonesim)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),i386-android)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),i386-aros)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),m68k-linux)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),m68k-netbsd)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),m68k-amiga)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),m68k-atari)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),m68k-palmos)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),m68k-macos)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),m68k-embedded)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),powerpc-linux)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),powerpc-netbsd)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),powerpc-amiga)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),powerpc-macos)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),powerpc-darwin)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),powerpc-morphos)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),powerpc-embedded)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),powerpc-wii)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),powerpc-aix)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),sparc-linux)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),sparc-netbsd)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),sparc-solaris)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),sparc-embedded)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),x86_64-linux)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),x86_64-freebsd)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),x86_64-netbsd)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),x86_64-solaris)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),x86_64-openbsd)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),x86_64-darwin)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),x86_64-win64)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),x86_64-embedded)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),x86_64-iphonesim)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),x86_64-android)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),x86_64-aros)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),x86_64-dragonfly)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),arm-linux)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),arm-netbsd)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),arm-palmos)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),arm-darwin)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),arm-wince)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),arm-gba)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),arm-nds)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),arm-embedded)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),arm-symbian)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),arm-android)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),arm-aros)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),powerpc64-linux)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),powerpc64-darwin)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),powerpc64-embedded)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),powerpc64-aix)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),avr-embedded)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),armeb-linux)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),armeb-embedded)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),mips-linux)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),mipsel-linux)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),mipsel-embedded)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),mipsel-android)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),jvm-java)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),jvm-android)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),i8086-embedded)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),i8086-msdos)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),i8086-win16)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),aarch64-linux)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),aarch64-darwin)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),aarch64-android)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),wasm-wasm)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),sparc64-linux)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),riscv32-linux)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),riscv32-embedded)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),riscv64-linux)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),riscv64-embedded)
-override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx sysutils
+override TARGET_UNITS+=system uuchar objpas macpas iso7185 extpas strings watcom dos cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl math typinfo mmx classes sysutils
 endif
 ifeq ($(FULL_TARGET),i386-linux)
 override TARGET_IMPLICITUNITS+=exeinfo cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp737 cp775 cp850 cp852 cp855 cp856 cp857 cp860 cp861 cp862 cp863 cp864 cp865 cp866 cp869 cp874 cp3021 cp8859_1 cp8859_2 cp8859_3 cp8859_4 cp8859_5 cp8859_6 cp8859_7 cp8859_8 cp8859_9 cp8859_10 cp8859_11 cp8859_13 cp8859_14 cp8859_15 cp8859_16 cpkoi8_r cpkoi8_u

+ 1 - 1
rtl/watcom/Makefile.fpc

@@ -11,7 +11,7 @@ loaders=prt0
 units=system uuchar objpas macpas iso7185 extpas strings watcom dos \
       cpu charset cpall types getopts heaptrc lnfodwrf lineinfo ctypes fgl \
       math typinfo mmx \
-      sysutils
+      classes sysutils
 implicitunits=exeinfo \
       cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 \
       cp437 cp646 cp737 cp775 cp850 cp852 cp855 cp856 cp857 cp860 cp861 cp862 \

+ 136 - 0
tests/webtbs/tw34605.pp

@@ -0,0 +1,136 @@
+{%OPT=-CR}
+
+{ This test checks that correct code is generated
+  when typecasting a class reference type variable with a descendent class }
+
+{$mode objfpc}
+
+uses
+  sysutils;
+
+type
+
+  TBaseClass = class
+   constructor Create;
+   class var  x : longint;
+   var loc : longint;
+   class procedure check; virtual;
+  end;
+
+  TDerClass = class(TBaseClass)
+   var der : longint;
+  end;
+
+  TDer1Class = class(TDerClass)
+   constructor Create;
+   class var y : longint;
+   var loc1 : longint;
+   class procedure check; override;
+  end;
+
+  TDer2Class = class(TDerClass)
+   constructor Create;
+   class var z : longint;
+   var loc2 : longint;
+   class procedure check; override;
+  end;
+
+constructor TBaseClass.Create;
+  begin
+    Inherited Create;
+    x:=1;
+  end;
+
+constructor TDer1Class.Create;
+  begin
+    Inherited Create;
+    y:=1;
+  end;
+
+constructor TDer2Class.Create;
+  begin
+    Inherited Create;
+    z:=1;
+  end;
+
+class procedure TBaseClass.check;
+begin
+  writeln('TBaseClass.check called');
+end;
+
+class procedure TDer1Class.check;
+begin
+  writeln('TDer1Class.check called');
+end;
+
+class procedure TDer2Class.check;
+begin
+  writeln('TDer2Class.check called');
+end;
+
+type
+  TBaseClassRef = class of TBaseClass;
+  TDerClassRef = class of TDerClass;
+
+var
+  c : TBaseClass;
+  cc : TBaseClassRef;
+  dcc : TDerClassRef;
+  exception_generated : boolean;
+
+begin
+  exception_generated:=false;
+  c:=TBaseClass.Create;
+
+  inc(c.x);
+  c.check;
+  c.free;
+
+  c:=TDer1Class.Create;
+
+  inc(c.x);
+  inc(TDer1Class(c).y);
+  c.check;
+  c.free;
+
+  c:=TDer2Class.Create;
+  inc(c.x);
+  inc(TDer2Class(c).z);
+  c.check;
+  c.free;
+
+  cc:=TbaseClass;
+  inc(cc.x);
+  cc.check;
+
+  cc:=TDer1Class;
+  inc(cc.x);
+  cc.check;
+
+
+  cc:=TDer2Class;
+  inc(cc.x);
+  cc.check;
+  TDerClassRef(cc).check;
+  TDerClass(cc).check;
+
+  dcc:=TDerClass;
+  dcc.check;
+
+  try
+    //inc (TDer1Class(cc).y);
+    TDer1Class(cc).check;
+  except
+    writeln('Exception generated');
+    exception_generated:=true;
+  end;
+  writeln('TBaseClass: x=',TBaseClass.x);
+  writeln('TDer1Class: x=',TDer1Class.x,', y=',TDer1Class.y);
+  writeln('TDer2Class: x=',TDer2Class.x,', z=',TDer2Class.z);
+  if not exception_generated then
+    begin
+      writeln('No exception generated on wrong typecast of class reference variable');
+      halt(1);
+    end;
+end.
+

+ 4 - 0
utils/fpdoc/fpmake.pp

@@ -26,6 +26,10 @@ begin
     P.Description := 'Free Pascal documentation generation utility.';
     P.NeedLibC:= false;
 
+    P.OSes:=AllOSes-[embedded,msdos,win16,go32v2,nativent,macos,palmos,atari];
+    if Defaults.CPU=jvm then
+      P.OSes := P.OSes - [java,android];
+
     P.Dependencies.Add('fcl-base');
     P.Dependencies.Add('fcl-xml');
     P.Dependencies.Add('fcl-passrc');

+ 4 - 0
utils/fppkg/fpmake.pp

@@ -30,6 +30,10 @@ begin
     P.Directory:=ADirectory;
     P.Version:='3.3.1';
 
+    P.OSes:=AllOSes-[embedded,msdos,win16,go32v2,nativent,macos,palmos,atari];
+    if Defaults.CPU=jvm then
+      P.OSes := P.OSes - [java,android];
+
     P.SourcePath.Add('lnet',lnetOSes);
     P.IncludePath.Add('lnet/sys',lnetOSes);
 

+ 4 - 0
utils/pas2jni/fpmake.pp

@@ -24,6 +24,10 @@ begin
     P.Email := '';
     P.NeedLibC:= false;
 
+    P.OSes:=AllOSes-[embedded,msdos,win16,go32v2,nativent,macos,palmos,atari];
+    if Defaults.CPU=jvm then
+      P.OSes := P.OSes - [java,android];
+
     P.Directory:=ADirectory;
     P.Version:='3.3.1';
     P.Dependencies.Add('fcl-base');

+ 6 - 0
utils/pas2js/docs/translation.html

@@ -164,6 +164,10 @@ Put + after a boolean switch option to enable it, - to disable it
    -Jo&lt;x&gt; : Enable or disable extra option. The x is case insensitive:
      -JoSearchLikeFPC : search source files like FPC, default: search case insensitive.
      -JoUseStrict : add "use strict" to modules, default.
+   -Jpcmd&lt;command&gt; : Run postprocessor. For each generated js execute
+                  command passing the js as stdin and read the new js from stdout.
+                  This option can be added multiple times to call several
+                  postprocessors in succession.
    -Ju&lt;x&gt; : Add &lt;x&gt; to foreign unit paths. Foreign units are not compiled.
   -l      : Write logo
   -MDelphi: Delphi 7 compatibility mode
@@ -2919,6 +2923,8 @@ End.
     Width and precision is supported. str(i:10) will add spaces to the left to fill up to 10 characters.</b>
     str(aDouble:1:5) returns a string in decimal format with 5 digits for the fraction.</li>
     <li>Intrinsic procedure WriteStr(out s: string; params...)</li>
+    <li><i>Debugger;</i> converts to <i>debugger;</i>. If a debugger is running
+      it will break on this line just like a break point.</li>
     </ul>
     </div>
 

+ 1 - 0
utils/pas2js/pas2jslib.lpi

@@ -39,6 +39,7 @@
     </Target>
     <SearchPaths>
       <IncludeFiles Value="$(ProjOutDir)"/>
+      <OtherUnitFiles Value="../../packages/fcl-js/src;../../packages/fcl-json/src;../../packages/fcl-passrc/src;../../packages/pastojs/src"/>
       <UnitOutputDirectory Value="lib/$(TargetCPU)-$(TargetOS)"/>
     </SearchPaths>
     <CodeGeneration>