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