Răsfoiți Sursa

+ support for http://en.wikipedia.org/wiki/Blocks_(C_language_extension)
o blocks are implemented as a variation of procedure variables
o declaration of a block variable: "test: procedure(c: char) is block;"
(C equivalent: (void)(^test)(char c) )
o the compiler automatically converts procedures/functions whose address
is passed to a block parameter or assigned to a block variable into
a "block". This consists of
1) generating a block descriptor (containing the size of the "block
literal" (see below) and the signature of the invocation function
encoded as an Objective-C selector)
2) generating a wrapper function around the original funcion (with C
calling convention), that has an extra first hidden parameter
(marked as vo_is_parentfp in the compiler) whose type is a pointer
to the describing "block literal"
3) generating the "block literal", which contains a pointer to an
external variable indicating whether this block captures context or
not, some flags (see compiler/blockutl.get_block_literal_flags for
info), a pointer to the wrapper function and a pointer to the
descriptor. In the future, it will also contain captured variables.
o right now, only global procedures/functions can be converted to blocks
(because they don't require state capturing). The next steps are (Object
Pascal) methods (not Objective-C methods, because Objective-C method
procvars don't exist) and finally nested functions
o on Mac OS X, the functionality will only work on Mac OS X 10.7 and later,
because we have to use the so-called "ABI.2010.3.16" to ensure that
our blocks aren't called as variadic functions by the runtime (which
came out after the Mac OS X 10.6 release)
o while the currently implemented functionality does not require any
library support at all, there's no use enabling it on other platforms
because unless it has been confirmed to work with a blocks runtime,
there's no point in using blocks (they're just somewhat bulky procvars
right now). Enabling it on other platforms (in combination with the
GNUStep Objective-C run time), should simply be a matter of adding
the right {$linklib xxx} statement to rtl/inc/blockrtl.pp file, adding
that file to Makefile.fpc for that platform and adding that platform
to the compiler/systems.systems_blocks_supported set

git-svn-id: branches/blocks@28232 -

Jonas Maebe 11 ani în urmă
părinte
comite
bd09b88a5b

+ 5 - 0
.gitattributes

@@ -138,6 +138,7 @@ compiler/avr/ravrstd.inc svneol=native#text/plain
 compiler/avr/ravrsup.inc svneol=native#text/plain
 compiler/avr/rgcpu.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/bsdcompile -text
 compiler/catch.pas svneol=native#text/plain
@@ -8190,6 +8191,7 @@ rtl/i8086/strings.inc svneol=native#text/plain
 rtl/i8086/stringss.inc svneol=native#text/plain
 rtl/inc/aliases.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/cgenmath.inc svneol=native#text/plain
 rtl/inc/cgenstr.inc svneol=native#text/plain
@@ -11113,6 +11115,9 @@ tests/test/tasm8.pp svneol=native#text/plain
 tests/test/tasmread.pp svneol=native#text/plain
 tests/test/tasout.pp svneol=native#text/plain
 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/tbopr.pp svneol=native#text/plain
 tests/test/tbrtlevt.pp svneol=native#text/plain
 tests/test/tbsx1.pp svneol=native#text/plain

+ 339 - 0
compiler/blockutl.pas

@@ -0,0 +1,339 @@
+{
+    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,
+    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,cutils,
+    pass_1,pparautl,fmodule,
+    aasmdata,
+    ncnv,nmem,
+    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_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
+          internalerror(2014071609);
+        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;
+
+
+  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
+          { local variable that gets initialised: create temp, initialise it,
+            return address of temp }
+          internalerror(2014071502);
+        end;
+
+      procvarnode.free;
+
+      { restore scanner }
+      restore_scanner(sstate);
+      { restore symtable stack }
+      symtablestack.free;
+      symtablestack:=old_symtablestack;
+    end;
+
+end.
+

+ 7 - 1
compiler/defcmp.pas

@@ -2213,7 +2213,10 @@ implementation
            include(po_comp,po_staticmethod);
          if (m_delphi in current_settings.modeswitches) then
            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
             equal_defs(def1.returndef,def2.returndef) then
           begin
@@ -2228,6 +2231,9 @@ implementation
                 { prefer non-nested to non-nested over non-nested to nested }
                 if (is_nested_pd(def1)<>is_nested_pd(def2)) then
                   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;
             proc_to_procvar_equal:=eq;
           end;

+ 4 - 2
compiler/globtype.pas

@@ -400,8 +400,9 @@ interface
                                   fields in Java) }
          m_default_unicodestring, { makes the default string type in $h+ mode unicodestring rather than
                                     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 }
+         m_blocks               { support for http://en.wikipedia.org/wiki/Blocks_(C_language_extension) }
        );
        tmodeswitches = set of tmodeswitch;
 
