[net.lang.c] %r, and why it disappeared

kendall@wjh12.UUCP (Sam Kendall) (10/13/83)

As previously noted, %r takes as argument a char **, which is a pointer
to a bunch of printf-style arguments, starting with a format string, on
the stack.  So %r can be used to write functions which take printf-like
variable argument lists, and call printf to print them.  THIS IS
OTHERWISE IMPOSSIBLE, without either (1) rewriting printf and including
the code in your function, or (2) calling _doprnt, the undocumented
function shared by all printf and [sf]printf.  (By the way, there was
once an article on the net on how to use _dorpnt for this purpose.  Maybe
it should be re-submitted.)

So %r is really useful.  It was documented in PWB, if I remember
correctly (can anyone check me there?); but why was it subsequently
un-documented, and then removed?  Well, the problem with %r is that it
CANNOT be implemented on one system, GCOS (a Honeywell somethingorother).
Maybe it was removed from USG UNIX because USG wants their UNIX to be
portable, even to GCOS.  On the other hand, perhaps it was just
un-documented accidentally, and then removed because it was
undocumented.

But it is (was) so useful!  And it could be respecified to be portable
using the usually undocumented varargs(3) package.  I am told that
Andrew Koenig (sp?) is the author both of the varargs(3) package and of
the System III printf.  Perhaps he can shed some light on this.  Can
someone ask him?

	Sam Kendall		  {allegra,ihnp4}!wjh12!kendall
	Delft Consulting Corp.	    decvax!genrad!wjh12!kendall

usenet@abnjh.UUCP (usenet) (10/14/83)

Will somebody who has a copy of the article that describes how to use
the _doprnt() subroutine please post it.  I missed it the last time
around.
Thanks in advance.
Rick Thomas
abnji!rbt
(201)-560-6565

eric@washu.UUCP (Eric Kiebler) (10/17/83)

BEWARE the _doprnt code, my son!
  The bits that twitch; the types that clash!
Use the portable varargs stuff,
  Avoid the _doprnt's teeth that gnash!

As Mark Horton pointed out, the _doprnt() routine is *not* portable
and should not be used for that reason.  Yes, of course, the code
will *never* leave your machine, but...

Just for you "my code stays at home and watches TV" folks out there,
here is a little collection of error functions which I used in code
that wasn't supposed to leave my machine either...

/*
   Error Handling Functions 
   Wash. U. Computer Systems Lab	E. Kiebler	Sept, 1982 
   Distribution allowed if and only if this entire comment is included 
*/

#include <stdio.h>
#include <sys/types.h>
#include <time.h>

extern char *ProgramName;
extern int  DebugFlag;
extern FILE *stdlog;

warning(fmt,args)
char *fmt;
{

  fprintf(stderr,"%s: (warning) ",ProgramName);
  _doprnt(fmt, &args, stderr);		/* magic */
  return(ferror(stderr)? EOF : 0);

}

error(fmt,args)
char *fmt;
{

  fprintf(stderr,"%s: (error) ",ProgramName);
  _doprnt(fmt, &args, stderr);		/* voodoo */
  return(ferror(stderr)? EOF : 0);

}

fatal(fmt,args)
char *fmt;
{

  fprintf(stderr,"%s: (fatal) ",ProgramName);
  _doprnt(fmt, &args, stderr);		/* read the manuals */
  exit(0);

}

debug(fmt,args)
char *fmt;
{

  if(DebugFlag){
    fprintf(stderr,"%s: (debug) ",ProgramName);
    _doprnt(fmt, &args, stderr);		/* wonderful! */
    fprintf(stderr,"\n");
   }

}

log(fmt,args)
char *fmt;
{
  struct tm *tp;
  extern struct tm *localtime();
  time_t clock;
  
  time(&clock);
  tp = localtime(&clock);
  fprintf(stdlog, "(%d/%d-%d:%d) ", tp->tm_mon + 1,
  	tp->tm_mday, tp->tm_hour, tp->tm_min);
  _doprnt(fmt,&args,stdlog);
  fprintf(stdlog,"\n");
}

This code was written by myself and, as far as I know, does not use
any proprietary (sp?) code (unless telling people that _doprnt()
exists is proprietary, in which case eat the code and call your lawyer).

		C A V E A T    E M P T O R
		==========================

-- 
eric
..!ihnp4!washu!eric

decot@cwruecmp.UUCP (Dave Decot) (10/21/83)

It is not exactly impossible, without the aid of %r, to make something that
reacts in an expected way to a call like

	err("identifier '%s' not declared in function %s", id, fun);

Declare err() as:

/*VARARGS 1*/
err(fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)
char *fmt;
int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10;
{
    fprintf(stderr, "%d: ", Linenum);
    fprintf(stderr, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10);
    fputs(stderr, "!!!\007\n");
}

This can be extended if you REALLY need more than up to 10 arguments.

----------------------------------------
Dave Decot	..!decvax!cwruecmp!decot