WinTer 0.1.1
Windows Terminal Emulator
Loading...
Searching...
No Matches
base_macros.h
Go to the documentation of this file.
1
16
17#ifndef BASE_MACROS_H
18#define BASE_MACROS_H
19
20#if defined(_WIN32)
21# ifndef WIN32_LEAN_AND_MEAN
23# define WIN32_LEAN_AND_MEAN
24# endif
25// Note: We don't include <windows.h> here to prevent namespace pollution.
26// Include it manually in the specific .c files that need it.
27#elif defined(__linux__) || (defined(__APPLE__) && defined(__MACH__))
29# include <unistd.h>
30#endif
31
42
43#if defined(__clang__)
45# define COMPILER_CLANG 1
47# define COMPILER_NAME "Clang"
48#elif defined(__GNUC__)
50# define COMPILER_GCC 1
52# define COMPILER_NAME "GCC"
53#elif defined(_MSC_VER)
55# define COMPILER_MSVC 1
57# define COMPILER_NAME "MSVC"
58#else
59# error "Compiler not supported"
60#endif
61
62#if defined(_WIN32)
64# define OS_WINDOWS 1
66# define OS_NAME "Windows"
67#elif defined(__linux__)
69# define OS_LINUX 1
71# define OS_NAME "Linux"
72#elif defined(__APPLE__) && defined(__MACH__)
74# define OS_MAC 1
76# define OS_NAME "macOS"
77#else
78# error "Operating system not supported"
79#endif
80
81#if defined(_M_X64) || defined(__x86_64__)
83# define ARCH_X64 1
85# define ARCH_NAME "x86_64"
86#elif defined(_M_IX86) || defined(__i386__)
88# define ARCH_X86 1
90# define ARCH_NAME "x86"
91#elif defined(_M_ARM64) || defined(__aarch64__)
93# define ARCH_ARM64 1
95# define ARCH_NAME "ARM64"
96#elif defined(_M_ARM) || defined(__arm__)
98# define ARCH_ARM 1
100# define ARCH_NAME "ARM"
101#else
102# error "Architecture not supported"
103#endif
104
105#if defined(NDEBUG)
107# define BUILD_RELEASE 1
109# define BUILD_NAME "Release"
110#else
112# define BUILD_DEBUG 1
114# define BUILD_NAME "Debug"
115#endif
116
117#if (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || defined(_M_IX86) || \
118 defined(_M_X64) || defined(__i386__) || defined(__x86_64__) || defined(_M_ARM) || \
119 defined(_M_ARM64)
121# define ENDIAN_LITTLE 1
123# define ENDIAN_NAME "Little Endian"
124#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) || defined(__BIG_ENDIAN__)
126# define ENDIAN_BIG 1
128# define ENDIAN_NAME "Big Endian"
129#else
130# error "Could not determine endianness"
131#endif
132
133#if defined(__STDC_VERSION__)
134# if __STDC_VERSION__ >= 202311L
136# define C_STANDARD 23
138# define C_STANDARD_NAME "C23"
139# elif __STDC_VERSION__ >= 201710L
140# define C_STANDARD 17
141# define C_STANDARD_NAME "C17"
142# elif __STDC_VERSION__ >= 201112L
143# define C_STANDARD 11
144# define C_STANDARD_NAME "C11"
145# elif __STDC_VERSION__ >= 199901L
146# define C_STANDARD 99
147# define C_STANDARD_NAME "C99"
148# else
149# define C_STANDARD 89
150# define C_STANDARD_NAME "C89"
151# endif
152#else
154# define C_STANDARD 89
156# define C_STANDARD_NAME "C89/Default"
157#endif
158 // end context_detection
160
161#include <stddef.h>
162#include <stdint.h>
163#include <stdio.h>
164#include <string.h>
165
171
173#define INTERNAL static
174
176#define EXTERNAL extern
177
178#if defined(__GNUC__) || defined(__clang__)
180# define API_EXPORT __attribute__((visibility("default")))
182# define API_LOCAL __attribute__((visibility("hidden")))
183#elif defined(_MSC_VER)
185# define API_EXPORT __declspec(dllexport)
187# define API_LOCAL
188#else
190# define API_EXPORT
192# define API_LOCAL
193#endif
194
195#ifdef __cplusplus
197# define C_LINKAGE_BEGIN extern "C" {
199# define C_LINKAGE_END }
200#else
202# define C_LINKAGE_BEGIN
204# define C_LINKAGE_END
205#endif
207
214
216#define STRINGIFY_DETAIL(x) #x
222#define STRINGIFY(x) STRINGIFY_DETAIL(x)
223
225#define GLUE_DETAIL(x, y) x##y
231#define GLUE(x, y) GLUE_DETAIL(x, y)
232
238#define INT_FROM_PTR(ptr) ((uintptr_t)(ptr))
239
246#define PTR_FROM_INT(type, val) ((type *)(uintptr_t)(val))
247
254#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
255
256#if defined(__GNUC__) || defined(__clang__) || \
257 (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L)
258
259# if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L
260# define _TYPEOF(x) typeof(x)
261# else
262# define _TYPEOF(x) __typeof__(x)
263# endif
264
268# define MIN(a, b) \
269 ({ \
270 _TYPEOF(a) _a = (a); \
271 _TYPEOF(b) _b = (b); \
272 _a < _b ? _a : _b; \
273 })
274
278# define MAX(a, b) \
279 ({ \
280 _TYPEOF(a) _a = (a); \
281 _TYPEOF(b) _b = (b); \
282 _a > _b ? _a : _b; \
283 })
284
288# define CLAMP(val, min, max) \
289 ({ \
290 _TYPEOF(val) _v = (val); \
291 _TYPEOF(min) _mn = (min); \
292 _TYPEOF(max) _mx = (max); \
293 (_v < _mn) ? _mn : ((_v > _mx) ? _mx : _v); \
294 })
295
296#else
297// Fallbacks for standard C89/C11 (MSVC)
299# define MIN(a, b) (((a) < (b)) ? (a) : (b))
301# define MAX(a, b) (((a) > (b)) ? (a) : (b))
303# define CLAMP(val, min, max) (((val) < (min)) ? (min) : ((val) > (max)) ? (max) : (val))
304#endif
305
312#define SWAP(type, a, b) \
313 do { \
314 type _tmp = (a); \
315 (a) = (b); \
316 (b) = _tmp; \
317 } while (0)
318
319
325
332#define ALIGN_UP_POW2(x, p) (((x) + (p) - 1) & ~((p) - 1))
333
340#define ALIGN_DOWN_POW2(x, p) ((x) & ~((p) - 1))
341
347#define IS_POW2_OR_ZERO(x) (((x) & ((x) - 1)) == 0)
349
355
357#define MEM_ZERO(ptr, size) memset((ptr), 0, (size))
358
363#define MEM_ZERO_STRUCT(ptr) MEM_ZERO((ptr), sizeof(*(ptr)))
364
369#define MEM_ZERO_ARRAY(arr) MEM_ZERO((arr), sizeof(arr))
370
372#define MEM_COPY(dst, src, size) memmove((dst), (src), (size))
373
380#define MEM_COPY_STRUCT(dst, src) MEM_COPY((dst), (src), MIN(sizeof(*(dst)), sizeof(*(src))))
381
388#define MEM_COPY_ARRAY(dst, src) MEM_COPY((dst), (src), MIN(sizeof(dst), sizeof(src)))
390
403
412#define DLL_PUSH_BACK_NP(f, l, n, next, prev) \
413 ((f) == 0 ? ((f) = (l) = (n), (n)->next = (n)->prev = 0) \
414 : ((n)->prev = (l), (l)->next = (n), (l) = (n), (n)->next = 0))
415
435#define DLL_PUSH_BACK(f, l, n) DLL_PUSH_BACK_NP(f, l, n, next, prev)
436
446#define DLL_PUSH_FRONT(f, l, n) DLL_PUSH_BACK_NP(l, f, n, prev, next)
447
456#define DLL_REMOVE_NP(f, l, n, next, prev) \
457 ((f) == (n) ? ((f) == (l) ? ((f) = (l) = (0)) : ((f) = (f)->next, (f)->prev = 0)) \
458 : (l) == (n) ? ((l) = (l)->prev, (l)->next = 0) \
459 : ((n)->next->prev = (n)->prev, (n)->prev->next = (n)->next))
460
471#define DLL_REMOVE(f, l, n) DLL_REMOVE_NP(f, l, n, next, prev)
472
480#define SLL_QUEUE_PUSH_N(f, l, n, next) \
481 (((f) == 0 ? (f) = (l) = (n) : ((l)->next = (n), (l) = (n))), (n)->next = 0)
482
492#define SLL_QUEUE_PUSH(f, l, n) SLL_QUEUE_PUSH_N(f, l, n, next)
493
500#define SLL_STACK_PUSH_N(f, n, next) ((n)->next = (f), (f) = (n))
501
510#define SLL_STACK_PUSH(f, n) SLL_STACK_PUSH_N(f, n, next)
511
517#define SLL_STACK_POP_N(f, next) ((f) == 0 ? 0 : ((f) = (f)->next))
518
527#define SLL_STACK_POP(f) SLL_STACK_POP_N(f, next)
529
535
553INTERNAL inline void
555{
556 printf("Compilation Context:\n");
557 printf(" - Compiler: " COMPILER_NAME "\n");
558 printf(" - OS: " OS_NAME "\n");
559 printf(" - Architecture: " ARCH_NAME "\n");
560 printf(" - Endianness: " ENDIAN_NAME "\n");
561 printf(" - Build: " BUILD_NAME "\n");
562 printf(" - C Standard: " C_STANDARD_NAME "\n");
563}
564
565#if COMPILER_MSVC
567# define debug_break() __debugbreak()
568#elif COMPILER_GCC || COMPILER_CLANG
570# define debug_break() __builtin_trap()
571#else
573# define debug_break() (*(volatile int *)0 = 0)
574#endif
575
576#if BUILD_DEBUG
581# define ASSERT(expr) \
582 do { \
583 if (!(expr)) { \
584 fputs("Assertion failed: " #expr "\n", stderr); \
585 fputs("File: " __FILE__ "\n", stderr); \
586 fputs("Line: " STRINGIFY(__LINE__) "\n", stderr); \
587 debug_break(); \
588 } \
589 } while (0)
590
595# define ASSERT_NOT_NULL(ptr) \
596 do { \
597 if ((ptr) == NULL) { \
598 fputs("Assertion failed: " #ptr " is NULL\n", stderr); \
599 fputs("File: " __FILE__ "\n", stderr); \
600 fputs("Line: " STRINGIFY(__LINE__) "\n", stderr); \
601 debug_break(); \
602 } \
603 } while (0)
604#else
605// Compile assertions out completely in Release builds for zero overhead
606# define ASSERT(expr) ((void)0)
607# define ASSERT_NOT_NULL(ptr) ((void)0)
608#endif
610
611#endif // BASE_MACROS_H
#define OS_NAME
Human-readable string name of the operating system.
Definition base_macros.h:66
#define BUILD_NAME
Human-readable string name of the build configuration.
#define C_STANDARD_NAME
Human-readable string of the detected C standard.
static void print_context_info(void)
Prints OS, architecture, compiler, endianness, build, and C standard to stdout.
#define INTERNAL
Marks a function or variable as strictly internal to its translation unit (static).