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
    * <[EMAIL PROTECTED]> 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;
   }
  -
  
  
  

Reply via email to