www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - forward variadic arguments

reply Frank Benoit <keinfarbton nospam.xyz> writes:
 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?
Jun 15 2006
next sibling parent reply Deewiant <deewiant.doesnotlike.spam gmail.com> writes:
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); }
Jun 15 2006
parent reply Frank Benoit <keinfarbton nospam.xyz> writes:
 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);
Jun 15 2006
parent Deewiant <deewiant.doesnotlike.spam gmail.com> writes:
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 }
Jun 15 2006
prev sibling parent reply Tom S <h3r3tic remove.mat.uni.torun.pl> writes:
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 +/
Jun 15 2006
parent Daniel Keep <daniel.keep.lists gmail.com> writes:
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/
Jun 16 2006