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 >
Text File  |  1991-07-02  |  4KB  |  177 lines

  1. Newsgroups: comp.sources.wanted,alt.sources.wanted,comp.lang.c,alt.sources
  2. Subject: Re: Portable mini-vfprintf?
  3. Message-ID: <25824@well.sf.ca.us>
  4. From: jef@well.sf.ca.us (Jef Poskanzer)
  5. Date: 2 Jul 91 02:41:01 GMT
  6.  
  7. Jonathan Kamens points out that there was a portable vsprintf posted
  8. to comp.sources.misc (volume 6, Bob Larson).  It works basically the
  9. same way as what I came up with.  My final version is appended.
  10. ---
  11. Jef
  12.  
  13.   Jef Poskanzer  jef@well.sf.ca.us  {apple, ucbvax, hplabs}!well!jef
  14.   "Public opinion in this country is everything." -- Abraham Lincoln
  15.  
  16.  
  17. /* CONFIGURE: Some systems don't have vfprintf(), which we need for the
  18. ** error-reporting routines.  If you compile and get a link error about
  19. ** this routine, uncomment the first define, which gives you a vfprintf
  20. ** that uses the internal but fairly common routine _doprnt().  If you
  21. ** then get a link error about _doprnt, or message-printing doesn't look
  22. ** like it's working, try the second define instead.
  23. */
  24. /* #define NEED_VFPRINTF1 */
  25. /* #define NEED_VFPRINTF2 */
  26.  
  27.  
  28. #if defined(NEED_VFPRINTF1) || defined(NEED_VFPRINTF2)
  29. int vfprintf ARGS(( FILE* stream, char* format, va_list args ));
  30. #endif /*NEED_VFPRINTF*/
  31.  
  32.  
  33. #ifdef NEED_VFPRINTF1
  34.  
  35. /* Micro-vfprintf, for systems that don't have vfprintf but do have _doprnt.
  36. */
  37.  
  38. int
  39. vfprintf( stream, format, args )
  40.     FILE* stream;
  41.     char* format;
  42.     va_list args;
  43.     {
  44.     return _doprnt( format, args, stream );
  45.     }
  46. #endif /*NEED_VFPRINTF1*/
  47.  
  48. #ifdef NEED_VFPRINTF2
  49.  
  50. /* Portable mini-vfprintf, for systems that don't have either vfprintf or
  51. ** _doprnt.  This depends only on fprintf.  If you don't have fprintf,
  52. ** you might consider getting a new stdio library.
  53. */
  54.  
  55. int
  56. vfprintf( stream, format, args )
  57.     FILE* stream;
  58.     char* format;
  59.     va_list args;
  60.     {
  61.     char* ep;
  62.     char fchar;
  63.     char tformat[512];
  64.     int do_long;
  65.     int i;
  66.     long l;
  67.     unsigned u;
  68.     unsigned long ul;
  69.     char* s;
  70.     double d;
  71.  
  72.     while ( *format != '\0' )
  73.     {
  74.     if ( *format != '%' )
  75.         { /* Not special, just write out the char. */
  76.         putc( *format, stream );
  77.         ++format;
  78.         }
  79.     else
  80.         {
  81.         do_long = 0;
  82.         ep = format + 1;
  83.  
  84.         /* Skip over all the field width and precision junk. */
  85.         if ( *ep == '-' )
  86.         ++ep;
  87.         if ( *ep == '0' )
  88.         ++ep;
  89.         while ( isdigit( *ep ) )
  90.         ++ep;
  91.         if ( *ep == '.' )
  92.         {
  93.         ++ep;
  94.         while ( isdigit( *ep ) )
  95.             ++ep;
  96.         }
  97.         if ( *ep == '#' )
  98.         ++ep;
  99.         if ( *ep == 'l' )
  100.         {
  101.         do_long = 1;
  102.         ++ep;
  103.         }
  104.  
  105.         /* Here's the field type.  Extract it, and copy this format
  106.         ** specifier to a temp string so we can add an end-of-string.
  107.         */
  108.         fchar = *ep;
  109.         (void) strncpy( tformat, format, ep - format + 1 );
  110.         tformat[ep - format + 1] = '\0';
  111.  
  112.         /* Now do a one-argument fprintf with the format string we have
  113.         ** isolated.
  114.         */
  115.         switch ( fchar )
  116.         {
  117.         case 'd':
  118.         if ( do_long )
  119.             {
  120.             l = va_arg( args, long );
  121.             (void) fprintf( stream, tformat, l );
  122.             }
  123.         else
  124.             {
  125.             i = va_arg( args, int );
  126.             (void) fprintf( stream, tformat, i );
  127.             }
  128.         break;
  129.  
  130.             case 'o':
  131.             case 'x':
  132.             case 'u':
  133.         if ( do_long )
  134.             {
  135.             ul = va_arg( args, unsigned long );
  136.             (void) fprintf( stream, tformat, ul );
  137.             }
  138.         else
  139.             {
  140.             u = va_arg( args, unsigned );
  141.             (void) fprintf( stream, tformat, u );
  142.             }
  143.         break;
  144.  
  145.             case 'c':
  146.         i = (char) va_arg( args, int );
  147.         (void) fprintf( stream, tformat, i );
  148.         break;
  149.  
  150.             case 's':
  151.         s = va_arg( args, char* );
  152.         (void) fprintf( stream, tformat, s );
  153.         break;
  154.  
  155.             case 'e':
  156.             case 'f':
  157.             case 'g':
  158.         d = va_arg( args, double );
  159.         (void) fprintf( stream, tformat, d );
  160.         break;
  161.  
  162.             case '%':
  163.         putc( '%', stream );
  164.         break;
  165.  
  166.         default:
  167.         return -1;
  168.         }
  169.  
  170.         /* Resume formatting on the next character. */
  171.         format = ep + 1;
  172.         }
  173.     }
  174.     return 0;
  175.     }
  176. #endif /*NEED_VFPRINTF2*/
  177.