Home | History | Annotate | Line # | Download | only in internal
      1 /****************************************************************************
      2  *
      3  * internal/compiler-macros.h
      4  *
      5  *   Compiler-specific macro definitions used internally by FreeType.
      6  *
      7  * Copyright (C) 2020 by
      8  * David Turner, Robert Wilhelm, and Werner Lemberg.
      9  *
     10  * This file is part of the FreeType project, and may only be used,
     11  * modified, and distributed under the terms of the FreeType project
     12  * license, LICENSE.TXT.  By continuing to use, modify, or distribute
     13  * this file you indicate that you have read the license and
     14  * understand and accept it fully.
     15  *
     16  */
     17 
     18 #ifndef INTERNAL_COMPILER_MACROS_H_
     19 #define INTERNAL_COMPILER_MACROS_H_
     20 
     21 #include <freetype/config/public-macros.h>
     22 
     23 FT_BEGIN_HEADER
     24 
     25   /* Fix compiler warning with sgi compiler. */
     26 #if defined( __sgi ) && !defined( __GNUC__ )
     27 #  if defined( _COMPILER_VERSION ) && ( _COMPILER_VERSION >= 730 )
     28 #    pragma set woff 3505
     29 #  endif
     30 #endif
     31 
     32   /* Fix compiler warning with sgi compiler. */
     33 #if defined( __sgi ) && !defined( __GNUC__ )
     34 #  if defined( _COMPILER_VERSION ) && ( _COMPILER_VERSION >= 730 )
     35 #    pragma set woff 3505
     36 #  endif
     37 #endif
     38 
     39   /*
     40    * When defining a macro that expands to a non-trivial C statement, use
     41    * FT_BEGIN_STMNT and FT_END_STMNT to enclose the macro's body.  This
     42    * ensures there are no surprises when the macro is invoked in conditional
     43    * branches.
     44    *
     45    * Example:
     46    *
     47    *   #define  LOG( ... )        \
     48    *     FT_BEGIN_STMNT           \
     49    *       if ( logging_enabled ) \
     50    *         log( __VA_ARGS__ );  \
     51    *     FT_END_STMNT
     52    */
     53 #define FT_BEGIN_STMNT  do {
     54 #define FT_END_STMNT    } while ( 0 )
     55 
     56   /*
     57    * FT_DUMMY_STMNT expands to an empty C statement.  Useful for
     58    * conditionally defined statement macros.
     59    *
     60    * Example:
     61    *
     62    *   #ifdef BUILD_CONFIG_LOGGING
     63    *   #define  LOG( ... )         \
     64    *      FT_BEGIN_STMNT           \
     65    *        if ( logging_enabled ) \
     66    *          log( __VA_ARGS__ );  \
     67    *      FT_END_STMNT
     68    *   #else
     69    *   #  define LOG( ... )  FT_DUMMY_STMNT
     70    *   #endif
     71    */
     72 #define FT_DUMMY_STMNT  FT_BEGIN_STMNT FT_END_STMNT
     73 
     74 #ifdef _WIN64
     75   /* only 64bit Windows uses the LLP64 data model, i.e., */
     76   /* 32-bit integers, 64-bit pointers.                   */
     77 #define FT_UINT_TO_POINTER( x )  (void *)(unsigned __int64)(x)
     78 #else
     79 #define FT_UINT_TO_POINTER( x )  (void *)(unsigned long)(x)
     80 #endif
     81 
     82   /*
     83    * Use `FT_TYPEOF( type )` to cast a value to `type`.  This is useful to
     84    * suppress signedness compilation warnings in macros.
     85    *
     86    * Example:
     87    *
     88    *   #define PAD_( x, n )  ( (x) & ~FT_TYPEOF( x )( (n) - 1 ) )
     89    *
     90    * (The `typeof` condition is taken from gnulib's `intprops.h` header
     91    * file.)
     92    */
     93 #if ( ( defined( __GNUC__ ) && __GNUC__ >= 2 )                       || \
     94       ( defined( __IBMC__ ) && __IBMC__ >= 1210 &&                      \
     95         defined( __IBM__TYPEOF__ ) )                                 || \
     96       ( defined( __SUNPRO_C ) && __SUNPRO_C >= 0x5110 && !__STDC__ ) )
     97 #define FT_TYPEOF( type )  ( __typeof__ ( type ) )
     98 #else
     99 #define FT_TYPEOF( type )  /* empty */
    100 #endif
    101 
    102   /*
    103    * Mark a function declaration as internal to the library.  This ensures
    104    * that it will not be exposed by default to client code, and helps
    105    * generate smaller and faster code on ELF-based platforms.  Place this
    106    * before a function declaration.
    107    */
    108 
    109   /* Visual C, mingw */
    110 #if defined( _WIN32 )
    111 #define FT_INTERNAL_FUNCTION_ATTRIBUTE  /* empty */
    112 
    113   /* gcc, clang */
    114 #elif ( defined( __GNUC__ ) && __GNUC__ >= 4 ) || defined( __clang__ )
    115 #define FT_INTERNAL_FUNCTION_ATTRIBUTE  \
    116           __attribute__(( visibility( "hidden" ) ))
    117 
    118   /* Sun */
    119 #elif defined( __SUNPRO_C ) && __SUNPRO_C >= 0x550
    120 #define FT_INTERNAL_FUNCTION_ATTRIBUTE  __hidden
    121 
    122 #else
    123 #define FT_INTERNAL_FUNCTION_ATTRIBUTE  /* empty */
    124 #endif
    125 
    126   /*
    127    * FreeType supports compilation of its C sources with a C++ compiler (in
    128    * C++ mode); this introduces a number of subtle issues.
    129    *
    130    * The main one is that a C++ function declaration and its definition must
    131    * have the same 'linkage'.  Because all FreeType headers declare their
    132    * functions with C linkage (i.e., within an `extern "C" { ... }` block
    133    * due to the magic of FT_BEGIN_HEADER and FT_END_HEADER), their
    134    * definition in FreeType sources should also be prefixed with `extern
    135    * "C"` when compiled in C++ mode.
    136    *
    137    * The `FT_FUNCTION_DECLARATION` and `FT_FUNCTION_DEFINITION` macros are
    138    * provided to deal with this case, as well as `FT_CALLBACK_DEF` and its
    139    * siblings below.
    140    */
    141 
    142   /*
    143    * `FT_FUNCTION_DECLARATION( type )` can be used to write a C function
    144    * declaration to ensure it will have C linkage when the library is built
    145    * with a C++ compiler.  The parameter is the function's return type, so a
    146    * declaration would look like
    147    *
    148    *    FT_FUNCTION_DECLARATION( int )
    149    *    foo( int x );
    150    *
    151    * NOTE: This requires that all uses are inside of `FT_BEGIN_HEADER ...
    152    * FT_END_HEADER` blocks, which guarantees that the declarations have C
    153    * linkage when the headers are included by C++ sources.
    154    *
    155    * NOTE: Do not use directly.  Use `FT_LOCAL`, `FT_BASE`, and `FT_EXPORT`
    156    * instead.
    157    */
    158 #define FT_FUNCTION_DECLARATION( x )  extern x
    159 
    160   /*
    161    * Same as `FT_FUNCTION_DECLARATION`, but for function definitions instead.
    162    *
    163    * NOTE: Do not use directly.  Use `FT_LOCAL_DEF`, `FT_BASE_DEF`, and
    164    * `FT_EXPORT_DEF` instead.
    165    */
    166 #ifdef __cplusplus
    167 #define FT_FUNCTION_DEFINITION( x )  extern "C" x
    168 #else
    169 #define FT_FUNCTION_DEFINITION( x )  x
    170 #endif
    171 
    172   /*
    173    * Use `FT_LOCAL` and `FT_LOCAL_DEF` to declare and define, respectively,
    174    * an internal FreeType function that is only used by the sources of a
    175    * single `src/module/` directory.  This ensures that the functions are
    176    * turned into static ones at build time, resulting in smaller and faster
    177    * code.
    178    */
    179 #ifdef FT_MAKE_OPTION_SINGLE_OBJECT
    180 
    181 #define FT_LOCAL( x )      static x
    182 #define FT_LOCAL_DEF( x )  static x
    183 
    184 #else
    185 
    186 #define FT_LOCAL( x )      FT_INTERNAL_FUNCTION_ATTRIBUTE \
    187                            FT_FUNCTION_DECLARATION( x )
    188 #define FT_LOCAL_DEF( x )  FT_FUNCTION_DEFINITION( x )
    189 
    190 #endif  /* FT_MAKE_OPTION_SINGLE_OBJECT */
    191 
    192   /*
    193    * Use `FT_LOCAL_ARRAY` and `FT_LOCAL_ARRAY_DEF` to declare and define,
    194    * respectively, a constant array that must be accessed from several
    195    * sources in the same `src/module/` sub-directory, and which are internal
    196    * to the library.
    197    */
    198 #define FT_LOCAL_ARRAY( x )      FT_INTERNAL_FUNCTION_ATTRIBUTE \
    199                                  extern const x
    200 #define FT_LOCAL_ARRAY_DEF( x )  FT_FUNCTION_DEFINITION( const x )
    201 
    202   /*
    203    * `Use FT_BASE` and `FT_BASE_DEF` to declare and define, respectively, an
    204    * internal library function that is used by more than a single module.
    205    */
    206 #define FT_BASE( x )      FT_INTERNAL_FUNCTION_ATTRIBUTE \
    207                           FT_FUNCTION_DECLARATION( x )
    208 #define FT_BASE_DEF( x )  FT_FUNCTION_DEFINITION( x )
    209 
    210 
    211   /*
    212    * NOTE: Conditionally define `FT_EXPORT_VAR` due to its definition in
    213    * `src/smooth/ftgrays.h` to make the header more portable.
    214    */
    215 #ifndef FT_EXPORT_VAR
    216 #define FT_EXPORT_VAR( x )  FT_FUNCTION_DECLARATION( x )
    217 #endif
    218 
    219   /* When compiling FreeType as a DLL or DSO with hidden visibility,   */
    220   /* some systems/compilers need a special attribute in front OR after */
    221   /* the return type of function declarations.                         */
    222   /*                                                                   */
    223   /* Two macros are used within the FreeType source code to define     */
    224   /* exported library functions: `FT_EXPORT` and `FT_EXPORT_DEF`.      */
    225   /*                                                                   */
    226   /* - `FT_EXPORT( return_type )`                                      */
    227   /*                                                                   */
    228   /*   is used in a function declaration, as in                        */
    229   /*                                                                   */
    230   /*   ```                                                             */
    231   /*     FT_EXPORT( FT_Error )                                         */
    232   /*     FT_Init_FreeType( FT_Library*  alibrary );                    */
    233   /*   ```                                                             */
    234   /*                                                                   */
    235   /* - `FT_EXPORT_DEF( return_type )`                                  */
    236   /*                                                                   */
    237   /*   is used in a function definition, as in                         */
    238   /*                                                                   */
    239   /*   ```                                                             */
    240   /*     FT_EXPORT_DEF( FT_Error )                                     */
    241   /*     FT_Init_FreeType( FT_Library*  alibrary )                     */
    242   /*     {                                                             */
    243   /*       ... some code ...                                           */
    244   /*       return FT_Err_Ok;                                           */
    245   /*     }                                                             */
    246   /*   ```                                                             */
    247   /*                                                                   */
    248   /* You can provide your own implementation of `FT_EXPORT` and        */
    249   /* `FT_EXPORT_DEF` here if you want.                                 */
    250   /*                                                                   */
    251   /* To export a variable, use `FT_EXPORT_VAR`.                        */
    252   /*                                                                   */
    253 
    254   /* See `freetype/config/compiler_macros.h` for the `FT_EXPORT` definition */
    255 #define FT_EXPORT_DEF( x )  FT_FUNCTION_DEFINITION( x )
    256 
    257   /* The following macros are needed to compile the library with a   */
    258   /* C++ compiler and with 16bit compilers.                          */
    259   /*                                                                 */
    260 
    261   /* This is special.  Within C++, you must specify `extern "C"` for */
    262   /* functions which are used via function pointers, and you also    */
    263   /* must do that for structures which contain function pointers to  */
    264   /* assure C linkage -- it's not possible to have (local) anonymous */
    265   /* functions which are accessed by (global) function pointers.     */
    266   /*                                                                 */
    267   /*                                                                 */
    268   /* FT_CALLBACK_DEF is used to _define_ a callback function,        */
    269   /* located in the same source code file as the structure that uses */
    270   /* it.                                                             */
    271   /*                                                                 */
    272   /* FT_BASE_CALLBACK and FT_BASE_CALLBACK_DEF are used to declare   */
    273   /* and define a callback function, respectively, in a similar way  */
    274   /* as FT_BASE and FT_BASE_DEF work.                                */
    275   /*                                                                 */
    276   /* FT_CALLBACK_TABLE is used to _declare_ a constant variable that */
    277   /* contains pointers to callback functions.                        */
    278   /*                                                                 */
    279   /* FT_CALLBACK_TABLE_DEF is used to _define_ a constant variable   */
    280   /* that contains pointers to callback functions.                   */
    281   /*                                                                 */
    282   /*                                                                 */
    283   /* Some 16bit compilers have to redefine these macros to insert    */
    284   /* the infamous `_cdecl` or `__fastcall` declarations.             */
    285   /*                                                                 */
    286 #ifdef __cplusplus
    287 #define FT_CALLBACK_DEF( x )  extern "C"  x
    288 #else
    289 #define FT_CALLBACK_DEF( x )  static  x
    290 #endif
    291 
    292 #define FT_BASE_CALLBACK( x )      FT_FUNCTION_DECLARATION( x )
    293 #define FT_BASE_CALLBACK_DEF( x )  FT_FUNCTION_DEFINITION( x )
    294 
    295 #ifndef FT_CALLBACK_TABLE
    296 #ifdef __cplusplus
    297 #define FT_CALLBACK_TABLE      extern "C"
    298 #define FT_CALLBACK_TABLE_DEF  extern "C"
    299 #else
    300 #define FT_CALLBACK_TABLE      extern
    301 #define FT_CALLBACK_TABLE_DEF  /* nothing */
    302 #endif
    303 #endif /* FT_CALLBACK_TABLE */
    304 
    305 FT_END_HEADER
    306 
    307 #endif  /* INTERNAL_COMPILER_MACROS_H_ */
    308