Last active
May 5, 2024 15:19
-
-
Save libsteve/fb755eda9312fee2525f2929e923e1c6 to your computer and use it in GitHub Desktop.
A control-flow construct in C for scoped variable declarations that satisfy a follow-up conditional expression.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// let_if.h | |
// | |
// A control-flow construct in C for scoped variable declarations that satisfy | |
// a follow-up conditional expression. | |
// | |
// let_if (<declaration>; <condition>) { | |
// <code-block> | |
// } | |
// | |
// This can be useful as a form of error handling when reading encoded data. | |
// | |
// let_if (fpos_t position; fgetpos(file, &position) == 0) { | |
// let_if (size_t offset; fscanf(file, "%8zx", &offset) == 1) | |
// let_if (int next = fgetc(file); next != EOF && ispunct(next)) | |
// let_if (size_t length; fscanf(file, "%8zx", &length) == 1) { | |
// if (fseek(file, offset, SEEK_CUR) == 0) { | |
// return length; | |
// } | |
// } | |
// fsetpos(file, &position); | |
// } | |
// | |
#if defined(__clang__) | |
# define let_if(...) for (__VA_ARGS__; __BREAK_EXPR) | |
# define let_in(...) for (__VA_ARGS__; 1; __BREAK_EXPR) | |
# define __BREAK_EXPR __extension__({ \ | |
_Pragma("clang diagnostic push") \ | |
_Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ | |
break; 0; \ | |
_Pragma("clang diagnostic pop") \ | |
}) | |
#elif defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1938) | |
# define let_if(...) __LET_IF(__LET_IF_ID(__COUNTER__), __VA_ARGS__) | |
# define let_in(...) __LET_IN(__LET_IN_ID(__COUNTER__), __VA_ARGS__) | |
# define __LET_IF(ID, ...) __LET_ONCE(ID) for (__VA_ARGS__; __BREAK_EXPR) | |
# define __LET_IN(ID, ...) __LET_ONCE(ID) for (__VA_ARGS__; ID; __BREAK_EXPR) | |
# define __LET_IF_ID(COUNTER) __CONCAT(__let_if_,COUNTER) | |
# define __LET_IN_ID(COUNTER) __CONCAT(__let_in_,COUNTER) | |
# define __LET_ONCE(ID) for (int ID = 1; ID; ID = 0) | |
# define __BREAK_EXPR __extension__({ break; 0; }) | |
# ifndef __CONCAT | |
# define __CONCAT(x, y) x ## y | |
# endif | |
#else | |
# error let_if relies on language extensions not available for this compiler. | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment