head 1.32; access; symbols STR_0_9_12:1.31 LMTP2NNTP_1_4_1:1.31 LMTP2NNTP_1_4_0:1.31 STR_0_9_11:1.31 STR_0_9_10:1.30 LMTP2NNTP_1_3_0:1.29 LMTP2NNTP_1_3b2:1.29 LMTP2NNTP_1_3b1:1.29 LMTP2NNTP_1_3a3:1.29 LMTP2NNTP_1_3a2:1.29 STR_0_9_9:1.29 LMTP2NNTP_1_3a1:1.28 STR_0_9_8:1.28 LMTP2NNTP_1_2_0:1.28 LMTP2NNTP_1_2b4:1.28 LMTP2NNTP_1_2b3:1.28 LMTP2NNTP_1_2b2:1.28 LMTP2NNTP_1_2b1:1.28 LMTP2NNTP_1_2a8:1.28 LMTP2NNTP_1_2a7:1.28 LMTP2NNTP_1_2a6:1.27 LMTP2NNTP_1_2a5:1.27 STR_0_9_7:1.27 LMTP2NNTP_1_2a4:1.26 LMTP2NNTP_1_2a3:1.26 OSSP_RC_SPEC:1.26 LMTP2NNTP_1_2a1:1.25 LMTP2NNTP_1_1_1:1.25 LMTP2NNTP_1_1_0:1.25 LMTP2NNTP_1_1b4:1.25 LMTP2NNTP_1_1b3:1.25 LMTP2NNTP_1_1b2:1.25 LMTP2NNTP_1_1b1:1.25 STR_0_9_6:1.25 STR_0_9_5:1.25 STR_0_9_4:1.20 STR_0_9_3:1.19 STR_0_9_2:1.19 STR_0_9_1:1.17 STR_0_9_0:1.17 str_init:1.1.1.1 str:1.1.1; locks; strict; comment @ * @; 1.32 date 2008.06.06.12.29.20; author rse; state Exp; branches; next 1.31; commitid 6YESR3F7oQNIYS5t; 1.31 date 2005.10.03.07.34.43; author rse; state Exp; branches; next 1.30; 1.30 date 2005.01.24.15.22.19; author rse; state Exp; branches; next 1.29; 1.29 date 2004.04.23.10.03.09; author thl; state Exp; branches; next 1.28; 1.28 date 2003.01.06.19.13.47; author rse; state Exp; branches; next 1.27; 1.27 date 2002.04.01.08.32.54; author rse; state Exp; branches; next 1.26; 1.26 date 2002.01.02.17.09.13; author rse; state Exp; branches; next 1.25; 1.25 date 2001.08.16.13.21.22; author rse; state Exp; branches; next 1.24; 1.24 date 2001.04.28.08.18.51; author rse; state Exp; branches; next 1.23; 1.23 date 2001.04.27.12.24.52; author rse; state Exp; branches; next 1.22; 1.22 date 2001.04.27.12.22.21; author rse; state Exp; branches; next 1.21; 1.21 date 2001.04.27.12.12.28; author rse; state Exp; branches; next 1.20; 1.20 date 2000.03.01.07.51.30; author rse; state Exp; branches; next 1.19; 1.19 date 2000.01.20.20.42.11; author rse; state Exp; branches; next 1.18; 1.18 date 2000.01.10.11.55.58; author rse; state Exp; branches; next 1.17; 1.17 date 2000.01.01.13.05.17; author rse; state Exp; branches; next 1.16; 1.16 date 99.12.27.18.40.58; author rse; state Exp; branches; next 1.15; 1.15 date 99.12.27.15.53.31; author rse; state Exp; branches; next 1.14; 1.14 date 99.12.27.13.47.07; author rse; state Exp; branches; next 1.13; 1.13 date 99.12.26.15.37.34; author rse; state Exp; branches; next 1.12; 1.12 date 99.12.25.18.23.02; author rse; state Exp; branches; next 1.11; 1.11 date 99.11.26.17.10.04; author rse; state Exp; branches; next 1.10; 1.10 date 99.11.26.17.08.35; author rse; state Exp; branches; next 1.9; 1.9 date 99.11.26.16.57.39; author rse; state Exp; branches; next 1.8; 1.8 date 99.11.23.15.39.31; author rse; state Exp; branches; next 1.7; 1.7 date 99.11.23.15.32.16; author rse; state Exp; branches; next 1.6; 1.6 date 99.11.23.15.04.43; author rse; state Exp; branches; next 1.5; 1.5 date 99.11.23.14.41.58; author rse; state Exp; branches; next 1.4; 1.4 date 99.11.23.14.27.35; author rse; state Exp; branches; next 1.3; 1.3 date 99.11.23.13.54.22; author rse; state Exp; branches; next 1.2; 1.2 date 99.11.22.18.02.51; author rse; state Exp; branches; next 1.1; 1.1 date 99.11.22.17.29.12; author rse; state Exp; branches 1.1.1.1; next ; 1.1.1.1 date 99.11.22.17.29.12; author rse; state Exp; branches; next ; desc @@ 1.32 log @use a static value for comparing against the null string @ text @/* ** OSSP str - String Handling ** Copyright (c) 1999-2005 Ralf S. Engelschall ** Copyright (c) 1999-2005 The OSSP Project ** ** This file is part of OSSP str, a string handling and manipulation ** library which can be found at http://www.ossp.org/pkg/lib/str/. ** ** Permission to use, copy, modify, and distribute this software for ** any purpose with or without fee is hereby granted, provided that ** the above copyright notice and this permission notice appear in all ** copies. ** ** THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED ** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF ** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ** IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR ** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF ** USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, ** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ** OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ** SUCH DAMAGE. ** ** str_format.c: formatting functions */ /* * Copyright (c) 1995-1999 The Apache Group. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. All advertising materials mentioning features or use of this * software must display the following acknowledgment: * "This product includes software developed by the Apache Group * for use in the Apache HTTP server project (http://www.apache.org/)." * * 4. The names "Apache Server" and "Apache Group" must not be used to * endorse or promote products derived from this software without * prior written permission. For written permission, please contact * apache@@apache.org. * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * 6. Redistributions of any form whatsoever must retain the following * acknowledgment: * "This product includes software developed by the Apache Group * for use in the Apache HTTP server project (http://www.apache.org/)." * * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * This is a generic printf-style formatting code which is based on * Apache's ap_snprintf which it turn is based on and used with the * permission of, the SIO stdio-replacement strx_* functions by Panos * Tsirigotis for xinetd. The IEEE * floating point formatting routines are derived from an anchient * FreeBSD version which took it from GNU libc-4.6.27 and modified it * to be thread safe. The whole code was finally cleaned up, stripped * and extended by Ralf S. Engelschall for use inside the Str library. * Especially any Apache and network specific kludges were removed again * and instead the formatting engine now can be extended by the caller * on-the-fly. */ #include #include #include #include #include #include #include "str_p.h" /* types which are locally use */ typedef long long_int; typedef unsigned long u_long_int; #if defined(SIZEOF_LONG_LONG) && (SIZEOF_LONG_LONG > 0) typedef long long quad_int; typedef unsigned long long u_quad_int; #else typedef long quad_int; typedef unsigned long u_quad_int; #endif /* a few handy defines */ static char str_null[] = "(NULL)"; #define S_NULL str_null #define S_NULL_LEN 6 #define FLOAT_DIGITS 6 #define EXPONENT_LENGTH 10 /* NUM_BUF_SIZE is the size of the buffer used for arithmetic conversions. This is a magic number; do NOT decrease it! */ #define NUM_BUF_SIZE 512 #define NDIG 80 /* compatibility */ #if !defined(HAVE_ISNAN) #define isnan(d) (0) #endif #if !defined(HAVE_ISINF) #define isinf(d) (0) #endif /* * Convert decimal number to its string representation. The number of * digits is specified by ndigit decpt is set to the position of the * decimal point sign is set to 0 for positive, 1 for negative. buf must * have at least NDIG bytes. */ #define str_ecvt(arg,ndigits,decpt,sign,buf) \ str_cvt((arg), (ndigits), (decpt), (sign), 1, (buf)) #define str_fcvt(arg,ndigits,decpt,sign,buf) \ str_cvt((arg), (ndigits), (decpt), (sign), 0, (buf)) /* inlined modf(3) to avoid dependency to external libm on systems (like Tru64, QNX, etc) where modf(3) is not part of libc. */ static double str_modf( double arg, double *iptr) { double fraction; double integral; long truncated; truncated = (long)arg; integral = (double)truncated; fraction = arg - integral; if (iptr != NULL) *iptr = integral; return fraction; } static char * str_cvt( double arg, int ndigits, int *decpt, BOOL *sign, int eflag, char *buf) { register int r2; double fi, fj; register char *p, *p1; if (ndigits >= NDIG - 1) ndigits = NDIG - 2; r2 = 0; *sign = FALSE; p = &buf[0]; if (arg < 0) { *sign = TRUE; arg = -arg; } arg = str_modf(arg, &fi); p1 = &buf[NDIG]; /* Do integer part */ if (fi != 0) { p1 = &buf[NDIG]; while (fi != 0 && p1 > &buf[0]) { fj = str_modf(fi / 10, &fi); *--p1 = (int)((fj + .03) * 10) + '0'; r2++; } while (p1 < &buf[NDIG]) *p++ = *p1++; } else if (arg > 0) { while ((fj = arg * 10) < 1) { arg = fj; r2--; } } p1 = &buf[ndigits]; if (eflag == 0) p1 += r2; *decpt = r2; if (p1 < &buf[0]) { buf[0] = NUL; return (buf); } while (p <= p1 && p < &buf[NDIG]) { arg *= 10; arg = str_modf(arg, &fj); *p++ = (int) fj + '0'; } if (p1 >= &buf[NDIG]) { buf[NDIG - 1] = NUL; return (buf); } p = p1; *p1 += 5; while (*p1 > '9') { *p1 = '0'; if (p1 > buf) ++ * --p1; else { *p1 = '1'; (*decpt)++; if (eflag == 0) { if (p > buf) *p = '0'; p++; } } } *p = NUL; return buf; } static char * str_gcvt( double number, int ndigit, char *buf, BOOL altform) { BOOL sign; int decpt; register char *p1, *p2; register int i; char buf1[NDIG]; p1 = str_ecvt(number, ndigit, &decpt, &sign, buf1); p2 = buf; if (sign) *p2++ = '-'; for (i = ndigit - 1; i > 0 && p1[i] == '0'; i--) ndigit--; if ((decpt >= 0 && decpt - ndigit > 4) || (decpt < 0 && decpt < -3)) { /* use E-style */ decpt--; *p2++ = *p1++; *p2++ = '.'; for (i = 1; i < ndigit; i++) *p2++ = *p1++; *p2++ = 'e'; if (decpt < 0) { decpt = -decpt; *p2++ = '-'; } else *p2++ = '+'; if (decpt / 100 > 0) *p2++ = decpt / 100 + '0'; if (decpt / 10 > 0) *p2++ = (decpt % 100) / 10 + '0'; *p2++ = decpt % 10 + '0'; } else { if (decpt <= 0) { if (*p1 != '0') *p2++ = '.'; while (decpt < 0) { decpt++; *p2++ = '0'; } } for (i = 1; i <= ndigit; i++) { *p2++ = *p1++; if (i == decpt) *p2++ = '.'; } if (ndigit < decpt) { while (ndigit++ < decpt) *p2++ = '0'; *p2++ = '.'; } } if (p2[-1] == '.' && !altform) p2--; *p2 = NUL; return buf; } /* * The INS_CHAR macro inserts a character in the buffer and flushes the * buffer if necessary. It uses the char pointers sp and bep: sp points * to the next available character in the buffer, bep points to the * end-of-buffer+1. While using this macro, note that the nextb pointer * is NOT updated. NOTE: Evaluation of the c argument should not have * any side-effects */ #define INS_CHAR(c, sp, bep, cc) { \ if (sp >= bep) { \ vbuff->curpos = sp; \ if (vbuff->flush(vbuff)) \ return -1; \ sp = vbuff->curpos; \ bep = vbuff->endpos; \ } \ *sp++ = (c); \ cc++; \ } /* * Convert a string to decimal value */ #define NUM(c) ((c) - '0') #define STR_TO_DEC(str, num) { \ num = NUM(*str++); \ while (str_isdigit(*(str))) { \ num *= 10 ; \ num += NUM(*str++) ; \ } \ } /* * This macro does zero padding so that the precision requirement is * satisfied. The padding is done by adding '0's to the left of the * string that is going to be printed. */ #define FIX_PRECISION(adjust, precision, s, s_len) \ if (adjust) { \ while (s_len < precision) { \ *--s = '0'; \ s_len++; \ } \ } /* * This macro does padding. * The padding is done by printing the character ch. */ #define PAD(width, len, ch) \ do { \ INS_CHAR(ch, sp, bep, cc); \ width-- ; \ } while (width > len) /* * Prefix the character ch to the string str * Increase length. Set the has_prefix flag. */ #define PREFIX(str, length, ch) \ *--str = ch; \ length++; \ has_prefix = TRUE /* * Convert num to its decimal format. * Return value: * - a pointer to a string containing the number (no sign) * - len contains the length of the string * - is_negative is set to TRUE or FALSE depending on the sign * of the number (always set to FALSE if is_unsigned is TRUE) * 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 long_int num, register BOOL is_unsigned, register BOOL *is_negative, char *buf_end, register int *len) { register char *p = buf_end; register u_long_int magnitude; if (is_unsigned) { magnitude = (u_long_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) { long_int t = num + 1; magnitude = ((u_long_int) - t) + 1; } else magnitude = (u_long_int)num; } /* We use a do-while loop so that we write at least 1 digit */ do { register u_long_int new_magnitude = magnitude / 10; *--p = (char) (magnitude - new_magnitude * 10 + '0'); magnitude = new_magnitude; } while (magnitude); *len = (int)(buf_end - p); return p; } static char * conv_10_quad( quad_int num, register BOOL is_unsigned, register BOOL *is_negative, char *buf_end, register int *len) { register char *p = buf_end; u_quad_int magnitude; if (is_unsigned) { magnitude = (u_quad_int)num; *is_negative = FALSE; } else { *is_negative = (num < 0); /* On a 2's complement machine, negating the most negative integer result 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) { quad_int t = num + 1; magnitude = ((u_quad_int) - t) + 1; } else magnitude = (u_quad_int)num; } /* We use a do-while loop so that we write at least 1 digit */ do { u_quad_int new_magnitude = magnitude / 10; *--p = (char)(magnitude - new_magnitude * 10 + '0'); magnitude = new_magnitude; } while (magnitude); *len = (int)(buf_end - p); return p; } /* * Convert a floating point number to a string formats 'f', 'e' or 'E'. * The result is placed in buf, and len denotes the length of the string * The sign is returned in the is_negative argument (and is not placed * in buf). */ static char * conv_fp( register char format, register double num, BOOL add_dp, int precision, BOOL *is_negative, char *buf, int *len) { register char *s = buf; register char *p; int decimal_point; char buf1[NDIG]; if (format == 'f') p = str_fcvt(num, precision, &decimal_point, is_negative, buf1); else /* either e or E format */ p = str_ecvt(num, precision + 1, &decimal_point, is_negative, buf1); /* Check for Infinity and NaN */ if (str_isalpha(*p)) { *len = str_len(str_copy(buf, p, 0)); *is_negative = FALSE; return (buf); } if (format == 'f') { if (decimal_point <= 0) { *s++ = '0'; if (precision > 0) { *s++ = '.'; while (decimal_point++ < 0) *s++ = '0'; } else if (add_dp) *s++ = '.'; } else { while (decimal_point-- > 0) *s++ = *p++; if (precision > 0 || add_dp) *s++ = '.'; } } else { *s++ = *p++; if (precision > 0 || add_dp) *s++ = '.'; } /* copy the rest of p, the NUL is NOT copied */ while (*p) *s++ = *p++; if (format != 'f') { char temp[EXPONENT_LENGTH]; /* for exponent conversion */ int t_len; BOOL exponent_is_negative; *s++ = format; /* either e or E */ decimal_point--; if (decimal_point != 0) { p = conv_10((long_int) decimal_point, FALSE, &exponent_is_negative, &temp[EXPONENT_LENGTH], &t_len); *s++ = exponent_is_negative ? '-' : '+'; /* Make sure the exponent has at least 2 digits */ if (t_len == 1) *s++ = '0'; while (t_len--) *s++ = *p++; } else { *s++ = '+'; *s++ = '0'; *s++ = '0'; } } *len = (int)(s - buf); return buf; } /* * Convert num to a base X number where X is a power of 2. nbits determines X. * For example, if nbits is 3, we do base 8 conversion * Return value: * a pointer to a string containing the number * 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 const char low_digits[] = "0123456789abcdef"; static const char upper_digits[] = "0123456789ABCDEF"; static char * conv_p2( register u_long_int num, register int nbits, char format, char *buf_end, register int *len) { register int mask = (1 << nbits) - 1; register char *p = buf_end; register const char *digits = (format == 'X') ? upper_digits : low_digits; do { *--p = digits[num & mask]; num >>= nbits; } while (num); *len = (int)(buf_end - p); return p; } static char * conv_p2_quad( u_quad_int num, register int nbits, char format, char *buf_end, register int *len) { register int mask = (1 << nbits) - 1; register char *p = buf_end; register const char *digits = (format == 'X') ? upper_digits : low_digits; do { *--p = digits[num & mask]; num >>= nbits; } while (num); *len = (int)(buf_end - p); return p; } /* * str_vformat(), the generic printf-style formatting routine * and heart of this piece of source. */ int str_vformat( str_vformat_t *vbuff, const char *fmt, va_list ap) { register char *sp; register char *bep; register int cc = 0; register int i; register char *s = NULL; char *q; int s_len; register int min_width = 0; int precision = 0; enum { LEFT, RIGHT } adjust; char pad_char; char prefix_char; double fp_num; quad_int i_quad = (quad_int)0; u_quad_int ui_quad; long_int i_num = (long_int)0; u_long_int ui_num; char num_buf[NUM_BUF_SIZE]; char char_buf[2]; /* for printing %% and % */ enum var_type_enum { IS_QUAD, IS_LONG, IS_SHORT, IS_INT }; enum var_type_enum var_type = IS_INT; BOOL alternate_form; BOOL print_sign; BOOL print_blank; BOOL adjust_precision; BOOL adjust_width; BOOL is_negative; char extinfo[20]; sp = vbuff->curpos; bep = vbuff->endpos; while (*fmt != NUL) { if (*fmt != '%') { INS_CHAR(*fmt, sp, bep, cc); } else { /* * Default variable settings */ adjust = RIGHT; alternate_form = print_sign = print_blank = FALSE; pad_char = ' '; prefix_char = NUL; extinfo[0] = NUL; fmt++; /* * Try to avoid checking for flags, width or precision */ if (!str_islower(*fmt)) { /* * Recognize flags: -, #, BLANK, + */ for (;; fmt++) { if (*fmt == '{') { i = 0; for (fmt++; *fmt != '}' && *fmt != NUL; fmt++) { if (i < sizeof(extinfo)-1) extinfo[i++] = *fmt; } extinfo[i] = NUL; } else if (*fmt == '-') adjust = LEFT; else if (*fmt == '+') print_sign = TRUE; else if (*fmt == '#') alternate_form = TRUE; else if (*fmt == ' ') print_blank = TRUE; else if (*fmt == '0') pad_char = '0'; else break; } /* * Check if a width was specified */ if (str_isdigit(*fmt)) { STR_TO_DEC(fmt, min_width); adjust_width = TRUE; } else if (*fmt == '*') { min_width = va_arg(ap, int); fmt++; adjust_width = TRUE; if (min_width < 0) { adjust = LEFT; min_width = -min_width; } } else adjust_width = FALSE; /* * Check if a precision was specified * * XXX: an unreasonable amount of precision may be specified * resulting in overflow of num_buf. Currently we * ignore this possibility. */ if (*fmt == '.') { adjust_precision = TRUE; fmt++; if (str_isdigit(*fmt)) { STR_TO_DEC(fmt, precision); } else if (*fmt == '*') { precision = va_arg(ap, int); fmt++; if (precision < 0) precision = 0; } else precision = 0; } else adjust_precision = FALSE; } else adjust_precision = adjust_width = FALSE; /* * Modifier check */ 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 { var_type = IS_INT; } /* * Argument extraction and printing. * First we determine the argument type. * Then, we convert the argument to a string. * On exit from the switch, s points to the string that * must be printed, s_len has the length of the string * The precision requirements, if any, are reflected in s_len. * * NOTE: pad_char may be set to '0' because of the 0 flag. * It is reset to ' ' by non-numeric formats */ switch (*fmt) { /* Unsigned Decimal Integer */ case 'u': if (var_type == IS_QUAD) { i_quad = va_arg(ap, u_quad_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 = (long_int)va_arg(ap, u_long_int); else if (var_type == IS_SHORT) i_num = (long_int)(unsigned short)va_arg(ap, unsigned int); else i_num = (long_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; /* Signed Decimal Integer */ case 'd': case 'i': if (var_type == IS_QUAD) { i_quad = va_arg(ap, quad_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 = (long_int)va_arg(ap, long_int); else if (var_type == IS_SHORT) i_num = (long_int)(short)va_arg(ap, int); else i_num = (long_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) prefix_char = '-'; else if (print_sign) prefix_char = '+'; else if (print_blank) prefix_char = ' '; break; /* Unsigned Octal Integer */ case 'o': if (var_type == IS_QUAD) { ui_quad = va_arg(ap, u_quad_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_long_int) va_arg(ap, u_long_int); else if (var_type == IS_SHORT) ui_num = (u_long_int)(unsigned short)va_arg(ap, unsigned int); else ui_num = (u_long_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'; s_len++; } break; /* Unsigned Hexadecimal Integer */ case 'x': case 'X': if (var_type == IS_QUAD) { ui_quad = va_arg(ap, u_quad_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_long_int)va_arg(ap, u_long_int); else if (var_type == IS_SHORT) ui_num = (u_long_int)(unsigned short)va_arg(ap, unsigned int); else ui_num = (u_long_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' */ *--s = '0'; s_len += 2; } break; /* String */ case 's': s = va_arg(ap, char *); if (s != NULL) { s_len = str_len(s); if (adjust_precision && precision < s_len) s_len = precision; } else { s = S_NULL; s_len = S_NULL_LEN; } pad_char = ' '; break; /* Double Floating Point (style 1) */ case 'f': case 'e': case 'E': fp_num = va_arg(ap, double); if (isnan(fp_num)) { s = "NaN"; s_len = 3; } else if (isinf(fp_num)) { s = "Inf"; s_len = 3; } else { /* use &num_buf[1], so that we have room for the sign */ s = conv_fp(*fmt, fp_num, alternate_form, (adjust_precision == FALSE) ? FLOAT_DIGITS : precision, &is_negative, &num_buf[1], &s_len); if (is_negative) prefix_char = '-'; else if (print_sign) prefix_char = '+'; else if (print_blank) prefix_char = ' '; } break; /* Double Floating Point (style 2) */ case 'g': case 'G': fp_num = va_arg(ap, double); if (isnan(fp_num)) { s = "NaN"; s_len = 3; } else if (isinf(fp_num)) { s = "Inf"; s_len = 3; } else { if (adjust_precision == FALSE) precision = FLOAT_DIGITS; else if (precision == 0) precision = 1; /* use &num_buf[1], so that we have room for the sign */ s = str_gcvt(fp_num, precision, &num_buf[1], alternate_form); if (*s == '-') prefix_char = *s++; else if (print_sign) prefix_char = '+'; else if (print_blank) prefix_char = ' '; s_len = str_len(s); if (alternate_form && (q = str_span(s, 0, ".", 0)) == NULL) { s[s_len++] = '.'; s[s_len] = NUL; /* delimit for following str_span() */ } if (*fmt == 'G' && (q = str_span(s, 0, "e", 0)) != NULL) *q = 'E'; } break; /* Single Character */ case 'c': char_buf[0] = (char) (va_arg(ap, int)); s = &char_buf[0]; s_len = 1; pad_char = ' '; break; /* The '%' Character */ case '%': char_buf[0] = '%'; s = &char_buf[0]; s_len = 1; pad_char = ' '; break; /* Special: Number of already written characters */ case 'n': if (var_type == IS_QUAD) *(va_arg(ap, quad_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; /* * Pointer argument type. */ case 'p': #if defined(SIZEOF_LONG_LONG) && (SIZEOF_LONG_LONG == SIZEOF_VOID_P) ui_quad = (u_quad_int) va_arg(ap, void *); s = conv_p2_quad(ui_quad, 4, 'x', &num_buf[NUM_BUF_SIZE], &s_len); #else ui_num = (u_long_int) va_arg(ap, void *); s = conv_p2(ui_num, 4, 'x', &num_buf[NUM_BUF_SIZE], &s_len); #endif pad_char = ' '; break; case NUL: /* * The last character of the format string was %. * We ignore it. */ continue; /* * The default case is for unrecognized %'s. We print * % to help the user identify what option is not * understood. This is also useful in case the user * wants to pass the output of format_converter to * another function that understands some other % * (like syslog). Note that we can't point s inside fmt * because the unknown could be preceded by width * etc. */ default: s = NULL; if (vbuff->format != NULL) { s = vbuff->format(vbuff, &prefix_char, &pad_char, &s_len, num_buf, NUM_BUF_SIZE, extinfo, *fmt, ap); } if (s == NULL) { char_buf[0] = '%'; char_buf[1] = *fmt; s = char_buf; s_len = 2; pad_char = ' '; } break; } if (prefix_char != NUL && s != S_NULL && s != char_buf) { *--s = prefix_char; s_len++; } if (adjust_width && adjust == RIGHT && min_width > s_len) { if (pad_char == '0' && prefix_char != NUL) { INS_CHAR(*s, sp, bep, cc); s++; s_len--; min_width--; } PAD(min_width, s_len, pad_char); } /* * Print the string s. */ for (i = s_len; i != 0; i--) { INS_CHAR(*s, sp, bep, cc); s++; } if (adjust_width && adjust == LEFT && min_width > s_len) PAD(min_width, s_len, pad_char); } fmt++; } vbuff->curpos = sp; return cc; } /* * str_format -- format a new string. * This is inspired by POSIX sprintf(3), but mainly provides the * following differences: first it is actually a snprintf(3) style, i.e. * it allows one to specify the maximum number of characters which are * allowed to write. Second, it allows one to just count the number of * characters which have to be written. */ #define STR_FORMAT_BUFLEN 20 static int str_flush_fake(str_vformat_t *out_handle) { out_handle->data[1].i += out_handle->data[2].i; out_handle->curpos = (char *)out_handle->data[0].p; return 0; } static int str_flush_real(str_vformat_t *out_handle) { return -1; } int str_format_va(char *s, str_size_t n, const char *fmt, va_list ap) { str_vformat_t handle; char buf[STR_FORMAT_BUFLEN]; int rv; if (n == 0) return 0; if (s == NULL) { /* fake formatting, i.e., calculate output length only */ handle.curpos = buf; handle.endpos = buf + sizeof(buf) - 1; handle.flush = str_flush_fake; handle.format = NULL; handle.data[0].p = buf; handle.data[1].i = 0; handle.data[2].i = sizeof(buf); rv = str_vformat(&handle, fmt, ap); if (rv == -1) rv = (int)n; } else { /* real formatting, i.e., create output */ handle.curpos = s; handle.endpos = s + n - 1; handle.flush = str_flush_real; handle.format = NULL; rv = str_vformat(&handle, fmt, ap); *(handle.curpos) = NUL; if (rv == -1) rv = (int)n; } return rv; } int str_format(char *s, str_size_t n, const char *fmt, ...) { va_list ap; int rv; va_start(ap, fmt); rv = str_format_va(s, n, fmt, ap); va_end(ap); return rv; } #if 0 /* still don't know whether it fits into API */ char *str_aprintf(const char *fmt, ...) { va_list ap; char *s; int rv; va_start(ap, fmt); rv = str_format_va(NULL, -1, fmt, ap); va_end(ap); if (rv == -1) return NULL; if ((s = malloc(rv+1)) == NULL) return NULL; va_start(ap, fmt); rv = str_format_va(s, rv+1, fmt, ap); va_end(ap); if (rv == -1) return NULL; return s; } #endif @ 1.31 log @flush pending changes @ text @d113 2 a114 1 #define S_NULL "(NULL)" @ 1.30 log @Adjusted copyright messages for new year 2004/2005. @ text @d92 7 d153 1 a153 1 long trunc; d155 2 a156 2 trunc = (long)arg; integral = (double)trunc; @ 1.29 log @Replace modf(3) with hand-crafted inlined function to avoid dependency to external libm; see Checkin [4512] @ text @d3 2 a4 2 ** Copyright (c) 1999-2003 Ralf S. Engelschall ** Copyright (c) 1999-2003 The OSSP Project @ 1.28 log @- adjust copyright messages for new year 2003 - strip trailing whitespaces - consistently use OSSP ASCII-art - add standard devtool.conf stuff from OSSP sa @ text @d137 19 d178 1 a178 1 arg = modf(arg, &fi); d185 1 a185 1 fj = modf(fi / 10, &fi); d208 1 a208 1 arg = modf(arg, &fj); @ 1.27 log @finally switch to full OSSP branding @ text @d3 2 a4 2 ** Copyright (c) 1999-2002 Ralf S. Engelschall ** Copyright (c) 1999-2002 The OSSP Project d6 1 a6 1 ** This file is part of OSSP str, a string handling and manipulation d38 1 a38 1 * notice, this list of conditions and the following disclaimer. d111 1 a111 1 /* NUM_BUF_SIZE is the size of the buffer used for arithmetic d124 1 a124 1 /* d139 4 a142 4 double arg, int ndigits, int *decpt, BOOL *sign, d218 3 a220 3 double number, int ndigit, char *buf, d302 1 a302 1 * Convert a string to decimal value d312 1 a312 1 d327 1 a327 1 * This macro does padding. d361 1 a361 1 register long_int num, d363 1 a363 1 register BOOL *is_negative, d376 1 a376 1 /* On a 2's complement machine, negating the most negative integer d403 1 a403 1 quad_int num, d405 1 a405 1 register BOOL *is_negative, d418 1 a418 1 /* On a 2's complement machine, negating the most negative integer d450 1 a450 1 register char format, d452 2 a453 2 BOOL add_dp, int precision, d455 1 a455 1 char *buf, d511 1 a511 1 p = conv_10((long_int) decimal_point, FALSE, &exponent_is_negative, d548 1 a548 1 register u_long_int num, d550 2 a551 2 char format, char *buf_end, d568 1 a568 1 u_quad_int num, d570 2 a571 2 char format, char *buf_end, d586 1 a586 1 /* d590 1 a590 1 int d592 2 a593 2 str_vformat_t *vbuff, const char *fmt, d887 1 a887 1 (adjust_precision == FALSE) ? FLOAT_DIGITS : precision, d962 1 a962 1 * Pointer argument type. d995 2 a996 2 s = vbuff->format(vbuff, &prefix_char, &pad_char, &s_len, d1025 1 a1025 1 * Print the string s. d1131 1 a1131 1 #endif @ 1.26 log @bump copyright year @ text @d2 1 a2 1 ** Str - String Library d4 1 d6 2 a7 2 ** This file is part of Str, a string handling and manipulation ** library which can be found at http://www.engelschall.com/sw/str/. @ 1.25 log @Adjust copyright for year 2001. @ text @d3 1 a3 1 ** Copyright (c) 1999-2001 Ralf S. Engelschall @ 1.24 log @*** empty log message *** @ text @d3 1 a3 1 ** Copyright (c) 1999-2000 Ralf S. Engelschall @ 1.23 log @*** empty log message *** @ text @d115 8 @ 1.22 log @*** empty log message *** @ text @d86 1 a86 1 * Especially and Apache and network specific kludges were removed again @ 1.21 log @*** empty log message *** @ text @d867 20 a886 10 /* We use &num_buf[1], so that we have room for the sign */ s = conv_fp(*fmt, fp_num, alternate_form, (adjust_precision == FALSE) ? FLOAT_DIGITS : precision, &is_negative, &num_buf[1], &s_len); if (is_negative) prefix_char = '-'; else if (print_sign) prefix_char = '+'; else if (print_blank) prefix_char = ' '; a888 1 d892 29 a920 17 if (adjust_precision == FALSE) precision = FLOAT_DIGITS; else if (precision == 0) precision = 1; /* We use &num_buf[1], so that we have room for the sign */ s = str_gcvt(va_arg(ap, double), precision, &num_buf[1], alternate_form); if (*s == '-') prefix_char = *s++; else if (print_sign) prefix_char = '+'; else if (print_blank) prefix_char = ' '; s_len = str_len(s); if (alternate_form && (q = str_span(s, 0, ".", 0)) == NULL) { s[s_len++] = '.'; s[s_len] = NUL; /* delimit for following str_span() */ a921 2 if (*fmt == 'G' && (q = str_span(s, 0, "e", 0)) != NULL) *q = 'E'; @ 1.20 log @*** empty log message *** @ text @d116 4 a119 3 * convert string to decimal. the number of digits is specified by * ndigit decpt is set to the position of the decimal point sign is set * to 0 for positive, 1 for negative. buf must have at least NDIG bytes. d156 1 a156 1 while (fi != 0) { d158 1 a158 1 *--p1 = (int) ((fj + .03) * 10) + '0'; d204 1 a204 1 return (buf); d269 1 a269 1 return (buf); d297 1 a297 1 num = NUM( *str++ ); \ d300 1 a300 1 num += NUM( *str++ ) ; \ d332 2 a333 2 *--str = ch; \ length++; \ d867 1 a867 1 /* We use &num_buf[ 1 ], so that we have room for the sign */ d869 1 a869 1 (adjust_precision == FALSE) ? FLOAT_DIGITS : precision, d879 1 d887 1 a887 1 /* We use &num_buf[ 1 ], so that we have room for the sign */ d1081 23 @ 1.19 log @*** empty log message *** @ text @d361 1 a361 1 magnitude = (u_long_int) num; d379 1 a379 1 magnitude = (u_long_int) num; d386 3 a388 4 } while (magnitude); *len = buf_end - p; return (p); d403 1 a403 1 magnitude = (u_quad_int) num; d420 1 a420 1 magnitude = (u_quad_int) num; d427 3 a429 4 } while (magnitude); *len = buf_end - p; return (p); d517 2 a518 2 *len = s - buf; return (buf); d552 2 a553 2 *len = buf_end - p; return (p); d572 2 a573 2 *len = buf_end - p; return (p); d1053 1 a1053 1 rv = n; d1064 1 a1064 1 rv = n; d1072 1 d1075 1 a1075 1 str_format_va(s, n, fmt, ap); d1077 1 a1077 1 return 0; @ 1.18 log @*** empty log message *** @ text @d1036 1 a1036 1 int str_format(char *s, str_size_t n, const char *fmt, ...) a1037 1 va_list ap; a1043 1 va_start(ap, fmt); d1068 9 d1078 1 a1078 1 return rv; @ 1.17 log @*** empty log message *** @ text @d627 1 a627 1 while (*fmt) { @ 1.16 log @*** empty log message *** @ text @d3 1 a3 1 ** Copyright (c) 1999 Ralf S. Engelschall @ 1.15 log @*** empty log message *** @ text @d462 1 a462 1 *len = str_len(strcpy(buf, p)); d1014 6 a1019 1 * The high-level API function str_format(3): @ 1.14 log @*** empty log message *** @ text @d584 1 a584 1 str_format_t *vbuff, d1014 1 a1014 2 * The str_format() function, a convinient wrapper around str_vformat() * which on-the-fly generates the va_list argument for the call. a1015 8 int str_format( str_format_t *fs, const char *format, ...) { va_list ap; int rc; d1017 1 a1017 11 va_start(ap, format); rc = str_vformat(fs, format, ap); va_end(ap); return rc; } /* * The str_nformat function, which does a NO-OP in formatting * but does not output anything. Instead it only returns the * number of bytes which would have been written out. */ d1019 1 a1019 5 #define STR_NFORMAT_BUFLEN 20 static int str_nformat_flush( str_format_t *out_handle) d1021 1 a1021 1 out_handle->data[1].i = out_handle->data[1].i + STR_NFORMAT_BUFLEN; d1026 1 a1026 3 int str_nformat( const char *format, ...) a1027 30 int rc; va_list ap; str_format_t handle; char buf[STR_NFORMAT_BUFLEN]; handle.curpos = buf; handle.endpos = buf + STR_NFORMAT_BUFLEN - 1; handle.flush = str_nformat_flush; handle.format = NULL; handle.data[0].p = buf; handle.data[1].i = 0; va_start(ap, format); rc = str_vformat(&handle, format, ap); va_end(ap); return rc; } /* * The two POSIX snprintf(3) and vsnprintf(3) style * functions which are based on str_vformat(3). */ static int str_snprintf_flush( str_format_t *out_handle) { /* * if the buffer fills we have to abort immediately, there is no way * to "flush" an str_snprintf... there's nowhere to flush it to. */ d1031 1 a1031 5 int str_snprintf( char *buf, size_t len, const char *format, ...) a1032 1 int rc; d1034 3 a1036 1 str_format_t handle; d1038 1 a1038 1 if (len == 0) d1040 25 a1064 6 handle.curpos = buf; handle.endpos = buf + len - 1; handle.flush = str_snprintf_flush; handle.format = NULL; va_start(ap, format); rc = str_vformat(&handle, format, ap); d1066 1 a1066 23 *(handle.curpos) = NUL; return (rc == -1) ? len : rc; } int str_vsnprintf( char *buf, size_t len, const char *format, va_list ap) { int rc; str_format_t handle; if (len == 0) return 0; handle.curpos = buf; handle.endpos = buf + len - 1; handle.flush = str_snprintf_flush; handle.format = NULL; rc = str_vformat(&handle, format, ap); *(handle.curpos) = NUL; return (rc == -1) ? len : rc; @ 1.13 log @*** empty log message *** @ text @d83 6 a88 3 * FreeBSD version which took it from GNU libc-4.6.27 and modified it to * be thread safe. The whole code was finally cleaned up and stripped * again by Ralf S. Engelschall for use inside the Str library. @ 1.12 log @*** empty log message *** @ text @d894 1 a894 1 if (alternate_form && (q = str_span(s, STR_FULL, ".", STR_DEF)) == NULL) { d898 1 a898 1 if (*fmt == 'G' && (q = str_span(s, STR_FULL, "e", STR_DEF)) != NULL) @ 1.11 log @*** empty log message *** @ text @d1 3 a3 5 /* ** str_format.c -- String Formatting ** ** ==================================================================== ** Copyright (c) 1999 Ralf S. Engelschall. All rights reserved. d5 2 a6 3 ** Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions ** are met: d8 4 a11 2 ** 1. Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. d13 12 a24 4 ** 2. Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. d26 1 a26 13 ** THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY ** EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR ** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RALF S. ENGELSCHALL OR ** ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT ** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, ** STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED ** OF THE POSSIBILITY OF SUCH DAMAGE. ** ==================================================================== a110 1 @ 1.10 log @*** empty log message *** @ text @d88 3 a90 3 * FreeBSD version which took it from GNU libc-4.6.27 and modified it * to be thread safe. The whole code was finally cleaned up by Ralf S. * Engelschall for use inside the Str library. @ 1.9 log @*** empty log message *** @ text @a437 48 * Convert a `struct in_addr' into `a.b.c.d'. */ static char * conv_in_addr( struct in_addr *ia, char *buf_end, int *len) { unsigned int addr; char *p; BOOL is_negative; int sub_len; addr = ntohl(ia->s_addr); p = buf_end; p = conv_10((addr & 0x000000FF), TRUE, &is_negative, p, &sub_len); *--p = '.'; p = conv_10((addr & 0x0000FF00) >> 8, TRUE, &is_negative, p, &sub_len); *--p = '.'; p = conv_10((addr & 0x00FF0000) >> 16, TRUE, &is_negative, p, &sub_len); *--p = '.'; p = conv_10((addr & 0xFF000000) >> 24, TRUE, &is_negative, p, &sub_len); *len = buf_end - p; return p; } /* * Convert a `struct sockaddr_in' into `a.b.c.d:port'. */ static char * conv_sockaddr_in( struct sockaddr_in *si, char *buf_end, int *len) { char *p; BOOL is_negative; int sub_len; p = buf_end; p = conv_10(ntohs(si->sin_port), TRUE, &is_negative, p, &sub_len); *--p = ':'; p = conv_in_addr(&si->sin_addr, p, &sub_len); *len = buf_end - p; return p; } /* d937 1 a937 2 * Pointer argument type. This is where we extend the * printf format, with a second type specifier. a939 8 switch (*++fmt) { /* * 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': d941 2 a942 5 if (sizeof(void *) <= sizeof(u_quad_int)) { ui_quad = (u_quad_int) va_arg(ap, void *); s = conv_p2_quad(ui_quad, 4, 'x', &num_buf[NUM_BUF_SIZE], &s_len); } d944 2 a945 5 if (sizeof(void *) <= sizeof(u_long_int)) { ui_num = (u_long_int) va_arg(ap, void *); s = conv_p2(ui_num, 4, 'x', &num_buf[NUM_BUF_SIZE], &s_len); } d947 1 a947 52 else { s = "%p"; s_len = 2; prefix_char = NUL; } pad_char = ' '; break; /* print a `struct sockaddr_in' as `a.b.c.d:port' */ case 'I': { struct sockaddr_in *si; si = va_arg(ap, struct sockaddr_in *); if (si != NULL) { s = conv_sockaddr_in(si, &num_buf[NUM_BUF_SIZE], &s_len); if (adjust_precision && precision < s_len) s_len = precision; } else { s = S_NULL; s_len = S_NULL_LEN; } pad_char = ' '; break; } /* print a `struct in_addr' as `a.b.c.d' */ case 'A': { struct in_addr *ia; ia = va_arg(ap, struct in_addr *); if (ia != NULL) { s = conv_in_addr(ia, &num_buf[NUM_BUF_SIZE], &s_len); if (adjust_precision && precision < s_len) s_len = precision; } else { s = S_NULL; s_len = S_NULL_LEN; } pad_char = ' '; break; } case NUL: /* if %p ends the string, oh well ignore it */ continue; default: s = "bogus %p"; s_len = 8; prefix_char = NUL; break; } @ 1.8 log @*** empty log message *** @ text @d177 1 a177 1 buf[0] = '\0'; d186 1 a186 1 buf[NDIG - 1] = '\0'; d205 1 a205 1 *p = '\0'; d270 1 a270 1 *p2 = '\0'; d948 1 a948 1 if (alternate_form && (q = strchr(s, '.')) == NULL) { d950 1 a950 1 s[s_len] = '\0'; /* delimit for following strchr() */ d952 1 a952 1 if (*fmt == 'G' && (q = strchr(s, 'e')) != NULL) @ 1.7 log @*** empty log message *** @ text @d1161 2 a1162 2 out_handle->data[1] = (void *)((unsigned long)out_handle->data[1] + STR_NFORMAT_BUFLEN); out_handle->curpos = (char *)out_handle->data[0]; d1175 6 a1180 8 handle.curpos = buf; handle.endpos = buf + STR_NFORMAT_BUFLEN - 1; handle.flush = str_nformat_flush; handle.format = NULL; handle.data[0] = buf; handle.data[1] = (void *)0; handle.data[2] = NULL; handle.data[3] = NULL; a1218 4 handle.data[0] = NULL; handle.data[1] = NULL; handle.data[2] = NULL; handle.data[3] = NULL; a1241 4 handle.data[0] = NULL; handle.data[1] = NULL; handle.data[2] = NULL; handle.data[3] = NULL; @ 1.6 log @*** empty log message *** @ text @d93 1 a93 12 #include "str.h" #include "str_config.h" #include /* for inaddr etc. */ #include /* for malloc, etc. */ #include /* for modf(3) */ /* explicit support for unsigned char */ #define str_isalpha(c) (isalpha(((unsigned char)(c)))) #define str_isdigit(c) (isdigit(((unsigned char)(c)))) #define str_islower(c) (islower(((unsigned char)(c)))) d1155 1 a1155 1 #define STR_NFORMAT_BUFLEN 2 @ 1.5 log @*** empty log message *** @ text @d684 2 d701 1 d713 9 a721 1 if (*fmt == '-') d1097 1 a1097 1 num_buf, NUM_BUF_SIZE, *fmt, ap); @ 1.4 log @*** empty log message *** @ text @d1082 13 a1094 5 char_buf[0] = '%'; char_buf[1] = *fmt; s = char_buf; s_len = 2; pad_char = ' '; d1178 1 d1219 2 a1224 1 handle.flush = str_snprintf_flush; d1246 2 a1251 1 handle.flush = str_snprintf_flush; @ 1.3 log @*** empty log message *** @ text @d296 1 a296 1 if (flush_func(vbuff)) \ a645 1 int (*flush_func)(str_format_t *), a1020 1 a1037 1 d1040 1 a1040 3 s = conv_in_addr(ia, &num_buf[NUM_BUF_SIZE], &s_len); d1128 1 a1128 2 int (*out_func)(str_format_t *), str_format_t *out_handle, d1136 1 a1136 1 rc = str_vformat(out_func, out_handle, format, ap); d1153 2 a1154 2 out_handle->data2 = (void *)((unsigned long)out_handle->data2 + STR_NFORMAT_BUFLEN); out_handle->curpos = (char *)out_handle->data1; d1167 7 a1173 4 handle.curpos = buf; handle.endpos = buf + STR_NFORMAT_BUFLEN - 1; handle.data1 = buf; handle.data2 = (void *)0; d1175 1 a1175 1 rc = str_vformat(str_nformat_flush, &handle, format, ap); d1208 7 a1214 4 handle.curpos = buf; handle.endpos = buf + len - 1; handle.data1 = NULL; handle.data2 = NULL; d1216 1 a1216 1 rc = str_vformat(str_snprintf_flush, &handle, format, ap); d1234 8 a1241 5 handle.curpos = buf; handle.endpos = buf + len - 1; handle.data1 = NULL; handle.data2 = NULL; rc = str_vformat(str_snprintf_flush, &handle, format, ap); @ 1.2 log @*** empty log message *** @ text @d519 1 a519 1 else /* either e or E format */ @ 1.1 log @Initial revision @ text @d1147 96 @ 1.1.1.1 log @ @ text @@