Thread overview
working va_arg implementation
May 02, 2004
Hauke Duden
May 02, 2004
J Anderson
May 02, 2004
Andrew Edwards
May 03, 2004
Andy Friesen
May 02, 2004
Hauke Duden
May 02, 2004
Walter
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:
> >
[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
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 03, 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:
>> >
>[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
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