1  /** Definitions for block support for GNUStep
       2     Copyright (C) 2011 Free Software Foundation, Inc.
       3  
       4     This file is part of the GNUstep Base Library.
       5  
       6     This library is free software; you can redistribute it and/or
       7     modify it under the terms of the GNU Lesser General Public
       8     License as published by the Free Software Foundation; either
       9     version 2 of the License, or (at your option) any later version.
      10  
      11     This library is distributed in the hope that it will be useful,
      12     but WITHOUT ANY WARRANTY; without even the implied warranty of
      13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14     Library General Public License for more details.
      15  
      16     You should have received a copy of the GNU Lesser General Public
      17     License along with this library; if not, write to the Free
      18     Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
      19     Boston, MA 02111 USA.
      20  
      21     */
      22  
      23  #ifndef __GSBlocks_h_GNUSTEP_BASE_INCLUDE
      24  #define __GSBlocks_h_GNUSTEP_BASE_INCLUDE
      25  
      26  /* Define the has_feature pseudo-macro for GCC. */
      27  #ifndef __has_feature
      28  #define __has_feature(x) 0
      29  #endif
      30  
      31  #ifndef GCC_VERSION
      32  #define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__)
      33  #endif
      34  
      35  #if __has_feature(blocks)
      36  
      37  #define BLOCK_SCOPE __block
      38  /**
      39   * Defines a block type.  Will work whether or not the compiler natively
      40   * supports blocks.
      41   */
      42  #define DEFINE_BLOCK_TYPE(name, retTy, argTys, ...) \
      43  typedef retTy(^name)(argTys, ## __VA_ARGS__)
      44  
      45  #define DEFINE_BLOCK_TYPE_NO_ARGS(name, retTy) \
      46  typedef retTy(^name)()
      47  
      48  /**
      49   * Calls a block.  Works irrespective of whether the compiler supports blocks.
      50   */
      51  #define CALL_BLOCK(block, args, ...) block(args, ## __VA_ARGS__)
      52  
      53  /**
      54   * Calls a block without arguments.
      55   */
      56  #define CALL_BLOCK_NO_ARGS(block) block()
      57  #else
      58  
      59  /* Fall-back versions for when the compiler doesn't have native blocks support.
      60   */
      61  #if (GCC_VERSION >= 3000)
      62  
      63  #define DEFINE_BLOCK_TYPE(name, retTy, argTys, ...) \
      64    typedef struct {\
      65      void *isa;\
      66      int flags;\
      67      int reserved;\
      68      retTy (*invoke)(void*, argTys, ## __VA_ARGS__);\
      69    } *name
      70  
      71  #define DEFINE_BLOCK_TYPE_NO_ARGS(name, retTy) \
      72    typedef struct {\
      73      void *isa;\
      74      int flags;\
      75      int reserved;\
      76      retTy (*invoke)(void*);\
      77    } *name
      78  
      79  #define CALL_BLOCK(block, args, ...) block->invoke(block, args, ## __VA_ARGS__)
      80  
      81  #define CALL_BLOCK_NO_ARGS(block) block->invoke(block)
      82  #define BLOCK_SCOPE
      83  
      84  #else /* GCC_VERSION >= 3000 */
      85  
      86  #define DEFINE_BLOCK_TYPE(name, retTy, argTys...) \
      87    typedef struct {\
      88      void *isa;\
      89      int flags;\
      90      int reserved;\
      91      retTy (*invoke)(void*, argTys);\
      92    } *name
      93  
      94  #define DEFINE_BLOCK_TYPE_NO_ARGS(name, retTy) \
      95    typedef struct {\
      96      void *isa;\
      97      int flags;\
      98      int reserved;\
      99      retTy (*invoke)(void*);\
     100    } *name
     101  
     102  
     103  #define CALL_BLOCK(block, args...) block->invoke(block, args)
     104  #define CALL_BLOCK_NO_ARGS(block) block->invoke(block)
     105  #define BLOCK_SCOPE
     106  #endif /* GCC_VERSION >= 3000 */
     107  
     108  #endif /* __has_feature(blocks) */
     109  
     110  #if __has_include(<objc/blocks_runtime.h>)
     111  #  include <objc/blocks_runtime.h>
     112  #else
     113  
     114  #ifdef __cplusplus
     115  extern "C" {
     116  #endif
     117  
     118  /**
     119   * _Block_copy and _Block_release are weakly imported, but can be assumed
     120   * to be available whenever a feature using blocks is accessed
     121   * by an application.
     122   */
     123  
     124  /* weak attributed supported only with ELF, MINGW is COFF */
     125  #ifndef __MINGW32__
     126  
     127  void *_Block_copy(const void *) __attribute__((weak));
     128  void _Block_release(const void *) __attribute__((weak));
     129  
     130  #endif /* __MINGW32__ */
     131  
     132  #ifdef __cplusplus
     133  }
     134  #endif
     135  
     136  #ifndef Block_copy
     137  #  define Block_copy(x) ((__typeof(x))_Block_copy((const void *)(x)))
     138  #endif
     139  #ifndef Block_release
     140  #  define Block_release(x) _Block_release((const void *)(x))
     141  #endif
     142  
     143  #endif /* __has_include(<objc/blocks_runtime.h>) */
     144  #endif /* __GSBlocks_h_GNUSTEP_BASE_INCLUDE */
     145