This PR adds support for varargs (closes #390). The idea is as follows:
If we have a call to a varargs-function, we write all the varargs to a pointer and pass it to the function. There is one exception to that: If the varargs are not used anyway, we ommit the creation of this pointer and just dispatch the arguments.
va_start(v, a) is just translated to an assignement of the varargs-pointer-argument to v.
va_arg(v, type) is translated using a macro complicated macro *((typeof(type) *)((v += sizeof(type)) - sizeof(type))), since it is not a function (because of the type) and we cannot handle it otherwise. The idea behind this macro is that we cast v to a type* and increment it afterwards by sizeof(type) (since += yields the value after the increment, we need to subtract it...).
va_end(v) basically deallocates v, but at its "original" offset 0.
This PR adds support for varargs (closes #390). The idea is as follows:
va_start(v, a)
is just translated to an assignement of the varargs-pointer-argument tov
.va_arg(v, type)
is translated using a macro complicated macro*((typeof(type) *)((v += sizeof(type)) - sizeof(type)))
, since it is not a function (because of the type) and we cannot handle it otherwise. The idea behind this macro is that we castv
to atype*
and increment it afterwards bysizeof(type)
(since+=
yields the value after the increment, we need to subtract it...).va_end(v)
basically deallocatesv
, but at its "original" offset 0.