stdio.c
上传用户:jnhtjd
上传日期:2022-07-16
资源大小:403k
文件大小:15k
源码类别:

微处理器开发

开发平台:

C/C++

  1. /* ----------------------------------------------------------------------------
  2.  *         ATMEL Microcontroller Software Support 
  3.  * ----------------------------------------------------------------------------
  4.  * Copyright (c) 2008, Atmel Corporation
  5.  *
  6.  * All rights reserved.
  7.  *
  8.  * Redistribution and use in source and binary forms, with or without
  9.  * modification, are permitted provided that the following conditions are met:
  10.  *
  11.  * - Redistributions of source code must retain the above copyright notice,
  12.  * this list of conditions and the disclaimer below.
  13.  *
  14.  * Atmel's name may not be used to endorse or promote products derived from
  15.  * this software without specific prior written permission.
  16.  *
  17.  * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
  18.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  19.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
  20.  * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
  21.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  22.  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
  23.  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  24.  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  25.  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  26.  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27.  * ----------------------------------------------------------------------------
  28.  */
  29. //------------------------------------------------------------------------------
  30. /// unit
  31. ///
  32. /// !Purpose
  33. ///
  34. /// Implementation of several stdio.h methods, such as printf(), sprintf() and
  35. /// so on. This reduces the memory footprint of the binary when using those
  36. /// methods, compared to the libc implementation.
  37. ///
  38. /// !Usage
  39. ///
  40. /// Adds stdio.c to the list of file to compile for the project. This will
  41. /// automatically replace libc methods by the custom ones.
  42. //------------------------------------------------------------------------------
  43. //------------------------------------------------------------------------------
  44. //         Headers
  45. //------------------------------------------------------------------------------
  46. #include <stdio.h>
  47. #include <stdarg.h>
  48. //------------------------------------------------------------------------------
  49. //         Local Definitions
  50. //------------------------------------------------------------------------------
  51. // Maximum string size allowed (in bytes).
  52. #define MAX_STRING_SIZE         100
  53. //------------------------------------------------------------------------------
  54. //         Global Variables
  55. //------------------------------------------------------------------------------
  56. // Required for proper compilation.
  57. struct _reent r = {0, (FILE *) 0, (FILE *) 1, (FILE *) 0};
  58. struct _reent *_impure_ptr = &r;
  59. //------------------------------------------------------------------------------
  60. //         Local Functions
  61. //------------------------------------------------------------------------------
  62. //------------------------------------------------------------------------------
  63. // Writes a character inside the given string. Returns 1.
  64. // param pStr  Storage string.
  65. // param c  Character to write.
  66. //------------------------------------------------------------------------------
  67. signed int PutChar(char *pStr, char c)
  68. {
  69.     *pStr = c;
  70.     return 1;
  71. }
  72. //------------------------------------------------------------------------------
  73. // Writes a string inside the given string.
  74. // Returns the size of the written
  75. // string.
  76. // param pStr  Storage string.
  77. // param pSource  Source string.
  78. //------------------------------------------------------------------------------
  79. signed int PutString(char *pStr, const char *pSource)
  80. {
  81.     signed int num = 0;
  82.     while (*pSource != 0) {
  83.         *pStr++ = *pSource++;
  84.         num++;
  85.     }
  86.     return num;
  87. }
  88. //------------------------------------------------------------------------------
  89. // Writes an unsigned int inside the given string, using the provided fill &
  90. // width parameters.
  91. // Returns the size in characters of the written integer.
  92. // param pStr  Storage string.
  93. // param fill  Fill character.
  94. // param width  Minimum integer width.
  95. // param value  Integer value.
  96. //------------------------------------------------------------------------------
  97. signed int PutUnsignedInt(
  98.     char *pStr,
  99.     char fill,
  100.     signed int width,
  101.     unsigned int value)
  102. {
  103.     signed int num = 0;
  104.     // Take current digit into account when calculating width
  105.     width--;
  106.     // Recursively write upper digits
  107.     if ((value / 10) > 0) {
  108.         num = PutUnsignedInt(pStr, fill, width, value / 10);
  109.         pStr += num;
  110.     }
  111.     // Write filler characters
  112.     else {
  113.         while (width > 0) {
  114.             PutChar(pStr, fill);
  115.             pStr++;
  116.             num++;
  117.             width--;
  118.         }
  119.     }
  120.     // Write lower digit
  121.     num += PutChar(pStr, (value % 10) + '0');
  122.     return num;
  123. }
  124. //------------------------------------------------------------------------------
  125. // Writes a signed int inside the given string, using the provided fill & width
  126. // parameters.
  127. // Returns the size of the written integer.
  128. // param pStr  Storage string.
  129. // param fill  Fill character.
  130. // param width  Minimum integer width.
  131. // param value  Signed integer value.
  132. //------------------------------------------------------------------------------
  133. signed int PutSignedInt(
  134.     char *pStr,
  135.     char fill,
  136.     signed int width,
  137.     signed int value)
  138. {
  139.     signed int num = 0;
  140.     unsigned int absolute;
  141.     // Compute absolute value
  142.     if (value < 0) {
  143.         absolute = -value;
  144.     }
  145.     else {
  146.         absolute = value;
  147.     }
  148.     // Take current digit into account when calculating width
  149.     width--;
  150.     // Recursively write upper digits
  151.     if ((absolute / 10) > 0) {
  152.         if (value < 0) {
  153.         
  154.             num = PutSignedInt(pStr, fill, width, -(absolute / 10));
  155.         }
  156.         else {
  157.             num = PutSignedInt(pStr, fill, width, absolute / 10);
  158.         }
  159.         pStr += num;
  160.     }
  161.     else {
  162.         // Reserve space for sign
  163.         if (value < 0) {
  164.             width--;
  165.         }
  166.         // Write filler characters
  167.         while (width > 0) {
  168.             PutChar(pStr, fill);
  169.             pStr++;
  170.             num++;
  171.             width--;
  172.         }
  173.         // Write sign
  174.         if (value < 0) {
  175.             num += PutChar(pStr, '-');
  176.             pStr++;
  177.         }
  178.     }
  179.     // Write lower digit
  180.     num += PutChar(pStr, (absolute % 10) + '0');
  181.     return num;
  182. }
  183. //------------------------------------------------------------------------------
  184. // Writes an hexadecimal value into a string, using the given fill, width &
  185. // capital parameters.
  186. // Returns the number of char written.
  187. // param pStr  Storage string.
  188. // param fill  Fill character.
  189. // param width  Minimum integer width.
  190. // param maj  Indicates if the letters must be printed in lower- or upper-case.
  191. // param value  Hexadecimal value.
  192. //------------------------------------------------------------------------------
  193. signed int PutHexa(
  194.     char *pStr,
  195.     char fill,
  196.     signed int width,
  197.     unsigned char maj,
  198.     unsigned int value)
  199. {
  200.     signed int num = 0;
  201.     // Decrement width
  202.     width--;
  203.     // Recursively output upper digits
  204.     if ((value >> 4) > 0) {
  205.         num += PutHexa(pStr, fill, width, maj, value >> 4);
  206.         pStr += num;
  207.     }
  208.     // Write filler chars
  209.     else {
  210.         while (width > 0) {
  211.             PutChar(pStr, fill);
  212.             pStr++;
  213.             num++;
  214.             width--;
  215.         }
  216.     }
  217.     // Write current digit
  218.     if ((value & 0xF) < 10) {
  219.         PutChar(pStr, (value & 0xF) + '0');
  220.     }
  221.     else if (maj) {
  222.         PutChar(pStr, (value & 0xF) - 10 + 'A');
  223.     }
  224.     else {
  225.         PutChar(pStr, (value & 0xF) - 10 + 'a');
  226.     }
  227.     num++;
  228.     return num;
  229. }
  230. //------------------------------------------------------------------------------
  231. //         Global Functions
  232. //------------------------------------------------------------------------------
  233. //------------------------------------------------------------------------------
  234. /// Stores the result of a formatted string into another string. Format
  235. /// arguments are given in a va_list instance.
  236. /// Return the number of characters written.
  237. /// param pStr    Destination string.
  238. /// param length  Length of Destination string.
  239. /// param pFormat Format string.
  240. /// param ap      Argument list.
  241. //------------------------------------------------------------------------------
  242. signed int vsnprintf(char *pStr, size_t length, const char *pFormat, va_list ap)
  243. {
  244.     char          fill;
  245.     unsigned char width;
  246.     signed int    num = 0;
  247.     signed int    size = 0;
  248.     // Clear the string
  249.     if (pStr) {
  250.         *pStr = 0;
  251.     }
  252.     // Phase string
  253.     while (*pFormat != 0 && size < length) {
  254.         // Normal character
  255.         if (*pFormat != '%') {
  256.             *pStr++ = *pFormat++;
  257.             size++;
  258.         }
  259.         // Escaped '%'
  260.         else if (*(pFormat+1) == '%') {
  261.             *pStr++ = '%';
  262.             pFormat += 2;
  263.             size++;
  264.         }
  265.         // Token delimiter
  266.         else {
  267.             fill = ' ';
  268.             width = 0;
  269.             pFormat++;
  270.             // Parse filler
  271.             if (*pFormat == '0') {
  272.                 fill = '0';
  273.                 pFormat++;
  274.             }
  275.             // Parse width
  276.             while ((*pFormat >= '0') && (*pFormat <= '9')) {
  277.         
  278.                 width = (width*10) + *pFormat-'0';
  279.                 pFormat++;
  280.             }
  281.             // Check if there is enough space
  282.             if (size + width > length) {
  283.                 width = length - size;
  284.             }
  285.         
  286.             // Parse type
  287.             switch (*pFormat) {
  288.             case 'd': 
  289.             case 'i': num = PutSignedInt(pStr, fill, width, va_arg(ap, signed int)); break;
  290.             case 'u': num = PutUnsignedInt(pStr, fill, width, va_arg(ap, unsigned int)); break;
  291.             case 'x': num = PutHexa(pStr, fill, width, 0, va_arg(ap, unsigned int)); break;
  292.             case 'X': num = PutHexa(pStr, fill, width, 1, va_arg(ap, unsigned int)); break;
  293.             case 's': num = PutString(pStr, va_arg(ap, char *)); break;
  294.             case 'c': num = PutChar(pStr, va_arg(ap, unsigned int)); break;
  295.             default:
  296.                 return EOF;
  297.             }
  298.             pFormat++;
  299.             pStr += num;
  300.             size += num;
  301.         }
  302.     }
  303.     // NULL-terminated (final  is not counted)
  304.     if (size < length) {
  305.         *pStr = 0;
  306.     }
  307.     else {
  308.         *(--pStr) = 0;
  309.         size--;
  310.     }
  311.     return size;
  312. }
  313. //------------------------------------------------------------------------------
  314. /// Stores the result of a formatted string into another string. Format
  315. /// arguments are given in a va_list instance.
  316. /// Return the number of characters written.
  317. /// param pString Destination string.
  318. /// param length  Length of Destination string.
  319. /// param pFormat Format string.
  320. /// param ...     Other arguments
  321. //------------------------------------------------------------------------------
  322. signed int snprintf(char *pString, size_t length, const char *pFormat, ...)
  323. {
  324.     va_list    ap;
  325.     signed int rc;
  326.     va_start(ap, pFormat);
  327.     rc = vsnprintf(pString, length, pFormat, ap);
  328.     va_end(ap);
  329.     return rc;
  330. }
  331. //------------------------------------------------------------------------------
  332. /// Stores the result of a formatted string into another string. Format
  333. /// arguments are given in a va_list instance.
  334. /// Return the number of characters written.
  335. /// param pString  Destination string.
  336. /// param pFormat  Format string.
  337. /// param ap       Argument list.
  338. //------------------------------------------------------------------------------
  339. signed int vsprintf(char *pString, const char *pFormat, va_list ap)
  340. {
  341.     return vsnprintf(pString, MAX_STRING_SIZE, pFormat, ap);
  342. }
  343. //------------------------------------------------------------------------------
  344. /// Outputs a formatted string on the given stream. Format arguments are given
  345. /// in a va_list instance.
  346. /// param pStream  Output stream.
  347. /// param pFormat  Format string
  348. /// param ap  Argument list.
  349. //------------------------------------------------------------------------------
  350. signed int vfprintf(FILE *pStream, const char *pFormat, va_list ap)
  351. {
  352.     char pStr[MAX_STRING_SIZE];
  353.     char pError[] = "stdio.c: increase MAX_STRING_SIZEnr";
  354.     // Write formatted string in buffer
  355.     if (vsprintf(pStr, pFormat, ap) >= MAX_STRING_SIZE) {
  356.         fputs(pError, stderr);
  357.         while (1); // Increase MAX_STRING_SIZE
  358.     }
  359.     // Display string
  360.     return fputs(pStr, pStream);
  361. }
  362. //------------------------------------------------------------------------------
  363. /// Outputs a formatted string on the DBGU stream. Format arguments are given
  364. /// in a va_list instance.
  365. /// param pFormat  Format string
  366. /// param ap  Argument list.
  367. //------------------------------------------------------------------------------
  368. signed int vprintf(const char *pFormat, va_list ap)
  369. {
  370.     return vfprintf(stdout, pFormat, ap);
  371. }
  372. //------------------------------------------------------------------------------
  373. /// Outputs a formatted string on the given stream, using a variable number of
  374. /// arguments.
  375. /// param pStream  Output stream.
  376. /// param pFormat  Format string.
  377. //------------------------------------------------------------------------------
  378. signed int fprintf(FILE *pStream, const char *pFormat, ...)
  379. {
  380.     va_list ap;
  381.     signed int result;
  382.     // Forward call to vfprintf
  383.     va_start(ap, pFormat);
  384.     result = vfprintf(pStream, pFormat, ap);
  385.     va_end(ap);
  386.     return result;
  387. }
  388. //------------------------------------------------------------------------------
  389. /// Outputs a formatted string on the DBGU stream, using a variable number of
  390. /// arguments.
  391. /// param pFormat  Format string.
  392. //------------------------------------------------------------------------------
  393. signed int printf(const char *pFormat, ...)
  394. {
  395.     va_list ap;
  396.     signed int result;
  397.     // Forward call to vprintf
  398.     va_start(ap, pFormat);
  399.     result = vprintf(pFormat, ap);
  400.     va_end(ap);
  401.     return result;
  402. }
  403. //------------------------------------------------------------------------------
  404. /// Writes a formatted string inside another string.
  405. /// param pStr  Storage string.
  406. /// param pFormat  Format string.
  407. //------------------------------------------------------------------------------
  408. signed int sprintf(char *pStr, const char *pFormat, ...)
  409. {
  410.     va_list ap;
  411.     signed int result;
  412.     // Forward call to vsprintf
  413.     va_start(ap, pFormat);
  414.     result = vsprintf(pStr, pFormat, ap);
  415.     va_end(ap);
  416.     return result;
  417. }
  418. //------------------------------------------------------------------------------
  419. /// Outputs a string on stdout.
  420. /// param pStr  String to output.
  421. //------------------------------------------------------------------------------
  422. signed int puts(const char *pStr)
  423. {
  424.     return fputs(pStr, stdout);
  425. }