Skip to content

Instantly share code, notes, and snippets.

@stevebrun
Last active May 5, 2024 15:19
Show Gist options
  • Save stevebrun/fb755eda9312fee2525f2929e923e1c6 to your computer and use it in GitHub Desktop.
Save stevebrun/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.
//
// 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