[comp.lang.c] Questions on vsprintf

gnu@hoptoad.uucp (John Gilmore) (07/28/87)

Tonight I reimplemented the curses routine printw(), which used to call
into the guts of stdio, using vsprintf().  I could not reimplement
scanw() because there is apparently no vsscanf().  If not, why not?  I
looked both in the Sun documentation (Rel 3.3) and in the draft C
standard.  This seems like an obvious omission.

Also, I noticed that the Sun documentation for varargs says:

       "The argument list (or its remainder) can be passed to another
	function using a pointer to a variable of type va_list -- in
	which case a call to va_arg in the subroutine advances the
	argument-list pointer with respect to the caller as well."

On the other hand, vsprintf() wants the argument list passed as a
variable of type va_list, not a pointer to such a variable.  It is not
clear what effect this has on the argument pointer, since the type of
va_list is unknown, and vsprintf() doesn't document the effect.

In the draft C standard, it specifies:

	"The type declared is va_list which is an array type...
	The variable ap may be passed as an argument to another function."

(ap refers to the parameter declared as va_list.)  If passed to another
function, the array will be converted to a pointer, which presumably
means that calls to va_arg in the subroutine would also advance
the argument pointer, as documented in SunOS.  The standard should
specify this behaviour rather than leaving it to be inferred.

(Actually the standard should standardize <varargs.h> rather than a newly
invented, incompatible construction.)
-- 
{dasys1,ncoast,well,sun,ihnp4}!hoptoad!gnu	     gnu@postgres.berkeley.edu
Alt.all: the alternative radio of the Usenet.

gwyn@brl-smoke.ARPA (Doug Gwyn ) (07/28/87)

In article <2545@hoptoad.uucp> gnu@hoptoad.uucp (John Gilmore) writes:
>... there is apparently no vsscanf().  If not, why not?

I suspect mainly because the scanf() family are unsafe functions that
are only provided because so much existing code already uses them.
There is little interest in adding to that family.

>In the draft C standard, it specifies:
>	"The type declared is va_list which is an array type...
>	The variable ap may be passed as an argument to another function."
>(ap refers to the parameter declared as va_list.)  If passed to another
>function, the array will be converted to a pointer, which presumably
>means that calls to va_arg in the subroutine would also advance
>the argument pointer, as documented in SunOS.  The standard should
>specify this behaviour rather than leaving it to be inferred.

The argument walker is stored in the array in the parent routine.
The standard does not purport to be a tutorial.  Generally it adds
explanations only where it is felt there are grounds for confusion
or misinterpretation.  The whole point of requiring va_list to be an
array type (and no other) is to make clear the exact semantics to
be expected of ap.  It would perhaps be appropriate to have words
to this effect in the Rationale, but the Standard is unambiguous on
this point.

>(Actually the standard should standardize <varargs.h> rather than a newly
>invented, incompatible construction.)

That is uncalled for.  I assure you that X3J11 does not go about
changing things without good reason.  They did start with <varargs.h>,
but found that it was simply not suitable for the more rigorous ", ..."
approach to variable argument lists, as well as to accommodate unusual
CPU architectures.  It is important to realize that it is only under a
simple, uniform implementation such as most VAX and MC68000 C systems
that the new X3J11 mechanisms duplicate existing functionality with no
substantial change to the underlying mechanisms.  In the more general
setting, a variable-argument function is a NEW and DIFFERENT beast than
what you have seen before.  It may be implemented quite differently from
a fixed-argument function.  The <stdarg.h> mechanism is specifically
designed to support this new and different beast, which in turn was
introduced out of necessity (under some circumstances) to let the
implementation know about the different essential nature of varargs
functions.  <stdarg.h> went through many design iterations before
stabilizing in the form it now has (very slightly amended on 15-May-1987).

I suspect that C implementations on the more trivial architectures will
provide both <varargs.h> and <stdarg.h>, but the v*printf() functions
have to know what type they're getting for ap, so they will no longer
be usable with <varargs.h> va_list variables.  The persistence of the
names va_* reflects the evolution from <varargs.h> and is perhaps
unfortunate at this point; for a while X3J11 was hoping to be able to
guarantee full compatibility between the two approaches.

Disclaimer:  This is not to be construed as an official X3J11 response.
Send public comments to Tom Plum; there is still some (slim) chance that
the committee will consider them before the next public review even
though it is way past the official comment period for the last public
draft.