rick@sparky.IMD.Sterling.COM (Richard Ohnemus) (05/03/91)
In article <3099@cirrusl.UUCP> Rahul Dhesi <dhesi@cirrus.COM> writes: >Suppose A is a varargs function, and it uses the first argument >supplied, and passes on the rest to B, which is also a varargs >function. What is the right way to do it? The Sun varargs manual >entry is a little confusing to me. It 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." > >So should I be declaring a variable in A and passing its address to B? >A does not know many arguments it is receiving and passing on to B. >All that A knows is the type of the one argument that it itself uses. > >Sample code follows. > >#include <varargs.h> > >int A(va_alist) >va_dcl >{ > int i; > va_list ap; > > va_start(ap); > i = va_arg(ap, int); > ... use i locally, pass remaining args to B ... > B(&ap); <<<<==== Is this what the Sun man page wants? > va_end(arg); >} > >int B(va_alist) >va_dcl >{ > ... B uses its variable argument list which it receives from A ... >} >-- >Rahul Dhesi <dhesi@cirrus.COM> >UUCP: oliveb!cirrusl!dhesi Just pass the variable argument list pointer instead of the address of the pointer. The following sample code works (Saber-C doesn't complain about and I haven't had any core dumps yet.). #include <varargs.h> int A(va_alist) va_dcl { int i; va_list ap; va_start(ap); i = va_arg(ap, int); ... use i locally, pass remaining args to B ... B(ap); va_end(arg); } int B(args) va_list args; { char *cp; cp = va_arg(args, char *); ... etc. } -- I never receive credit for anything I write! (I'm an Ohnemus. 8-) Rick Ohnemus UUCP: uunet!sparky!rick Sterling Software IMD INTERNET: rick@sparky.IMD.Sterling.COM 1404 Ft. Crook Rd. South Phone: (402) 291-8300 Bellevue, NE. 68005-2969 FAX: (402) 291-4362
richard@aiai.ed.ac.uk (Richard Tobin) (05/03/91)
In article <1991May2.170148.12655@sparky.IMD.Sterling.COM> rick@sparky.IMD.Sterling.COM (Richard Ohnemus) writes: >In article <3099@cirrusl.UUCP> Rahul Dhesi <dhesi@cirrus.COM> writes: >>Suppose A is a varargs function, and it uses the first argument >>supplied, and passes on the rest to B, which is also a varargs >>function. What is the right way to do it? It can't be done. What Rahul wants is the equivalent of Lisp's "apply", and C doesn't have one. >Just pass the variable argument list pointer instead of the address of >the pointer. Note that he wanted to pass the arguments on to another varargs function, not one that took a single va_list argument. Imagine a function debug() which takes a "debugging level" and and some arguments that will be passed on to fprintf() if the level is high enough. For this particular case C provides the functions vfprintf() etc. If there were a (portable) way to do what Rahul wanted, those functions would be unnecessary. -- Richard Richard Tobin, JANET: R.Tobin@uk.ac.ed AI Applications Institute, ARPA: R.Tobin%uk.ac.ed@nsfnet-relay.ac.uk Edinburgh University. UUCP: ...!ukc!ed.ac.uk!R.Tobin
dhesi%cirrusl@oliveb.ATC.olivetti.com (Rahul Dhesi) (05/04/91)
After I posted my inquiry I realized that I was asking a
frequently-asked-question, and the FAQ postings already answered it. I
cancelled my posting, but not soon enough.
Briefly, the question was: if A and B are varags functions, how can
one portably write them so that A uses one argument and passes the rest
to B? The short answer is: you can't. The long answer is: you
cannot.
In <4606@skye.ed.ac.uk> richard@aiai.ed.ac.uk (Richard Tobin) writes:
If there were a (portable) way to do what Rahul wanted, those
functions [such as vfprintf] would be unnecessary.
Right. The problem is that A wants to use one argument and pass on the
rest to B, but A doesn't know how many arguments there are. So it
doesn't know how many to pass on to B.
Nonportably, A could fudge with the stack -- if the arguments were
guaranteed to be there -- and pass on most of the stack intact to B.
In assembly language you can probably do this quite easily. Even in C,
it should be possible to design compilers to allow this and to have
some way of telling the compiler that it should do this.
But nobody did, so there is no portable way of doing it in C.
--
Rahul Dhesi <dhesi@cirrus.COM>
UUCP: oliveb!cirrusl!dhesi
catfood@NCoast.ORG (Mark W. Schumann) (05/06/91)
richard@aiai.uucp (Richard Tobin) writes: >In article <1991May2.170148.12655@sparky.IMD.Sterling.COM> rick@sparky.IMD.Sterling.COM (Richard Ohnemus) writes: >>In article <3099@cirrusl.UUCP> Rahul Dhesi <dhesi@cirrus.COM> writes: >>>Suppose A is a varargs function, and it uses the first argument >>>supplied, and passes on the rest to B, which is also a varargs >>>function. What is the right way to do it? > >It can't be done. What Rahul wants is the equivalent of Lisp's >"apply", and C doesn't have one. > >>Just pass the variable argument list pointer instead of the address of >>the pointer. > >Note that he wanted to pass the arguments on to another varargs >function, not one that took a single va_list argument. > Actually, I think this can be done, but not in any guaranteed portable way. (To many, that means it can't be done. :-) ) -- ============================================================ Mark W. Schumann 3111 Mapledale Avenue, Cleveland 44109 USA Domain: catfood@ncoast.org UUCP: ...!mailrus!usenet.ins.cwru.edu!ncoast!catfood
gwyn@smoke.brl.mil (Doug Gwyn) (05/07/91)
In article <3110@cirrusl.UUCP> Rahul Dhesi <dhesi@cirrus.COM> writes: >Briefly, the question was: if A and B are varags functions, how can >one portably write them so that A uses one argument and passes the rest >to B? The short answer is: you can't. Sure you can, but you have to pass the remaining arguments via a va_list parameter, not scattered about. I do this all the time.
ray@philmtl.philips.ca (Ray Dunn) (05/17/91)
In referenced article, gwyn@smoke.brl.mil (Doug Gwyn) writes: >In article <3110@cirrusl.UUCP> Rahul Dhesi <dhesi@cirrus.COM> writes: >>Briefly, the question was: if A and B are varags functions, how can >>one portably write them so that A uses one argument and passes the rest >>to B? The short answer is: you can't. > >Sure you can, but you have to pass the remaining arguments via a va_list >parameter, not scattered about. I do this all the time. What I've found this means in practice is that when you write a varargs function it's usually best to write it as *two* functions, fn and vfn, where fn creates the va_list and passes it vfn where the work is actually done. Both fn and vfn can then be called as required. void fn(int arg, ...) { va_list argsp; va_start(argsp, arg); vfn(arg, argsp); va_end(argsp); } void vfn(int arg, va_list argsp) { /* body of code */ } Note that the example in the FAQ list defines a 'v' named function, vstrcat, as taking a variable number of arguments not a va_list. It's better style to keep to the implied convention that 'v' named functions take a va_list. -- Ray Dunn. | UUCP: ray@philmtl.philips.ca Philips Electronics Ltd. | ..!{uunet|philapd|philabs}!philmtl!ray 600 Dr Frederik Philips Blvd | TEL : (514) 744-8987 (Phonemail) St Laurent. Quebec. H4M 2S9 | FAX : (514) 744-9550 TLX: 05-824090
gwyn@smoke.brl.mil (Doug Gwyn) (05/17/91)
In article <1991May16.173145.2440@philmtl.philips.ca> ray@philmtl.philips.ca (Ray Dunn) writes:
-What I've found this means in practice is that when you write a varargs
-function it's usually best to write it as *two* functions, fn and vfn,
-where fn creates the va_list and passes it vfn where the work is actually
-done.
-Both fn and vfn can then be called as required.
Exactly right.