You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by ji...@hyperreal.org on 1999/12/13 14:36:18 UTC

cvs commit: apache-2.0/src/lib/apr/lib apr_snprintf.c

jim         99/12/13 05:36:17

  Modified:    src/lib/apr/lib apr_snprintf.c
  Log:
  Fold in the snprintf() changes
  
  Revision  Changes    Path
  1.5       +202 -44   apache-2.0/src/lib/apr/lib/apr_snprintf.c
  
  Index: apr_snprintf.c
  ===================================================================
  RCS file: /export/home/cvs/apache-2.0/src/lib/apr/lib/apr_snprintf.c,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- apr_snprintf.c	1999/12/09 21:00:44	1.4
  +++ apr_snprintf.c	1999/12/13 13:36:16	1.5
  @@ -54,7 +54,7 @@
    * project, please see <http://www.apache.org/>.
    *
    * This code is based on, and used with the permission of, the
  - * SIO stdiocntxteplacement strx_* functions by Panos Tsirigotis
  + * SIO stdio-replacement strx_* functions by Panos Tsirigotis
    * <pa...@alumni.cs.colorado.edu> for xinetd.
    */
   
  @@ -90,12 +90,22 @@
   #ifndef TRUE
   #define TRUE			1
   #endif
  +#ifndef AP_LONGEST_LONG
  +#define AP_LONGEST_LONG		long
  +#endif
   #define NUL			'\0'
  -#define INT_NULL		((int *)0)
   #define WIDE_INT		long
  +#define WIDEST_INT		AP_LONGEST_LONG
   
   typedef WIDE_INT wide_int;
   typedef unsigned WIDE_INT u_wide_int;
  +typedef WIDEST_INT widest_int;
  +#ifdef __TANDEM
  +/* Although Tandem supports "long long" there is no unsigned variant. */
  +typedef unsigned long       u_widest_int;
  +#else
  +typedef unsigned WIDEST_INT u_widest_int;
  +#endif
   typedef int bool_int;
   
   #define S_NULL			"(null)"
  @@ -131,7 +141,7 @@
       register int r2;
       double fi, fj;
       register char *p, *p1;
  -
  +    
       if (ndigits >= NDIG - 1)
   	ndigits = NDIG - 2;
       r2 = 0;
  @@ -350,6 +360,10 @@
    * The caller provides a buffer for the string: that is the buf_end argument
    * which is a pointer to the END of the buffer + 1 (i.e. if the buffer
    * is declared as buf[ 100 ], buf_end should be &buf[ 100 ])
  + *
  + * Note: we have 2 versions. One is used when we need to use quads
  + * (conv_10_quad), the other when we don't (conv_10). We're assuming the
  + * latter is faster.
    */
   static char *conv_10(register wide_int num, register bool_int is_unsigned,
   		     register bool_int *is_negative, char *buf_end,
  @@ -398,6 +412,62 @@
       return (p);
   }
   
  +static char *conv_10_quad(widest_int num, register bool_int is_unsigned,
  +		     register bool_int *is_negative, char *buf_end,
  +		     register int *len)
  +{
  +    register char *p = buf_end;
  +    u_widest_int magnitude;
  +
  +    /*
  +     * We see if we can use the faster non-quad version by checking the
  +     * number against the largest long value it can be. If <=, we
  +     * punt to the quicker version.
  +     */
  +    if ((num <= ULONG_MAX && is_unsigned) || (num <= LONG_MAX && !is_unsigned))
  +    	return(conv_10( (wide_int)num, is_unsigned, is_negative,
  +	       buf_end, len));
  +
  +    if (is_unsigned) {
  +	magnitude = (u_widest_int) num;
  +	*is_negative = FALSE;
  +    }
  +    else {
  +	*is_negative = (num < 0);
  +
  +	/*
  +	 * On a 2's complement machine, negating the most negative integer 
  +	 * results in a number that cannot be represented as a signed integer.
  +	 * Here is what we do to obtain the number's magnitude:
  +	 *      a. add 1 to the number
  +	 *      b. negate it (becomes positive)
  +	 *      c. convert it to unsigned
  +	 *      d. add 1
  +	 */
  +	if (*is_negative) {
  +	    widest_int t = num + 1;
  +
  +	    magnitude = ((u_widest_int) -t) + 1;
  +	}
  +	else
  +	    magnitude = (u_widest_int) num;
  +    }
  +
  +    /*
  +     * We use a do-while loop so that we write at least 1 digit 
  +     */
  +    do {
  +	u_widest_int new_magnitude = magnitude / 10;
  +
  +	*--p = (char) (magnitude - new_magnitude * 10 + '0');
  +	magnitude = new_magnitude;
  +    }
  +    while (magnitude);
  +
  +    *len = buf_end - p;
  +    return (p);
  +}
  +
   
   
   static char *conv_in_addr(struct in_addr *ia, char *buf_end, int *len)
  @@ -537,6 +607,9 @@
    * The caller provides a buffer for the string: that is the buf_end argument
    * which is a pointer to the END of the buffer + 1 (i.e. if the buffer
    * is declared as buf[ 100 ], buf_end should be &buf[ 100 ])
  + *
  + * As with conv_10, we have a faster version which is used when
  + * the number isn't quad size.
    */
   static char *conv_p2(register u_wide_int num, register int nbits,
   		     char format, char *buf_end, register int *len)
  @@ -557,12 +630,34 @@
       return (p);
   }
   
  +static char *conv_p2_quad(u_widest_int num, register int nbits,
  +		     char format, char *buf_end, register int *len)
  +{
  +    register int mask = (1 << nbits) - 1;
  +    register char *p = buf_end;
  +    static const char low_digits[] = "0123456789abcdef";
  +    static const char upper_digits[] = "0123456789ABCDEF";
  +    register const char *digits = (format == 'X') ? upper_digits : low_digits;
  +
  +    if (num <= ULONG_MAX)
  +    	return(conv_p2( (u_wide_int)num, nbits, format, buf_end, len));
  +
  +    do {
  +	*--p = digits[num & mask];
  +	num >>= nbits;
  +    }
  +    while (num);
  +
  +    *len = buf_end - p;
  +    return (p);
  +}
  +
   
   /*
    * Do format conversion placing the output in buffer
    */
  -API_EXPORT(int) ap_vformatter(int (*flush_func)(ap_vformatter_buff_t *),
  -    ap_vformatter_buff_t *vbuff, const char *fmt, va_list ap)
  +API_EXPORT(int) ap_vformatter(int (*flush_func)(ap_vformatter_buff *),
  +    ap_vformatter_buff *vbuff, const char *fmt, va_list ap)
   {
       register char *sp;
       register char *bep;
  @@ -582,16 +677,22 @@
       char prefix_char;
   
       double fp_num;
  +    widest_int i_quad = (widest_int) 0;
  +    u_widest_int ui_quad;
       wide_int i_num = (wide_int) 0;
       u_wide_int ui_num;
   
       char num_buf[NUM_BUF_SIZE];
       char char_buf[2];		/* for printing %% and %<unknown> */
   
  +    enum var_type_enum {
  +    	IS_QUAD, IS_LONG, IS_SHORT, IS_INT
  +    };
  +    enum var_type_enum var_type = IS_INT;
  +
       /*
        * Flag variables
        */
  -    boolean_e is_long;
       boolean_e alternate_form;
       boolean_e print_sign;
       boolean_e print_blank;
  @@ -689,14 +790,20 @@
   	    /*
   	     * Modifier check
   	     */
  -	    if (*fmt == 'l') {
  -		is_long = YES;
  +	    if (*fmt == 'q') {
  +		var_type = IS_QUAD;
   		fmt++;
   	    }
  +	    else if (*fmt == 'l') {
  +		var_type = IS_LONG;
  +		fmt++;
  +	    }
  +	    else if (*fmt == 'h') {
  +		var_type = IS_SHORT;
  +		fmt++;
  +	    }
   	    else {
  -		if (*fmt == 'h')  /* "short" backward compatibility */
  -		    ++fmt;
  -		is_long = NO;
  +		var_type = IS_INT;
   	    }
   
   	    /*
  @@ -712,23 +819,41 @@
   	     */
   	    switch (*fmt) {
   	    case 'u':
  -		if (is_long)
  -		    i_num = va_arg(ap, u_wide_int);
  -		else
  -		    i_num = (wide_int) va_arg(ap, unsigned int);
  -		s = conv_10(i_num, 1, &is_negative,
  +	    	if (var_type == IS_QUAD) {
  +		    i_quad = va_arg(ap, u_widest_int);
  +		    s = conv_10_quad(i_quad, 1, &is_negative,
  +			    &num_buf[NUM_BUF_SIZE], &s_len);
  +		}
  +		else {
  +		    if (var_type == IS_LONG)
  +			i_num = (wide_int) va_arg(ap, u_wide_int);
  +		    else if (var_type == IS_SHORT)
  +			i_num = (wide_int) (unsigned short) va_arg(ap, unsigned int);
  +		    else
  +			i_num = (wide_int) va_arg(ap, unsigned int);
  +		    s = conv_10(i_num, 1, &is_negative,
   			    &num_buf[NUM_BUF_SIZE], &s_len);
  +		}
   		FIX_PRECISION(adjust_precision, precision, s, s_len);
   		break;
   
   	    case 'd':
   	    case 'i':
  -		if (is_long)
  -		    i_num = va_arg(ap, wide_int);
  -		else
  -		    i_num = (wide_int) va_arg(ap, int);
  -		s = conv_10(i_num, 0, &is_negative,
  +	    	if (var_type == IS_QUAD) {
  +		    i_quad = va_arg(ap, widest_int);
  +		    s = conv_10_quad(i_quad, 0, &is_negative,
   			    &num_buf[NUM_BUF_SIZE], &s_len);
  +		}
  +		else {
  +		    if (var_type == IS_LONG)
  +			i_num = (wide_int) va_arg(ap, wide_int);
  +		    else if (var_type == IS_SHORT)
  +			i_num = (wide_int) (short) va_arg(ap, int);
  +		    else
  +			i_num = (wide_int) va_arg(ap, int);
  +		    s = conv_10(i_num, 0, &is_negative,
  +			    &num_buf[NUM_BUF_SIZE], &s_len);
  +		}
   		FIX_PRECISION(adjust_precision, precision, s, s_len);
   
   		if (is_negative)
  @@ -741,12 +866,21 @@
   
   
   	    case 'o':
  -		if (is_long)
  -		    ui_num = va_arg(ap, u_wide_int);
  -		else
  -		    ui_num = (u_wide_int) va_arg(ap, unsigned int);
  -		s = conv_p2(ui_num, 3, *fmt,
  +		if (var_type == IS_QUAD) {
  +		    ui_quad = va_arg(ap, u_widest_int);
  +		    s = conv_p2_quad(ui_quad, 3, *fmt,
  +			    &num_buf[NUM_BUF_SIZE], &s_len);
  +		}
  +		else {
  +		    if (var_type == IS_LONG)
  +			ui_num = (u_wide_int) va_arg(ap, u_wide_int);
  +		    else if (var_type == IS_SHORT)
  +			ui_num = (u_wide_int) (unsigned short) va_arg(ap, unsigned int);
  +		    else
  +			ui_num = (u_wide_int) va_arg(ap, unsigned int);
  +		    s = conv_p2(ui_num, 3, *fmt,
   			    &num_buf[NUM_BUF_SIZE], &s_len);
  +		}
   		FIX_PRECISION(adjust_precision, precision, s, s_len);
   		if (alternate_form && *s != '0') {
   		    *--s = '0';
  @@ -757,12 +891,21 @@
   
   	    case 'x':
   	    case 'X':
  -		if (is_long)
  -		    ui_num = (u_wide_int) va_arg(ap, u_wide_int);
  -		else
  -		    ui_num = (u_wide_int) va_arg(ap, unsigned int);
  -		s = conv_p2(ui_num, 4, *fmt,
  +		if (var_type == IS_QUAD) {
  +		    ui_quad = va_arg(ap, u_widest_int);
  +		    s = conv_p2_quad(ui_quad, 4, *fmt,
   			    &num_buf[NUM_BUF_SIZE], &s_len);
  +		}
  +		else {
  +		    if (var_type == IS_LONG)
  +			ui_num = (u_wide_int) va_arg(ap, u_wide_int);
  +		    else if (var_type == IS_SHORT)
  +			ui_num = (u_wide_int) (unsigned short) va_arg(ap, unsigned int);
  +		    else
  +			ui_num = (u_wide_int) va_arg(ap, unsigned int);
  +		    s = conv_p2(ui_num, 4, *fmt,
  +			    &num_buf[NUM_BUF_SIZE], &s_len);
  +		}
   		FIX_PRECISION(adjust_precision, precision, s, s_len);
   		if (alternate_form && i_num != 0) {
   		    *--s = *fmt;	/* 'x' or 'X' */
  @@ -852,7 +995,14 @@
   
   
   	    case 'n':
  -		*(va_arg(ap, int *)) = cc;
  +	    	if (var_type == IS_QUAD)
  +		    *(va_arg(ap, widest_int *)) = cc;
  +		else if (var_type == IS_LONG)
  +		    *(va_arg(ap, long *)) = cc;
  +		else if (var_type == IS_SHORT)
  +		    *(va_arg(ap, short *)) = cc;
  +		else
  +		    *(va_arg(ap, int *)) = cc;
   		break;
   
   		/*
  @@ -862,16 +1012,25 @@
   	    case 'p':
   		switch(*++fmt) {
   		    /*
  -		     * If the pointer size is equal to the size of an unsigned
  -		     * integer we convert the pointer to a hex number, otherwise 
  -		     * we print "%p" to indicate that we don't handle "%p".
  +		     * If the pointer size is equal to or smaller than the size
  +		     * of the largest unsigned int, we convert the pointer to a
  +		     * hex number, otherwise we print "%p" to indicate that we
  +		     * don't handle "%p".
   		     */
   		case 'p':
  -		    ui_num = (u_wide_int) va_arg(ap, void *);
  -
  -		    if (sizeof(char *) <= sizeof(u_wide_int))
  -				s = conv_p2(ui_num, 4, 'x',
  -					    &num_buf[NUM_BUF_SIZE], &s_len);
  +#ifdef AP_VOID_P_IS_QUAD
  +		    if (sizeof(void *) <= sizeof(u_widest_int)) {
  +		    	ui_quad = (u_widest_int) va_arg(ap, void *);
  +			s = conv_p2_quad(ui_quad, 4, 'x',
  +				&num_buf[NUM_BUF_SIZE], &s_len);
  +		    }
  +#else
  +		    if (sizeof(void *) <= sizeof(u_wide_int)) {
  +		    	ui_num = (u_wide_int) va_arg(ap, void *);
  +			s = conv_p2(ui_num, 4, 'x',
  +				&num_buf[NUM_BUF_SIZE], &s_len);
  +		    }
  +#endif
   		    else {
   			s = "%p";
   			s_len = 2;
  @@ -990,7 +1149,7 @@
   }
   
   
  -static int snprintf_flush(ap_vformatter_buff_t *vbuff)
  +static int snprintf_flush(ap_vformatter_buff *vbuff)
   {
       /* if the buffer fills we have to abort immediately, there is no way
        * to "flush" an ap_snprintf... there's nowhere to flush it to.
  @@ -1003,7 +1162,7 @@
   {
       int cc;
       va_list ap;
  -    ap_vformatter_buff_t vbuff;
  +    ap_vformatter_buff vbuff;
   
       if (len == 0)
   	return 0;
  @@ -1023,7 +1182,7 @@
   			     va_list ap)
   {
       int cc;
  -    ap_vformatter_buff_t vbuff;
  +    ap_vformatter_buff vbuff;
   
       if (len == 0)
   	return 0;
  @@ -1035,4 +1194,3 @@
       *vbuff.curpos = '\0';
       return (cc == -1) ? len : cc;
   }
  -