Main Page | Modules | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

# rprintf.c

Go to the documentation of this file.

    00001 /*! \file rprintf.c \brief printf routine and associated routines. */
    00002 //*****************************************************************************
    00003 //
    00004 // File Name    : 'rprintf.c'
    00005 // Title        : printf routine and associated routines
    00006 // Author       : Pascal Stang - Copyright (C) 2000-2002
    00007 // Created      : 2000.12.26
    00008 // Revised      : 2003.5.1
    00009 // Version      : 1.0
    00010 // Target MCU   : Atmel AVR series and other targets
    00011 // Editor Tabs  : 4
    00012 //
    00013 // NOTE: This code is currently below version 1.0, and therefore is considered
    00014 // to be lacking in some functionality or documentation, or may not be fully
    00015 // tested.  Nonetheless, you can expect most functions to work.
    00016 //
    00017 // This code is distributed under the GNU Public License
    00018 //      which can be found at http://www.gnu.org/licenses/gpl.txt
    00019 //
    00020 //*****************************************************************************
    00021
    00022 //#include <avr/pgmspace.h>
    00023 //#include <string-avr.h>
    00024 //#include <stdlib.h>
    00025 #include <stdarg.h>
    00026 //#include "global.h"
    00027 #include "rprintf.h"
    00028
    00029 #ifndef TRUE
    00030     #define TRUE    -1
    00031     #define FALSE   0
    00032 #endif
    00033
    00034 #define INF     32766   // maximum field size to print
    00035 #define READMEMBYTE(a,char_ptr) ((a)?(*char_ptr):(*char_ptr))
    00036
    00037 #ifdef RPRINTF_COMPLEX
    00038     static unsigned char buf[128];
    00039 #endif
    00040
    00041 // hex conversion table
    00042 static const char HexChars[] = "0123456789ABCDEF";
    00043 #define hexchar(x)  HexChars[(x)&0x0F]
    00044 //#define hexchar(x)    ((((x)&0x0F)>9)?((x)+'A'-10):((x)+'0'))
    00045
    00046 // function pointer to single character output routine
    00047 static void (*rputchar)(unsigned char c);
    00048
    00049 // *** rprintf initialization ***
    00050 // you must call this function once and supply the character output
    00051 // routine before using other functions in this library
    00052 void rprintfInit(void (*putchar_func)(unsigned char c))
    00053 {
    00054     rputchar = putchar_func;
    00055 }
    00056
    00057 // *** rprintfChar ***
    00058 // send a character/byte to the current output device
    00059 void rprintfChar(unsigned char c)
    00060 {
    00061     // do LF -> CR/LF translation
    00062     if(c == '\n')
    00063         rputchar('\r');
    00064     // send character
    00065     rputchar(c);
    00066 }
    00067
    00068 // *** rprintfStr ***
    00069 // prints a null-terminated string stored in RAM
    00070 void rprintfStr(char str[])
    00071 {
    00072     // send a string stored in RAM
    00073     // check to make sure we have a good pointer
    00074     if (!str) return;
    00075
    00076     // print the string until a null-terminator
    00077     while (*str)
    00078         rprintfChar(*str++);
    00079 }
    00080
    00081 // *** rprintfStrLen ***
    00082 // prints a section of a string stored in RAM
    00083 // begins printing at position indicated by <start>
    00084 // prints number of characters indicated by <len>
    00085 void rprintfStrLen(char str[], unsigned char start, unsigned char len)
    00086 {
    00087     register char i=0;
    00088
    00089     // check to make sure we have a good pointer
    00090     if (!str) return;
    00091     // spin through characters up to requested start
    00092     // keep going as long as there's no null
    00093     while((i++<start) && (*str++));
    00094
    00095     // then print exactly len characters
    00096     for(i=0; i<len; i++)
    00097     {
    00098         // print data out of the string as long as we haven't reached a null yet
    00099         // at the null, start printing spaces
    00100         if(*str)
    00101             rprintfChar(*str++);
    00102         else
    00103             rprintfChar(' ');
    00104     }
    00105
    00106 }
    00107
    00108 // *** rprintfCRLF ***
    00109 // prints carriage return and line feed
    00110 void rprintfCRLF(void)
    00111 {
    00112     // print CR/LF
    00113     rprintfChar('\r');
    00114     rprintfChar('\n');
    00115 }
    00116
    00117 // *** rprintfu04 ***
    00118 // prints an unsigned 4-bit number in hex (1 digit)
    00119 void rprintfu04(unsigned char data)
    00120 {
    00121     // print 4-bit hex value
    00122     rprintfChar( hexchar(data) );
    00123 }
    00124
    00125 // *** rprintfu08 ***
    00126 // prints an unsigned 8-bit number in hex (2 digits)
    00127 void rprintfu08(unsigned char data)
    00128 {
    00129     // print 8-bit hex value
    00130     rprintfu04(data>>4);
    00131     rprintfu04(data);
    00132 }
    00133
    00134 // *** rprintfu16 ***
    00135 // prints an unsigned 16-bit number in hex (4 digits)
    00136 void rprintfu16(unsigned short data)
    00137 {
    00138     // print 16-bit hex value
    00139     rprintfu08(data>>8);
    00140     rprintfu08(data);
    00141 }
    00142
    00143 // *** rprintfu32 ***
    00144 // prints an unsigned 32-bit number in hex (8 digits)
    00145 void rprintfu32(unsigned long data)
    00146 {
    00147     // print 32-bit hex value
    00148     rprintfu16(data>>16);
    00149     rprintfu16(data);
    00150 }
    00151
    00152 // *** rprintfNum ***
    00153 // special printf for numbers only
    00154 // see formatting information below
    00155 //  Print the number "n" in the given "base"
    00156 //  using exactly "numDigits"
    00157 //  print +/- if signed flag "isSigned" is TRUE
    00158 //  use the character specified in "padchar" to pad extra characters
    00159 //
    00160 //  Examples:
    00161 //  uartPrintfNum(10, 6,  TRUE, ' ',   1234);  -->  " +1234"
    00162 //  uartPrintfNum(10, 6, FALSE, '0',   1234);  -->  "001234"
    00163 //  uartPrintfNum(16, 6, FALSE, '.', 0x5AA5);  -->  "..5AA5"
    00164 void rprintfNum(char base, char numDigits, char isSigned, char padchar, long n)
    00165 {
    00166     // define a global HexChars or use line below
    00167     //static char HexChars[16] = "0123456789ABCDEF";
    00168     char *p, buf[32];
    00169     unsigned long x;
    00170     unsigned char count;
    00171
    00172     // prepare negative number
    00173     if( isSigned && (n < 0) )
    00174     {
    00175         x = -n;
    00176     }
    00177     else
    00178     {
    00179         x = n;
    00180     }
    00181
    00182     // setup little string buffer
    00183     count = (numDigits-1)-(isSigned?1:0);
    00184     p = buf + sizeof (buf);
    00185     *--p = '\0';
    00186
    00187     // force calculation of first digit
    00188     // (to prevent zero from not printing at all!!!)
    00189     *--p = hexchar(x%base); x /= base;
    00190     // calculate remaining digits
    00191     while(count--)
    00192     {
    00193         if(x != 0)
    00194         {
    00195             // calculate next digit
    00196             *--p = hexchar(x%base); x /= base;
    00197         }
    00198         else
    00199         {
    00200             // no more digits left, pad out to desired length
    00201             *--p = padchar;
    00202         }
    00203     }
    00204
    00205     // apply signed notation if requested
    00206     if( isSigned )
    00207     {
    00208         if(n < 0)
    00209         {
    00210             *--p = '-';
    00211         }
    00212         else if(n > 0)
    00213         {
    00214             *--p = '+';
    00215         }
    00216         else
    00217         {
    00218             *--p = ' ';
    00219         }
    00220     }
    00221
    00222     // print the string right-justified
    00223     count = numDigits;
    00224     while(count--)
    00225     {
    00226         rprintfChar(*p++);
    00227     }
    00228 }
    00229
    00230 #ifdef RPRINTF_FLOAT
    00231 // *** rprintfFloat ***
    00232 // floating-point print
    00233 void rprintfFloat(char numDigits, double x)
    00234 {
    00235     unsigned char firstplace = FALSE;
    00236     unsigned char negative;
    00237     unsigned char i, digit;
    00238     double place = 1.0;
    00239
    00240     // save sign
    00241     negative = (x<0);
    00242     // convert to absolute value
    00243     x = (x>0)?(x):(-x);
    00244
    00245     // find starting digit place
    00246     for(i=0; i<15; i++)
    00247     {
    00248         if((x/place) < 10.0)
    00249             break;
    00250         else
    00251             place *= 10.0;
    00252     }
    00253     // print polarity character
    00254     if(negative)
    00255         rprintfChar('-');
    00256     else
    00257         rprintfChar('+');
    00258
    00259     // print digits
    00260     for(i=0; i<numDigits; i++)
    00261     {
    00262         digit = (x/place);
    00263
    00264         if(digit | firstplace | (place == 1.0))
    00265         {
    00266             firstplace = TRUE;
    00267             rprintfChar(digit+0x30);
    00268         }
    00269         else
    00270             rprintfChar(' ');
    00271
    00272         if(place == 1.0)
    00273         {
    00274             rprintfChar('.');
    00275         }
    00276
    00277         x -= (digit*place);
    00278         place /= 10.0;
    00279     }
    00280 }
    00281 #endif
    00282
    00283 #ifdef RPRINTF_SIMPLE
    00284 // *** rprintf1RamRom ***
    00285 //! called by rprintf() - does a simple printf (supports %d, %x, %c)
    00286 // Supports:
    00287 // %d - decimal
    00288 // %x - hex
    00289 // %c - character
    00290 int rprintf1RamRom(unsigned char stringInRom, const char *format, ...)
    00291 {
    00292     // simple printf routine
    00293     // define a global HexChars or use line below
    00294     //static char HexChars[16] = "0123456789ABCDEF";
    00295     char format_flag;
    00296     unsigned int u_val, div_val, base;
    00297     va_list ap;
    00298
    00299     va_start(ap, format);
    00300     for (;;)
    00301     {
    00302         while ((format_flag = READMEMBYTE(stringInRom,format++) ) != '%')
    00303         {   // Until '%' or '\0'
    00304             if (!format_flag)
    00305             {
    00306                 va_end(ap);
    00307                 return(0);
    00308             }
    00309             rprintfChar(format_flag);
    00310         }
    00311
    00312         switch (format_flag = READMEMBYTE(stringInRom,format++) )
    00313         {
    00314             case 'c': format_flag = va_arg(ap,int);
    00315             default:  rprintfChar(format_flag); continue;
    00316             case 'd': base = 10; div_val = 10000; goto CONVERSION_LOOP;
    00317             case 'x': base = 16; div_val = 0x1000;
    00318
    00319             CONVERSION_LOOP:
    00320             u_val = va_arg(ap,int);
    00321             if (format_flag == 'd')
    00322             {
    00323                 if (((int)u_val) < 0)
    00324                 {
    00325                     u_val = - u_val;
    00326                     rprintfChar('-');
    00327                 }
    00328                 while (div_val > 1 && div_val > u_val) div_val /= 10;
    00329             }
    00330             do
    00331             {
    00332                 //rprintfChar( hexchar(u_val/div_val) );
    00333                 rprintfu04(u_val/div_val);
    00334                 u_val %= div_val;
    00335                 div_val /= base;
    00336             } while (div_val);
    00337         }
    00338     }
    00339     va_end(ap);
    00340 }
    00341 #endif
    00342
    00343
    00344 #ifdef RPRINTF_COMPLEX
    00345 // *** rprintf2RamRom ***
    00346 //! called by rprintf() - does a more powerful printf (supports %d, %u, %o, %x, %c, %s)
    00347 // Supports:
    00348 // %d - decimal
    00349 // %u - unsigned decimal
    00350 // %o - octal
    00351 // %x - hex
    00352 // %c - character
    00353 // %s - strings
    00354 // and the width,precision,padding modifiers
    00355 // **this printf does not support floating point numbers
    00356 int rprintf2RamRom(unsigned char stringInRom, const char *sfmt, ...)
    00357 {
    00358     register unsigned char *f, *bp;
    00359     register long l;
    00360     register unsigned long u;
    00361     register int i;
    00362     register int fmt;
    00363     register unsigned char pad = ' ';
    00364     int flush_left = 0, f_width = 0, prec = INF, hash = 0, do_long = 0;
    00365     int sign = 0;
    00366
    00367     va_list ap;
    00368     va_start(ap, sfmt);
    00369
    00370     f = (unsigned char *) sfmt;
    00371
    00372     for (; READMEMBYTE(stringInRom,f); f++)
    00373     {
    00374         if (READMEMBYTE(stringInRom,f) != '%')
    00375         {   // not a format character
    00376             // then just output the char
    00377             rprintfChar(READMEMBYTE(stringInRom,f));
    00378         }
    00379         else
    00380         {
    00381             f++;                        // if we have a "%" then skip it
    00382             if (READMEMBYTE(stringInRom,f) == '-')
    00383             {
    00384                 flush_left = 1; // minus: flush left
    00385                 f++;
    00386             }
    00387             if (READMEMBYTE(stringInRom,f) == '0'
    00388                  || READMEMBYTE(stringInRom,f) == '.')
    00389                 {
    00390                     // padding with 0 rather than blank
    00391                     pad = '0';
    00392                     f++;
    00393             }
    00394             if (READMEMBYTE(stringInRom,f) == '*')
    00395                 {   // field width
    00396                     f_width = va_arg(ap, int);
    00397                     f++;
    00398             }
    00399             else if (Isdigit(READMEMBYTE(stringInRom,f)))
    00400                 {
    00401                     f_width = atoiRamRom(stringInRom, (char *) f);
    00402                     while (Isdigit(READMEMBYTE(stringInRom,f)))
    00403                         f++;        // skip the digits
    00404             }
    00405             if (READMEMBYTE(stringInRom,f) == '.')
    00406                 {   // precision
    00407                     f++;
    00408                     if (READMEMBYTE(stringInRom,f) == '*')
    00409                     {
    00410                         prec = va_arg(ap, int);
    00411                         f++;
    00412                     }
    00413                     else if (Isdigit(READMEMBYTE(stringInRom,f)))
    00414                     {
    00415                         prec = atoiRamRom(stringInRom, (char *) f);
    00416                         while (Isdigit(READMEMBYTE(stringInRom,f)))
    00417                             f++;    // skip the digits
    00418                     }
    00419                 }
    00420             if (READMEMBYTE(stringInRom,f) == '#')
    00421                 {   // alternate form
    00422                     hash = 1;
    00423                     f++;
    00424             }
    00425             if (READMEMBYTE(stringInRom,f) == 'l')
    00426                 {   // long format
    00427                     do_long = 1;
    00428                     f++;
    00429             }
    00430
    00431                 fmt = READMEMBYTE(stringInRom,f);
    00432                 bp = buf;
    00433                 switch (fmt) {      // do the formatting
    00434                 case 'd':           // 'd' signed decimal
    00435                     if (do_long)
    00436                         l = va_arg(ap, long);
    00437                     else
    00438                         l = (long) (va_arg(ap, int));
    00439                     if (l < 0)
    00440                     {
    00441                         sign = 1;
    00442                         l = -l;
    00443                     }
    00444                     do  {
    00445                         *bp++ = l % 10 + '0';
    00446                     } while ((l /= 10) > 0);
    00447                     if (sign)
    00448                         *bp++ = '-';
    00449                     f_width = f_width - (bp - buf);
    00450                     if (!flush_left)
    00451                         while (f_width-- > 0)
    00452                             rprintfChar(pad);
    00453                     for (bp--; bp >= buf; bp--)
    00454                         rprintfChar(*bp);
    00455                     if (flush_left)
    00456                         while (f_width-- > 0)
    00457                             rprintfChar(' ');
    00458                     break;
    00459             case 'o':           // 'o' octal number
    00460             case 'x':           // 'x' hex number
    00461             case 'u':           // 'u' unsigned decimal
    00462                     if (do_long)
    00463                         u = va_arg(ap, unsigned long);
    00464                     else
    00465                         u = (unsigned long) (va_arg(ap, unsigned));
    00466                     if (fmt == 'u')
    00467                     {   // unsigned decimal
    00468                         do {
    00469                             *bp++ = u % 10 + '0';
    00470                         } while ((u /= 10) > 0);
    00471                     }
    00472                     else if (fmt == 'o')
    00473                     {  // octal
    00474                         do {
    00475                             *bp++ = u % 8 + '0';
    00476                         } while ((u /= 8) > 0);
    00477                         if (hash)
    00478                             *bp++ = '0';
    00479                     }
    00480                     else if (fmt == 'x')
    00481                     {   // hex
    00482                         do {
    00483                             i = u % 16;
    00484                             if (i < 10)
    00485                                 *bp++ = i + '0';
    00486                             else
    00487                                 *bp++ = i - 10 + 'a';
    00488                         } while ((u /= 16) > 0);
    00489                         if (hash)
    00490                         {
    00491                             *bp++ = 'x';
    00492                             *bp++ = '0';
    00493                         }
    00494                     }
    00495                     i = f_width - (bp - buf);
    00496                     if (!flush_left)
    00497                         while (i-- > 0)
    00498                             rprintfChar(pad);
    00499                     for (bp--; bp >= buf; bp--)
    00500                         rprintfChar((int) (*bp));
    00501                     if (flush_left)
    00502                         while (i-- > 0)
    00503                             rprintfChar(' ');
    00504                     break;
    00505             case 'c':           // 'c' character
    00506                     i = va_arg(ap, int);
    00507                     rprintfChar((int) (i));
    00508                     break;
    00509             case 's':           // 's' string
    00510                     bp = va_arg(ap, unsigned char *);
    00511                     if (!bp)
    00512                         bp = (unsigned char *) "(nil)";
    00513                     f_width = f_width - strlen((char *) bp);
    00514                     if (!flush_left)
    00515                         while (f_width-- > 0)
    00516                             rprintfChar(pad);
    00517                     for (i = 0; *bp && i < prec; i++)
    00518                     {
    00519                         rprintfChar(*bp);
    00520                         bp++;
    00521                     }
    00522                     if (flush_left)
    00523                         while (f_width-- > 0)
    00524                             rprintfChar(' ');
    00525                     break;
    00526             case '%':           // '%' character
    00527                     rprintfChar('%');
    00528                     break;
    00529             }
    00530             flush_left = 0, f_width = 0, prec = INF, hash = 0, do_long = 0;
    00531             sign = 0;
    00532             pad = ' ';
    00533         }
    00534     }
    00535
    00536     va_end(ap);
    00537     return 0;
    00538 }
    00539
    00540 unsigned char Isdigit(char c)
    00541 {
    00542     if((c >= 0x30) && (c <= 0x39))
    00543         return TRUE;
    00544     else
    00545         return FALSE;
    00546 }
    00547
    00548 int atoiRamRom(unsigned char stringInRom, char *str)
    00549 {
    00550     int num = 0;;
    00551
    00552     while(Isdigit(READMEMBYTE(stringInRom,str)))
    00553     {
    00554         num *= 10;
    00555         num += ((READMEMBYTE(stringInRom,str++)) - 0x30);
    00556     }
    00557     return num;
    00558 }
    00559
    00560 #endif
    00561
    00562 //******************************************************************************
    00563 // code below this line is commented out and can be ignored
    00564 //******************************************************************************
    00565 /*
    00566 char* sprintf(const char *sfmt, ...)
    00567 {
    00568     register unsigned char *f, *bp, *str;
    00569     register long l;
    00570     register unsigned long u;
    00571     register int i;
    00572     register int fmt;
    00573     register unsigned char pad = ' ';
    00574     int     flush_left = 0, f_width = 0, prec = INF, hash = 0, do_long = 0;
    00575     int     sign = 0;
    00576
    00577     va_list ap;
    00578     va_start(ap, sfmt);
    00579
    00580     str = bufstring;
    00581     f = (unsigned char *) sfmt;
    00582
    00583     for (; *f; f++)
    00584     {
    00585         if (*f != '%')
    00586         {                               // not a format character
    00587             *str++ = (*f);          // then just output the char
    00588         }
    00589         else
    00590         {
    00591             f++;                        // if we have a "%" then skip it
    00592             if (*f == '-')
    00593             {
    00594                 flush_left = 1; // minus: flush left
    00595                 f++;
    00596             }
    00597             if (*f == '0' || *f == '.')
    00598                 {
    00599                     // padding with 0 rather than blank
    00600                     pad = '0';
    00601                     f++;
    00602             }
    00603             if (*f == '*')
    00604                 {   // field width
    00605                     f_width = va_arg(ap, int);
    00606                     f++;
    00607             }
    00608             else if (Isdigit(*f))
    00609                 {
    00610                     f_width = atoi((char *) f);
    00611                     while (Isdigit(*f))
    00612                         f++;        // skip the digits
    00613             }
    00614             if (*f == '.')
    00615                 {   // precision
    00616                     f++;
    00617                     if (*f == '*')
    00618                     {
    00619                         prec = va_arg(ap, int);
    00620                         f++;
    00621                     }
    00622                     else if (Isdigit(*f))
    00623                     {
    00624                         prec = atoi((char *) f);
    00625                         while (Isdigit(*f))
    00626                             f++;    // skip the digits
    00627                     }
    00628                 }
    00629             if (*f == '#')
    00630                 {   // alternate form
    00631                     hash = 1;
    00632                     f++;
    00633             }
    00634             if (*f == 'l')
    00635                 {   // long format
    00636                     do_long = 1;
    00637                     f++;
    00638             }
    00639
    00640                 fmt = *f;
    00641                 bp = buf;
    00642                 switch (fmt) {      // do the formatting
    00643                 case 'd':           // 'd' signed decimal
    00644                     if (do_long)
    00645                         l = va_arg(ap, long);
    00646                     else
    00647                         l = (long) (va_arg(ap, int));
    00648                     if (l < 0)
    00649                     {
    00650                         sign = 1;
    00651                         l = -l;
    00652                     }
    00653                     do  {
    00654                         *bp++ = l % 10 + '0';
    00655                     } while ((l /= 10) > 0);
    00656                     if (sign)
    00657                         *bp++ = '-';
    00658                     f_width = f_width - (bp - buf);
    00659                     if (!flush_left)
    00660                         while (f_width-- > 0)
    00661                             *str++ = (pad);
    00662                     for (bp--; bp >= buf; bp--)
    00663                         *str++ = (*bp);
    00664                     if (flush_left)
    00665                         while (f_width-- > 0)
    00666                             *str++ = (' ');
    00667                     break;
    00668             case 'o':           // 'o' octal number
    00669             case 'x':           // 'x' hex number
    00670             case 'u':           // 'u' unsigned decimal
    00671                     if (do_long)
    00672                         u = va_arg(ap, unsigned long);
    00673                     else
    00674                         u = (unsigned long) (va_arg(ap, unsigned));
    00675                     if (fmt == 'u')
    00676                     {   // unsigned decimal
    00677                         do {
    00678                             *bp++ = u % 10 + '0';
    00679                         } while ((u /= 10) > 0);
    00680                     }
    00681                     else if (fmt == 'o')
    00682                     {  // octal
    00683                         do {
    00684                             *bp++ = u % 8 + '0';
    00685                         } while ((u /= 8) > 0);
    00686                         if (hash)
    00687                             *bp++ = '0';
    00688                     }
    00689                     else if (fmt == 'x')
    00690                     {   // hex
    00691                         do {
    00692                             i = u % 16;
    00693                             if (i < 10)
    00694                                 *bp++ = i + '0';
    00695                             else
    00696                                 *bp++ = i - 10 + 'a';
    00697                         } while ((u /= 16) > 0);
    00698                         if (hash)
    00699                         {
    00700                             *bp++ = 'x';
    00701                             *bp++ = '0';
    00702                         }
    00703                     }
    00704                     i = f_width - (bp - buf);
    00705                     if (!flush_left)
    00706                         while (i-- > 0)
    00707                             *str++ = (pad);
    00708                     for (bp--; bp >= buf; bp--)
    00709                         *str++ = ((int) (*bp));
    00710                     if (flush_left)
    00711                         while (i-- > 0)
    00712                             *str++ = (' ');
    00713                     break;
    00714             case 'c':           // 'c' character
    00715                     i = va_arg(ap, int);
    00716                     *str++ = ((int) (i));
    00717                     break;
    00718             case 's':           // 's' string
    00719                     bp = va_arg(ap, unsigned char *);
    00720                     if (!bp)
    00721                         bp = (unsigned char *) "(nil)";
    00722                     f_width = f_width - strlen((char *) bp);
    00723                     if (!flush_left)
    00724                         while (f_width-- > 0)
    00725                             *str++ = (pad);
    00726                     for (i = 0; *bp && i < prec; i++)
    00727                     {
    00728                         *str++ = (*bp);
    00729                         bp++;
    00730                     }
    00731                     if (flush_left)
    00732                         while (f_width-- > 0)
    00733                             *str++ = (' ');
    00734                     break;
    00735             case '%':           // '%' character
    00736                     *str++ = ('%');
    00737                     break;
    00738             }
    00739             flush_left = 0, f_width = 0, prec = INF, hash = 0, do_long = 0;
    00740             sign = 0;
    00741             pad = ' ';
    00742         }
    00743     }
    00744
    00745     va_end(ap);
    00746     // terminate string with null
    00747     *str++ = '\0';
    00748     return bufstring;
    00749 }
    00750
    00751 */