Subversion Repositories libSmallPrintf

Rev

Rev 5 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.         Copyright 2001, 2002 Georges Menie (www.menie.org)
  3.         stdarg version contributed by Christian Ettinger
  4.  
  5.         This program is free software; you can redistribute it and/or modify
  6.         it under the terms of the GNU Lesser General Public License as published by
  7.         the Free Software Foundation; either version 2 of the License, or
  8.         (at your option) any later version.
  9.  
  10.         This program is distributed in the hope that it will be useful,
  11.         but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.         GNU Lesser General Public License for more details.
  14.  
  15.         You should have received a copy of the GNU Lesser General Public License
  16.         along with this program; if not, write to the Free Software
  17.         Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18. */
  19.  
  20. /* Includes */
  21.  
  22. #include "libSmallPrintf/small_printf.h"
  23.  
  24. #include <stdarg.h>
  25. #include <stdio.h>
  26. #include <string.h>
  27.  
  28. /*
  29.         putchar is the only external dependency for this file,
  30.         if you have a working putchar, leave it commented out.
  31.         If not, uncomment the define below and
  32.         replace outbyte(c) by your own function call.
  33. */
  34. #if defined SERIAL_UART1 || defined SERIAL_UART2 || defined SERIAL_UART3 || defined SERIAL_UART4
  35. extern void PutCharSerial(char c);
  36. #endif
  37.  
  38. static void printchar(char **str, int c)
  39. {
  40.  
  41.         if (str)
  42.         {
  43.                 **str = c;
  44.                 ++(*str);
  45.         }
  46. #if defined SERIAL_UART1 || defined SERIAL_UART2 || defined SERIAL_UART3 || defined SERIAL_UART4
  47.         else
  48.                 (void)PutCharSerial(c);
  49. #endif
  50. }
  51.  
  52. char static const PAD_RIGHT = 1;
  53. char static const PAD_ZERO = 2;
  54.  
  55. static int prints(char **out, const char *string, int width, int pad)
  56. {
  57.         register int pc = 0, padchar = ' ';
  58.  
  59.         if (width > 0)
  60.         {
  61.                 register int len = 0;
  62.                 register const char *ptr;
  63.                 for (ptr = string; *ptr; ++ptr)
  64.                         ++len;
  65.                 if (len >= width)
  66.                         width = 0;
  67.                 else
  68.                         width -= len;
  69.                 if (pad & PAD_ZERO)
  70.                         padchar = '0';
  71.         }
  72.         if (!(pad & PAD_RIGHT))
  73.         {
  74.                 for (; width > 0; --width)
  75.                 {
  76.                         printchar(out, padchar);
  77.                         ++pc;
  78.                 }
  79.         }
  80.         for (; *string; ++string)
  81.         {
  82.                 printchar(out, *string);
  83.                 ++pc;
  84.         }
  85.         for (; width > 0; --width)
  86.         {
  87.                 printchar(out, padchar);
  88.                 ++pc;
  89.         }
  90.  
  91.         return pc;
  92. }
  93.  
  94. /* the following should be enough for 32 bit int */
  95. #define PRINT_BUF_LEN 12
  96.  
  97. static int printi(char **out, int i, int b, int sg, int width, int pad, int letbase)
  98. {
  99.         char print_buf[PRINT_BUF_LEN];
  100.         register char *s;
  101.         register int t, neg = 0, pc = 0;
  102.         register unsigned int u = i;
  103.  
  104.         if (i == 0)
  105.         {
  106.                 print_buf[0] = '0';
  107.                 print_buf[1] = '\0';
  108.                 return prints(out, print_buf, width, pad);
  109.         }
  110.  
  111.         if (sg && b == 10 && i < 0)
  112.         {
  113.                 neg = 1;
  114.                 u = -i;
  115.         }
  116.  
  117.         s = print_buf + PRINT_BUF_LEN - 1;
  118.         *s = '\0';
  119.  
  120.         while (u)
  121.         {
  122.                 t = u % b;
  123.                 if (t >= 10)
  124.                         t += letbase - '0' - 10;
  125.                 *--s = t + '0';
  126.                 u /= b;
  127.         }
  128.  
  129.         if (neg)
  130.         {
  131.                 if (width && (pad & PAD_ZERO))
  132.                 {
  133.                         printchar(out, '-');
  134.                         ++pc;
  135.                         --width;
  136.                 }
  137.                 else
  138.                 {
  139.                         *--s = '-';
  140.                 }
  141.         }
  142.  
  143.         return pc + prints(out, s, width, pad);
  144. }
  145.  
  146. static int small_print(char **out, const char *format, va_list args)
  147. {
  148.         register int width, pad;
  149.         register int pc = 0;
  150.         char scr[2];
  151.  
  152.         for (; *format != 0; ++format)
  153.         {
  154.                 if (*format == '%')
  155.                 {
  156.                         ++format;
  157.                         width = pad = 0;
  158.                         if (*format == '\0')
  159.                                 break;
  160.                         if (*format == '%')
  161.                                 goto out;
  162.                         if (*format == '-')
  163.                         {
  164.                                 ++format;
  165.                                 pad = PAD_RIGHT;
  166.                         }
  167.                         while (*format == '0')
  168.                         {
  169.                                 ++format;
  170.                                 pad |= PAD_ZERO;
  171.                         }
  172.                         if ('*' == *format)
  173.                         {
  174.                                 width = va_arg(args, int); // get width from next argument
  175.                                 format++;
  176.                         }
  177.                         else
  178.                         {
  179.                                 for (; *format >= '0' && *format <= '9'; ++format)
  180.                                 {
  181.                                         width *= 10;
  182.                                         width += *format - '0';
  183.                                 }
  184.                         }
  185.                         if (*format == 'l')
  186.                         { /* skip l in ld etc */
  187.                                 format++;
  188.                         }
  189.                         if (*format == 's')
  190.                         {
  191.                                 register char *s = (char *)va_arg(args, int);
  192.                                 pc += prints(out, s ? s : "(null)", width, pad);
  193.                                 continue;
  194.                         }
  195.                         if (*format == 'd')
  196.                         {
  197.                                 pc += printi(out, va_arg(args, int), 10, 1, width, pad, 'a');
  198.                                 continue;
  199.                         }
  200.                         if (*format == 'x')
  201.                         {
  202.                                 pc += printi(out, va_arg(args, int), 16, 0, width, pad, 'a');
  203.                                 continue;
  204.                         }
  205.                         if (*format == 'X')
  206.                         {
  207.                                 pc += printi(out, va_arg(args, int), 16, 0, width, pad, 'A');
  208.                                 continue;
  209.                         }
  210.                         if (*format == 'u')
  211.                         {
  212.                                 pc += printi(out, va_arg(args, int), 10, 0, width, pad, 'a');
  213.                                 continue;
  214.                         }
  215.                         if (*format == 'c')
  216.                         {
  217.                                 /* char are converted to int then pushed on the stack */
  218.                                 scr[0] = (char)va_arg(args, int);
  219.                                 scr[1] = '\0';
  220.                                 pc += prints(out, scr, width, pad);
  221.                                 continue;
  222.                         }
  223.                         if (*format == 'n')
  224.                         { /* convert number printed so far and store in *va_arg( args, int)... */
  225.                                 int *dp = (int *)va_arg(args, int);
  226.                                 *dp = pc;
  227.                                 continue;
  228.                         }
  229.                 }
  230.                 else
  231.                 {
  232.                 out:
  233.                         /* deal with LF -> CRLF mapping */
  234.                         if (*format == '\n')
  235.                         {
  236.                                 printchar(out, '\r');
  237.                                 ++pc; // extra char
  238.                         }
  239.                         printchar(out, *format);
  240.                         ++pc;
  241.                 }
  242.         }
  243.         if (out)
  244.                 **out = '\0';
  245.         return pc;
  246. }
  247.  
  248. int small_printf(const char *format, ...)
  249. {
  250.         int result = 0;
  251.         va_list args;
  252.  
  253.         va_start(args, format);
  254.         result = small_print(0, format, args);
  255.         va_end(args);
  256.         return result;
  257. }
  258.  
  259. int small_sprintf(char *out, const char *format, ...)
  260. {
  261.         int result = 0;
  262.         va_list args;
  263.         va_start(args, format);
  264.         result = small_print(&out, format, args);
  265.         va_end(args);
  266.         return result;
  267. }
  268.