hdo  beta
/home/mrazik/Documents/web/old/hdo/at91lib/utility/stdio.c
Zobrazit dokumentaci tohoto souboru.
00001 /* ----------------------------------------------------------------------------
00002  *         ATMEL Microcontroller Software Support 
00003  * ----------------------------------------------------------------------------
00004  * Copyright (c) 2008, Atmel Corporation
00005  *
00006  * All rights reserved.
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted provided that the following conditions are met:
00010  *
00011  * - Redistributions of source code must retain the above copyright notice,
00012  * this list of conditions and the disclaimer below.
00013  *
00014  * Atmel's name may not be used to endorse or promote products derived from
00015  * this software without specific prior written permission.
00016  *
00017  * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00019  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
00020  * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
00021  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00022  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
00023  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00024  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00025  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
00026  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027  * ----------------------------------------------------------------------------
00028  */
00029 
00030 //------------------------------------------------------------------------------
00043 //------------------------------------------------------------------------------
00044 
00045 //------------------------------------------------------------------------------
00046 //         Headers
00047 //------------------------------------------------------------------------------
00048 
00049 #include <stdio.h>
00050 #include <stdarg.h>
00051 
00052 //------------------------------------------------------------------------------
00053 //         Local Definitions
00054 //------------------------------------------------------------------------------
00055 
00056 // Maximum string size allowed (in bytes).
00057 #define MAX_STRING_SIZE         100
00058 
00059 //------------------------------------------------------------------------------
00060 //         Global Variables
00061 //------------------------------------------------------------------------------
00062 
00063 // Required for proper compilation.
00064 struct _reent r = {0, (FILE *) 0, (FILE *) 1, (FILE *) 0};
00065 struct _reent *_impure_ptr = &r;
00066 
00067 //------------------------------------------------------------------------------
00068 //         Local Functions
00069 //------------------------------------------------------------------------------
00070 
00071 //------------------------------------------------------------------------------
00072 // Writes a character inside the given string. Returns 1.
00073 // \param pStr  Storage string.
00074 // \param c  Character to write.
00075 //------------------------------------------------------------------------------
00076 signed int PutChar(char *pStr, char c)
00077 {
00078     *pStr = c;
00079     return 1;
00080 }
00081 
00082 //------------------------------------------------------------------------------
00083 // Writes a string inside the given string.
00084 // Returns the size of the written
00085 // string.
00086 // \param pStr  Storage string.
00087 // \param pSource  Source string.
00088 //------------------------------------------------------------------------------
00089 signed int PutString(char *pStr, const char *pSource)
00090 {
00091     signed int num = 0;
00092 
00093     while (*pSource != 0) {
00094 
00095         *pStr++ = *pSource++;
00096         num++;
00097     }
00098 
00099     return num;
00100 }
00101 
00102 //------------------------------------------------------------------------------
00103 // Writes an unsigned int inside the given string, using the provided fill &
00104 // width parameters.
00105 // Returns the size in characters of the written integer.
00106 // \param pStr  Storage string.
00107 // \param fill  Fill character.
00108 // \param width  Minimum integer width.
00109 // \param value  Integer value.
00110 //------------------------------------------------------------------------------
00111 signed int PutUnsignedInt(
00112     char *pStr,
00113     char fill,
00114     signed int width,
00115     unsigned int value)
00116 {
00117     signed int num = 0;
00118 
00119     // Take current digit into account when calculating width
00120     width--;
00121 
00122     // Recursively write upper digits
00123     if ((value / 10) > 0) {
00124 
00125         num = PutUnsignedInt(pStr, fill, width, value / 10);
00126         pStr += num;
00127     }
00128     // Write filler characters
00129     else {
00130 
00131         while (width > 0) {
00132 
00133             PutChar(pStr, fill);
00134             pStr++;
00135             num++;
00136             width--;
00137         }
00138     }
00139 
00140     // Write lower digit
00141     num += PutChar(pStr, (value % 10) + '0');
00142 
00143     return num;
00144 }
00145 
00146 //------------------------------------------------------------------------------
00147 // Writes a signed int inside the given string, using the provided fill & width
00148 // parameters.
00149 // Returns the size of the written integer.
00150 // \param pStr  Storage string.
00151 // \param fill  Fill character.
00152 // \param width  Minimum integer width.
00153 // \param value  Signed integer value.
00154 //------------------------------------------------------------------------------
00155 signed int PutSignedInt(
00156     char *pStr,
00157     char fill,
00158     signed int width,
00159     signed int value)
00160 {
00161     signed int num = 0;
00162     unsigned int absolute;
00163 
00164     // Compute absolute value
00165     if (value < 0) {
00166 
00167         absolute = -value;
00168     }
00169     else {
00170 
00171         absolute = value;
00172     }
00173 
00174     // Take current digit into account when calculating width
00175     width--;
00176 
00177     // Recursively write upper digits
00178     if ((absolute / 10) > 0) {
00179 
00180         if (value < 0) {
00181         
00182             num = PutSignedInt(pStr, fill, width, -(absolute / 10));
00183         }
00184         else {
00185 
00186             num = PutSignedInt(pStr, fill, width, absolute / 10);
00187         }
00188         pStr += num;
00189     }
00190     else {
00191 
00192         // Reserve space for sign
00193         if (value < 0) {
00194 
00195             width--;
00196         }
00197 
00198         // Write filler characters
00199         while (width > 0) {
00200 
00201             PutChar(pStr, fill);
00202             pStr++;
00203             num++;
00204             width--;
00205         }
00206 
00207         // Write sign
00208         if (value < 0) {
00209 
00210             num += PutChar(pStr, '-');
00211             pStr++;
00212         }
00213     }
00214 
00215     // Write lower digit
00216     num += PutChar(pStr, (absolute % 10) + '0');
00217 
00218     return num;
00219 }
00220 
00221 //------------------------------------------------------------------------------
00222 // Writes an hexadecimal value into a string, using the given fill, width &
00223 // capital parameters.
00224 // Returns the number of char written.
00225 // \param pStr  Storage string.
00226 // \param fill  Fill character.
00227 // \param width  Minimum integer width.
00228 // \param maj  Indicates if the letters must be printed in lower- or upper-case.
00229 // \param value  Hexadecimal value.
00230 //------------------------------------------------------------------------------
00231 signed int PutHexa(
00232     char *pStr,
00233     char fill,
00234     signed int width,
00235     unsigned char maj,
00236     unsigned int value)
00237 {
00238     signed int num = 0;
00239 
00240     // Decrement width
00241     width--;
00242 
00243     // Recursively output upper digits
00244     if ((value >> 4) > 0) {
00245 
00246         num += PutHexa(pStr, fill, width, maj, value >> 4);
00247         pStr += num;
00248     }
00249     // Write filler chars
00250     else {
00251 
00252         while (width > 0) {
00253 
00254             PutChar(pStr, fill);
00255             pStr++;
00256             num++;
00257             width--;
00258         }
00259     }
00260 
00261     // Write current digit
00262     if ((value & 0xF) < 10) {
00263 
00264         PutChar(pStr, (value & 0xF) + '0');
00265     }
00266     else if (maj) {
00267 
00268         PutChar(pStr, (value & 0xF) - 10 + 'A');
00269     }
00270     else {
00271 
00272         PutChar(pStr, (value & 0xF) - 10 + 'a');
00273     }
00274     num++;
00275 
00276     return num;
00277 }
00278 
00279 //------------------------------------------------------------------------------
00280 //         Global Functions
00281 //------------------------------------------------------------------------------
00282 
00283 //------------------------------------------------------------------------------
00291 //------------------------------------------------------------------------------
00292 signed int vsnprintf(char *pStr, size_t length, const char *pFormat, va_list ap)
00293 {
00294     char          fill;
00295     unsigned char width;
00296     signed int    num = 0;
00297     signed int    size = 0;
00298 
00299     // Clear the string
00300     if (pStr) {
00301 
00302         *pStr = 0;
00303     }
00304 
00305     // Phase string
00306     while (*pFormat != 0 && size < length) {
00307 
00308         // Normal character
00309         if (*pFormat != '%') {
00310 
00311             *pStr++ = *pFormat++;
00312             size++;
00313         }
00314         // Escaped '%'
00315         else if (*(pFormat+1) == '%') {
00316 
00317             *pStr++ = '%';
00318             pFormat += 2;
00319             size++;
00320         }
00321         // Token delimiter
00322         else {
00323 
00324             fill = ' ';
00325             width = 0;
00326             pFormat++;
00327 
00328             // Parse filler
00329             if (*pFormat == '0') {
00330 
00331                 fill = '0';
00332                 pFormat++;
00333             }
00334 
00335             // Parse width
00336             while ((*pFormat >= '0') && (*pFormat <= '9')) {
00337         
00338                 width = (width*10) + *pFormat-'0';
00339                 pFormat++;
00340             }
00341 
00342             // Check if there is enough space
00343             if (size + width > length) {
00344 
00345                 width = length - size;
00346             }
00347         
00348             // Parse type
00349             switch (*pFormat) {
00350             case 'd': 
00351             case 'i': num = PutSignedInt(pStr, fill, width, va_arg(ap, signed int)); break;
00352             case 'u': num = PutUnsignedInt(pStr, fill, width, va_arg(ap, unsigned int)); break;
00353             case 'x': num = PutHexa(pStr, fill, width, 0, va_arg(ap, unsigned int)); break;
00354             case 'X': num = PutHexa(pStr, fill, width, 1, va_arg(ap, unsigned int)); break;
00355             case 's': num = PutString(pStr, va_arg(ap, char *)); break;
00356             case 'c': num = PutChar(pStr, va_arg(ap, unsigned int)); break;
00357             default:
00358                 return EOF;
00359             }
00360 
00361             pFormat++;
00362             pStr += num;
00363             size += num;
00364         }
00365     }
00366 
00367     // NULL-terminated (final \0 is not counted)
00368     if (size < length) {
00369 
00370         *pStr = 0;
00371     }
00372     else {
00373 
00374         *(--pStr) = 0;
00375         size--;
00376     }
00377 
00378     return size;
00379 }
00380 
00381 //------------------------------------------------------------------------------
00389 //------------------------------------------------------------------------------
00390 signed int snprintf(char *pString, size_t length, const char *pFormat, ...)
00391 {
00392     va_list    ap;
00393     signed int rc;
00394 
00395     va_start(ap, pFormat);
00396     rc = vsnprintf(pString, length, pFormat, ap);
00397     va_end(ap);
00398 
00399     return rc;
00400 }
00401 
00402 //------------------------------------------------------------------------------
00409 //------------------------------------------------------------------------------
00410 signed int vsprintf(char *pString, const char *pFormat, va_list ap)
00411 {
00412     return vsnprintf(pString, MAX_STRING_SIZE, pFormat, ap);
00413 }
00414 
00415 //------------------------------------------------------------------------------
00421 //------------------------------------------------------------------------------
00422 signed int vfprintf(FILE *pStream, const char *pFormat, va_list ap)
00423 {
00424     char pStr[MAX_STRING_SIZE];
00425     char pError[] = "stdio.c: increase MAX_STRING_SIZE\n\r";
00426 
00427     // Write formatted string in buffer
00428     if (vsprintf(pStr, pFormat, ap) >= MAX_STRING_SIZE) {
00429 
00430         fputs(pError, stderr);
00431         while (1); // Increase MAX_STRING_SIZE
00432     }
00433 
00434     // Display string
00435     return fputs(pStr, pStream);
00436 }
00437 
00438 //------------------------------------------------------------------------------
00443 //------------------------------------------------------------------------------
00444 signed int vprintf(const char *pFormat, va_list ap)
00445 {
00446     return vfprintf(stdout, pFormat, ap);
00447 }
00448 
00449 //------------------------------------------------------------------------------
00454 //------------------------------------------------------------------------------
00455 signed int fprintf(FILE *pStream, const char *pFormat, ...)
00456 {
00457     va_list ap;
00458     signed int result;
00459 
00460     // Forward call to vfprintf
00461     va_start(ap, pFormat);
00462     result = vfprintf(pStream, pFormat, ap);
00463     va_end(ap);
00464 
00465     return result;
00466 }
00467 
00468 //------------------------------------------------------------------------------
00472 //------------------------------------------------------------------------------
00473 signed int printf(const char *pFormat, ...)
00474 {
00475     va_list ap;
00476     signed int result;
00477 
00478     // Forward call to vprintf
00479     va_start(ap, pFormat);
00480     result = vprintf(pFormat, ap);
00481     va_end(ap);
00482 
00483     return result;
00484 }
00485 
00486 //------------------------------------------------------------------------------
00490 //------------------------------------------------------------------------------
00491 signed int sprintf(char *pStr, const char *pFormat, ...)
00492 {
00493     va_list ap;
00494     signed int result;
00495 
00496     // Forward call to vsprintf
00497     va_start(ap, pFormat);
00498     result = vsprintf(pStr, pFormat, ap);
00499     va_end(ap);
00500 
00501     return result;
00502 }
00503 
00504 //------------------------------------------------------------------------------
00507 //------------------------------------------------------------------------------
00508 signed int puts(const char *pStr)
00509 {
00510     return fputs(pStr, stdout);
00511 }
00512