SAM3S8/SD8 Software Package: sam-ba_applets/common/samba_stdio.c Source File

SAM3S8/SD8 Software Package 1.2

# samba_stdio.c

    00001 /* ----------------------------------------------------------------------------
    00002  *         ATMEL Microcontroller Software Support
    00003  * ----------------------------------------------------------------------------
    00004  * Copyright (c) 2010, 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 /**
    00031  * \section Purpose
    00032  *
    00033  * Implementation of several stdio.h methods, such as printf(), sprintf() and
    00034  * so on. This reduces the memory footprint of the binary when using those
    00035  * methods, compared to the libc implementation.
    00036  *
    00037  * \section Usage
    00038  *
    00039  * Adds stdio.c to the list of file to compile for the project. This will
    00040  * automatically replace libc methods by the custom ones.
    00041  */
    00042
    00043 /*----------------------------------------------------------------------------
    00044  *        Headers
    00045  *----------------------------------------------------------------------------*/
    00046
    00047 #include <stdio.h>
    00048 #include <stdarg.h>
    00049
    00050 /*----------------------------------------------------------------------------
    00051  *        Definitions
    00052  *----------------------------------------------------------------------------*/
    00053
    00054 /* Maximum string size allowed (in bytes). */
    00055 #define MAX_STRING_SIZE         100
    00056
    00057 /*----------------------------------------------------------------------------
    00058  *        Variables
    00059  *----------------------------------------------------------------------------*/
    00060
    00061 /* Required for proper compilation. */
    00062 struct _reent r = {0, (FILE *) 0, (FILE *) 1, (FILE *) 0};
    00063 struct _reent *_impure_ptr = &r;
    00064
    00065 /*----------------------------------------------------------------------------
    00066  *        Local functions
    00067  *----------------------------------------------------------------------------*/
    00068
    00069 /**
    00070  * \brief Writes a character inside the given string.
    00071  *
    00072  * \param pStr  Storage string.
    00073  * \param c  Character to write.
    00074  *
    00075  * \return Returns 1.
    00076  */
    00077 signed int PutChar(char *pStr, char c)
    00078 {
    00079     *pStr = c;
    00080     return 1;
    00081 }
    00082
    00083 /**
    00084  * \brief Writes a string inside the given string.
    00085  *
    00086  * \param pStr  Storage string.
    00087  * \param pSource  Source string.
    00088  *
    00089  * \return Returns the size of the written string.
    00090  */
    00091 signed int PutString(char *pStr, const char *pSource)
    00092 {
    00093     signed int num = 0;
    00094
    00095     while (*pSource != 0) {
    00096
    00097         *pStr++ = *pSource++;
    00098         num++;
    00099     }
    00100
    00101     return num;
    00102 }
    00103
    00104 /**
    00105  * \brief Writes an unsigned int inside the given string, using the provided fill &
    00106  * width parameters.
    00107  *
    00108  * \param pStr  Storage string.
    00109  * \param fill  Fill character.
    00110  * \param width  Minimum integer width.
    00111  * \param value  Integer value.
    00112  *
    00113  * \return Returns the size in characters of the written integer.
    00114  */
    00115 signed int PutUnsignedInt(
    00116     char *pStr,
    00117     char fill,
    00118     signed int width,
    00119     unsigned int value)
    00120 {
    00121     signed int num = 0;
    00122
    00123     /* Take current digit into account when calculating width */
    00124     width--;
    00125
    00126     /* Recursively write upper digits */
    00127     if ((value / 10) > 0) {
    00128
    00129         num = PutUnsignedInt(pStr, fill, width, value / 10);
    00130         pStr += num;
    00131     }
    00132     /* Write filler characters */
    00133     else {
    00134
    00135         while (width > 0) {
    00136
    00137             PutChar(pStr, fill);
    00138             pStr++;
    00139             num++;
    00140             width--;
    00141         }
    00142     }
    00143
    00144     /* Write lower digit */
    00145     num += PutChar(pStr, (value % 10) + '0');
    00146
    00147     return num;
    00148 }
    00149
    00150 /**
    00151  * \brief Writes a signed int inside the given string, using the provided fill & width
    00152  * parameters.
    00153  *
    00154  * \param pStr  Storage string.
    00155  * \param fill  Fill character.
    00156  * \param width  Minimum integer width.
    00157  * \param value  Signed integer value.
    00158  *
    00159  * \return Returns the size of the written integer.
    00160  */
    00161 signed int PutSignedInt(
    00162     char *pStr,
    00163     char fill,
    00164     signed int width,
    00165     signed int value)
    00166 {
    00167     signed int num = 0;
    00168     unsigned int absolute;
    00169
    00170     /* Compute absolute value */
    00171     if (value < 0) {
    00172
    00173         absolute = -value;
    00174     }
    00175     else {
    00176
    00177         absolute = value;
    00178     }
    00179
    00180     /* Take current digit into account when calculating width */
    00181     width--;
    00182
    00183     /* Recursively write upper digits */
    00184     if ((absolute / 10) > 0) {
    00185
    00186         if (value < 0) {
    00187
    00188             num = PutSignedInt(pStr, fill, width, -(absolute / 10));
    00189         }
    00190         else {
    00191
    00192             num = PutSignedInt(pStr, fill, width, absolute / 10);
    00193         }
    00194         pStr += num;
    00195     }
    00196     else {
    00197
    00198         /* Reserve space for sign */
    00199         if (value < 0) {
    00200
    00201             width--;
    00202         }
    00203
    00204         /* Write filler characters */
    00205         while (width > 0) {
    00206
    00207             PutChar(pStr, fill);
    00208             pStr++;
    00209             num++;
    00210             width--;
    00211         }
    00212
    00213         /* Write sign */
    00214         if (value < 0) {
    00215
    00216             num += PutChar(pStr, '-');
    00217             pStr++;
    00218         }
    00219     }
    00220
    00221     /* Write lower digit */
    00222     num += PutChar(pStr, (absolute % 10) + '0');
    00223
    00224     return num;
    00225 }
    00226
    00227 /**
    00228  * \brief Writes an hexadecimal value into a string, using the given fill, width &
    00229  * capital parameters.
    00230  *
    00231  * \param pStr  Storage string.
    00232  * \param fill  Fill character.
    00233  * \param width  Minimum integer width.
    00234  * \param maj  Indicates if the letters must be printed in lower- or upper-case.
    00235  * \param value  Hexadecimal value.
    00236  *
    00237  * \return Returns the number of char written.
    00238  */
    00239 signed int PutHexa(
    00240     char *pStr,
    00241     char fill,
    00242     signed int width,
    00243     unsigned char maj,
    00244     unsigned int value)
    00245 {
    00246     signed int num = 0;
    00247
    00248     /* Decrement width */
    00249     width--;
    00250
    00251     /* Recursively output upper digits */
    00252     if ((value >> 4) > 0) {
    00253
    00254         num += PutHexa(pStr, fill, width, maj, value >> 4);
    00255         pStr += num;
    00256     }
    00257     /* Write filler chars */
    00258     else {
    00259
    00260         while (width > 0) {
    00261
    00262             PutChar(pStr, fill);
    00263             pStr++;
    00264             num++;
    00265             width--;
    00266         }
    00267     }
    00268
    00269     /* Write current digit */
    00270     if ((value & 0xF) < 10) {
    00271
    00272         PutChar(pStr, (value & 0xF) + '0');
    00273     }
    00274     else if (maj) {
    00275
    00276         PutChar(pStr, (value & 0xF) - 10 + 'A');
    00277     }
    00278     else {
    00279
    00280         PutChar(pStr, (value & 0xF) - 10 + 'a');
    00281     }
    00282     num++;
    00283
    00284     return num;
    00285 }
    00286
    00287 /*----------------------------------------------------------------------------
    00288  *        Exported functions
    00289  *----------------------------------------------------------------------------*/
    00290
    00291 /**
    00292  * \brief Stores the result of a formatted string into another string. Format
    00293  * arguments are given in a va_list instance.
    00294  *
    00295  * \param pStr    Destination string.
    00296  * \param length  Length of Destination string.
    00297  * \param pFormat Format string.
    00298  * \param ap      Argument list.
    00299  *
    00300  * \return Return the number of characters written.
    00301  */
    00302 signed int vsnprintf(char *pStr, size_t length, const char *pFormat, va_list ap)
    00303 {
    00304     char          fill;
    00305     unsigned char width;
    00306     signed int    num = 0;
    00307     signed int    size = 0;
    00308
    00309     /* Clear the string */
    00310     if (pStr) {
    00311
    00312         *pStr = 0;
    00313     }
    00314
    00315     /* Phase string */
    00316     while (*pFormat != 0 && size < length) {
    00317
    00318         /* Normal character */
    00319         if (*pFormat != '%') {
    00320
    00321             *pStr++ = *pFormat++;
    00322             size++;
    00323         }
    00324         /* Escaped '%' */
    00325         else if (*(pFormat+1) == '%') {
    00326
    00327             *pStr++ = '%';
    00328             pFormat += 2;
    00329             size++;
    00330         }
    00331         /* Token delimiter */
    00332         else {
    00333
    00334             fill = ' ';
    00335             width = 0;
    00336             pFormat++;
    00337
    00338             /* Parse filler */
    00339             if (*pFormat == '0') {
    00340
    00341                 fill = '0';
    00342                 pFormat++;
    00343             }
    00344
    00345             /* Parse width */
    00346             while ((*pFormat >= '0') && (*pFormat <= '9')) {
    00347
    00348                 width = (width*10) + *pFormat-'0';
    00349                 pFormat++;
    00350             }
    00351
    00352             /* Check if there is enough space */
    00353             if (size + width > length) {
    00354
    00355                 width = length - size;
    00356             }
    00357
    00358             /* Parse type */
    00359             switch (*pFormat) {
    00360             case 'd':
    00361             case 'i': num = PutSignedInt(pStr, fill, width, va_arg(ap, signed int)); break;
    00362             case 'u': num = PutUnsignedInt(pStr, fill, width, va_arg(ap, unsigned int)); break;
    00363             case 'x': num = PutHexa(pStr, fill, width, 0, va_arg(ap, unsigned int)); break;
    00364             case 'X': num = PutHexa(pStr, fill, width, 1, va_arg(ap, unsigned int)); break;
    00365             case 's': num = PutString(pStr, va_arg(ap, char *)); break;
    00366             case 'c': num = PutChar(pStr, va_arg(ap, unsigned int)); break;
    00367             default:
    00368                 return EOF;
    00369             }
    00370
    00371             pFormat++;
    00372             pStr += num;
    00373             size += num;
    00374         }
    00375     }
    00376
    00377     /* NULL-terminated (final \0 is not counted) */
    00378     if (size < length) {
    00379
    00380         *pStr = 0;
    00381     }
    00382     else {
    00383
    00384         *(--pStr) = 0;
    00385         size--;
    00386     }
    00387
    00388     return size;
    00389 }
    00390
    00391 /**
    00392  * \brief Stores the result of a formatted string into another string. Format
    00393  * arguments are given in a va_list instance.
    00394  *
    00395  * \param pString Destination string.
    00396  * \param length  Length of Destination string.
    00397  * \param pFormat Format string.
    00398  * \param ...     Other arguments
    00399  *
    00400  * \return Return the number of characters written.
    00401  */
    00402 signed int snprintf(char *pString, size_t length, const char *pFormat, ...)
    00403 {
    00404     va_list    ap;
    00405     signed int rc;
    00406
    00407     va_start(ap, pFormat);
    00408     rc = vsnprintf(pString, length, pFormat, ap);
    00409     va_end(ap);
    00410
    00411     return rc;
    00412 }
    00413
    00414 /**
    00415  * \brief Stores the result of a formatted string into another string. Format
    00416  * arguments are given in a va_list instance.
    00417  *
    00418  * \param pString  Destination string.
    00419  * \param pFormat  Format string.
    00420  * \param ap       Argument list.
    00421  *
    00422  * \return Return the number of characters written.
    00423  */
    00424 signed int vsprintf(char *pString, const char *pFormat, va_list ap)
    00425 {
    00426     return vsnprintf(pString, MAX_STRING_SIZE, pFormat, ap);
    00427 }
    00428
    00429 /**
    00430  * \brief Outputs a formatted string on the given stream. Format arguments are given
    00431  * in a va_list instance.
    00432  *
    00433  * \param pStream  Output stream.
    00434  * \param pFormat  Format string
    00435  * \param ap  Argument list.
    00436  */
    00437 signed int vfprintf(FILE *pStream, const char *pFormat, va_list ap)
    00438 {
    00439     char pStr[MAX_STRING_SIZE];
    00440     char pError[] = "stdio.c: increase MAX_STRING_SIZE\n\r";
    00441
    00442     /* Write formatted string in buffer */
    00443     if (vsprintf(pStr, pFormat, ap) >= MAX_STRING_SIZE) {
    00444
    00445         fputs(pError, stderr);
    00446         while (1); /* Increase MAX_STRING_SIZE */
    00447     }
    00448
    00449     /* Display string */
    00450     return fputs(pStr, pStream);
    00451 }
    00452
    00453 /**
    00454  * \brief Outputs a formatted string on the UART stream. Format arguments are given
    00455  * in a va_list instance.
    00456  *
    00457  * \param pFormat  Format string
    00458  * \param ap  Argument list.
    00459  */
    00460 signed int vprintf(const char *pFormat, va_list ap)
    00461 {
    00462     return vfprintf(stdout, pFormat, ap);
    00463 }
    00464
    00465 /**
    00466  * \brief Outputs a formatted string on the given stream, using a variable number of
    00467  * arguments.
    00468  *
    00469  * \param pStream  Output stream.
    00470  * \param pFormat  Format string.
    00471  */
    00472 signed int fprintf(FILE *pStream, const char *pFormat, ...)
    00473 {
    00474     va_list ap;
    00475     signed int result;
    00476
    00477     /* Forward call to vfprintf */
    00478     va_start(ap, pFormat);
    00479     result = vfprintf(pStream, pFormat, ap);
    00480     va_end(ap);
    00481
    00482     return result;
    00483 }
    00484
    00485 /**
    00486  * \brief Outputs a formatted string on the UART stream, using a variable number of
    00487  * arguments.
    00488  *
    00489  * \param pFormat  Format string.
    00490  */
    00491 signed int printf(const char *pFormat, ...)
    00492 {
    00493     va_list ap;
    00494     signed int result;
    00495
    00496     /* Forward call to vprintf */
    00497     va_start(ap, pFormat);
    00498     result = vprintf(pFormat, ap);
    00499     va_end(ap);
    00500
    00501     return result;
    00502 }
    00503
    00504 /**
    00505  * \brief Writes a formatted string inside another string.
    00506  *
    00507  * \param pStr  Storage string.
    00508  * \param pFormat  Format string.
    00509  */
    00510 signed int sprintf(char *pStr, const char *pFormat, ...)
    00511 {
    00512     va_list ap;
    00513     signed int result;
    00514
    00515     /* Forward call to vsprintf */
    00516     va_start(ap, pFormat);
    00517     result = vsprintf(pStr, pFormat, ap);
    00518     va_end(ap);
    00519
    00520     return result;
    00521 }
    00522
    00523 /**
    00524  * \brief Outputs a string on stdout.
    00525  *
    00526  * \param pStr  String to output.
    00527  */
    00528 signed int puts(const char *pStr)
    00529 {
    00530     return fputs(pStr, stdout);
    00531 }
    00532

All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines