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.
Aha, as I understand, your problem is creating a new va_list
argument to pass on to the standard vprintf
functions. Which in turn, will require you to modify each member of the list. However, since there is no element wise fetch/edit/insert operation for such a list you are stuck.
I don't really see any way of doing this. Of course, you can create a vprintf
apply the transformations in situ, one argument at a time. My suggestion will be: Reimplement all such standard library functions -- at any rate you are writing wrappers. This involves some work, but you are already doing a part of it with hc_printf
etc, so why not go the whole distance (and guess what save on a function call!).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With