[net.lang.c] varargs fails on typedefs

brett@wjvax.UUCP (Brett Galloway) (07/29/86)

I have a complaint about the a shortcoming of the standard varargs
package (to allow use of variable nos. of arguments).  The varargs package
uses a line of the form

	var = va_arg(va,<type>)

to grab the next (variable) argument, where va is the variable argument
pointer maintained by the varargs package, and <type> is the type of the
next argument.

The problem is related to C's argument promotion; namely, that it promotes
char and short arguments to int's and float to double.  Because the varargs
package is a macro package, an expression of the form

	var = va_arg(va,short)

fails, because, even if the caller tried to pass a short, it got converted
to an int, and the va_arg macro will fail because it will not pick up all
the bits of the int (assuming (sizeof(short) < sizeof(int))).  So far, this
is not deadly; you just remember never to have variable arguments that
are "promotable"; i.e., always use int's or double's.

The problem appears when you use a typedef.  Depending on whether the
typedef was promotable or not, a variable argument of the type will or
will not fail.  For example, I may do the following:

	typedef	int	NUMBER;
	...
	NUMBER	val;
	...
	foo(val);
	...
	foo(va_alist)
	va_dcl
	...
	NUMBER	value;
	...
	value = va_arg(va,NUMBER);

the latter part of this fragment is a function foo() with a variable
argument of type NUMBER.  If, in fact, NUMBER was an int, this will work.
If NUMBER was a short, it will fail.  This makes the typedef completely
useless.

To fix this problem, I propose a promote() operator, as follows:

	"promote(char)" => "int"
	"promote(short)" => "int"
	"promote(int)" => "int"
	"promote(float)" => "double"
	"promote(NUMBER)" => <whatever NUMBER typedef'd as>
	etc.

An operator like this is REQUIRED to write a varargs package that works
with typedef'd types.  Note that there is NO way to emulate promote() with
a macro.

-- 
-------------
Brett Galloway
{pesnta,twg,ios,qubix,turtlevax,tymix,vecpyr,certes,isi}!wjvax!brett

rbj@icst-cmr (Root Boy Jim) (07/29/86)

	This makes the typedef completely useless.

Only for varargs use. You can always have *two* typedefs, one for
definitions, and one for argument declarations. I know, yuk!

	To fix this problem, I propose a promote() operator, as follows:

Clearly, as you say, there is no way to emulate this. On the other hand,
this is done so rarely as to be tolerated the way it is. Do you really
want to muck up the language with rarely used constructs?

As a side issue, routines requiring varargs are frowned on anyway.

	(Root Boy) Jim Cottrell		<rbj@icst-cmr.arpa>
On the road, ZIPPY is a pinhead without a purpose, but never without a POINT.

brett@wjvax.UUCP (Brett Galloway) (07/30/86)

Doug Gwyn <seismo!BRL.ARPA!gwyn> sent me E-mail responding to my posting
about the need for a promote() operator to implement varargs.  Unforunately,
our mailer is broken, so I cannot respond privately.  In any event, I
believe that his response is of interest:

>This is the second such suggestion in recent weeks.
>I think we should be careful to distinguish between what the
>application code/programmer sees for an interface and
>what the C runtime implementer needs for his implementation.

><varargs.h> can be used safely if the programmer specifies
>the correct (possibly widened) type and if he restricts himself
>to the simpler data types.  X3J11 has designed <stdarg.h> to
>replace <varargs.h>, but there is still room for debate about
>the current design.

>Statements such as "<varargs.h> cannot be implemented without
>a promote() or alignof() operator" are simply false.  The
>existence of such operators would not even be sufficient for some
>architectures.  Rather than specify such fine-grained details
>of use only for implementing varargs, X3J11 is leaving it up
>to the implementor how he pulls this trick, and is specifying
>only the application code/programmer visible interface.  If
>this interface is properly designed, it will be implementable
>"somehow" on every significant architecture (although perhaps
>not purely in C).

As might be guessed, I disagree.  Of course, varargs can be implemented
without a promote() or alignof() operator; it is so implemented now.
However, it imposes the restrictions that Doug cites: "if the programmer
specifies the correct (possibly widened) type and if he restricts himself to
the simpler data types."

I argue that a promote() operator is necessary to remove these restrictions.
My article referred to using typedef'd types in varargs, and, in fact, without
a promote() operator, using typedef'd types in varargs is impossible.  Note
that promote() is a necessary condition; not a sufficient condition.

In short, I believe that X3J11, by omitting the (normally invisible) promote()
operator, is forcing itself to limit the usefulness of the (visible) stdarg
interface.

-- 
-------------
Brett Galloway
{pesnta,twg,ios,qubix,turtlevax,tymix,vecpyr,certes,isi}!wjvax!brett

brett@wjvax.UUCP (Brett Galloway) (07/31/86)

In article <2640@brl-smoke.ARPA> version B 2.10.3 4.3bsd-beta 6/6/85; site wjvax.wjvax.UUCP wjvax!qubix!saber!sun!decwrl!pyramid!hplabs!tektronix!uw-beaver!cornell!rochester!seismo!lll-crg!caip!brl-adm!brl-smoke!smoke!rbj@icst-cmr rbj@icst-cmr (Root Boy Jim) writes:
>>	This makes the typedef completely useless.
>Only for varargs use. You can always have *two* typedefs, one for
>definitions, and one for argument declarations. I know, yuk!
>>	To fix this problem, I propose a promote() operator, as follows:
>Clearly, as you say, there is no way to emulate this. On the other hand,
>this is done so rarely as to be tolerated the way it is. Do you really
>want to muck up the language with rarely used constructs?
>
>As a side issue, routines requiring varargs are frowned on anyway.

This is probably a question of varargs' role more than anything else.  I find
varargs useful, and therefor use it.  When I do, I find the restriction that
the user know about argument type promotion annoying, especially since the
compiler knows about type promotion already.

Apparently, you find varargs a kludge (you frown on it), and so label an
enhancement to C that would generalize variable argument parsing
"mucking up" the language.

Presumably, since varargs is being standardized (as stdarg), the X3J11
committee finds it to be a feature and not a kludge.  In that case, now
is the time to generalize the stdarg interface, and that requires (a)
new operator(s) in C.

-- 
-------------
Brett Galloway
{pesnta,twg,ios,qubix,turtlevax,tymix,vecpyr,certes,isi}!wjvax!brett