瀏覽代碼

* reintegrated "blocks" branch. Adds support for calling C-style blocks with
global procedures and Object Pascal methods on Darwin platforms. Support
for nested procedures will be added later on. For the syntax, see
tests/test/tblock*.pp

git-svn-id: trunk@29517 -

Jonas Maebe 10 年之前
父節點
當前提交
2f40fa7b33

+ 7 - 0
.gitattributes

@@ -138,6 +138,7 @@ compiler/avr/ravrstd.inc svneol=native#text/plain
 compiler/avr/ravrsup.inc svneol=native#text/plain
 compiler/avr/ravrsup.inc svneol=native#text/plain
 compiler/avr/rgcpu.pas svneol=native#text/plain
 compiler/avr/rgcpu.pas svneol=native#text/plain
 compiler/avr/symcpu.pas svneol=native#text/plain
 compiler/avr/symcpu.pas svneol=native#text/plain
+compiler/blockutl.pas svneol=native#text/plain
 compiler/browcol.pas svneol=native#text/plain
 compiler/browcol.pas svneol=native#text/plain
 compiler/bsdcompile -text
 compiler/bsdcompile -text
 compiler/catch.pas svneol=native#text/plain
 compiler/catch.pas svneol=native#text/plain
@@ -8330,6 +8331,7 @@ rtl/i8086/strings.inc svneol=native#text/plain
 rtl/i8086/stringss.inc svneol=native#text/plain
 rtl/i8086/stringss.inc svneol=native#text/plain
 rtl/inc/aliases.inc svneol=native#text/plain
 rtl/inc/aliases.inc svneol=native#text/plain
 rtl/inc/astrings.inc svneol=native#text/plain
 rtl/inc/astrings.inc svneol=native#text/plain
+rtl/inc/blockrtl.pp svneol=native#text/plain
 rtl/inc/cgeneric.inc svneol=native#text/plain
 rtl/inc/cgeneric.inc svneol=native#text/plain
 rtl/inc/cgenmath.inc svneol=native#text/plain
 rtl/inc/cgenmath.inc svneol=native#text/plain
 rtl/inc/cgenstr.inc svneol=native#text/plain
 rtl/inc/cgenstr.inc svneol=native#text/plain
@@ -11236,6 +11238,11 @@ tests/test/tasm8.pp svneol=native#text/plain
 tests/test/tasmread.pp svneol=native#text/plain
 tests/test/tasmread.pp svneol=native#text/plain
 tests/test/tasout.pp svneol=native#text/plain
 tests/test/tasout.pp svneol=native#text/plain
 tests/test/tassignmentoperator1.pp svneol=native#text/pascal
 tests/test/tassignmentoperator1.pp svneol=native#text/pascal
+tests/test/tblock1.pp svneol=native#text/plain
+tests/test/tblock1a.pp svneol=native#text/plain
+tests/test/tblock1c.pp svneol=native#text/plain
+tests/test/tblock2.pp svneol=native#text/plain
+tests/test/tblock2a.pp svneol=native#text/plain
 tests/test/tbopr.pp svneol=native#text/plain
 tests/test/tbopr.pp svneol=native#text/plain
 tests/test/tbrtlevt.pp svneol=native#text/plain
 tests/test/tbrtlevt.pp svneol=native#text/plain
 tests/test/tbsx1.pp svneol=native#text/plain
 tests/test/tbsx1.pp svneol=native#text/plain

+ 385 - 0
compiler/blockutl.pas

