b_print.c revision 101613
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
11979998Skris# if defined(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,
38159191Skris                    value, 16, min, max, flags);
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;
48559191Skris    unsigned LLONG uvalue;
48659191Skris    char convert[20];
48759191Skris    int place = 0;
48859191Skris    int spadlen = 0;
48959191Skris    int zpadlen = 0;
49059191Skris    int caps = 0;
49159191Skris
49259191Skris    if (max < 0)
49359191Skris        max = 0;
49459191Skris    uvalue = value;
49559191Skris    if (!(flags & DP_F_UNSIGNED)) {
49659191Skris        if (value < 0) {
49759191Skris            signvalue = '-';
49859191Skris            uvalue = -value;
49959191Skris        } else if (flags & DP_F_PLUS)
50059191Skris            signvalue = '+';
50159191Skris        else if (flags & DP_F_SPACE)
50259191Skris            signvalue = ' ';
50359191Skris    }
50459191Skris    if (flags & DP_F_UP)
50559191Skris        caps = 1;
50659191Skris    do {
50759191Skris        convert[place++] =
50859191Skris            (caps ? "0123456789ABCDEF" : "0123456789abcdef")
50959191Skris            [uvalue % (unsigned) base];
51059191Skris        uvalue = (uvalue / (unsigned) base);
51159191Skris    } while (uvalue && (place < 20));
51259191Skris    if (place == 20)
51359191Skris        place--;
51459191Skris    convert[place] = 0;
51559191Skris
51659191Skris    zpadlen = max - place;
51779998Skris    spadlen = min - OSSL_MAX(max, place) - (signvalue ? 1 : 0);
51859191Skris    if (zpadlen < 0)
51959191Skris        zpadlen = 0;
52059191Skris    if (spadlen < 0)
52159191Skris        spadlen = 0;
52259191Skris    if (flags & DP_F_ZERO) {
52379998Skris        zpadlen = OSSL_MAX(zpadlen, spadlen);
52459191Skris        spadlen = 0;
52559191Skris    }
52659191Skris    if (flags & DP_F_MINUS)
52759191Skris        spadlen = -spadlen;
52859191Skris
52959191Skris    /* spaces */
53059191Skris    while (spadlen > 0) {
53168651Skris        doapr_outch(sbuffer, buffer, currlen, maxlen, ' ');
53259191Skris        --spadlen;
53359191Skris    }
53459191Skris
53559191Skris    /* sign */
53659191Skris    if (signvalue)
53768651Skris        doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue);
53859191Skris
53959191Skris    /* zeros */
54059191Skris    if (zpadlen > 0) {
54159191Skris        while (zpadlen > 0) {
54268651Skris            doapr_outch(sbuffer, buffer, currlen, maxlen, '0');
54359191Skris            --zpadlen;
54459191Skris        }
54559191Skris    }
54659191Skris    /* digits */
54759191Skris    while (place > 0)
54868651Skris        doapr_outch(sbuffer, buffer, currlen, maxlen, convert[--place]);
54959191Skris
55059191Skris    /* left justified spaces */
55159191Skris    while (spadlen < 0) {
55268651Skris        doapr_outch(sbuffer, buffer, currlen, maxlen, ' ');
55359191Skris        ++spadlen;
55459191Skris    }
55559191Skris    return;
55659191Skris}
55759191Skris
55859191Skrisstatic LDOUBLE
55959191Skrisabs_val(LDOUBLE value)
56059191Skris{
56159191Skris    LDOUBLE result = value;
56259191Skris    if (value < 0)
56359191Skris        result = -value;
56459191Skris    return result;
56559191Skris}
56659191Skris
56759191Skrisstatic LDOUBLE
56859191Skrispow10(int exp)
56959191Skris{
57059191Skris    LDOUBLE result = 1;
57159191Skris    while (exp) {
57259191Skris        result *= 10;
57359191Skris        exp--;
57459191Skris    }
57559191Skris    return result;
57659191Skris}
57759191Skris
57859191Skrisstatic long
57989837Skrisroundv(LDOUBLE value)
58059191Skris{
58159191Skris    long intpart;
58259191Skris    intpart = (long) value;
58359191Skris    value = value - intpart;
58459191Skris    if (value >= 0.5)
58559191Skris        intpart++;
58659191Skris    return intpart;
58759191Skris}
58859191Skris
58959191Skrisstatic void
59059191Skrisfmtfp(
59168651Skris    char **sbuffer,
59259191Skris    char **buffer,
59359191Skris    size_t *currlen,
59459191Skris    size_t *maxlen,
59559191Skris    LDOUBLE fvalue,
59659191Skris    int min,
59759191Skris    int max,
59859191Skris    int flags)
59959191Skris{
60059191Skris    int signvalue = 0;
60159191Skris    LDOUBLE ufvalue;
60259191Skris    char iconvert[20];
60359191Skris    char fconvert[20];
60459191Skris    int iplace = 0;
60559191Skris    int fplace = 0;
60659191Skris    int padlen = 0;
60759191Skris    int zpadlen = 0;
60859191Skris    int caps = 0;
60959191Skris    long intpart;
61059191Skris    long fracpart;
61159191Skris
61259191Skris    if (max < 0)
61359191Skris        max = 6;
61459191Skris    ufvalue = abs_val(fvalue);
61559191Skris    if (fvalue < 0)
61659191Skris        signvalue = '-';
61759191Skris    else if (flags & DP_F_PLUS)
61859191Skris        signvalue = '+';
61959191Skris    else if (flags & DP_F_SPACE)
62059191Skris        signvalue = ' ';
62159191Skris
62259191Skris    intpart = (long)ufvalue;
62359191Skris
62459191Skris    /* sorry, we only support 9 digits past the decimal because of our
62559191Skris       conversion method */
62659191Skris    if (max > 9)
62759191Skris        max = 9;
62859191Skris
62959191Skris    /* we "cheat" by converting the fractional part to integer by
63059191Skris       multiplying by a factor of 10 */
63189837Skris    fracpart = roundv((pow10(max)) * (ufvalue - intpart));
63259191Skris
63359191Skris    if (fracpart >= pow10(max)) {
63459191Skris        intpart++;
63559191Skris        fracpart -= (long)pow10(max);
63659191Skris    }
63759191Skris
63859191Skris    /* convert integer part */
63959191Skris    do {
64059191Skris        iconvert[iplace++] =
64159191Skris            (caps ? "0123456789ABCDEF"
64259191Skris              : "0123456789abcdef")[intpart % 10];
64359191Skris        intpart = (intpart / 10);
64459191Skris    } while (intpart && (iplace < 20));
64559191Skris    if (iplace == 20)
64659191Skris        iplace--;
64759191Skris    iconvert[iplace] = 0;
64859191Skris
64959191Skris    /* convert fractional part */
65059191Skris    do {
65159191Skris        fconvert[fplace++] =
65259191Skris            (caps ? "0123456789ABCDEF"
65359191Skris              : "0123456789abcdef")[fracpart % 10];
65459191Skris        fracpart = (fracpart / 10);
65579998Skris    } while (fplace < max);
65659191Skris    if (fplace == 20)
65759191Skris        fplace--;
65859191Skris    fconvert[fplace] = 0;
65959191Skris
66059191Skris    /* -1 for decimal point, another -1 if we are printing a sign */
66159191Skris    padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0);
66259191Skris    zpadlen = max - fplace;
66359191Skris    if (zpadlen < 0)
66459191Skris        zpadlen = 0;
66559191Skris    if (padlen < 0)
66659191Skris        padlen = 0;
66759191Skris    if (flags & DP_F_MINUS)
66859191Skris        padlen = -padlen;
66959191Skris
67059191Skris    if ((flags & DP_F_ZERO) && (padlen > 0)) {
67159191Skris        if (signvalue) {
67268651Skris            doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue);
67359191Skris            --padlen;
67459191Skris            signvalue = 0;
67559191Skris        }
67659191Skris        while (padlen > 0) {
67768651Skris            doapr_outch(sbuffer, buffer, currlen, maxlen, '0');
67859191Skris            --padlen;
67959191Skris        }
68059191Skris    }
68159191Skris    while (padlen > 0) {
68268651Skris        doapr_outch(sbuffer, buffer, currlen, maxlen, ' ');
68359191Skris        --padlen;
68459191Skris    }
68559191Skris    if (signvalue)
68668651Skris        doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue);
68759191Skris
68859191Skris    while (iplace > 0)
68968651Skris        doapr_outch(sbuffer, buffer, currlen, maxlen, iconvert[--iplace]);
69059191Skris
69159191Skris    /*
69259191Skris     * Decimal point. This should probably use locale to find the correct
69359191Skris     * char to print out.
69459191Skris     */
69559191Skris    if (max > 0) {
69668651Skris        doapr_outch(sbuffer, buffer, currlen, maxlen, '.');
69759191Skris
69859191Skris        while (fplace > 0)
69968651Skris            doapr_outch(sbuffer, buffer, currlen, maxlen, fconvert[--fplace]);
70059191Skris    }
70159191Skris    while (zpadlen > 0) {
70268651Skris        doapr_outch(sbuffer, buffer, currlen, maxlen, '0');
70359191Skris        --zpadlen;
70459191Skris    }
70559191Skris
70659191Skris    while (padlen < 0) {
70768651Skris        doapr_outch(sbuffer, buffer, currlen, maxlen, ' ');
70859191Skris        ++padlen;
70959191Skris    }
71059191Skris}
71159191Skris
71259191Skrisstatic void
71368651Skrisdoapr_outch(
71468651Skris    char **sbuffer,
71559191Skris    char **buffer,
71659191Skris    size_t *currlen,
71759191Skris    size_t *maxlen,
71859191Skris    int c)
71959191Skris{
72068651Skris    /* If we haven't at least one buffer, someone has doe a big booboo */
72168651Skris    assert(*sbuffer != NULL || buffer != NULL);
72259191Skris
72368651Skris    if (buffer) {
72468651Skris	while (*currlen >= *maxlen) {
72568651Skris	    if (*buffer == NULL) {
72668651Skris		if (*maxlen == 0)
72768651Skris		    *maxlen = 1024;
72868651Skris		*buffer = OPENSSL_malloc(*maxlen);
729100928Snectar		if (*currlen > 0) {
730100928Snectar		    assert(*sbuffer != NULL);
73168651Skris		    memcpy(*buffer, *sbuffer, *currlen);
732100928Snectar		}
73368651Skris		*sbuffer = NULL;
73468651Skris	    } else {
73568651Skris		*maxlen += 1024;
73668651Skris		*buffer = OPENSSL_realloc(*buffer, *maxlen);
73768651Skris	    }
73868651Skris	}
73968651Skris	/* What to do if *buffer is NULL? */
74068651Skris	assert(*sbuffer != NULL || *buffer != NULL);
74159191Skris    }
74268651Skris
74368651Skris    if (*currlen < *maxlen) {
74468651Skris	if (*sbuffer)
74568651Skris	    (*sbuffer)[(*currlen)++] = (char)c;
74668651Skris	else
74768651Skris	    (*buffer)[(*currlen)++] = (char)c;
74859191Skris    }
74959191Skris
75059191Skris    return;
75159191Skris}
75268651Skris
75368651Skris/***************************************************************************/
75468651Skris
75568651Skrisint BIO_printf (BIO *bio, const char *format, ...)
75668651Skris	{
75768651Skris	va_list args;
75868651Skris	int ret;
75968651Skris
76068651Skris	va_start(args, format);
76168651Skris
76268651Skris	ret = BIO_vprintf(bio, format, args);
76368651Skris
76468651Skris	va_end(args);
76568651Skris	return(ret);
76668651Skris	}
76768651Skris
76868651Skrisint BIO_vprintf (BIO *bio, const char *format, va_list args)
76968651Skris	{
77068651Skris	int ret;
77168651Skris	size_t retlen;
772100928Snectar	char hugebuf[1024*2];	/* Was previously 10k, which is unreasonable
773100928Snectar				   in small-stack environments, like threads
774100928Snectar				   or DOS programs. */
77568651Skris	char *hugebufp = hugebuf;
77668651Skris	size_t hugebufsize = sizeof(hugebuf);
77768651Skris	char *dynbuf = NULL;
77868651Skris	int ignored;
77968651Skris
78068651Skris	dynbuf = NULL;
78168651Skris	CRYPTO_push_info("doapr()");
78268651Skris	_dopr(&hugebufp, &dynbuf, &hugebufsize,
78368651Skris		&retlen, &ignored, format, args);
78468651Skris	if (dynbuf)
78568651Skris		{
78668651Skris		ret=BIO_write(bio, dynbuf, (int)retlen);
78768651Skris		OPENSSL_free(dynbuf);
78868651Skris		}
78968651Skris	else
79068651Skris		{
79168651Skris		ret=BIO_write(bio, hugebuf, (int)retlen);
79268651Skris		}
79368651Skris	CRYPTO_pop_info();
79468651Skris	return(ret);
79568651Skris	}
79668651Skris
79768651Skris/* As snprintf is not available everywhere, we provide our own implementation.
79868651Skris * This function has nothing to do with BIOs, but it's closely related
79968651Skris * to BIO_printf, and we need *some* name prefix ...
80068651Skris * (XXX  the function should be renamed, but to what?) */
80168651Skrisint BIO_snprintf(char *buf, size_t n, const char *format, ...)
80268651Skris	{
80368651Skris	va_list args;
80468651Skris	int ret;
80568651Skris
80668651Skris	va_start(args, format);
80768651Skris
80868651Skris	ret = BIO_vsnprintf(buf, n, format, args);
80968651Skris
81068651Skris	va_end(args);
81168651Skris	return(ret);
81268651Skris	}
81368651Skris
81468651Skrisint BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args)
81568651Skris	{
81668651Skris	size_t retlen;
81768651Skris	int truncated;
81868651Skris
81968651Skris	_dopr(&buf, NULL, &n, &retlen, &truncated, format, args);
82068651Skris
82168651Skris	if (truncated)
82268651Skris		/* In case of truncation, return -1 like traditional snprintf.
82368651Skris		 * (Current drafts for ISO/IEC 9899 say snprintf should return
82468651Skris		 * the number of characters that would have been written,
82568651Skris		 * had the buffer been large enough.) */
82668651Skris		return -1;
82768651Skris	else
82868651Skris		return (retlen <= INT_MAX) ? retlen : -1;
82968651Skris	}
830