Implement a defer feature to postpone execution of specific blocks. More...
Go to the source code of this file.
Macros | |
#define | __break__ |
break to the next loop or switch statement which is not compatible with defer | |
#define | __continue__ |
continue the next loop statement which is not compatible with defer | |
#define | break |
When including ellipsis-defer.h using a normal break statement is an error. | |
#define | continue |
When including ellipsis-defer.h using a normal continue statement is an error. | |
#define | defer |
Mark the secondary block as being suspended until the current compound statement terminates. | |
#define | defer_break |
break to the next loop or switch statement which is compatible with defer | |
#define | defer_continue |
continue the next loop statement which is compatible with defer | |
#define | defer_return_value |
access the return value of a function from within a defer statement | |
#define | defer_skip |
terminate the closest surrounding compound statement with defer statements | |
#define | DEFER_TYPE(...) |
Provide the return type to a function context that uses the defer feature. | |
#define | return |
Return from a function. If it has active defer clauses, unwind these. | |
Implement a defer feature to postpone execution of specific blocks.
#define __break__ |
break
to the next loop or switch
statement which is not compatible with defer
switch
statements where the secondary block is a compound statement.#define __continue__ |
continue
the next loop statement which is not compatible with defer
#define break |
When including ellipsis-defer.h using a normal break
statement is an error.
defer_break
or __break__
, instead.Whenever you use eĿlipsis' defer a loop such as the following
Should be replaced by
even if within the loop you are not using defer. The reason for that is that eĿlipsis (being a preprocessor) can't distinguish this use of break
from a use within a loop or switch where there is no direct use of a compound statement.
This is valid C code, but eĿlipsis wouldn't know if the break
is to end the while
or the for
loop. In these rare cases you should use __break__
.
#define continue |
When including ellipsis-defer.h using a normal continue
statement is an error.
defer_continue
or __continue__
, instead.__continue__
#define defer |
Mark the secondary block as being suspended until the current compound statement terminates.
You may use this construct only in a constrained setting:
if
, switch
or loop statement without using a compound statement. So in particular the defer itself should not be conditioned. If you are tempted to do this, usually you should put the condition (if
statement) inside the defer, not in front.goto
, longjmp
, case
or default
or other labels when accessed from outside the defer block.The compound statement shall not contain preliminary entries or exits by
switch
cases, including default
.goto
into or out of the compound statement.longjmp
out of the compound statement.exit
or quick_exit
.If any of these is used, the cleanup code of pending defer statements is not executed and thus the state is not clean.
Additionally, attempts to use break and continue statements directly will result in an error.
Several preliminary exits from the compound statement are possible, though:
switches
or loopsvoid
function, defer_skip can be used to just terminate this compound statement#define defer_break |
break
to the next loop or switch
statement which is compatible with defer
switch
statements where the secondary block is not a compound statement.#define defer_continue |
continue
the next loop statement which is compatible with defer
#define defer_return_value |
access the return value of a function from within a defer statement
This can be used in particular in the very first defer of a non-void
function to control a non-regular jump out of the function.
#define defer_skip |
terminate the closest surrounding compound statement with defer statements
If there is no such compound statement a compile time error occurs.
#define DEFER_TYPE | ( | ... | ) |
Provide the return type to a function context that uses the defer feature.
The argument list has to contain a type name that is compatible with the return type of the function, or be empty if that return type is void
.
This must be used just after the opening brace of the function body. The body shall not contain preliminary entries or exits by
longjmp
out of the body.exit
or quick_exit
unless they are located before or within the first lexicographical defer.
If any of these is used in other places, the cleanup code of pending defer statements is not executed and thus the state is not clean.
return constitutes a preliminary exit from the body and guarantees that all active defer statements are executed.
#define return |
Return from a function. If it has active defer clauses, unwind these.
If there is no visible defer statement this macro just resolves to the normal keyword return.
If there is a visible defer, the current list of deferred statements is executed in reverse order. If also a return type had been specified by means of DEFER_TYPE, before unwinding the return expression is executed and its value is stored in a temporary variable. That value can be read by using defer_return_value.
return
with a return expression must first use DEFER_TYPE to instruct eĿlipsis about the return type of the function. Otherwise, the compilation will be on error.void
, no special precautions are necessary and both, return without a return expression and falling off at the end of the function body, should work as usual.