May 02, 2004 Re: va_start/va_end | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter | 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 Re: va_start/va_end | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter | "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 Re: va_start/va_end | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter | 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 Re: va_start/va_end | ||||
---|---|---|---|---|
| ||||
Posted in reply to J C Calvarese | 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 Re: va_start/va_end | ||||
---|---|---|---|---|
| ||||
Posted in reply to Hauke Duden | "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. |
Copyright © 1999-2021 by the D Language Foundation