eĿlipsis
a language independent preprocessor
 
Loading...
Searching...
No Matches
ellipsis-defer.h File Reference

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.
 

Detailed Description

Implement a defer feature to postpone execution of specific blocks.

See also
Defer: a lexical extension of the C grammar

Macro Definition Documentation

◆ __break__

#define __break__

break to the next loop or switch statement which is not compatible with defer

Warning
Don't use this from within loop or switch statements where the secondary block is a compound statement.
See also
Defer: a lexical extension of the C grammar
break
defer

◆ __continue__

#define __continue__

continue the next loop statement which is not compatible with defer

Warning
Don't use this from within loop statements where the secondary block is a compound statement.
See also
Defer: a lexical extension of the C grammar
continue
defer

◆ break

#define break

When including ellipsis-defer.h using a normal break statement is an error.

Warning
Don't use this directly whenever you are including the defer feature. Use defer_break or __break__, instead.

Whenever you use eĿlipsis' defer a loop such as the following

while (something) {
...
if (somelse) break;
...
}

Should be replaced by

while (something) {
...
if (somelse) defer_break;
...
}
#define defer_break
break to the next loop or switch statement which is compatible with defer
Definition ellipsis-defer.h:328

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.

while (something) {
...
size_t counter;
for (counter; counter < maximum; counter++) if (somelse) break;
...
}

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__.

while (something) {
...
size_t counter;
for (counter; counter < maximum; counter++) if (somelse) __break__;
...
}
#define __break__
break to the next loop or switch statement which is not compatible with defer
Definition ellipsis-defer.h:333
See also
Defer: a lexical extension of the C grammar
defer_break
__break__
defer

◆ continue

#define continue

When including ellipsis-defer.h using a normal continue statement is an error.

Warning
Don't use this directly whenever you are including the defer feature. Use defer_continue or __continue__, instead.
See also
break for a reasoning why you can't use these statements directly
Defer: a lexical extension of the C grammar
defer_continue
__continue__
defer

◆ defer

#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:

  • It must be placed into a compound statement. That compound statement limits the validity of the defer construct.
  • It must not be hidden inside a 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.
  • There must be no jumps into, out of or across a defer statement. Jumps here are the most general, no goto, longjmp, case or default or other labels when accessed from outside the defer block.
  • The secondary block must be valid in place, only that it is guaranteed to be executed at the very end of the guarded function body or block, respectively.
  • If a compound statement contains several defer statements, these are then executed in the inverse lexicographical order.
  • If a compound statement terminates before a specific defer has been met, the depending secondary block is not executed at all.

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:

  • return from the surrounding function context
  • defer_break for surrounding switches or loops
  • defer_continue for surrounding loops
  • If the top-most compound statement of a non-void function, defer_skip can be used to just terminate this compound statement
See also
Defer: a lexical extension of the C grammar
DEFER_TYPE

◆ defer_break

#define defer_break

break to the next loop or switch statement which is compatible with defer

Warning
Don't use this from within loop or switch statements where the secondary block is not a compound statement.
See also
Defer: a lexical extension of the C grammar
break
defer

◆ defer_continue

#define defer_continue

continue the next loop statement which is compatible with defer

Warning
Don't use this from within loop statements where the secondary block is not a compound statement.
See also
Defer: a lexical extension of the C grammar
continue
defer

◆ defer_return_value

#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.

Warning
This can obviously only be used after the return value has been set, that is after a return statement has been executed. The only points where this is accessible are during deferred statements that are executed after such a return. A good static analyzer should always warn you of possible code paths that try to use this value before it exists.
See also
Defer: a lexical extension of the C grammar
DEFER_TYPE

◆ defer_skip

#define defer_skip

terminate the closest surrounding compound statement with defer statements

If there is no such compound statement a compile time error occurs.

See also
Defer: a lexical extension of the C grammar

◆ DEFER_TYPE

#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.

See also
Defer: a lexical extension of the C grammar

◆ return

#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.

Warning
If defer is included in the unit, using 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.
Remarks
If the function has type 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.
See also
Defer: a lexical extension of the C grammar
DEFER_TYPE
defer_return_value