[comp.lang.c] `va_dcl' macro question

maart@cs.vu.nl (Maarten Litmaath) (01/25/89)

Anybody got an example (of some weird architecture) to show why it has been
decided that no semicolon shall follow `va_dcl'?
On a Sun (4.3BSD), a VAX (4.3BSD) and a Mantra (SysV) the define for `va_dcl'
is simply:

	# define va_dcl int va_alist;

In these cases the semicolon could have been removed from the `define' and
added to the invocation:

	int	printf(fmt, va_alist)
	char	*fmt;
	va_dcl;
	{
		...
	}

To me this appears more natural.
-- 
Lee Harvey Oswald was a patsy.        |Maarten Litmaath @ VU Amsterdam:
                       Or a superman. |maart@cs.vu.nl, mcvax!botter!maart

gwyn@smoke.BRL.MIL (Doug Gwyn ) (01/27/89)

In article <1964@kappl.cs.vu.nl> maart@cs.vu.nl (Maarten Litmaath) writes:
>Anybody got an example (of some weird architecture) to show why it has been
>decided that no semicolon shall follow `va_dcl'?

No, but it's always been that way and nobody is going to change it now.

>	int	printf(fmt, va_alist)
>	char	*fmt;
>	va_dcl;
>	{
>		...
>	}

Apart from the question of the semicolon, this is wrong anyway.
It's not permissible to mix fixed parameter declarations with the
va_alist.  va_alist must stand alone as the only parameter, with
known parameters then being fetched from it via va_arg.  This of
course applies only to varargs; in ANSI C, one has at least one
fixed parameter and uses the ,... notation.

geoff@warwick.UUCP (Geoff Rimmer) (02/01/89)

In article <9507@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes:

>This of course applies only to varargs; in ANSI C, one has at least
>one fixed parameter and uses the ,... notation.

All I know about variable arguments in ANSI C is how to do prototypes,
and define the functions.  However, I don't know how to read each of
the arguments passed to the function.  Could someone email/post a
simple function that will take a variable number of strings, and then
print them to stdout one at a time.

i.e.

	void print_strings (char *str, ...)
	{
	...
	}

Geoff

	------------------------------------------------------------
	Geoff Rimmer, Computer Science, Warwick University, England.
			geoff@uk.ac.warwick.emerald

	"I'd like to go on with the rest of the song,
	 Describing this schmuck.
	 I'd like to go on, but I'm gonna throw up."
		- Roger Waters, Pros & Cons of Hitchhiking
	------------------------------------------------------------

gwyn@smoke.BRL.MIL (Doug Gwyn ) (02/03/89)

In article <991@ubu.warwick.UUCP> geoff@emerald.UUCP (Geoff Rimmer) writes:
>All I know about variable arguments in ANSI C is how to do prototypes,
>and define the functions.  However, I don't know how to read each of
>the arguments passed to the function.  Could someone email/post a
>simple function that will take a variable number of strings, and then
>print them to stdout one at a time.
>i.e.
>	void print_strings (char *str, ...)
>	{
>	...
>	}

Well, there has to be some way to tell when the argument list is
exhausted, which you didn't specify.  Let's assume that a null pointer
marks the end of the list.  Then here is how I would implement this:

#include	<stdio.h>
#if __STDC__
#include	<stdarg.h>
#else
#include	<varargs.h>
#define	const	/* nothing */
#endif

#if __STDC__
void					/* DESIGN BOTCH: should return status */
print_strings( register const char *str, ... )
#else
void
print_strings( va_alist )
	va_dcl
#endif
	{
#if !__STDC__
	register const char	*str;
#endif
	va_list		ap;

#if __STDC__
	va_start( ap, str );
#else
	va_start( ap );
	str = va_arg( ap, const char * );
#endif
	for ( ; str != NULL; str = va_arg( ap, const char * ) )
		(void)fputs( str, stdout );

	va_end( ap );
	}

gwyn@smoke.BRL.MIL (Doug Gwyn ) (02/03/89)

In article <9571@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes:
>print_strings( register const char *str, ... )

Oops, scratch the "register" in that.  It makes the example nonportable.

mark@jhereg.Jhereg.MN.ORG (Mark H. Colburn) (02/03/89)

In article <991@ubu.warwick.UUCP> geoff@emerald.UUCP (Geoff Rimmer) writes:
>
>All I know about variable arguments in ANSI C is how to do prototypes,
>and define the functions.  However, I don't know how to read each of
>the arguments passed to the function.  Could someone email/post a
>simple function that will take a variable number of strings, and then
>print them to stdout one at a time.
>
>i.e.
>
>	void print_strings (char *str, ...)
>	{
>	...
>	}


In ANSI (as well as most other existing varargs), there is no way to tell 
that you are at the end of the passed parameter list.  Therefore, most
varargs-type functions have some way of determining the number and type
of arguments that they were passed.  Routines like printf and scanf assume 
that there is one argument for each '%' which also specifies they parameter
type, other routines may use a parameter count or some other means of
relaying the number and types of arguments to the routine.

Therefore, your initial routine is impossible to code portably unless
the 'str' parameter has some indication as to the number of parameters
which were passed to the print_strings function.

If we add a parameter count to the print strings function, it will work,
and can be coded as such:


	#include <stdio.h>
	#include <sdtarg.h>

	void
	print_strings(int num, ...)
	{
	    va_list	va;

	    va_start(va, num);
	    while (num--) {
		puts(va_arg(va, char *));
	    }
	    va_end(va);
	}

It could then be called as such:

	print_strings(2, "hi", "there");
	print_strings(4, "this", "is", "a", "test");

Note, that the following call,

	print_strings(3, "this", "is", "a", "test");

would be completely legal, but would only print:

	this
	is
	a


If you wanted an error function, which allowed for printf() style error
messages, it could be coded like this:


	#include <stdio.h>
	#include <stdarg.h>

	void
	error(char *format, ...)
	{
	    va_list	va;

	    va_start(va, format);
	    vfprintf(stderr, format, va);
	    va_end(va);
	}


It's pretty easy once you see how to do it...


-- 
Mark H. Colburn                  "Look into a child's eye;
Minnetech Consulting, Inc.        there's no hate and there's no lie;
mark@jhereg.mn.org                there's no black and there's no white."