/*
- * snprintf.c -- formatted output to a string
- *
- * This is an implementation of snprintf() and vsnprintf()
- * taken from the Apache web server. This is only used on
- * systems which do not have a native version.
- */
+** snprintf.c -- formatted output to a string
+**
+** This is an implementation of snprintf() and vsnprintf()
+** taken from the Apache web server. This is only used on
+** systems which do not have a native version.
+*/
/* ====================================================================
- * 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 software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Group and was originally based
- * on public domain software written at the National Center for
- * Supercomputing Applications, University of Illinois, Urbana-Champaign.
- * For more information on the Apache Group and the Apache HTTP server
- * project, please see <http://www.apache.org/>.
- *
- * This code is based on, and used with the permission of, the
- * SIO stdio-replacement strx_* functions by Panos Tsirigotis
- * <panos@alumni.cs.colorado.edu> for xinetd.
- */
+** 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 software consists of voluntary contributions made by many
+** individuals on behalf of the Apache Group and was originally based
+** on public domain software written at the National Center for
+** Supercomputing Applications, University of Illinois, Urbana-Champaign.
+** For more information on the Apache Group and the Apache HTTP server
+** project, please see <http://www.apache.org/>.
+**
+** This code is based on, and used with the permission of, the
+** SIO stdio-replacement strx_* functions by Panos Tsirigotis
+** <panos@alumni.cs.colorado.edu> for xinetd.
+*/
#include <stdio.h>
#include <ctype.h>
#define FLOAT_DIGITS 6
#define EXPONENT_LENGTH 10
-/* These macros allow correct support of 8-bit characters on systems which
- * support 8-bit characters. Pretty dumb how the cast is required, but
- * that's legacy libc for ya. These new macros do not support EOF like
- * the standard macros do. Tough.
- */
+/*
+** These macros allow correct support of 8-bit characters on systems which
+** support 8-bit characters. Pretty dumb how the cast is required, but
+** that's legacy libc for ya. These new macros do not support EOF like
+** the standard macros do. Tough.
+*/
#define ap_isalpha(c) (isalpha(((unsigned char)(c))))
#define ap_isdigit(c) (isdigit(((unsigned char)(c))))
#define ap_islower(c) (islower(((unsigned char)(c))))
/*
- * NUM_BUF_SIZE is the size of the buffer used for arithmetic conversions
- *
- * XXX: this is a magic number; do not decrease it
- */
+** NUM_BUF_SIZE is the size of the buffer used for arithmetic conversions
+**
+** XXX: this is a magic number; do not decrease it
+*/
#define NUM_BUF_SIZE 512
/*
- * cvt.c - IEEE floating point formatting routines for FreeBSD
- * from GNU libc-4.6.27. Modified to be thread safe.
- */
+** cvt.c - IEEE floating point formatting routines for FreeBSD
+** from GNU libc-4.6.27. Modified to be thread safe.
+*/
/*
- * ap_ecvt converts 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
- */
+** ap_ecvt converts 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
+*/
#define NDIG 80
arg = modf(arg, &fi);
p1 = &buf[NDIG];
/*
- * Do integer part
- */
+ ** Do integer part
+ */
if (fi != 0) {
p1 = &buf[NDIG];
while (fi != 0) {
}
/*
- * ap_gcvt - Floating output conversion to
- * minimal length string
- */
+** ap_gcvt - Floating output conversion to
+** minimal length string
+*/
static char *
ap_gcvt(double number, int ndigit, char *buf, boolean_e altform)
}
/*
- * The INS_CHAR macro inserts a character in the buffer and writes
- * the buffer back to disk 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
- */
+** The INS_CHAR macro inserts a character in the buffer and writes
+** the buffer back to disk 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) { \
}
/*
- * 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.
- */
+** 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 ) \
}
/*
- * Macro that does padding. The padding is done by printing
- * the character ch.
- */
+** Macro that does padding. The padding is done by printing
+** the character ch.
+*/
#define PAD( width, len, ch ) do \
{ \
INS_CHAR( ch, sp, bep, cc ) ; \
while ( width > len )
/*
- * Prefix the character ch to the string str
- * Increase length
- * Set the has_prefix flag
- */
+** 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 = YES
/*
- * 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 ])
- */
+** 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 ])
+*/
static char *
conv_10(register wide_int num, register bool_int is_unsigned,
register bool_int *is_negative, char *buf_end,
*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
- */
+ ** 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) {
wide_int t = num + 1;
}
/*
- * We use a do-while loop so that we write at least 1 digit
- */
+ ** We use a do-while loop so that we write at least 1 digit
+ */
do {
register u_wide_int new_magnitude = magnitude / 10;
/*
- * 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).
- */
+** 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,
boolean_e add_dp, int precision, bool_int *is_negative,
p = ap_ecvt(num, precision + 1, &decimal_point, is_negative, buf1);
/*
- * Check for Infinity and NaN
- */
+ ** Check for Infinity and NaN
+ */
if (ap_isalpha(*p)) {
*len = strlen(strcpy(buf, p));
*is_negative = FALSE;
}
/*
- * copy the rest of p, the NUL is NOT copied
- */
+ ** copy the rest of p, the NUL is NOT copied
+ */
while (*p)
*s++ = *p++;
*s++ = exponent_is_negative ? '-' : '+';
/*
- * Make sure the exponent has at least 2 digits
- */
+ ** Make sure the exponent has at least 2 digits
+ */
if (t_len == 1)
*s++ = '0';
while (t_len--)
/*
- * 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 ])
- */
+** 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 ])
+*/
static char *
conv_p2(register u_wide_int num, register int nbits,
char format, char *buf_end, register int *len)
/*
- * Do format conversion placing the output in buffer
- */
+** Do format conversion placing the output in buffer
+*/
static int
ap_vformatter(int (*flush_func)(ap_vformatter_buff *),
ap_vformatter_buff *vbuff, const char *fmt, va_list ap)
char char_buf[2]; /* for printing %% and %<unknown> */
/*
- * Flag variables
- */
+ ** Flag variables
+ */
boolean_e is_long;
boolean_e alternate_form;
boolean_e print_sign;
INS_CHAR(*fmt, sp, bep, cc);
} else {
/*
- * Default variable settings
- */
+ ** Default variable settings
+ */
adjust = RIGHT;
alternate_form = print_sign = print_blank = NO;
pad_char = ' ';
fmt++;
/*
- * Try to avoid checking for flags, width or precision
- */
+ ** Try to avoid checking for flags, width or precision
+ */
if (!ap_islower(*fmt)) {
/*
- * Recognize flags: -, #, BLANK, +
- */
+ ** Recognize flags: -, #, BLANK, +
+ */
for (;; fmt++) {
if (*fmt == '-')
adjust = LEFT;
}
/*
- * Check if a width was specified
- */
+ ** Check if a width was specified
+ */
if (ap_isdigit(*fmt)) {
STR_TO_DEC(fmt, min_width);
adjust_width = YES;
adjust_width = NO;
/*
- * 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.
- */
+ ** 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 = YES;
fmt++;
adjust_precision = adjust_width = NO;
/*
- * Modifier check
- */
+ ** Modifier check
+ */
if (*fmt == 'l') {
is_long = YES;
fmt++;
}
/*
- * 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
- */
+ ** 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) {
case 'u':
if (is_long)
case 'E':
fp_num = va_arg(ap, double);
/*
- * * We use &num_buf[ 1 ], so that we have room for the sign
- */
+ ** We use &num_buf[ 1 ], so that we have
+ ** room for the sign
+ */
s = conv_fp(*fmt, fp_num, alternate_form,
(adjust_precision == NO) ? FLOAT_DIGITS : precision,
&is_negative, &num_buf[1], &s_len);
else if (precision == 0)
precision = 1;
/*
- * * We use &num_buf[ 1 ], so that we have room for the sign
- */
+ ** We use &num_buf[ 1 ], so that we have
+ ** room for the sign
+ */
s = ap_gcvt(va_arg(ap, double), precision, &num_buf[1],
alternate_form);
if (*s == '-')
break;
/*
- * This is where we extend the printf format, with a second
- * type specifier
- */
+ ** This is where we extend the printf format,
+ ** with a second type specifier
+ */
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
+ ** 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".
+ */
case 'p':
ui_num = (u_wide_int) va_arg(ap, void *);
pad_char = ' ';
break;
- /* print a struct sockaddr_in as a.b.c.d:port */
+ /*
+ ** print a struct sockaddr_in as
+ ** a.b.c.d:port
+ */
case 'I':
{
struct sockaddr_in *si;
s = conv_sockaddr_in(si, &num_buf[NUM_BUF_SIZE], &s_len);
if (adjust_precision && precision < s_len)
s_len = precision;
- }
- else {
+ } else {
s = S_NULL;
s_len = S_NULL_LEN;
}
s = conv_in_addr(ia, &num_buf[NUM_BUF_SIZE], &s_len);
if (adjust_precision && precision < s_len)
s_len = precision;
- }
- else {
+ } else {
s = S_NULL;
s_len = S_NULL_LEN;
}
case NUL:
/*
- * The last character of the format string was %.
- * We ignore it.
- */
+ ** The last character of the format string
+ ** was %. We ignore it.
+ */
continue;
/*
- * The default case is for unrecognized %'s.
- * We print %<char> 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 %<char> (like syslog).
- * Note that we can't point s inside fmt because the
- * unknown <char> could be preceded by width etc.
- */
+ ** The default case is for unrecognized %'s.
+ ** We print %<char> 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 %<char> (like syslog).
+ ** Note that we can't point s inside fmt
+ ** because the unknown <char> could be
+ ** preceded by width etc.
+ */
default:
char_buf[0] = '%';
char_buf[1] = *fmt;
}
/*
- * Print the string s.
- */
+ ** Print the string s.
+ */
for (i = s_len; i != 0; i--) {
INS_CHAR(*s, sp, bep, cc);
s++;
static int
snprintf_flush(ap_vformatter_buff *vbuff)
{
- /* if the buffer fills we have to abort immediately, there is no way
- * to "flush" a snprintf... there's nowhere to flush it to.
- */
+ /*
+ ** if the buffer fills we have to abort immediately, there is no way
+ ** to "flush" a snprintf... there's nowhere to flush it to.
+ */
return -1;
}