• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /****************************************************************************
2  *
3  * internal/compiler-macros.h
4  *
5  *   Compiler-specific macro definitions used internally by FreeType.
6  *
7  * Copyright (C) 2020-2021 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 __UINTPTR_TYPE__
75   /*
76    * GCC and Clang both provide a `__UINTPTR_TYPE__` that can be used to
77    * avoid a dependency on `stdint.h`.
78    */
79 #  define FT_UINT_TO_POINTER( x )  (void *)(__UINTPTR_TYPE__)(x)
80 #elif defined( _WIN64 )
81   /* only 64bit Windows uses the LLP64 data model, i.e., */
82   /* 32-bit integers, 64-bit pointers.                   */
83 #  define FT_UINT_TO_POINTER( x )  (void *)(unsigned __int64)(x)
84 #else
85 #  define FT_UINT_TO_POINTER( x )  (void *)(unsigned long)(x)
86 #endif
87 
88   /*
89    * Use `FT_TYPEOF( type )` to cast a value to `type`.  This is useful to
90    * suppress signedness compilation warnings in macros.
91    *
92    * Example:
93    *
94    *   #define PAD_( x, n )  ( (x) & ~FT_TYPEOF( x )( (n) - 1 ) )
95    *
96    * (The `typeof` condition is taken from gnulib's `intprops.h` header
97    * file.)
98    */
99 #if ( ( defined( __GNUC__ ) && __GNUC__ >= 2 )                       || \
100       ( defined( __IBMC__ ) && __IBMC__ >= 1210 &&                      \
101         defined( __IBM__TYPEOF__ ) )                                 || \
102       ( defined( __SUNPRO_C ) && __SUNPRO_C >= 0x5110 && !__STDC__ ) )
103 #define FT_TYPEOF( type )  ( __typeof__ ( type ) )
104 #else
105 #define FT_TYPEOF( type )  /* empty */
106 #endif
107 
108   /*
109    * Mark a function declaration as internal to the library.  This ensures
110    * that it will not be exposed by default to client code, and helps
111    * generate smaller and faster code on ELF-based platforms.  Place this
112    * before a function declaration.
113    */
114 
115   /* Visual C, mingw */
116 #if defined( _WIN32 )
117 #define FT_INTERNAL_FUNCTION_ATTRIBUTE  /* empty */
118 
119   /* gcc, clang */
120 #elif ( defined( __GNUC__ ) && __GNUC__ >= 4 ) || defined( __clang__ )
121 #define FT_INTERNAL_FUNCTION_ATTRIBUTE  \
122           __attribute__(( visibility( "hidden" ) ))
123 
124   /* Sun */
125 #elif defined( __SUNPRO_C ) && __SUNPRO_C >= 0x550
126 #define FT_INTERNAL_FUNCTION_ATTRIBUTE  __hidden
127 
128 #else
129 #define FT_INTERNAL_FUNCTION_ATTRIBUTE  /* empty */
130 #endif
131 
132   /*
133    * FreeType supports compilation of its C sources with a C++ compiler (in
134    * C++ mode); this introduces a number of subtle issues.
135    *
136    * The main one is that a C++ function declaration and its definition must
137    * have the same 'linkage'.  Because all FreeType headers declare their
138    * functions with C linkage (i.e., within an `extern "C" { ... }` block
139    * due to the magic of FT_BEGIN_HEADER and FT_END_HEADER), their
140    * definition in FreeType sources should also be prefixed with `extern
141    * "C"` when compiled in C++ mode.
142    *
143    * The `FT_FUNCTION_DECLARATION` and `FT_FUNCTION_DEFINITION` macros are
144    * provided to deal with this case, as well as `FT_CALLBACK_DEF` and its
145    * siblings below.
146    */
147 
148   /*
149    * `FT_FUNCTION_DECLARATION( type )` can be used to write a C function
150    * declaration to ensure it will have C linkage when the library is built
151    * with a C++ compiler.  The parameter is the function's return type, so a
152    * declaration would look like
153    *
154    *    FT_FUNCTION_DECLARATION( int )
155    *    foo( int x );
156    *
157    * NOTE: This requires that all uses are inside of `FT_BEGIN_HEADER ...
158    * FT_END_HEADER` blocks, which guarantees that the declarations have C
159    * linkage when the headers are included by C++ sources.
160    *
161    * NOTE: Do not use directly.  Use `FT_LOCAL`, `FT_BASE`, and `FT_EXPORT`
162    * instead.
163    */
164 #define FT_FUNCTION_DECLARATION( x )  extern x
165 
166   /*
167    * Same as `FT_FUNCTION_DECLARATION`, but for function definitions instead.
168    *
169    * NOTE: Do not use directly.  Use `FT_LOCAL_DEF`, `FT_BASE_DEF`, and
170    * `FT_EXPORT_DEF` instead.
171    */
172 #ifdef __cplusplus
173 #define FT_FUNCTION_DEFINITION( x )  extern "C" x
174 #else
175 #define FT_FUNCTION_DEFINITION( x )  x
176 #endif
177 
178   /*
179    * Use `FT_LOCAL` and `FT_LOCAL_DEF` to declare and define, respectively,
180    * an internal FreeType function that is only used by the sources of a
181    * single `src/module/` directory.  This ensures that the functions are
182    * turned into static ones at build time, resulting in smaller and faster
183    * code.
184    */
185 #ifdef FT_MAKE_OPTION_SINGLE_OBJECT
186 
187 #define FT_LOCAL( x )      static x
188 #define FT_LOCAL_DEF( x )  static x
189 
190 #else
191 
192 #define FT_LOCAL( x )      FT_INTERNAL_FUNCTION_ATTRIBUTE \
193                            FT_FUNCTION_DECLARATION( x )
194 #define FT_LOCAL_DEF( x )  FT_FUNCTION_DEFINITION( x )
195 
196 #endif  /* FT_MAKE_OPTION_SINGLE_OBJECT */
197 
198   /*
199    * Use `FT_LOCAL_ARRAY` and `FT_LOCAL_ARRAY_DEF` to declare and define,
200    * respectively, a constant array that must be accessed from several
201    * sources in the same `src/module/` sub-directory, and which are internal
202    * to the library.
203    */
204 #define FT_LOCAL_ARRAY( x )      FT_INTERNAL_FUNCTION_ATTRIBUTE \
205                                  extern const x
206 #define FT_LOCAL_ARRAY_DEF( x )  FT_FUNCTION_DEFINITION( const x )
207 
208   /*
209    * `Use FT_BASE` and `FT_BASE_DEF` to declare and define, respectively, an
210    * internal library function that is used by more than a single module.
211    */
212 #define FT_BASE( x )      FT_INTERNAL_FUNCTION_ATTRIBUTE \
213                           FT_FUNCTION_DECLARATION( x )
214 #define FT_BASE_DEF( x )  FT_FUNCTION_DEFINITION( x )
215 
216 
217   /*
218    * NOTE: Conditionally define `FT_EXPORT_VAR` due to its definition in
219    * `src/smooth/ftgrays.h` to make the header more portable.
220    */
221 #ifndef FT_EXPORT_VAR
222 #define FT_EXPORT_VAR( x )  FT_FUNCTION_DECLARATION( x )
223 #endif
224 
225   /*
226    * When compiling FreeType as a DLL or DSO with hidden visibility,
227    * some systems/compilers need a special attribute in front OR after
228    * the return type of function declarations.
229    *
230    * Two macros are used within the FreeType source code to define
231    * exported library functions: `FT_EXPORT` and `FT_EXPORT_DEF`.
232    *
233    * - `FT_EXPORT( return_type )`
234    *
235    *   is used in a function declaration, as in
236    *
237    *   ```
238    *     FT_EXPORT( FT_Error )
239    *     FT_Init_FreeType( FT_Library*  alibrary );
240    *   ```
241    *
242    * - `FT_EXPORT_DEF( return_type )`
243    *
244    *   is used in a function definition, as in
245    *
246    *   ```
247    *     FT_EXPORT_DEF( FT_Error )
248    *     FT_Init_FreeType( FT_Library*  alibrary )
249    *     {
250    *       ... some code ...
251    *       return FT_Err_Ok;
252    *     }
253    *   ```
254    *
255    * You can provide your own implementation of `FT_EXPORT` and
256    * `FT_EXPORT_DEF` here if you want.
257    *
258    * To export a variable, use `FT_EXPORT_VAR`.
259    */
260 
261   /* See `freetype/config/compiler_macros.h` for the `FT_EXPORT` definition */
262 #define FT_EXPORT_DEF( x )  FT_FUNCTION_DEFINITION( x )
263 
264   /*
265    * The following macros are needed to compile the library with a
266    * C++ compiler and with 16bit compilers.
267    */
268 
269   /*
270    * This is special.  Within C++, you must specify `extern "C"` for
271    * functions which are used via function pointers, and you also
272    * must do that for structures which contain function pointers to
273    * assure C linkage -- it's not possible to have (local) anonymous
274    * functions which are accessed by (global) function pointers.
275    *
276    *
277    * FT_CALLBACK_DEF is used to _define_ a callback function,
278    * located in the same source code file as the structure that uses
279    * it.  FT_COMPARE_DEF, in addition, ensures the `cdecl` calling
280    * convention on x86, required by the C library function `qsort`.
281    *
282    * FT_BASE_CALLBACK and FT_BASE_CALLBACK_DEF are used to declare
283    * and define a callback function, respectively, in a similar way
284    * as FT_BASE and FT_BASE_DEF work.
285    *
286    * FT_CALLBACK_TABLE is used to _declare_ a constant variable that
287    * contains pointers to callback functions.
288    *
289    * FT_CALLBACK_TABLE_DEF is used to _define_ a constant variable
290    * that contains pointers to callback functions.
291    *
292    *
293    * Some 16bit compilers have to redefine these macros to insert
294    * the infamous `_cdecl` or `__fastcall` declarations.
295    */
296 #ifdef __cplusplus
297 #define FT_CALLBACK_DEF( x )  extern "C"  x
298 #else
299 #define FT_CALLBACK_DEF( x )  static  x
300 #endif
301 
302 #if defined( __i386__ )
303 #define FT_COMPARE_DEF( x )  FT_CALLBACK_DEF( x ) __attribute__(( cdecl ))
304 #elif defined( _M_IX86 )
305 #define FT_COMPARE_DEF( x )  FT_CALLBACK_DEF( x ) __cdecl
306 #else
307 #define FT_COMPARE_DEF( x )  FT_CALLBACK_DEF( x )
308 #endif
309 
310 #define FT_BASE_CALLBACK( x )      FT_FUNCTION_DECLARATION( x )
311 #define FT_BASE_CALLBACK_DEF( x )  FT_FUNCTION_DEFINITION( x )
312 
313 #ifndef FT_CALLBACK_TABLE
314 #ifdef __cplusplus
315 #define FT_CALLBACK_TABLE      extern "C"
316 #define FT_CALLBACK_TABLE_DEF  extern "C"
317 #else
318 #define FT_CALLBACK_TABLE      extern
319 #define FT_CALLBACK_TABLE_DEF  /* nothing */
320 #endif
321 #endif /* FT_CALLBACK_TABLE */
322 
323 FT_END_HEADER
324 
325 #endif  /* INTERNAL_COMPILER_MACROS_H_ */
326