Main Page   Compound List   File List   Compound Members   File Members  

rprintf.c

Go to the documentation of this file.
00001 
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              : 2002.08.23
00009 // Version              : 0.8
00010 // Target MCU   : Atmel AVR series and other targets
00011 // Editor Tabs  : 3
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 <progmem.h>
00023 #include <string-avr.h>
00024 //#include <stdlib.h>
00025 #include <stdarg.h>
00026 //#include "global.h"
00027 //#include <math.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)?(PRG_RDB(char_ptr)):(*char_ptr))
00036 
00037 static unsigned char buf[128];
00038 //static unsigned char bufstring[80];
00039 
00040 // use this to store hex conversion in RAM
00041 //static char HexChars[] = "0123456789ABCDEF";
00042 // use this to store hex conversion in program memory
00043 //static prog_char HexChars[] = "0123456789ABCDEF";
00044 static char __attribute__ ((progmem)) HexChars[] = "0123456789ABCDEF";
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 inline void rprintfChar(unsigned char c)
00060 {
00061         // send character
00062         rputchar(c);
00063 }
00064 
00065 // *** rprintfStr ***
00066 // prints a null-terminated string stored in RAM
00067 void rprintfStr(char str[])
00068 {
00069         // send a string stored in RAM
00070         // check to make sure we have a good pointer
00071         if (!str) return;
00072 
00073         // print the string until a null-terminator
00074         while (*str)
00075                 rprintfChar(*str++);
00076 }
00077 
00078 // *** rprintfStrLen ***
00079 // prints a section of a string stored in RAM
00080 // begins printing at position indicated by <start>
00081 // prints number of characters indicated by <len>
00082 void rprintfStrLen(char str[], unsigned char start, unsigned char len)
00083 {
00084         register char i;
00085 
00086         // check to make sure we have a good pointer
00087         if (!str) return;
00088         // spin through characters up to requested start
00089         for(i=0; i<start; i++)
00090         {
00091                 // keep steping through string as long as there's no null
00092                 if(*str) str++;
00093         }
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 // *** rprintfProgStr ***
00109 // prints a null-terminated string stored in program ROM
00110 void rprintfProgStr(char str[])
00111 {
00112         // print a string stored in program memory
00113         register char c;
00114 
00115         // check to make sure we have a good pointer
00116         if (!str) return;
00117         
00118         // print the string until the null-terminator
00119         while((c = PRG_RDB(str++)))
00120                 rprintfChar(c);
00121 }
00122 
00123 // *** rprintfCRLF ***
00124 // prints carriage return and line feed
00125 void rprintfCRLF(void)
00126 {
00127         // print CR/LF
00128         rprintfChar('\r');
00129         rprintfChar('\n');
00130 }
00131 
00132 // *** rprintfu04 ***
00133 // prints an unsigned 4-bit number in hex (1 digit)
00134 void rprintfu04(unsigned char data)
00135 {
00136         // print 4-bit hex value
00137 //      char Character = data&0x0f;
00138 //      if (Character>9)
00139 //              Character+='A'-10;
00140 //      else
00141 //              Character+='0';
00142         rprintfChar(PRG_RDB( HexChars+(data&0x0f) ));
00143 }
00144 
00145 // *** rprintfu08 ***
00146 // prints an unsigned 8-bit number in hex (2 digits)
00147 void rprintfu08(unsigned char data)
00148 {
00149         // print 8-bit hex value
00150         rprintfu04(data>>4);
00151         rprintfu04(data);
00152 }
00153 
00154 // *** rprintfu16 ***
00155 // prints an unsigned 16-bit number in hex (4 digits)
00156 void rprintfu16(unsigned short data)
00157 {
00158         // print 16-bit hex value
00159         rprintfu08(data>>8);
00160         rprintfu08(data);
00161 }
00162 
00163 // *** rprintfu32 ***
00164 // prints an unsigned 32-bit number in hex (8 digits)
00165 void rprintfu32(unsigned long data)
00166 {
00167         // print 32-bit hex value
00168         rprintfu16(data>>16);
00169         rprintfu16(data);
00170 }
00171 
00172 // *** rprintfNum ***
00173 // special printf for numbers only
00174 // see formatting information below
00175 void rprintfNum(char base, char numDigits, char isSigned, char padchar, long n)
00176 {
00177         // Print the number "n" in the given "base"
00178         // using exactly "numDigits"
00179         // print +/- if signed flag "isSigned" is TRUE
00180         // use the character specified in "padchar" to pad extra characters
00181         
00182         // Examples:
00183         // uartPrintfNum(10, 6,  TRUE, ' ',   1234);  -->  " +1234"
00184         // uartPrintfNum(10, 6, FALSE, '0',   1234);  -->  "001234"
00185         // uartPrintfNum(16, 6, FALSE, '.', 0x5AA5);  -->  "..5AA5"
00186         
00187         // define a global HexChars or use line below
00188         //static char HexChars[16] = "0123456789ABCDEF";
00189         char *p, buf[32];
00190         unsigned long x;
00191         unsigned char count;
00192 
00193         // prepare negative number
00194         if( isSigned && (n < 0) )
00195         {
00196                 x = -n;
00197         }
00198         else
00199         {
00200                 x = n;
00201         }
00202 
00203         // setup little string buffer
00204         count = (numDigits-1)-(isSigned?1:0);
00205         p = buf + sizeof (buf);
00206         *--p = '\0';
00207         
00208         // force calculation of first digit
00209         // (to prevent zero from not printing at all!!!)
00210         *--p = PRG_RDB(HexChars + (x%base)); x /= base;
00211         // calculate remaining digits
00212         while(count--)
00213         {
00214                 if(x != 0)
00215                 {
00216                         // calculate next digit
00217                         *--p = PRG_RDB(HexChars + (x%base)); x /= base;
00218                 }
00219                 else
00220                 {
00221                         // no more digits left, pad out to desired length
00222                         *--p = padchar;
00223                 }
00224         }
00225 
00226         // apply signed notation if requested
00227         if( isSigned )
00228         {
00229                 if(n < 0)
00230                 {
00231                 *--p = '-';
00232            }
00233                 else if(n > 0)
00234                 {
00235                 *--p = '+';
00236            }
00237                 else
00238                 {
00239                 *--p = ' ';
00240                 }
00241         }
00242 
00243         // print the string right-justified
00244         count = numDigits;
00245         while(count--)
00246         {
00247                 rprintfChar(*p++);
00248         }
00249 }
00250 
00251 // floating-point print
00252 void rprintfFloat(char numDigits, double x)
00253 {
00254         unsigned char firstplace = FALSE;
00255         unsigned char negative;
00256         unsigned char i, digit;
00257         double place = 1.0;
00258         
00259         // save sign
00260         negative = (x<0);
00261         // convert to absolute value
00262         x = (x>0)?(x):(-x);
00263         
00264         // find starting digit place
00265         for(i=0; i<15; i++)
00266         {
00267                 if((x/place) < 10.0)
00268                         break;
00269                 else
00270                         place *= 10.0;
00271         }
00272 
00273         if(negative)
00274                 rprintfChar('-');
00275         else
00276                 rprintfChar('+');
00277 
00278 
00279         for(i=0; i<numDigits; i++)
00280         {
00281                 digit = (x/place);
00282 
00283                 if(digit | firstplace | (place == 1.0))
00284                 {
00285                         firstplace = TRUE;
00286                         rprintfChar(digit+0x30);
00287                 }
00288                 else
00289                         rprintfChar(' ');
00290                 
00291                 if(place == 1.0)
00292                 {
00293                         rprintfChar('.');
00294                 }
00295                 
00296                 x -= (digit*place);
00297                 place /= 10.0;
00298         }
00299 }
00300 
00301 // *** rprintf1RamRom ***
00302 // does a simple printf (supports %c, %d, %x)
00303 int rprintf1RamRom(unsigned char stringInRom, const char *format, ...)
00304 {
00305         // simple printf routine
00306         // define a global HexChars or use line below
00307         //static char HexChars[16] = "0123456789ABCDEF";
00308         char format_flag;
00309         unsigned int u_val, div_val, base;
00310         va_list ap;
00311 
00312         va_start(ap, format);
00313         for (;;)
00314         {
00315                 while ((format_flag = READMEMBYTE(stringInRom,format++) ) != '%')
00316                 {       // Until '%' or '\0'
00317                         if (!format_flag)
00318                         {
00319                                 va_end(ap);
00320                                 return(0);
00321                         }
00322                         rprintfChar(format_flag);
00323                 }
00324 
00325                 switch (format_flag = READMEMBYTE(stringInRom,format++) )
00326                 {
00327                         case 'c': format_flag = va_arg(ap,int);
00328                         default:  rprintfChar(format_flag); continue;
00329                         case 'd': base = 10; div_val = 10000; goto CONVERSION_LOOP;
00330                         case 'x': base = 16; div_val = 0x10;
00331 
00332                         CONVERSION_LOOP:
00333                         u_val = va_arg(ap,int);
00334                         if (format_flag == 'd')
00335                         {
00336                                 if (((int)u_val) < 0)
00337                                 {
00338                                         u_val = - u_val;
00339                                         rprintfChar('-');
00340                                 }
00341                                 while (div_val > 1 && div_val > u_val) div_val /= 10;
00342                         }
00343                         do
00344                         {
00345                                 rprintfChar(PRG_RDB(HexChars+(u_val/div_val)));
00346                                 u_val %= div_val;
00347                                 div_val /= base;
00348                         } while (div_val);
00349                 }
00350         }
00351         va_end(ap);
00352 }
00353 
00354 unsigned char Isdigit(char c)
00355 {
00356         if((c >= 0x30) && (c <= 0x39))
00357                 return TRUE;
00358         else
00359                 return FALSE;
00360 }
00361 
00362 int atoiRamRom(unsigned char stringInRom, char *str)
00363 {
00364         int num = 0;;
00365 
00366         while(Isdigit(READMEMBYTE(stringInRom,str)))
00367         {
00368                 num *= 10;
00369                 num += ((READMEMBYTE(stringInRom,str++)) - 0x30);
00370         }
00371         return num;
00372 }
00373 
00374 // *** rprintf2RamRom ***
00375 // does a more powerful printf
00376 // %d - decimal %d
00377 // %u - unsigned decimal
00378 // %o - octal
00379 // %x - hex
00380 // %c - character
00381 // %s - strings
00382 // and the width,precision,padding modifiers
00383 // **this printf does not support floating point numbers
00384 int rprintf2RamRom(unsigned char stringInRom, const char *sfmt, ...)
00385 {
00386         register unsigned char *f, *bp;
00387         register long l;
00388         register unsigned long u;
00389         register int i;
00390         register int fmt;
00391         register unsigned char pad = ' ';
00392         int flush_left = 0, f_width = 0, prec = INF, hash = 0, do_long = 0;
00393         int sign = 0;
00394 
00395         va_list ap;
00396         va_start(ap, sfmt);
00397 
00398         f = (unsigned char *) sfmt;
00399 
00400         for (; READMEMBYTE(stringInRom,f); f++)
00401         {
00402                 if (READMEMBYTE(stringInRom,f) != '%')
00403                 {       // not a format character
00404                         // then just output the char
00405                         rprintfChar(READMEMBYTE(stringInRom,f));
00406                 }
00407                 else 
00408                 {
00409                         f++;                                            // if we have a "%" then skip it
00410                         if (READMEMBYTE(stringInRom,f) == '-')
00411                         {
00412                                 flush_left = 1; // minus: flush left
00413                                 f++;
00414                         }
00415             if (READMEMBYTE(stringInRom,f) == '0'
00416                                  || READMEMBYTE(stringInRom,f) == '.')
00417                                 {
00418                                         // padding with 0 rather than blank
00419                                         pad = '0';
00420                                         f++;
00421             }
00422             if (READMEMBYTE(stringInRom,f) == '*')
00423                                 {       // field width
00424                                         f_width = va_arg(ap, int);
00425                                         f++;
00426             }
00427             else if (Isdigit(READMEMBYTE(stringInRom,f)))
00428                                 {
00429                                         f_width = atoiRamRom(stringInRom, (char *) f);
00430                                         while (Isdigit(READMEMBYTE(stringInRom,f)))
00431                                                 f++;        // skip the digits
00432             }
00433             if (READMEMBYTE(stringInRom,f) == '.')
00434                                 {       // precision
00435                                         f++;
00436                                         if (READMEMBYTE(stringInRom,f) == '*')
00437                                         {
00438                                                 prec = va_arg(ap, int);
00439                                                 f++;
00440                                         }
00441                                         else if (Isdigit(READMEMBYTE(stringInRom,f)))
00442                                         {
00443                                                 prec = atoiRamRom(stringInRom, (char *) f);
00444                                                 while (Isdigit(READMEMBYTE(stringInRom,f)))
00445                                                         f++;    // skip the digits
00446                                         }
00447                                 }
00448             if (READMEMBYTE(stringInRom,f) == '#')
00449                                 {       // alternate form
00450                                         hash = 1;
00451                                         f++;
00452             }
00453             if (READMEMBYTE(stringInRom,f) == 'l')
00454                                 {       // long format
00455                                         do_long = 1;
00456                                         f++;
00457             }
00458 
00459                                 fmt = READMEMBYTE(stringInRom,f);
00460                                 bp = buf;
00461                                 switch (fmt) {          // do the formatting
00462                                 case 'd':                       // 'd' signed decimal
00463                                         if (do_long)
00464                                                 l = va_arg(ap, long);
00465                                         else
00466                                                 l = (long) (va_arg(ap, int));
00467                                         if (l < 0)
00468                                         {
00469                                                 sign = 1;
00470                                                 l = -l;
00471                                         }
00472                                         do      {
00473                                                 *bp++ = l % 10 + '0';
00474                                         } while ((l /= 10) > 0);
00475                                         if (sign)
00476                                                 *bp++ = '-';
00477                                         f_width = f_width - (bp - buf);
00478                                         if (!flush_left)
00479                                                 while (f_width-- > 0)
00480                                                         rprintfChar(pad);
00481                                         for (bp--; bp >= buf; bp--)
00482                                                 rprintfChar(*bp);
00483                                         if (flush_left)
00484                                                 while (f_width-- > 0)
00485                                                         rprintfChar(' ');
00486                                         break;
00487             case 'o':                   // 'o' octal number
00488             case 'x':                   // 'x' hex number
00489             case 'u':                   // 'u' unsigned decimal
00490                                         if (do_long)
00491                                                 u = va_arg(ap, unsigned long);
00492                                         else
00493                                                 u = (unsigned long) (va_arg(ap, unsigned));
00494                                         if (fmt == 'u')
00495                                         {       // unsigned decimal
00496                                                 do {
00497                                                         *bp++ = u % 10 + '0';
00498                                                 } while ((u /= 10) > 0);
00499                                         }
00500                                         else if (fmt == 'o')
00501                                         {  // octal
00502                                                 do {
00503                                                         *bp++ = u % 8 + '0';
00504                                                 } while ((u /= 8) > 0);
00505                                                 if (hash)
00506                                                         *bp++ = '0';
00507                                         }
00508                                         else if (fmt == 'x')
00509                                         {       // hex
00510                                                 do {
00511                                                         i = u % 16;
00512                                                         if (i < 10)
00513                                                                 *bp++ = i + '0';
00514                                                         else
00515                                                                 *bp++ = i - 10 + 'a';
00516                                                 } while ((u /= 16) > 0);
00517                                                 if (hash)
00518                                                 {
00519                                                         *bp++ = 'x';
00520                                                         *bp++ = '0';
00521                                                 }
00522                                         }
00523                                         i = f_width - (bp - buf);
00524                                         if (!flush_left)
00525                                                 while (i-- > 0)
00526                                                         rprintfChar(pad);
00527                                         for (bp--; bp >= buf; bp--)
00528                                                 rprintfChar((int) (*bp));
00529                                         if (flush_left)
00530                                                 while (i-- > 0)
00531                                                         rprintfChar(' ');
00532                                         break;
00533             case 'c':                   // 'c' character
00534                                         i = va_arg(ap, int);
00535                                         rprintfChar((int) (i));
00536                                         break;
00537             case 's':                   // 's' string
00538                                         bp = va_arg(ap, unsigned char *);
00539                                         if (!bp)
00540                                                 bp = (unsigned char *) "(nil)";
00541                                         f_width = f_width - strlen((char *) bp);
00542                                         if (!flush_left)
00543                                                 while (f_width-- > 0)
00544                                                         rprintfChar(pad);
00545                                         for (i = 0; *bp && i < prec; i++)
00546                                         {
00547                                                 rprintfChar(*bp);
00548                                                 bp++;
00549                                         }
00550                                         if (flush_left)
00551                                                 while (f_width-- > 0)
00552                                                         rprintfChar(' ');
00553                                         break;
00554             case '%':                   // '%' character
00555                                         rprintfChar('%');
00556                                         break;
00557                         }
00558                         flush_left = 0, f_width = 0, prec = INF, hash = 0, do_long = 0;
00559                         sign = 0;
00560                         pad = ' ';
00561                 }
00562         }
00563 
00564         va_end(ap);
00565         return 0;
00566 }
00567 
00568 
00569 //******************************************************************************
00570 // code below this line is commented out and can be ignored
00571 //******************************************************************************
00572 /*
00573 // *** rprintf2RamRom ***
00574 // does a more powerful printf
00575 // %d - decimal %d
00576 // %u - unsigned decimal
00577 // %o - octal
00578 // %x - hex
00579 // %c - character
00580 // %s - strings
00581 // and the width,precision,padding modifiers
00582 // **this printf does not support floating point numbers
00583 int rprintf2RamRom(unsigned char stringInRom, const char *sfmt, ...)
00584 {
00585         register unsigned char *f, *bp;
00586         register long l;
00587         register unsigned long u;
00588         register int i;
00589         register int fmt;
00590         register unsigned char pad = ' ';
00591         int flush_left = 0, f_width = 0, prec = INF, hash = 0, do_long = 0;
00592         int sign = 0;
00593 
00594         va_list ap;
00595         va_start(ap, sfmt);
00596 
00597         f = (unsigned char *) sfmt;
00598 
00599         for (; *f; f++)
00600         {
00601                 if (*f != '%')
00602                 {                                                               // not a format character
00603                         rprintfChar(*f);                // then just output the char
00604                 }
00605                 else 
00606                 {
00607                         f++;                                            // if we have a "%" then skip it
00608                         if (*f == '-')
00609                         {
00610                                 flush_left = 1; // minus: flush left
00611                                 f++;
00612                         }
00613             if (*f == '0' || *f == '.')
00614                                 {
00615                                         // padding with 0 rather than blank
00616                                         pad = '0';
00617                                         f++;
00618             }
00619             if (*f == '*')
00620                                 {       // field width
00621                                         f_width = va_arg(ap, int);
00622                                         f++;
00623             }
00624             else if (Isdigit(*f))
00625                                 {
00626                                         f_width = atoi((char *) f);
00627                                         while (Isdigit(*f))
00628                                                 f++;        // skip the digits
00629             }
00630             if (*f == '.')
00631                                 {       // precision
00632                                         f++;
00633                                         if (*f == '*')
00634                                         {
00635                                                 prec = va_arg(ap, int);
00636                                                 f++;
00637                                         }
00638                                         else if (Isdigit(*f))
00639                                         {
00640                                                 prec = atoi((char *) f);
00641                                                 while (Isdigit(*f))
00642                                                         f++;    // skip the digits
00643                                         }
00644                                 }
00645             if (*f == '#')
00646                                 {       // alternate form
00647                                         hash = 1;
00648                                         f++;
00649             }
00650             if (*f == 'l')
00651                                 {       // long format
00652                                         do_long = 1;
00653                                         f++;
00654             }
00655 
00656                                 fmt = *f;
00657                                 bp = buf;
00658                                 switch (fmt) {          // do the formatting
00659                                 case 'd':                       // 'd' signed decimal
00660                                         if (do_long)
00661                                                 l = va_arg(ap, long);
00662                                         else
00663                                                 l = (long) (va_arg(ap, int));
00664                                         if (l < 0)
00665                                         {
00666                                                 sign = 1;
00667                                                 l = -l;
00668                                         }
00669                                         do      {
00670                                                 *bp++ = l % 10 + '0';
00671                                         } while ((l /= 10) > 0);
00672                                         if (sign)
00673                                                 *bp++ = '-';
00674                                         f_width = f_width - (bp - buf);
00675                                         if (!flush_left)
00676                                                 while (f_width-- > 0)
00677                                                         rprintfChar(pad);
00678                                         for (bp--; bp >= buf; bp--)
00679                                                 rprintfChar(*bp);
00680                                         if (flush_left)
00681                                                 while (f_width-- > 0)
00682                                                         rprintfChar(' ');
00683                                         break;
00684             case 'o':                   // 'o' octal number
00685             case 'x':                   // 'x' hex number
00686             case 'u':                   // 'u' unsigned decimal
00687                                         if (do_long)
00688                                                 u = va_arg(ap, unsigned long);
00689                                         else
00690                                                 u = (unsigned long) (va_arg(ap, unsigned));
00691                                         if (fmt == 'u')
00692                                         {       // unsigned decimal
00693                                                 do {
00694                                                         *bp++ = u % 10 + '0';
00695                                                 } while ((u /= 10) > 0);
00696                                         }
00697                                         else if (fmt == 'o')
00698                                         {  // octal
00699                                                 do {
00700                                                         *bp++ = u % 8 + '0';
00701                                                 } while ((u /= 8) > 0);
00702                                                 if (hash)
00703                                                         *bp++ = '0';
00704                                         }
00705                                         else if (fmt == 'x')
00706                                         {       // hex
00707                                                 do {
00708                                                         i = u % 16;
00709                                                         if (i < 10)
00710                                                                 *bp++ = i + '0';
00711                                                         else
00712                                                                 *bp++ = i - 10 + 'a';
00713                                                 } while ((u /= 16) > 0);
00714                                                 if (hash)
00715                                                 {
00716                                                         *bp++ = 'x';
00717                                                         *bp++ = '0';
00718                                                 }
00719                                         }
00720                                         i = f_width - (bp - buf);
00721                                         if (!flush_left)
00722                                                 while (i-- > 0)
00723                                                         rprintfChar(pad);
00724                                         for (bp--; bp >= buf; bp--)
00725                                                 rprintfChar((int) (*bp));
00726                                         if (flush_left)
00727                                                 while (i-- > 0)
00728                                                         rprintfChar(' ');
00729                                         break;
00730             case 'c':                   // 'c' character
00731                                         i = va_arg(ap, int);
00732                                         rprintfChar((int) (i));
00733                                         break;
00734             case 's':                   // 's' string
00735                                         bp = va_arg(ap, unsigned char *);
00736                                         if (!bp)
00737                                                 bp = (unsigned char *) "(nil)";
00738                                         f_width = f_width - strlen((char *) bp);
00739                                         if (!flush_left)
00740                                                 while (f_width-- > 0)
00741                                                         rprintfChar(pad);
00742                                         for (i = 0; *bp && i < prec; i++)
00743                                         {
00744                                                 rprintfChar(*bp);
00745                                                 bp++;
00746                                         }
00747                                         if (flush_left)
00748                                                 while (f_width-- > 0)
00749                                                         rprintfChar(' ');
00750                                         break;
00751             case '%':                   // '%' character
00752                                         rprintfChar('%');
00753                                         break;
00754                         }
00755                         flush_left = 0, f_width = 0, prec = INF, hash = 0, do_long = 0;
00756                         sign = 0;
00757                         pad = ' ';
00758                 }
00759         }
00760 
00761         va_end(ap);
00762         return 0;
00763 }
00764 
00765 char* sprintf(const char *sfmt, ...)
00766 {
00767         register unsigned char *f, *bp, *str;
00768         register long l;
00769         register unsigned long u;
00770         register int i;
00771         register int fmt;
00772         register unsigned char pad = ' ';
00773         int     flush_left = 0, f_width = 0, prec = INF, hash = 0, do_long = 0;
00774         int     sign = 0;
00775 
00776         va_list ap;
00777         va_start(ap, sfmt);
00778 
00779         str = bufstring;
00780         f = (unsigned char *) sfmt;
00781 
00782         for (; *f; f++)
00783         {
00784                 if (*f != '%')
00785                 {                                                               // not a format character
00786                         *str++ = (*f);                  // then just output the char
00787                 }
00788                 else 
00789                 {
00790                         f++;                                            // if we have a "%" then skip it
00791                         if (*f == '-')
00792                         {
00793                                 flush_left = 1; // minus: flush left
00794                                 f++;
00795                         }
00796             if (*f == '0' || *f == '.')
00797                                 {
00798                                         // padding with 0 rather than blank
00799                                         pad = '0';
00800                                         f++;
00801             }
00802             if (*f == '*')
00803                                 {       // field width
00804                                         f_width = va_arg(ap, int);
00805                                         f++;
00806             }
00807             else if (Isdigit(*f))
00808                                 {
00809                                         f_width = atoi((char *) f);
00810                                         while (Isdigit(*f))
00811                                                 f++;        // skip the digits
00812             }
00813             if (*f == '.')
00814                                 {       // precision
00815                                         f++;
00816                                         if (*f == '*')
00817                                         {
00818                                                 prec = va_arg(ap, int);
00819                                                 f++;
00820                                         }
00821                                         else if (Isdigit(*f))
00822                                         {
00823                                                 prec = atoi((char *) f);
00824                                                 while (Isdigit(*f))
00825                                                         f++;    // skip the digits
00826                                         }
00827                                 }
00828             if (*f == '#')
00829                                 {       // alternate form
00830                                         hash = 1;
00831                                         f++;
00832             }
00833             if (*f == 'l')
00834                                 {       // long format
00835                                         do_long = 1;
00836                                         f++;
00837             }
00838 
00839                                 fmt = *f;
00840                                 bp = buf;
00841                                 switch (fmt) {          // do the formatting
00842                                 case 'd':                       // 'd' signed decimal
00843                                         if (do_long)
00844                                                 l = va_arg(ap, long);
00845                                         else
00846                                                 l = (long) (va_arg(ap, int));
00847                                         if (l < 0)
00848                                         {
00849                                                 sign = 1;
00850                                                 l = -l;
00851                                         }
00852                                         do      {
00853                                                 *bp++ = l % 10 + '0';
00854                                         } while ((l /= 10) > 0);
00855                                         if (sign)
00856                                                 *bp++ = '-';
00857                                         f_width = f_width - (bp - buf);
00858                                         if (!flush_left)
00859                                                 while (f_width-- > 0)
00860                                                         *str++ = (pad);
00861                                         for (bp--; bp >= buf; bp--)
00862                                                 *str++ = (*bp);
00863                                         if (flush_left)
00864                                                 while (f_width-- > 0)
00865                                                         *str++ = (' ');
00866                                         break;
00867             case 'o':                   // 'o' octal number
00868             case 'x':                   // 'x' hex number
00869             case 'u':                   // 'u' unsigned decimal
00870                                         if (do_long)
00871                                                 u = va_arg(ap, unsigned long);
00872                                         else
00873                                                 u = (unsigned long) (va_arg(ap, unsigned));
00874                                         if (fmt == 'u')
00875                                         {       // unsigned decimal
00876                                                 do {
00877                                                         *bp++ = u % 10 + '0';
00878                                                 } while ((u /= 10) > 0);
00879                                         }
00880                                         else if (fmt == 'o')
00881                                         {  // octal
00882                                                 do {
00883                                                         *bp++ = u % 8 + '0';
00884                                                 } while ((u /= 8) > 0);
00885                                                 if (hash)
00886                                                         *bp++ = '0';
00887                                         }
00888                                         else if (fmt == 'x')
00889                                         {       // hex
00890                                                 do {
00891                                                         i = u % 16;
00892                                                         if (i < 10)
00893                                                                 *bp++ = i + '0';
00894                                                         else
00895                                                                 *bp++ = i - 10 + 'a';
00896                                                 } while ((u /= 16) > 0);
00897                                                 if (hash)
00898                                                 {
00899                                                         *bp++ = 'x';
00900                                                         *bp++ = '0';
00901                                                 }
00902                                         }
00903                                         i = f_width - (bp - buf);
00904                                         if (!flush_left)
00905                                                 while (i-- > 0)
00906                                                         *str++ = (pad);
00907                                         for (bp--; bp >= buf; bp--)
00908                                                 *str++ = ((int) (*bp));
00909                                         if (flush_left)
00910                                                 while (i-- > 0)
00911                                                         *str++ = (' ');
00912                                         break;
00913             case 'c':                   // 'c' character
00914                                         i = va_arg(ap, int);
00915                                         *str++ = ((int) (i));
00916                                         break;
00917             case 's':                   // 's' string
00918                                         bp = va_arg(ap, unsigned char *);
00919                                         if (!bp)
00920                                                 bp = (unsigned char *) "(nil)";
00921                                         f_width = f_width - strlen((char *) bp);
00922                                         if (!flush_left)
00923                                                 while (f_width-- > 0)
00924                                                         *str++ = (pad);
00925                                         for (i = 0; *bp && i < prec; i++)
00926                                         {
00927                                                 *str++ = (*bp);
00928                                                 bp++;
00929                                         }
00930                                         if (flush_left)
00931                                                 while (f_width-- > 0)
00932                                                         *str++ = (' ');
00933                                         break;
00934             case '%':                   // '%' character
00935                                         *str++ = ('%');
00936                                         break;
00937                         }
00938                         flush_left = 0, f_width = 0, prec = INF, hash = 0, do_long = 0;
00939                         sign = 0;
00940                         pad = ' ';
00941                 }
00942         }
00943 
00944         va_end(ap);
00945         // terminate string with null
00946         *str++ = '\0';
00947         return bufstring;
00948 }
00949 
00950 */

Generated at Mon Oct 14 00:10:51 2002 for avrlib by doxygen1.2.8.1 written by Dimitri van Heesch, © 1997-2001