richwill@swatsun.uucp (Rich Williamson) (02/19/88)
I'm trying to put together a simple formatted output routine for
X-Windows. I would like to be able to say something like this
MyXText( X, Y, formatString, arg1, ... , argn );
void
MyXText( X, Y, formatString, arg1, .... , argn )
int X;
int Y;
char *formatString;
??;
{
char TempString[100];
sprintf( TempString, formatString, arg1, ... , argn );
X-windows stuff here.
}
I would like to pass the necessary parameters to sprintf but I
don't know how to declare the arguments to MyXText. I don't know
how to declare a variable number of arguments. Is it even possible?
The family of printf() functions seem to be able to receive variable
arguments, so it would seem to possible.
K&R aren't much help. They say that it can be done but the resulting
code isn't portable. (p. 71) Do they mean that you have to pop
the arguments off the stack by hand? I don't need to do that, I
just want to pass the arguments transparently onto sprintf().
Thanks in advance for any helpful 'pointers'.
-- Richard Williamson
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
UUCP: seismo!bpa!swatsun!richwill
CSNET: richwill%swatsun.swarthmore.edu@relay.cs.net
--
UUCP: seismo!bpa!swatsun!richwill
CSNET: richwill%swatsun.swarthmore.edu@relay.cs.net
schwartz@gondor.cs.psu.edu (Scott E. Schwartz) (02/20/88)
In article <1608@byzantium.UUCP> richwill@byzantium.UUCP (Rich Williamson) writes: >I'm trying to put together a simple formatted output routine for >X-Windows. I would like to be able to say something like this > MyXText( X, Y, formatString, arg1, ... , argn ); >I would like to pass the necessary parameters to sprintf but I >don't know how to declare the arguments to MyXText. I don't know >how to declare a variable number of arguments. Is it even possible? >The family of printf() functions seem to be able to receive variable >arguments, so it would seem to possible. Hi Rich, how's life back at Swat? Anyway, you should look at the man page for varargs. Varargs is the only portable way to pass a varying number of arguments to a procedure. Since you want to use sprintf inside of MyXText, and since you are using a Sun with System V compatible libraries, you should strongly consider using vsprintf(), which directly takes the (varargs definded) parameters to MyXText, saving you from having to unpack arg1...argn and pass them to sprintf(). -- Scott Schwartz schwartz@gondor.cs.psu.edu
tim@amdcad.AMD.COM (Tim Olson) (02/20/88)
In article <1608@byzantium.UUCP> richwill@byzantium.UUCP (Rich Williamson) writes: | I would like to pass the necessary parameters to sprintf but I | don't know how to declare the arguments to MyXText. I don't know | how to declare a variable number of arguments. Is it even possible? | The family of printf() functions seem to be able to receive variable | arguments, so it would seem to possible. Some C libraries supply the vprintf, vfprintf, and vsprintf routines. These use the varargs facility to print a variable number of parameters. -- Tim Olson Advanced Micro Devices (tim@amdcad.amd.com)
hst@mhres.mh.nl (Klaas Hemstra) (02/23/88)
Try using the vsprintf() function together with varargs.
Example:
MyXText( X, Y, formatString, va_alist)
....
va_dcl
{ char TempString[100];
va_list args;
va_start(args);
vsprintf(TempString , formatString, args);
va_end(args);
}
Note that you have to include the varargs.h file. This file is present in most
Unix systems and also with most non-Unix C compilers.
Be carefull using varargs !! Recently I had some trouble using them.
If you think they are REALLY flexible you are wrong.
e.g.: You have a function accepting a variable number of arguments with
the va_alist declaration. Then you can call this function with (..,a1,a2,...).
But if you want to call the function from another function which also accepts
a variable number of arguments, you can NOT pass that variable number of
arguments to the first function mentioned. This is probably the reason
why vprintf,vfprintf & vsprintf exist.
Note that on some of the Unix systems I tried this was possible but not on all
of them ! (I don't want a discussion on where you can and where you can't use
this way of varargs passing).
friedl@vsi.UUCP (Stephen J. Friedl) (02/26/88)
In article <1632@mhres.mh.nl>, hst@mhres.mh.nl (Klaas Hemstra) writes: > Try using the vsprintf() function together with varargs. > Example: > > MyXText( X, Y, formatString, va_alist) > .... > va_dcl > { char TempString[100]; > va_list args; > > va_start(args); > vsprintf(TempString , formatString, args); > > va_end(args); > > } I think you are better with: MyXText(va_alist) va_dcl { char buf[256]; /* buffer to format to */ int x, y; /* X/Y location */ char *fmt; /* printf format string */ va_args args; va_start(args); x = va_arg(args, int); /* GET... */ y = va_arg(args, int); /* .. ALL... */ fmt = va_arg(args, char *); /* .... ARGS.. */ vsprintf(buf, fmt, args); va_end(args); } I have no specific reason to doubt the portability, but it strikes me that since args are so crazy on various machines (stack grows up, stack grows down, params passed in registers, etc.) that letting varargs handle *all* the details would not be a bad idea. Just a thought, Steve -- Life : Stephen J. Friedl @ V-Systems, Inc/Santa Ana, CA *Hi Mom* CSNet: friedl%vsi.uucp@kent.edu ARPA: friedl%vsi.uucp@uunet.uu.net uucp : {kentvax, uunet, attmail, ihnp4!amdcad!uport}!vsi!friedl
gwyn@brl-smoke.ARPA (Doug Gwyn ) (02/28/88)
In article <51@vsi.UUCP> friedl@vsi.UUCP (Stephen J. Friedl) writes: > I have no specific reason to doubt the portability, but it >strikes me that since args are so crazy on various machines (stack >grows up, stack grows down, params passed in registers, etc.) >that letting varargs handle *all* the details would not be a bad >idea. In fact that's the right way to use varargs. Declaring part of the argument list is the wrong way. (This is the opposite of ANSI C <stdarg.h> macros, where there MUST be at least one "anchor" argument declared right before the variadic part.)
dheller@cory.Berkeley.EDU (Dan Heller) (02/28/88)
In article <7361@brl-smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes: >In article <51@vsi.UUCP> friedl@vsi.UUCP (Stephen J. Friedl) writes: >> I have no specific reason to doubt the portability, but it >>strikes me that since args are so crazy on various machines (stack >>grows up, stack grows down, params passed in registers, etc.) >>that letting varargs handle *all* the details would not be a bad >>idea. > >In fact that's the right way to use varargs. Declaring part of >the argument list is the wrong way. (This is the opposite of >ANSI C <stdarg.h> macros, where there MUST be at least one >"anchor" argument declared right before the variadic part.) I have reservations about wanting to use varargs for _all_ the arguments passed to the function. While lint be be told not to "complain", it avoids lint's ability to find potential mistakes in the calling routines. The example that the original poster used was a good one (altho I don't remember it exactly, it went something like): function(X, Y, fmt, args) int X, Y; char *fmt; va_dcl Next, to help the lint (and the reader of someone else's code), we can add: /*VARARGS3*/ function(X, Y, fmt, args) Stephan has an interesting point: >>strikes me that since args are so crazy on various machines (stack >>grows up, stack grows down, params passed in registers, etc.) >>that letting varargs handle *all* the details would not be a bad >>idea. I refute that claiming that it shouldn't be necessary to worry about it. A good compiler will pass the arguments correctly and the architecture should be completely transparent to the programmer. Declaring the _known_ arguments makes the code more easily linted and more easily understood by others readers. ...dan
gwyn@brl-smoke.ARPA (Doug Gwyn ) (02/28/88)
In article <1078@pasteur.Berkeley.Edu> dheller@cory.Berkeley.EDU.UUCP (Dan Heller) writes: >I refute that claiming that it shouldn't be necessary to worry about it. But since in fact it is necessary to worry about it, that's not a good refutation. >A good compiler will pass the arguments correctly and the architecture >should be completely transparent to the programmer. Sorry, in order for the architecture to be "transparent" across all systems, you have to use varargs as I said. >Declaring the _known_ arguments makes the code more easily linted and >more easily understood by others readers. Which doesn't do much good if it won't run.
blarson@skat.usc.edu (Bob Larson) (02/28/88)
In article <1078@pasteur.Berkeley.Edu> dheller@cory.Berkeley.EDU.UUCP (Dan Heller) writes: >In article <7361@brl-smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes: >>In article <51@vsi.UUCP> friedl@vsi.UUCP (Stephen J. Friedl) writes: >>>that letting varargs handle *all* the details would not be a bad >>>idea. >>In fact that's the right way to use varargs. Declaring part of >>the argument list is the wrong way. (This is the opposite of >>ANSI C <stdarg.h> macros, where there MUST be at least one >>"anchor" argument declared right before the variadic part.) >I have reservations about wanting to use varargs for _all_ the arguments >passed to the function. While lint be be told not to "complain", it avoids >lint's ability to find potential mistakes in the calling routines. The versions of lint I have used document, but do not support /*VARARGS0*/ (Sun 4.0 beta reportadly fixes this bug.) Lint will complain about correct use of varargs because of this bug. Writing non-portable code to shut lint up is something I consider very poor practice. >I refute that claiming that it shouldn't be necessary to worry about >it. Claiming something doesn't make it so. I claim that compiler writers shouldn't have to worry about non-portable code. (Note that my claim seems to be supported by the ANSI C commitee.) Guy Harris and I had a long email discussion relating to this, and there were only two cases where he was able to convince me /*VARARGSn*/ where n!=0 should be allowed: where portability checking was explictily turned off, and lint libraries. -- Bob Larson Arpa: Blarson@Ecla.Usc.Edu blarson@skat.usc.edu Uucp: {sdcrdcf,cit-vax}!oberon!skat!blarson Prime mailing list: info-prime-request%fns1@ecla.usc.edu oberon!fns1!info-prime-request
ta-dw30@cunixa.cc.columbia.edu (David Worenklein) (05/14/91)
I know I can pull a variable number of arguments off of the stack using va_... but how do I know how many arguments are there? Is there any way to get the C compiler to push all the arguments and then push the number of (arguments, bytes, etc.) pushed? Thanks. PS I'm using Symantec Think C v4 so if it has some feature that ANSI doesn't... =============================================================================== David C Worenklein | No one could tell me where my soul might be; Columbia College '93 | I searched for God, but he eluded me; in the City of New York | I sought my brother out, and found all three. -Crosby
steve@taumet.com (Stephen Clamage) (05/15/91)
ta-dw30@cunixa.cc.columbia.edu (David Worenklein) writes: >I know I can pull a variable number of arguments off of the stack using va_... >but how do I know how many arguments are there? Is there any way to get the >C compiler to push all the arguments and then push the number of (arguments, >bytes, etc.) pushed? >PS I'm using Symantec Think C v4 so if it has some feature that ANSI doesn't... There is no portable way to do this; I don't know whether Think C provides some extension. One of the requirements of writing such a function is that one of the fixed arguments must explicitly or implicitly provide information about the number and type of the arguments. For example, the printf/scanf families interpret the fixed string argument to determine what the remaining arguments are. If you have a function which expects a variable number of args all of the same type, it would be sufficient to have a fixed arg containing the number of args. Alternatively, if there is an "impossible" value for the arg type (NULL pointer, a count of -1), you can use that value as a flag for the end of the args. -- Steve Clamage, TauMetric Corp, steve@taumet.com
daw@cbnewsh.att.com (David Wolverton) (05/15/91)
In article <726@taumet.com>, steve@taumet.com (Stephen Clamage) writes: > ta-dw30@cunixa.cc.columbia.edu (David Worenklein) writes: > > >I know I can pull a variable number of arguments off of the stack using va_... > There is no portable way to do this; I don't know whether Think C > provides some extension. > [good suggestions deleted] Please think long and hard about using such an extension, even if it is available. You'll save a lot of work on the part of the person who has to port the code next year to another compiler or environment that doesn't have the neat extension. And remember, that person may be you. Stephen gives some good approaches to identifying the length and/or end of the list -- use them! Dave Wolverton David.Wolverton@att.com
dave@aspect.UUCP (Dave Corcoran) (05/20/91)
In article <1991May13.210257.20240@cunixf.cc.columbia.edu>, ta-dw30@cunixa.cc.columbia.edu (David Worenklein) writes: > I know I can pull a variable number of arguments off of the stack using va_... > but how do I know how many arguments are there? Is there any way to get the > C compiler to push all the arguments and then push the number of (arguments, > Thanks. Email bounced so... m4 can help if you want to pass the argument count as the first argument run this through m4 (/usr/5bin/m4 if BSD): --------------------8<-------------------- define(`numarg_',`$#,$*') func(numarg_(asdf,qwer,wqer,s,dfa,fdsa,qwre,sdfa,f,qwer,ewrq,sfd)) func(numarg_(asdf,asd,f)) func(numarg_(qwer,"qwer asfd",&asdf,*vzxc)) func(numarg_("caveat:,commas,in,quotes,are,computed,in,count")) --------------------8<-------------------- -- David Corcoran -@@ uunet!aspect!dave ~ Having the right to do something is not the same as being right in doing it. -- C.K. Chesterson