manipulating arguments (in C)

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

manipulating arguments (in C)

Jean-Christophe Deschamps

I feel the need to wrap an SQLite printf-like function into a scalar
function.
I wish to use it as in:

    select printf(format_string, list of arguments);

My question is slightly off topic but there are experienced users here
who have probably done it before.

In the scalar function (printf), I get arguments as the usual array of
pointers. How would you pass the variable list arguments to
sqlite3_mprintf()?
Is there any nice way not imposing a limitation on n?



_______________________________________________
sqlite-users mailing list
[hidden email]
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users
Reply | Threaded
Open this post in threaded view
|

Re: manipulating arguments (in C)

Roger Binns
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Jean-Christophe Deschamps wrote:
> I feel the need to wrap an SQLite printf-like function into a scalar
> function.

You can just do that sort of thing in your application.  There is no need to
do it via a SQL function.

> My question is slightly off topic but there are experienced users here
> who have probably done it before.

You can retrieve any value as any type.  For example if an integer is
returned but you call column_text then it will be converted to text for you.

> In the scalar function (printf), I get arguments as the usual array of
> pointers. How would you pass the variable list arguments to
> sqlite3_mprintf()?
> Is there any nice way not imposing a limitation on n?

This kind of thing is extra-ordinarily tricky under C, error prone, easy to
crash and usually non-portable.  This is how you receive a variable number
of arguments:

  http://en.wikipedia.org/wiki/Stdarg.h

sqlite3_vmprintf can receive that.  GCC can do some variable argument
calling but not really useful here:

  http://gcc.gnu.org/onlinedocs/gcc/Constructing-Calls.html

But what you are really trying to do is take an arbitrary number of
parameters, unwrap them from SQLite types into native types and then compose
a call to sqlite3_mprintf.  The only way this is directly possible is using
a library that can do this for you at runtime which pretty much means this one:

  http://en.wikipedia.org/wiki/Libffi

You really don't want to go down this route.  If you do then you really
don't want to use C.  As an example your requirement is trivial to do in
Python - it would be a one liner using either wrapper.

Roger
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iEYEARECAAYFAkrfi+sACgkQmOOfHg372QTuhwCg3rYnGnuFi5SJexL4rpF+N09d
DvcAoMFzJymLEnTY2CQl0juFMQdoW+Y7
=jL1v
-----END PGP SIGNATURE-----
_______________________________________________
sqlite-users mailing list
[hidden email]
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users
Reply | Threaded
Open this post in threaded view
|

Re: manipulating arguments (in C)

Jean-Christophe Deschamps
Roger,

Thank you for your answer.  I knew from old days that va_* things are
very fragile (not only from the portability point of view).

In the "duct tape programming" situation where I currently am, the best
I can came up with is by fixing the max # of arguments to 32 and using
a _ugly_ kludge on the stack.  It gives something along the line of:

select printf('abc %lli %s %s %g %s %lld',
     -357,
     Proper('febÆhùivÊ 1no 2no'),
     null,
     3.1415926,
     Upper('ådefàßùç'),
     1234567890123456
) as Result;

returning:

Result
abc -357 Febæhùivê 1No 2No <NULL> 3.14159 ÅDEFÀSSÙÇ 1234567890123456

I confess that the way I pass sqlite3_mprintf(fmt, stuff) the "stuff"
structure containing ... ahem ... exactly what the stack is supposed to
contain is probably not a very academic programming model.   (but it
works >:-} )



_______________________________________________
sqlite-users mailing list
[hidden email]
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users
Reply | Threaded
Open this post in threaded view
|

Re: manipulating arguments (in C)

Rob Sciuk
In reply to this post by Jean-Christophe Deschamps

Perhaps this might lead you in the right direction Jean-Christophe ...

#include <stdarg.h>
#include <stdlib.h>
#include <strings.h>

Str_t  s_format( Str_t fmt, ... ){
   va_list  ap ;
   Int_t    nx ;
   Byt_t    buf[1] ;
   Str_t    qptr ;

   va_start( ap, fmt );
    nx = vsnprintf( buf, 0, fmt, ap ) ;
   va_end( ap ) ;

   qptr = (Str_t) q_calloc( 1, nx+1 ) ;

   va_start( ap, fmt ) ;
    nx = vsnprintf( qptr, nx+1, fmt, ap ) ;
   va_end( ap ) ;

   return qptr ;
}

--
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
Robert S. Sciuk http://www.controlq.com                259 Simcoe St. S.
Control-Q Research tel: 905.576.8028 Oshawa, Ont.
[hidden email] fax: 905.576.8386   Canada, L1H 4H3
_______________________________________________
sqlite-users mailing list
[hidden email]
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users
Reply | Threaded
Open this post in threaded view
|

Re: manipulating arguments (in C)

Jean-Christophe Deschamps
Hi Rob,


>Perhaps this might lead you in the right direction Jean-Christophe ...
>
>#include <stdarg.h>

Thank you for your answer.
The va_* construct isn't portable, AFAIK.  Various compilers (headers,
libraries) may (and did) implement it in different and potentially
incompatible ways.

Since in my case I have homebrew extensions, stock sqlite3.dll and
third-party software, all compiled with distinct compilers, I've
avoided using va_*.

In fact, this is a bit pedantic, since what I've done (packing
arguments in a structure which is pushed on the stack) is strictly
equivalent to the "packed array" va_* variation and is simply what the
stack would look like if individual parameters were pushed naturally in
a standard multi-parameter function call.  The drawback is that the
maximum number for parameters must be fixed, but I guess this is harder
to circumvent (in C).

Some day when/if I get spare time, I'll reimplement the printf
extension, remove what's useless here (eg %c) and make it a bit more
robust (force ll prefix for integers, a.s.o.) but this is very low
priority for now.



_______________________________________________
sqlite-users mailing list
[hidden email]
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users