The basic idea is to have a routine like printf(), which calls another
routine, like fprintf(), passing one argument in addition to the arguments
passed to it. The first routine to get called, which works fine, looks
like this:
myprintf(fmt, va_alist)
char *fmt;
va_dcl
{
va_list vap;
va_start(vap);
/* here I can pull of the arguments with no problem */
myfprintf(stdout,fmt,vap);
va_end(vap);
}
Here's what I've tried, which doesn't work, for myfprintf():
myfprintf(f, fmt, va_alist)
FILE *f;
char *fmt;
va_dcl
{
va_list vap;
va_start(vap);
/* at this point, the va_arg() routine doesn't return the arguments correctly */
va_end(vap)
}
Is there anyone out there who has a good handle on varargs that can tell
me the right (portable) way to do this? Is there someone with the source
to vprintf() with some insight?
Thanks,
Theo Pozzy, Corporate Microsystems, Inc.
...!decvax!dartvax!eleazar!cmi (UUCP) c...@eleazar.dartmouth (CSNET)
cmi%ele...@dartmouth.edu (ARPA) Box A-58, Hanover, NH, 03755 (USPS)
CompuServe (76267,413) (603) 448-5193 (BellNet)
--
Theo Pozzy, Corporate Microsystems, Inc.
...!decvax!dartvax!eleazar!cmi (UUCP) c...@eleazar.dartmouth (CSNET)
cmi%ele...@dartmouth.edu (ARPA) Box A-58, Hanover, NH, 03755 (USPS)
CompuServe (76267,413) (603) 448-5193 (BellNet)
myprintf(va_alist)
va_dcl
{
va_list vap;
char *fmt;
va_start(vap);
fmt = va_arg(vap, char *);
myfprintf(stdout, fmt, vap);
va_end(vap);
}
>myfprintf(f, fmt, va_alist)
>FILE *f;
>char *fmt;
>va_dcl
>{
>va_list vap;
>va_start(vap);
>/* at this point, the va_arg() routine doesn't return the arguments correctly */
>va_end(vap)
>}
This is where your major mistakes are.
myfprintf(f, fmt, vap)
FILE *f;
char *fmt;
va_list vap;
{
/* va_arg should work here */
}
Note that you may have to pass a pointer to vap on systems that
va_list is a structure but don't have structure passing.
--
Bob Larson Arpa: Bla...@Ecla.Usc.Edu bla...@skat.usc.edu
Uucp: {sdcrdcf,cit-vax}!oberon!skat!blarson
Prime mailing list: info-prime-request%fn...@ecla.usc.edu
oberon!fns1!info-prime-request
The basic trick (if I may phrase it so) is to have only one va_alist
parameter anywhere in the chain. printf() does not call fprintf();
printf() calls vfprintf():
myprintf(fmt, va_alist)
char *fmt;
va_dcl
{
va_list vap;
va_start(vap);
myvfprintf(stdout, fmt, vap);
va_end(vap);
}
myfprintf(f, fmt, va_alist)
FILE *f;
char *fmt;
va_dcl
{
va_list vap;
va_start(vap);
myvfprintf(f, fmt, vap);
va_end(vap)
}
myvfprintf(f, fmt, ap)
FILE *f;
char *fmt;
va_list ap;
{
...
}
--
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain: ch...@mimsy.umd.edu Path: uunet!mimsy!chris
void
myprintf( va_alist ) /* NOTE: do not declare any "fixed" args here */
va_dcl
{
void myfprintf();
char *fmt;
va_list ap;
va_start( ap );
fmt = va_arg( ap, char * ); /* pick up "fixed" arg like this */
/* access the first few arguments via va_arg, as needed */
myfprintf( stdout, fmt, ap );
va_end( ap );
}
void
myfprintf( f, fmt, ap )
FILE *f;
char *fmt;
va_list ap; /* NOTE: type must agree with caller! */
{
/* access the remaining arguments via va_arg, as needed */
}
Gee, I guess AT&T made a mistake, too, because that code linted quite happily
on a 3B2 running S5R3.1. 4.2BSD has nothing to do with it....
Fortunately, ANSI C repairs this deficiency; va_alist need not be the only
argument to a "stdargs" function. "va_start" takes an extra argument, which is
the last non-varargs parameter to the function; presumably, this is intended to
permit this to work on machines where "varargs" won't work if "va_alist" isn't
the only argument to the function (I presume they exist, although none of the
machines I've worked with, including my trusty Sun-4, have a problem with
this).
Guy Harris
{ihnp4, decvax, seismo, decwrl, ...}!sun!guy
g...@sun.com