Thread overview | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
May 02, 2004 working va_arg implementation | ||||
---|---|---|---|---|
| ||||
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 Re: working va_arg implementation | ||||
---|---|---|---|---|
| ||||
Posted in reply to Hauke Duden | 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 Re: working va_arg implementation | ||||
---|---|---|---|---|
| ||||
Posted in reply to J Anderson | "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 Re: working va_arg implementation | ||||
---|---|---|---|---|
| ||||
Posted in reply to Achilleas Margaritis | "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: > > [SNIP] va_arg implimentation [/SNIP] > > > > -- > > -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): > } > } > } > This was exactly my suggestion a few months back (http://www.digitalmars.com/drn-bin/wwwnews?D/25025). IMHO this is an elegant solution to both variable argument and typesafe functions. Regards, Andrew |
May 02, 2004 Re: working va_arg implementation | ||||
---|---|---|---|---|
| ||||
Posted in reply to J Anderson | 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 Re: working va_arg implementation | ||||
---|---|---|---|---|
| ||||
Posted in reply to Hauke Duden | 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 03, 2004 Re: working va_arg implementation | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrew Edwards | 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: >> > >[SNIP] va_arg implimentation [/SNIP] >> > >> > -- >> > -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): >> } >> } >> } >> > >This was exactly my suggestion a few months back (http://www.digitalmars.com/drn-bin/wwwnews?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 Re: working va_arg implementation | ||||
---|---|---|---|---|
| ||||
Posted in reply to Achilleas Margaritis | 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
|
Copyright © 1999-2021 by the D Language Foundation