_print/_doprnt; curses on sys III

Tony L. Hansen hansen at pegasus.UUCP
Fri Jul 6 15:17:41 AEST 1984


Golly, no one bit after two weeks.

> Gee guys ... I wouild like to see you implement something
> like printw *correctly* without calling _doprnt.  I do NOT
> consider limiting the number of format items to 10 (or any
> other upper limit) a correct implementation.

I'd be glad to, using the v*printf() facility now fully documented and
supported as part of System Vr2:

	#include <stdio.h>
	#include <varargs.h>

	printw (va_alist)
	va_dcl
	{
	    va_list ap;
	    WINDOW *win;
	    char *fmt;
	    char buffer[BUFSIZ];

	    va_start(ap);
	    win = va_arg(ap, WINDOW *);
	    fmt = va_arg(ap,char *);
	    vsprintf(buffer, fmt, ap);
	    va_end(ap);
	    return waddstr(win,buffer);
	}

I think that that's as portable an implementation as you're going to get,
assuming that you have varargs.h on your system, modulo Henry Spencer's
comments on varargs.h:

> Not even the varargs.h machinery is workable on all machines, and
> the various more simplistic schemes are much less portable.


The REAL kicker is that you need vsprintf(). In System Vr2, it is
implemented using _doprnt on the Vaxen, using an assembly language routine
(not called _doprnt) on the AT&T 3b20, and I don't know what else on the
other machines that System Vr2 is available on. The point is that is to be
implemented using whatever underlying mechanism is available for the rest of
your stdio implementation.

So, if you don't have v*printf() on your system, here is a version of
vsprintf() that should work with the _doprnt() that comes with 4.xBSD, V7
and System V, rewritten from some public domain software that I had lying
around:

	#include <stdio.h>
	#ifdef BSD
	# define MAXINT 32767
	#else
	# include <values.h>
	#endif BSD
	#include <varargs.h>

	vsprintf(buffer, fmt, ap)
	char *buffer, *fmt;
	va_list ap;
	{
	    FILE temp;
	    int count;
	    extern int _doprnt();

	    temp._cnt = MAXINT;
	#ifdef BSD
	    temp._flag = _IOSTRG | _IOWRT;
	    temp._ptr = buffer;
	#else
	    temp._base = temp._ptr = (unsigned char *) buffer;
	    temp._flag = _IOWRT;
	#endif BSD
	    temp._file = _NFILE;
	    count = _doprnt(fmt, ap, &temp);
	    *temp._ptr = '\0';
	    return count;
	}

It shouldn't be too hard to rewrite the above to use _print() or whatever
other internal mechanism your stdio happens to use. Vprintf() and vfprintf()
are left as an exercize for the reader. (Does anyone want to do a completely
public domain version for the record?)

There is now no excuse for anyone to have to reinvent the wheel as long as
people start providing the v*printf() facilities along with the rest of
their stdio implementations.

					Tony Hansen
					pegasus!hansen



More information about the Comp.unix.wizards mailing list