digitalmars.D - va_start/va_end
- J Anderson <REMOVEanderson badmama.com.au> May 01 2004
- "Andrew Edwards" <edwardsac spamfreeusa.com> May 01 2004
- "Andrew Edwards" <edwardsac spamfreeusa.com> May 01 2004
- J Anderson <REMOVEanderson badmama.com.au> May 01 2004
- J Anderson <REMOVEanderson badmama.com.au> May 02 2004
- "Walter" <newshound digitalmars.com> May 02 2004
- Ben Hinkle <bhinkle4 juno.com> May 01 2004
- Hauke Duden <H.NS.Duden gmx.net> May 02 2004
- Hauke Duden <H.NS.Duden gmx.net> May 02 2004
- "Walter" <newshound digitalmars.com> May 02 2004
- J C Calvarese <jcc7 cox.net> May 02 2004
- "Walter" <newshound digitalmars.com> May 02 2004
- "Andrew Edwards" <edwardsac spamfreeusa.com> May 02 2004
- Hauke Duden <H.NS.Duden gmx.net> May 02 2004
- "Walter" <newshound digitalmars.com> May 02 2004
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...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); }
sorry , that should read: ap = cast(va_list*)(&ap+ap.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..."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/
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); }
sorry , that should read: ap = cast(va_list*)(&ap+ap.size);
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/
May 01 2004
J Anderson wrote:Andrew Edwards wrote:"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 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); }
sorry , that should read: ap = cast(va_list*)(&ap+ap.size);
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/
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:
"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/
before, but am not sure if I came up with the correct syntax as I'm
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);
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/
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...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; }
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); }
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:Your 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-------------------------------------------------
------------------------------------------------------------------ Here's a little test program to show how to use it: ------------------------------------------------------------------
------------------------------------------------------
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:Your 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.
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.
May 02 2004









J Anderson <REMOVEanderson badmama.com.au> 