Functions with variable arguments, countof()
May 21, 2023WCPL fully supports <stdarg.h>
header defining a type and three macros for
advancing through an array of values supplied as the value of the ...
(ellipsis)
argument. Internally, this argument comes last in the argument list and has the
va_list
type, defined internally as follows:
WCPL has no requirement of the ellipsis argument to be preceded by ‘normal’ arguments; if needed,
...
can be the only argument in the argument list. The ellipsis argument can be referenced
in the body of the function as a pointer expression either via WCPL-specific intrinsic va_etc()
or via its equivalent pseudo-variable ...
. The following is a legal WCPL code (which,
of course, can return garbage if no arguments are supplied to foo
by the caller):
It is compiled to the following WASM code:
(func $_:foo (export "foo")
(param $ap$ i32) (result i32)
local.get $ap$
i32.load offset=0 align=4
return
)
The va_arg
form is an intrinsic (cannot be a macro because WCPL macros can’t
have types as parameters):
va_arg(ap, type)
is equivalent to *(type*)ap++
The rest of the standard macros for variable argument access are defined as follows:
Also, WCPL supports a countof
intrinsic, which serves three purposes. It can act as
a shortcut for counting the number of elements in an array, so if a
is an array
expression:
countof(a)
is equivalent to sizeof(a)/sizeof(a[0])
Its second purpose is to access the number of the arguments supplied to vararg function:
countof(...)
returns the corresponding count, which is always stored by the caller in
va_arg_t
-typed slot preceding the first actual argument in the ...
argument array:
countof(...)
is equivalent to ...[-1].va_size
This feature makes it possible to write code like this:
WCPL’s <stdarg.h>
header defines an additional macro for this scenario:
The third purpose of countof()
is related to variadic and generic macros; it will
be described in the next few posts.