This is a weird question, but is there a standard way to manipulate the contents of a va_list
before passing it to another function? For instance, suppose I have two functions, sum
and vsum
:
int vsum(int n, va_list ap) {
int total = 0;
for (int i = 0; i < n; ++i) {
total += va_arg(n, int);
return total;
}
int sum(int n, ...) {
va_list ap;
va_start(ap, n);
int total = vsum(n, ap);
va_end(ap);
return total;
}
If I call sum
as sum(4, 1, 2, 3, 4)
, I expect to get the result 10. Now let's suppose that instead of calling vsum
directly, sum
calls an intermediate function, vsum_stub
which does the following:
int vsum_stub(int n, va_list ap) {
va_list temp_ap;
va_copy(temp_ap, ap);
for (int i = 0; i < n; ++i) {
int *arg = &va_arg(ap, int);
*arg += 2;
}
va_end(temp_ap);
return vsum(n, ap);
}
Now when I call sum(4, 1, 2, 3, 4)
, I should get back the result 20, since vsum_stub
increments all of the values in the va_list
by 2. This doesn't compile of course since you can't take the address of the result of va_arg
. Is there another way to do this though? I'm working in C99.
Background:
I'm working on a library that does some pointer translation so that data may be stored on the heap in a more efficient format. Programs are compiled with a custom transformation which converts calls to library functions like printf
to my own stub functions (e.g., hc_printf
). hc_printf
needs to translate any pointer arguments (strings intended for %s
) before passing the arguments to the real printf
function.
Edit: Here's a code example. Let's say we have a string foo
. foo
is dynamically allocated with a modified version of malloc
which returns a fake pointer. The compiler modifies the program so that it can deal with fake pointers. So this works:
char *foo = fake_malloc(4);
fake_strcpy(foo, "foo");
I want to write a fake_vprintf
function like this (in pseudocode):
int fake_vprintf(const char *format, va_list args) {
for each pointer argument p in args
translate p to q, a real pointer to contiguous memory
replace p with q in args
}
return vprintf(format, args);
}
The program would call fake_vprintf
just like the original vprintf
using the fake pointer. fake_vprintf
translates the fake pointer to a real pointer that the real vprintf
can use.