stmt.h

Statement chaining.

This module exports a bunch of so-called statement chaining macros: they expect a statement right after their invocation, and moreover, an invocation of such a macro with a statement afterwards altogether form a single statement.

How can this be helpful? Imagine you are writing a macro with the following syntax:

MY_MACRO(...) { bla bla bla }

Then MY_MACRO must expand to a statement prefix, i.e., something that expects a statement after itself. One possible solution is to make MY_MACRO expand to a sequence of statement chaining macros like this:

#define MY_MACRO(...) \
    ML99_INTRODUCE_VAR_TO_STMT(int x = 5) \
        ML99_CHAIN_EXPR_STMT(printf("%d\n", x)) \
            // and so on...

Here ML99_INTRODUCE_VAR_TO_STMT accepts the statement formed by ML99_CHAIN_EXPR_STMT, which, in turn, accepts the next statement and so on, until a caller of MY_MACRO specifies the final statement, thus completing the chain.

See also

https://www.chiark.greenend.org.uk/~sgtatham/mp/ for a more involved explanation.

Defines

ML99_INTRODUCE_VAR_TO_STMT(...)

A statement chaining macro that introduces several variable definitions to a statement right after its invocation.

Variable definitions must be specified as in the first clause of the for-loop.

Top-level break/continue inside a user-provided statement are prohibited.

Example

#include <metalang99/stmt.h>

for (int i = 0; i < 10; i++)
    ML99_INTRODUCE_VAR_TO_STMT(double x = 5.0, y = 7.0)
        if (i % 2 == 0)
            printf("i = %d, x = %f, y = %f\n", i, x, y);

ML99_INTRODUCE_NON_NULL_PTR_TO_STMT(ty, name, init)

The same as ML99_INTRODUCE_VAR_TO_STMT but deals with a single non-NULL pointer.

In comparison with ML99_INTRODUCE_VAR_TO_STMT, this macro generates a little less code. It introduces a pointer to ty identified by name and initialised to init.

Top-level break/continue inside a user-provided statement are prohibited.

Example

#include <metalang99/stmt.h>

double x = 5.0, y = 7.0;

for (int i = 0; i < 10; i++)
    ML99_INTRODUCE_NON_NULL_PTR_TO_STMT(double, x_ptr, &x)
        ML99_INTRODUCE_NON_NULL_PTR_TO_STMT(double, y_ptr, &y)
            printf("i = %d, x = %f, y = %f\n", i, *x_ptr, *y_ptr);

Note

Unlike ML99_INTRODUCE_VAR_TO_STMT, the generated pointer is guaranteed to be used at least once, meaning that you do not need to suppress the unused variable warning.

Note

init is guaranteed to be executed only once.

ML99_CHAIN_EXPR_STMT(expr)

A statement chaining macro that executes an expression statement derived from expr right before the next statement.

Top-level break/continue inside a user-provided statement are prohibited.

Example

#include <metalang99/stmt.h>

int x;

for(;;)
    ML99_CHAIN_EXPR_STMT(x = 5)
        ML99_CHAIN_EXPR_STMT(printf("%d\n", x))
            puts("abc");

ML99_CHAIN_EXPR_STMT_AFTER(expr)

The same as ML99_CHAIN_EXPR_STMT but executes expr after the next statement.

ML99_SUPPRESS_UNUSED_BEFORE_STMT(expr)

A statement chaining macro that suppresses the “unused X” warning right before a statement after its invocation.

Top-level break/continue inside a user-provided statement are prohibited.

Example

#include <metalang99/stmt.h>

int x, y;

for(;;)
    ML99_SUPPRESS_UNUSED_BEFORE_STMT(x)
        ML99_SUPPRESS_UNUSED_BEFORE_STMT(y)
            puts("abc");

Deprecated:

Use ML99_CHAIN_EXPR_STMT((void)expr) instead.