@@ -0,0 +1,385 @@
+{
+    Copyright (c) 2014 by Jonas Maebe, Member of the Free Pascal
+    development team.
+
+    This unit implements helper routines for "blocks" support
+    (http://en.wikipedia.org/wiki/Blocks_(C_language_extension) )
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit blockutl;
+
+{$i fpcdefs.inc}
+
+interface
+
+  uses
+    node,nld,ncnv,
+    symtype,symdef;
+
+  { accepts a loadnode for a procdef
+
+    returns a node representing the converted code to implement this
+    conversion (this node is valid both for typed constant declarations and
+    in function bodies). The node is not reused }
+  function generate_block_for_procaddr(procloadnode: tloadnode): tnode;
+
+  { for a procdef, return a recorddef representing a block literal for this
+    procdef
+
+    for a procvardef, return a basic recorddef representing a block literal
+    with enough info to call this procvardef }
+  function get_block_literal_type_for_proc(pd: tabstractprocdef): trecorddef;
+
+implementation
+
+  uses
+    verbose,globtype,globals,cutils,constexp,
+    pass_1,pparautl,fmodule,
+    aasmdata,
+    nbas,ncon,nmem,nutils,
+    symbase,symconst,symtable,symsym,symcreat,objcutil,objcdef,defutil,
+    paramgr;
+
+
+  function get_block_literal_type_for_proc(pd: tabstractprocdef): trecorddef;
+    begin
+      if pd.typ=procvardef then
+        result:=trecorddef(search_named_unit_globaltype('BLOCKRTL','FPC_BLOCK_LITERAL_BASE',true).typedef)
+      else if pd.is_addressonly then
+        result:=trecorddef(search_named_unit_globaltype('BLOCKRTL','FPC_BLOCK_LITERAL_STATIC',true).typedef)
+      { todo: nested functions and Objective-C methods }
+      else if not is_nested_pd(pd) and
+              not is_objcclass(tdef(pd.owner.defowner)) then
+        result:=trecorddef(search_named_unit_globaltype('BLOCKRTL','FPC_BLOCK_LITERAL_COMPLEX_PROCVAR',true).typedef)
+      else
+        internalerror(2014071304);
+    end;
+
+
+  function get_block_literal_isa(orgpd: tprocdef): tstaticvarsym;
+    var
+      srsym: tsym;
+      srsymtable: tsymtable;
+      name: tidstring;
+    begin
+      if orgpd.is_addressonly then
+        name:='_NSCONCRETEGLOBALBLOCK'
+      else
+        name:='_NSCONCRETESTACKBLOCK';
+      if not searchsym_in_named_module('BLOCKRTL',name,srsym,srsymtable) or
+         (srsym.typ<>staticvarsym) then
+        internalerror(2014071501);
+      result:=tstaticvarsym(srsym);
+    end;
+
+
+  function get_block_literal_flags(orgpd, invokepd: tprocdef): longint;
+    { BlockLiteralFlags }
+    const
+      BLOCK_HAS_COPY_DISPOSE    = 1 shl 25;
+      BLOCK_HAS_CXX_OBJ         = 1 shl 26;
+      BLOCK_IS_GLOBAL           = 1 shl 28;
+      BLOCK_USE_STRET           = 1 shl 29;
+      BLOCK_HAS_SIGNATURE       = 1 shl 30;
+      BLOCK_HAS_EXTENDED_LAYOUT = 1 shl 31;
+    begin
+      result:=0;
+      { BLOCK_HAS_COPY_DISPOSE :
+          copy/dispose will be necessary once we support nested procedures, in
+          case they capture reference counted types, Objective-C class instances
+          or block-type variables
+      }
+
+      { BLOCK_HAS_CXX_OBJ:
+          we don't support C++ (stack-based) class instances yet
+      }
+
+      { BLOCK_IS_GLOBAL:
+          set in case the block does not capture any local state; used for
+          global functions and in theory also possible for nested functions that
+          do not access any variables from their parentfp context
+      }
+      if orgpd.is_addressonly then
+        result:=result or BLOCK_IS_GLOBAL;
+
+      { BLOCK_USE_STRET:
+          set in case the invoke function returns its result via a hidden
+          parameter
+      }
+      if paramanager.ret_in_param(invokepd.returndef,orgpd) then
+        result:=result or BLOCK_USE_STRET;
+      { BLOCK_HAS_SIGNATURE:
+          only if this bit is set, the above bit will actually be taken into
+          account (for backward compatibility). We need it so that our invoke
+          function isn't called as a variadic function, but on the downside this
+          requires Mac OS X 10.7 or later
+      }
+      result:=result or BLOCK_HAS_SIGNATURE;
+      { BLOCK_HAS_EXTENDED_LAYOUT:
+          no documentation about what this means or what it's good for (clang
+          adds it for Objective-C 1 platforms in case garbage collection is
+          switched off, but then you also have to actually generate this layout)
+      }
+    end;
+
+
+  function get_block_literal_descriptor(invokepd: tprocdef; block_literal_size: tcgint): tstaticvarsym;
+    var
+      descriptordef: tdef;
+      descriptor: tstaticvarsym;
+      name: tsymstr;
+      srsym: tsym;
+      srsymtable: tsymtable;
+    begin
+      (*
+        FPC_Block_descriptor_simple = record
+          reserved: culong;
+          Block_size: culong;
+          { signatures are only for the "ABI.2010.3.16" version, but that's all
+            we support because otherwise the callback has to be a C-style
+            variadic function, which we cannot (yet?) generate }
+          signature: pchar;
+        end;
+      *)
+
+      { must be a valid Pascal identifier, because we will reference it when
+        constructing the block initialiser }
+      { we don't have to include the moduleid in this mangledname, because
+        the invokepd is a local procedure in the current unit -> defid by
+        itself is unique }
+      name:='__FPC_BLOCK_DESCRIPTOR_SIMPLE_'+tostr(invokepd.defid);
+      { already exists -> return }
+      if searchsym(name,srsym,srsymtable) then
+        begin
+          if srsym.typ<>staticvarsym then
+            internalerror(2014071402);
+          result:=tstaticvarsym(srsym);
+          exit;
+        end;
+      { find the type of the descriptor structure }
+      descriptordef:=search_named_unit_globaltype('BLOCKRTL','FPC_BLOCK_DESCRIPTOR_SIMPLE',true).typedef;
+      { create new static variable }
+      descriptor:=cstaticvarsym.create(name,vs_value,descriptordef,[]);
+      symtablestack.top.insert(descriptor);
+      include(descriptor.symoptions,sp_internal);
+      { create typed constant for the descriptor }
+      str_parse_typedconst(current_asmdata.AsmLists[al_const],
+        '(reserved: 0; Block_size: '+tostr(block_literal_size)+
+        '; signature: '''+objcencodemethod(invokepd)+''');',descriptor);
+      result:=descriptor;
+    end;
+
+
+  { creates a wrapper function for pd with the C calling convention and an
+    extra first parameter pointing to the block "self" pointer. This wrapper is
+    what will be assigned to the "invoke" field of the block }
+  function get_invoke_wrapper(orgpd: tprocdef; orgpv: tprocvardef): tprocdef;
+    var
+      wrappername: TIDString;
+      srsym: tsym;
+      srsymtable: tsymtable;
+    begin
+      { the copy() is to ensure we don't overflow the maximum identifier length;
+        the combination of owner.moduleid and defid will make the name unique }
+      wrappername:='__FPC_BLOCK_INVOKE_'+upper(copy(orgpd.procsym.realname,1,60))+'_'+tostr(orgpd.owner.moduleid)+'_'+tostr(orgpd.defid);
+      { already an invoke wrapper for this procsym -> reuse }
+      if searchsym(wrappername,srsym,srsymtable) then
+        begin
+          if (srsym.typ<>procsym) or
+             (tprocsym(srsym).procdeflist.count<>1) then
+            internalerror(2014071503);
+          result:=tprocdef(tprocsym(srsym).procdeflist[0]);
+          exit;
+        end;
+      { bare copy, so that self etc are not inserted }
+      result:=tprocdef(orgpd.getcopyas(procdef,pc_bareproc));
+      { will be called accoding to the ABI conventions }
+      result.proccalloption:=pocall_cdecl;
+      { add po_is_block so that a block "self" pointer gets added (of the type
+        returned by get_block_literal_type_for_proc()) }
+      include(result.procoptions,po_is_block);
+      { now insert self/vmt/funcret according to the newly set calling
+        convention }
+      insert_self_and_vmt_para(result);
+      insert_funcret_para(result);
+      finish_copied_procdef(result,wrappername,current_module.localsymtable,nil);
+      if orgpd.is_addressonly then
+        begin
+          result.synthetickind:=tsk_callthrough;
+          result.skpara:=orgpd;
+        end
+      else
+        begin
+          { alias for the type to invoke the procvar, used in the symcreat
+            handling of tsk_block_invoke_procvar }
+          result.localst.insert(ctypesym.create('__FPC_BLOCK_INVOKE_PV_TYPE',orgpv));
+          result.synthetickind:=tsk_block_invoke_procvar;
+        end;
+    end;
+
+
+  { compose a block literal for a static block (one without context) }
+  function get_global_proc_literal_sym(blockliteraldef: tdef; blockisasym: tstaticvarsym; blockflags: longint; invokepd: tprocdef; descriptor: tstaticvarsym): tstaticvarsym;
+    var
+      literalname: TIDString;
+      srsym: tsym;
+      srsymtable: tsymtable;
+    begin
+      literalname:='block_literal_for_'+invokepd.procsym.realname;
+      { already exists -> return }
+      if searchsym(literalname,srsym,srsymtable) then
+        begin
+          if srsym.typ<>staticvarsym then
+            internalerror(2014071506);
+          result:=tstaticvarsym(srsym);
+          exit;
+        end;
+      { create new block literal symbol }
+      result:=cstaticvarsym.create(
+        '$'+literalname,
+        vs_value,
+        blockliteraldef,[]);
+      include(result.symoptions,sp_internal);
+      symtablestack.top.insert(result);
+      { initialise it }
+      str_parse_typedconst(current_asmdata.AsmLists[al_const],
+        '(base: (isa        : @'+blockisasym.realname+
+              '; flags     : '+tostr(blockflags)+
+              '; reserved  : 0'+
+              '; invoke    : @'+invokepd.procsym.realname+
+              '; descriptor: @'+descriptor.realname+
+              '));',
+        result);
+    end;
+
+
+  { compose an on-stack block literal for a "procedure of object" }
+  function get_pascal_method_literal(blockliteraldef: tdef; blockisasym: tstaticvarsym; blockflags: longint; procvarnode: tnode; invokepd: tprocdef; orgpv: tprocvardef; descriptor: tstaticvarsym): tnode;
+    var
+      statement: tstatementnode;
+      literaltemp: ttempcreatenode;
+    begin
+      result:=internalstatements(statement);
+      { create new block literal structure }
+      literaltemp:=ctempcreatenode.create(blockliteraldef,blockliteraldef.size,tt_persistent,false);
+      addstatement(statement,literaltemp);
+      { temp.base.isa:=@blockisasym }
+      addstatement(statement,cassignmentnode.create(
+        genloadfield(genloadfield(ctemprefnode.create(literaltemp),'BASE'),'ISA'),
+        caddrnode.create(cloadnode.create(blockisasym,blockisasym.owner))));
+      { temp.base.flags:=blockflags }
+      addstatement(statement,cassignmentnode.create(
+        genloadfield(genloadfield(ctemprefnode.create(literaltemp),'BASE'),'FLAGS'),
+        genintconstnode(blockflags)));
+      { temp.base.reserved:=0 }
+      addstatement(statement,cassignmentnode.create(
+        genloadfield(genloadfield(ctemprefnode.create(literaltemp),'BASE'),'RESERVED'),
+        genintconstnode(0)));
+      { temp.base.invoke:=tmethod(@invokepd) }
+      addstatement(statement,cassignmentnode.create(
+        genloadfield(genloadfield(ctemprefnode.create(literaltemp),'BASE'),'INVOKE'),
+        ctypeconvnode.create_proc_to_procvar(
+          cloadnode.create_procvar(invokepd.procsym,invokepd,invokepd.owner))));
+      { temp.base.descriptor:=@descriptor }
+      addstatement(statement,cassignmentnode.create(
+        genloadfield(genloadfield(ctemprefnode.create(literaltemp),'BASE'),'DESCRIPTOR'),
+        caddrnode.create(cloadnode.create(descriptor,descriptor.owner))));
+      { temp.pv:=tmethod(@orgpd) }
+      addstatement(statement,cassignmentnode.create(
+        ctypeconvnode.create_explicit(genloadfield(ctemprefnode.create(literaltemp),'PV'),orgpv),
+          procvarnode.getcopy));
+      { and return the address of the temp }
+      addstatement(statement,caddrnode.create(ctemprefnode.create(literaltemp)));
+      { typecheck this now, because the current source may be written in TP/
+        Delphi/MacPas mode and the above node tree has been constructed for
+        ObjFPC mode, which has been set by replace_scanner (in Delphi, the
+        assignment to invoke would be without the proc_to_procvar conversion) }
+      typecheckpass(result);
+    end;
+
+
+  function generate_block_for_procaddr(procloadnode: tloadnode): tnode;
+    var
+      procvarnode: tnode;
+      { procvardef representing the original function we want to invoke }
+      orgpv: tprocvardef;
+      { procdef of the original function we want to invoke }
+      orgpd,
+      { procdef for the invoke-wrapper that we generated to call the original
+        function via a procvar }
+      invokepd: tprocdef;
+      blockliteraldef: tdef;
+      descriptor,
+      blockisasym,
+      blockliteralsym: tstaticvarsym;
+      blockflags: longint;
+      old_symtablestack: tsymtablestack;
+      sstate: tscannerstate;
+    begin
+      result:=nil;
+      { supported? (should be caught earlier) }
+      if (procloadnode.resultdef.typ<>procdef) or
+         is_nested_pd(tprocdef(procloadnode.resultdef)) or
+         is_objcclass(tdef(procloadnode.resultdef.owner.defowner)) then
+        internalerror(2014071401);
+
+      { add every symbol that we create here to the unit-level symbol table }
+      old_symtablestack:=symtablestack;
+      symtablestack:=old_symtablestack.getcopyuntil(current_module.localsymtable);
+      { save scanner state }
+      replace_scanner('block literal creation',sstate);
+
+      { def representing the original function }
+      orgpd:=tprocdef(procloadnode.resultdef);
+      { def representing the corresponding procvar type }
+      procvarnode:=ctypeconvnode.create_proc_to_procvar(procloadnode.getcopy);
+      typecheckpass(procvarnode);
+      orgpv:=tprocvardef(procvarnode.resultdef);
+      { get blockdef for this kind of procdef }
+      blockliteraldef:=get_block_literal_type_for_proc(orgpd);
+      { get the invoke wrapper }
+      invokepd:=get_invoke_wrapper(orgpd,orgpv);
+      { get the descriptor }
+      descriptor:=get_block_literal_descriptor(invokepd,blockliteraldef.size);
+      { get the ISA pointer for the literal }
+      blockisasym:=get_block_literal_isa(orgpd);
+      { get the flags for the block }
+      blockflags:=get_block_literal_flags(orgpd,invokepd);
+      { global/simple procedure -> block literal is a typed constant }
+      if orgpd.is_addressonly then
+        begin
+          blockliteralsym:=get_global_proc_literal_sym(blockliteraldef,blockisasym,blockflags,invokepd,descriptor);
+          { result: address of the block literal }
+          result:=caddrnode.create(cloadnode.create(blockliteralsym,blockliteralsym.owner));
+        end
+      else
+        begin
+          result:=get_pascal_method_literal(blockliteraldef,blockisasym,blockflags,procvarnode,invokepd,orgpv,descriptor)
+        end;
+
+      procvarnode.free;
+
+      { restore scanner }
+      restore_scanner(sstate);
+      { restore symtable stack }
+      symtablestack.free;
+      symtablestack:=old_symtablestack;
+    end;
+
+end.
+

+ 27 - 9
compiler/defcmp.pas

@@ -1533,6 +1533,10 @@ implementation
                    begin
                    begin
                      { procvar -> procvar }
                      { procvar -> procvar }
                      eq:=proc_to_procvar_equal(tprocvardef(def_from),tprocvardef(def_to),cdo_warn_incompatible_univ in cdoptions);
                      eq:=proc_to_procvar_equal(tprocvardef(def_from),tprocvardef(def_to),cdo_warn_incompatible_univ in cdoptions);
+                     if eq<te_equal then
+                       doconv:=tc_proc_2_procvar
+                     else
+                       doconv:=tc_equal;
                    end;
                    end;
                  pointerdef :
                  pointerdef :
                    begin
                    begin
@@ -2176,30 +2180,38 @@ implementation
          if not(assigned(def1)) or not(assigned(def2)) then
          if not(assigned(def1)) or not(assigned(def2)) then
            exit;
            exit;
          { check for method pointer and local procedure pointer:
          { check for method pointer and local procedure pointer:
-             a) if one is a procedure of object, the other also has to be one
-             b) if one is a pure address, the other also has to be one
+             a) anything but procvars can be assigned to blocks
+             b) if one is a procedure of object, the other also has to be one
+                (except for block)
+             c) if one is a pure address, the other also has to be one
                 except if def1 is a global proc and def2 is a nested procdef
                 except if def1 is a global proc and def2 is a nested procdef
                 (global procedures can be converted into nested procvars)
                 (global procedures can be converted into nested procvars)
-             c) if def1 is a nested procedure, then def2 has to be a nested
+             d) if def1 is a nested procedure, then def2 has to be a nested
                 procvar and def1 has to have the po_delphi_nested_cc option
                 procvar and def1 has to have the po_delphi_nested_cc option
-             d) if def1 is a procvar, def1 and def2 both have to be nested or
+             e) if def1 is a procvar, def1 and def2 both have to be nested or
                 non-nested (we don't allow assignments from non-nested to
                 non-nested (we don't allow assignments from non-nested to
                 nested procvars to make sure that we can still implement
                 nested procvars to make sure that we can still implement
                 nested procvars using trampolines -- e.g., this would be
                 nested procvars using trampolines -- e.g., this would be
                 necessary for LLVM or CIL as long as they do not have support
                 necessary for LLVM or CIL as long as they do not have support
                 for Delphi-style frame pointer parameter passing) }
                 for Delphi-style frame pointer parameter passing) }
-         if (def1.is_methodpointer<>def2.is_methodpointer) or  { a) }
-            ((def1.is_addressonly<>def2.is_addressonly) and    { b) }
+         if is_block(def2) then                                     { a) }
+           { can't explicitly check against procvars here, because
+             def1 may already be a procvar due to a proc_to_procvar;
+             this is checked in the type conversion node itself -> ok }
+         else if (def1.is_methodpointer<>def2.is_methodpointer) or  { b) }
+            ((def1.is_addressonly<>def2.is_addressonly) and         { c) }
              (is_nested_pd(def1) or
              (is_nested_pd(def1) or
               not is_nested_pd(def2))) or
               not is_nested_pd(def2))) or
-            ((def1.typ=procdef) and                            { c) }
+            ((def1.typ=procdef) and                                 { d) }
              is_nested_pd(def1) and
              is_nested_pd(def1) and
              (not(po_delphi_nested_cc in def1.procoptions) or
              (not(po_delphi_nested_cc in def1.procoptions) or
               not is_nested_pd(def2))) or
               not is_nested_pd(def2))) or
-            ((def1.typ=procvardef) and                         { d) }
+            ((def1.typ=procvardef) and                              { e) }
              (is_nested_pd(def1)<>is_nested_pd(def2))) then
              (is_nested_pd(def1)<>is_nested_pd(def2))) then
            exit;
            exit;
          pa_comp:=[cpo_ignoreframepointer];
          pa_comp:=[cpo_ignoreframepointer];
+         if is_block(def2) then
+           include(pa_comp,cpo_ignorehidden);
          if checkincompatibleuniv then
          if checkincompatibleuniv then
            include(pa_comp,cpo_warn_incompatible_univ);
            include(pa_comp,cpo_warn_incompatible_univ);
          { check return value and options, methodpointer is already checked }
          { check return value and options, methodpointer is already checked }
@@ -2209,7 +2221,10 @@ implementation
            include(po_comp,po_staticmethod);
            include(po_comp,po_staticmethod);
          if (m_delphi in current_settings.modeswitches) then
          if (m_delphi in current_settings.modeswitches) then
            exclude(po_comp,po_varargs);
            exclude(po_comp,po_varargs);
-         if (def1.proccalloption=def2.proccalloption) and
+         { for blocks, the calling convention doesn't matter because we have to
+           generate a wrapper anyway }
+         if ((po_is_block in def2.procoptions) or
+             (def1.proccalloption=def2.proccalloption)) and
             ((po_comp * def1.procoptions)= (po_comp * def2.procoptions)) and
             ((po_comp * def1.procoptions)= (po_comp * def2.procoptions)) and
             equal_defs(def1.returndef,def2.returndef) then
             equal_defs(def1.returndef,def2.returndef) then
           begin
           begin
@@ -2224,6 +2239,9 @@ implementation
                 { prefer non-nested to non-nested over non-nested to nested }
                 { prefer non-nested to non-nested over non-nested to nested }
                 if (is_nested_pd(def1)<>is_nested_pd(def2)) then
                 if (is_nested_pd(def1)<>is_nested_pd(def2)) then
                   eq:=te_convert_l1;
                   eq:=te_convert_l1;
+                { in case of non-block to block, we need a type conversion }
+                if (po_is_block in def1.procoptions) <> (po_is_block in def2.procoptions) then
+                  eq:=te_convert_l1;
               end;
               end;
             proc_to_procvar_equal:=eq;
             proc_to_procvar_equal:=eq;
           end;
           end;

+ 9 - 0
compiler/defutil.pas

@@ -331,6 +331,9 @@ interface
     { returns true of def is a methodpointer }
     { returns true of def is a methodpointer }
     function is_methodpointer(def : tdef) : boolean;
     function is_methodpointer(def : tdef) : boolean;
 
 
+    { returns true if def is a C "block" }
+    function is_block(def: tdef): boolean;
+
 implementation
 implementation
 
 
     uses
     uses
@@ -1425,4 +1428,10 @@ implementation
         result:=(def.typ=procvardef) and (po_methodpointer in tprocvardef(def).procoptions);
         result:=(def.typ=procvardef) and (po_methodpointer in tprocvardef(def).procoptions);
       end;
       end;
 
 
+
+    function is_block(def: tdef): boolean;
+      begin
+        result:=(def.typ=procvardef) and (po_is_block in tprocvardef(def).procoptions)
+      end;
+
 end.
 end.

+ 4 - 2
compiler/globtype.pas

@@ -400,8 +400,9 @@ interface
                                   fields in Java) }
                                   fields in Java) }
          m_default_unicodestring, { makes the default string type in $h+ mode unicodestring rather than
          m_default_unicodestring, { makes the default string type in $h+ mode unicodestring rather than
                                     ansistring; similarly, char becomes unicodechar rather than ansichar }
                                     ansistring; similarly, char becomes unicodechar rather than ansichar }
-         m_type_helpers         { allows the declaration of "type helper" (non-Delphi) or "record helper"
+         m_type_helpers,        { allows the declaration of "type helper" (non-Delphi) or "record helper"
                                   (Delphi) for primitive types }
                                   (Delphi) for primitive types }
+         m_blocks               { support for http://en.wikipedia.org/wiki/Blocks_(C_language_extension) }
        );
        );
        tmodeswitches = set of tmodeswitch;
        tmodeswitches = set of tmodeswitch;
 
 
@@ -566,7 +567,8 @@ interface
          'SYSTEMCODEPAGE',
          'SYSTEMCODEPAGE',
          'FINALFIELDS',
          'FINALFIELDS',
          'UNICODESTRINGS',
          'UNICODESTRINGS',
-         'TYPEHELPERS');
+         'TYPEHELPERS',
+         'BLOCKS');
 
 
 
 
      type
      type

+ 11 - 4
compiler/msg/errore.msg

@@ -1538,7 +1538,7 @@ parser_e_global_generic_references_static=03339_E_Global Generic template refere
 %
 %
 # Type Checking
 # Type Checking
 #
 #
-# 04122 is the last used one
+# 04123 is the last used one
 #
 #
 % \section{Type checking errors}
 % \section{Type checking errors}
 % This section lists all errors that can occur when type checking is
 % This section lists all errors that can occur when type checking is
@@ -1846,13 +1846,13 @@ type_w_zero_to_nil=04090_W_Converting 0 to NIL
 % Use NIL rather than 0 when initialising a pointer.
 % Use NIL rather than 0 when initialising a pointer.
 type_e_protocol_type_expected=04091_E_Objective-C protocol type expected, but got "$1"
 type_e_protocol_type_expected=04091_E_Objective-C protocol type expected, but got "$1"
 % The compiler expected a protocol type name, but found something else.
 % The compiler expected a protocol type name, but found something else.
-type_e_objc_type_unsupported=04092_E_The type "$1" is not supported for interaction with the Objective-C runtime.
-% Objective-C makes extensive use of run time type information (RTTI). This format
+type_e_objc_type_unsupported=04092_E_The type "$1" is not supported for interaction with the Objective-C and the blocks runtime.
+% Objective-C and Blocks make extensive use of run time type information (RTTI). This format
 % is defined by the maintainers of the run time and can therefore not be adapted
 % is defined by the maintainers of the run time and can therefore not be adapted
 % to all possible Object Pascal types. In particular, types that depend on
 % to all possible Object Pascal types. In particular, types that depend on
 % reference counting by the compiler (such as ansistrings and certain kinds of
 % reference counting by the compiler (such as ansistrings and certain kinds of
 % interfaces) cannot be used as fields of Objective-C classes, cannot be
 % interfaces) cannot be used as fields of Objective-C classes, cannot be
-% directly passed to Objective-C methods, and cannot be encoded using \var{objc\_encode}.
+% directly passed to Objective-C methods or Blocks, and cannot be encoded using \var{objc\_encode}.
 type_e_class_or_objcclass_type_expected=04093_E_Class or objcclass type expected, but got "$1"
 type_e_class_or_objcclass_type_expected=04093_E_Class or objcclass type expected, but got "$1"
 % It is only possible to create class reference types of \var{class} and \var{objcclass}
 % It is only possible to create class reference types of \var{class} and \var{objcclass}
 type_e_objcclass_type_expected=04094_E_Objcclass type expected
 type_e_objcclass_type_expected=04094_E_Objcclass type expected
@@ -1968,6 +1968,13 @@ type_e_procedure_must_be_far=04121_E_Procedure or function must be far in order
 type_w_instance_abstract_class=04122_W_Creating an instance of abstract class "$1"
 type_w_instance_abstract_class=04122_W_Creating an instance of abstract class "$1"
 % The specified class is declared as \var{abstract} and thus no instance of this class
 % The specified class is declared as \var{abstract} and thus no instance of this class
 % should be created. This is merely a warning for Delphi compatibility.
 % should be created. This is merely a warning for Delphi compatibility.
+type_e_function_reference_kind=04123_E_Subroutine references cannot be declared as "of object" or "is nested", they can always refer to any kind of subroutine
+% Subroutine references can refer to any kind of subroutine and hence do not
+% require specialisation for methods or nested subroutines.
+type_e_anonymous_function_unsupported=04999_E_Function references are not yet supported, only blocks (add "cdecl;" at the end)
+% Remove this error message once Delphi-style anonymous are implemented. It has
+% number 4999 so as not to result in a gap in the error message numbering once
+% it's removed.
 % \end{description}
 % \end{description}
 #
 #
 # Symtable
 # Symtable

+ 4 - 2
compiler/msgidx.inc

@@ -554,6 +554,8 @@ const
   type_e_type_not_allowed_for_type_helper=04120;
   type_e_type_not_allowed_for_type_helper=04120;
   type_e_procedure_must_be_far=04121;
   type_e_procedure_must_be_far=04121;
   type_w_instance_abstract_class=04122;
   type_w_instance_abstract_class=04122;
+  type_e_function_reference_kind=04123;
+  type_e_anonymous_function_unsupported=04999;
   sym_e_id_not_found=05000;
   sym_e_id_not_found=05000;
   sym_f_internal_error_in_symtablestack=05001;
   sym_f_internal_error_in_symtablestack=05001;
   sym_e_duplicate_id=05002;
   sym_e_duplicate_id=05002;
@@ -1004,9 +1006,9 @@ const
   option_info=11024;
   option_info=11024;
   option_help_pages=11025;
   option_help_pages=11025;
 
 
-  MsgTxtSize = 74721;
+  MsgTxtSize = 74953;
 
 
   MsgIdxMax : array[1..20] of longint=(
   MsgIdxMax : array[1..20] of longint=(
-    26,99,340,123,96,57,126,29,202,64,
+    26,99,340,1000,96,57,126,29,202,64,
     58,20,1,1,1,1,1,1,1,1
     58,20,1,1,1,1,1,1,1,1
   );
   );

文件差異過大導致無法顯示
+ 203 - 199
compiler/msgtxt.inc


+ 11 - 1
compiler/ncal.pas

@@ -69,6 +69,7 @@ interface
           function  gen_procvar_context_tree_parentfp:tnode;
           function  gen_procvar_context_tree_parentfp:tnode;
           function  gen_self_tree:tnode;
           function  gen_self_tree:tnode;
           function  gen_vmt_tree:tnode;
           function  gen_vmt_tree:tnode;
+          function gen_block_context:tnode;
           procedure gen_hidden_parameters;
           procedure gen_hidden_parameters;
           function  funcret_can_be_reused:boolean;
           function  funcret_can_be_reused:boolean;
           procedure maybe_create_funcret_node;
           procedure maybe_create_funcret_node;
@@ -2343,6 +2344,13 @@ implementation
       end;
       end;
 
 
 
 
+    function tcallnode.gen_block_context: tnode;
+      begin
+        { the self parameter of a block invocation is that address of the
+          block literal (which is what right contains) }
+        result:=right.getcopy;
+      end;
+
 
 
     function check_funcret_used_as_para(var n: tnode; arg: pointer): foreachnoderesult;
     function check_funcret_used_as_para(var n: tnode; arg: pointer): foreachnoderesult;
       var
       var
@@ -2573,8 +2581,10 @@ implementation
                          else
                          else
                            internalerror(200309287);
                            internalerror(200309287);
                        end
                        end
+                     else if not(po_is_block in procdefinition.procoptions) then
+                       para.left:=gen_procvar_context_tree_parentfp
                      else
                      else
-                       para.left:=gen_procvar_context_tree_parentfp;
+                       para.left:=gen_block_context
                    end
                    end
                 else
                 else
                  if vo_is_range_check in para.parasym.varoptions then
                  if vo_is_range_check in para.parasym.varoptions then

+ 29 - 5
compiler/ncgcal.pas

@@ -28,7 +28,7 @@ interface
     uses
     uses
       cpubase,
       cpubase,
       globtype,
       globtype,
-      parabase,cgutils,
+      parabase,cgbase,cgutils,
       symdef,node,ncal;
       symdef,node,ncal;
 
 
     type
     type
@@ -95,6 +95,8 @@ interface
           function can_call_ref(var ref: treference):boolean;virtual;
           function can_call_ref(var ref: treference):boolean;virtual;
           procedure extra_call_ref_code(var ref: treference);virtual;
           procedure extra_call_ref_code(var ref: treference);virtual;
           procedure do_call_ref(ref: treference);virtual;
           procedure do_call_ref(ref: treference);virtual;
+
+          procedure load_block_invoke(toreg: tregister);virtual;
        public
        public
           procedure pass_generate_code;override;
           procedure pass_generate_code;override;
           destructor destroy;override;
           destructor destroy;override;
@@ -107,11 +109,11 @@ implementation
       systems,
       systems,
       cutils,verbose,globals,
       cutils,verbose,globals,
       cpuinfo,
       cpuinfo,
-      symconst,symtable,symtype,defutil,paramgr,
-      cgbase,pass_2,
+      symconst,symbase,symtable,symtype,symsym,defutil,paramgr,
+      pass_2,
       aasmbase,aasmtai,aasmdata,
       aasmbase,aasmtai,aasmdata,
       nbas,nmem,nld,ncnv,nutils,
       nbas,nmem,nld,ncnv,nutils,
-      ncgutil,
+      ncgutil,blockutl,
       cgobj,tgobj,hlcgobj,
       cgobj,tgobj,hlcgobj,
       procinfo,
       procinfo,
       wpobase;
       wpobase;
@@ -449,6 +451,26 @@ implementation
       end;
       end;
 
 
 
 
+    procedure tcgcallnode.load_block_invoke(toreg: tregister);
+      var
+        href: treference;
+        srsym: tsym;
+        srsymtable: tsymtable;
+        literaldef: trecorddef;
+      begin
+        literaldef:=get_block_literal_type_for_proc(tabstractprocdef(right.resultdef));
+        hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,getpointerdef(literaldef),true);
+        { load the invoke pointer }
+        hlcg.reference_reset_base(href,right.resultdef,right.location.register,0,right.resultdef.alignment);
+        if not searchsym_in_record(literaldef,'INVOKE',srsym,srsymtable) or
+           (srsym.typ<>fieldvarsym) or
+           (tfieldvarsym(srsym).vardef<>voidpointertype) then
+          internalerror(2014071506);
+        href.offset:=tfieldvarsym(srsym).fieldoffset;
+        hlcg.a_load_ref_reg(current_asmdata.CurrAsmList,tfieldvarsym(srsym).vardef,procdefinition,href,toreg);
+      end;
+
+
     procedure tcgcallnode.set_result_location(realresdef: tstoreddef);
     procedure tcgcallnode.set_result_location(realresdef: tstoreddef);
       begin
       begin
         if realresdef.is_intregable or
         if realresdef.is_intregable or
@@ -1007,7 +1029,9 @@ implementation
               pvreg:=cg.getintregister(current_asmdata.CurrAsmList,proc_addr_size);
               pvreg:=cg.getintregister(current_asmdata.CurrAsmList,proc_addr_size);
               { Only load OS_ADDR from the reference (when converting to hlcg:
               { Only load OS_ADDR from the reference (when converting to hlcg:
                 watch out with procedure of object) }
                 watch out with procedure of object) }
-              if right.location.loc in [LOC_REFERENCE,LOC_CREFERENCE] then
+              if po_is_block in procdefinition.procoptions then
+                load_block_invoke(pvreg)
+              else if right.location.loc in [LOC_REFERENCE,LOC_CREFERENCE] then
                 begin
                 begin
                   href:=right.location.reference;
                   href:=right.location.reference;
                   callref:=can_call_ref(href);
                   callref:=can_call_ref(href);

+ 35 - 3
compiler/ncnv.pas

@@ -296,7 +296,7 @@ implementation
       symconst,symdef,symsym,symcpu,symtable,
       symconst,symdef,symsym,symcpu,symtable,
       ncon,ncal,nset,nadd,nmem,nmat,nbas,nutils,ninl,
       ncon,ncal,nset,nadd,nmem,nmat,nbas,nutils,ninl,
       cgbase,procinfo,
       cgbase,procinfo,
-      htypechk,pass_1,cpuinfo;
+      htypechk,blockutl,pass_1,cpuinfo;
 
 
 
 
 {*****************************************************************************
 {*****************************************************************************
@@ -1992,6 +1992,7 @@ implementation
     function ttypeconvnode.typecheck_proc_to_procvar : tnode;
     function ttypeconvnode.typecheck_proc_to_procvar : tnode;
       var
       var
         pd : tabstractprocdef;
         pd : tabstractprocdef;
+        source: pnode;
       begin
       begin
         result:=nil;
         result:=nil;
         pd:=tabstractprocdef(left.resultdef);
         pd:=tabstractprocdef(left.resultdef);
@@ -2002,7 +2003,36 @@ implementation
           real procvartype that we are converting to) }
           real procvartype that we are converting to) }
         if assigned(totypedef) and
         if assigned(totypedef) and
            (totypedef.typ=procvardef) then
            (totypedef.typ=procvardef) then
-          resultdef:=totypedef
+          begin
+            { have to do this in typecheckpass so that it's triggered for
+              typed constant declarations }
+            if po_is_block in tprocvardef(totypedef).procoptions then
+              begin
+                { can only convert from procdef to procvardef, but in the mean
+                  time other type conversions may have been inserted (pointers,
+                  proc2procvar, ...) }
+                source:=actualtargetnode(@left);
+                while (source^.nodetype=typeconvn) and
+                      (ttypeconvnode(source^).convtype=tc_proc_2_procvar) and
+                      (is_void(source^.resultdef) or
+                       (source^.resultdef.typ=procvardef)) do
+                  begin
+                    { won't skip proc2procvar }
+                    source:=actualtargetnode(@ttypeconvnode(source^).left);
+                  end;
+                if (source^.nodetype=loadn) and
+                   (source^.resultdef.typ=procdef) and
+                   not is_nested_pd(tprocdef(source^.resultdef)) and
+                   not is_objcclass(tdef(source^.resultdef.owner.defowner)) then
+                  begin
+                    result:=generate_block_for_procaddr(tloadnode(source^));
+                    exit;
+                  end
+                else
+                  CGMessage2(type_e_illegal_type_conversion,left.resultdef.typename,resultdef.typename);
+              end;
+            resultdef:=totypedef;
+          end
         else
         else
          begin
          begin
            resultdef:=pd.getcopyas(procvardef,pc_normal);
            resultdef:=pd.getcopyas(procvardef,pc_normal);
@@ -2241,7 +2271,9 @@ implementation
                        the procvar, is compatible with the procvar's type }
                        the procvar, is compatible with the procvar's type }
                      if not(nf_explicit in flags) and
                      if not(nf_explicit in flags) and
                         (proc_to_procvar_equal(currprocdef,tprocvardef(resultdef),false)=te_incompatible) then
                         (proc_to_procvar_equal(currprocdef,tprocvardef(resultdef),false)=te_incompatible) then
-                       IncompatibleTypes(left.resultdef,resultdef);
+                       IncompatibleTypes(left.resultdef,resultdef)
+                     else
+                       result:=typecheck_call_helper(convtype);
                      exit;
                      exit;
                    end
                    end
                   else if maybe_global_proc_to_nested(left,resultdef) then
                   else if maybe_global_proc_to_nested(left,resultdef) then

+ 23 - 5
compiler/ngtcon.pas

@@ -1237,6 +1237,8 @@ function get_next_varsym(def: tabstractrecorddef; const SymList:TFPHashObjectLis
       var
       var
         tmpn,n : tnode;
         tmpn,n : tnode;
         pd   : tprocdef;
         pd   : tprocdef;
+        havepd,
+        haveblock: boolean;
       begin
       begin
         { Procvars and pointers are no longer compatible.  }
         { Procvars and pointers are no longer compatible.  }
         { under tp:  =nil or =var under fpc: =nil or =@var }
         { under tp:  =nil or =var under fpc: =nil or =@var }
@@ -1287,17 +1289,33 @@ function get_next_varsym(def: tabstractrecorddef; const SymList:TFPHashObjectLis
             n:=tmpn;
             n:=tmpn;
           end;
           end;
         { we now need to have a loadn with a procsym }
         { we now need to have a loadn with a procsym }
-        if (n.nodetype=loadn) and
-           (tloadnode(n).symtableentry.typ=procsym) then
+        havepd:=
+          (n.nodetype=loadn) and
+          (tloadnode(n).symtableentry.typ=procsym);
+        { or a staticvarsym representing a block }
+        haveblock:=
+          (n.nodetype=loadn) and
+          (tloadnode(n).symtableentry.typ=staticvarsym) and
+          (sp_internal in tloadnode(n).symtableentry.symoptions);
+        if havepd or
+           haveblock then
           begin
           begin
-            pd:=tloadnode(n).procdef;
-            list.concat(Tai_const.createname(pd.mangledname,0));
+            if havepd then
+              begin
+                pd:=tloadnode(n).procdef;
+                list.concat(Tai_const.createname(pd.mangledname,0));
+              end
+            else
+              begin
+                list.concat(Tai_const.Createname(tstaticvarsym(tloadnode(n).symtableentry).mangledname,0));
+              end;
             { nested procvar typed consts can only be initialised with nil
             { nested procvar typed consts can only be initialised with nil
               (checked above) or with a global procedure (checked here),
               (checked above) or with a global procedure (checked here),
               because in other cases we need a valid frame pointer }
               because in other cases we need a valid frame pointer }
             if is_nested_pd(def) then
             if is_nested_pd(def) then
               begin
               begin
-                if is_nested_pd(pd) then
+                if haveblock or
+                   is_nested_pd(pd) then
                   Message(parser_e_no_procvarnested_const);
                   Message(parser_e_no_procvarnested_const);
                 list.concat(Tai_const.Create_sym(nil));
                 list.concat(Tai_const.Create_sym(nil));
               end
               end

+ 4 - 1
compiler/objcdef.pas

@@ -371,7 +371,10 @@ implementation
                 end;
                 end;
             end;
             end;
           procvardef :
           procvardef :
-            encodedstr:=encodedstr+'^?';
+            if not(po_is_block in tprocvardef(def).procoptions) then
+              encodedstr:=encodedstr+'^?'
+            else
+              encodedstr:=encodedstr+'@?';
           objectdef :
           objectdef :
             case tobjectdef(def).objecttype of
             case tobjectdef(def).objecttype of
               odt_helper,
               odt_helper,

+ 7 - 3
compiler/objcutil.pas

@@ -40,7 +40,7 @@ interface
 
 
     { Encode a method's parameters and result type into the format used by the
     { Encode a method's parameters and result type into the format used by the
       run time (for generating protocol and class rtti).  }
       run time (for generating protocol and class rtti).  }
-    function objcencodemethod(pd: tprocdef): ansistring;
+    function objcencodemethod(pd: tabstractprocdef): ansistring;
 
 
     { Exports all assembler symbols related to the obj-c class }
     { Exports all assembler symbols related to the obj-c class }
     procedure exportobjcclass(def: tobjectdef);
     procedure exportobjcclass(def: tobjectdef);
@@ -196,7 +196,7 @@ end;
       end;
       end;
 
 
 
 
-    function objcencodemethod(pd: tprocdef): ansistring;
+    function objcencodemethod(pd: tabstractprocdef): ansistring;
       var
       var
         parasize,
         parasize,
         totalsize: aint;
         totalsize: aint;
@@ -230,7 +230,11 @@ end;
                (vs.varspez in [vs_var,vs_out,vs_constref]) then
                (vs.varspez in [vs_var,vs_out,vs_constref]) then
               result:=result+'^';
               result:=result+'^';
             { Add the parameter type.  }
             { Add the parameter type.  }
-            if not objcaddencodedtype(vs.vardef,ris_initial,false,result,founderror) then
+            if (vo_is_parentfp in vs.varoptions) and
+               (po_is_block in pd.procoptions) then
+              { special case: self parameter of block procvars has to be @? }
+              result:=result+'@?'
+            else if not objcaddencodedtype(vs.vardef,ris_initial,false,result,founderror) then
               { should be checked earlier on }
               { should be checked earlier on }
               internalerror(2009081701);
               internalerror(2009081701);
             { And the total size of the parameters coming before this one
             { And the total size of the parameters coming before this one

+ 22 - 0
compiler/pdecl.pas

@@ -787,6 +787,28 @@ implementation
                            consume(_SEMICOLON);
                            consume(_SEMICOLON);
                          end;
                          end;
                        parse_var_proc_directives(tsym(newtype));
                        parse_var_proc_directives(tsym(newtype));
+                       if po_is_function_ref in tprocvardef(hdef).procoptions then
+                         begin
+                           { these always support everything, no "of object" or
+                             "is_nested" is allowed }
+                           if is_nested_pd(tprocvardef(hdef)) or
+                              is_methodpointer(hdef) then
+                             cgmessage(type_e_function_reference_kind)
+                           else
+                             begin
+                               if (po_hascallingconvention in tprocvardef(hdef).procoptions) and
+                                  (tprocvardef(hdef).proccalloption=pocall_cdecl) then
+                                 begin
+                                   include(tprocvardef(hdef).procoptions,po_is_block);
+                                   { can't check yet whether the parameter types
+                                     are valid for a block, since some of them
+                                     may still be forwarddefs }
+                                 end
+                               else
+                                 { a regular anonymous function type: not yet supported }
+                                 cgmessage(type_e_anonymous_function_unsupported);
+                             end
+                         end;
                        handle_calling_convention(tprocvardef(hdef));
                        handle_calling_convention(tprocvardef(hdef));
                        if try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg) then
                        if try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg) then
                          consume(_SEMICOLON);
                          consume(_SEMICOLON);

+ 4 - 0
compiler/pmodules.pas

@@ -348,6 +348,10 @@ implementation
         if m_iso in current_settings.modeswitches then
         if m_iso in current_settings.modeswitches then
           AddUnit('iso7185');
           AddUnit('iso7185');
 
 
+        { blocks support? }
+        if m_blocks in current_settings.modeswitches then
+          AddUnit('blockrtl');
+
         { default char=widechar? }
         { default char=widechar? }
         if m_default_unicodestring in current_settings.modeswitches then
         if m_default_unicodestring in current_settings.modeswitches then
           AddUnit('uuchar');
           AddUnit('uuchar');

+ 26 - 1
compiler/pparautl.pas

@@ -39,7 +39,7 @@ implementation
 
 
     uses
     uses
       globals,globtype,verbose,systems,
       globals,globtype,verbose,systems,
-      symconst,symtype,symbase,symsym,symtable,symcreat,defutil,
+      symconst,symtype,symbase,symsym,symtable,symcreat,defutil,blockutl,
       paramgr;
       paramgr;
 
 
 
 
@@ -176,6 +176,31 @@ implementation
             vs:=cparavarsym.create('$self',paranr_self,vs_value,voidpointertype,[vo_is_self,vo_is_hidden_para]);
             vs:=cparavarsym.create('$self',paranr_self,vs_value,voidpointertype,[vo_is_self,vo_is_hidden_para]);
             pd.parast.insert(vs);
             pd.parast.insert(vs);
           end
           end
+        { while only procvardefs of this type can be declared in Pascal code,
+          internally we also generate procdefs of this type when creating
+          block wrappers }
+        else if (po_is_block in pd.procoptions) then
+          begin
+            { generate the first hidden parameter, which is a so-called "block
+              literal" describing the block and containing its invocation
+              procedure  }
+            hdef:=getpointerdef(get_block_literal_type_for_proc(pd));
+            { mark as vo_is_parentfp so that proc2procvar comparisons will
+              succeed when assigning arbitrary routines to the block }
+            vs:=cparavarsym.create('$_block_literal',paranr_blockselfpara,vs_value,
+              hdef,[vo_is_hidden_para,vo_is_parentfp]
+            );
+            pd.parast.insert(vs);
+            if pd.typ=procdef then
+              begin
+                { make accessible to code }
+                sl:=tpropaccesslist.create;
+                sl.addsym(sl_load,vs);
+                aliasvs:=cabsolutevarsym.create_ref('FPC_BLOCK_SELF',hdef,sl);
+                include(aliasvs.varoptions,vo_is_parentfp);
+                tlocalsymtable(tprocdef(pd).localst).insert(aliasvs);
+              end;
+          end
         else
         else
           begin
           begin
              if (pd.typ=procdef) and
              if (pd.typ=procdef) and

+ 39 - 14
compiler/ptype.pas

@@ -73,7 +73,7 @@ implementation
        paramgr,procinfo,
        paramgr,procinfo,
        { symtable }
        { symtable }
        symconst,symsym,symtable,symcreat,
        symconst,symsym,symtable,symcreat,
-       defutil,defcmp,
+       defutil,defcmp,objcdef,
 {$ifdef jvm}
 {$ifdef jvm}
        jvmdef,
        jvmdef,
 {$endif}
 {$endif}
@@ -1795,6 +1795,43 @@ implementation
                 jvm_create_procvar_class(name,def);
                 jvm_create_procvar_class(name,def);
 {$endif}
 {$endif}
               end;
               end;
+            _ID:
+              begin
+                case idtoken of
+                  _HELPER:
+                    begin
+                      if hadtypetoken and
+                         { don't allow "type helper" in mode delphi and require modeswitch typehelpers }
+                         ([m_delphi,m_type_helpers]*current_settings.modeswitches=[m_type_helpers]) then
+                        begin
+                          { reset hadtypetoken, so that calling code knows that it should not be handled
+                            as a "unique" type }
+                          hadtypetoken:=false;
+                          consume(_HELPER);
+                          def:=object_dec(odt_helper,name,newsym,genericdef,genericlist,nil,ht_type);
+                        end
+                      else
+                        expr_type
+                    end;
+                  _REFERENCE:
+                    begin
+                      if m_blocks in current_settings.modeswitches then
+                        begin
+                          consume(_REFERENCE);
+                          consume(_TO);
+                          def:=procvar_dec(genericdef,genericlist);
+                          { could be errordef in case of a syntax error }
+                          if assigned(def) and
+                             (def.typ=procvardef) then
+                            include(tprocvardef(def).procoptions,po_is_function_ref);
+                        end
+                      else
+                        expr_type;
+                    end;
+                  else
+                    expr_type;
+                end;
+              end
             else
             else
               if (token=_KLAMMERAFFE) and (m_iso in current_settings.modeswitches) then
               if (token=_KLAMMERAFFE) and (m_iso in current_settings.modeswitches) then
                 begin
                 begin
@@ -1805,19 +1842,7 @@ implementation
                     current_module.checkforwarddefs.add(def);
                     current_module.checkforwarddefs.add(def);
                 end
                 end
               else
               else
-                if hadtypetoken and
-                    { don't allow "type helper" in mode delphi and require modeswitch typehelpers }
-                    ([m_delphi,m_type_helpers]*current_settings.modeswitches=[m_type_helpers]) and
-                    (token=_ID) and (idtoken=_HELPER) then
-                  begin
-                    { reset hadtypetoken, so that calling code knows that it should not be handled
-                      as a "unique" type }
-                    hadtypetoken:=false;
-                    consume(_HELPER);
-                    def:=object_dec(odt_helper,name,newsym,genericdef,genericlist,nil,ht_type);
-                  end
-                else
-                  expr_type;
+                expr_type;
          end;
          end;
 
 
          if def=nil then
          if def=nil then

+ 9 - 0
compiler/scanner.pas

@@ -602,6 +602,15 @@ implementation
                   break;
                   break;
                 end;
                 end;
 
 
+              { Blocks supported? }
+              if doinclude and
+                 (i = m_blocks) and
+                 not(target_info.system in systems_blocks_supported) then
+                begin
+                  Message1(option_unsupported_target_for_feature,'Blocks');
+                  break;
+                end;
+
               if changeInit then
               if changeInit then
                 current_settings.modeswitches:=init_settings.modeswitches;
                 current_settings.modeswitches:=init_settings.modeswitches;
               Result:=true;
               Result:=true;

+ 18 - 9
compiler/symconst.pas

@@ -113,16 +113,17 @@ const
   { implicit parameter positions, normal parameters start at 10
   { implicit parameter positions, normal parameters start at 10
     and will increase with 10 for each parameter. The high parameters
     and will increase with 10 for each parameter. The high parameters
     will be inserted with n+1 }
     will be inserted with n+1 }
-  paranr_parentfp = 1;
-  paranr_parentfp_delphi_cc_leftright = 1;
-  paranr_self = 2;
-  paranr_result = 3;
-  paranr_vmt = 4;
+  paranr_blockselfpara = 1;
+  paranr_parentfp = 2;
+  paranr_parentfp_delphi_cc_leftright = 2;
+  paranr_self = 3;
+  paranr_result = 4;
+  paranr_vmt = 5;
 
 
   { the implicit parameters for Objective-C methods need to come
   { the implicit parameters for Objective-C methods need to come
     after the hidden result parameter }
     after the hidden result parameter }
-  paranr_objc_self = 4;
-  paranr_objc_cmd = 5;
+  paranr_objc_self = 5;
+  paranr_objc_cmd = 6;
   { Required to support variations of syscalls on MorphOS }
   { Required to support variations of syscalls on MorphOS }
   paranr_syscall_basesysv    = 9;
   paranr_syscall_basesysv    = 9;
   paranr_syscall_sysvbase    = high(word)-5;
   paranr_syscall_sysvbase    = high(word)-5;
@@ -355,7 +356,11 @@ type
     { procedure is far (x86 only) }
     { procedure is far (x86 only) }
     po_far,
     po_far,
     { the procedure never returns, this information is usefull for dfa }
     { the procedure never returns, this information is usefull for dfa }
-    po_noreturn
+    po_noreturn,
+    { procvar is a function reference }
+    po_is_function_ref,
+    { procvar is a block (http://en.wikipedia.org/wiki/Blocks_(C_language_extension) ) }
+    po_is_block
   );
   );
   tprocoptions=set of tprocoption;
   tprocoptions=set of tprocoption;
 
 
@@ -393,7 +398,8 @@ type
     tsk_jvm_procvar_intconstr, // Java procvar class constructor that accepts an interface instance for easy Java interoperation
     tsk_jvm_procvar_intconstr, // Java procvar class constructor that accepts an interface instance for easy Java interoperation
     tsk_jvm_virtual_clmethod,  // Java wrapper for virtual class method
     tsk_jvm_virtual_clmethod,  // Java wrapper for virtual class method
     tsk_field_getter,          // getter for a field (callthrough property is passed in skpara)
     tsk_field_getter,          // getter for a field (callthrough property is passed in skpara)
-    tsk_field_setter           // Setter for a field (callthrough property is passed in skpara)
+    tsk_field_setter,          // Setter for a field (callthrough property is passed in skpara)
+    tsk_block_invoke_procvar   // Call a procvar to invoke inside a block
   );
   );
 
 
   { options for objects and classes }
   { options for objects and classes }
@@ -762,6 +768,9 @@ inherited_objectoptions : tobjectoptions = [oo_has_virtual,oo_has_private,oo_has
       vararray = $2000;
       vararray = $2000;
       varbyref = $4000;
       varbyref = $4000;
 
 
+      { blocks-related constants }
+      blocks_procvar_invoke_type_name = '__FPC_invoke_pvtype';
+
 implementation
 implementation
 
 
 end.
 end.

+ 16 - 3
compiler/symcreat.pas

@@ -916,6 +916,20 @@ implementation
     end;
     end;
 
 
 
 
+  procedure implement_block_invoke_procvar(pd: tprocdef);
+    var
+      str: ansistring;
+    begin
+      str:='';
+      str:='begin ';
+      if pd.returndef<>voidtype then
+        str:=str+'result:=';
+      str:=str+'__FPC_BLOCK_INVOKE_PV_TYPE(PFPC_Block_literal_complex_procvar(FPC_Block_Self)^.pv)(';
+      addvisibibleparameters(str,pd);
+      str:=str+') end;';
+      str_parse_method_impl(str,pd,false);
+    end;
+
   procedure add_synthetic_method_implementations_for_st(st: tsymtable);
   procedure add_synthetic_method_implementations_for_st(st: tsymtable);
     var
     var
       i   : longint;
       i   : longint;
@@ -986,6 +1000,8 @@ implementation
               implement_field_getter(pd);
               implement_field_getter(pd);
             tsk_field_setter:
             tsk_field_setter:
               implement_field_setter(pd);
               implement_field_setter(pd);
+            tsk_block_invoke_procvar:
+              implement_block_invoke_procvar(pd);
             else
             else
               internalerror(2011032801);
               internalerror(2011032801);
           end;
           end;
@@ -999,9 +1015,6 @@ implementation
       def: tdef;
       def: tdef;
       sstate: tscannerstate;
       sstate: tscannerstate;
     begin
     begin
-      { only necessary for the JVM target currently }
-      if not (target_info.system in systems_jvm) then
-        exit;
       { skip if any errors have occurred, since then this can only cause more
       { skip if any errors have occurred, since then this can only cause more
         errors }
         errors }
       if ErrorCount<>0 then
       if ErrorCount<>0 then

+ 8 - 2
compiler/symdef.pas

@@ -5243,7 +5243,9 @@ implementation
            not(is_void(returndef)) then
            not(is_void(returndef)) then
           s:=s+':'+returndef.GetTypeName;
           s:=s+':'+returndef.GetTypeName;
         if owner.symtabletype=localsymtable then
         if owner.symtabletype=localsymtable then
-          s:=s+' is nested';
+          s:=s+' is nested'
+        else if po_is_block in procoptions then
+          s:=s+' is block';
         s:=s+';';
         s:=s+';';
         { forced calling convention? }
         { forced calling convention? }
         if (po_hascallingconvention in procoptions) then
         if (po_hascallingconvention in procoptions) then
@@ -5885,7 +5887,11 @@ implementation
            s := s+' of object';
            s := s+' of object';
          if is_nested_pd(self) then
          if is_nested_pd(self) then
            s := s+' is nested';
            s := s+' is nested';
-         GetTypeName := s+';'+ProcCallOptionStr[proccalloption]+'>';
+         { calling convention doesn't matter for blocks }
+         if po_is_block in procoptions then
+           GetTypeName := s+' is block;'
+         else
+           GetTypeName := s+';'+ProcCallOptionStr[proccalloption]+'>';
       end;
       end;
 
 
 
 

+ 20 - 1
compiler/symtable.pas

@@ -43,6 +43,7 @@ interface
           init_final_check_done : boolean;
           init_final_check_done : boolean;
           procedure _needs_init_final(sym:TObject;arg:pointer);
           procedure _needs_init_final(sym:TObject;arg:pointer);
           procedure check_forward(sym:TObject;arg:pointer);
           procedure check_forward(sym:TObject;arg:pointer);
+          procedure check_block_valid(def: TObject;arg:pointer);
           procedure labeldefined(sym:TObject;arg:pointer);
           procedure labeldefined(sym:TObject;arg:pointer);
           procedure varsymbolused(sym:TObject;arg:pointer);
           procedure varsymbolused(sym:TObject;arg:pointer);
           procedure TestPrivate(sym:TObject;arg:pointer);
           procedure TestPrivate(sym:TObject;arg:pointer);
@@ -360,7 +361,7 @@ implementation
       { global }
       { global }
       verbose,globals,
       verbose,globals,
       { symtable }
       { symtable }
-      symutil,defutil,defcmp,
+      symutil,defutil,defcmp,objcdef,
       { module }
       { module }
       fmodule,
       fmodule,
       { codegen }
       { codegen }
@@ -656,6 +657,21 @@ implementation
       end;
       end;
 
 
 
 
+    procedure tstoredsymtable.check_block_valid(def: TObject; arg: pointer);
+      var
+        founderrordef: tdef;
+      begin
+        { all parameters passed to a block must be handled by the Objective-C
+          runtime }
+        if is_block(tdef(def)) and
+           not objcchecktype(tdef(def),founderrordef) then
+          if assigned(tdef(def).typesym) then
+            MessagePos1(tdef(def).typesym.fileinfo,type_e_objc_type_unsupported,founderrordef.typename)
+          else
+            Message1(type_e_objc_type_unsupported,tprocvardef(def).typename)
+      end;
+
+
     procedure TStoredSymtable.labeldefined(sym:TObject;arg:pointer);
     procedure TStoredSymtable.labeldefined(sym:TObject;arg:pointer);
       begin
       begin
         if (tsym(sym).typ=labelsym) and
         if (tsym(sym).typ=labelsym) and
@@ -800,6 +816,9 @@ implementation
     procedure tstoredsymtable.check_forwards;
     procedure tstoredsymtable.check_forwards;
       begin
       begin
          SymList.ForEachCall(@check_forward,nil);
          SymList.ForEachCall(@check_forward,nil);
+         { check whether all block definitions contain valid Objective-C types
+           (now that all forward definitions have been resolved) }
+         DefList.ForEachCall(@check_block_valid,nil);
       end;
       end;
 
 
 
 

+ 3 - 0
compiler/systems.pas

@@ -287,6 +287,9 @@ interface
        { systems using the non-fragile Objective-C ABI }
        { systems using the non-fragile Objective-C ABI }
        systems_objc_nfabi = [system_powerpc64_darwin,system_x86_64_darwin,system_arm_darwin,system_i386_iphonesim];
        systems_objc_nfabi = [system_powerpc64_darwin,system_x86_64_darwin,system_arm_darwin,system_i386_iphonesim];
 
 
+       { systems supporting "blocks" }
+       systems_blocks_supported = systems_darwin;
+
        { all systems supporting exports from programs or units }
        { all systems supporting exports from programs or units }
        systems_unit_program_exports = [system_i386_win32,
        systems_unit_program_exports = [system_i386_win32,
                                          system_i386_wdosx,
                                          system_i386_wdosx,

+ 2 - 0
compiler/tokens.pas

@@ -258,6 +258,7 @@ type
     _PROCEDURE,
     _PROCEDURE,
     _PROTECTED,
     _PROTECTED,
     _PUBLISHED,
     _PUBLISHED,
+    _REFERENCE,
     _SOFTFLOAT,
     _SOFTFLOAT,
     _THREADVAR,
     _THREADVAR,
     _WRITEONLY,
     _WRITEONLY,
@@ -577,6 +578,7 @@ const
       (str:'PROCEDURE'     ;special:false;keyword:alllanguagemodes;op:NOTOKEN),
       (str:'PROCEDURE'     ;special:false;keyword:alllanguagemodes;op:NOTOKEN),
       (str:'PROTECTED'     ;special:false;keyword:[m_none];op:NOTOKEN),
       (str:'PROTECTED'     ;special:false;keyword:[m_none];op:NOTOKEN),
       (str:'PUBLISHED'     ;special:false;keyword:[m_none];op:NOTOKEN),
       (str:'PUBLISHED'     ;special:false;keyword:[m_none];op:NOTOKEN),
+      (str:'REFERENCE'     ;special:false;keyword:[m_none];op:NOTOKEN),
       (str:'SOFTFLOAT'     ;special:false;keyword:[m_none];op:NOTOKEN),
       (str:'SOFTFLOAT'     ;special:false;keyword:[m_none];op:NOTOKEN),
       (str:'THREADVAR'     ;special:false;keyword:alllanguagemodes-[m_iso];op:NOTOKEN),
       (str:'THREADVAR'     ;special:false;keyword:alllanguagemodes-[m_iso];op:NOTOKEN),
       (str:'WRITEONLY'     ;special:false;keyword:[m_none];op:NOTOKEN),
       (str:'WRITEONLY'     ;special:false;keyword:[m_none];op:NOTOKEN),

+ 4 - 2
compiler/utils/ppuutils/ppudump.pp

@@ -463,7 +463,7 @@ const
       'jvm enum fpcvalueof', 'jvm enum long2set',
       'jvm enum fpcvalueof', 'jvm enum long2set',
       'jvm enum bitset2set', 'jvm enum set2set',
       'jvm enum bitset2set', 'jvm enum set2set',
       'jvm procvar invoke', 'jvm procvar intf constructor',
       'jvm procvar invoke', 'jvm procvar intf constructor',
-      'jvm virtual class method', 'jvm field getter', 'jvm field setter');
+      'jvm virtual class method', 'jvm field getter', 'jvm field setter', 'block invoke');
 begin
 begin
   if w<=ord(high(syntheticName)) then
   if w<=ord(high(syntheticName)) then
     result:=syntheticName[tsynthetickind(w)]
     result:=syntheticName[tsynthetickind(w)]
@@ -1755,7 +1755,9 @@ const
      (mask:po_rtlproc;         str: 'RTL procedure'),
      (mask:po_rtlproc;         str: 'RTL procedure'),
      (mask:po_auto_raised_visibility; str: 'Visibility raised by compiler'),
      (mask:po_auto_raised_visibility; str: 'Visibility raised by compiler'),
      (mask:po_far;             str: 'Far'),
      (mask:po_far;             str: 'Far'),
-     (mask:po_noreturn;             str: 'No return')
+     (mask:po_noreturn;        str: 'No return'),
+     (mask:po_is_function_ref; str: 'Function reference'),
+     (mask:po_is_block;        str: 'C "Block"')
   );
   );
 var
 var
   proctypeoption  : tproctypeoption;
   proctypeoption  : tproctypeoption;

+ 76 - 75
rtl/darwin/Makefile

@@ -359,235 +359,235 @@ ifndef USELIBGGI
 USELIBGGI=NO
 USELIBGGI=NO
 endif
 endif
 ifeq ($(FULL_TARGET),i386-linux)
 ifeq ($(FULL_TARGET),i386-linux)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),i386-go32v2)
 ifeq ($(FULL_TARGET),i386-go32v2)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),i386-win32)
 ifeq ($(FULL_TARGET),i386-win32)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),i386-os2)
 ifeq ($(FULL_TARGET),i386-os2)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),i386-freebsd)
 ifeq ($(FULL_TARGET),i386-freebsd)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),i386-beos)
 ifeq ($(FULL_TARGET),i386-beos)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),i386-haiku)
 ifeq ($(FULL_TARGET),i386-haiku)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),i386-netbsd)
 ifeq ($(FULL_TARGET),i386-netbsd)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),i386-solaris)
 ifeq ($(FULL_TARGET),i386-solaris)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),i386-qnx)
 ifeq ($(FULL_TARGET),i386-qnx)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),i386-netware)
 ifeq ($(FULL_TARGET),i386-netware)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),i386-openbsd)
 ifeq ($(FULL_TARGET),i386-openbsd)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),i386-wdosx)
 ifeq ($(FULL_TARGET),i386-wdosx)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),i386-darwin)
 ifeq ($(FULL_TARGET),i386-darwin)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),i386-emx)
 ifeq ($(FULL_TARGET),i386-emx)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),i386-watcom)
 ifeq ($(FULL_TARGET),i386-watcom)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),i386-netwlibc)
 ifeq ($(FULL_TARGET),i386-netwlibc)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),i386-wince)
 ifeq ($(FULL_TARGET),i386-wince)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),i386-embedded)
 ifeq ($(FULL_TARGET),i386-embedded)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),i386-symbian)
 ifeq ($(FULL_TARGET),i386-symbian)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),i386-nativent)
 ifeq ($(FULL_TARGET),i386-nativent)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),i386-iphonesim)
 ifeq ($(FULL_TARGET),i386-iphonesim)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),i386-android)
 ifeq ($(FULL_TARGET),i386-android)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),i386-aros)
 ifeq ($(FULL_TARGET),i386-aros)
 override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),m68k-linux)
 ifeq ($(FULL_TARGET),m68k-linux)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),m68k-freebsd)
 ifeq ($(FULL_TARGET),m68k-freebsd)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),m68k-netbsd)
 ifeq ($(FULL_TARGET),m68k-netbsd)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),m68k-amiga)
 ifeq ($(FULL_TARGET),m68k-amiga)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),m68k-atari)
 ifeq ($(FULL_TARGET),m68k-atari)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),m68k-openbsd)
 ifeq ($(FULL_TARGET),m68k-openbsd)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),m68k-palmos)
 ifeq ($(FULL_TARGET),m68k-palmos)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),m68k-embedded)
 ifeq ($(FULL_TARGET),m68k-embedded)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),powerpc-linux)
 ifeq ($(FULL_TARGET),powerpc-linux)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),powerpc-netbsd)
 ifeq ($(FULL_TARGET),powerpc-netbsd)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),powerpc-amiga)
 ifeq ($(FULL_TARGET),powerpc-amiga)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),powerpc-macos)
 ifeq ($(FULL_TARGET),powerpc-macos)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),powerpc-darwin)
 ifeq ($(FULL_TARGET),powerpc-darwin)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),powerpc-morphos)
 ifeq ($(FULL_TARGET),powerpc-morphos)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),powerpc-embedded)
 ifeq ($(FULL_TARGET),powerpc-embedded)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),powerpc-wii)
 ifeq ($(FULL_TARGET),powerpc-wii)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),powerpc-aix)
 ifeq ($(FULL_TARGET),powerpc-aix)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),sparc-linux)
 ifeq ($(FULL_TARGET),sparc-linux)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),sparc-netbsd)
 ifeq ($(FULL_TARGET),sparc-netbsd)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),sparc-solaris)
 ifeq ($(FULL_TARGET),sparc-solaris)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),sparc-embedded)
 ifeq ($(FULL_TARGET),sparc-embedded)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),x86_64-linux)
 ifeq ($(FULL_TARGET),x86_64-linux)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),x86_64-freebsd)
 ifeq ($(FULL_TARGET),x86_64-freebsd)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),x86_64-netbsd)
 ifeq ($(FULL_TARGET),x86_64-netbsd)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),x86_64-solaris)
 ifeq ($(FULL_TARGET),x86_64-solaris)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),x86_64-openbsd)
 ifeq ($(FULL_TARGET),x86_64-openbsd)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),x86_64-darwin)
 ifeq ($(FULL_TARGET),x86_64-darwin)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),x86_64-win64)
 ifeq ($(FULL_TARGET),x86_64-win64)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),x86_64-embedded)
 ifeq ($(FULL_TARGET),x86_64-embedded)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),x86_64-dragonfly)
 ifeq ($(FULL_TARGET),x86_64-dragonfly)
 override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),arm-linux)
 ifeq ($(FULL_TARGET),arm-linux)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),arm-palmos)
 ifeq ($(FULL_TARGET),arm-palmos)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),arm-darwin)
 ifeq ($(FULL_TARGET),arm-darwin)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),arm-wince)
 ifeq ($(FULL_TARGET),arm-wince)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),arm-gba)
 ifeq ($(FULL_TARGET),arm-gba)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),arm-nds)
 ifeq ($(FULL_TARGET),arm-nds)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),arm-embedded)
 ifeq ($(FULL_TARGET),arm-embedded)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),arm-symbian)
 ifeq ($(FULL_TARGET),arm-symbian)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),arm-android)
 ifeq ($(FULL_TARGET),arm-android)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),powerpc64-linux)
 ifeq ($(FULL_TARGET),powerpc64-linux)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),powerpc64-darwin)
 ifeq ($(FULL_TARGET),powerpc64-darwin)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),powerpc64-embedded)
 ifeq ($(FULL_TARGET),powerpc64-embedded)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),powerpc64-aix)
 ifeq ($(FULL_TARGET),powerpc64-aix)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),avr-embedded)
 ifeq ($(FULL_TARGET),avr-embedded)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),armeb-linux)
 ifeq ($(FULL_TARGET),armeb-linux)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),armeb-embedded)
 ifeq ($(FULL_TARGET),armeb-embedded)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),mips-linux)
 ifeq ($(FULL_TARGET),mips-linux)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),mipsel-linux)
 ifeq ($(FULL_TARGET),mipsel-linux)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),mipsel-embedded)
 ifeq ($(FULL_TARGET),mipsel-embedded)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),mipsel-android)
 ifeq ($(FULL_TARGET),mipsel-android)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),jvm-java)
 ifeq ($(FULL_TARGET),jvm-java)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),jvm-android)
 ifeq ($(FULL_TARGET),jvm-android)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),i8086-msdos)
 ifeq ($(FULL_TARGET),i8086-msdos)
-override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
+override TARGET_UNITS+=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 strings sysctl baseunix unixutil unix initc cmem dynlibs $(CPU_UNITS) dos dl blockrtl sysutils typinfo fgl classes math types charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb errors termio sysconst cthreads rtlconsts cwstring bsd fpwidestring fpintres fpextres objc objcbase unixcp
 endif
 endif
 ifeq ($(FULL_TARGET),i386-linux)
 ifeq ($(FULL_TARGET),i386-linux)
 override TARGET_IMPLICITUNITS+=exeinfo cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp856 cp866 cp874 cp8859_1 cp8859_5 cp8859_2 cp852 unicodedata unicodenumtable
 override TARGET_IMPLICITUNITS+=exeinfo cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp856 cp866 cp874 cp8859_1 cp8859_5 cp8859_2 cp852 unicodedata unicodenumtable
@@ -2703,6 +2703,7 @@ strings$(PPUEXT) : $(SYSTEMUNIT)$(PPUEXT) $(INC)/strings.pp $(INC)/stringsi.inc\
 		   $(SYSTEMUNIT)$(PPUEXT)
 		   $(SYSTEMUNIT)$(PPUEXT)
 objc$(PPUEXT) : $(SYSTEMUNIT)$(PPUEXT) ctypes$(PPUEXT) unixtype$(PPUEXT) $(INC)/objc.pp $(INC)/objc1.inc $(INC)/objcnf.inc
 objc$(PPUEXT) : $(SYSTEMUNIT)$(PPUEXT) ctypes$(PPUEXT) unixtype$(PPUEXT) $(INC)/objc.pp $(INC)/objc1.inc $(INC)/objcnf.inc
 objcbase$(PPUEXT) : $(SYSTEMUNIT)$(PPUEXT) $(INC)/objcbase.pp objc$(PPUEXT)
 objcbase$(PPUEXT) : $(SYSTEMUNIT)$(PPUEXT) $(INC)/objcbase.pp objc$(PPUEXT)
+blockrtl$(PPUEXT) : $(SYSTEMUNIT)$(PPUEXT) objpas$(PPUEXT) initc$(PPUEXT) ctypes$(PPUEXT) $(INC)/blockrtl.pp
 baseunix$(PPUEXT) : unixtype$(PPUEXT) sysctl$(PPUEXT) errno.inc ptypes.inc $(UNIXINC)/ctypes.inc \
 baseunix$(PPUEXT) : unixtype$(PPUEXT) sysctl$(PPUEXT) errno.inc ptypes.inc $(UNIXINC)/ctypes.inc \
   signal.inc $(UNIXINC)/bunxh.inc \
   signal.inc $(UNIXINC)/bunxh.inc \
   $(BSDINC)/bunxsysc.inc \
   $(BSDINC)/bunxsysc.inc \

+ 3 - 1
rtl/darwin/Makefile.fpc

@@ -11,7 +11,7 @@ loaders=
 units=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 \
 units=$(SYSTEMUNIT) uuchar unixtype ctypes objpas macpas iso7185 \
       strings sysctl baseunix unixutil \
       strings sysctl baseunix unixutil \
       unix initc cmem dynlibs $(CPU_UNITS) \
       unix initc cmem dynlibs $(CPU_UNITS) \
-      dos dl \
+      dos dl blockrtl \
       sysutils typinfo fgl classes math types \
       sysutils typinfo fgl classes math types \
       charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb \
       charset cpall character getopts heaptrc lineinfo lnfodwrf lnfogdb \
       errors termio \
       errors termio \
@@ -142,6 +142,8 @@ objc$(PPUEXT) : $(SYSTEMUNIT)$(PPUEXT) ctypes$(PPUEXT) unixtype$(PPUEXT) $(INC)/
 
 
 objcbase$(PPUEXT) : $(SYSTEMUNIT)$(PPUEXT) $(INC)/objcbase.pp objc$(PPUEXT)
 objcbase$(PPUEXT) : $(SYSTEMUNIT)$(PPUEXT) $(INC)/objcbase.pp objc$(PPUEXT)
 
 
+blockrtl$(PPUEXT) : $(SYSTEMUNIT)$(PPUEXT) objpas$(PPUEXT) initc$(PPUEXT) ctypes$(PPUEXT) $(INC)/blockrtl.pp
+
 #
 #
 # System Dependent Units
 # System Dependent Units
 #
 #

+ 128 - 0
rtl/inc/blockrtl.pp

@@ -0,0 +1,128 @@
+ {
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 20134 by Jonas Maebe,
+    member of the Free Pascal development team
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+unit blockrtl;
+
+{ for tmethod }
+{$mode objfpc}
+
+{$packrecords c}
+
+interface
+
+  uses
+    initc,
+    ctypes;
+
+  { blocks helpers }
+  function _Block_copy(const aBlock: pointer): pointer; cdecl; external;
+  procedure _Block_release(const aBlock: pointer); cdecl; external;
+  procedure _Block_object_assign(dst, src: pointer; const flags: cint); cdecl; external;
+  procedure _Block_object_dispose(const aBlock: pointer; const flags: cint); cdecl; external;
+
+  { blocks isa pointers }
+  var
+    _NSConcreteGlobalBlock: array[0..31] of pointer; cvar; external;
+    _NSConcreteStackBlock: array[0..31] of pointer; cvar; external;
+
+  { from Clang source, distributed under the University of Illinois Open Source
+    License }
+
+  { BlockByrefFlags }
+  const
+    BLOCK_BYREF_HAS_COPY_DISPOSE  =  1 shl 25;
+    BLOCK_BYREF_LAYOUT_MASK       = $f shl 28;
+    BLOCK_BYREF_LAYOUT_EXTENDED   =  1 shl 28;
+    BLOCK_BYREF_LAYOUT_NON_OBJECT =  2 shl 28;
+    BLOCK_BYREF_LAYOUT_STRONG     =  3 shl 28;
+    BLOCK_BYREF_LAYOUT_WEAK       =  4 shl 28;
+    BLOCK_BYREF_LAYOUT_UNRETAINED =  5 shl 28;
+
+  { BlockLiteralFlags }
+  const
+    BLOCK_HAS_COPY_DISPOSE    = 1 shl 25;
+    BLOCK_HAS_CXX_OBJ         = 1 shl 26;
+    BLOCK_IS_GLOBAL           = 1 shl 28;
+    BLOCK_USE_STRET           = 1 shl 29;
+    BLOCK_HAS_SIGNATURE       = 1 shl 30;
+    BLOCK_HAS_EXTENDED_LAYOUT = 1 shl 31;
+
+  { BlockFieldFlag_t }
+  const
+    BLOCK_FIELD_IS_OBJECT = $03; { id, NSObject, __attribute__((NSObject)), block, ... }
+    BLOCK_FIELD_IS_BLOCK  = $07; { a block variable }
+    BLOCK_FIELD_IS_BYREF  = $08; { the on stack structure holding the __block variable }
+    BLOCK_FIELD_IS_WEAK   = $10; { declared __weak, only used in byref copy helpers }
+    BLOCK_FIELD_IS_ARC    = $40; { field has ARC-specific semantics }
+    BLOCK_BYREF_CALLER    = 128; { called from __block (byref) copy/dispose support routines }
+    BLOCK_BYREF_CURRENT_MAX = 256;
+
+  type
+    FPC_Block_literal_base = record
+      isa: pointer; // initialized to &_NSConcreteStackBlock or &_NSConcreteGlobalBlock
+      flags: cint;
+      reserved: cint;
+      { actually a function pointer, will be cast by the compiler }
+      invoke: pointer;
+      descriptor: pointer;
+    end;
+
+
+    { descriptor for a simple block (no copy/release) }
+    FPC_Block_descriptor_simple = record
+      reserved: culong;
+      Block_size: culong;
+      { signatures are only for the "ABI.2010.3.16" version, but that's all we support
+        because otherwise the callback has to be a C-style variadic function, which
+        we cannot (yet?) generate on the callee side}
+      signature: pchar;
+    end;
+
+    { descriptor for a simple block (no copy/release) }
+    FPC_Block_descriptor_complex = record
+      reserved: culong;
+      Block_size: culong;
+      copy_helper: procedure(dst, src: pointer); cdecl;
+      dispose_helper: procedure(block: pointer); cdecl;
+      { signatures are only for the "ABI.2010.3.16" version, but that's all we support
+        because otherwise the callback has to be a C-style variadic function, which
+        we cannot (yet?) generate on the callee side}
+      signature: pchar;
+    end;
+
+    { for global procedures }
+    FPC_Block_literal_static = record
+      base: FPC_Block_literal_base;
+      { no local state }
+    end;
+
+    { for simple procedure variable (just an address) }
+    FPC_Block_literal_simple_procvar = record
+      base: FPC_Block_literal_base;
+      { the procvar to call }
+      pv: pointer;
+    end;
+
+    { for procedure of object, and in the future also nested procedures and
+      maybe Objective-C methods }
+    FPC_Block_literal_complex_procvar = record
+      base: FPC_Block_literal_base;
+      { the procvar to call }
+      pv: tmethod;
+    end;
+    PFPC_Block_literal_complex_procvar = ^FPC_Block_literal_complex_procvar;
+
+implementation
+
+end.

+ 31 - 0
tests/test/tblock1.pp

@@ -0,0 +1,31 @@
+{ %target=darwin,iphonesim}
+
+{$modeswitch blocks}
+
+type
+  tblock = reference to procedure; cdecl;
+
+procedure test(b: tblock);
+  begin
+    b;
+  end;
+
+procedure proc;
+  begin
+    writeln('called as block');
+  end;
+
+const
+  bconst: tblock = @proc;
+
+var
+  b: tblock;
+begin
+  b:=@proc;
+  b;
+  test(@proc);
+  test(b);
+  bconst;
+  test(bconst);
+end.
+

+ 32 - 0
tests/test/tblock1a.pp

@@ -0,0 +1,32 @@
+{ %target=darwin,iphonesim}
+
+{$mode delphi}
+{$modeswitch blocks}
+
+type
+  tblock = reference to procedure; cdecl;
+
+procedure test(b: tblock);
+  begin
+    b;
+  end;
+
+procedure proc;
+  begin
+    writeln('called as block');
+  end;
+
+const
+  bconst: tblock = proc;
+
+var
+  b: tblock;
+begin
+  b:=proc;
+  b;
+  test(proc);
+  test(b);
+  bconst;
+  test(bconst);
+end.
+

+ 37 - 0
tests/test/tblock1c.pp

@@ -0,0 +1,37 @@
+{ %target=darwin,iphonesim}
+
+{$modeswitch blocks}
+
+type
+  tblock = reference to function(l: longint): longint; cdecl;
+
+function test(b: tblock; l: longint): longint;
+  begin
+    test:=b(l);
+  end;
+
+function func(l: longint): longint;
+  begin
+    writeln('called as block');
+    func:=l+1;
+  end;
+
+const
+  bconst: tblock = @func;
+
+var
+  b: tblock;
+begin
+  b:=@func;
+  if b(1)<>2 then
+    halt(1);
+  if test(@func,4)<>5 then
+    halt(2);
+  if test(b,123)<>124 then
+    halt(3);
+  if bconst(100)<>101 then
+    halt(4);
+  if test(bconst,10)<>11 then
+    halt(5);
+end.
+

+ 51 - 0
tests/test/tblock2.pp

@@ -0,0 +1,51 @@
+{ %target=darwin,iphonesim}
+
+{$mode objfpc}
+{$modeswitch blocks}
+
+type
+  tblock = reference to procedure(j: longint); cdecl;
+
+  tc = class
+    i: longint;
+    procedure callme(j: longint);
+  end;
+
+var
+  b: tblock;
+  c: tc;
+
+procedure tc.callme(j: longint);
+const
+  invocationcount: longint = 0;
+begin
+  writeln('self: ',hexstr(pointer(self)),', i: ',i,', j: ',j);
+  if self<>c then
+    halt(1);
+  if i<>12345 then
+    halt(2);
+  if invocationcount=0 then
+    begin
+      if j<>1 then
+        halt(3)
+    end
+  else if j<>2 then
+    halt(4);
+  inc(invocationcount);
+end;
+
+
+procedure test(b: tblock);
+  begin
+    b(2);
+  end;
+
+begin
+  c:=tc.create;
+  c.i:=12345;
+  b:[email protected];
+  b(1);
+  test(@c.callme);
+  test(b);
+end.
+

+ 51 - 0
tests/test/tblock2a.pp

@@ -0,0 +1,51 @@
+{ %target=darwin,iphonesim}
+
+{$mode delphi}
+{$modeswitch blocks}
+
+type
+  tblock = reference to procedure(j: longint); cdecl;
+
+  tc = class
+    i: longint;
+    procedure callme(j: longint);
+  end;
+
+var
+  b: tblock;
+  p: procedure(j: longint) of object;
+  c: tc;
+
+procedure tc.callme(j: longint);
+const
+  invocationcount: longint = 0;
+begin
+  writeln('self: ',hexstr(pointer(self)),', i: ',i,', j: ',j);
+  if self<>c then
+    halt(1);
+  if i<>12345 then
+    halt(2);
+  if invocationcount=0 then
+    begin
+      if j<>1 then
+        halt(3)
+    end
+  else if j<>2 then
+    halt(4);
+  inc(invocationcount);
+end;
+
+procedure test(b: tblock);
+  begin
+    b(2);
+  end;
+
+begin
+  c:=tc.create;
+  c.i:=12345;
+  b:=c.callme;
+  b(1);
+  test(c.callme);
+  test(b);
+end.
+

部分文件因文件數量過多而無法顯示