Thread overview
forward variadic arguments
Jun 15, 2006
Frank Benoit
Jun 15, 2006
Deewiant
Jun 15, 2006
Frank Benoit
Jun 15, 2006
Deewiant
Jun 15, 2006
Tom S
Jun 16, 2006
Daniel Keep
June 15, 2006
 void execSql( char[] aSql, ... ){
  char[] sql = std.string.format( aSql, _arguments, _argptr );
  database.exec( sql );
 }

The forwarding of all arguments to format() seams not to work.
how can I do this?

June 15, 2006
Frank Benoit wrote:
>  void execSql( char[] aSql, ... ){
>   char[] sql = std.string.format( aSql, _arguments, _argptr );
>   database.exec( sql );
>  }
> 
> The forwarding of all arguments to format() seams not to work.
> how can I do this?
> 

You'll need to do it "manually" by calling the std.format.doFormat function.

void execSql(char[] aSql, ...) {
	char[] sql;
	void putc(dchar c) {
		sql ~= c;
	}

	std.format.doFormat(&putc, _arguments, _argptr);

	database.exec(sql);
}
June 15, 2006
> void execSql(char[] aSql, ...) {
> 	char[] sql;
> 	void putc(dchar c) {
> 		sql ~= c;
> 	}
> 
> 	std.format.doFormat(&putc, _arguments, _argptr);
> 
> 	database.exec(sql);
> }

And what happend to my format string 'aSql' ? :)

TypeInfo[] ti;
ti ~= aSql.typeinfo;
ti ~= _arguments

void* p = ????;
std.format.doFormat(&putc, ti, p);
June 15, 2006
Frank Benoit wrote:
>> void execSql(char[] aSql, ...) {
>> 	char[] sql;
>> 	void putc(dchar c) {
>> 		sql ~= c;
>> 	}
>>
>> 	std.format.doFormat(&putc, _arguments, _argptr);
>>
>> 	database.exec(sql);
>> }
> 
> And what happend to my format string 'aSql' ? :)
> 
> TypeInfo[] ti;
> ti ~= aSql.typeinfo;
> ti ~= _arguments
> 
> void* p = ????;
> std.format.doFormat(&putc, ti, p);

Oh, whoops! :-)

I guess you could try a hack like that. I think you'll have to use std.stdarg - somehow; I've never done this myself - to collect the arguments themselves into an array and then pass the address of the first element of that array as the equivalent of _argptr. BTW, "aSql.typeinfo" is deprecated: use "typeid(typeof(aSql))" or just "typeid(char[])" if you're confident you'll never change its type.

Personally, I'd just change the function signature to "void execSql(...)". It gives a bit more versatility, the following are equivalent:

execSql("%d hello %d", a, b);
execSql(a, " hello ", b);
execSql("%d hello ", a, b);

If you really want to force the first parameter to be char[], I think the only way to be sure (apart from that hackish approach, of course :-P) is to assert it at runtime:

void execSql(...)
in {
	assert (_arguments[0] == typeid(char[]));
} body {
	// the code
}
June 15, 2006
Frank Benoit wrote:
>  void execSql( char[] aSql, ... ){
>   char[] sql = std.string.format( aSql, _arguments, _argptr );
>   database.exec( sql );
>  }
> 
> The forwarding of all arguments to format() seams not to work.
> how can I do this?

I know it's evil and stuff, but I had to do this :D




import std.stdio;


/**
  there's a simpler solution, actually, but it makes the assumption, that
  _argptr - xsize == &x;

  without exploiting this assumption, the following code should
  even be portable ;D
*/
void foo(char[] x, ...) {
	TypeInfo[]		args = _arguments.dup;
	void*			ptr  = _argptr;

	const size_t	xsize = (char[]).sizeof;
	ubyte[xsize]	ptrVal = (cast(ubyte*)ptr)[0 .. xsize];

	// we'll be writing to the stack, this array will store the old values
	ubyte[xsize] backup;

	// this will hold the binary contents of 'x'
	ubyte[xsize] newVal;

	// make space for the value we'll be inserting to the stack
	ptr -= xsize;

	// it will tell writefx to expect another argument
	args = typeid(char[]) ~ args;

	// make a backup of the old value of ptrVal
	backup[] = ptrVal[];

	// and get the new values into the temp array
	newVal[] = (cast(ubyte*)&x)[0 .. xsize];

	// finally, write the new values
	ptrVal[] = newVal[];
	
		writefx(stdout, args, ptr, true);

	// restore the old stack data
	ptrVal[] = backup[];
}


void main() {
	foo("foo ", "bar", 1, 2, 3);
}




-- 
Tomasz Stachowiak  /+ a.k.a. h3r3tic +/
June 16, 2006

Tom S wrote:
> Frank Benoit wrote:
>>  void execSql( char[] aSql, ... ){
>>   char[] sql = std.string.format( aSql, _arguments, _argptr );
>>   database.exec( sql );
>>  }
>>
>> The forwarding of all arguments to format() seams not to work.
>> how can I do this?
> 
> I know it's evil and stuff, but I had to do this :D
> 
> [snip evil but quite handy code]
> 

One of the projects I've been thinking about doing is writing a library for doing programmatic function calls, which would allow things like this to actually be portable :P

Of course, I've been putting it off since Walter still hasn't documented the calling convention for D, and I didn't even realize until a month or so ago that it (sometimes) passes an argument in EAX >_<

	-- Daniel

-- 
Unlike Knuth, I have neither proven or tried the above; it may not even make sense.

v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP  http://hackerkey.com/