digitalmars.D - va_start/va_end
- J Anderson (10/10) May 01 2004 What are the equivalent of:
- Andrew Edwards (17/27) May 01 2004 There is no equivalent...You need to roll your own. I had played with th...
- Andrew Edwards (3/34) May 01 2004 sorry , that should read: ap = cast(va_list*)(&ap+ap.size);
- J Anderson (29/64) May 01 2004 I don't get it, where do I get the parameter input from? For example,
- J Anderson (4/70) May 02 2004 Oh I see. Your taking it from the stack. Very clever.
- Walter (7/71) May 02 2004 Replace the va_start with:
- Ben Hinkle (6/15) May 01 2004 It's a bummer but I don't think "global" va_start and friends can be wri...
- Hauke Duden (37/70) May 02 2004 This is wrong. ap is allocated on the stack AFTER the variable
- Hauke Duden (21/25) May 02 2004 Just realized my error here: if the stack grows downwards (which, if
- Walter (59/59) May 02 2004 Your use of templates to do varargs is cool. I made a couple of fixes, a...
- J C Calvarese (7/82) May 02 2004 Cool!
- Walter (5/87) May 02 2004 On second thought, it should be std.c.stdarg, since it mirrors the C
- Andrew Edwards (16/23) May 02 2004 Awesome! Now there's only one thing I'd like to bother you with: can we
- Hauke Duden (17/19) May 02 2004 Thanks! I thought it was obvious, but apparently it was not ;).
- Walter (11/30) May 02 2004 and
What are the equivalent of: va_start and va_end in D? Thanks. PS - This is not meant to be an argument in anyway. I just want to use the ... for multiple arguments. -- -Anderson: http://badmama.com.au/~anderson/
May 01 2004
"J Anderson" <REMOVEanderson badmama.com.au> wrote in message news:c716pl$1ljo$1 digitaldaemon.com...What are the equivalent of: va_start and va_end in D? Thanks. PS - This is not meant to be an argument in anyway. I just want to use the ... for multiple arguments. -- -Anderson: http://badmama.com.au/~anderson/There is no equivalent...You need to roll your own. I had played with this before, but am not sure if I came up with the correct syntax as I'm still having problems with it. void va_start(inout va_list ap, char[] fmt) { ap = cast(void*)(&args+args.size); } void va_end(inout va_list ap) { ap = null; } if you come up with something that works please I'd like to get a hold of it. Thanks, Andrew
May 01 2004
"Andrew Edwards" <edwardsac spamfreeusa.com> wrote in message news:c71m0d$2ck4$1 digitaldaemon.com..."J Anderson" <REMOVEanderson badmama.com.au> wrote in message news:c716pl$1ljo$1 digitaldaemon.com...sorry , that should read: ap = cast(va_list*)(&ap+ap.size);What are the equivalent of: va_start and va_end in D? Thanks. PS - This is not meant to be an argument in anyway. I just want to use the ... for multiple arguments. -- -Anderson: http://badmama.com.au/~anderson/There is no equivalent...You need to roll your own. I had played with this before, but am not sure if I came up with the correct syntax as I'm still having problems with it. void va_start(inout va_list ap, char[] fmt) { ap = cast(void*)(&args+args.size); }void va_end(inout va_list ap) { ap = null; } if you come up with something that works please I'd like to get a hold of it. Thanks, Andrew
May 01 2004
Andrew Edwards wrote:"Andrew Edwards" <edwardsac spamfreeusa.com> wrote in message news:c71m0d$2ck4$1 digitaldaemon.com...I don't get it, where do I get the parameter input from? For example, at the moment I've got something like this: void printp(char *format, ... ) { char [] TempStr; TempStr.length = (strlen((char*)format) * 2) + 50; //Guess va_list varg; //Holds arguments //Open the argument list va_start(varg,format); //Generate the string int x = _vsnprintf(TempStr, TempStr.length - 1, format, varg); //Increase size until it fits (not to efficient, but no overflows) while (x == -1) { //Increase size TempStr.length += 100; x = _vsnprintf(TempStr, TempStr.length - 1, format, varg); } //Close the argument list va_end(varg); } Of course the va_start doesn't work. Thanks. -- -Anderson: http://badmama.com.au/~anderson/"J Anderson" <REMOVEanderson badmama.com.au> wrote in message news:c716pl$1ljo$1 digitaldaemon.com...sorry , that should read: ap = cast(va_list*)(&ap+ap.size);What are the equivalent of: va_start and va_end in D? Thanks. PS - This is not meant to be an argument in anyway. I just want to use the ... for multiple arguments. -- -Anderson: http://badmama.com.au/~anderson/There is no equivalent...You need to roll your own. I had played with this before, but am not sure if I came up with the correct syntax as I'm still having problems with it. void va_start(inout va_list ap, char[] fmt) { ap = cast(void*)(&args+args.size); }
May 01 2004
J Anderson wrote:Andrew Edwards wrote:Oh I see. Your taking it from the stack. Very clever. -- -Anderson: http://badmama.com.au/~anderson/"Andrew Edwards" <edwardsac spamfreeusa.com> wrote in message news:c71m0d$2ck4$1 digitaldaemon.com...I don't get it, where do I get the parameter input from? For example, at the moment I've got something like this: void printp(char *format, ... ) { char [] TempStr; TempStr.length = (strlen((char*)format) * 2) + 50; //Guess va_list varg; //Holds arguments //Open the argument list va_start(varg,format); //Generate the string int x = _vsnprintf(TempStr, TempStr.length - 1, format, varg); //Increase size until it fits (not to efficient, but no overflows) while (x == -1) { //Increase size TempStr.length += 100; x = _vsnprintf(TempStr, TempStr.length - 1, format, varg); } //Close the argument list va_end(varg); } Of course the va_start doesn't work. Thanks."J Anderson" <REMOVEanderson badmama.com.au> wrote in message news:c716pl$1ljo$1 digitaldaemon.com...sorry , that should read: ap = cast(va_list*)(&ap+ap.size);What are the equivalent of: va_start and va_end in D? Thanks. PS - This is not meant to be an argument in anyway. I just want to use the ... for multiple arguments. -- -Anderson: http://badmama.com.au/~anderson/There is no equivalent...You need to roll your own. I had played with this before, but am not sure if I came up with the correct syntax as I'm still having problems with it. void va_start(inout va_list ap, char[] fmt) { ap = cast(void*)(&args+args.size); }
May 02 2004
Replace the va_start with: varg = (void*)&format + (void*).size; Replace va_end with nothing. "J Anderson" <REMOVEanderson badmama.com.au> wrote in message news:c71qcc$2jnr$1 digitaldaemon.com...Andrew Edwards wrote:this"Andrew Edwards" <edwardsac spamfreeusa.com> wrote in message news:c71m0d$2ck4$1 digitaldaemon.com..."J Anderson" <REMOVEanderson badmama.com.au> wrote in message news:c716pl$1ljo$1 digitaldaemon.com...What are the equivalent of: va_start and va_end in D? Thanks. PS - This is not meant to be an argument in anyway. I just want to use the ... for multiple arguments. -- -Anderson: http://badmama.com.au/~anderson/There is no equivalent...You need to roll your own. I had played withstillbefore, but am not sure if I came up with the correct syntax as I'mI don't get it, where do I get the parameter input from? For example, at the moment I've got something like this: void printp(char *format, ... ) { char [] TempStr; TempStr.length = (strlen((char*)format) * 2) + 50; //Guess va_list varg; //Holds arguments //Open the argument list va_start(varg,format); //Generate the string int x = _vsnprintf(TempStr, TempStr.length - 1, format, varg); //Increase size until it fits (not to efficient, but no overflows) while (x == -1) { //Increase size TempStr.length += 100; x = _vsnprintf(TempStr, TempStr.length - 1, format, varg); } //Close the argument list va_end(varg); } Of course the va_start doesn't work. Thanks. -- -Anderson: http://badmama.com.au/~anderson/having problems with it. void va_start(inout va_list ap, char[] fmt) { ap = cast(void*)(&args+args.size); }sorry , that should read: ap = cast(va_list*)(&ap+ap.size);
May 02 2004
void va_start(inout va_list ap, char[] fmt) { ap = cast(void*)(&args+args.size); } void va_end(inout va_list ap) { ap = null; }It's a bummer but I don't think "global" va_start and friends can be written without macros. I'd look at the printf code in std.outbuffer or std.stream for examples of how to use varargs in D. Maybe using nested functions would work but it wouldn't be very practical to have to define va_start inside every function that uses it. -Ben
May 01 2004
Andrew Edwards wrote:"J Anderson" <REMOVEanderson badmama.com.au> wrote in message news:c716pl$1ljo$1 digitaldaemon.com...This is wrong. ap is allocated on the stack AFTER the variable arguments. I'm not sure about the D calling convention, but when parameters are pushed in-order then it would have to look something like this: void va_start(out va_list ap, inout void* prevArg) { ap = (&prevArg)+prevArg.size; } This will only work if the previous argument is a pointer, though. A template helps: typedef void* va_list; template va_start(T) { void va_start(out va_list ap, inout T prevArg) { ap = (cast(void*)&prevArg)+prevArg.size; } } template va_arg(T) { T va_arg(inout va_list ap) { T arg=*cast(T*)ap; ap+=T.size; return arg; } } Unfortunately, since we have no implicit template instantiation, you then have to use it like this: void printf(char[] fmt,...) { va_list ap; va_start!(char[])(ap,fmt); if(....) int param=va_arg!(int)(ap); }What are the equivalent of: va_start and va_end in D? Thanks. PS - This is not meant to be an argument in anyway. I just want to use the ... for multiple arguments. -- -Anderson: http://badmama.com.au/~anderson/There is no equivalent...You need to roll your own. I had played with this before, but am not sure if I came up with the correct syntax as I'm still having problems with it. void va_start(inout va_list ap, char[] fmt) { ap = cast(void*)(&args+args.size); } void va_end(inout va_list ap) { ap = null; }
May 02 2004
Hauke Duden wrote:This is wrong. ap is allocated on the stack AFTER the variable arguments. I'm not sure about the D calling convention, but when parameters are pushed in-order then it would have to look something like this:Just realized my error here: if the stack grows downwards (which, if memory serves, it usually does) and the arguments are still pushed in-order then this must look a little different: typedef void* va_list; template va_start(T) { void va_start(out va_list ap, inout T prevArg) { ap = cast(void*)&prevArg; } } template va_arg(T) { T va_arg(inout va_list ap) { ap-=T.size; return *cast(T*)ap; } } Hauke
May 02 2004
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. ------------------------------------------------- /* * 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); } ------------------------------------------------------
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
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:andYour use of templates to do varargs is cool. I made a couple of fixes,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
"Hauke Duden" <H.NS.Duden gmx.net> wrote in message news:c73f7f$24jc$1 digitaldaemon.com...Walter wrote:andYour use of templates to do varargs is cool. I made a couple of fixes,Nothing is ever as simple as it seems. I goofed up my first version, too.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.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.
May 02 2004