b_print.c revision 127128
155714Skris/* crypto/bio/b_print.c */
255714Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
355714Skris * All rights reserved.
455714Skris *
555714Skris * This package is an SSL implementation written
655714Skris * by Eric Young (eay@cryptsoft.com).
755714Skris * The implementation was written so as to conform with Netscapes SSL.
855714Skris *
955714Skris * This library is free for commercial and non-commercial use as long as
1055714Skris * the following conditions are aheared to.  The following conditions
1155714Skris * apply to all code found in this distribution, be it the RC4, RSA,
1255714Skris * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
1355714Skris * included with this distribution is covered by the same copyright terms
1455714Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com).
1555714Skris *
1655714Skris * Copyright remains Eric Young's, and as such any Copyright notices in
1755714Skris * the code are not to be removed.
1855714Skris * If this package is used in a product, Eric Young should be given attribution
1955714Skris * as the author of the parts of the library used.
2055714Skris * This can be in the form of a textual message at program startup or
2155714Skris * in documentation (online or textual) provided with the package.
2255714Skris *
2355714Skris * Redistribution and use in source and binary forms, with or without
2455714Skris * modification, are permitted provided that the following conditions
2555714Skris * are met:
2655714Skris * 1. Redistributions of source code must retain the copyright
2755714Skris *    notice, this list of conditions and the following disclaimer.
2855714Skris * 2. Redistributions in binary form must reproduce the above copyright
2955714Skris *    notice, this list of conditions and the following disclaimer in the
3055714Skris *    documentation and/or other materials provided with the distribution.
3155714Skris * 3. All advertising materials mentioning features or use of this software
3255714Skris *    must display the following acknowledgement:
3355714Skris *    "This product includes cryptographic software written by
3455714Skris *     Eric Young (eay@cryptsoft.com)"
3555714Skris *    The word 'cryptographic' can be left out if the rouines from the library
3655714Skris *    being used are not cryptographic related :-).
3755714Skris * 4. If you include any Windows specific code (or a derivative thereof) from
3855714Skris *    the apps directory (application code) you must include an acknowledgement:
3955714Skris *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
4055714Skris *
4155714Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
4255714Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4355714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4455714Skris * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4555714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4655714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4755714Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4955714Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5055714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5155714Skris * SUCH DAMAGE.
5255714Skris *
5355714Skris * The licence and distribution terms for any publically available version or
5455714Skris * derivative of this code cannot be changed.  i.e. this code cannot simply be
5555714Skris * copied and put under another distribution licence
5655714Skris * [including the GNU Public Licence.]
5755714Skris */
5855714Skris
59100936Snectar/* disable assert() unless BIO_DEBUG has been defined */
60100936Snectar#ifndef BIO_DEBUG
61100936Snectar# ifndef NDEBUG
62100936Snectar#  define NDEBUG
63100936Snectar# endif
64100936Snectar#endif
65100936Snectar
6655714Skris/*
6755714Skris * Stolen from tjh's ssl/ssl_trc.c stuff.
6855714Skris */
6955714Skris
7055714Skris#include <stdio.h>
7159191Skris#include <string.h>
7259191Skris#include <ctype.h>
7359191Skris#include <assert.h>
7459191Skris#include <limits.h>
7555714Skris#include "cryptlib.h"
7659191Skris#ifndef NO_SYS_TYPES_H
7759191Skris#include <sys/types.h>
7859191Skris#endif
7979998Skris#include <openssl/bn.h>         /* To get BN_LLONG properly defined */
8055714Skris#include <openssl/bio.h>
8155714Skris
8259191Skris#ifdef BN_LLONG
8359191Skris# ifndef HAVE_LONG_LONG
8459191Skris#  define HAVE_LONG_LONG 1
8559191Skris# endif
8659191Skris#endif
8759191Skris
8868651Skris/***************************************************************************/
8959191Skris
9059191Skris/*
9159191Skris * Copyright Patrick Powell 1995
9259191Skris * This code is based on code written by Patrick Powell <papowell@astart.com>
9359191Skris * It may be used for any purpose as long as this notice remains intact
9459191Skris * on all source code distributions.
9559191Skris */
9659191Skris
9759191Skris/*
9859191Skris * This code contains numerious changes and enhancements which were
9959191Skris * made by lots of contributors over the last years to Patrick Powell's
10059191Skris * original code:
10159191Skris *
10259191Skris * o Patrick Powell <papowell@astart.com>      (1995)
10359191Skris * o Brandon Long <blong@fiction.net>          (1996, for Mutt)
10459191Skris * o Thomas Roessler <roessler@guug.de>        (1998, for Mutt)
10559191Skris * o Michael Elkins <me@cs.hmc.edu>            (1998, for Mutt)
10659191Skris * o Andrew Tridgell <tridge@samba.org>        (1998, for Samba)
10759191Skris * o Luke Mewburn <lukem@netbsd.org>           (1999, for LukemFTP)
10859191Skris * o Ralf S. Engelschall <rse@engelschall.com> (1999, for Pth)
10968651Skris * o ...                                       (for OpenSSL)
11059191Skris */
11159191Skris
112101613Snectar#ifdef HAVE_LONG_DOUBLE
11359191Skris#define LDOUBLE long double
11459191Skris#else
11559191Skris#define LDOUBLE double
11659191Skris#endif
11759191Skris
11859191Skris#if HAVE_LONG_LONG
119109998Smarkm# if defined(OPENSSL_SYS_WIN32) && !defined(__GNUC__)
12079998Skris# define LLONG _int64
12179998Skris# else
12279998Skris# define LLONG long long
12379998Skris# endif
12459191Skris#else
12559191Skris#define LLONG long
12659191Skris#endif
12759191Skris
12868651Skrisstatic void fmtstr     (char **, char **, size_t *, size_t *,
12968651Skris			const char *, int, int, int);
13068651Skrisstatic void fmtint     (char **, char **, size_t *, size_t *,
13168651Skris			LLONG, int, int, int, int);
13268651Skrisstatic void fmtfp      (char **, char **, size_t *, size_t *,
13368651Skris			LDOUBLE, int, int, int);
13468651Skrisstatic void doapr_outch (char **, char **, size_t *, size_t *, int);
13568651Skrisstatic void _dopr(char **sbuffer, char **buffer,
13668651Skris		  size_t *maxlen, size_t *retlen, int *truncated,
13759191Skris		  const char *format, va_list args);
13859191Skris
13959191Skris/* format read states */
14059191Skris#define DP_S_DEFAULT    0
14159191Skris#define DP_S_FLAGS      1
14259191Skris#define DP_S_MIN        2
14359191Skris#define DP_S_DOT        3
14459191Skris#define DP_S_MAX        4
14559191Skris#define DP_S_MOD        5
14659191Skris#define DP_S_CONV       6
14759191Skris#define DP_S_DONE       7
14859191Skris
14959191Skris/* format flags - Bits */
15059191Skris#define DP_F_MINUS      (1 << 0)
15159191Skris#define DP_F_PLUS       (1 << 1)
15259191Skris#define DP_F_SPACE      (1 << 2)
15359191Skris#define DP_F_NUM        (1 << 3)
15459191Skris#define DP_F_ZERO       (1 << 4)
15559191Skris#define DP_F_UP         (1 << 5)
15659191Skris#define DP_F_UNSIGNED   (1 << 6)
15759191Skris
15859191Skris/* conversion flags */
15959191Skris#define DP_C_SHORT      1
16059191Skris#define DP_C_LONG       2
16159191Skris#define DP_C_LDOUBLE    3
16259191Skris#define DP_C_LLONG      4
16359191Skris
16459191Skris/* some handy macros */
16559191Skris#define char_to_int(p) (p - '0')
16679998Skris#define OSSL_MAX(p,q) ((p >= q) ? p : q)
16759191Skris
16859191Skrisstatic void
16959191Skris_dopr(
17068651Skris    char **sbuffer,
17159191Skris    char **buffer,
17259191Skris    size_t *maxlen,
17359191Skris    size_t *retlen,
17468651Skris    int *truncated,
17559191Skris    const char *format,
17659191Skris    va_list args)
17759191Skris{
17859191Skris    char ch;
17959191Skris    LLONG value;
18059191Skris    LDOUBLE fvalue;
18159191Skris    char *strvalue;
18259191Skris    int min;
18359191Skris    int max;
18459191Skris    int state;
18559191Skris    int flags;
18659191Skris    int cflags;
18759191Skris    size_t currlen;
18859191Skris
18959191Skris    state = DP_S_DEFAULT;
19059191Skris    flags = currlen = cflags = min = 0;
19159191Skris    max = -1;
19259191Skris    ch = *format++;
19359191Skris
19459191Skris    while (state != DP_S_DONE) {
19568651Skris        if (ch == '\0' || (buffer == NULL && currlen >= *maxlen))
19659191Skris            state = DP_S_DONE;
19759191Skris
19859191Skris        switch (state) {
19959191Skris        case DP_S_DEFAULT:
20059191Skris            if (ch == '%')
20159191Skris                state = DP_S_FLAGS;
20259191Skris            else
20368651Skris                doapr_outch(sbuffer,buffer, &currlen, maxlen, ch);
20459191Skris            ch = *format++;
20559191Skris            break;
20659191Skris        case DP_S_FLAGS:
20759191Skris            switch (ch) {
20859191Skris            case '-':
20959191Skris                flags |= DP_F_MINUS;
21059191Skris                ch = *format++;
21159191Skris                break;
21259191Skris            case '+':
21359191Skris                flags |= DP_F_PLUS;
21459191Skris                ch = *format++;
21559191Skris                break;
21659191Skris            case ' ':
21759191Skris                flags |= DP_F_SPACE;
21859191Skris                ch = *format++;
21959191Skris                break;
22059191Skris            case '#':
22159191Skris                flags |= DP_F_NUM;
22259191Skris                ch = *format++;
22359191Skris                break;
22459191Skris            case '0':
22559191Skris                flags |= DP_F_ZERO;
22659191Skris                ch = *format++;
22759191Skris                break;
22859191Skris            default:
22959191Skris                state = DP_S_MIN;
23059191Skris                break;
23159191Skris            }
23259191Skris            break;
23359191Skris        case DP_S_MIN:
23459191Skris            if (isdigit((unsigned char)ch)) {
23559191Skris                min = 10 * min + char_to_int(ch);
23659191Skris                ch = *format++;
23759191Skris            } else if (ch == '*') {
23859191Skris                min = va_arg(args, int);
23959191Skris                ch = *format++;
24059191Skris                state = DP_S_DOT;
24159191Skris            } else
24259191Skris                state = DP_S_DOT;
24359191Skris            break;
24459191Skris        case DP_S_DOT:
24559191Skris            if (ch == '.') {
24659191Skris                state = DP_S_MAX;
24759191Skris                ch = *format++;
24859191Skris            } else
24959191Skris                state = DP_S_MOD;
25059191Skris            break;
25159191Skris        case DP_S_MAX:
25259191Skris            if (isdigit((unsigned char)ch)) {
25359191Skris                if (max < 0)
25459191Skris                    max = 0;
25559191Skris                max = 10 * max + char_to_int(ch);
25659191Skris                ch = *format++;
25759191Skris            } else if (ch == '*') {
25859191Skris                max = va_arg(args, int);
25959191Skris                ch = *format++;
26059191Skris                state = DP_S_MOD;
26159191Skris            } else
26259191Skris                state = DP_S_MOD;
26359191Skris            break;
26459191Skris        case DP_S_MOD:
26559191Skris            switch (ch) {
26659191Skris            case 'h':
26759191Skris                cflags = DP_C_SHORT;
26859191Skris                ch = *format++;
26959191Skris                break;
27059191Skris            case 'l':
27159191Skris                if (*format == 'l') {
27259191Skris                    cflags = DP_C_LLONG;
27359191Skris                    format++;
27459191Skris                } else
27559191Skris                    cflags = DP_C_LONG;
27659191Skris                ch = *format++;
27759191Skris                break;
27859191Skris            case 'q':
27959191Skris                cflags = DP_C_LLONG;
28059191Skris                ch = *format++;
28159191Skris                break;
28259191Skris            case 'L':
28359191Skris                cflags = DP_C_LDOUBLE;
28459191Skris                ch = *format++;
28559191Skris                break;
28659191Skris            default:
28759191Skris                break;
28859191Skris            }
28959191Skris            state = DP_S_CONV;
29059191Skris            break;
29159191Skris        case DP_S_CONV:
29259191Skris            switch (ch) {
29359191Skris            case 'd':
29459191Skris            case 'i':
29559191Skris                switch (cflags) {
29659191Skris                case DP_C_SHORT:
29759191Skris                    value = (short int)va_arg(args, int);
29859191Skris                    break;
29959191Skris                case DP_C_LONG:
30059191Skris                    value = va_arg(args, long int);
30159191Skris                    break;
30259191Skris                case DP_C_LLONG:
30359191Skris                    value = va_arg(args, LLONG);
30459191Skris                    break;
30559191Skris                default:
30659191Skris                    value = va_arg(args, int);
30759191Skris                    break;
30859191Skris                }
30968651Skris                fmtint(sbuffer, buffer, &currlen, maxlen,
31068651Skris                       value, 10, min, max, flags);
31159191Skris                break;
31259191Skris            case 'X':
31359191Skris                flags |= DP_F_UP;
31459191Skris                /* FALLTHROUGH */
31559191Skris            case 'x':
31659191Skris            case 'o':
31759191Skris            case 'u':
31859191Skris                flags |= DP_F_UNSIGNED;
31959191Skris                switch (cflags) {
32059191Skris                case DP_C_SHORT:
32159191Skris                    value = (unsigned short int)va_arg(args, unsigned int);
32259191Skris                    break;
32359191Skris                case DP_C_LONG:
32459191Skris                    value = (LLONG) va_arg(args,
32559191Skris                        unsigned long int);
32659191Skris                    break;
32759191Skris                case DP_C_LLONG:
32859191Skris                    value = va_arg(args, unsigned LLONG);
32959191Skris                    break;
33059191Skris                default:
33159191Skris                    value = (LLONG) va_arg(args,
33259191Skris                        unsigned int);
33359191Skris                    break;
33459191Skris                }
33568651Skris                fmtint(sbuffer, buffer, &currlen, maxlen, value,
33659191Skris                       ch == 'o' ? 8 : (ch == 'u' ? 10 : 16),
33759191Skris                       min, max, flags);
33859191Skris                break;
33959191Skris            case 'f':
34059191Skris                if (cflags == DP_C_LDOUBLE)
34159191Skris                    fvalue = va_arg(args, LDOUBLE);
34259191Skris                else
34359191Skris                    fvalue = va_arg(args, double);
34468651Skris                fmtfp(sbuffer, buffer, &currlen, maxlen,
34568651Skris                      fvalue, min, max, flags);
34659191Skris                break;
34759191Skris            case 'E':
34859191Skris                flags |= DP_F_UP;
34959191Skris            case 'e':
35059191Skris                if (cflags == DP_C_LDOUBLE)
35159191Skris                    fvalue = va_arg(args, LDOUBLE);
35259191Skris                else
35359191Skris                    fvalue = va_arg(args, double);
35459191Skris                break;
35559191Skris            case 'G':
35659191Skris                flags |= DP_F_UP;
35759191Skris            case 'g':
35859191Skris                if (cflags == DP_C_LDOUBLE)
35959191Skris                    fvalue = va_arg(args, LDOUBLE);
36059191Skris                else
36159191Skris                    fvalue = va_arg(args, double);
36259191Skris                break;
36359191Skris            case 'c':
36468651Skris                doapr_outch(sbuffer, buffer, &currlen, maxlen,
36559191Skris                    va_arg(args, int));
36659191Skris                break;
36759191Skris            case 's':
36859191Skris                strvalue = va_arg(args, char *);
36968651Skris                if (max < 0) {
37068651Skris		    if (buffer)
37168651Skris			max = INT_MAX;
37268651Skris		    else
37368651Skris			max = *maxlen;
37468651Skris		}
37568651Skris                fmtstr(sbuffer, buffer, &currlen, maxlen, strvalue,
37668651Skris                       flags, min, max);
37759191Skris                break;
37859191Skris            case 'p':
37959191Skris                value = (long)va_arg(args, void *);
38068651Skris                fmtint(sbuffer, buffer, &currlen, maxlen,
381120631Snectar                    value, 16, min, max, flags|DP_F_NUM);
38259191Skris                break;
38359191Skris            case 'n': /* XXX */
38459191Skris                if (cflags == DP_C_SHORT) {
38559191Skris                    short int *num;
38659191Skris                    num = va_arg(args, short int *);
38759191Skris                    *num = currlen;
38859191Skris                } else if (cflags == DP_C_LONG) { /* XXX */
38959191Skris                    long int *num;
39059191Skris                    num = va_arg(args, long int *);
39159191Skris                    *num = (long int) currlen;
39259191Skris                } else if (cflags == DP_C_LLONG) { /* XXX */
39359191Skris                    LLONG *num;
39459191Skris                    num = va_arg(args, LLONG *);
39559191Skris                    *num = (LLONG) currlen;
39659191Skris                } else {
39759191Skris                    int    *num;
39859191Skris                    num = va_arg(args, int *);
39959191Skris                    *num = currlen;
40059191Skris                }
40159191Skris                break;
40259191Skris            case '%':
40368651Skris                doapr_outch(sbuffer, buffer, &currlen, maxlen, ch);
40459191Skris                break;
40559191Skris            case 'w':
40659191Skris                /* not supported yet, treat as next char */
40759191Skris                ch = *format++;
40859191Skris                break;
40959191Skris            default:
41059191Skris                /* unknown, skip */
41159191Skris                break;
41259191Skris            }
41359191Skris            ch = *format++;
41459191Skris            state = DP_S_DEFAULT;
41559191Skris            flags = cflags = min = 0;
41659191Skris            max = -1;
41759191Skris            break;
41859191Skris        case DP_S_DONE:
41959191Skris            break;
42059191Skris        default:
42159191Skris            break;
42259191Skris        }
42359191Skris    }
42468651Skris    *truncated = (currlen > *maxlen - 1);
42568651Skris    if (*truncated)
42659191Skris        currlen = *maxlen - 1;
42768651Skris    doapr_outch(sbuffer, buffer, &currlen, maxlen, '\0');
42868651Skris    *retlen = currlen - 1;
42959191Skris    return;
43059191Skris}
43159191Skris
43259191Skrisstatic void
43359191Skrisfmtstr(
43468651Skris    char **sbuffer,
43559191Skris    char **buffer,
43659191Skris    size_t *currlen,
43759191Skris    size_t *maxlen,
43859191Skris    const char *value,
43959191Skris    int flags,
44059191Skris    int min,
44159191Skris    int max)
44259191Skris{
44359191Skris    int padlen, strln;
44459191Skris    int cnt = 0;
44559191Skris
44659191Skris    if (value == 0)
44759191Skris        value = "<NULL>";
44859191Skris    for (strln = 0; value[strln]; ++strln)
44959191Skris        ;
45059191Skris    padlen = min - strln;
45159191Skris    if (padlen < 0)
45259191Skris        padlen = 0;
45359191Skris    if (flags & DP_F_MINUS)
45459191Skris        padlen = -padlen;
45559191Skris
45659191Skris    while ((padlen > 0) && (cnt < max)) {
45768651Skris        doapr_outch(sbuffer, buffer, currlen, maxlen, ' ');
45859191Skris        --padlen;
45959191Skris        ++cnt;
46059191Skris    }
46159191Skris    while (*value && (cnt < max)) {
46268651Skris        doapr_outch(sbuffer, buffer, currlen, maxlen, *value++);
46359191Skris        ++cnt;
46459191Skris    }
46559191Skris    while ((padlen < 0) && (cnt < max)) {
46668651Skris        doapr_outch(sbuffer, buffer, currlen, maxlen, ' ');
46759191Skris        ++padlen;
46859191Skris        ++cnt;
46959191Skris    }
47059191Skris}
47159191Skris
47259191Skrisstatic void
47359191Skrisfmtint(
47468651Skris    char **sbuffer,
47559191Skris    char **buffer,
47659191Skris    size_t *currlen,
47759191Skris    size_t *maxlen,
47859191Skris    LLONG value,
47959191Skris    int base,
48059191Skris    int min,
48159191Skris    int max,
48259191Skris    int flags)
48359191Skris{
48459191Skris    int signvalue = 0;
485120631Snectar    char *prefix = "";
48659191Skris    unsigned LLONG uvalue;
487120631Snectar    char convert[DECIMAL_SIZE(value)+3];
48859191Skris    int place = 0;
48959191Skris    int spadlen = 0;
49059191Skris    int zpadlen = 0;
49159191Skris    int caps = 0;
49259191Skris
49359191Skris    if (max < 0)
49459191Skris        max = 0;
49559191Skris    uvalue = value;
49659191Skris    if (!(flags & DP_F_UNSIGNED)) {
49759191Skris        if (value < 0) {
49859191Skris            signvalue = '-';
49959191Skris            uvalue = -value;
50059191Skris        } else if (flags & DP_F_PLUS)
50159191Skris            signvalue = '+';
50259191Skris        else if (flags & DP_F_SPACE)
50359191Skris            signvalue = ' ';
50459191Skris    }
505120631Snectar    if (flags & DP_F_NUM) {
506120631Snectar	if (base == 8) prefix = "0";
507120631Snectar	if (base == 16) prefix = "0x";
508120631Snectar    }
50959191Skris    if (flags & DP_F_UP)
51059191Skris        caps = 1;
51159191Skris    do {
51259191Skris        convert[place++] =
51359191Skris            (caps ? "0123456789ABCDEF" : "0123456789abcdef")
51459191Skris            [uvalue % (unsigned) base];
51559191Skris        uvalue = (uvalue / (unsigned) base);
516109998Smarkm    } while (uvalue && (place < sizeof convert));
517109998Smarkm    if (place == sizeof convert)
51859191Skris        place--;
51959191Skris    convert[place] = 0;
52059191Skris
52159191Skris    zpadlen = max - place;
522120631Snectar    spadlen = min - OSSL_MAX(max, place) - (signvalue ? 1 : 0) - strlen(prefix);
52359191Skris    if (zpadlen < 0)
52459191Skris        zpadlen = 0;
52559191Skris    if (spadlen < 0)
52659191Skris        spadlen = 0;
52759191Skris    if (flags & DP_F_ZERO) {
52879998Skris        zpadlen = OSSL_MAX(zpadlen, spadlen);
52959191Skris        spadlen = 0;
53059191Skris    }
53159191Skris    if (flags & DP_F_MINUS)
53259191Skris        spadlen = -spadlen;
53359191Skris
53459191Skris    /* spaces */
53559191Skris    while (spadlen > 0) {
53668651Skris        doapr_outch(sbuffer, buffer, currlen, maxlen, ' ');
53759191Skris        --spadlen;
53859191Skris    }
53959191Skris
54059191Skris    /* sign */
54159191Skris    if (signvalue)
54268651Skris        doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue);
54359191Skris
544120631Snectar    /* prefix */
545120631Snectar    while (*prefix) {
546120631Snectar	doapr_outch(sbuffer, buffer, currlen, maxlen, *prefix);
547120631Snectar	prefix++;
548120631Snectar    }
549120631Snectar
55059191Skris    /* zeros */
55159191Skris    if (zpadlen > 0) {
55259191Skris        while (zpadlen > 0) {
55368651Skris            doapr_outch(sbuffer, buffer, currlen, maxlen, '0');
55459191Skris            --zpadlen;
55559191Skris        }
55659191Skris    }
55759191Skris    /* digits */
55859191Skris    while (place > 0)
55968651Skris        doapr_outch(sbuffer, buffer, currlen, maxlen, convert[--place]);
56059191Skris
56159191Skris    /* left justified spaces */
56259191Skris    while (spadlen < 0) {
56368651Skris        doapr_outch(sbuffer, buffer, currlen, maxlen, ' ');
56459191Skris        ++spadlen;
56559191Skris    }
56659191Skris    return;
56759191Skris}
56859191Skris
56959191Skrisstatic LDOUBLE
57059191Skrisabs_val(LDOUBLE value)
57159191Skris{
57259191Skris    LDOUBLE result = value;
57359191Skris    if (value < 0)
57459191Skris        result = -value;
57559191Skris    return result;
57659191Skris}
57759191Skris
57859191Skrisstatic LDOUBLE
579127128Snectarpow10(int in_exp)
58059191Skris{
58159191Skris    LDOUBLE result = 1;
582127128Snectar    while (in_exp) {
58359191Skris        result *= 10;
584127128Snectar        in_exp--;
58559191Skris    }
58659191Skris    return result;
58759191Skris}
58859191Skris
58959191Skrisstatic long
59089837Skrisroundv(LDOUBLE value)
59159191Skris{
59259191Skris    long intpart;
59359191Skris    intpart = (long) value;
59459191Skris    value = value - intpart;
59559191Skris    if (value >= 0.5)
59659191Skris        intpart++;
59759191Skris    return intpart;
59859191Skris}
59959191Skris
60059191Skrisstatic void
60159191Skrisfmtfp(
60268651Skris    char **sbuffer,
60359191Skris    char **buffer,
60459191Skris    size_t *currlen,
60559191Skris    size_t *maxlen,
60659191Skris    LDOUBLE fvalue,
60759191Skris    int min,
60859191Skris    int max,
60959191Skris    int flags)
61059191Skris{
61159191Skris    int signvalue = 0;
61259191Skris    LDOUBLE ufvalue;
61359191Skris    char iconvert[20];
61459191Skris    char fconvert[20];
61559191Skris    int iplace = 0;
61659191Skris    int fplace = 0;
61759191Skris    int padlen = 0;
61859191Skris    int zpadlen = 0;
61959191Skris    int caps = 0;
62059191Skris    long intpart;
62159191Skris    long fracpart;
62259191Skris
62359191Skris    if (max < 0)
62459191Skris        max = 6;
62559191Skris    ufvalue = abs_val(fvalue);
62659191Skris    if (fvalue < 0)
62759191Skris        signvalue = '-';
62859191Skris    else if (flags & DP_F_PLUS)
62959191Skris        signvalue = '+';
63059191Skris    else if (flags & DP_F_SPACE)
63159191Skris        signvalue = ' ';
63259191Skris
63359191Skris    intpart = (long)ufvalue;
63459191Skris
63559191Skris    /* sorry, we only support 9 digits past the decimal because of our
63659191Skris       conversion method */
63759191Skris    if (max > 9)
63859191Skris        max = 9;
63959191Skris
64059191Skris    /* we "cheat" by converting the fractional part to integer by
64159191Skris       multiplying by a factor of 10 */
64289837Skris    fracpart = roundv((pow10(max)) * (ufvalue - intpart));
64359191Skris
64459191Skris    if (fracpart >= pow10(max)) {
64559191Skris        intpart++;
64659191Skris        fracpart -= (long)pow10(max);
64759191Skris    }
64859191Skris
64959191Skris    /* convert integer part */
65059191Skris    do {
65159191Skris        iconvert[iplace++] =
65259191Skris            (caps ? "0123456789ABCDEF"
65359191Skris              : "0123456789abcdef")[intpart % 10];
65459191Skris        intpart = (intpart / 10);
655127128Snectar    } while (intpart && (iplace < sizeof iconvert));
656127128Snectar    if (iplace == sizeof iconvert)
65759191Skris        iplace--;
65859191Skris    iconvert[iplace] = 0;
65959191Skris
66059191Skris    /* convert fractional part */
66159191Skris    do {
66259191Skris        fconvert[fplace++] =
66359191Skris            (caps ? "0123456789ABCDEF"
66459191Skris              : "0123456789abcdef")[fracpart % 10];
66559191Skris        fracpart = (fracpart / 10);
66679998Skris    } while (fplace < max);
667127128Snectar    if (fplace == sizeof fconvert)
66859191Skris        fplace--;
66959191Skris    fconvert[fplace] = 0;
67059191Skris
67159191Skris    /* -1 for decimal point, another -1 if we are printing a sign */
67259191Skris    padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0);
67359191Skris    zpadlen = max - fplace;
67459191Skris    if (zpadlen < 0)
67559191Skris        zpadlen = 0;
67659191Skris    if (padlen < 0)
67759191Skris        padlen = 0;
67859191Skris    if (flags & DP_F_MINUS)
67959191Skris        padlen = -padlen;
68059191Skris
68159191Skris    if ((flags & DP_F_ZERO) && (padlen > 0)) {
68259191Skris        if (signvalue) {
68368651Skris            doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue);
68459191Skris            --padlen;
68559191Skris            signvalue = 0;
68659191Skris        }
68759191Skris        while (padlen > 0) {
68868651Skris            doapr_outch(sbuffer, buffer, currlen, maxlen, '0');
68959191Skris            --padlen;
69059191Skris        }
69159191Skris    }
69259191Skris    while (padlen > 0) {
69368651Skris        doapr_outch(sbuffer, buffer, currlen, maxlen, ' ');
69459191Skris        --padlen;
69559191Skris    }
69659191Skris    if (signvalue)
69768651Skris        doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue);
69859191Skris
69959191Skris    while (iplace > 0)
70068651Skris        doapr_outch(sbuffer, buffer, currlen, maxlen, iconvert[--iplace]);
70159191Skris
70259191Skris    /*
70359191Skris     * Decimal point. This should probably use locale to find the correct
70459191Skris     * char to print out.
70559191Skris     */
706120631Snectar    if (max > 0 || (flags & DP_F_NUM)) {
70768651Skris        doapr_outch(sbuffer, buffer, currlen, maxlen, '.');
70859191Skris
70959191Skris        while (fplace > 0)
71068651Skris            doapr_outch(sbuffer, buffer, currlen, maxlen, fconvert[--fplace]);
71159191Skris    }
71259191Skris    while (zpadlen > 0) {
71368651Skris        doapr_outch(sbuffer, buffer, currlen, maxlen, '0');
71459191Skris        --zpadlen;
71559191Skris    }
71659191Skris
71759191Skris    while (padlen < 0) {
71868651Skris        doapr_outch(sbuffer, buffer, currlen, maxlen, ' ');
71959191Skris        ++padlen;
72059191Skris    }
72159191Skris}
72259191Skris
72359191Skrisstatic void
72468651Skrisdoapr_outch(
72568651Skris    char **sbuffer,
72659191Skris    char **buffer,
72759191Skris    size_t *currlen,
72859191Skris    size_t *maxlen,
72959191Skris    int c)
73059191Skris{
73168651Skris    /* If we haven't at least one buffer, someone has doe a big booboo */
73268651Skris    assert(*sbuffer != NULL || buffer != NULL);
73359191Skris
73468651Skris    if (buffer) {
73568651Skris	while (*currlen >= *maxlen) {
73668651Skris	    if (*buffer == NULL) {
73768651Skris		if (*maxlen == 0)
73868651Skris		    *maxlen = 1024;
73968651Skris		*buffer = OPENSSL_malloc(*maxlen);
740100928Snectar		if (*currlen > 0) {
741100928Snectar		    assert(*sbuffer != NULL);
74268651Skris		    memcpy(*buffer, *sbuffer, *currlen);
743100928Snectar		}
74468651Skris		*sbuffer = NULL;
74568651Skris	    } else {
74668651Skris		*maxlen += 1024;
74768651Skris		*buffer = OPENSSL_realloc(*buffer, *maxlen);
74868651Skris	    }
74968651Skris	}
75068651Skris	/* What to do if *buffer is NULL? */
75168651Skris	assert(*sbuffer != NULL || *buffer != NULL);
75259191Skris    }
75368651Skris
75468651Skris    if (*currlen < *maxlen) {
75568651Skris	if (*sbuffer)
75668651Skris	    (*sbuffer)[(*currlen)++] = (char)c;
75768651Skris	else
75868651Skris	    (*buffer)[(*currlen)++] = (char)c;
75959191Skris    }
76059191Skris
76159191Skris    return;
76259191Skris}
76368651Skris
76468651Skris/***************************************************************************/
76568651Skris
76668651Skrisint BIO_printf (BIO *bio, const char *format, ...)
76768651Skris	{
76868651Skris	va_list args;
76968651Skris	int ret;
77068651Skris
77168651Skris	va_start(args, format);
77268651Skris
77368651Skris	ret = BIO_vprintf(bio, format, args);
77468651Skris
77568651Skris	va_end(args);
77668651Skris	return(ret);
77768651Skris	}
77868651Skris
77968651Skrisint BIO_vprintf (BIO *bio, const char *format, va_list args)
78068651Skris	{
78168651Skris	int ret;
78268651Skris	size_t retlen;
783100928Snectar	char hugebuf[1024*2];	/* Was previously 10k, which is unreasonable
784100928Snectar				   in small-stack environments, like threads
785100928Snectar				   or DOS programs. */
78668651Skris	char *hugebufp = hugebuf;
78768651Skris	size_t hugebufsize = sizeof(hugebuf);
78868651Skris	char *dynbuf = NULL;
78968651Skris	int ignored;
79068651Skris
79168651Skris	dynbuf = NULL;
79268651Skris	CRYPTO_push_info("doapr()");
79368651Skris	_dopr(&hugebufp, &dynbuf, &hugebufsize,
79468651Skris		&retlen, &ignored, format, args);
79568651Skris	if (dynbuf)
79668651Skris		{
79768651Skris		ret=BIO_write(bio, dynbuf, (int)retlen);
79868651Skris		OPENSSL_free(dynbuf);
79968651Skris		}
80068651Skris	else
80168651Skris		{
80268651Skris		ret=BIO_write(bio, hugebuf, (int)retlen);
80368651Skris		}
80468651Skris	CRYPTO_pop_info();
80568651Skris	return(ret);
80668651Skris	}
80768651Skris
80868651Skris/* As snprintf is not available everywhere, we provide our own implementation.
80968651Skris * This function has nothing to do with BIOs, but it's closely related
81068651Skris * to BIO_printf, and we need *some* name prefix ...
81168651Skris * (XXX  the function should be renamed, but to what?) */
81268651Skrisint BIO_snprintf(char *buf, size_t n, const char *format, ...)
81368651Skris	{
81468651Skris	va_list args;
81568651Skris	int ret;
81668651Skris
81768651Skris	va_start(args, format);
81868651Skris
81968651Skris	ret = BIO_vsnprintf(buf, n, format, args);
82068651Skris
82168651Skris	va_end(args);
82268651Skris	return(ret);
82368651Skris	}
82468651Skris
82568651Skrisint BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args)
82668651Skris	{
82768651Skris	size_t retlen;
82868651Skris	int truncated;
82968651Skris
83068651Skris	_dopr(&buf, NULL, &n, &retlen, &truncated, format, args);
83168651Skris
83268651Skris	if (truncated)
83368651Skris		/* In case of truncation, return -1 like traditional snprintf.
83468651Skris		 * (Current drafts for ISO/IEC 9899 say snprintf should return
83568651Skris		 * the number of characters that would have been written,
83668651Skris		 * had the buffer been large enough.) */
83768651Skris		return -1;
83868651Skris	else
839120631Snectar		return (retlen <= INT_MAX) ? (int)retlen : -1;
84068651Skris	}
841