digitalmars.D - working va_arg implementation
- Hauke Duden <H.NS.Duden gmx.net> May 02 2004
- J Anderson <REMOVEanderson badmama.com.au> May 02 2004
- "Achilleas Margaritis" <axilmar in.gr> May 02 2004
- "Andrew Edwards" <edwardsac spamfreeusa.com> May 02 2004
- Andy Friesen <andy ikagames.com> May 03 2004
- Hauke Duden <H.NS.Duden gmx.net> May 02 2004
- "Walter" <newshound digitalmars.com> May 02 2004
After not being sure in my previous post, I ran a few tests with a
template implementation for varargs until I got it to work.
This is what I came up with. It works with the normal D calling
convention on Windows:
typedef void* va_list;
template va_start(T)
{
va_list va_start(inout T prevArg)
{
return cast(va_list) (&prevArg + 1);
}
}
template va_arg(T)
{
T va_arg(inout va_list ap)
{
T arg=*cast(T*)ap;
ap = cast(va_list) ((cast(T*)ap) +1);
return arg;
}
}
usage:
void printf(char[] fmt,...)
{
va_list argList = va_start!(char[])(fmt);
int param1=va_arg!(int)(argList);
double param2=va_arg!(double)(argList);
etc...
}
May 02 2004
Hauke Duden wrote:After not being sure in my previous post, I ran a few tests with a template implementation for varargs until I got it to work. This is what I came up with. It works with the normal D calling convention on Windows: typedef void* va_list; template va_start(T) { va_list va_start(inout T prevArg) { return cast(va_list) (&prevArg + 1); } } template va_arg(T) { T va_arg(inout va_list ap) { T arg=*cast(T*)ap; ap = cast(va_list) ((cast(T*)ap) +1); return arg; } } usage: void printf(char[] fmt,...) { va_list argList = va_start!(char[])(fmt); int param1=va_arg!(int)(argList); double param2=va_arg!(double)(argList); etc... }
Thanks a lot! Parhaps this should go into phobos? -- -Anderson: http://badmama.com.au/~anderson/
May 02 2004
"J Anderson" <REMOVEanderson badmama.com.au> wrote in message news:c72ro7$15jj$1 digitaldaemon.com...Hauke Duden wrote:After not being sure in my previous post, I ran a few tests with a template implementation for varargs until I got it to work. This is what I came up with. It works with the normal D calling convention on Windows: typedef void* va_list; template va_start(T) { va_list va_start(inout T prevArg) { return cast(va_list) (&prevArg + 1); } } template va_arg(T) { T va_arg(inout va_list ap) { T arg=*cast(T*)ap; ap = cast(va_list) ((cast(T*)ap) +1); return arg; } } usage: void printf(char[] fmt,...) { va_list argList = va_start!(char[])(fmt); int param1=va_arg!(int)(argList); double param2=va_arg!(double)(argList); etc... }
Thanks a lot! Parhaps this should go into phobos? -- -Anderson: http://badmama.com.au/~anderson/
In order to do safe varargs, D should have a 'variant' primitive type which can be anything. When pushing varargs on the stack, a static array of variants is created, then accessed in the function as an array, using RTTI. For example: void printf(...) { foreach(variant v; printf.args) { switch (typeof(v)) { case typeof(int): case typeof(string): } } }
May 02 2004
"Achilleas Margaritis" <axilmar in.gr> wrote in message news:c72s1u$167n$1 digitaldaemon.com..."J Anderson" <REMOVEanderson badmama.com.au> wrote in message news:c72ro7$15jj$1 digitaldaemon.com...Hauke Duden wrote:
-- -Anderson: http://badmama.com.au/~anderson/
In order to do safe varargs, D should have a 'variant' primitive type
can be anything. When pushing varargs on the stack, a static array of variants is created, then accessed in the function as an array, using
For example: void printf(...) { foreach(variant v; printf.args) { switch (typeof(v)) { case typeof(int): case typeof(string): } } }
This was exactly my suggestion a few months back (D/25025). IMHO this is an elegant solution to both variable argument and typesafe functions. Regards, Andrew
May 02 2004
In article <c72tu3$196a$1 digitaldaemon.com>, Andrew Edwards says..."Achilleas Margaritis" <axilmar in.gr> wrote in message news:c72s1u$167n$1 digitaldaemon.com..."J Anderson" <REMOVEanderson badmama.com.au> wrote in message news:c72ro7$15jj$1 digitaldaemon.com...Hauke Duden wrote:
-- -Anderson: http://badmama.com.au/~anderson/
In order to do safe varargs, D should have a 'variant' primitive type
can be anything. When pushing varargs on the stack, a static array of variants is created, then accessed in the function as an array, using
For example: void printf(...) { foreach(variant v; printf.args) { switch (typeof(v)) { case typeof(int): case typeof(string): } } }
This was exactly my suggestion a few months back (D/25025). IMHO this is an elegant solution to both variable argument and typesafe functions. Regards, Andrew
It is the only solution that makes sense for variable arguments. Does Walter know about it ?
May 03 2004
Achilleas Margaritis wrote:In order to do safe varargs, D should have a 'variant' primitive type which can be anything. When pushing varargs on the stack, a static array of variants is created, then accessed in the function as an array, using RTTI. For example: void printf(...) { foreach(variant v; printf.args) { switch (typeof(v)) { case typeof(int): case typeof(string): } } }
If you have to check the type at runtime like that, it's not very typesafe. ;) I see two resolutions to this issue. The easy one is the opCall idiom: stdout.print("aoeuaoeu") (42) (3.141596) (); The hard (but awesome) one requires some sort of type deduction. Given that, it would be very simple to add a symbol to the language that represents "all the other arguments". Normal overloading rules would apply: void print(char[] s, other) { puts(s); print(other); } void print(int i, other) { printf("%i", i); print(other); } void print() { } -- andy
May 03 2004
J Anderson wrote:Thanks a lot! Parhaps this should go into phobos?
If Walter wants to have it in there - sure. And before any licensing stuff comes up: I hereby place the code in the public domain. Hauke
May 02 2004
It's almost perfect - but the advancement of ap doesn't take into account objects that take more than a pointer size of the stack. I've posted a corrected version in the other thread. Thanks!
May 02 2004









Achilleas Margaritis <Achilleas_member pathlink.com> 