atj@prism.UUCP (02/24/88)
Hi, I am having a little problem with developing a "wrapper" to sprintf.
What I wish to do is write a "dialog_box" routine that takes the
same parameters as printf. So, I have the following:
dialog_box(cs, args)
char *cs;
{
char buffer[512];
sprintf(buffer, cs, args);
.
.
.
}
/* anything obviously wrong with this? */
What happens is that only the first arg is formatted correctly.
This is on a Pyramid 9820, OSx 4.0 (BSD universe)
Thanks.
--
Alex T. Jenkins
Mirror Systems, Cambridge Massachusetts atj@mirror.TMC.COM
rnovak@pyrnova (Robert E. Novak) (03/01/88)
In article <232400003@prism> atj@prism.UUCP writes: >Hi, I am having a little problem with developing a "wrapper" to sprintf. >What I wish to do is write a "dialog_box" routine that takes the >same parameters as printf. So, I have the following: >dialog_box(cs, args) >char *cs; >{ > char buffer[512]; > sprintf(buffer, cs, args); >} >/* anything obviously wrong with this? */ > >What happens is that only the first arg is formatted correctly. >This is on a Pyramid 9820, OSx 4.0 (BSD universe) >Thanks. >Alex T. Jenkins >Mirror Systems, Cambridge Massachusetts atj@mirror.TMC.COM VARARGS(3-ucb) Pyramid OSx Operating System VARARGS(3-ucb) NAME varargs - variable argument list SYNOPSIS #include <varargs.h> function(va_alist) va_dcl va_list pvar; va_start(pvar); f = va_arg(pvar, type); va_end(pvar); DESCRIPTION This set of macros provides a means of writing portable pro- cedures that accept variable argument lists. Routines hav- ing variable argument lists (such as printf(3)) that do not use varargs are inherently nonportable, since different machines use different argument passing conventions.
mechjgh@tness1.UUCP (Greg Hackney 214+464-2771) (03/03/88)
In article <232400003@prism> atj@prism.UUCP writes: > >Hi, I am having a little problem with developing a "wrapper" to sprintf. >What I wish to do is write a "dialog_box" routine that takes the >same parameters as printf. So, I have the following: >dialog_box(cs, args) >char *cs; >{ > char buffer[512]; > > sprintf(buffer, cs, args); I couldn't figure out how to pass an array of pointers to sprintf() and make it work correctly, but here's a dippy way that does work. -- Greg Hackney Southwestern Bell telephone Co. mechjgh@tness1.UUCP ---------<cut here>--------- #include <stdio.h> #include <varargs.h> main() { dialog("%s\t%s\t%s", "one", "two", "three"); } char * dialog(format,va_alist) char *format; va_dcl { va_list ap; char *args[10]; char buffer[512]; int argcount = 0; va_start(ap); while((args[argcount++] = va_arg(ap, char *)) != (char *)NULL) ; va_end(ap); sprintf(buffer,format,args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]); printf("%s\n",buffer); return(buffer); } -------<end of dippiness>-----
romain@pyrnj.uucp (Romain Kang) (03/03/88)
varargs is indeed the correct solution, though the man page says
nothing about nested variadic functions. This is probably trivial for
comp.lang.c junkies, but it's still easy to use varargs non-portably.
The correct translation of your function is
#include <varargs.h>
dialog_box(cs, va_alist)
char *cs;
va_dcl
{
char buffer[512];
sprintf(buffer, cs, va_alist);
.
}
However, it's easy to get wrong. The following doesn't look
unreasonable -- it may even work on a VAX -- but probably fails on a
Sun-3, which isn't such a radical box. It definitely doesn't work
on a Pyramid...
va_list ap;
va_start(ap);
sprintf(buffer, cs, ap);
va_end(ap);
--
Romain Kang {allegra,cmcl2,pyramid,rutgers}!pyrnj!romain
Pyramid Technology Corp. / 10 Woodbridge Center. Dr / Woodbridge NJ 07095
"Eggheads unite! You have nothing to lose but your yolks!" -Adlai Stevenson
chris@MIMSY.UMD.EDU (Chris Torek) (03/04/88)
I am afraid I have to agree with Greg Hackney's own description of his method: I couldn't figure out how to pass an array of pointers to sprintf() and make it work correctly, but here's a dippy way that does work. The reason you cannot do this `correctly' is simple. sprintf takes a variable argument list; the desired `wrapper' function also takes a variable argument list; but there is no way to say `take my argument list, whatever it may have been, package it up, and send it on to this other function'. In other words, the only correct call to sprintf is `direct' one. There *is* a way to implement the desired `dialog' function, however. A careful scan of the manuals reveals the `vsprintf' function. (This is in SysV, at any rate, and an equivalent 4BSD version appears below. The 4BSD version is not Officially Approved.) #include <stdio.h> #include <varargs.h> /* char *dialog(char *fmt, ...); */ char *dialog(); main() { (void) dialog("%s\t%s\t%s", "one", "two", "three"); } char * dialog(va_alist) va_dcl { va_list ap; char *format; char buffer[512]; /* this had best be big enough */ va_start(ap); format = va_arg(ap, char *); (void) vsprintf(buffer, format, ap); va_end(ap); printf("%s\n", buffer); return (buffer); } /* if you need it: */ #ifdef notdef int vsprintf(str, fmt, arg) char *str, *fmt; va_list arg; { FILE f; int ret; f._flag = _IOSTRG; /* leave out _IOWRT to avoid libc bug */ f._base = f._ptr = str; ret = _doprnt(fmt, arg, &f); *f._ptr = 0; return (ret); } #endif
mechjgh@tness1.UUCP (Greg Hackney 214+464-2771) (03/06/88)
In article <8803040308.AA02292@mimsy.umd.edu> chris@MIMSY.UMD.EDU (Chris Torek) writes: >I am afraid I have to agree with Greg Hackney's own description of >his method: > > I couldn't figure out how to pass an array of pointers to sprintf() > and make it work correctly, but here's a dippy way that does work. Ouch Chris. >There *is* a way to implement the desired `dialog' function, however. >A careful scan of the manuals reveals the `vsprintf' function. >/* if you need it: */ >#ifdef notdef >int >vsprintf(str, fmt, arg) > char *str, *fmt; > va_list arg; >{ > FILE f; > int ret; > > f._flag = _IOSTRG; /* leave out _IOWRT to avoid libc bug */ > f._base = f._ptr = str; > ret = _doprnt(fmt, arg, &f); > *f._ptr = 0; > return (ret); >} >#endif The code (vsprintf) does work in the SysV universe, but there were 2 lines that needed to be added to make it work in the Pyramid BSD environment... #include <values.h> f._cnt = MAXINT; -- Greg Hackney Southwestern Bell Telephone Co. Dallas, Texas mechjgh@tness1.UUCP {ihnp4,bellcore,killer}!tness1!mechjgh Newsgroups: comp.sys.pyramid Subject: Re: Wrapper function to sprintf Summary: Expires: References: <8803040308.AA02292@mimsy.umd.edu> Sender: Reply-To: mechjgh@tness1.UUCP (Greg Hackney) Followup-To: Distribution: Organization: S.W. Bell, Network Engineering, Dallas, Texas Keywords: In article <8803040308.AA02292@mimsy.umd.edu> chris@MIMSY.UMD.EDU (Chris Torek) writes: >I am afraid I have to agree with Greg Hackney's own description of >his method: > > I couldn't figure out how to pass an array of pointers to sprintf() > and make it work correctly, but here's a dippy way that does work. Ouch Chris. >There *is* a way to implement the desired `dialog' function, however. >A careful scan of the manuals reveals the `vsprintf' function. >/* if you need it: */ >#ifdef notdef >int >vsprintf(str, fmt, arg) > char *str, *fmt; > va_list arg; >{ > FILE f; > int ret; > > f._flag = _IOSTRG; /* leave out _IOWRT to avoid libc bug */ > f._base = f._ptr = str; > ret = _doprnt(fmt, arg, &f); > *f._ptr = 0; > return (ret); >} >#endif The code (vsprintf) does work in the SysV universe, but there were 2 lines that needed to be added to make it work in the Pyramid BSD environment... #include <values.h> f._cnt = MAXINT; -- Greg Hackney Southwestern Bell Telephone Co. Dallas, Texas mechjgh@tness1.UUCP {ihnp4,bellcore,killer}!tness1!mechjgh