home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Source Code 1992 March
/
Source_Code_CD-ROM_Walnut_Creek_March_1992.iso
/
usenet
/
altsrcs
/
3
/
3573
< prev
next >
Wrap
Text File
|
1991-07-02
|
4KB
|
177 lines
Newsgroups: comp.sources.wanted,alt.sources.wanted,comp.lang.c,alt.sources
Subject: Re: Portable mini-vfprintf?
Message-ID: <25824@well.sf.ca.us>
From: jef@well.sf.ca.us (Jef Poskanzer)
Date: 2 Jul 91 02:41:01 GMT
Jonathan Kamens points out that there was a portable vsprintf posted
to comp.sources.misc (volume 6, Bob Larson). It works basically the
same way as what I came up with. My final version is appended.
---
Jef
Jef Poskanzer jef@well.sf.ca.us {apple, ucbvax, hplabs}!well!jef
"Public opinion in this country is everything." -- Abraham Lincoln
/* CONFIGURE: Some systems don't have vfprintf(), which we need for the
** error-reporting routines. If you compile and get a link error about
** this routine, uncomment the first define, which gives you a vfprintf
** that uses the internal but fairly common routine _doprnt(). If you
** then get a link error about _doprnt, or message-printing doesn't look
** like it's working, try the second define instead.
*/
/* #define NEED_VFPRINTF1 */
/* #define NEED_VFPRINTF2 */
#if defined(NEED_VFPRINTF1) || defined(NEED_VFPRINTF2)
int vfprintf ARGS(( FILE* stream, char* format, va_list args ));
#endif /*NEED_VFPRINTF*/
#ifdef NEED_VFPRINTF1
/* Micro-vfprintf, for systems that don't have vfprintf but do have _doprnt.
*/
int
vfprintf( stream, format, args )
FILE* stream;
char* format;
va_list args;
{
return _doprnt( format, args, stream );
}
#endif /*NEED_VFPRINTF1*/
#ifdef NEED_VFPRINTF2
/* Portable mini-vfprintf, for systems that don't have either vfprintf or
** _doprnt. This depends only on fprintf. If you don't have fprintf,
** you might consider getting a new stdio library.
*/
int
vfprintf( stream, format, args )
FILE* stream;
char* format;
va_list args;
{
char* ep;
char fchar;
char tformat[512];
int do_long;
int i;
long l;
unsigned u;
unsigned long ul;
char* s;
double d;
while ( *format != '\0' )
{
if ( *format != '%' )
{ /* Not special, just write out the char. */
putc( *format, stream );
++format;
}
else
{
do_long = 0;
ep = format + 1;
/* Skip over all the field width and precision junk. */
if ( *ep == '-' )
++ep;
if ( *ep == '0' )
++ep;
while ( isdigit( *ep ) )
++ep;
if ( *ep == '.' )
{
++ep;
while ( isdigit( *ep ) )
++ep;
}
if ( *ep == '#' )
++ep;
if ( *ep == 'l' )
{
do_long = 1;
++ep;
}
/* Here's the field type. Extract it, and copy this format
** specifier to a temp string so we can add an end-of-string.
*/
fchar = *ep;
(void) strncpy( tformat, format, ep - format + 1 );
tformat[ep - format + 1] = '\0';
/* Now do a one-argument fprintf with the format string we have
** isolated.
*/
switch ( fchar )
{
case 'd':
if ( do_long )
{
l = va_arg( args, long );
(void) fprintf( stream, tformat, l );
}
else
{
i = va_arg( args, int );
(void) fprintf( stream, tformat, i );
}
break;
case 'o':
case 'x':
case 'u':
if ( do_long )
{
ul = va_arg( args, unsigned long );
(void) fprintf( stream, tformat, ul );
}
else
{
u = va_arg( args, unsigned );
(void) fprintf( stream, tformat, u );
}
break;
case 'c':
i = (char) va_arg( args, int );
(void) fprintf( stream, tformat, i );
break;
case 's':
s = va_arg( args, char* );
(void) fprintf( stream, tformat, s );
break;
case 'e':
case 'f':
case 'g':
d = va_arg( args, double );
(void) fprintf( stream, tformat, d );
break;
case '%':
putc( '%', stream );
break;
default:
return -1;
}
/* Resume formatting on the next character. */
format = ep + 1;
}
}
return 0;
}
#endif /*NEED_VFPRINTF2*/