home *** CD-ROM | disk | FTP | other *** search
/ Big Green CD 8 / BGCD_8_Dev.iso / NEXTSTEP / UNIX / Networking / wu-ftpd-2.4.2b13-MIHS / support / snprintf.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-03-03  |  11.5 KB  |  367 lines

  1. /*
  2.  * Copyright (c) 1983, 1995, 1996 Eric P. Allman
  3.  * Copyright (c) 1988, 1993
  4.  *    The Regents of the University of California.  All rights reserved.
  5.  *
  6.  * Redistribution and use in source and binary forms, with or without
  7.  * modification, are permitted provided that the following conditions
  8.  * are met:
  9.  * 1. Redistributions of source code must retain the above copyright
  10.  *    notice, this list of conditions and the following disclaimer.
  11.  * 2. Redistributions in binary form must reproduce the above copyright
  12.  *    notice, this list of conditions and the following disclaimer in the
  13.  *    documentation and/or other materials provided with the distribution.
  14.  * 3. All advertising materials mentioning features or use of this software
  15.  *    must display the following acknowledgement:
  16.  *    This product includes software developed by the University of
  17.  *    California, Berkeley and its contributors.
  18.  * 4. Neither the name of the University nor the names of its contributors
  19.  *    may be used to endorse or promote products derived from this software
  20.  *    without specific prior written permission.
  21.  *
  22.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  23.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  24.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  25.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  26.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  27.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  28.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  29.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  31.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  32.  * SUCH DAMAGE.
  33.  */
  34. /* Extracted from sendmail 8.8.5 */
  35. #ifndef lint
  36. static char sccsid[] = "@(#)$Id: snprintf.c,v 1.4 1997/03/03 09:11:11 sob Exp $ excerpted from conf.c 8.333 (Berkeley) 1/21/97";
  37. #endif /* not lint */
  38. #include <stdio.h>
  39. # ifdef __STDC__
  40. #ifndef __P
  41. #define __P(p)  p
  42. #endif
  43. # include <stdarg.h>
  44.  
  45. # define VA_LOCAL_DECL    va_list ap;
  46. # define VA_START(f)    va_start(ap, f)
  47. # define VA_END        va_end(ap)
  48.  
  49. # else
  50.  
  51. #ifndef __P
  52. #define __P(p)  ()
  53. #endif
  54. # include <varargs.h>
  55.  
  56. # define VA_LOCAL_DECL    va_list ap;
  57. # define VA_START(f)    va_start(ap)
  58. # define VA_END        va_end(ap)
  59.  
  60. # endif
  61. /*
  62. **  SNPRINTF, VSNPRINT -- counted versions of printf
  63. **
  64. **    These versions have been grabbed off the net.  They have been
  65. **    cleaned up to compile properly and support for .precision and
  66. **    %lx has been added.
  67. */
  68.  
  69. /**************************************************************
  70.  * Original:
  71.  * Patrick Powell Tue Apr 11 09:48:21 PDT 1995
  72.  * A bombproof version of doprnt (dopr) included.
  73.  * Sigh.  This sort of thing is always nasty do deal with.  Note that
  74.  * the version here does not include floating point...
  75.  *
  76.  * snprintf() is used instead of sprintf() as it does limit checks
  77.  * for string length.  This covers a nasty loophole.
  78.  *
  79.  * The other functions are there to prevent NULL pointers from
  80.  * causing nast effects.
  81.  **************************************************************/
  82.  
  83. /*static char _id[] = "$Id: snprintf.c,v 1.4 1997/03/03 09:11:11 sob Exp $";*/
  84. static void dopr();
  85. static char *end;
  86. #ifndef _SCO_DS
  87. /* VARARGS3 */
  88. int
  89. # ifdef __STDC__
  90. snprintf(char *str, size_t count, const char *fmt, ...)
  91. # else
  92. snprintf(str, count, fmt, va_alist)
  93.     char *str;
  94.     size_t count;
  95.     const char *fmt;
  96.     va_dcl
  97. #endif
  98. {
  99.     int len;
  100.     VA_LOCAL_DECL
  101.  
  102.     VA_START(fmt);
  103.     len = vsnprintf(str, count, fmt, ap);
  104.     VA_END;
  105.     return len;
  106. }
  107. #endif 
  108.  
  109. # ifndef luna2
  110. int
  111. # ifdef __STDC__
  112. vsnprintf(char *str, size_t count, const char *fmt, va_list args)
  113. #else
  114. vsnprintf(str, count, fmt, args)
  115.     char *str;
  116.     int count;
  117.     char *fmt;
  118.     va_list args;
  119. #endif
  120. {
  121.     str[0] = 0;
  122.     end = str + count - 1;
  123.     dopr( str, fmt, args );
  124.     if (count > 0)
  125.         end[0] = 0;
  126.     return strlen(str);
  127. }
  128.  
  129. /*
  130.  * dopr(): poor man's version of doprintf
  131.  */
  132.  
  133. static void fmtstr __P((char *value, int ljust, int len, int zpad, int maxwidth));
  134. static void fmtnum __P((long value, int base, int dosign, int ljust, int len, int zpad));
  135. static void dostr __P(( char * , int ));
  136. static char *output;
  137. static void dopr_outch __P(( int c ));
  138.  
  139. static void
  140. # ifdef __STDC__
  141. dopr(char  * buffer, const char * format, va_list args )
  142. #else
  143. dopr( buffer, format, args )
  144.        char *buffer;
  145.        char *format;
  146.        va_list args;
  147. #endif
  148. {
  149.        int ch;
  150.        long value;
  151.        int longflag  = 0;
  152.        int pointflag = 0;
  153.        int maxwidth  = 0;
  154.        char *strvalue;
  155.        int ljust;
  156.        int len;
  157.        int zpad;
  158.  
  159.        output = buffer;
  160.        while( (ch = *format++) ){
  161.                switch( ch ){
  162.                case '%':
  163.                        ljust = len = zpad = maxwidth = 0;
  164.                        longflag = pointflag = 0;
  165.                nextch:
  166.                        ch = *format++;
  167.                        switch( ch ){
  168.                        case 0:
  169.                                dostr( "**end of format**" , 0);
  170.                                return;
  171.                        case '-': ljust = 1; goto nextch;
  172.                        case '0': /* set zero padding if len not set */
  173.                                if(len==0 && !pointflag) zpad = '0';
  174.                        case '1': case '2': case '3':
  175.                        case '4': case '5': case '6':
  176.                        case '7': case '8': case '9':
  177.                    if (pointflag)
  178.                  maxwidth = maxwidth*10 + ch - '0';
  179.                    else
  180.                  len = len*10 + ch - '0';
  181.                                goto nextch;
  182.                case '*': 
  183.                    if (pointflag)
  184.                  maxwidth = va_arg( args, int );
  185.                    else
  186.                  len = va_arg( args, int );
  187.                    goto nextch;
  188.                case '.': pointflag = 1; goto nextch;
  189.                        case 'l': longflag = 1; goto nextch;
  190.                        case 'u': case 'U':
  191.                                /*fmtnum(value,base,dosign,ljust,len,zpad) */
  192.                                if( longflag ){
  193.                                        value = va_arg( args, long );
  194.                                } else {
  195.                                        value = va_arg( args, int );
  196.                                }
  197.                                fmtnum( value, 10,0, ljust, len, zpad ); break;
  198.                        case 'o': case 'O':
  199.                                /*fmtnum(value,base,dosign,ljust,len,zpad) */
  200.                                if( longflag ){
  201.                                        value = va_arg( args, long );
  202.                                } else {
  203.                                        value = va_arg( args, int );
  204.                                }
  205.                                fmtnum( value, 8,0, ljust, len, zpad ); break;
  206.                        case 'd': case 'D':
  207.                                if( longflag ){
  208.                                        value = va_arg( args, long );
  209.                                } else {
  210.                                        value = va_arg( args, int );
  211.                                }
  212.                                fmtnum( value, 10,1, ljust, len, zpad ); break;
  213.                        case 'x':
  214.                                if( longflag ){
  215.                                        value = va_arg( args, long );
  216.                                } else {
  217.                                        value = va_arg( args, int );
  218.                                }
  219.                                fmtnum( value, 16,0, ljust, len, zpad ); break;
  220.                        case 'X':
  221.                                if( longflag ){
  222.                                        value = va_arg( args, long );
  223.                                } else {
  224.                                        value = va_arg( args, int );
  225.                                }
  226.                                fmtnum( value,-16,0, ljust, len, zpad ); break;
  227.                        case 's':
  228.                                strvalue = va_arg( args, char *);
  229.                    if (maxwidth > 0 || !pointflag) {
  230.                  if (pointflag && len > maxwidth)
  231.                    len = maxwidth; /* Adjust padding */
  232.                  fmtstr( strvalue,ljust,len,zpad, maxwidth);
  233.                    }
  234.                    break;
  235.                        case 'c':
  236.                                ch = va_arg( args, int );
  237.                                dopr_outch( ch ); break;
  238.                        case '%': dopr_outch( ch ); continue;
  239.                        default:
  240.                                dostr(  "???????" , 0);
  241.                        }
  242.                        break;
  243.                default:
  244.                        dopr_outch( ch );
  245.                        break;
  246.                }
  247.        }
  248.        *output = 0;
  249. }
  250.  
  251. static void
  252. fmtstr(  value, ljust, len, zpad, maxwidth )
  253.        char *value;
  254.        int ljust, len, zpad, maxwidth;
  255. {
  256.        int padlen, strlen;     /* amount to pad */
  257.  
  258.        if( value == 0 ){
  259.                value = "<NULL>";
  260.        }
  261.        for( strlen = 0; value[strlen]; ++ strlen ); /* strlen */
  262.        if (strlen > maxwidth && maxwidth)
  263.      strlen = maxwidth;
  264.        padlen = len - strlen;
  265.        if( padlen < 0 ) padlen = 0;
  266.        if( ljust ) padlen = -padlen;
  267.        while( padlen > 0 ) {
  268.                dopr_outch( ' ' );
  269.                --padlen;
  270.        }
  271.        dostr( value, maxwidth );
  272.        while( padlen < 0 ) {
  273.                dopr_outch( ' ' );
  274.                ++padlen;
  275.        }
  276. }
  277.  
  278. static void
  279. fmtnum(  value, base, dosign, ljust, len, zpad )
  280.        long value;
  281.        int base, dosign, ljust, len, zpad;
  282. {
  283.        int signvalue = 0;
  284.        unsigned long uvalue;
  285.        char convert[20];
  286.        int place = 0;
  287.        int padlen = 0; /* amount to pad */
  288.        int caps = 0;
  289.  
  290.        /* DEBUGP(("value 0x%x, base %d, dosign %d, ljust %d, len %d, zpad %d\n",
  291.                value, base, dosign, ljust, len, zpad )); */
  292.        uvalue = value;
  293.        if( dosign ){
  294.                if( value < 0 ) {
  295.                        signvalue = '-';
  296.                        uvalue = -value;
  297.                }
  298.        }
  299.        if( base < 0 ){
  300.                caps = 1;
  301.                base = -base;
  302.        }
  303.        do{
  304.                convert[place++] =
  305.                        (caps? "0123456789ABCDEF":"0123456789abcdef")
  306.                         [uvalue % (unsigned)base  ];
  307.                uvalue = (uvalue / (unsigned)base );
  308.        }while(uvalue);
  309.        convert[place] = 0;
  310.        padlen = len - place;
  311.        if( padlen < 0 ) padlen = 0;
  312.        if( ljust ) padlen = -padlen;
  313.        /* DEBUGP(( "str '%s', place %d, sign %c, padlen %d\n",
  314.                convert,place,signvalue,padlen)); */
  315.        if( zpad && padlen > 0 ){
  316.                if( signvalue ){
  317.                        dopr_outch( signvalue );
  318.                        --padlen;
  319.                        signvalue = 0;
  320.                }
  321.                while( padlen > 0 ){
  322.                        dopr_outch( zpad );
  323.                        --padlen;
  324.                }
  325.        }
  326.        while( padlen > 0 ) {
  327.                dopr_outch( ' ' );
  328.                --padlen;
  329.        }
  330.        if( signvalue ) dopr_outch( signvalue );
  331.        while( place > 0 ) dopr_outch( convert[--place] );
  332.        while( padlen < 0 ){
  333.                dopr_outch( ' ' );
  334.                ++padlen;
  335.        }
  336. }
  337.  
  338. static void
  339. dostr( str , cut)
  340.      char *str;
  341.      int cut;
  342. {
  343.   if (cut) {
  344.     while(*str && cut-- > 0) dopr_outch(*str++);
  345.   } else {
  346.     while(*str) dopr_outch(*str++);
  347.   }
  348. }
  349.  
  350. static void
  351. dopr_outch( c )
  352.        int c;
  353. {
  354. #if 0
  355.        if( iscntrl(c) && c != '\n' && c != '\t' ){
  356.                c = '@' + (c & 0x1F);
  357.                if( end == 0 || output < end )
  358.                        *output++ = '^';
  359.        }
  360. #endif
  361.        if( end == 0 || output < end )
  362.                *output++ = c;
  363. }
  364.  
  365. # endif /* !luna2 */
  366.  
  367.