home *** CD-ROM | disk | FTP | other *** search
/ linuxmafia.com 2016 / linuxmafia.com.tar / linuxmafia.com / pub / palmos / pippy-0.6beta-src.tar.gz / pippy-0.6beta-src.tar / pippy-0.6beta-src / src / Palm / libc / vsprintf.c < prev   
C/C++ Source or Header  |  2000-12-21  |  7KB  |  415 lines

  1. /*
  2.  *  linux/lib/vsprintf.c
  3.  *
  4.  *  Copyright (C) 1991, 1992  Linus Torvalds
  5.  */
  6.  
  7. /* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
  8. /*
  9.  * Wirzenius wrote this portably, Torvalds fucked it up :-)
  10.  */
  11.  
  12. /* Adapted for the use in the 332 kernel, then again for PalmOS/Pilot
  13.  * Added floating point support, D. Jeff Dionne, 1995, 1997
  14.  */
  15.  
  16. #include <stdio.h>
  17. #include <sys/types.h>
  18. #include <string.h>
  19. #include <ctype.h>
  20.  
  21. /* we use this so that we can do without the ctype library */
  22. #define is_digit(c)    ((c) >= '0' && (c) <= '9')
  23.  
  24. static int skip_atoi(const char **s) SEG_LIBC;
  25. static int skip_atoi(const char **s)
  26. {
  27.     int i=0;
  28.  
  29.     while (is_digit(**s))
  30.         i = i*10 + *((*s)++) - '0';
  31.     return i;
  32. }
  33.  
  34. #define ZEROPAD    1        /* pad with zero */
  35. #define SIGN    2        /* unsigned/signed long */
  36. #define PLUS    4        /* show plus */
  37. #define SPACE    8        /* space if plus */
  38. #define LEFT    16        /* left justified */
  39. #define SPECIAL    32        /* 0x */
  40. #define LARGE    64        /* use 'ABCDEF' instead of 'abcdef' */
  41.  
  42. #define do_div(n,base) ({ \
  43. int __res; \
  44. __res = ((unsigned long) n) % (unsigned) base; \
  45. n = ((unsigned long) n) / (unsigned) base; \
  46. __res; })
  47.  
  48. #ifdef PRINT_FLOATS
  49. #define PSH(X) (*(st++)=(X))
  50.  
  51. char * ftoa(char *st, float f, int flags)
  52. {
  53.   int i;
  54.   int z;
  55.   int exp = 0;
  56.  
  57.   if (f < 0) {
  58.     PSH('-');
  59.     f = -f;
  60.   } else {
  61.     if (flags & PLUS) PSH('+');
  62.     if (flags & SPACE) PSH(' ');
  63.   }
  64.  
  65.   if (f) {
  66.     while (f < 1) {
  67.       f *=10;
  68.       exp--;
  69.     }
  70.  
  71.     while (f >= 10) {
  72.       f /=10;
  73.       exp++;
  74.     }
  75.   }
  76.  
  77.   PSH('0'+f);
  78.   z = f;
  79.   f -= z;
  80.   f *= 10;
  81.   PSH('.');
  82.  
  83.   for (i=0;i<4;i++) {
  84.     PSH('0'+f);
  85.     z = f;
  86.     f -= z;
  87.     f *= 10;
  88.   }
  89.  
  90.   PSH('e');
  91.   if (exp < 0) {
  92.     PSH('-');
  93.     exp = -exp;
  94.   } else {
  95.     PSH('+');
  96.   }
  97.  
  98.   PSH('0'+exp/10);
  99.   exp -= (exp/10) * 10;
  100.   PSH('0'+exp);
  101.  
  102.   return st;
  103. }
  104.  
  105. /* jdc - added the following for doubles */
  106. char * dtoa(char *st, double f, int flags)
  107. {
  108.   int i;
  109.   int z;
  110.   int exp = 0;
  111.  
  112.   if (f < 0) {
  113.     PSH('-');
  114.     f = -f;
  115.   } else {
  116.     if (flags & PLUS) PSH('+');
  117.     if (flags & SPACE) PSH(' ');
  118.   }
  119.  
  120.   if (f) {
  121.     while (f < 1) {
  122.       f *=10;
  123.       exp--;
  124.     }
  125.  
  126.     while (f >= 10) {
  127.       f /=10;
  128.       exp++;
  129.     }
  130.   }
  131.  
  132.   PSH('0'+f);
  133.   z = f;
  134.   f -= z;
  135.   f *= 10;
  136.   PSH('.');
  137.  
  138.   for (i=0;i<4;i++) {
  139.     PSH('0'+f);
  140.     z = f;
  141.     f -= z;
  142.     f *= 10;
  143.   }
  144.  
  145.   PSH('e');
  146.   if (exp < 0) {
  147.     PSH('-');
  148.     exp = -exp;
  149.   } else {
  150.     PSH('+');
  151.   }
  152.  
  153.   PSH('0'+exp/10);
  154.   exp -= (exp/10) * 10;
  155.   PSH('0'+exp);
  156.  
  157.   return st;
  158. }
  159.  
  160. #endif /* PRINT_FLOATS */
  161.  
  162. static char * number(char * str, long num, int base, int size, int precision
  163.     ,int type) SEG_LIBC;
  164.  
  165. static char * number(char * str, long num, int base, int size, int precision
  166.     ,int type)
  167. {
  168.     char c,sign,tmp[66];
  169.     const char *digits="0123456789abcdefghijklmnopqrstuvwxyz";
  170.     int i;
  171.  
  172.     if (type & LARGE)
  173.         digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  174.     if (type & LEFT)
  175.         type &= ~ZEROPAD;
  176.     if (base < 2 || base > 36)
  177.         return 0;
  178.     c = (type & ZEROPAD) ? '0' : ' ';
  179.     sign = 0;
  180.     if (type & SIGN) {
  181.         if (num < 0) {
  182.             sign = '-';
  183.             num = -num;
  184.             size--;
  185.         } else if (type & PLUS) {
  186.             sign = '+';
  187.             size--;
  188.         } else if (type & SPACE) {
  189.             sign = ' ';
  190.             size--;
  191.         }
  192.     }
  193.     if (type & SPECIAL) {
  194.         if (base == 16)
  195.             size -= 2;
  196.         else if (base == 8)
  197.             size--;
  198.     }
  199.     i = 0;
  200.     if (num == 0)
  201.         tmp[i++]='0';
  202.     else while (num != 0)
  203.         tmp[i++] = digits[do_div(num,base)];
  204.     if (i > precision)
  205.         precision = i;
  206.     size -= precision;
  207.     if (!(type&(ZEROPAD+LEFT)))
  208.         while(size-->0)
  209.             *str++ = ' ';
  210.     if (sign)
  211.         *str++ = sign;
  212.     if (type & SPECIAL) {
  213.         if (base==8)
  214.             *str++ = '0';
  215.         else if (base==16) {
  216.             *str++ = '0';
  217.             *str++ = digits[33];
  218.         }
  219.     }
  220.     if (!(type & LEFT))
  221.         while (size-- > 0)
  222.             *str++ = c;
  223.     while (i < precision--)
  224.         *str++ = '0';
  225.     while (i-- > 0)
  226.         *str++ = tmp[i];
  227.     while (size-- > 0)
  228.         *str++ = ' ';
  229.     return str;
  230. }
  231.  
  232. int vsprintf(char *buf, const char *fmt, va_list args)
  233. {
  234.     int len;
  235.     unsigned long num;
  236.     int i, base;
  237.     char * str;
  238.     char *s;
  239. #ifdef PRINT_FLOATS
  240.     float fl;
  241.     double gl;
  242. #endif /* PRINT_FLOATS */
  243.     int flags;        /* flags to number() */
  244.  
  245.     int field_width;    /* width of output field */
  246.     int precision;        /* min. # of digits for integers; max
  247.                    number of chars for from string */
  248.     int qualifier;        /* 'h', 'l', or 'L' for integer fields */
  249.  
  250.     for (str=buf ; *fmt ; ++fmt) {
  251.         if (*fmt != '%') {
  252.             *str++ = *fmt;
  253.             continue;
  254.         }
  255.             
  256.         /* process flags */
  257.         flags = 0;
  258.         repeat:
  259.             ++fmt;        /* this also skips first '%' */
  260.             switch (*fmt) {
  261.                 case '-': flags |= LEFT; goto repeat;
  262.                 case '+': flags |= PLUS; goto repeat;
  263.                 case ' ': flags |= SPACE; goto repeat;
  264.                 case '#': flags |= SPECIAL; goto repeat;
  265.                 case '0': flags |= ZEROPAD; goto repeat;
  266.                 }
  267.         
  268.         /* get field width */
  269.         field_width = -1;
  270.         if (is_digit(*fmt))
  271.             field_width = skip_atoi(&fmt);
  272.         else if (*fmt == '*') {
  273.             ++fmt;
  274.             /* it's the next argument */
  275.             field_width = va_arg(args, int);
  276.             if (field_width < 0) {
  277.                 field_width = -field_width;
  278.                 flags |= LEFT;
  279.             }
  280.         }
  281.  
  282.         /* get the precision */
  283.         precision = -1;
  284.         if (*fmt == '.') {
  285.             ++fmt;    
  286.             if (is_digit(*fmt))
  287.                 precision = skip_atoi(&fmt);
  288.             else if (*fmt == '*') {
  289.                 ++fmt;
  290.                 /* it's the next argument */
  291.                 precision = va_arg(args, int);
  292.             }
  293.             if (precision < 0)
  294.                 precision = 0;
  295.         }
  296.  
  297.         /* get the conversion qualifier */
  298.         qualifier = -1;
  299.         if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') {
  300.             qualifier = *fmt;
  301.             ++fmt;
  302.         }
  303.  
  304.         /* default base */
  305.         base = 10;
  306.  
  307.         switch (*fmt) {
  308.         case 'c':
  309.             if (!(flags & LEFT))
  310.                 while (--field_width > 0)
  311.                     *str++ = ' ';
  312.             *str++ = (unsigned char) va_arg(args, int);
  313.             while (--field_width > 0)
  314.                 *str++ = ' ';
  315.             continue;
  316.  
  317.         case 's':
  318.             s = va_arg(args, char *);
  319.             if (!s)
  320.                 s = "<NULL>";
  321.  
  322.             len = strnlen(s, precision);
  323.  
  324.             if (!(flags & LEFT))
  325.                 while (len < field_width--)
  326.                     *str++ = ' ';
  327.             for (i = 0; i < len; ++i)
  328.                 *str++ = *s++;
  329.             while (len < field_width--)
  330.                 *str++ = ' ';
  331.             continue;
  332.  
  333.         case 'p':
  334.             if (field_width == -1) {
  335.                 field_width = 2*sizeof(void *);
  336.                 flags |= ZEROPAD;
  337.             }
  338.             str = number(str,
  339.                 (unsigned long) va_arg(args, void *), 16,
  340.                 field_width, precision, flags);
  341.             continue;
  342.  
  343. #ifdef PRINT_FLOATS
  344.                 case 'e':
  345. /*                 fl = va_arg(args, double); */
  346. /*             str = ftoa(str,fl,flags); */
  347.                 gl = va_arg(args, double);
  348.             str = dtoa(str,gl,flags);
  349.                         continue;
  350. #endif /* PRINT_FLOATS */
  351.  
  352.         case 'n':
  353.             if (qualifier == 'l') {
  354.                 long * ip = va_arg(args, long *);
  355.                 *ip = (str - buf);
  356.             } else {
  357.                 int * ip = va_arg(args, int *);
  358.                 *ip = (str - buf);
  359.             }
  360.             continue;
  361.  
  362.         /* integer number formats - set up the flags and "break" */
  363.         case 'o':
  364.             base = 8;
  365.             break;
  366.  
  367.         case 'X':
  368.             flags |= LARGE;
  369.         case 'x':
  370.             base = 16;
  371.             break;
  372.  
  373.         case 'd':
  374.         case 'i':
  375.             flags |= SIGN;
  376.         case 'u':
  377.             break;
  378.  
  379.         default:
  380.             if (*fmt != '%')
  381.                 *str++ = '%';
  382.             if (*fmt)
  383.                 *str++ = *fmt;
  384.             else
  385.                 --fmt;
  386.             continue;
  387.         }
  388.         if (qualifier == 'l')
  389.             num = va_arg(args, unsigned long);
  390.         else if (qualifier == 'h')
  391.             if (flags & SIGN)
  392.                 num = va_arg(args, short);
  393.             else
  394.                 num = va_arg(args, unsigned short);
  395.         else if (flags & SIGN)
  396.             num = va_arg(args, int);
  397.         else
  398.             num = va_arg(args, unsigned int);
  399.         str = number(str, num, base, field_width, precision, flags);
  400.     }
  401.     *str = '\0';
  402.     return str-buf;
  403. }
  404.  
  405. int sprintf(char * buf, const char *fmt, ...)
  406. {
  407.     va_list args;
  408.     int i;
  409.  
  410.     va_start(args, fmt);
  411.     i=vsprintf(buf,fmt,args);
  412.     va_end(args);
  413.     return i;
  414. }
  415.