@@ -566,7 +567,8 @@ interface
          'SYSTEMCODEPAGE',
          'FINALFIELDS',
          'UNICODESTRINGS',
-         'TYPEHELPERS');
+         'TYPEHELPERS',
+         'BLOCKS');
 
 
      type

+ 11 - 1
compiler/ncal.pas

@@ -69,6 +69,7 @@ interface
           function  gen_procvar_context_tree_parentfp:tnode;
           function  gen_self_tree:tnode;
           function  gen_vmt_tree:tnode;
+          function gen_block_context:tnode;
           procedure gen_hidden_parameters;
           function  funcret_can_be_reused:boolean;
           procedure maybe_create_funcret_node;
@@ -2319,6 +2320,13 @@ implementation
       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;
       var
@@ -2549,8 +2557,10 @@ implementation
                          else
                            internalerror(200309287);
                        end
+                     else if not(po_is_block in procdefinition.procoptions) then
+                       para.left:=gen_procvar_context_tree_parentfp
                      else
-                       para.left:=gen_procvar_context_tree_parentfp;
+                       para.left:=gen_block_context
                    end
                 else
                  if vo_is_range_check in para.parasym.varoptions then

+ 29 - 5
compiler/ncgcal.pas

@@ -28,7 +28,7 @@ interface
     uses
       cpubase,
       globtype,
-      parabase,cgutils,
+      parabase,cgbase,cgutils,
       symdef,node,ncal;
 
     type
@@ -95,6 +95,8 @@ interface
           function can_call_ref(var ref: treference):boolean;virtual;
           procedure extra_call_ref_code(var ref: treference);virtual;
           procedure do_call_ref(ref: treference);virtual;
+
+          procedure load_block_invoke(toreg: tregister);virtual;
        public
           procedure pass_generate_code;override;
           destructor destroy;override;
@@ -107,11 +109,11 @@ implementation
       systems,
       cutils,verbose,globals,
       cpuinfo,
-      symconst,symtable,symtype,defutil,paramgr,
-      cgbase,pass_2,
+      symconst,symbase,symtable,symtype,symsym,defutil,paramgr,
+      pass_2,
       aasmbase,aasmtai,aasmdata,
       nbas,nmem,nld,ncnv,nutils,
-      ncgutil,
+      ncgutil,blockutl,
       cgobj,tgobj,hlcgobj,
       procinfo,
       wpobase;
@@ -441,6 +443,26 @@ implementation
       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);
       begin
         if realresdef.is_intregable or
@@ -1000,7 +1022,9 @@ implementation
               pvreg:=cg.getintregister(current_asmdata.CurrAsmList,proc_addr_size);
               { Only load OS_ADDR from the reference (when converting to hlcg:
                 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
                   href:=right.location.reference;
                   callref:=can_call_ref(href);

+ 36 - 3
compiler/ncnv.pas

@@ -296,7 +296,7 @@ implementation
       symconst,symdef,symsym,symcpu,symtable,
       ncon,ncal,nset,nadd,nmem,nmat,nbas,nutils,ninl,
       cgbase,procinfo,
-      htypechk,pass_1,cpuinfo;
+      htypechk,blockutl,pass_1,cpuinfo;
 
 
 {*****************************************************************************
@@ -1992,6 +1992,7 @@ implementation
     function ttypeconvnode.typecheck_proc_to_procvar : tnode;
       var
         pd : tabstractprocdef;
+        source: pnode;
       begin
         result:=nil;
         pd:=tabstractprocdef(left.resultdef);
@@ -2002,7 +2003,37 @@ implementation
           real procvartype that we are converting to) }
         if assigned(totypedef) and
            (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) and
+                        tprocvardef(source^.resultdef).is_addressonly)) 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
          begin
            resultdef:=pd.getcopyas(procvardef,pc_normal);
