Go to the documentation of this file.
43 #define P00_ROBUST(...) __VA_ARGS__
45 #define P00 P99_FILEID(blk)
47 #define P00_BLK_GEN(BEFORE, COND, ...) for (P00_ROBUST(BEFORE); (COND) && P00; (__VA_ARGS__), P00 = 0)
48 #define P00_BLK_BEFORE(...) for (__VA_ARGS__; P00; P00 = 0)
49 #define P00_BLK_AFTER(...) P00_BLK_BEFAFT(, (__VA_ARGS__))
50 #define P00_BLK_CONDITIONAL(...) for (; (__VA_ARGS__) && P00; P00 = 0)
51 #define P00_BLK_START P00_BLK_BEFORE(_Bool P00 = 1)
52 #define P00_BLK_END P00_BLK_BEFORE()
58 #define P00_BLK_DECL_REC(TYPE, NAME, ...) \
59 P00_BLK_BEFORE(TYPE P99_PASTE2(p00_decl_, NAME) = P00_ROBUST(__VA_ARGS__)) \
60 P00_BLK_BEFAFT(TYPE NAME = P99_PASTE2(p00_decl_, NAME), (void)NAME)
64 #define P00_BLK_DECL(...) \
65 P99_IF_EQ_2(P99_NARG(__VA_ARGS__)) \
66 (P00_BLK_DECL_2(__VA_ARGS__)) \
67 (P00_BLK_DECL_3(__VA_ARGS__))
69 #define P00_BLK_DECL_3(TYPE, NAME, ...) P00_BLK_BEFAFT(TYPE NAME = __VA_ARGS__, (void)NAME)
71 #define P00_BLK_DECL_2(TYPE, NAME) P00_BLK_DECL_3(TYPE, NAME, P99_INIT)
75 #define P00_BLK_DECL_STATIC(TYPE, NAME, ...) \
76 P00_BLK_DECL_STATIC4(TYPE, NAME, P99_UNIQ(p00_static, NAME), P00_ROBUST(__VA_ARGS__))
78 #define P00_BLK_DECL_STATIC4(TYPE, NAME, ID, INIT) \
79 P00_BLK_BEFORE(TYPE* NAME = 0) \
81 static TYPE ID = INIT; \
93 # define P99_MARK(X) ({ __asm__ volatile ("# " P99_STRINGIFY(__LINE__: X)); })
95 # define P99_MARK(X) P99_NOP
103 #define P99_BLK_MARK(X) \
104 P00_BLK_BEFAFT(P99_MARK(P99_PASTE2(X, _bef)), \
105 P99_MARK(P99_PASTE2(X, _end)))
110 #define P00_UNWIND_DOCUMENT \
118 #define P00_INHIBIT(NAME, EXT) P99_PASTE3(p00_inhibit_, NAME, EXT)
130 #define P99_DECLARE_INHIBIT(NAME) enum { P00_INHIBIT(NAME,) = 0 }
137 #define P99_INHIBIT_CHECK(NAME) \
138 switch (P99_STRINGIFY(P00_INHIBIT(NAME,))[P00_INHIBIT(NAME,)]) default:
147 #define P99_INHIBIT(NAME) \
149 for (unsigned const*const P00_INHIBIT(NAME,) = 0; !P00_INHIBIT(NAME,) && P00; P00 = 0)
158 #define P99_ALLOW(NAME) \
160 P00_BLK_DECL(unsigned const, P00_INHIBIT(NAME,), 0)
165 #if defined(P99_CHECK_RETURN) && !defined(P00_DOXYGEN)
166 #define return P99_INHIBIT_CHECK(RETURN) return
178 #define P99_CHECK_RETURN
185 #define P00_BLK_BEFAFT(BEFORE, ...) \
186 P99_INHIBIT(RETURN) \
187 P00_BLK_GEN(P00_ROBUST(BEFORE), true, __VA_ARGS__)
217 #define P99_PROTECTED_BLOCK(BEFORE, AFTER)
219 #define P99_PROTECTED_BLOCK(BEFORE, ...) \
221 P00_BLK_BEFAFT(P00_ROBUST(BEFORE), __VA_ARGS__) \
226 # ifndef P99_SIMPLE_BLOCKS
240 # define P99_SIMPLE_BLOCKS 0
269 #define P99_GUARDED_BLOCK(T, NAME, INITIAL, BEFORE, AFTER)
271 # if !P99_SIMPLE_BLOCKS
275 # define P99_GUARDED_BLOCK(T, NAME, INITIAL, BEFORE, AFTER) \
277 P00_BLK_DECL_REC(T, NAME, P00_ROBUST(INITIAL)) \
278 P99_UNWIND_PROTECT if (0) { P99_PROTECT: AFTER; } else \
279 P00_BLK_BEFAFT(P00_ROBUST(BEFORE), AFTER) \
283 # define P99_GUARDED_BLOCK(T, NAME, INITIAL, BEFORE, AFTER) \
285 P00_BLK_DECL(T, NAME, P00_ROBUST(INITIAL)) \
286 P00_BLK_BEFAFT(P00_ROBUST(BEFORE), AFTER) \
297 #define P99_NOP ((void)0)
326 #if p99_has_feature(statement_expression)
327 # define P99_PREFER(...) \
328 for (_Bool p00 = 1; p00 && p99_extension ({ { __VA_ARGS__ } 1; }); p00 = 0)
330 # define P99_PREFER(...) if (1) { __VA_ARGS__ } else
360 #define P99_AVOID for (;0;)
387 #define P99_BLOCK(...) P99_PREFER(__VA_ARGS__) P99_NOP
424 #define P99_XCASE P99_AVOID case
429 #define P99_XDEFAULT P99_AVOID default
431 typedef enum p00_uncase_enum {
436 #define P00_UNCASE switch((p00_uncase_enum)0) P99_XCASE 0
445 #define P99_UNCASE P00_UNCASE :
472 #define P99_HANDLE_ERRNO \
474 P00_BLK_DECL(int const, p99_errno, errno) \
475 switch (P99_UNLIKELY(!!p99_errno)) case true: \
476 P00_BLK_AFTER(errno = 0) \
477 switch (p99_errno) case 0:
490 p00_unwind_bottom = 0,
506 #define p99_unwind_code ((int)(p00_unwind_top[0].p00_code))
511 struct p00_jmp_buf0 {
512 p00_jmp_buf0 * p99_lifo;
513 bool volatile p00_returning;
514 int volatile p00_code;
518 #define P00_JMP_BUF0_INITIALIZER { .p00_returning = 0 }
520 typedef p00_jmp_buf0 p00_jmp_buf[1];
522 #define P00_JMP_BUF_INITIALIZER { [0] = P00_JMP_BUF0_INITIALIZER }
526 struct p00_inhibitor {
532 void p00_longjmp(p00_jmp_buf0 * p00_buf,
int p00_val) {
533 p00_buf->p00_code = p00_val;
613 #define P99_UNWIND_PROTECT \
619 P00_BLK_BEFAFT(auto p00_jmp_buf p00_unwind_return = P00_ROBUST(P00_JMP_BUF_INITIALIZER), \
623 p00_unwind_return[0].p00_returning ? p00_longjmp(p00_unwind_return, 1) : P99_NOP) \
628 P00_BLK_DECL_REC(register p00_jmp_buf *const, p00_unwind_bottom, \
629 (p00_unwind_bottom ? p00_unwind_bottom : &p00_unwind_return)) \
631 P00_BLK_DECL(register p00_inhibitor const, p00_unwind_return, { INT_MAX }) \
633 P00_BLK_DECL(auto _Bool volatile, p00_unw) \
636 P00_BLK_BEFAFT(auto int volatile p00_code = 0, \
647 ? P99_UNWIND(p00_code < 0 ? p00_code : p00_code - 1) \
651 P00_BLK_DECL_REC(register unsigned const, p99_unwind_level, p99_unwind_level + 1) \
652 P00_BLK_DECL(p00_jmp_buf0*, p00_unwind_prev, p00_unwind_top) \
654 P00_BLK_DECL(auto p00_jmp_buf, p00_unwind_top, P00_JMP_BUF_INITIALIZER) \
658 switch (!setjmp(p00_unwind_top[0].p00_buf)) case 1:
661 void p00_unwind(
void* p00_top,
unsigned p00_level,
int p00_cond) {
662 if (p00_level && p00_cond && p00_top) p00_longjmp(p00_top, p00_cond);
684 #define P99_UNWIND(X) p00_unwind(p00_unwind_top, p99_unwind_level, (X))
711 #define P99_UNWIND_RETURN \
714 switch (!!p00_unwind_bottom) \
720 if (!setjmp(p00_unwind_bottom[0]->p00_buf)) { \
722 p00_unwind_bottom[0]->p00_returning = 1; \
723 P99_UNWIND(-p99_unwind_return); \
724 } else case 0: P99_ALLOW(RETURN) return
743 #define P99_PROTECT \
744 P99_DECLARE_INHIBIT(RETURN); \
747 p00_code = p00_unwind_top[0].p00_code; \
748 p00_unw = !!p00_code; \
756 #define P99_BLOCK_DOCUMENT \
766 P00_DOCUMENT_MULTIPLE_ARGUMENT(P99_INVARIANT, 0)
768 #define P99_INVARIANT(EXPR) \
769 P99_PROTECTED_BLOCK(assert((EXPR) && "failed at beginning of block"), assert((EXPR) && "failed at end of block"))
#define P99_BLOCK_DOCUMENT
Add some default documentation and links to the following block macro.
#define noreturn
Declare a function that doesn't return to the caller.
#define p99_inline
Try to force a function always to be inlined.
#define P99_GUARDED_BLOCK(T, NAME, INITIAL, BEFORE, AFTER)
A meta-macro to protect a dependent block or statement by a guard variable NAME of type T.
#define P99_DECLARE_INHIBIT(NAME)
Declare a feature NAME that can be inhibited or allowed at compile time in certain parts of code.
#define P99_DECLARE_STRUCT(NAME)
forward declaration of a struct NAME
@ p99_unwind_level
The level of nesting P99_UNWIND_PROTECT.
#define longjmp(...)
Default arguments for C99 function longjmp
#define P99_IF_COMPILER(COMP,...)
Issue the pragma that is given as a supplementary argument iff the actual compiler is COMP.
Macros handling integer types and initialization.