May 02, 2004
Walter wrote:

> Your use of templates to do varargs is cool. I made a couple of fixes, and
> the result is std.stdarg! It'll go out in the next release.

Cool!

Could I suggest a name of "std.vararg"?

(Or perhaps we could go a step farther and call it "std.stdstdarg?")

> 
> -------------------------------------------------
> /*
>  * Placed in public domain.
>  * Written by Hauke Duden and Walter Bright
>  */
> 
> module std.stdarg;
> 
> typedef void* va_list;
> 
> template va_start(T)
> {
>     void va_start(out va_list ap, inout T parmn)
>     {
>  ap = cast(va_list)(cast(void*)&parmn + ((T.sizeof + int.sizeof - 1) &
> ~(int.sizeof - 1)));
>     }
> }
> 
> template va_arg(T)
> {
>     T va_arg(inout va_list ap)
>     {
>  T arg = *cast(T*)ap;
>  ap = cast(va_list)(cast(void*)ap + ((T.sizeof + int.sizeof - 1) &
> ~(int.sizeof - 1)));
>  return arg;
>     }
> }
> 
> void va_end(va_list ap)
> {
> }
> ------------------------------------------------------------------
> Here's a little test program to show how to use it:
> 
> ------------------------------------------------------------------
> import std.stdarg;
> 
> int foo(char *x, ...)
> {
>     va_list ap;
> 
>     va_start!(typeof(x))(ap, x);
>     printf("&x = %p, ap = %p\n", &x, ap);
> 
>     int i;
>     i = va_arg!(typeof(i))(ap);
>     printf("i = %d\n", i);
> 
>     long l;
>     l = va_arg!(typeof(l))(ap);
>     printf("l = %lld\n", l);
> 
>     uint k;
>     k = va_arg!(typeof(k))(ap);
>     printf("k = %u\n", k);
> 
>     va_end(ap);
> 
>     return i + l + k;
> }
> 
> void main()
> {
>     int j;
> 
>     j = foo("hello", 3, 23L, 4);
>     printf("j = %d\n", j);
>     assert(j == 30);
> }
> ------------------------------------------------------


-- 
Justin
http://jcc_7.tripod.com/d/
May 02, 2004
"Walter" <newshound@digitalmars.com> wrote in message news:c73b94$1svo$1@digitaldaemon.com...
> Your use of templates to do varargs is cool. I made a couple of fixes, and the result is std.stdarg! It'll go out in the next release.

Awesome! Now there's only one thing I'd like to bother you with: can we
please have types as parameters for switch/case statements?
i.e.

type T;

switch(typeof(T))
{
  case (int): ...
  case (double): ...
  case (char[]): ...
}

Thanks,
Andrew

> -------------------------------------------------
[SNIP] varargs implementation [/SNIP]
> ------------------------------------------------------------------
> Here's a little test program to show how to use it:
>
> ------------------------------------------------------------------
[SNIP] usage example [/SNIP]
> ------------------------------------------------------
>
>


May 02, 2004
Walter wrote:
> Your use of templates to do varargs is cool. I made a couple of fixes, and
> the result is std.stdarg! It'll go out in the next release.

Thanks! I thought it was obvious, but apparently it was not ;).

But: is there a real reason why there even is a va_end? Since it is empty I see no need to burden the user with calling it. I'd also suggest to modify va_start like this:

template va_start(T)
{
    va_list va_start(inout T parmn)
    {
 return cast(va_list)(cast(void*)&parmn + ((T.sizeof + int.sizeof - 1) &
~(int.sizeof - 1)));
    }
}

I.e. return the va_list instead of filling an out parameter. That way the user can write "va_list args=va_start" instead of having to make two lines of it.

Hauke
May 02, 2004
On second thought, it should be std.c.stdarg, since it mirrors the C stdarg.h.

"J C Calvarese" <jcc7@cox.net> wrote in message news:c73c0e$1tj1$2@digitaldaemon.com...
> Walter wrote:
>
> > Your use of templates to do varargs is cool. I made a couple of fixes,
and
> > the result is std.stdarg! It'll go out in the next release.
>
> Cool!
>
> Could I suggest a name of "std.vararg"?
>
> (Or perhaps we could go a step farther and call it "std.stdstdarg?")
>
> >
> > -------------------------------------------------
> > /*
> >  * Placed in public domain.
> >  * Written by Hauke Duden and Walter Bright
> >  */
> >
> > module std.stdarg;
> >
> > typedef void* va_list;
> >
> > template va_start(T)
> > {
> >     void va_start(out va_list ap, inout T parmn)
> >     {
> >  ap = cast(va_list)(cast(void*)&parmn + ((T.sizeof + int.sizeof - 1) &
> > ~(int.sizeof - 1)));
> >     }
> > }
> >
> > template va_arg(T)
> > {
> >     T va_arg(inout va_list ap)
> >     {
> >  T arg = *cast(T*)ap;
> >  ap = cast(va_list)(cast(void*)ap + ((T.sizeof + int.sizeof - 1) &
> > ~(int.sizeof - 1)));
> >  return arg;
> >     }
> > }
> >
> > void va_end(va_list ap)
> > {
> > }
> > ------------------------------------------------------------------
> > Here's a little test program to show how to use it:
> >
> > ------------------------------------------------------------------
> > import std.stdarg;
> >
> > int foo(char *x, ...)
> > {
> >     va_list ap;
> >
> >     va_start!(typeof(x))(ap, x);
> >     printf("&x = %p, ap = %p\n", &x, ap);
> >
> >     int i;
> >     i = va_arg!(typeof(i))(ap);
> >     printf("i = %d\n", i);
> >
> >     long l;
> >     l = va_arg!(typeof(l))(ap);
> >     printf("l = %lld\n", l);
> >
> >     uint k;
> >     k = va_arg!(typeof(k))(ap);
> >     printf("k = %u\n", k);
> >
> >     va_end(ap);
> >
> >     return i + l + k;
> > }
> >
> > void main()
> > {
> >     int j;
> >
> >     j = foo("hello", 3, 23L, 4);
> >     printf("j = %d\n", j);
> >     assert(j == 30);
> > }
> > ------------------------------------------------------
>
>
> -- 
> Justin
> http://jcc_7.tripod.com/d/


May 02, 2004
"Hauke Duden" <H.NS.Duden@gmx.net> wrote in message news:c73f7f$24jc$1@digitaldaemon.com...
> Walter wrote:
> > Your use of templates to do varargs is cool. I made a couple of fixes,
and
> > the result is std.stdarg! It'll go out in the next release.
> Thanks! I thought it was obvious, but apparently it was not ;).

Nothing is ever as simple as it seems. I goofed up my first version, too.

> But: is there a real reason why there even is a va_end? Since it is empty I see no need to burden the user with calling it.

Some CPU architectures require it, and have a non-empty va_end(), which works like a destructor. To write portable code, it'll need to be there.

> I'd also suggest
> to modify va_start like this:
>
> template va_start(T)
> {
>      va_list va_start(inout T parmn)
>      {
>   return cast(va_list)(cast(void*)&parmn + ((T.sizeof + int.sizeof - 1) &
> ~(int.sizeof - 1)));
>      }
> }
>
> I.e. return the va_list instead of filling an out parameter. That way the user can write "va_list args=va_start" instead of having to make two lines of it.

I understand, but upon second thought I want to make this a simple analog of C's <stdarg.h>, and move it into std.c.stdarg. The va_end() suggests that a D-ish version would make use of an auto class for robust cleanup, and so I want to leave the door open for this better design, which would also incorporate your suggestion.


1 2
Next ›   Last »