473,387 Members | 1,812 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,387 software developers and data experts.

Howto pass va_list to another va func

I have a C program, where I control the error behavior according to context:
/* some error handlers */
static void on_error_log (MYSQL *mysql, const char *msg, ...);
....
static void on_error_exit (MYSQL *mysql, const char *msg, ...);

/* the error function */
static void (*error_fatal) (MYSQL *mysql, const char *msg, ...) =
on_error_log;
i.e. on the fly I can change which handler error_fatal() uses, sometimes I
want to call exit(), other times just log error and continue etc.
So far, no problem, but then I wanted a trace function and decided to reuse
the on_error_log() function, since the trace function didn't need the MYSQL
context, a simplified interface could be used:
static void log_err(const char *msg, ...);
Now comes the problem, how to make log_err() call on_err_log(), clearly my
first try didn't work:
$ cat test_argp.c
/*
Demonstrate the problem of calling variable argument
function, from another va function.
*/

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <assert.h>

#define LOG_FILE_NAME "test.log"

static void on_error_log(const char *msg, ...)
{
va_list argp;
FILE *log;

assert(msg != NULL);

log = fopen(LOG_FILE_NAME, "a");
if (log == NULL)
{
perror(LOG_FILE_NAME);
exit(EXIT_FAILURE);
}

if ( msg != NULL)
{
va_start(argp, msg);
(void) vfprintf(log, msg, argp);
va_end(argp);
}

fclose(log);
}

static void log_err(const char *msg, ...)
{
va_list argp;

assert(msg != NULL);

va_start(argp, msg);
on_error_log(NULL, msg, argp);
va_end(argp);
}

int main(void)
{
const char *string = "Test string";

log_err("Log test.... string");
log_err("Log test.... string");

log_err("string = '%s'\n", string);
log_err("string = '%s'\n", string);

return EXIT_SUCCESS;
}

$ gcc -ansi -W -Wall -pedantic -g test_argp.c
$ ./a.out
a.out: test_argp.c:18: on_error_log: Assertion `msg != ((void *)0)' failed.
Aborted
$ gdb a.out
(gdb) r
Starting program: /****/***/***/******/a.out
a.out: test_argp.c:18: on_error_log: Assertion `msg != ((void *)0)' failed.

Program received signal SIGABRT, Aborted.
0xffffe410 in __kernel_vsyscall ()
(gdb) bt
#0 0xffffe410 in __kernel_vsyscall ()
#1 0xb7e51770 in raise () from /lib/tls/i686/cmov/libc.so.6
#2 0xb7e52ef3 in abort () from /lib/tls/i686/cmov/libc.so.6
#3 0xb7e4adbb in __assert_fail () from /lib/tls/i686/cmov/libc.so.6
#4 0x080484b4 in on_error_log (msg=0x0) at test_argp.c:18
#5 0x0804856b in log_err (msg=0x80486f7 "Log test.... string") at
test_argp.c:44
#6 0x08048591 in main () at test_argp.c:52
(gdb)
so the assert() bomb out on the first logerr() call. Unless I'm missing some
trivial point here, could someone explain how to do this, and why the above
code fail.

--
Tor <torust [at] online [dot] no>

Apr 25 '07 #1
4 19202
Tor Rustad wrote:
on_error_log(NULL, msg, argp);
Grrrrrrrrrrr...

on_error_log(msg, argp);
--
Tor <torust [at] online [dot] no>

Apr 25 '07 #2
Tor Rustad wrote On 04/25/07 15:41,:
I have a C program, where I control the error behavior according to context:
/* some error handlers */
static void on_error_log (MYSQL *mysql, const char *msg, ...);
...
static void on_error_exit (MYSQL *mysql, const char *msg, ...);

/* the error function */
static void (*error_fatal) (MYSQL *mysql, const char *msg, ...) =
on_error_log;
i.e. on the fly I can change which handler error_fatal() uses, sometimes I
want to call exit(), other times just log error and continue etc.
So far, no problem, but then I wanted a trace function and decided to reuse
the on_error_log() function, since the trace function didn't need the MYSQL
context, a simplified interface could be used:
static void log_err(const char *msg, ...);
Now comes the problem, how to make log_err() call on_err_log(), clearly my
first try didn't work:
[...]
You were about half way home, but only half. The idea
is to put the "guts" of the operation in a function that
takes a fixed argument list, one of which is a va_list.
Then you also write one or more wrappers that take "..."
arguments, initialize a va_list, call the "guts" function,
and clean up the va_list. See Question 15.12 in the FAQ
at <http://www.c-faq.com/>.

