jr@fortune.UUCP (John A. Rogers) (10/12/83)
I need to port some code (from DECUS C on the RT11), which uses the "%r" format in printf. Of course, I've never heard of "%r", and I can't find it in K&R, or the documentation for V7 or Sys III. Does anyone know what it is, and (even better) how I can simulate it using standard printf formats? Thanks in advance... -- John Rogers CompuServe: 70140,213 Usenet: ...decvax!decwrl!amd70!fortune!jr
leichter@yale-com.UUCP (Jerry Leichter) (10/12/83)
"%r" is "Remote Format" in DECUS C; I don't know whether any other C's support
it. Here is the relevant documentation from the DECUS C manual:
Remote Format. The next printf() argument is the format. Note that
this is not a subroutine. The current format is not processed
further. For example:
bug(args)
{
error("Error at %r",&args);
}
This routine might be called as follows:
bug("Error %d at %s\n",val,name);
Note: error() in DECUS C takes a printf-like argument, prints it to stderr,
then exits. The use of "&args" is a standard hack for passing on multiple
arguments.
There is no general equivalent for %r that I know of. You can probably get
some of the effect using the variable-number-of-arguments package. In some
cases, you'll have to re-organize the code, perhaps to do multiple sprintf's.
BTW, the example above is rather silly, since the "bug" call shown will produce
a message of the form "Error at Error xxx at yyy". However, the idea should
be clear...The only examples of %r I know of, as it happens, are in error
printers of this general form; in fact, I think error() itself may use %r
to call fprintf.
-- Jerry
decvax!yale-comix!leichter leichter@yale
guido@mcvax.UUCP (Guido van Rossum) (10/13/83)
Since %r is - as far as I know - not standard, and the stated most common
use (in general error message printers) is as easily programmed as follows:
/* VARARGS 1 */ bug(fmt, a1, a2, ..., a10) char *fmt; {
fprintf(stderr, "Error: ");
fprintf(stderr, fmt, a1, a2, ..., a10);
abort();
}
it seems better if DECUS had never introduced it in the first place.
The same is true for the "well-known hack" to pass a variable number
of arguments!!!--
Guido van Rossum, Mathematical Centre, Amsterdam, {philabs,decvax}!mcvax!guido
eric@washu.UUCP (10/13/83)
The C-compiler at BBN allowed the %R or %r construction, but I believe
it was a local hack. You can get the same results as follows (although
it is a bit less beautiful):
char *ProgramName;
warning(fmt,args)
char *fmt;
{
fprintf(stderr,"%s: (warning) ",ProgramName);
_doprnt(fmt, &args, stderr); /* this is the good line */
return(ferror(stderr)? EOF : 0);
}
On 4.1 at least, no special libs need be included.
eric
..!ihnp4!washu!eric--
eric
..!ihnp4!washu!eric
henry@utzoo.UUCP (Henry Spencer) (10/13/83)
The reason (well, I think the major reason) why %r has gone away in recent years is that it is not really portable. The trick of calling a routine with a variable number of parameters, while the routine declares only one parameter and invokes printf %r with the address of that parameter, is nifty and neat but absolutely requires some highly machine-dependent assumptions about calling sequences. There is no truly machine-independent way to do this trick without help from the language, help which C does not provide. The only thing you can really do about it is to sprintf into a string and then pass that. (Yes, I know, it's not as convenient.) Please, no questions about why a machine-dependent construct like this is in DECUS C. Either they didn't know what they were doing, or they didn't care (anyone using a DEC operating system obviously isn't worried about portability anyway, right?). -- Henry Spencer @ U of Toronto Zoology {allegra,ihnp4,linus,decvax}!utzoo!henry
gwyn%brl-vld@sri-unix.UUCP (10/14/83)
From: Doug Gwyn (VLD/VMB) <gwyn@brl-vld> printf %r was removed in UNIX System III. If I remember right, it was a means of embedding a format spec ((char *) corresponding to the %r in the main format spec) within the main format spec. One way to do this would be to assemble the "real" format spec with sprintf into a char buffer (maybe strcats would be easier), then use that buffer as the printf main format spec. If you have code that is using printf %r, you should also be alert for use of sprintf return value as a (char *); this was also changed in System III.
leichter@yale-com.UUCP (Jerry Leichter) (10/14/83)
"it seems better if DECUS had never introduced it in the first place." What a remarkable statement! According to various replies to the original article, %r was certainly in V6, probably in V7, and may have been in System II. The "well-known hack" is the technique used to IMPLEMENT VARARGS, so is as current as anything. VARARGS is also fairly recent in itself. DECUS C goes back a ways. At the time its printf was done, it is quite probable that %r was "current". Just because Unix has historically been quite cavalier about ignoring problems of upward compatibility, do you think everyone should be? Hey, you commit something to a public interface and you are COMMITTED to it; you are introducing major costs on your users if you decide you no longer want it. In any case, DECUS C never claimed to be 100% Unix compatible. The compiler is quite close to C AS DESCRIBED IN K&R - the ONLY widely available language reference. The library emulates a variety of Unix functions and provides much the same functionality as the Unix library, but it is by no means identi- cal. MOST Unix programs move to DECUS C with little or no trouble. MOST DECUS C programs move to Unix in the same way. If you want to eliminate the "most", run on Unix. DECUS C runs under 4 different operating systems, none of which is particularly similar to Unix. When these operating systems have required some non-Unix-compatible feature to make C more useful on them, it has found its way into DECUS C. For example, in DECUS C the compiler allows you to manipulate PSECT's, a concept that doesn't even exist in Unix in the same form. Also, when Unix's approach was just plain wrong, or when Unix was missing something that was obviously useful, DECUS C has been willing to say: We will do it right - often by implementing things in a way similar to that discussed in this very newsgroup. (Actually, there are very few of the former - Unix "errors" - but a good number of the latter - Unix "lacks". For example, DECUS C's library has a function, msize(), which tells you the size of a block returned by malloc() - after all, free() can find out, why shouldn't the user be able to? I wrote that one myself; you don't like it, it's "not portable"? - fix your own system. After all, everyone claims one of Unix'x \\\Unix's big advantages is that if you don't like something you can change it!) -- Jerry decvax!yale-comix!leichter leichter@yale
mark@cbosgd.UUCP (Mark Horton) (10/14/83)
I think %r was in UNIX/32V (undocumented) and possibly V7. It went away in 4BSD and was never in System III or its precursors. Calling _doprnt is very unportable. In particular, System III and V don't have _doprnt, they have _print, with slightly different conventions. There are also slight differences between V7 and 32V. The next release of System V has something called vsprintf: vsprintf(string, format, ap) char *string, *fmt; va_list ap; (see varargs(3)). This is like sprintf, except that ap is something that can be passed through more than one layer of function (e.g. it's normally a pointer to the first argument in the list.) Assuming you consider System V "standard", this will be the first documented way to do this in "standard UNIX". In general, this is useful when you want to provide a printf-style routine for other routines to use. It's great for debugging and error messages. It's also useful when you want to provide a subroutine package - e.g. printw in curses.
lwa%mit-csr@sri-unix.UUCP (10/15/83)
The %r format item is "recursive format". It causes the next argument in the argument list (which should be a string) to be interpreted as a format string; the remainder of the arguments in the argument list are printed according to the new format string. Note that this isn't really "recursive" in that the format strings aren't nested; when the end of the new format string is reached the printf terminates. Fortunately, this means it's pretty easy to simulate %r: just concatenate (strcat) the original format string and the "recursive" string and use the result as the format string to printf. -Larry Allen -------
guy@rlgvax.UUCP (Guy Harris) (10/15/83)
To be precise: %r was in V6, and if I remember my ancient history was documented. %r is in PDP-11 V7 but is NOT documented. %r is not in PDP-11 nor VAX-11 System III nor VAX-11 4.?BSD, nor, I suspect, 32V (i.e., VAX-11 V7). I have no idea whether %r is in other V7, 4.?BSD, or System III/V implementations, but I wouldn't count on it. (The (mostly)-portable C implementation of "printf" that comes with System III uses the "varargs" include file, by the way. If you want "varargs" *documentation*, however, the only place I've seen it is in the 4.?BSD documentation.) Guy Harris {seismo,mcnc,we13,brl-bmd,allegra}!rlgvax!guy
henry@utzoo.UUCP (Henry Spencer) (10/16/83)
Unfortunately, Guido van Rossum's solution to the lack of %r (declaring a whole bunch of arguments) isn't portable either. If you call a function declared with m arguments and pass it n arguments, m != n, the resulting behavior is machine-dependent. In particular, you are *not* guaranteed that the first passed argument will show up as the first declared one. /* VARARGS 1 */ doesn't help -- it just shuts lint up, without affecting how the compiler deals with the situation. -- Henry Spencer @ U of Toronto Zoology {allegra,ihnp4,linus,decvax}!utzoo!henry
henry@utzoo.UUCP (Henry Spencer) (10/16/83)
washu!eric says: "_doprnt(fmt, &args, stderr); /* this is the good line */" On the contrary, this is the bad, unportable, implementation-dependent line. If you search chapter 3 of the Unix manual, you will not find an entry for _doprnt. This is because it is a detail of the implementation, not a guaranteed feature of the library. There are Unixes that don't have such a function. Incidentally, the technique of passing _doprnt a whole argument list by passing it the address of one argument is also machine- dependent and unportable. -- Henry Spencer @ U of Toronto Zoology {allegra,ihnp4,linus,decvax}!utzoo!henry
gwyn%brl-vld@sri-unix.UUCP (10/22/83)
From: Doug Gwyn (VLD/VMB) <gwyn@brl-vld> Just for the record, you CAN get a more recent definition of C; just buy the appropriate UNIX System V manuals. You don't need a license. The language is much nicer these days than it was at the time of 7th Edition UNIX. I obtained the DECUS C compiler and was not at all impressed with it. To give the audience an idea of how its developers viewed C, the DECUS compiler was WRITTEN IN MACRO-11! Most of the emphasis in its library support was on ways of accessing the baroque DECisms, especially bad in the RSX-11M version. You would think that "Software Tools" would have had a larger impact..
gwyn%brl-vld@sri-unix.UUCP (10/23/83)
From: Doug Gwyn (VLD/VMB) <gwyn@brl-vld> _doprnt() came back in (at least the VAX version of) UNIX System V. vsprintf() and friends were in UNIX System III (with one bug) but went away in UNIX System V. What is the "next release of UNIX System V"? Any relation to USG 6.0? Why can't the WECo developers make up their mind about these things??