Skip to content

Variadic macros, countof()

Although WCPL macros, having a completely different nature from C macros (expression-based vs. token-based), are limited compared to their C counterparts, some of advanced features of C macros are supported in a form that allows for interoperability. One such feature is variadic macros, i.e. macros accepting variable number of arguments.

WCPL implementation of variadic macros is also expression-based. Parameterized macro can have ... (ellipsis) as its last parameter; use of such a macro must provide at least as many parameters as there are non-ellipsis parameters in the parameter list. Any number of additional (“overflow”) parameters can be supplied in macro use; they will be available for substitution in the body of the macro (the replacement list, in C terms).

A parameterized macro with ... as the last parameter is said to bind the ... name to the list of actual parameters remaining after all non-ellipsis parameters are assigned. If ... is bound by the macro, its use in the macro body refers to “overflow” macro parameters. If ... is not bound by the macro, use of ... in macro body refers to outside binding of ..., e.g. its use as the ellipsis parameter of a function.

In the body of the variadic macro, ... can be used in any form that looks like a function call, in any argument position, and any number of times. All such uses are replaced by actual “overflow” macro parameter expressions.

C99-like __VA_ARGS__ name can be used as an alias for ... in the body of a variadic macro. This allows for writing of some variadic macros that will work the same way in WCPL and in C99, e.g.:

#define debug(msg, ...) (fprintf(stderr, msg, __VA_ARGS__))

In WCPL, one can also use ... in the body directly:

#define debug(msg, ...) (fprintf(stderr, msg, ...)) /* WCPL only */ 

Since in WCPL replacement is done on the expression level, no special comma-related hacks are needed, so __VA_OPT__ is not supported.

There is also a place for countof(...) in WCPL variadic macro: as one would expect, it is replaced by the count of “overflow” arguments in macro use:

extern struct list *make_list(size_t cnt, ...);
#define list(...) (make_list(countof(...), ...)) /* WCPL only */

/* list(10, 20, 30) expands to make_list(3, 10, 20, 30) */