os/ossrv/ssl/libcrypto/src/crypto/bio/b_print.c
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/ossrv/ssl/libcrypto/src/crypto/bio/b_print.c	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,848 @@
     1.4 +/* crypto/bio/b_print.c */
     1.5 +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
     1.6 + * All rights reserved.
     1.7 + *
     1.8 + * This package is an SSL implementation written
     1.9 + * by Eric Young (eay@cryptsoft.com).
    1.10 + * The implementation was written so as to conform with Netscapes SSL.
    1.11 + * 
    1.12 + * This library is free for commercial and non-commercial use as long as
    1.13 + * the following conditions are aheared to.  The following conditions
    1.14 + * apply to all code found in this distribution, be it the RC4, RSA,
    1.15 + * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
    1.16 + * included with this distribution is covered by the same copyright terms
    1.17 + * except that the holder is Tim Hudson (tjh@cryptsoft.com).
    1.18 + * 
    1.19 + * Copyright remains Eric Young's, and as such any Copyright notices in
    1.20 + * the code are not to be removed.
    1.21 + * If this package is used in a product, Eric Young should be given attribution
    1.22 + * as the author of the parts of the library used.
    1.23 + * This can be in the form of a textual message at program startup or
    1.24 + * in documentation (online or textual) provided with the package.
    1.25 + * 
    1.26 + * Redistribution and use in source and binary forms, with or without
    1.27 + * modification, are permitted provided that the following conditions
    1.28 + * are met:
    1.29 + * 1. Redistributions of source code must retain the copyright
    1.30 + *    notice, this list of conditions and the following disclaimer.
    1.31 + * 2. Redistributions in binary form must reproduce the above copyright
    1.32 + *    notice, this list of conditions and the following disclaimer in the
    1.33 + *    documentation and/or other materials provided with the distribution.
    1.34 + * 3. All advertising materials mentioning features or use of this software
    1.35 + *    must display the following acknowledgement:
    1.36 + *    "This product includes cryptographic software written by
    1.37 + *     Eric Young (eay@cryptsoft.com)"
    1.38 + *    The word 'cryptographic' can be left out if the rouines from the library
    1.39 + *    being used are not cryptographic related :-).
    1.40 + * 4. If you include any Windows specific code (or a derivative thereof) from 
    1.41 + *    the apps directory (application code) you must include an acknowledgement:
    1.42 + *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
    1.43 + * 
    1.44 + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
    1.45 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    1.46 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    1.47 + * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
    1.48 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    1.49 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    1.50 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    1.51 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    1.52 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    1.53 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    1.54 + * SUCH DAMAGE.
    1.55 + * 
    1.56 + * The licence and distribution terms for any publically available version or
    1.57 + * derivative of this code cannot be changed.  i.e. this code cannot simply be
    1.58 + * copied and put under another distribution licence
    1.59 + * [including the GNU Public Licence.]
    1.60 + */
    1.61 +/*
    1.62 + © Portions copyright (c) 2006 Nokia Corporation.  All rights reserved.
    1.63 + */
    1.64 +/* disable assert() unless BIO_DEBUG has been defined */
    1.65 +#ifndef BIO_DEBUG
    1.66 +# ifndef NDEBUG
    1.67 +#  define NDEBUG
    1.68 +# endif
    1.69 +#endif
    1.70 +
    1.71 +/* 
    1.72 + * Stolen from tjh's ssl/ssl_trc.c stuff.
    1.73 + */
    1.74 +
    1.75 +#include <stdio.h>
    1.76 +#include <string.h>
    1.77 +#include <ctype.h>
    1.78 +#include <assert.h>
    1.79 +#include <limits.h>
    1.80 +#include "cryptlib.h"
    1.81 +#ifndef NO_SYS_TYPES_H
    1.82 +#include <sys/types.h>
    1.83 +#endif
    1.84 +#include <openssl/bn.h>         /* To get BN_LLONG properly defined */
    1.85 +#include <openssl/bio.h>
    1.86 +
    1.87 +#if defined(BN_LLONG) || defined(SIXTY_FOUR_BIT)
    1.88 +# ifndef HAVE_LONG_LONG
    1.89 +#  define HAVE_LONG_LONG 1
    1.90 +# endif
    1.91 +#endif
    1.92 +
    1.93 +/***************************************************************************/
    1.94 +
    1.95 +/*
    1.96 + * Copyright Patrick Powell 1995
    1.97 + * This code is based on code written by Patrick Powell <papowell@astart.com>
    1.98 + * It may be used for any purpose as long as this notice remains intact
    1.99 + * on all source code distributions.
   1.100 + */
   1.101 +
   1.102 +/*
   1.103 + * This code contains numerious changes and enhancements which were
   1.104 + * made by lots of contributors over the last years to Patrick Powell's
   1.105 + * original code:
   1.106 + *
   1.107 + * o Patrick Powell <papowell@astart.com>      (1995)
   1.108 + * o Brandon Long <blong@fiction.net>          (1996, for Mutt)
   1.109 + * o Thomas Roessler <roessler@guug.de>        (1998, for Mutt)
   1.110 + * o Michael Elkins <me@cs.hmc.edu>            (1998, for Mutt)
   1.111 + * o Andrew Tridgell <tridge@samba.org>        (1998, for Samba)
   1.112 + * o Luke Mewburn <lukem@netbsd.org>           (1999, for LukemFTP)
   1.113 + * o Ralf S. Engelschall <rse@engelschall.com> (1999, for Pth)
   1.114 + * o ...                                       (for OpenSSL)
   1.115 + */
   1.116 +
   1.117 +#ifdef HAVE_LONG_DOUBLE
   1.118 +#define LDOUBLE long double
   1.119 +#else
   1.120 +#define LDOUBLE double
   1.121 +#endif
   1.122 +
   1.123 +#if HAVE_LONG_LONG
   1.124 +# if defined(OPENSSL_SYS_WIN32) && !defined(__GNUC__)
   1.125 +# define LLONG __int64
   1.126 +# else
   1.127 +# define LLONG long long
   1.128 +# endif
   1.129 +#else
   1.130 +#define LLONG long
   1.131 +#endif
   1.132 +
   1.133 +static void fmtstr     (char **, char **, size_t *, size_t *,
   1.134 +			const char *, int, int, int);
   1.135 +static void fmtint     (char **, char **, size_t *, size_t *,
   1.136 +			LLONG, int, int, int, int);
   1.137 +static void fmtfp      (char **, char **, size_t *, size_t *,
   1.138 +			LDOUBLE, int, int, int);
   1.139 +static void doapr_outch (char **, char **, size_t *, size_t *, int);
   1.140 +static void _dopr(char **sbuffer, char **buffer,
   1.141 +		  size_t *maxlen, size_t *retlen, int *truncated,
   1.142 +		  const char *format, va_list args);
   1.143 +
   1.144 +/* format read states */
   1.145 +#define DP_S_DEFAULT    0
   1.146 +#define DP_S_FLAGS      1
   1.147 +#define DP_S_MIN        2
   1.148 +#define DP_S_DOT        3
   1.149 +#define DP_S_MAX        4
   1.150 +#define DP_S_MOD        5
   1.151 +#define DP_S_CONV       6
   1.152 +#define DP_S_DONE       7
   1.153 +
   1.154 +/* format flags - Bits */
   1.155 +#define DP_F_MINUS      (1 << 0)
   1.156 +#define DP_F_PLUS       (1 << 1)
   1.157 +#define DP_F_SPACE      (1 << 2)
   1.158 +#define DP_F_NUM        (1 << 3)
   1.159 +#define DP_F_ZERO       (1 << 4)
   1.160 +#define DP_F_UP         (1 << 5)
   1.161 +#define DP_F_UNSIGNED   (1 << 6)
   1.162 +
   1.163 +/* conversion flags */
   1.164 +#define DP_C_SHORT      1
   1.165 +#define DP_C_LONG       2
   1.166 +#define DP_C_LDOUBLE    3
   1.167 +#define DP_C_LLONG      4
   1.168 +
   1.169 +/* some handy macros */
   1.170 +#define char_to_int(p) (p - '0')
   1.171 +#define OSSL_MAX(p,q) ((p >= q) ? p : q)
   1.172 +
   1.173 +static void
   1.174 +_dopr(
   1.175 +    char **sbuffer,
   1.176 +    char **buffer,
   1.177 +    size_t *maxlen,
   1.178 +    size_t *retlen,
   1.179 +    int *truncated,
   1.180 +    const char *format,
   1.181 +    va_list args)
   1.182 +{
   1.183 +    char ch;
   1.184 +    LLONG value;
   1.185 +    LDOUBLE fvalue;
   1.186 +    char *strvalue;
   1.187 +    int min;
   1.188 +    int max;
   1.189 +    int state;
   1.190 +    int flags;
   1.191 +    int cflags;
   1.192 +    size_t currlen;
   1.193 +
   1.194 +    state = DP_S_DEFAULT;
   1.195 +    flags = currlen = cflags = min = 0;
   1.196 +    max = -1;
   1.197 +    ch = *format++;
   1.198 +
   1.199 +    while (state != DP_S_DONE) {
   1.200 +        if (ch == '\0' || (buffer == NULL && currlen >= *maxlen))
   1.201 +            state = DP_S_DONE;
   1.202 +
   1.203 +        switch (state) {
   1.204 +        case DP_S_DEFAULT:
   1.205 +            if (ch == '%')
   1.206 +                state = DP_S_FLAGS;
   1.207 +            else
   1.208 +                doapr_outch(sbuffer,buffer, &currlen, maxlen, ch);
   1.209 +            ch = *format++;
   1.210 +            break;
   1.211 +        case DP_S_FLAGS:
   1.212 +            switch (ch) {
   1.213 +            case '-':
   1.214 +                flags |= DP_F_MINUS;
   1.215 +                ch = *format++;
   1.216 +                break;
   1.217 +            case '+':
   1.218 +                flags |= DP_F_PLUS;
   1.219 +                ch = *format++;
   1.220 +                break;
   1.221 +            case ' ':
   1.222 +                flags |= DP_F_SPACE;
   1.223 +                ch = *format++;
   1.224 +                break;
   1.225 +            case '#':
   1.226 +                flags |= DP_F_NUM;
   1.227 +                ch = *format++;
   1.228 +                break;
   1.229 +            case '0':
   1.230 +                flags |= DP_F_ZERO;
   1.231 +                ch = *format++;
   1.232 +                break;
   1.233 +            default:
   1.234 +                state = DP_S_MIN;
   1.235 +                break;
   1.236 +            }
   1.237 +            break;
   1.238 +        case DP_S_MIN:
   1.239 +            if (isdigit((unsigned char)ch)) {
   1.240 +                min = 10 * min + char_to_int(ch);
   1.241 +                ch = *format++;
   1.242 +            } else if (ch == '*') {
   1.243 +                min = va_arg(args, int);
   1.244 +                ch = *format++;
   1.245 +                state = DP_S_DOT;
   1.246 +            } else
   1.247 +                state = DP_S_DOT;
   1.248 +            break;
   1.249 +        case DP_S_DOT:
   1.250 +            if (ch == '.') {
   1.251 +                state = DP_S_MAX;
   1.252 +                ch = *format++;
   1.253 +            } else
   1.254 +                state = DP_S_MOD;
   1.255 +            break;
   1.256 +        case DP_S_MAX:
   1.257 +            if (isdigit((unsigned char)ch)) {
   1.258 +                if (max < 0)
   1.259 +                    max = 0;
   1.260 +                max = 10 * max + char_to_int(ch);
   1.261 +                ch = *format++;
   1.262 +            } else if (ch == '*') {
   1.263 +                max = va_arg(args, int);
   1.264 +                ch = *format++;
   1.265 +                state = DP_S_MOD;
   1.266 +            } else
   1.267 +                state = DP_S_MOD;
   1.268 +            break;
   1.269 +        case DP_S_MOD:
   1.270 +            switch (ch) {
   1.271 +            case 'h':
   1.272 +                cflags = DP_C_SHORT;
   1.273 +                ch = *format++;
   1.274 +                break;
   1.275 +            case 'l':
   1.276 +                if (*format == 'l') {
   1.277 +                    cflags = DP_C_LLONG;
   1.278 +                    format++;
   1.279 +                } else
   1.280 +                    cflags = DP_C_LONG;
   1.281 +                ch = *format++;
   1.282 +                break;
   1.283 +            case 'q':
   1.284 +                cflags = DP_C_LLONG;
   1.285 +                ch = *format++;
   1.286 +                break;
   1.287 +            case 'L':
   1.288 +                cflags = DP_C_LDOUBLE;
   1.289 +                ch = *format++;
   1.290 +                break;
   1.291 +            default:
   1.292 +                break;
   1.293 +            }
   1.294 +            state = DP_S_CONV;
   1.295 +            break;
   1.296 +        case DP_S_CONV:
   1.297 +            switch (ch) {
   1.298 +            case 'd':
   1.299 +            case 'i':
   1.300 +                switch (cflags) {
   1.301 +                case DP_C_SHORT:
   1.302 +                    value = (short int)va_arg(args, int);
   1.303 +                    break;
   1.304 +                case DP_C_LONG:
   1.305 +                    value = va_arg(args, long int);
   1.306 +                    break;
   1.307 +                case DP_C_LLONG:
   1.308 +                    value = va_arg(args, LLONG);
   1.309 +                    break;
   1.310 +                default:
   1.311 +                    value = va_arg(args, int);
   1.312 +                    break;
   1.313 +                }
   1.314 +                fmtint(sbuffer, buffer, &currlen, maxlen,
   1.315 +                       value, 10, min, max, flags);
   1.316 +                break;
   1.317 +            case 'X':
   1.318 +                flags |= DP_F_UP;
   1.319 +                /* FALLTHROUGH */
   1.320 +            case 'x':
   1.321 +            case 'o':
   1.322 +            case 'u':
   1.323 +                flags |= DP_F_UNSIGNED;
   1.324 +                switch (cflags) {
   1.325 +                case DP_C_SHORT:
   1.326 +                    value = (unsigned short int)va_arg(args, unsigned int);
   1.327 +                    break;
   1.328 +                case DP_C_LONG:
   1.329 +                    value = (LLONG) va_arg(args,
   1.330 +                        unsigned long int);
   1.331 +                    break;
   1.332 +                case DP_C_LLONG:
   1.333 +                    value = va_arg(args, unsigned LLONG);
   1.334 +                    break;
   1.335 +                default:
   1.336 +                    value = (LLONG) va_arg(args,
   1.337 +                        unsigned int);
   1.338 +                    break;
   1.339 +                }
   1.340 +                fmtint(sbuffer, buffer, &currlen, maxlen, value,
   1.341 +                       ch == 'o' ? 8 : (ch == 'u' ? 10 : 16),
   1.342 +                       min, max, flags);
   1.343 +                break;
   1.344 +            case 'f':
   1.345 +                if (cflags == DP_C_LDOUBLE)
   1.346 +                    fvalue = va_arg(args, LDOUBLE);
   1.347 +                else
   1.348 +                    fvalue = va_arg(args, double);
   1.349 +                fmtfp(sbuffer, buffer, &currlen, maxlen,
   1.350 +                      fvalue, min, max, flags);
   1.351 +                break;
   1.352 +            case 'E':
   1.353 +                flags |= DP_F_UP;
   1.354 +            case 'e':
   1.355 +                if (cflags == DP_C_LDOUBLE)
   1.356 +                    fvalue = va_arg(args, LDOUBLE);
   1.357 +                else
   1.358 +                    fvalue = va_arg(args, double);
   1.359 +                break;
   1.360 +            case 'G':
   1.361 +                flags |= DP_F_UP;
   1.362 +            case 'g':
   1.363 +                if (cflags == DP_C_LDOUBLE)
   1.364 +                    fvalue = va_arg(args, LDOUBLE);
   1.365 +                else
   1.366 +                    fvalue = va_arg(args, double);
   1.367 +                break;
   1.368 +            case 'c':
   1.369 +                doapr_outch(sbuffer, buffer, &currlen, maxlen,
   1.370 +                    va_arg(args, int));
   1.371 +                break;
   1.372 +            case 's':
   1.373 +                strvalue = va_arg(args, char *);
   1.374 +                if (max < 0) {
   1.375 +		    if (buffer)
   1.376 +			max = INT_MAX;
   1.377 +		    else
   1.378 +			max = *maxlen;
   1.379 +		}
   1.380 +                fmtstr(sbuffer, buffer, &currlen, maxlen, strvalue,
   1.381 +                       flags, min, max);
   1.382 +                break;
   1.383 +            case 'p':
   1.384 +                value = (long)va_arg(args, void *);
   1.385 +                fmtint(sbuffer, buffer, &currlen, maxlen,
   1.386 +                    value, 16, min, max, flags|DP_F_NUM);
   1.387 +                break;
   1.388 +            case 'n': /* XXX */
   1.389 +                if (cflags == DP_C_SHORT) {
   1.390 +                    short int *num;
   1.391 +                    num = va_arg(args, short int *);
   1.392 +                    *num = currlen;
   1.393 +                } else if (cflags == DP_C_LONG) { /* XXX */
   1.394 +                    long int *num;
   1.395 +                    num = va_arg(args, long int *);
   1.396 +                    *num = (long int) currlen;
   1.397 +                } else if (cflags == DP_C_LLONG) { /* XXX */
   1.398 +                    LLONG *num;
   1.399 +                    num = va_arg(args, LLONG *);
   1.400 +                    *num = (LLONG) currlen;
   1.401 +                } else {
   1.402 +                    int    *num;
   1.403 +                    num = va_arg(args, int *);
   1.404 +                    *num = currlen;
   1.405 +                }
   1.406 +                break;
   1.407 +            case '%':
   1.408 +                doapr_outch(sbuffer, buffer, &currlen, maxlen, ch);
   1.409 +                break;
   1.410 +            case 'w':
   1.411 +                /* not supported yet, treat as next char */
   1.412 +                ch = *format++;
   1.413 +                break;
   1.414 +            default:
   1.415 +                /* unknown, skip */
   1.416 +                break;
   1.417 +            }
   1.418 +            ch = *format++;
   1.419 +            state = DP_S_DEFAULT;
   1.420 +            flags = cflags = min = 0;
   1.421 +            max = -1;
   1.422 +            break;
   1.423 +        case DP_S_DONE:
   1.424 +            break;
   1.425 +        default:
   1.426 +            break;
   1.427 +        }
   1.428 +    }
   1.429 +    *truncated = (currlen > *maxlen - 1);
   1.430 +    if (*truncated)
   1.431 +        currlen = *maxlen - 1;
   1.432 +    doapr_outch(sbuffer, buffer, &currlen, maxlen, '\0');
   1.433 +    *retlen = currlen - 1;
   1.434 +    return;
   1.435 +}
   1.436 +
   1.437 +static void
   1.438 +fmtstr(
   1.439 +    char **sbuffer,
   1.440 +    char **buffer,
   1.441 +    size_t *currlen,
   1.442 +    size_t *maxlen,
   1.443 +    const char *value,
   1.444 +    int flags,
   1.445 +    int min,
   1.446 +    int max)
   1.447 +{
   1.448 +    int padlen, strln;
   1.449 +    int cnt = 0;
   1.450 +
   1.451 +    if (value == 0)
   1.452 +        value = "<NULL>";
   1.453 +    for (strln = 0; value[strln]; ++strln)
   1.454 +        ;
   1.455 +    padlen = min - strln;
   1.456 +    if (padlen < 0)
   1.457 +        padlen = 0;
   1.458 +    if (flags & DP_F_MINUS)
   1.459 +        padlen = -padlen;
   1.460 +
   1.461 +    while ((padlen > 0) && (cnt < max)) {
   1.462 +        doapr_outch(sbuffer, buffer, currlen, maxlen, ' ');
   1.463 +        --padlen;
   1.464 +        ++cnt;
   1.465 +    }
   1.466 +    while (*value && (cnt < max)) {
   1.467 +        doapr_outch(sbuffer, buffer, currlen, maxlen, *value++);
   1.468 +        ++cnt;
   1.469 +    }
   1.470 +    while ((padlen < 0) && (cnt < max)) {
   1.471 +        doapr_outch(sbuffer, buffer, currlen, maxlen, ' ');
   1.472 +        ++padlen;
   1.473 +        ++cnt;
   1.474 +    }
   1.475 +}
   1.476 +
   1.477 +static void
   1.478 +fmtint(
   1.479 +    char **sbuffer,
   1.480 +    char **buffer,
   1.481 +    size_t *currlen,
   1.482 +    size_t *maxlen,
   1.483 +    LLONG value,
   1.484 +    int base,
   1.485 +    int min,
   1.486 +    int max,
   1.487 +    int flags)
   1.488 +{
   1.489 +    int signvalue = 0;
   1.490 +    const char *prefix = "";
   1.491 +    unsigned LLONG uvalue;
   1.492 +    char convert[DECIMAL_SIZE(value)+3];
   1.493 +    int place = 0;
   1.494 +    int spadlen = 0;
   1.495 +    int zpadlen = 0;
   1.496 +    int caps = 0;
   1.497 +
   1.498 +    if (max < 0)
   1.499 +        max = 0;
   1.500 +    uvalue = value;
   1.501 +    if (!(flags & DP_F_UNSIGNED)) {
   1.502 +        if (value < 0) {
   1.503 +            signvalue = '-';
   1.504 +            uvalue = -value;
   1.505 +        } else if (flags & DP_F_PLUS)
   1.506 +            signvalue = '+';
   1.507 +        else if (flags & DP_F_SPACE)
   1.508 +            signvalue = ' ';
   1.509 +    }
   1.510 +    if (flags & DP_F_NUM) {
   1.511 +	if (base == 8) prefix = "0";
   1.512 +	if (base == 16) prefix = "0x";
   1.513 +    }
   1.514 +    if (flags & DP_F_UP)
   1.515 +        caps = 1;
   1.516 +    do {
   1.517 +        convert[place++] =
   1.518 +            (caps ? "0123456789ABCDEF" : "0123456789abcdef")
   1.519 +            [uvalue % (unsigned) base];
   1.520 +        uvalue = (uvalue / (unsigned) base);
   1.521 +    } while (uvalue && (place < (int)sizeof(convert)));
   1.522 +    if (place == sizeof(convert))
   1.523 +        place--;
   1.524 +    convert[place] = 0;
   1.525 +
   1.526 +    zpadlen = max - place;
   1.527 +    spadlen = min - OSSL_MAX(max, place) - (signvalue ? 1 : 0) - strlen(prefix);
   1.528 +    if (zpadlen < 0)
   1.529 +        zpadlen = 0;
   1.530 +    if (spadlen < 0)
   1.531 +        spadlen = 0;
   1.532 +    if (flags & DP_F_ZERO) {
   1.533 +        zpadlen = OSSL_MAX(zpadlen, spadlen);
   1.534 +        spadlen = 0;
   1.535 +    }
   1.536 +    if (flags & DP_F_MINUS)
   1.537 +        spadlen = -spadlen;
   1.538 +
   1.539 +    /* spaces */
   1.540 +    while (spadlen > 0) {
   1.541 +        doapr_outch(sbuffer, buffer, currlen, maxlen, ' ');
   1.542 +        --spadlen;
   1.543 +    }
   1.544 +
   1.545 +    /* sign */
   1.546 +    if (signvalue)
   1.547 +        doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue);
   1.548 +
   1.549 +    /* prefix */
   1.550 +    while (*prefix) {
   1.551 +	doapr_outch(sbuffer, buffer, currlen, maxlen, *prefix);
   1.552 +	prefix++;
   1.553 +    }
   1.554 +
   1.555 +    /* zeros */
   1.556 +    if (zpadlen > 0) {
   1.557 +        while (zpadlen > 0) {
   1.558 +            doapr_outch(sbuffer, buffer, currlen, maxlen, '0');
   1.559 +            --zpadlen;
   1.560 +        }
   1.561 +    }
   1.562 +    /* digits */
   1.563 +    while (place > 0)
   1.564 +        doapr_outch(sbuffer, buffer, currlen, maxlen, convert[--place]);
   1.565 +
   1.566 +    /* left justified spaces */
   1.567 +    while (spadlen < 0) {
   1.568 +        doapr_outch(sbuffer, buffer, currlen, maxlen, ' ');
   1.569 +        ++spadlen;
   1.570 +    }
   1.571 +    return;
   1.572 +}
   1.573 +
   1.574 +static LDOUBLE
   1.575 +abs_val(LDOUBLE value)
   1.576 +{
   1.577 +    LDOUBLE result = value;
   1.578 +    if (value < 0)
   1.579 +        result = -value;
   1.580 +    return result;
   1.581 +}
   1.582 +
   1.583 +static LDOUBLE
   1.584 +pow_10(int in_exp)
   1.585 +{
   1.586 +    LDOUBLE result = 1;
   1.587 +    while (in_exp) {
   1.588 +        result *= 10;
   1.589 +        in_exp--;
   1.590 +    }
   1.591 +    return result;
   1.592 +}
   1.593 +
   1.594 +static long
   1.595 +roundv(LDOUBLE value)
   1.596 +{
   1.597 +    long intpart;
   1.598 +    intpart = (long) value;
   1.599 +    value = value - intpart;
   1.600 +    if (value >= 0.5)
   1.601 +        intpart++;
   1.602 +    return intpart;
   1.603 +}
   1.604 +
   1.605 +static void
   1.606 +fmtfp(
   1.607 +    char **sbuffer,
   1.608 +    char **buffer,
   1.609 +    size_t *currlen,
   1.610 +    size_t *maxlen,
   1.611 +    LDOUBLE fvalue,
   1.612 +    int min,
   1.613 +    int max,
   1.614 +    int flags)
   1.615 +{
   1.616 +    int signvalue = 0;
   1.617 +    LDOUBLE ufvalue;
   1.618 +    char iconvert[20];
   1.619 +    char fconvert[20];
   1.620 +    int iplace = 0;
   1.621 +    int fplace = 0;
   1.622 +    int padlen = 0;
   1.623 +    int zpadlen = 0;
   1.624 +    int caps = 0;
   1.625 +    long intpart;
   1.626 +    long fracpart;
   1.627 +    long max10;
   1.628 +
   1.629 +    if (max < 0)
   1.630 +        max = 6;
   1.631 +    ufvalue = abs_val(fvalue);
   1.632 +    if (fvalue < 0)
   1.633 +        signvalue = '-';
   1.634 +    else if (flags & DP_F_PLUS)
   1.635 +        signvalue = '+';
   1.636 +    else if (flags & DP_F_SPACE)
   1.637 +        signvalue = ' ';
   1.638 +
   1.639 +    intpart = (long)ufvalue;
   1.640 +
   1.641 +    /* sorry, we only support 9 digits past the decimal because of our
   1.642 +       conversion method */
   1.643 +    if (max > 9)
   1.644 +        max = 9;
   1.645 +
   1.646 +    /* we "cheat" by converting the fractional part to integer by
   1.647 +       multiplying by a factor of 10 */
   1.648 +    max10 = roundv(pow_10(max));
   1.649 +    fracpart = roundv(pow_10(max) * (ufvalue - intpart));
   1.650 +
   1.651 +    if (fracpart >= max10) {
   1.652 +        intpart++;
   1.653 +        fracpart -= max10;
   1.654 +    }
   1.655 +
   1.656 +    /* convert integer part */
   1.657 +    do {
   1.658 +        iconvert[iplace++] =
   1.659 +            (caps ? "0123456789ABCDEF"
   1.660 +              : "0123456789abcdef")[intpart % 10];
   1.661 +        intpart = (intpart / 10);
   1.662 +    } while (intpart && (iplace < (int)sizeof(iconvert)));
   1.663 +    if (iplace == sizeof iconvert)
   1.664 +        iplace--;
   1.665 +    iconvert[iplace] = 0;
   1.666 +
   1.667 +    /* convert fractional part */
   1.668 +    do {
   1.669 +        fconvert[fplace++] =
   1.670 +            (caps ? "0123456789ABCDEF"
   1.671 +              : "0123456789abcdef")[fracpart % 10];
   1.672 +        fracpart = (fracpart / 10);
   1.673 +    } while (fplace < max);
   1.674 +    if (fplace == sizeof fconvert)
   1.675 +        fplace--;
   1.676 +    fconvert[fplace] = 0;
   1.677 +
   1.678 +    /* -1 for decimal point, another -1 if we are printing a sign */
   1.679 +    padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0);
   1.680 +    zpadlen = max - fplace;
   1.681 +    if (zpadlen < 0)
   1.682 +        zpadlen = 0;
   1.683 +    if (padlen < 0)
   1.684 +        padlen = 0;
   1.685 +    if (flags & DP_F_MINUS)
   1.686 +        padlen = -padlen;
   1.687 +
   1.688 +    if ((flags & DP_F_ZERO) && (padlen > 0)) {
   1.689 +        if (signvalue) {
   1.690 +            doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue);
   1.691 +            --padlen;
   1.692 +            signvalue = 0;
   1.693 +        }
   1.694 +        while (padlen > 0) {
   1.695 +            doapr_outch(sbuffer, buffer, currlen, maxlen, '0');
   1.696 +            --padlen;
   1.697 +        }
   1.698 +    }
   1.699 +    while (padlen > 0) {
   1.700 +        doapr_outch(sbuffer, buffer, currlen, maxlen, ' ');
   1.701 +        --padlen;
   1.702 +    }
   1.703 +    if (signvalue)
   1.704 +        doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue);
   1.705 +
   1.706 +    while (iplace > 0)
   1.707 +        doapr_outch(sbuffer, buffer, currlen, maxlen, iconvert[--iplace]);
   1.708 +
   1.709 +    /*
   1.710 +     * Decimal point. This should probably use locale to find the correct
   1.711 +     * char to print out.
   1.712 +     */
   1.713 +    if (max > 0 || (flags & DP_F_NUM)) {
   1.714 +        doapr_outch(sbuffer, buffer, currlen, maxlen, '.');
   1.715 +
   1.716 +        while (fplace > 0)
   1.717 +            doapr_outch(sbuffer, buffer, currlen, maxlen, fconvert[--fplace]);
   1.718 +    }
   1.719 +    while (zpadlen > 0) {
   1.720 +        doapr_outch(sbuffer, buffer, currlen, maxlen, '0');
   1.721 +        --zpadlen;
   1.722 +    }
   1.723 +
   1.724 +    while (padlen < 0) {
   1.725 +        doapr_outch(sbuffer, buffer, currlen, maxlen, ' ');
   1.726 +        ++padlen;
   1.727 +    }
   1.728 +}
   1.729 +
   1.730 +static void
   1.731 +doapr_outch(
   1.732 +    char **sbuffer,
   1.733 +    char **buffer,
   1.734 +    size_t *currlen,
   1.735 +    size_t *maxlen,
   1.736 +    int c)
   1.737 +{
   1.738 +    /* If we haven't at least one buffer, someone has doe a big booboo */
   1.739 +    assert(*sbuffer != NULL || buffer != NULL);
   1.740 +
   1.741 +    if (buffer) {
   1.742 +	while (*currlen >= *maxlen) {
   1.743 +	    if (*buffer == NULL) {
   1.744 +		if (*maxlen == 0)
   1.745 +		    *maxlen = 1024;
   1.746 +		*buffer = OPENSSL_malloc(*maxlen);
   1.747 +		if (*currlen > 0) {
   1.748 +		    assert(*sbuffer != NULL);
   1.749 +		    memcpy(*buffer, *sbuffer, *currlen);
   1.750 +		}
   1.751 +		*sbuffer = NULL;
   1.752 +	    } else {
   1.753 +		*maxlen += 1024;
   1.754 +		*buffer = OPENSSL_realloc(*buffer, *maxlen);
   1.755 +	    }
   1.756 +	}
   1.757 +	/* What to do if *buffer is NULL? */
   1.758 +	assert(*sbuffer != NULL || *buffer != NULL);
   1.759 +    }
   1.760 +
   1.761 +    if (*currlen < *maxlen) {
   1.762 +	if (*sbuffer)
   1.763 +	    (*sbuffer)[(*currlen)++] = (char)c;
   1.764 +	else
   1.765 +	    (*buffer)[(*currlen)++] = (char)c;
   1.766 +    }
   1.767 +
   1.768 +    return;
   1.769 +}
   1.770 +
   1.771 +/***************************************************************************/
   1.772 +
   1.773 +EXPORT_C int BIO_printf (BIO *bio, const char *format, ...)
   1.774 +	{
   1.775 +	va_list args;
   1.776 +	int ret;
   1.777 +
   1.778 +	va_start(args, format);
   1.779 +
   1.780 +	ret = BIO_vprintf(bio, format, args);
   1.781 +
   1.782 +	va_end(args);
   1.783 +	return(ret);
   1.784 +	}
   1.785 +
   1.786 +EXPORT_C int BIO_vprintf (BIO *bio, const char *format, va_list args)
   1.787 +	{
   1.788 +	int ret;
   1.789 +	size_t retlen;
   1.790 +	#ifndef SYMBIAN
   1.791 +	char hugebuf[1024*2];	/* Was previously 10k, which is unreasonable
   1.792 +				   in small-stack environments, like threads
   1.793 +				   or DOS programs. */
   1.794 +#else
   1.795 +  char hugebuf[512];
   1.796 +#endif				   
   1.797 +	char *hugebufp = hugebuf;
   1.798 +	size_t hugebufsize = sizeof(hugebuf);
   1.799 +	char *dynbuf = NULL;
   1.800 +	int ignored;
   1.801 +
   1.802 +	dynbuf = NULL;
   1.803 +	CRYPTO_push_info("doapr()");
   1.804 +	_dopr(&hugebufp, &dynbuf, &hugebufsize,
   1.805 +		&retlen, &ignored, format, args);
   1.806 +	if (dynbuf)
   1.807 +		{
   1.808 +		ret=BIO_write(bio, dynbuf, (int)retlen);
   1.809 +		OPENSSL_free(dynbuf);
   1.810 +		}
   1.811 +	else
   1.812 +		{
   1.813 +		ret=BIO_write(bio, hugebuf, (int)retlen);
   1.814 +		}
   1.815 +	CRYPTO_pop_info();
   1.816 +	return(ret);
   1.817 +	}
   1.818 +
   1.819 +/* As snprintf is not available everywhere, we provide our own implementation.
   1.820 + * This function has nothing to do with BIOs, but it's closely related
   1.821 + * to BIO_printf, and we need *some* name prefix ...
   1.822 + * (XXX  the function should be renamed, but to what?) */
   1.823 +EXPORT_C int BIO_snprintf(char *buf, size_t n, const char *format, ...)
   1.824 +	{
   1.825 +	va_list args;
   1.826 +	int ret;
   1.827 +
   1.828 +	va_start(args, format);
   1.829 +
   1.830 +	ret = BIO_vsnprintf(buf, n, format, args);
   1.831 +
   1.832 +	va_end(args);
   1.833 +	return(ret);
   1.834 +	}
   1.835 +
   1.836 +EXPORT_C int BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args)
   1.837 +	{
   1.838 +	size_t retlen;
   1.839 +	int truncated;
   1.840 +
   1.841 +	_dopr(&buf, NULL, &n, &retlen, &truncated, format, args);
   1.842 +
   1.843 +	if (truncated)
   1.844 +		/* In case of truncation, return -1 like traditional snprintf.
   1.845 +		 * (Current drafts for ISO/IEC 9899 say snprintf should return
   1.846 +		 * the number of characters that would have been written,
   1.847 +		 * had the buffer been large enough.) */
   1.848 +		return -1;
   1.849 +	else
   1.850 +		return (retlen <= INT_MAX) ? (int)retlen : -1;
   1.851 +	}