www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - working va_arg implementation

reply Hauke Duden <H.NS.Duden gmx.net> writes:
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
next sibling parent reply J Anderson <REMOVEanderson badmama.com.au> writes:
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
next sibling parent reply "Achilleas Margaritis" <axilmar in.gr> writes:
"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
next sibling parent reply "Andrew Edwards" <edwardsac spamfreeusa.com> writes:
"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
parent Achilleas Margaritis <Achilleas_member pathlink.com> writes:
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
prev sibling parent Andy Friesen <andy ikagames.com> writes:
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
prev sibling parent Hauke Duden <H.NS.Duden gmx.net> writes:
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
prev sibling parent "Walter" <newshound digitalmars.com> writes:
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