CX Framework
Cross-platform C utility framework
Loading...
Searching...
No Matches
block.h
Go to the documentation of this file.
1#pragma once
2
5
57
58// Block wrapping using complex for statements
59// Inspired by P99 preprocessor macros, modified (in some cases heavily)
60// to fit with CX design philosophy.
61// https://gustedt.gitlabpages.inria.fr/p99/p99-html/
62
63#include <cx/stype/stype.h>
64#include <cx/platform/base.h>
66
67// -------------------- Compile-Time Feature Inhibition --------------------
68
81
82#define _inhibit_name(name) _inhibit_##name
83
89#define inhibitDeclare(name) enum { _inhibit_name(name) = 0 }
90
101#if !defined(_MSC_VER) || _MSC_VER > 1930
102#define inhibitCheck(name) switch(tokstring(_inhibit_name(name))[_inhibit_name(name)]) default:
103#else
104#define inhibitCheck(name)
105#endif
106
107#define _inhibitDisallow(name) _blkCond(const int * const _inhibit_name(name) = 0, !_inhibit_name(name))
108
125#define inhibitDisallow(name) _blkStart _inhibitDisallow(name)
126
127#define _inhibitAllow(name) _blkCond(const int _inhibit_name(name) = 0, !_inhibit_name(name))
128
137#define inhibitAllow(name) _blkStart _inhibitAllow(name)
138
140
141// The "RETURN" feature is used internally for correctness checks
142
143// If this is being compiled in debug/dev mode, redefine "return" to check it for correctness
144#if DEBUG_LEVEL >= 1 && !defined(_PREFAST_)
145inhibitDeclare(RETURN);
146#define _inhibitReturn _inhibitDisallow(RETURN)
147#define _allowReturn _inhibitAllow(RETURN)
148#define return inhibitCheck(RETURN) return
149#else
150#define _inhibitReturn _blkStart
151#define _allowReturn _blkStart
152#endif
153
154// -------------------- Block Wrapping Macros --------------------
155
156#define _BLK_VAR _block_done
157
158// Internal building blocks (no pun intended)
159
160#define _blkDef(before) for (tokeval(before); _BLK_VAR; _BLK_VAR = 0)
161#define _blkCond(before, cond) for (tokeval(before); (cond) && _BLK_VAR; _BLK_VAR = 0)
162#define _blkFull(before, cond, ...) for (tokeval(before); (cond) && _BLK_VAR; (__VA_ARGS__), _BLK_VAR = 0)
163
164// _blkStart should be the first token used when building a structure that uses blocks.
165// It declares the marker variable that is used to ensure the various for loop abuse only executes once.
166#define _blkStart _blkDef(bool _BLK_VAR = 1)
167#define _blkBefore(...) for (tokeval(__VA_ARGS__); _BLK_VAR; _BLK_VAR = 0)
168#define _blkBeforeAfter(before, ...) _inhibitReturn _blkFull(tokeval(before), true, __VA_ARGS__)
169#define _blkAfter(...) _blkBeforeAfter(, (__VA_ARGS__))
170// _blkEnd is used as an inner loop around a user-provided block to swallow 'break' so it
171// doesn't interrupt control flow.
172#define _blkEnd _blkBefore()
173
174// Special helper for declaring a scoped variable that can refer to a variable in the outer scope with
175// the same name. It does this by using a temporary variable with a different name.
176#define _blkDefRecursive(type, name, ...) \
177 _blkDef(type tokcat2(_block_decl_, name) = tokeval(__VA_ARGS__)) \
178 _blkCond(type name = tokcat2(_block_decl_, name), ((void)name, true))
179
225#define blkWrap(before, ...) _blkStart _blkBeforeAfter(tokeval(before), __VA_ARGS__) _blkEnd
226
Compiler and platform detection macros.
#define inhibitDeclare(name)
Definition block.h:89
Runtime type system and type descriptor infrastructure.
Token pasting and stringification macros.