@@ -2241,7 +2272,9 @@ implementation
                        the procvar, is compatible with the procvar's type }
                      if not(nf_explicit in flags) and
                         (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;
                    end
                   else if maybe_global_proc_to_nested(left,resultdef) then

+ 23 - 5
compiler/ngtcon.pas

@@ -1235,6 +1235,8 @@ function get_next_varsym(def: tabstractrecorddef; const SymList:TFPHashObjectLis
       var
         tmpn,n : tnode;
         pd   : tprocdef;
+        havepd,
+        haveblock: boolean;
       begin
         { Procvars and pointers are no longer compatible.  }
         { under tp:  =nil or =var under fpc: =nil or =@var }
@@ -1285,17 +1287,33 @@ function get_next_varsym(def: tabstractrecorddef; const SymList:TFPHashObjectLis
             n:=tmpn;
           end;
         { 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
-            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
               (checked above) or with a global procedure (checked here),
               because in other cases we need a valid frame pointer }
             if is_nested_pd(def) then
               begin
-                if is_nested_pd(pd) then
+                if haveblock or
+                   is_nested_pd(pd) then
                   Message(parser_e_no_procvarnested_const);
                 list.concat(Tai_const.Create_sym(nil));
               end

+ 4 - 1
compiler/objcdef.pas

@@ -371,7 +371,10 @@ implementation
                 end;
             end;
           procvardef :
-            encodedstr:=encodedstr+'^?';
+            if not(po_is_block in tprocvardef(def).procoptions) then
+              encodedstr:=encodedstr+'^?'
+            else
+              encodedstr:=encodedstr+'@?';
           objectdef :
             case tobjectdef(def).objecttype of
               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
       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 }
     procedure exportobjcclass(def: tobjectdef);
@@ -196,7 +196,7 @@ end;
       end;
 
 
-    function objcencodemethod(pd: tprocdef): ansistring;
+    function objcencodemethod(pd: tabstractprocdef): ansistring;
       var
         parasize,
         totalsize: aint;
@@ -230,7 +230,11 @@ end;
                (vs.varspez in [vs_var,vs_out,vs_constref]) then
               result:=result+'^';
             { 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 }
               internalerror(2009081701);
             { And the total size of the parameters coming before this one

+ 4 - 0
compiler/pmodules.pas

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

+ 6 - 1
compiler/pp.lpi

@@ -27,7 +27,7 @@
         <FormatVersion Value="1"/>
       </local>
     </RunParams>
-    <Units Count="3">
+    <Units Count="4">
       <Unit0>
         <Filename Value="pp.pas"/>
         <IsPartOfProject Value="True"/>
@@ -43,6 +43,11 @@
         <IsPartOfProject Value="True"/>
         <UnitName Value="symcpu"/>
       </Unit2>
+      <Unit3>
+        <Filename Value="..\..\..\..\Volumes\Snow\Data\dev\fpcgit\compiler\blockutl.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="blockutl"/>
+      </Unit3>
     </Units>
   </ProjectOptions>
   <CompilerOptions>

+ 26 - 1
compiler/pparautl.pas

@@ -39,7 +39,7 @@ implementation
 
     uses
       globals,globtype,verbose,systems,
-      symconst,symtype,symbase,symsym,symtable,symcreat,defutil,
+      symconst,symtype,symbase,symsym,symtable,symcreat,defutil,blockutl,
       paramgr;
 
 
@@ -176,6 +176,31 @@ implementation
             vs:=cparavarsym.create('$self',paranr_self,vs_value,voidpointertype,[vo_is_self,vo_is_hidden_para]);
             pd.parast.insert(vs);
           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
           begin
              if (pd.typ=procdef) and

+ 28 - 5
compiler/ptype.pas

@@ -1401,6 +1401,7 @@ implementation
             newtype:ttypesym;
             old_current_genericdef,
             old_current_specializedef: tstoreddef;
+            nestedok, blockok,
             old_parse_generic: boolean;
           begin
             old_current_genericdef:=current_genericdef;
@@ -1448,12 +1449,34 @@ implementation
                 consume(_OBJECT);
                 include(pd.procoptions,po_methodpointer);
               end
-            else if (m_nested_procvars in current_settings.modeswitches) and
-                    try_to_consume(_IS) then
+            else
               begin
-                consume(_NESTED);
-                pd.parast.symtablelevel:=normal_function_level+1;
-                pd.check_mark_as_nested;
+                nestedok:=m_nested_procvars in current_settings.modeswitches;
+                blockok:=m_blocks in current_settings.modeswitches;
+                if (nestedok or blockok) and
+                    try_to_consume(_IS) then
+                  begin
+                    if nestedok and
+                       try_to_consume(_NESTED) then
+                      begin
+                        pd.parast.symtablelevel:=normal_function_level+1;
+                        pd.check_mark_as_nested;
+                      end
+                    else if blockok and
+                       try_to_consume(_BLOCK) then
+                      begin
+                        include(pd.procoptions,po_is_block);
+                      end
+                    else
+                      begin
+                        if nestedok and blockok then
+                          Message2(scan_f_syn_expected,'Nested/Block',tokeninfo^[token].str)
+                        else if nestedok then
+                          consume(_NESTED)
+                        else
+                          consume(_BLOCK)
+                      end;
+                  end;
               end;
             symtablestack.pop(pd.parast);
             tparasymtable(pd.parast).readonly:=false;

+ 9 - 0
compiler/scanner.pas

@@ -602,6 +602,15 @@ implementation
                   break;
                 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
                 current_settings.modeswitches:=init_settings.modeswitches;
               Result:=true;

+ 16 - 9
compiler/symconst.pas

@@ -113,16 +113,17 @@ const
   { implicit parameter positions, normal parameters start at 10
     and will increase with 10 for each parameter. The high parameters
     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
     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 }
   paranr_syscall_basesysv    = 9;
   paranr_syscall_sysvbase    = high(word)-5;
@@ -353,7 +354,9 @@ type
     { procedure is far (x86 only) }
     po_far,
     { the procedure never returns, this information is usefull for dfa }
-    po_noreturn
+    po_noreturn,
+    { procvar is a block (http://en.wikipedia.org/wiki/Blocks_(C_language_extension) ) }
+    po_is_block
   );
   tprocoptions=set of tprocoption;
 
@@ -391,7 +394,8 @@ type
     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_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 }
@@ -760,6 +764,9 @@ inherited_objectoptions : tobjectoptions = [oo_has_virtual,oo_has_private,oo_has
       vararray = $2000;
       varbyref = $4000;
 
+      { blocks-related constants }
+      blocks_procvar_invoke_type_name = '__FPC_invoke_pvtype';
+
 implementation
 
 end.

+ 0 - 3
compiler/symcreat.pas

@@ -999,9 +999,6 @@ implementation
       def: tdef;
       sstate: tscannerstate;
     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
         errors }
       if ErrorCount<>0 then

+ 8 - 2
compiler/symdef.pas

@@ -5120,7 +5120,9 @@ implementation
            not(is_void(returndef)) then
           s:=s+':'+returndef.GetTypeName;
         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+';';
         { forced calling convention? }
         if (po_hascallingconvention in procoptions) then
@@ -5762,7 +5764,11 @@ implementation
            s := s+' of object';
          if is_nested_pd(self) then
            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;
 
 

+ 3 - 0
compiler/systems.pas

@@ -286,6 +286,9 @@ interface
        { 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 supporting "blocks" }
+       systems_blocks_supported = systems_darwin;
+
        { all systems supporting exports from programs or units }
        systems_unit_program_exports = [system_i386_win32,
                                          system_i386_wdosx,

+ 2 - 0
compiler/tokens.pas

@@ -150,6 +150,7 @@ type
     _ALIAS,
     _ARRAY,
     _BEGIN,
+    _BLOCK,
     _BREAK,
     _CDECL,
     _CLASS,
@@ -468,6 +469,7 @@ const
       (str:'ALIAS'         ;special:false;keyword:[m_none];op:NOTOKEN),
       (str:'ARRAY'         ;special:false;keyword:alllanguagemodes;op:NOTOKEN),
       (str:'BEGIN'         ;special:false;keyword:alllanguagemodes;op:NOTOKEN),
+      (str:'BLOCK'         ;special:false;keyword:[m_none];op:NOTOKEN),
       (str:'BREAK'         ;special:false;keyword:[m_none];op:NOTOKEN),
       (str:'CDECL'         ;special:false;keyword:[m_none];op:NOTOKEN),
       (str:'CLASS'         ;special:false;keyword:[m_class];op:NOTOKEN),

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

@@ -460,7 +460,7 @@ const
       'jvm enum fpcvalueof', 'jvm enum long2set',
       'jvm enum bitset2set', 'jvm enum set2set',
       '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
   if w<=ord(high(syntheticName)) then
     result:=syntheticName[tsynthetickind(w)]
@@ -1740,7 +1740,8 @@ const
      (mask:po_rtlproc;         str: 'RTL procedure'),
      (mask:po_auto_raised_visibility; str: 'Visibility raised by compiler'),
      (mask:po_far;             str: 'Far'),
-     (mask:po_noreturn;             str: 'No return')
+     (mask:po_noreturn;        str: 'No return'),
+     (mask:po_is_block;        str: 'Block')
   );
 var
   proctypeoption  : tproctypeoption;

+ 76 - 75
rtl/darwin/Makefile

@@ -359,229 +359,229 @@ ifndef USELIBGGI
 USELIBGGI=NO
 endif
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
@@ -2662,6 +2662,7 @@ strings$(PPUEXT) : $(SYSTEMUNIT)$(PPUEXT) $(INC)/strings.pp $(INC)/stringsi.inc\
 		   $(SYSTEMUNIT)$(PPUEXT)
 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)
+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 \
   signal.inc $(UNIXINC)/bunxh.inc \
   $(BSDINC)/bunxsysc.inc \

+ 3 - 1
rtl/darwin/Makefile.fpc

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

+ 129 - 0
rtl/inc/blockrtl.pp

@@ -0,0 +1,129 @@
+ {
+    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;
+    PFPC_Block_descriptor_simple = ^FPC_Block_descriptor_simple;
+
+    { 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 = procedure is block;
+
+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 = procedure is block;
+
+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 = function(l: longint): longint is block;
+
+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.
+