home *** CD-ROM | disk | FTP | other *** search
- 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*/
-