[comp.sys.pyramid] Wrapper function to sprintf

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