8/23/2010

08-23-10 - AutoPrintf v2

Okay, v2 works and confirmed doesn't give massive exe size bloat or compiler time death the way v1 does.

At the heart of v2 is a "fixed" way of doing varargs. The problem with varargs in C is that you don't
get the types of the variables passed in, or the number of them. Well there's no need to groan about
that because it's actually really trivial to fix. You just make a bunch of functions like :

for various number of args. Here autoToStringFunc(int nArgs, ...) is the basic vararg guy who will do
all the work, and we just want to help him out a bit. This kind of adapter could be used very generally
to make enhanced varargs functions. Here I only care about the "printf_type" of the variable, but
more generaly you could use type_info there. (you could also easily make abstract Objects to encapsulate
the args and pass through an array of Objects, so that the called function wouldn't have to be a stupid C
vararg function at all, but then it's harder to pass through to the old C funcs that still want varargs).

autoToString calls down to autoToStringSub, and uses autoArgConvert. autoArgConvert is a template that passes through basic types
and calls ToString() on other types. ToString is a template that knows the basic types, and the client can
extend it by adding ToString for their own types. If they don't, it will be a compile error.
StringToChar is a helper that turns a String into a char * and passes through anything else. We have to do it
in that double-call way so that the String can get allocated and stick around as a temporary until our whole call is done.

The next piece is how to implement autoToStringFunc() , which takes "enhanced varargs". We need to figure out
which pieces are format strings and do various types of printfs (including supporting %a for auto-typed printf).
The only tricky part of this is how to step around in the varargs. Here is the only place we have to use a
little bit of undefined behavior. First of all, think of the va_list as a pointer to a linked list.
Calling va_arg essentially advances the pointer one step. That's fine and stanard. But I assume that I can
then take that pointer and pass it on as a va_list which is the remaining args (see note *).

* : actually it looks like this is okay by the standard, I just have to call va_end after each function call then
SkipArgs back to where I was. I believe this is pointless busywork, but you can add it if you want to
be fully standard compliant.