sl@0: /* crypto/bio/b_print.c */ sl@0: /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) sl@0: * All rights reserved. sl@0: * sl@0: * This package is an SSL implementation written sl@0: * by Eric Young (eay@cryptsoft.com). sl@0: * The implementation was written so as to conform with Netscapes SSL. sl@0: * sl@0: * This library is free for commercial and non-commercial use as long as sl@0: * the following conditions are aheared to. The following conditions sl@0: * apply to all code found in this distribution, be it the RC4, RSA, sl@0: * lhash, DES, etc., code; not just the SSL code. The SSL documentation sl@0: * included with this distribution is covered by the same copyright terms sl@0: * except that the holder is Tim Hudson (tjh@cryptsoft.com). sl@0: * sl@0: * Copyright remains Eric Young's, and as such any Copyright notices in sl@0: * the code are not to be removed. sl@0: * If this package is used in a product, Eric Young should be given attribution sl@0: * as the author of the parts of the library used. sl@0: * This can be in the form of a textual message at program startup or sl@0: * in documentation (online or textual) provided with the package. sl@0: * sl@0: * Redistribution and use in source and binary forms, with or without sl@0: * modification, are permitted provided that the following conditions sl@0: * are met: sl@0: * 1. Redistributions of source code must retain the copyright sl@0: * notice, this list of conditions and the following disclaimer. sl@0: * 2. Redistributions in binary form must reproduce the above copyright sl@0: * notice, this list of conditions and the following disclaimer in the sl@0: * documentation and/or other materials provided with the distribution. sl@0: * 3. All advertising materials mentioning features or use of this software sl@0: * must display the following acknowledgement: sl@0: * "This product includes cryptographic software written by sl@0: * Eric Young (eay@cryptsoft.com)" sl@0: * The word 'cryptographic' can be left out if the rouines from the library sl@0: * being used are not cryptographic related :-). sl@0: * 4. If you include any Windows specific code (or a derivative thereof) from sl@0: * the apps directory (application code) you must include an acknowledgement: sl@0: * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" sl@0: * sl@0: * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND sl@0: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE sl@0: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE sl@0: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE sl@0: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL sl@0: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS sl@0: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) sl@0: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT sl@0: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY sl@0: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF sl@0: * SUCH DAMAGE. sl@0: * sl@0: * The licence and distribution terms for any publically available version or sl@0: * derivative of this code cannot be changed. i.e. this code cannot simply be sl@0: * copied and put under another distribution licence sl@0: * [including the GNU Public Licence.] sl@0: */ sl@0: /* sl@0: © Portions copyright (c) 2006 Nokia Corporation. All rights reserved. sl@0: */ sl@0: /* disable assert() unless BIO_DEBUG has been defined */ sl@0: #ifndef BIO_DEBUG sl@0: # ifndef NDEBUG sl@0: # define NDEBUG sl@0: # endif sl@0: #endif sl@0: sl@0: /* sl@0: * Stolen from tjh's ssl/ssl_trc.c stuff. sl@0: */ sl@0: sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include "cryptlib.h" sl@0: #ifndef NO_SYS_TYPES_H sl@0: #include sl@0: #endif sl@0: #include /* To get BN_LLONG properly defined */ sl@0: #include sl@0: sl@0: #if defined(BN_LLONG) || defined(SIXTY_FOUR_BIT) sl@0: # ifndef HAVE_LONG_LONG sl@0: # define HAVE_LONG_LONG 1 sl@0: # endif sl@0: #endif sl@0: sl@0: /***************************************************************************/ sl@0: sl@0: /* sl@0: * Copyright Patrick Powell 1995 sl@0: * This code is based on code written by Patrick Powell sl@0: * It may be used for any purpose as long as this notice remains intact sl@0: * on all source code distributions. sl@0: */ sl@0: sl@0: /* sl@0: * This code contains numerious changes and enhancements which were sl@0: * made by lots of contributors over the last years to Patrick Powell's sl@0: * original code: sl@0: * sl@0: * o Patrick Powell (1995) sl@0: * o Brandon Long (1996, for Mutt) sl@0: * o Thomas Roessler (1998, for Mutt) sl@0: * o Michael Elkins (1998, for Mutt) sl@0: * o Andrew Tridgell (1998, for Samba) sl@0: * o Luke Mewburn (1999, for LukemFTP) sl@0: * o Ralf S. Engelschall (1999, for Pth) sl@0: * o ... (for OpenSSL) sl@0: */ sl@0: sl@0: #ifdef HAVE_LONG_DOUBLE sl@0: #define LDOUBLE long double sl@0: #else sl@0: #define LDOUBLE double sl@0: #endif sl@0: sl@0: #if HAVE_LONG_LONG sl@0: # if defined(OPENSSL_SYS_WIN32) && !defined(__GNUC__) sl@0: # define LLONG __int64 sl@0: # else sl@0: # define LLONG long long sl@0: # endif sl@0: #else sl@0: #define LLONG long sl@0: #endif sl@0: sl@0: static void fmtstr (char **, char **, size_t *, size_t *, sl@0: const char *, int, int, int); sl@0: static void fmtint (char **, char **, size_t *, size_t *, sl@0: LLONG, int, int, int, int); sl@0: static void fmtfp (char **, char **, size_t *, size_t *, sl@0: LDOUBLE, int, int, int); sl@0: static void doapr_outch (char **, char **, size_t *, size_t *, int); sl@0: static void _dopr(char **sbuffer, char **buffer, sl@0: size_t *maxlen, size_t *retlen, int *truncated, sl@0: const char *format, va_list args); sl@0: sl@0: /* format read states */ sl@0: #define DP_S_DEFAULT 0 sl@0: #define DP_S_FLAGS 1 sl@0: #define DP_S_MIN 2 sl@0: #define DP_S_DOT 3 sl@0: #define DP_S_MAX 4 sl@0: #define DP_S_MOD 5 sl@0: #define DP_S_CONV 6 sl@0: #define DP_S_DONE 7 sl@0: sl@0: /* format flags - Bits */ sl@0: #define DP_F_MINUS (1 << 0) sl@0: #define DP_F_PLUS (1 << 1) sl@0: #define DP_F_SPACE (1 << 2) sl@0: #define DP_F_NUM (1 << 3) sl@0: #define DP_F_ZERO (1 << 4) sl@0: #define DP_F_UP (1 << 5) sl@0: #define DP_F_UNSIGNED (1 << 6) sl@0: sl@0: /* conversion flags */ sl@0: #define DP_C_SHORT 1 sl@0: #define DP_C_LONG 2 sl@0: #define DP_C_LDOUBLE 3 sl@0: #define DP_C_LLONG 4 sl@0: sl@0: /* some handy macros */ sl@0: #define char_to_int(p) (p - '0') sl@0: #define OSSL_MAX(p,q) ((p >= q) ? p : q) sl@0: sl@0: static void sl@0: _dopr( sl@0: char **sbuffer, sl@0: char **buffer, sl@0: size_t *maxlen, sl@0: size_t *retlen, sl@0: int *truncated, sl@0: const char *format, sl@0: va_list args) sl@0: { sl@0: char ch; sl@0: LLONG value; sl@0: LDOUBLE fvalue; sl@0: char *strvalue; sl@0: int min; sl@0: int max; sl@0: int state; sl@0: int flags; sl@0: int cflags; sl@0: size_t currlen; sl@0: sl@0: state = DP_S_DEFAULT; sl@0: flags = currlen = cflags = min = 0; sl@0: max = -1; sl@0: ch = *format++; sl@0: sl@0: while (state != DP_S_DONE) { sl@0: if (ch == '\0' || (buffer == NULL && currlen >= *maxlen)) sl@0: state = DP_S_DONE; sl@0: sl@0: switch (state) { sl@0: case DP_S_DEFAULT: sl@0: if (ch == '%') sl@0: state = DP_S_FLAGS; sl@0: else sl@0: doapr_outch(sbuffer,buffer, &currlen, maxlen, ch); sl@0: ch = *format++; sl@0: break; sl@0: case DP_S_FLAGS: sl@0: switch (ch) { sl@0: case '-': sl@0: flags |= DP_F_MINUS; sl@0: ch = *format++; sl@0: break; sl@0: case '+': sl@0: flags |= DP_F_PLUS; sl@0: ch = *format++; sl@0: break; sl@0: case ' ': sl@0: flags |= DP_F_SPACE; sl@0: ch = *format++; sl@0: break; sl@0: case '#': sl@0: flags |= DP_F_NUM; sl@0: ch = *format++; sl@0: break; sl@0: case '0': sl@0: flags |= DP_F_ZERO; sl@0: ch = *format++; sl@0: break; sl@0: default: sl@0: state = DP_S_MIN; sl@0: break; sl@0: } sl@0: break; sl@0: case DP_S_MIN: sl@0: if (isdigit((unsigned char)ch)) { sl@0: min = 10 * min + char_to_int(ch); sl@0: ch = *format++; sl@0: } else if (ch == '*') { sl@0: min = va_arg(args, int); sl@0: ch = *format++; sl@0: state = DP_S_DOT; sl@0: } else sl@0: state = DP_S_DOT; sl@0: break; sl@0: case DP_S_DOT: sl@0: if (ch == '.') { sl@0: state = DP_S_MAX; sl@0: ch = *format++; sl@0: } else sl@0: state = DP_S_MOD; sl@0: break; sl@0: case DP_S_MAX: sl@0: if (isdigit((unsigned char)ch)) { sl@0: if (max < 0) sl@0: max = 0; sl@0: max = 10 * max + char_to_int(ch); sl@0: ch = *format++; sl@0: } else if (ch == '*') { sl@0: max = va_arg(args, int); sl@0: ch = *format++; sl@0: state = DP_S_MOD; sl@0: } else sl@0: state = DP_S_MOD; sl@0: break; sl@0: case DP_S_MOD: sl@0: switch (ch) { sl@0: case 'h': sl@0: cflags = DP_C_SHORT; sl@0: ch = *format++; sl@0: break; sl@0: case 'l': sl@0: if (*format == 'l') { sl@0: cflags = DP_C_LLONG; sl@0: format++; sl@0: } else sl@0: cflags = DP_C_LONG; sl@0: ch = *format++; sl@0: break; sl@0: case 'q': sl@0: cflags = DP_C_LLONG; sl@0: ch = *format++; sl@0: break; sl@0: case 'L': sl@0: cflags = DP_C_LDOUBLE; sl@0: ch = *format++; sl@0: break; sl@0: default: sl@0: break; sl@0: } sl@0: state = DP_S_CONV; sl@0: break; sl@0: case DP_S_CONV: sl@0: switch (ch) { sl@0: case 'd': sl@0: case 'i': sl@0: switch (cflags) { sl@0: case DP_C_SHORT: sl@0: value = (short int)va_arg(args, int); sl@0: break; sl@0: case DP_C_LONG: sl@0: value = va_arg(args, long int); sl@0: break; sl@0: case DP_C_LLONG: sl@0: value = va_arg(args, LLONG); sl@0: break; sl@0: default: sl@0: value = va_arg(args, int); sl@0: break; sl@0: } sl@0: fmtint(sbuffer, buffer, &currlen, maxlen, sl@0: value, 10, min, max, flags); sl@0: break; sl@0: case 'X': sl@0: flags |= DP_F_UP; sl@0: /* FALLTHROUGH */ sl@0: case 'x': sl@0: case 'o': sl@0: case 'u': sl@0: flags |= DP_F_UNSIGNED; sl@0: switch (cflags) { sl@0: case DP_C_SHORT: sl@0: value = (unsigned short int)va_arg(args, unsigned int); sl@0: break; sl@0: case DP_C_LONG: sl@0: value = (LLONG) va_arg(args, sl@0: unsigned long int); sl@0: break; sl@0: case DP_C_LLONG: sl@0: value = va_arg(args, unsigned LLONG); sl@0: break; sl@0: default: sl@0: value = (LLONG) va_arg(args, sl@0: unsigned int); sl@0: break; sl@0: } sl@0: fmtint(sbuffer, buffer, &currlen, maxlen, value, sl@0: ch == 'o' ? 8 : (ch == 'u' ? 10 : 16), sl@0: min, max, flags); sl@0: break; sl@0: case 'f': sl@0: if (cflags == DP_C_LDOUBLE) sl@0: fvalue = va_arg(args, LDOUBLE); sl@0: else sl@0: fvalue = va_arg(args, double); sl@0: fmtfp(sbuffer, buffer, &currlen, maxlen, sl@0: fvalue, min, max, flags); sl@0: break; sl@0: case 'E': sl@0: flags |= DP_F_UP; sl@0: case 'e': sl@0: if (cflags == DP_C_LDOUBLE) sl@0: fvalue = va_arg(args, LDOUBLE); sl@0: else sl@0: fvalue = va_arg(args, double); sl@0: break; sl@0: case 'G': sl@0: flags |= DP_F_UP; sl@0: case 'g': sl@0: if (cflags == DP_C_LDOUBLE) sl@0: fvalue = va_arg(args, LDOUBLE); sl@0: else sl@0: fvalue = va_arg(args, double); sl@0: break; sl@0: case 'c': sl@0: doapr_outch(sbuffer, buffer, &currlen, maxlen, sl@0: va_arg(args, int)); sl@0: break; sl@0: case 's': sl@0: strvalue = va_arg(args, char *); sl@0: if (max < 0) { sl@0: if (buffer) sl@0: max = INT_MAX; sl@0: else sl@0: max = *maxlen; sl@0: } sl@0: fmtstr(sbuffer, buffer, &currlen, maxlen, strvalue, sl@0: flags, min, max); sl@0: break; sl@0: case 'p': sl@0: value = (long)va_arg(args, void *); sl@0: fmtint(sbuffer, buffer, &currlen, maxlen, sl@0: value, 16, min, max, flags|DP_F_NUM); sl@0: break; sl@0: case 'n': /* XXX */ sl@0: if (cflags == DP_C_SHORT) { sl@0: short int *num; sl@0: num = va_arg(args, short int *); sl@0: *num = currlen; sl@0: } else if (cflags == DP_C_LONG) { /* XXX */ sl@0: long int *num; sl@0: num = va_arg(args, long int *); sl@0: *num = (long int) currlen; sl@0: } else if (cflags == DP_C_LLONG) { /* XXX */ sl@0: LLONG *num; sl@0: num = va_arg(args, LLONG *); sl@0: *num = (LLONG) currlen; sl@0: } else { sl@0: int *num; sl@0: num = va_arg(args, int *); sl@0: *num = currlen; sl@0: } sl@0: break; sl@0: case '%': sl@0: doapr_outch(sbuffer, buffer, &currlen, maxlen, ch); sl@0: break; sl@0: case 'w': sl@0: /* not supported yet, treat as next char */ sl@0: ch = *format++; sl@0: break; sl@0: default: sl@0: /* unknown, skip */ sl@0: break; sl@0: } sl@0: ch = *format++; sl@0: state = DP_S_DEFAULT; sl@0: flags = cflags = min = 0; sl@0: max = -1; sl@0: break; sl@0: case DP_S_DONE: sl@0: break; sl@0: default: sl@0: break; sl@0: } sl@0: } sl@0: *truncated = (currlen > *maxlen - 1); sl@0: if (*truncated) sl@0: currlen = *maxlen - 1; sl@0: doapr_outch(sbuffer, buffer, &currlen, maxlen, '\0'); sl@0: *retlen = currlen - 1; sl@0: return; sl@0: } sl@0: sl@0: static void sl@0: fmtstr( sl@0: char **sbuffer, sl@0: char **buffer, sl@0: size_t *currlen, sl@0: size_t *maxlen, sl@0: const char *value, sl@0: int flags, sl@0: int min, sl@0: int max) sl@0: { sl@0: int padlen, strln; sl@0: int cnt = 0; sl@0: sl@0: if (value == 0) sl@0: value = ""; sl@0: for (strln = 0; value[strln]; ++strln) sl@0: ; sl@0: padlen = min - strln; sl@0: if (padlen < 0) sl@0: padlen = 0; sl@0: if (flags & DP_F_MINUS) sl@0: padlen = -padlen; sl@0: sl@0: while ((padlen > 0) && (cnt < max)) { sl@0: doapr_outch(sbuffer, buffer, currlen, maxlen, ' '); sl@0: --padlen; sl@0: ++cnt; sl@0: } sl@0: while (*value && (cnt < max)) { sl@0: doapr_outch(sbuffer, buffer, currlen, maxlen, *value++); sl@0: ++cnt; sl@0: } sl@0: while ((padlen < 0) && (cnt < max)) { sl@0: doapr_outch(sbuffer, buffer, currlen, maxlen, ' '); sl@0: ++padlen; sl@0: ++cnt; sl@0: } sl@0: } sl@0: sl@0: static void sl@0: fmtint( sl@0: char **sbuffer, sl@0: char **buffer, sl@0: size_t *currlen, sl@0: size_t *maxlen, sl@0: LLONG value, sl@0: int base, sl@0: int min, sl@0: int max, sl@0: int flags) sl@0: { sl@0: int signvalue = 0; sl@0: const char *prefix = ""; sl@0: unsigned LLONG uvalue; sl@0: char convert[DECIMAL_SIZE(value)+3]; sl@0: int place = 0; sl@0: int spadlen = 0; sl@0: int zpadlen = 0; sl@0: int caps = 0; sl@0: sl@0: if (max < 0) sl@0: max = 0; sl@0: uvalue = value; sl@0: if (!(flags & DP_F_UNSIGNED)) { sl@0: if (value < 0) { sl@0: signvalue = '-'; sl@0: uvalue = -value; sl@0: } else if (flags & DP_F_PLUS) sl@0: signvalue = '+'; sl@0: else if (flags & DP_F_SPACE) sl@0: signvalue = ' '; sl@0: } sl@0: if (flags & DP_F_NUM) { sl@0: if (base == 8) prefix = "0"; sl@0: if (base == 16) prefix = "0x"; sl@0: } sl@0: if (flags & DP_F_UP) sl@0: caps = 1; sl@0: do { sl@0: convert[place++] = sl@0: (caps ? "0123456789ABCDEF" : "0123456789abcdef") sl@0: [uvalue % (unsigned) base]; sl@0: uvalue = (uvalue / (unsigned) base); sl@0: } while (uvalue && (place < (int)sizeof(convert))); sl@0: if (place == sizeof(convert)) sl@0: place--; sl@0: convert[place] = 0; sl@0: sl@0: zpadlen = max - place; sl@0: spadlen = min - OSSL_MAX(max, place) - (signvalue ? 1 : 0) - strlen(prefix); sl@0: if (zpadlen < 0) sl@0: zpadlen = 0; sl@0: if (spadlen < 0) sl@0: spadlen = 0; sl@0: if (flags & DP_F_ZERO) { sl@0: zpadlen = OSSL_MAX(zpadlen, spadlen); sl@0: spadlen = 0; sl@0: } sl@0: if (flags & DP_F_MINUS) sl@0: spadlen = -spadlen; sl@0: sl@0: /* spaces */ sl@0: while (spadlen > 0) { sl@0: doapr_outch(sbuffer, buffer, currlen, maxlen, ' '); sl@0: --spadlen; sl@0: } sl@0: sl@0: /* sign */ sl@0: if (signvalue) sl@0: doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue); sl@0: sl@0: /* prefix */ sl@0: while (*prefix) { sl@0: doapr_outch(sbuffer, buffer, currlen, maxlen, *prefix); sl@0: prefix++; sl@0: } sl@0: sl@0: /* zeros */ sl@0: if (zpadlen > 0) { sl@0: while (zpadlen > 0) { sl@0: doapr_outch(sbuffer, buffer, currlen, maxlen, '0'); sl@0: --zpadlen; sl@0: } sl@0: } sl@0: /* digits */ sl@0: while (place > 0) sl@0: doapr_outch(sbuffer, buffer, currlen, maxlen, convert[--place]); sl@0: sl@0: /* left justified spaces */ sl@0: while (spadlen < 0) { sl@0: doapr_outch(sbuffer, buffer, currlen, maxlen, ' '); sl@0: ++spadlen; sl@0: } sl@0: return; sl@0: } sl@0: sl@0: static LDOUBLE sl@0: abs_val(LDOUBLE value) sl@0: { sl@0: LDOUBLE result = value; sl@0: if (value < 0) sl@0: result = -value; sl@0: return result; sl@0: } sl@0: sl@0: static LDOUBLE sl@0: pow_10(int in_exp) sl@0: { sl@0: LDOUBLE result = 1; sl@0: while (in_exp) { sl@0: result *= 10; sl@0: in_exp--; sl@0: } sl@0: return result; sl@0: } sl@0: sl@0: static long sl@0: roundv(LDOUBLE value) sl@0: { sl@0: long intpart; sl@0: intpart = (long) value; sl@0: value = value - intpart; sl@0: if (value >= 0.5) sl@0: intpart++; sl@0: return intpart; sl@0: } sl@0: sl@0: static void sl@0: fmtfp( sl@0: char **sbuffer, sl@0: char **buffer, sl@0: size_t *currlen, sl@0: size_t *maxlen, sl@0: LDOUBLE fvalue, sl@0: int min, sl@0: int max, sl@0: int flags) sl@0: { sl@0: int signvalue = 0; sl@0: LDOUBLE ufvalue; sl@0: char iconvert[20]; sl@0: char fconvert[20]; sl@0: int iplace = 0; sl@0: int fplace = 0; sl@0: int padlen = 0; sl@0: int zpadlen = 0; sl@0: int caps = 0; sl@0: long intpart; sl@0: long fracpart; sl@0: long max10; sl@0: sl@0: if (max < 0) sl@0: max = 6; sl@0: ufvalue = abs_val(fvalue); sl@0: if (fvalue < 0) sl@0: signvalue = '-'; sl@0: else if (flags & DP_F_PLUS) sl@0: signvalue = '+'; sl@0: else if (flags & DP_F_SPACE) sl@0: signvalue = ' '; sl@0: sl@0: intpart = (long)ufvalue; sl@0: sl@0: /* sorry, we only support 9 digits past the decimal because of our sl@0: conversion method */ sl@0: if (max > 9) sl@0: max = 9; sl@0: sl@0: /* we "cheat" by converting the fractional part to integer by sl@0: multiplying by a factor of 10 */ sl@0: max10 = roundv(pow_10(max)); sl@0: fracpart = roundv(pow_10(max) * (ufvalue - intpart)); sl@0: sl@0: if (fracpart >= max10) { sl@0: intpart++; sl@0: fracpart -= max10; sl@0: } sl@0: sl@0: /* convert integer part */ sl@0: do { sl@0: iconvert[iplace++] = sl@0: (caps ? "0123456789ABCDEF" sl@0: : "0123456789abcdef")[intpart % 10]; sl@0: intpart = (intpart / 10); sl@0: } while (intpart && (iplace < (int)sizeof(iconvert))); sl@0: if (iplace == sizeof iconvert) sl@0: iplace--; sl@0: iconvert[iplace] = 0; sl@0: sl@0: /* convert fractional part */ sl@0: do { sl@0: fconvert[fplace++] = sl@0: (caps ? "0123456789ABCDEF" sl@0: : "0123456789abcdef")[fracpart % 10]; sl@0: fracpart = (fracpart / 10); sl@0: } while (fplace < max); sl@0: if (fplace == sizeof fconvert) sl@0: fplace--; sl@0: fconvert[fplace] = 0; sl@0: sl@0: /* -1 for decimal point, another -1 if we are printing a sign */ sl@0: padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0); sl@0: zpadlen = max - fplace; sl@0: if (zpadlen < 0) sl@0: zpadlen = 0; sl@0: if (padlen < 0) sl@0: padlen = 0; sl@0: if (flags & DP_F_MINUS) sl@0: padlen = -padlen; sl@0: sl@0: if ((flags & DP_F_ZERO) && (padlen > 0)) { sl@0: if (signvalue) { sl@0: doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue); sl@0: --padlen; sl@0: signvalue = 0; sl@0: } sl@0: while (padlen > 0) { sl@0: doapr_outch(sbuffer, buffer, currlen, maxlen, '0'); sl@0: --padlen; sl@0: } sl@0: } sl@0: while (padlen > 0) { sl@0: doapr_outch(sbuffer, buffer, currlen, maxlen, ' '); sl@0: --padlen; sl@0: } sl@0: if (signvalue) sl@0: doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue); sl@0: sl@0: while (iplace > 0) sl@0: doapr_outch(sbuffer, buffer, currlen, maxlen, iconvert[--iplace]); sl@0: sl@0: /* sl@0: * Decimal point. This should probably use locale to find the correct sl@0: * char to print out. sl@0: */ sl@0: if (max > 0 || (flags & DP_F_NUM)) { sl@0: doapr_outch(sbuffer, buffer, currlen, maxlen, '.'); sl@0: sl@0: while (fplace > 0) sl@0: doapr_outch(sbuffer, buffer, currlen, maxlen, fconvert[--fplace]); sl@0: } sl@0: while (zpadlen > 0) { sl@0: doapr_outch(sbuffer, buffer, currlen, maxlen, '0'); sl@0: --zpadlen; sl@0: } sl@0: sl@0: while (padlen < 0) { sl@0: doapr_outch(sbuffer, buffer, currlen, maxlen, ' '); sl@0: ++padlen; sl@0: } sl@0: } sl@0: sl@0: static void sl@0: doapr_outch( sl@0: char **sbuffer, sl@0: char **buffer, sl@0: size_t *currlen, sl@0: size_t *maxlen, sl@0: int c) sl@0: { sl@0: /* If we haven't at least one buffer, someone has doe a big booboo */ sl@0: assert(*sbuffer != NULL || buffer != NULL); sl@0: sl@0: if (buffer) { sl@0: while (*currlen >= *maxlen) { sl@0: if (*buffer == NULL) { sl@0: if (*maxlen == 0) sl@0: *maxlen = 1024; sl@0: *buffer = OPENSSL_malloc(*maxlen); sl@0: if (*currlen > 0) { sl@0: assert(*sbuffer != NULL); sl@0: memcpy(*buffer, *sbuffer, *currlen); sl@0: } sl@0: *sbuffer = NULL; sl@0: } else { sl@0: *maxlen += 1024; sl@0: *buffer = OPENSSL_realloc(*buffer, *maxlen); sl@0: } sl@0: } sl@0: /* What to do if *buffer is NULL? */ sl@0: assert(*sbuffer != NULL || *buffer != NULL); sl@0: } sl@0: sl@0: if (*currlen < *maxlen) { sl@0: if (*sbuffer) sl@0: (*sbuffer)[(*currlen)++] = (char)c; sl@0: else sl@0: (*buffer)[(*currlen)++] = (char)c; sl@0: } sl@0: sl@0: return; sl@0: } sl@0: sl@0: /***************************************************************************/ sl@0: sl@0: EXPORT_C int BIO_printf (BIO *bio, const char *format, ...) sl@0: { sl@0: va_list args; sl@0: int ret; sl@0: sl@0: va_start(args, format); sl@0: sl@0: ret = BIO_vprintf(bio, format, args); sl@0: sl@0: va_end(args); sl@0: return(ret); sl@0: } sl@0: sl@0: EXPORT_C int BIO_vprintf (BIO *bio, const char *format, va_list args) sl@0: { sl@0: int ret; sl@0: size_t retlen; sl@0: #ifndef SYMBIAN sl@0: char hugebuf[1024*2]; /* Was previously 10k, which is unreasonable sl@0: in small-stack environments, like threads sl@0: or DOS programs. */ sl@0: #else sl@0: char hugebuf[512]; sl@0: #endif sl@0: char *hugebufp = hugebuf; sl@0: size_t hugebufsize = sizeof(hugebuf); sl@0: char *dynbuf = NULL; sl@0: int ignored; sl@0: sl@0: dynbuf = NULL; sl@0: CRYPTO_push_info("doapr()"); sl@0: _dopr(&hugebufp, &dynbuf, &hugebufsize, sl@0: &retlen, &ignored, format, args); sl@0: if (dynbuf) sl@0: { sl@0: ret=BIO_write(bio, dynbuf, (int)retlen); sl@0: OPENSSL_free(dynbuf); sl@0: } sl@0: else sl@0: { sl@0: ret=BIO_write(bio, hugebuf, (int)retlen); sl@0: } sl@0: CRYPTO_pop_info(); sl@0: return(ret); sl@0: } sl@0: sl@0: /* As snprintf is not available everywhere, we provide our own implementation. sl@0: * This function has nothing to do with BIOs, but it's closely related sl@0: * to BIO_printf, and we need *some* name prefix ... sl@0: * (XXX the function should be renamed, but to what?) */ sl@0: EXPORT_C int BIO_snprintf(char *buf, size_t n, const char *format, ...) sl@0: { sl@0: va_list args; sl@0: int ret; sl@0: sl@0: va_start(args, format); sl@0: sl@0: ret = BIO_vsnprintf(buf, n, format, args); sl@0: sl@0: va_end(args); sl@0: return(ret); sl@0: } sl@0: sl@0: EXPORT_C int BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args) sl@0: { sl@0: size_t retlen; sl@0: int truncated; sl@0: sl@0: _dopr(&buf, NULL, &n, &retlen, &truncated, format, args); sl@0: sl@0: if (truncated) sl@0: /* In case of truncation, return -1 like traditional snprintf. sl@0: * (Current drafts for ISO/IEC 9899 say snprintf should return sl@0: * the number of characters that would have been written, sl@0: * had the buffer been large enough.) */ sl@0: return -1; sl@0: else sl@0: return (retlen <= INT_MAX) ? (int)retlen : -1; sl@0: }