LINNDR%VUENGVAX.BITNET@WISCVM.ARPA (07/11/86)
All this stuff about v*printf has brought me back to a problem
I was trying to solve earlier. Having a terminal that supports inverse
video, blinking and underlining, I thought it would be fun to write some
printing functions to take advantage of these features. For example,
invprintf(fmt,args)
{
printf(<string to go into inverse video mode>);
printf(fmt,args);
printf(<string to leave inverse mode>);
}
This simple solution didn't work. Oh great gurus of such things, what
should I have done?
David Linn
----------------------------------------------------------
ARPANET(?): LINNDR%VUEngVAX.BITNET@WISCVM.WISC.EDU
BITNET: LINNDR@VUEngVAX.BITNET
CSNET: drl@vanderbilt.csnet
Ma Bell: (615)322-7924
USPS: P.O. 3241-B Vanderbilt
Nashville, TN 37235
UUCP: ...psuvax1!vuengvax.bitnet!linndr
gwyn@brl-smoke.UUCP (07/12/86)
In article <2138@brl-smoke.ARPA> LINNDR%VUENGVAX.BITNET@WISCVM.ARPA writes: >invprintf(fmt,args) >{ > printf(<string to go into inverse video mode>); > printf(fmt,args); > printf(<string to leave inverse mode>); >} > >This simple solution didn't work. Oh great gurus of such things, what >should I have done? Assuming you're using UNIX System V Release 2.0 for sake of concreteness, #include <stdio.h> #include <varargs.h> void invprintf( va_alist ) va_dcl { char *fmt; /* printf control string */ va_list args; /* argument pointer */ (void)fputs( "string to enter inverse video mode", stdout ); va_start( args ); fmt = va_arg( args, char * ); (void)vprintf( fmt, args ); /* warning! not printf(va_arg etc. */ va_end( args ); (void)fputs( "string to leave inverse video mode", stdout ); } The final mechanism of ANSI X3J11 will probably be slightly different. P.S. You should perhaps also test whether the write to the terminal succeeds.
rbj%icst-cmr@smoke.UUCP (07/15/86)
> In article <2138@brl-smoke.ARPA> LINNDR%VUENGVAX.BITNET@WISCVM.ARPA writes: > >invprintf(fmt,args) > >{ > > printf(<string to go into inverse video mode>); > > printf(fmt,args); > > printf(<string to leave inverse mode>); > >} > > > >This simple solution didn't work. Oh great gurus of such things, what > >should I have done? The solution presented below is probably correct, given the poster. I find it rather unreadable, and would opt for a more local but readable solution. Having expressed my opinions, I present my solutions along with their required constraints. First I present Berkeley's solution: /* @(#)printf.c 4.1 (Berkeley) 12/21/80 */ #include <stdio.h> printf(fmt, args) char *fmt; { ABC: _doprnt(fmt, &args, stdout); return(ferror(stdout)? EOF: 0); XYZ: } The labels ABC & XYZ are where you put the strings to go into reverse video and back to normal. You also must fix up the return status to account for the extra I/O. This only works if all the arguments are pushed on the stack in reverse order. VAXen, SUNS, most any 68k box, Sequent, most any ns32032 box, and anyone else attempting to be reasonable. Secondly, if you are willing to limit 1) the number of parameters to a reasonable number, say ten 2) the type of parameters to only integers and pointers 3) sizeof(int) = sizeof(int *) = sizeof(char *) = sizeof(any *) then you might like the following solution: invprintf(fmt,_0,_1,_2,_3,_4,_5,_6,_7,_8,_9) { printf(<reverse video>); printf(fmt,_0,_1,_2,_3,_4,_5,_6,_7,_8,_9); printf(<reverse video>); } > Assuming you're using UNIX System V Release 2.0 for sake of concreteness, > #include <stdio.h> > #include <varargs.h> > > void > invprintf( va_alist ) > va_dcl > { > char *fmt; /* printf control string */ > va_list args; /* argument pointer */ > > (void)fputs( "string to enter inverse video mode", stdout ); > > va_start( args ); > > fmt = va_arg( args, char * ); > > (void)vprintf( fmt, args ); /* warning! not printf(va_arg etc. */ > > va_end( args ); > > (void)fputs( "string to leave inverse video mode", stdout ); > } > > The final mechanism of ANSI X3J11 will probably be slightly different. > > P.S. You should perhaps also test whether the write to the terminal succeeds. (Root Boy) Jim Cottrell <rbj@icst-cmr.arpa> Are we live or on tape? .
gwyn@BRL.ARPA (07/15/86)
invprintf(fmt,_0,_1,_2,_3,_4,_5,_6,_7,_8,_9) is not a portable solution. In some cases an attempt to invoke it with a small actual parameter count can even lead to abnormal process termination. The reason <varargs.h> or <stdarg.h> exist is to provide the hooks necessary for implementation of a portable solution; the other half of the solution requires something like the v*printf() functions. The fellow asked the great gurus what he *should* have done. Why do you feed him that garbage in return? If it's to show us that you don't believe in writing portable code, we knew that already from your ravings about how the VAX is the only sane architecture.
rbj@icst-cmr.ARPA (07/15/86)
Doug Gwyn chastises me: invprintf(fmt,_0,_1,_2,_3,_4,_5,_6,_7,_8,_9) is not a portable solution. I thought I said that. If not, `taint portable', but just might be useful. In some cases an attempt to invoke it with a small actual parameter count can even lead to abnormal process termination. True, such as floats or doubles, weird format pointers, longs on PDP-11's. Also, if called directly from main, it could run off the end of the stack. The reason <varargs.h> or <stdarg.h> exist is to provide the hooks necessary for implementation of a portable solution; the other half of the solution requires something like the v*printf() functions. I can relate to the v*printf guys. The fellow asked the great gurus what he *should* have done. Why do you feed him that garbage in return? For educational purposes. At least my `solutions' are understandable. The guy was obviously a novice, and while your solution is probably the best one, do you think he can read it? Also, there is no harm in disseminating bad information as well as good, for comparison purposes, so he can tell the difference. Also, to understand why yours works, it is useful to know the usual (or original if you will) calling sequence. Its probably going to be awhile before he ports code all over creation. I wish *I* had known the magic printf trick when I wrote code that had to run in both hosted and standalone 68k environments. I wrote three sets of code, the common stuff, the hosted interface, and the standalone interface. We were using only integers (chars, shorts, & ints) & pointers. It would have been easier and more maintainable if I had rewritten a subset of printf (no floats, no field widths or left justification, etc) INSTEAD OF AN ENTIRE INCOMPATIBLE EDITING PACKAGE based on Exec 8!!! If it's to show us that you don't believe in writing portable code, we knew that already from your ravings about how the VAX is the only sane architecture. Why do you keep saying VAX only? I also mentioned 68k's, ns32032's, I forgot the PDP-11, all of which I would take home to mother. I suppose even IBM qualifies as a rational data structure. Just because a piece of hardware exists doesn't mean it's rational. Just because a piece of hardware is rational doesn't mean the software model imposed upon it is rational. INTEL's small, medium, and large models create more problems than they solve. There is nothing wrong with the 8086 that treating it like a PDP-11 wouldn't cure. I suppose I would rather program in C than anything else on a dinosaur, but I would realize that the model was strained at best. I will never touch one of those beasts again. As far as I am concerned, they don't exist. If you want to contort your code to conform to the lowest common denominator, fine. My code is optimized for sanity. I am from the National Bureau of Standards, and as such, believe in them. There ain't nothing else but ASCII. My code will never support EBCDIC. I expect 'I' + 1 to equal 'J'. If it doesn't, that's your problem. You fix it. You say your car is 6 volts, positive ground? Wreck it! There comes a time to forego the past and desanction it. If you make it easy for them, they'll never give it up. Okay, I'm ranting again, let me get back to the subject. It's all a matter of tradeoffs. Portability comes at a price, both in time and in space (extra characters), which I find detracts from readability. Yes, I know that one should aim high, and I do. Perhaps I aim higher than you. You abide the past, I demand the future. I added proper cautionary notes. I acknowledged your solution. In any case, yours is not the only opinion. Mine is shared by others. We are not unaware of the consequences of our actions, and accept the responsibility for same. We have made our choice. Respect it. Agree to disagree. (Root Boy) Jim Cottrell <rbj@icst-cmr.arpa> I guess it was all a DREAM.. or an episode of HAWAII FIVE-O...
throopw@dg_rtp.UUCP (07/17/86)
> rbj@icst-cmr (Root Boy Jim) > ... > _doprnt(fmt, &args, stdout); > ... 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! --- Eric Kiebler (eric@washu.UUCP) -- Wayne Throop <the-known-world>!mcnc!rti-sel!dg_rtp!throopw
mouse@mcgill-vision.UUCP (der Mouse) (07/22/86)
>> invprintf(fmt,args) >> { >> printf(<string to go into inverse video mode>); >> printf(fmt,args); >> printf(<string to leave inverse mode>); >> } > Assuming you're using UNIX System V Release 2.0 for sake of concreteness, > [...solution involving.... > (void)vprintf( fmt, args ); /* warning! not printf(va_arg etc. */ > ] Sounds to me more like assuming SVR2 for the sake of possibility. Many Unices do not have vprintf(), much though AT&T may wish it otherwise. Absent some indication of what flavor of UNIX the solution is desired for, an "answer" using vprintf() not much of an answer. I doubt that the original poster is prepared to change operating systems just to get a portable version of invprintf(). By the way, when I need something like this I write it as follows: /* VARARGS 1 */ invprintf(fmt,a1,a2,a3,a4,a5,a6,a7,a8) char *fmt; int a1; int a2; int a3; int a4; int a5; int a6; int a7; int a8; { printf(<inverse-video-string>); printf(fmt,a1,a2,a3,a4,a5,a6,a7,a8); printf(<exit-inverse-video-string>); } Anyone out there care to enlighten me as to all the ways in which this can fail (besides wanting to print more than eight arguments)? It works on enough machines that I don't feel *too* guilty using it. I would guess that it works on substantially more machines than the vprintf() solution. -- der Mouse USA: {ihnp4,decvax,akgua,utzoo,etc}!utcsri!mcgill-vision!mouse philabs!micomvax!musocs!mcgill-vision!mouse Europe: mcvax!decvax!utcsri!mcgill-vision!mouse mcvax!seismo!cmcl2!philabs!micomvax!musocs!mcgill-vision!mouse ARPAnet: utcsri!mcgill-vision!mouse@uw-beaver.arpa "Come with me a few minutes, mortal, and we shall talk."
moss@BRL.ARPA (Gary S. Moss (SLCBR-VLD-V)) (07/28/86)
If you don't have the vprintf() library, but do have a _doprnt(), this may be
a more desirable, non-portable solution than limiting yourself to 8 args...
-moss
#include <stdio.h>
#include <varargs.h>
/* VARARGS */
void
prnt_rvideo( fmt, va_alist )
char *fmt;
va_dcl
{ va_list ap;
va_start( ap );
(void) printf( <turn ON standout mode> );
(void) _doprnt( fmt, ap, stdout );
(void) printf( <turn OFF standout mode> );
va_end( ap );
return;
}