[net.unix-wizards] %r format item in some printf implementations

v.wales@Ucla-Security@sri-unix (08/30/82)

From: v.wales at Ucla-Security (Rich Wales)
Date: 24 August 1982 1012-PDT (Tuesday)
Dan Franklin's "cmderr" routine for having programs print out error
messages reminds me of how nice the "%r" (remote) format item for
"printf" is.  "%r" is especially helpful for "printf"-like routines
that take a variable number of arguments -- much cleaner, in my view,
than writing a zillion dummy arguments.

Several UNIX implementations -- 4.1BSD among them -- removed "%r" from
"printf" (or, more precisely, from /usr/src/libc/stdio/doprnt.s).  I
consider it such an unqualified "win" that I put it back into our code.

In case anyone is interested in the changes to "doprnt.s" necessary to
implement "%r", here's what I did:

(1) Add the following comment at the beginning of "doprnt.s":

    #ifdef REMOTE
    /*
     * "%r" (remote) format option added.  The argument associated
     * with "%r" is a pointer to a new argument list (format list and
     * series of values).  The original argument list is abandoned
     * forever.
     */
    #endif REMOTE

(2) Make the following change in the "L5" table:

    #ifdef REMOTE	/* "%r" (remote) format */
	    .word remote-L5			# r
    #else
	    .word fmtbad-L5			# r
    #endif REMOTE

(3) Add the following (it could go almost anywhere; I put it just
    before the existing label "float"):

    #ifdef REMOTE	/* "%r" (remote) format */
    remote:
	    movl (ap)+,ap
	    movl (ap)+,r11
	    jbr loop
    #endif REMOTE

Also, of course, you want to update the manual entry for printf(3S) so
that people know that "%r" is there.

Here is an example of a routine which uses "%r":

	oops (args)
	    char *args;
	{   fprintf (stderr, "ERROR: %r", &args);
	    exit (1);
	}

You can then call "oops" exactly as you would call "printf":

	oops ("\"%s\" is an unknown option\n", option);

Happy hacking.

-- Rich

gwyn@Brl@sri-unix (09/04/82)

From:     Doug Gwyn <gwyn@Brl>
Date:     31 Aug 82 1:49:04-EDT (Tue)
%r has also been removed from System III.  I don't know why.

lee@usc-cse@sri-unix (09/15/82)

Date:         13 Sep 1982 11:49-PDT
%r is not portable, since it presumes that you can address the
parameters uniformly.  The varargs stuff, tho a bit clumsy to use, does
the job properly.  It is, however, unfortunate that the designers of
the varargs business did not make a printf format character to accept
the va_list type object and therefore reduce the number of vsprintf
calls needed to pass arguments down levels of message printers.

vsprintf, vfprintf and vprintf are available on System III (tho not
documented) and there is a obvious bug in vsprintf.c where the
vfprintf.c reference to the FILE was not replaced by the reference to
the buffer variable.
						-- Lee
 

dan@Bbn-Unix@sri-unix (09/18/82)

From: Dan Franklin <dan@Bbn-Unix>
Date: 15 Sep 1982 16:58:16 EDT (Wednesday)
Having looked at the "varargs stuff", which (in V7) appears to consist solely
of a five-line include file with no comments or other hints as to how it's
supposed to work (and, of course, no documentation), I think I can infer how
it's supposed to be used.  If I understand it correctly, there is already a
format item which accepts a va_list; it's called %r.  For all the UNIX machines
I know about whose printf offers %r format, %r accepts exactly what varargs.h
maintains!  So %r really is portable--it's just that we've all been using it in
a non-portable way up to now.  You just need to change your documentation as to
what it accepts--that is, if you've documented it at all!  (One undocumented
hack deserves another...)

mark (09/19/82)

Caution: at least one version of UNIX (Zilog's) passes the first
few arguments to each function in registers, and the remaining
ones on the stack.  There are obvious performance gains here, but
implementing either %r or varargs.h would be nontrivial.

There is a manual page for varargs.h in 4.1BSD in section 3.  The
version of printf in vi version 3 uses varargs.h.

oster (09/20/82)

Re: "Due to the lack of a clearly portable way to provide routines like:
        warn("Cannot open %s", filename);
Steve Daniel (duke!mcnc!swd) used the following for "A news":
        char    bfr[BIGENOUGH]; /* handy global buffer */
        ...
        sprintf(bfr, "Cannot open %s", filename);
        warn(bfr);"

The trouble with this is, that among the things %r stands for, it stands for
"recursive" -- if the argument that matches the %r itself has %r's in it, the
above will bomb.  Since implementation of printf is compiler and hardware
dependent anyway, you might as well bite the bullet and implement the whole
thing.