1 | /* |
2 | Simple DirectMedia Layer |
3 | Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org> |
4 | |
5 | This software is provided 'as-is', without any express or implied |
6 | warranty. In no event will the authors be held liable for any damages |
7 | arising from the use of this software. |
8 | |
9 | Permission is granted to anyone to use this software for any purpose, |
10 | including commercial applications, and to alter it and redistribute it |
11 | freely, subject to the following restrictions: |
12 | |
13 | 1. The origin of this software must not be misrepresented; you must not |
14 | claim that you wrote the original software. If you use this software |
15 | in a product, an acknowledgment in the product documentation would be |
16 | appreciated but is not required. |
17 | 2. Altered source versions must be plainly marked as such, and must not be |
18 | misrepresented as being the original software. |
19 | 3. This notice may not be removed or altered from any source distribution. |
20 | */ |
21 | |
22 | /* WIKI CATEGORY: BeginCode */ |
23 | |
24 | /** |
25 | * # CategoryBeginCode |
26 | * |
27 | * `SDL_begin_code.h` sets things up for C dynamic library function |
28 | * definitions, static inlined functions, and structures aligned at 4-byte |
29 | * alignment. If you don't like ugly C preprocessor code, don't look at this |
30 | * file. :) |
31 | * |
32 | * SDL's headers use this; applications generally should not include this |
33 | * header directly. |
34 | */ |
35 | |
36 | /* This shouldn't be nested -- included it around code only. */ |
37 | #ifdef SDL_begin_code_h |
38 | #error Nested inclusion of SDL_begin_code.h |
39 | #endif |
40 | #define SDL_begin_code_h |
41 | |
42 | #ifdef SDL_WIKI_DOCUMENTATION_SECTION |
43 | |
44 | /** |
45 | * A macro to tag a symbol as deprecated. |
46 | * |
47 | * A function is marked deprecated by adding this macro to its declaration: |
48 | * |
49 | * ```c |
50 | * extern SDL_DEPRECATED int ThisFunctionWasABadIdea(void); |
51 | * ``` |
52 | * |
53 | * Compilers with deprecation support can give a warning when a deprecated |
54 | * function is used. This symbol may be used in SDL's headers, but apps are |
55 | * welcome to use it for their own interfaces as well. |
56 | * |
57 | * SDL, on occasion, might deprecate a function for various reasons. However, |
58 | * SDL never removes symbols before major versions, so deprecated interfaces |
59 | * in SDL3 will remain available until SDL4, where it would be expected an app |
60 | * would have to take steps to migrate anyhow. |
61 | * |
62 | * On compilers without a deprecation mechanism, this is defined to nothing, |
63 | * and using a deprecated function will not generate a warning. |
64 | * |
65 | * \since This macro is available since SDL 3.2.0. |
66 | */ |
67 | #define SDL_DEPRECATED __attribute__((deprecated)) |
68 | |
69 | /** |
70 | * A macro to tag a symbol as a public API. |
71 | * |
72 | * SDL uses this macro for all its public functions. On some targets, it is |
73 | * used to signal to the compiler that this function needs to be exported from |
74 | * a shared library, but it might have other side effects. |
75 | * |
76 | * This symbol is used in SDL's headers, but apps and other libraries are |
77 | * welcome to use it for their own interfaces as well. |
78 | * |
79 | * \since This macro is available since SDL 3.2.0. |
80 | */ |
81 | #define SDL_DECLSPEC __attribute__ ((visibility("default"))) |
82 | |
83 | /** |
84 | * A macro to set a function's calling conventions. |
85 | * |
86 | * SDL uses this macro for all its public functions, and any callbacks it |
87 | * defines. This macro guarantees that calling conventions match between SDL |
88 | * and the app, even if the two were built with different compilers or |
89 | * optimization settings. |
90 | * |
91 | * When writing a callback function, it is very important for it to be |
92 | * correctly tagged with SDLCALL, as mismatched calling conventions can cause |
93 | * strange behaviors and can be difficult to diagnose. Plus, on many |
94 | * platforms, SDLCALL is defined to nothing, so compilers won't be able to |
95 | * warn that the tag is missing. |
96 | * |
97 | * This symbol is used in SDL's headers, but apps and other libraries are |
98 | * welcome to use it for their own interfaces as well. |
99 | * |
100 | * \since This macro is available since SDL 3.2.0. |
101 | */ |
102 | #define SDLCALL __cdecl |
103 | |
104 | /** |
105 | * A macro to request a function be inlined. |
106 | * |
107 | * This is a hint to the compiler to inline a function. The compiler is free |
108 | * to ignore this request. On compilers without inline support, this is |
109 | * defined to nothing. |
110 | * |
111 | * \since This macro is available since SDL 3.2.0. |
112 | */ |
113 | #define SDL_INLINE __inline |
114 | |
115 | /** |
116 | * A macro to demand a function be inlined. |
117 | * |
118 | * This is a command to the compiler to inline a function. SDL uses this macro |
119 | * in its public headers for a handful of simple functions. On compilers |
120 | * without forceinline support, this is defined to `static SDL_INLINE`, which |
121 | * is often good enough. |
122 | * |
123 | * This symbol is used in SDL's headers, but apps and other libraries are |
124 | * welcome to use it for their own interfaces as well. |
125 | * |
126 | * \since This macro is available since SDL 3.2.0. |
127 | */ |
128 | #define SDL_FORCE_INLINE __forceinline |
129 | |
130 | /** |
131 | * A macro to tag a function as never-returning. |
132 | * |
133 | * This is a hint to the compiler that a function does not return. An example |
134 | * of a function like this is the C runtime's exit() function. |
135 | * |
136 | * This hint can lead to code optimizations, and help analyzers understand |
137 | * code flow better. On compilers without noreturn support, this is defined to |
138 | * nothing. |
139 | * |
140 | * This symbol is used in SDL's headers, but apps and other libraries are |
141 | * welcome to use it for their own interfaces as well. |
142 | * |
143 | * \since This macro is available since SDL 3.2.0. |
144 | */ |
145 | #define SDL_NORETURN __attribute__((noreturn)) |
146 | |
147 | /** |
148 | * A macro to tag a function as never-returning (for analysis purposes). |
149 | * |
150 | * This is almost identical to SDL_NORETURN, except functions marked with this |
151 | * _can_ actually return. The difference is that this isn't used for code |
152 | * generation, but rather static analyzers use this information to assume |
153 | * truths about program state and available code paths. Specifically, this tag |
154 | * is useful for writing an assertion mechanism. Indeed, SDL_assert uses this |
155 | * tag behind the scenes. Generally, apps that don't understand the specific |
156 | * use-case for this tag should avoid using it directly. |
157 | * |
158 | * On compilers without analyzer_noreturn support, this is defined to nothing. |
159 | * |
160 | * This symbol is used in SDL's headers, but apps and other libraries are |
161 | * welcome to use it for their own interfaces as well. |
162 | * |
163 | * \since This macro is available since SDL 3.2.0. |
164 | */ |
165 | #define SDL_ANALYZER_NORETURN __attribute__((analyzer_noreturn)) |
166 | |
167 | |
168 | /** |
169 | * A macro to signal that a case statement without a `break` is intentional. |
170 | * |
171 | * C compilers have gotten more aggressive about warning when a switch's |
172 | * `case` block does not end with a `break` or other flow control statement, |
173 | * flowing into the next case's code, as this is a common accident that leads |
174 | * to strange bugs. But sometimes falling through to the next case is the |
175 | * correct and desired behavior. This symbol lets an app communicate this |
176 | * intention to the compiler, so it doesn't generate a warning. |
177 | * |
178 | * It is used like this: |
179 | * |
180 | * ```c |
181 | * switch (x) { |
182 | * case 1: |
183 | * DoSomethingOnlyForOne(); |
184 | * SDL_FALLTHROUGH; // tell the compiler this was intentional. |
185 | * case 2: |
186 | * DoSomethingForOneAndTwo(); |
187 | * break; |
188 | * } |
189 | * ``` |
190 | * |
191 | * \since This macro is available since SDL 3.2.0. |
192 | */ |
193 | #define SDL_FALLTHROUGH [[fallthrough]] |
194 | |
195 | /** |
196 | * A macro to tag a function's return value as critical. |
197 | * |
198 | * This is a hint to the compiler that a function's return value should not be |
199 | * ignored. |
200 | * |
201 | * If an NODISCARD function's return value is thrown away (the function is |
202 | * called as if it returns `void`), the compiler will issue a warning. |
203 | * |
204 | * While it's generally good practice to check return values for errors, often |
205 | * times legitimate programs do not for good reasons. Be careful about what |
206 | * functions are tagged as NODISCARD. It operates best when used on a function |
207 | * that's failure is surprising and catastrophic; a good example would be a |
208 | * program that checks the return values of all its file write function calls |
209 | * but not the call to close the file, which it assumes incorrectly never |
210 | * fails. |
211 | * |
212 | * Function callers that want to throw away a NODISCARD return value can call |
213 | * the function with a `(void)` cast, which informs the compiler the act is |
214 | * intentional. |
215 | * |
216 | * On compilers without nodiscard support, this is defined to nothing. |
217 | * |
218 | * \since This macro is available since SDL 3.2.0. |
219 | */ |
220 | #define SDL_NODISCARD [[nodiscard]] |
221 | |
222 | /** |
223 | * A macro to tag a function as an allocator. |
224 | * |
225 | * This is a hint to the compiler that a function is an allocator, like |
226 | * malloc(), with certain rules. A description of how GCC treats this hint is |
227 | * here: |
228 | * |
229 | * https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-malloc-function-attribute |
230 | * |
231 | * On compilers without allocator tag support, this is defined to nothing. |
232 | * |
233 | * Most apps don't need to, and should not, use this directly. |
234 | * |
235 | * \since This macro is available since SDL 3.2.0. |
236 | */ |
237 | #define SDL_MALLOC __declspec(allocator) __desclspec(restrict) |
238 | |
239 | /** |
240 | * A macro to tag a function as returning a certain allocation. |
241 | * |
242 | * This is a hint to the compiler that a function allocates and returns a |
243 | * specific amount of memory based on one of its arguments. For example, the C |
244 | * runtime's malloc() function could use this macro with an argument of 1 |
245 | * (first argument to malloc is the size of the allocation). |
246 | * |
247 | * On compilers without alloc_size support, this is defined to nothing. |
248 | * |
249 | * Most apps don't need to, and should not, use this directly. |
250 | * |
251 | * \since This macro is available since SDL 3.2.0. |
252 | */ |
253 | #define SDL_ALLOC_SIZE(p) __attribute__((alloc_size(p))) |
254 | |
255 | /** |
256 | * A macro to tag a pointer variable, to help with pointer aliasing. |
257 | * |
258 | * A good explanation of the restrict keyword is here: |
259 | * |
260 | * https://en.wikipedia.org/wiki/Restrict |
261 | * |
262 | * On compilers without restrict support, this is defined to nothing. |
263 | * |
264 | * \since This macro is available since SDL 3.2.0. |
265 | */ |
266 | #define SDL_RESTRICT __restrict__ |
267 | |
268 | /** |
269 | * Check if the compiler supports a given builtin functionality. |
270 | * |
271 | * This allows preprocessor checks for things that otherwise might fail to |
272 | * compile. |
273 | * |
274 | * Supported by virtually all clang versions and more-recent GCCs. Use this |
275 | * instead of checking the clang version if possible. |
276 | * |
277 | * On compilers without has_builtin support, this is defined to 0 (always |
278 | * false). |
279 | * |
280 | * \since This macro is available since SDL 3.2.0. |
281 | */ |
282 | #define SDL_HAS_BUILTIN(x) __has_builtin(x) |
283 | |
284 | /* end of wiki documentation section. */ |
285 | #endif |
286 | |
287 | #ifndef SDL_HAS_BUILTIN |
288 | #ifdef __has_builtin |
289 | #define SDL_HAS_BUILTIN(x) __has_builtin(x) |
290 | #else |
291 | #define SDL_HAS_BUILTIN(x) 0 |
292 | #endif |
293 | #endif |
294 | |
295 | #ifndef SDL_DEPRECATED |
296 | # if defined(__GNUC__) && (__GNUC__ >= 4) /* technically, this arrived in gcc 3.1, but oh well. */ |
297 | # define SDL_DEPRECATED __attribute__((deprecated)) |
298 | # elif defined(_MSC_VER) |
299 | # define SDL_DEPRECATED __declspec(deprecated) |
300 | # else |
301 | # define SDL_DEPRECATED |
302 | # endif |
303 | #endif |
304 | |
305 | #ifndef SDL_UNUSED |
306 | # ifdef __GNUC__ |
307 | # define SDL_UNUSED __attribute__((unused)) |
308 | # else |
309 | # define SDL_UNUSED |
310 | # endif |
311 | #endif |
312 | |
313 | /* Some compilers use a special export keyword */ |
314 | #ifndef SDL_DECLSPEC |
315 | # if defined(SDL_PLATFORM_WINDOWS) |
316 | # ifdef DLL_EXPORT |
317 | # define SDL_DECLSPEC __declspec(dllexport) |
318 | # else |
319 | # define SDL_DECLSPEC |
320 | # endif |
321 | # else |
322 | # if defined(__GNUC__) && __GNUC__ >= 4 |
323 | # define SDL_DECLSPEC __attribute__ ((visibility("default"))) |
324 | # else |
325 | # define SDL_DECLSPEC |
326 | # endif |
327 | # endif |
328 | #endif |
329 | |
330 | /* By default SDL uses the C calling convention */ |
331 | #ifndef SDLCALL |
332 | #if defined(SDL_PLATFORM_WINDOWS) && !defined(__GNUC__) |
333 | #define SDLCALL __cdecl |
334 | #else |
335 | #define SDLCALL |
336 | #endif |
337 | #endif /* SDLCALL */ |
338 | |
339 | /* Force structure packing at 4 byte alignment. |
340 | This is necessary if the header is included in code which has structure |
341 | packing set to an alternate value, say for loading structures from disk. |
342 | The packing is reset to the previous value in SDL_close_code.h |
343 | */ |
344 | #if defined(_MSC_VER) || defined(__MWERKS__) || defined(__BORLANDC__) |
345 | #ifdef _MSC_VER |
346 | #pragma warning(disable: 4103) |
347 | #endif |
348 | #ifdef __clang__ |
349 | #pragma clang diagnostic ignored "-Wpragma-pack" |
350 | #endif |
351 | #ifdef __BORLANDC__ |
352 | #pragma nopackwarning |
353 | #endif |
354 | #ifdef _WIN64 |
355 | /* Use 8-byte alignment on 64-bit architectures, so pointers are aligned */ |
356 | #pragma pack(push,8) |
357 | #else |
358 | #pragma pack(push,4) |
359 | #endif |
360 | #endif /* Compiler needs structure packing set */ |
361 | |
362 | #ifndef SDL_INLINE |
363 | #ifdef __GNUC__ |
364 | #define SDL_INLINE __inline__ |
365 | #elif defined(_MSC_VER) || defined(__BORLANDC__) || \ |
366 | defined(__DMC__) || defined(__SC__) || \ |
367 | defined(__WATCOMC__) || defined(__LCC__) || \ |
368 | defined(__DECC) || defined(__CC_ARM) |
369 | #define SDL_INLINE __inline |
370 | #ifndef __inline__ |
371 | #define __inline__ __inline |
372 | #endif |
373 | #else |
374 | #define SDL_INLINE inline |
375 | #ifndef __inline__ |
376 | #define __inline__ inline |
377 | #endif |
378 | #endif |
379 | #endif /* SDL_INLINE not defined */ |
380 | |
381 | #ifndef SDL_FORCE_INLINE |
382 | #ifdef _MSC_VER |
383 | #define SDL_FORCE_INLINE __forceinline |
384 | #elif ( (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__) ) |
385 | #define SDL_FORCE_INLINE __attribute__((always_inline)) static __inline__ |
386 | #else |
387 | #define SDL_FORCE_INLINE static SDL_INLINE |
388 | #endif |
389 | #endif /* SDL_FORCE_INLINE not defined */ |
390 | |
391 | #ifndef SDL_NORETURN |
392 | #ifdef __GNUC__ |
393 | #define SDL_NORETURN __attribute__((noreturn)) |
394 | #elif defined(_MSC_VER) |
395 | #define SDL_NORETURN __declspec(noreturn) |
396 | #else |
397 | #define SDL_NORETURN |
398 | #endif |
399 | #endif /* SDL_NORETURN not defined */ |
400 | |
401 | #ifdef __clang__ |
402 | #if __has_feature(attribute_analyzer_noreturn) |
403 | #define SDL_ANALYZER_NORETURN __attribute__((analyzer_noreturn)) |
404 | #endif |
405 | #endif |
406 | |
407 | #ifndef SDL_ANALYZER_NORETURN |
408 | #define SDL_ANALYZER_NORETURN |
409 | #endif |
410 | |
411 | /* Apparently this is needed by several Windows compilers */ |
412 | #ifndef __MACH__ |
413 | #ifndef NULL |
414 | #ifdef __cplusplus |
415 | #define NULL 0 |
416 | #else |
417 | #define NULL ((void *)0) |
418 | #endif |
419 | #endif /* NULL */ |
420 | #endif /* ! macOS - breaks precompiled headers */ |
421 | |
422 | #ifndef SDL_FALLTHROUGH |
423 | #if (defined(__cplusplus) && __cplusplus >= 201703L) || \ |
424 | (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202000L) |
425 | #define SDL_FALLTHROUGH [[fallthrough]] |
426 | #else |
427 | #if defined(__has_attribute) && !defined(__SUNPRO_C) && !defined(__SUNPRO_CC) |
428 | #define SDL_HAS_FALLTHROUGH __has_attribute(__fallthrough__) |
429 | #else |
430 | #define SDL_HAS_FALLTHROUGH 0 |
431 | #endif /* __has_attribute */ |
432 | #if SDL_HAS_FALLTHROUGH && \ |
433 | ((defined(__GNUC__) && __GNUC__ >= 7) || \ |
434 | (defined(__clang_major__) && __clang_major__ >= 10)) |
435 | #define SDL_FALLTHROUGH __attribute__((__fallthrough__)) |
436 | #else |
437 | #define SDL_FALLTHROUGH do {} while (0) /* fallthrough */ |
438 | #endif /* SDL_HAS_FALLTHROUGH */ |
439 | #undef SDL_HAS_FALLTHROUGH |
440 | #endif /* C++17 or C2x */ |
441 | #endif /* SDL_FALLTHROUGH not defined */ |
442 | |
443 | #ifndef SDL_NODISCARD |
444 | #if (defined(__cplusplus) && __cplusplus >= 201703L) || \ |
445 | (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L) |
446 | #define SDL_NODISCARD [[nodiscard]] |
447 | #elif ( (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__) ) |
448 | #define SDL_NODISCARD __attribute__((warn_unused_result)) |
449 | #elif defined(_MSC_VER) && (_MSC_VER >= 1700) |
450 | #define SDL_NODISCARD _Check_return_ |
451 | #else |
452 | #define SDL_NODISCARD |
453 | #endif /* C++17 or C23 */ |
454 | #endif /* SDL_NODISCARD not defined */ |
455 | |
456 | #ifndef SDL_MALLOC |
457 | #if defined(__GNUC__) && (__GNUC__ >= 3) |
458 | #define SDL_MALLOC __attribute__((malloc)) |
459 | /** FIXME |
460 | #elif defined(_MSC_VER) |
461 | #define SDL_MALLOC __declspec(allocator) __desclspec(restrict) |
462 | **/ |
463 | #else |
464 | #define SDL_MALLOC |
465 | #endif |
466 | #endif /* SDL_MALLOC not defined */ |
467 | |
468 | #ifndef SDL_ALLOC_SIZE |
469 | #if (defined(__clang__) && __clang_major__ >= 4) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))) |
470 | #define SDL_ALLOC_SIZE(p) __attribute__((alloc_size(p))) |
471 | #elif defined(_MSC_VER) |
472 | #define SDL_ALLOC_SIZE(p) |
473 | #else |
474 | #define SDL_ALLOC_SIZE(p) |
475 | #endif |
476 | #endif /* SDL_ALLOC_SIZE not defined */ |
477 | |
478 | #ifndef SDL_ALLOC_SIZE2 |
479 | #if (defined(__clang__) && __clang_major__ >= 4) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))) |
480 | #define SDL_ALLOC_SIZE2(p1, p2) __attribute__((alloc_size(p1, p2))) |
481 | #elif defined(_MSC_VER) |
482 | #define SDL_ALLOC_SIZE2(p1, p2) |
483 | #else |
484 | #define SDL_ALLOC_SIZE2(p1, p2) |
485 | #endif |
486 | #endif /* SDL_ALLOC_SIZE2 not defined */ |
487 | |