vsnprintf.c
上传用户:pycemail
上传日期:2007-01-04
资源大小:329k
文件大小:7k
源码类别:

Ftp客户端

开发平台:

Unix_Linux

  1. /*
  2. This library is free software; you can redistribute it and/or
  3. modify it under the terms of the GNU Library General Public License as
  4. published by the Free Software Foundation; either version 2 of the
  5. License, or (at your option) any later version.
  6. This library is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  9. Library General Public License for more details.
  10. You should have received a copy of the GNU Library General Public
  11. License along with this library; see the file COPYING.LIB.  If
  12. not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite
  13. 330, Boston, MA  02111-1307, USA.  */
  14. /* Required to tell conf.h not to include the standard ProFTPD
  15.  * header files
  16.  */
  17. /* AIX requires this to be first */
  18. #if ! defined (__GNUC__) && defined (_AIX)
  19. #pragma alloca
  20. #endif
  21. #define __PROFTPD_SUPPORT_LIBRARY
  22. #include <conf.h>
  23. #include <libsupp.h>
  24. #if !defined(HAVE_VSNPRINTF) || !defined(HAVE_SNPRINTF)
  25. static size_t strnlen(const char *s, size_t count)
  26. {
  27.   const char *sc;
  28.   for(sc = s; count-- && *sc != ''; ++sc) ;
  29.   return sc - s;
  30. }
  31. static int skip_atoi(const char **s)
  32. {
  33.   int i = 0;
  34.   while(isdigit(**s))
  35.     i = i * 10 + *((*s)++) - '0';
  36.   return i;
  37. }
  38. #define ZEROPAD 1
  39. #define SIGN 2
  40. #define PLUS 4
  41. #define SPACE 8
  42. #define LEFT 16
  43. #define SPECIAL 32
  44. #define LARGE 64
  45. static char *number(char *str, long num, int base, int size, int
  46.                     precision, int type, size_t *max_size)
  47. {
  48.   char c,sign,tmp[66];
  49.   const char *digits="0123456789abcdefghijklmnopqrstuvwxyz";
  50.   int i;
  51.   size_t msize;
  52.   msize = *max_size;
  53.   if(type & LARGE)
  54.     digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  55.   if(type & LEFT)
  56.     type &= ~ZEROPAD;
  57.   if(base < 2 || base > 36)
  58.     return 0;
  59.   c = (type & ZEROPAD) ? '0' : ' ';
  60.   sign = 0;
  61.   if(type & SIGN) {
  62.     if(num < 0) {
  63.       sign = '-';
  64.       num = -num;
  65.       size--;
  66.     } else if(type & PLUS) {
  67.       sign = '+';
  68.       size--;
  69.     } else if(type & SPACE) {
  70.       sign = ' ';
  71.       size--;
  72.     }
  73.   }
  74.   if(type & SPECIAL) {
  75.     if(base == 16)
  76.       size -= 2;
  77.     else if(base == 8)
  78.       size--;
  79.   }
  80.   i = 0;
  81.   if(num == 0)
  82.     tmp[i++] = '0';
  83.   else while(num != 0) {
  84.    tmp[i++] = digits[((unsigned long) num) % (unsigned) base];
  85.           num /= base;
  86.   }
  87.   if(i > precision)
  88.     precision = i;
  89.   size -= precision;
  90.   if(!(type & (ZEROPAD+LEFT)))
  91.     while(size-- > 0 && msize) {
  92.       *str++ = ' ';
  93.       msize--;
  94.     }
  95.   if(sign && msize)
  96.     { *str++ = sign; msize--; }
  97.   if(msize) {
  98.     if(type & SPECIAL)
  99.       if(base == 8)
  100.         { *str++ = '0'; msize--; }
  101.       else if(base == 16) {
  102.         *str++ = '0'; msize--;
  103.         if(msize)
  104.           { *str++ = digits[33]; msize--; }
  105.       }
  106.   }
  107.   if(!(type & LEFT))
  108.     while(size-- > 0 && msize)
  109.       { *str++ = c; msize--; }
  110.   while(i < precision-- && msize)
  111.     { *str++ = '0'; msize--; }
  112.   while(i-- > 0 && msize)
  113.     { *str++ = tmp[i]; msize--; }
  114.   while(size-- > 0 && msize)
  115.     { *str++ = ' '; msize--; }
  116.   *max_size = msize;
  117.   return str;
  118. }
  119. int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
  120. {
  121.   int len;
  122.   unsigned long num;
  123.   int i, base; 
  124.   char *str;
  125.   const char *s;
  126.   int flags;
  127.   int field_width;
  128.   int precision;
  129.   int qualifier;
  130.   size--;
  131.   for(str = buf; *fmt && size; ++fmt) {
  132.     if(*fmt != '%') {
  133.       *str++ = *fmt;
  134.       size--;
  135.       continue;
  136.     }
  137.     flags = 0;
  138.     repeat:
  139.       ++fmt;
  140.       switch(*fmt) {
  141.         case '-': flags |= LEFT; goto repeat;
  142.         case '+': flags |= PLUS; goto repeat;
  143.         case ' ': flags |= SPACE; goto repeat;
  144.         case '#': flags |= SPECIAL; goto repeat;
  145.         case '0': flags |= ZEROPAD; goto repeat;
  146.       }
  147.       field_width = -1;
  148.       if(isdigit(*fmt))
  149.         field_width = skip_atoi(&fmt);
  150.       else if(*fmt == '*') {
  151.         ++fmt;
  152.         field_width = va_arg(args,int);
  153.         if(field_width < 0) {
  154.           field_width = - field_width;
  155.           flags |= LEFT;
  156.         }
  157.       }
  158.       precision = -1;
  159.       if(*fmt == '.') {
  160.         ++fmt;
  161.         if(isdigit(*fmt))
  162.           precision = skip_atoi(&fmt);
  163.         else if(*fmt == '*') {
  164.           ++fmt;
  165.           precision = va_arg(args,int);
  166.         }
  167.         if(precision < 0)
  168.           precision = 0;
  169.       }
  170.       qualifier = -1;
  171.       if(*fmt == 'h' || *fmt == 'l' || *fmt == 'L') {
  172.         qualifier = *fmt;
  173.         ++fmt;
  174.       }
  175.       base = 10;
  176.       switch(*fmt) {
  177.       case 'c':
  178.         if(!(flags & LEFT))
  179.           while(--field_width > 0 && size)
  180.             { *str++ = ' '; size--; }
  181.         if(size)
  182.           { *str++ = (unsigned char)va_arg(args,int); size--; }
  183.         while(--field_width > 0 && size)
  184.           { *str++ = ' '; size--; }
  185.         continue;
  186.       case 's':
  187.         s = va_arg(args,char*);
  188.         if(!s)
  189.           s = "(null)";
  190.         len = strnlen(s, precision);
  191.         if(!(flags & LEFT))
  192.           while(len < field_width-- && size) {
  193.             *str++ = ' ';
  194.             size--;
  195.           }
  196.         for(i = 0; i < len && size; ++i) {
  197.           *str++ = *s++;
  198.           size--;
  199.         }
  200. while(len < field_width-- && size) {
  201.           *str++ = ' ';
  202.           size--;
  203.         }
  204.         continue;
  205.       case 'p':
  206.         if(field_width == -1) {
  207.           field_width = 2 * sizeof(void*);
  208.           flags |= ZEROPAD;
  209.         }
  210.         str = number(str,
  211.                   (unsigned long)va_arg(args,void*),16,
  212.                   field_width, precision, flags, &size);
  213.         continue;
  214.       case 'n':
  215.         if(qualifier == 'l') {
  216.           long *ip = va_arg(args,long*);
  217.           *ip = (str - buf);
  218.         } else {
  219.           int *ip = va_arg(args,int*);
  220.           *ip = (str - buf);
  221.         }
  222.         continue;
  223.       case 'o':
  224.         base = 8;
  225.         break;
  226.       case 'X':
  227.         flags |= LARGE;
  228.       case 'x':
  229.         base = 16;
  230.         break;
  231.       case 'd':
  232.       case 'i':
  233.         flags |= SIGN;
  234.       case 'u':
  235.         break;
  236.       default:
  237.         if(*fmt != '%')
  238.           *str++ = '%';
  239.         if(*fmt && size)
  240.           { *str++ = *fmt; size--; }
  241.         else
  242.           --fmt;
  243.         continue;
  244.       }
  245.       if(qualifier == 'l')
  246.         num = va_arg(args,unsigned long);
  247.       else if(qualifier == 'h') {
  248.         if(flags & SIGN)
  249.           num = va_arg(args,short);
  250.         else
  251.           num = va_arg(args,unsigned short);
  252.       } else if(flags & SIGN)
  253.         num = va_arg(args,int);
  254.       else
  255.         num = va_arg(args, unsigned int);
  256.       str = number(str,num,base,field_width,precision,flags,&size);
  257.   }
  258.   *str = '';
  259.   return str - buf;
  260. }
  261. #ifndef HAVE_SNPRINTF
  262. int snprintf(char *buf, size_t size, const char *fmt, ...)
  263. {
  264.   va_list args;
  265.   int i;
  266.   va_start(args,fmt);
  267.   i = vsnprintf(buf,size,fmt,args);
  268.   va_end(args);
  269.   return i;
  270. }
  271. #endif /* HAVE_SNPRINTF */
  272. #endif  /* HAVE_VSNPRINTF */