snprintf.c
上传用户:zibowangxu
上传日期:2007-01-04
资源大小:331k
文件大小:8k
源码类别:

Ftp客户端

开发平台:

Unix_Linux

  1. /****************************************************************************  
  2.  
  3.   Copyright (c) 1999 WU-FTPD Development Group.  
  4.   All rights reserved.
  5.   
  6.   Portions Copyright (c) 1980, 1985, 1988, 1989, 1990, 1991, 1993, 1994
  7.     The Regents of the University of California.
  8.   Portions Copyright (c) 1993, 1994 Washington University in Saint Louis.
  9.   Portions Copyright (c) 1996, 1998 Berkeley Software Design, Inc.
  10.   Portions Copyright (c) 1989 Massachusetts Institute of Technology.
  11.   Portions Copyright (c) 1998 Sendmail, Inc.
  12.   Portions Copyright (c) 1983, 1995, 1996, 1997 Eric P.  Allman.
  13.   Portions Copyright (c) 1997 by Stan Barber.
  14.   Portions Copyright (c) 1997 by Kent Landfield.
  15.   Portions Copyright (c) 1991, 1992, 1993, 1994, 1995, 1996, 1997
  16.     Free Software Foundation, Inc.  
  17.  
  18.   Use and distribution of this software and its source code are governed 
  19.   by the terms and conditions of the WU-FTPD Software License ("LICENSE").
  20.  
  21.   If you did not receive a copy of the license, it may be obtained online
  22.   at http://www.wu-ftpd.org/license.html.
  23.  
  24.   $Id: snprintf.c,v 1.7 1999/09/10 04:16:31 wuftpd Exp $
  25.  
  26. ****************************************************************************/
  27. #include <stdio.h>
  28. #include <stdlib.h>
  29. #include <string.h>
  30. #ifndef __P
  31. #define __P(p)  p
  32. #endif
  33. #include <stdarg.h>
  34. #define VA_LOCAL_DECL va_list ap;
  35. #define VA_START(f) va_start(ap, f)
  36. #define VA_END va_end(ap)
  37. #ifdef SOLARIS2
  38. #ifdef _FILE_OFFSET_BITS
  39. #define SOLARIS26
  40. #endif
  41. #endif
  42. #ifdef SOLARIS26
  43. #define HAS_SNPRINTF
  44. #define HAS_VSNPRINTF
  45. #endif
  46. #ifdef _SCO_DS_
  47. #define HAS_SNPRINTF
  48. #endif
  49. #ifdef luna2
  50. #define HAS_VSNPRINTF
  51. #endif
  52. /*
  53.    **  SNPRINTF, VSNPRINT -- counted versions of printf
  54.    **
  55.    **   These versions have been grabbed off the net.  They have been
  56.    **   cleaned up to compile properly and support for .precision and
  57.    **   %lx has been added.
  58.  */
  59. /**************************************************************
  60.  * Original:
  61.  * Patrick Powell Tue Apr 11 09:48:21 PDT 1995
  62.  * A bombproof version of doprnt (dopr) included.
  63.  * Sigh.  This sort of thing is always nasty do deal with.  Note that
  64.  * the version here does not include floating point...
  65.  *
  66.  * snprintf() is used instead of sprintf() as it does limit checks
  67.  * for string length.  This covers a nasty loophole.
  68.  *
  69.  * The other functions are there to prevent NULL pointers from
  70.  * causing nast effects.
  71.  **************************************************************/
  72. /*static char _id[] = "$Id: snprintf.c,v 1.7 1999/09/10 04:16:31 wuftpd Exp $"; */
  73. static void dopr(char *, const char *, va_list);
  74. static char *end;
  75. #ifndef HAS_VSNPRINTF
  76. int vsnprintf(char *str, size_t count, const char *fmt, va_list args)
  77. {
  78.     str[0] = 0;
  79.     end = str + count - 1;
  80.     dopr(str, fmt, args);
  81.     if (count > 0)
  82. end[0] = 0;
  83.     return strlen(str);
  84. }
  85. #ifndef HAS_SNPRINTF
  86. /* VARARGS3 */
  87. int snprintf(char *str, size_t count, const char *fmt,...)
  88. {
  89.     int len;
  90.     VA_LOCAL_DECL
  91. VA_START(fmt);
  92.     len = vsnprintf(str, count, fmt, ap);
  93.     VA_END;
  94.     return len;
  95. }
  96. #endif
  97. /*
  98.  * dopr(): poor man's version of doprintf
  99.  */
  100. static void fmtstr __P((char *value, int ljust, int len, int zpad, int maxwidth));
  101. static void fmtnum __P((long value, int base, int dosign, int ljust, int len, int zpad));
  102. static void dostr __P((char *, int));
  103. static char *output;
  104. static void dopr_outch __P((int c));
  105. static void dopr(char *buffer, const char *format, va_list args)
  106. {
  107.     int ch;
  108.     long value;
  109.     int longflag = 0;
  110.     int pointflag = 0;
  111.     int maxwidth = 0;
  112.     char *strvalue;
  113.     int ljust;
  114.     int len;
  115.     int zpad;
  116.     output = buffer;
  117.     while ((ch = *format++)) {
  118. switch (ch) {
  119. case '%':
  120.     ljust = len = zpad = maxwidth = 0;
  121.     longflag = pointflag = 0;
  122.   nextch:
  123.     ch = *format++;
  124.     switch (ch) {
  125.     case 0:
  126. dostr("**end of format**", 0);
  127. return;
  128.     case '-':
  129. ljust = 1;
  130. goto nextch;
  131.     case '0': /* set zero padding if len not set */
  132. if (len == 0 && !pointflag)
  133.     zpad = '0';
  134.     case '1':
  135.     case '2':
  136.     case '3':
  137.     case '4':
  138.     case '5':
  139.     case '6':
  140.     case '7':
  141.     case '8':
  142.     case '9':
  143. if (pointflag)
  144.     maxwidth = maxwidth * 10 + ch - '0';
  145. else
  146.     len = len * 10 + ch - '0';
  147. goto nextch;
  148.     case '*':
  149. if (pointflag)
  150.     maxwidth = va_arg(args, int);
  151. else
  152.     len = va_arg(args, int);
  153. goto nextch;
  154.     case '.':
  155. pointflag = 1;
  156. goto nextch;
  157.     case 'l':
  158. longflag = 1;
  159. goto nextch;
  160.     case 'u':
  161.     case 'U':
  162. /*fmtnum(value,base,dosign,ljust,len,zpad) */
  163. if (longflag) {
  164.     value = va_arg(args, long);
  165. }
  166. else {
  167.     value = va_arg(args, int);
  168. }
  169. fmtnum(value, 10, 0, ljust, len, zpad);
  170. break;
  171.     case 'o':
  172.     case 'O':
  173. /*fmtnum(value,base,dosign,ljust,len,zpad) */
  174. if (longflag) {
  175.     value = va_arg(args, long);
  176. }
  177. else {
  178.     value = va_arg(args, int);
  179. }
  180. fmtnum(value, 8, 0, ljust, len, zpad);
  181. break;
  182.     case 'd':
  183.     case 'D':
  184. if (longflag) {
  185.     value = va_arg(args, long);
  186. }
  187. else {
  188.     value = va_arg(args, int);
  189. }
  190. fmtnum(value, 10, 1, ljust, len, zpad);
  191. break;
  192.     case 'x':
  193. if (longflag) {
  194.     value = va_arg(args, long);
  195. }
  196. else {
  197.     value = va_arg(args, int);
  198. }
  199. fmtnum(value, 16, 0, ljust, len, zpad);
  200. break;
  201.     case 'X':
  202. if (longflag) {
  203.     value = va_arg(args, long);
  204. }
  205. else {
  206.     value = va_arg(args, int);
  207. }
  208. fmtnum(value, -16, 0, ljust, len, zpad);
  209. break;
  210.     case 's':
  211. strvalue = va_arg(args, char *);
  212. if (maxwidth > 0 || !pointflag) {
  213.     if (pointflag && len > maxwidth)
  214. len = maxwidth; /* Adjust padding */
  215.     fmtstr(strvalue, ljust, len, zpad, maxwidth);
  216. }
  217. break;
  218.     case 'c':
  219. ch = va_arg(args, int);
  220. dopr_outch(ch);
  221. break;
  222.     case '%':
  223. dopr_outch(ch);
  224. continue;
  225.     default:
  226. dostr("???????", 0);
  227.     }
  228.     break;
  229. default:
  230.     dopr_outch(ch);
  231.     break;
  232. }
  233.     }
  234.     *output = 0;
  235. }
  236. static void fmtstr(char *value, int ljust, int len, int zpad, int maxwidth)
  237. {
  238.     int padlen, strlen; /* amount to pad */
  239.     if (value == 0) {
  240. value = "<NULL>";
  241.     }
  242.     for (strlen = 0; value[strlen]; ++strlen); /* strlen */
  243.     if (strlen > maxwidth && maxwidth)
  244. strlen = maxwidth;
  245.     padlen = len - strlen;
  246.     if (padlen < 0)
  247. padlen = 0;
  248.     if (ljust)
  249. padlen = -padlen;
  250.     while (padlen > 0) {
  251. dopr_outch(' ');
  252. --padlen;
  253.     }
  254.     dostr(value, maxwidth);
  255.     while (padlen < 0) {
  256. dopr_outch(' ');
  257. ++padlen;
  258.     }
  259. }
  260. static void fmtnum(long value, int base, int dosign, int ljust, int len, int zpad)
  261. {
  262.     int signvalue = 0;
  263.     unsigned long uvalue;
  264.     char convert[20];
  265.     int place = 0;
  266.     int padlen = 0; /* amount to pad */
  267.     int caps = 0;
  268.     /* DEBUGP(("value 0x%x, base %d, dosign %d, ljust %d, len %d, zpad %dn",
  269.        value, base, dosign, ljust, len, zpad )); */
  270.     uvalue = value;
  271.     if (dosign) {
  272. if (value < 0) {
  273.     signvalue = '-';
  274.     uvalue = -value;
  275. }
  276.     }
  277.     if (base < 0) {
  278. caps = 1;
  279. base = -base;
  280.     }
  281.     do {
  282. convert[place++] =
  283.     (caps ? "0123456789ABCDEF" : "0123456789abcdef")
  284.     [uvalue % (unsigned) base];
  285. uvalue = (uvalue / (unsigned) base);
  286.     } while (uvalue);
  287.     convert[place] = 0;
  288.     padlen = len - place;
  289.     if (padlen < 0)
  290. padlen = 0;
  291.     if (ljust)
  292. padlen = -padlen;
  293.     /* DEBUGP(( "str '%s', place %d, sign %c, padlen %dn",
  294.        convert,place,signvalue,padlen)); */
  295.     if (zpad && padlen > 0) {
  296. if (signvalue) {
  297.     dopr_outch(signvalue);
  298.     --padlen;
  299.     signvalue = 0;
  300. }
  301. while (padlen > 0) {
  302.     dopr_outch(zpad);
  303.     --padlen;
  304. }
  305.     }
  306.     while (padlen > 0) {
  307. dopr_outch(' ');
  308. --padlen;
  309.     }
  310.     if (signvalue)
  311. dopr_outch(signvalue);
  312.     while (place > 0)
  313. dopr_outch(convert[--place]);
  314.     while (padlen < 0) {
  315. dopr_outch(' ');
  316. ++padlen;
  317.     }
  318. }
  319. static void dostr(char *str, int cut)
  320. {
  321.     if (cut) {
  322. while (*str && cut-- > 0)
  323.     dopr_outch(*str++);
  324.     }
  325.     else {
  326. while (*str)
  327.     dopr_outch(*str++);
  328.     }
  329. }
  330. static void dopr_outch(int c)
  331. {
  332. #if 0
  333.     if (iscntrl(c) && c != 'n' && c != 't') {
  334. c = '@' + (c & 0x1F);
  335. if (end == 0 || output < end)
  336.     *output++ = '^';
  337.     }
  338. #endif
  339.     if (end == 0 || output < end)
  340. *output++ = c;
  341. }
  342. #endif