--
Er*********@sun.com
Apr 25 '07 #3
Tor Rustad wrote, On 25/04/07 20:49:
Tor Rustad wrote:
>on_error_log(NULL, msg, argp);

Grrrrrrrrrrr...

on_error_log(msg, argp);
Also you have to make on_error_log take a va_list rather than being
varidac (ending in a ...). If you want to be able to call it both ways,
something like:

void von_error_log(char *msg, va_list args)
{
/* do the work */
}

void on_error_log(char *msg, ...)
{
va_list args;
va_start(args,msg);
von_error_log(msg,args);
va_end(args);
}
--
Flash Gordon
Apr 25 '07 #4
Eric Sosman wrote:
Tor Rustad wrote On 04/25/07 15:41,:
[...]
>>
Now comes the problem, how to make log_err() call on_err_log(), clearly
my first try didn't work:

You were about half way home, but only half. The idea
is to put the "guts" of the operation in a function that
takes a fixed argument list, one of which is a va_list.
Then you also write one or more wrappers that take "..."
arguments, initialize a va_list, call the "guts" function,
and clean up the va_list. See Question 15.12 in the FAQ
at <http://www.c-faq.com/>.
For some reason I must have forgot 15.12, thanks a lot!

Here, is the modified test code, which indeed worked as expected:
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <assert.h>

#define LOG_FILE_NAME "test.log"

static void verror_log(const char *msg, va_list argp)
{
FILE *log;

assert(msg != NULL);

log = fopen(LOG_FILE_NAME, "a");
if (log == NULL)
{
perror(LOG_FILE_NAME);
exit(EXIT_FAILURE);
}

if ( msg != NULL)
{
(void) vfprintf(log, msg, argp);
}

fclose(log);
}

static void on_error_log(const char *msg, ...)
{
va_list argp;

assert(msg != NULL);

va_start(argp, msg);
verror_log(msg, argp);
va_end(argp);
}

static void log_err(const char *msg, ...)
{
va_list argp;

assert(msg != NULL);

va_start(argp, msg);
verror_log(msg, argp);
va_end(argp);
}

int main(void)
{
const char *string = "Test string";

on_error_log("Log test.... string\n");
log_err("Log test.... string\n");

on_error_log("string = '%s'\n", string);
log_err("string = '%s'\n", string);

return EXIT_SUCCESS;
}

--
Tor <torust [at] online [dot] no>

Apr 25 '07 #5

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: Renie83 | last post by:
Hi I really am going crazy! I'm using VBScript, ASP, and SQL My page reminds me of a shopping cart but looking at shopping cart examples has not helped! What I have is a page that brings in...
2
by: Timmins | last post by:
I have a date in a frame/page that i want to pass to another page. I can succefully pass a static value, i just can't pass a value from a text box. I tried to make everything public. I believe...
10
by: Steven Blair | last post by:
Hi, Quick overview of the problem: public bool Something( out DataSet ds ) { bool ret=false; try {
0
by: Wilhelm Pieper | last post by:
Hello, I want to setup a webservice. But before lauching the client webpage I'd like to fill up the clients menu with data from the server. So I created a reference inside the client project to...
6
by: Wijaya Edward | last post by:
Hi, How can I pass Array, Hash, and a plain variable in to a function at the same time. I come from Perl. Where as you probably know it is done like this: sub myfunc {
1
by: skillzero | last post by:
Is there a portable way to pass a va_list as a parameter to another function taking a variable argument list? I have a function that takes a printf-like format string and I'd like to use...
2
by: Alexander Eisenhuth | last post by:
Hallo Alltogether, I've searched in this mailing list, but it seems to me that there is no general approach to pass exceptions from one thread to another. I think most application do a unique...
0
by: fiveheads | last post by:
Hi guy, I'm Javascript beginner... Recently thinking to have a code, which can read a list of servers from EXCEL (XLS) file and search these servers from network and then pass the results into...
1
by: amitjain123 | last post by:
Hello Friends, I have list box and grid view on screen. on selection of list box item, value of selected item gets added into grid view through java script. Now I want to generate the XML...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.