os/ossrv/ssl/libcrypto/src/crypto/bio/b_print.c
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
/* crypto/bio/b_print.c */
sl@0
     2
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
sl@0
     3
 * All rights reserved.
sl@0
     4
 *
sl@0
     5
 * This package is an SSL implementation written
sl@0
     6
 * by Eric Young (eay@cryptsoft.com).
sl@0
     7
 * The implementation was written so as to conform with Netscapes SSL.
sl@0
     8
 * 
sl@0
     9
 * This library is free for commercial and non-commercial use as long as
sl@0
    10
 * the following conditions are aheared to.  The following conditions
sl@0
    11
 * apply to all code found in this distribution, be it the RC4, RSA,
sl@0
    12
 * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
sl@0
    13
 * included with this distribution is covered by the same copyright terms
sl@0
    14
 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
sl@0
    15
 * 
sl@0
    16
 * Copyright remains Eric Young's, and as such any Copyright notices in
sl@0
    17
 * the code are not to be removed.
sl@0
    18
 * If this package is used in a product, Eric Young should be given attribution
sl@0
    19
 * as the author of the parts of the library used.
sl@0
    20
 * This can be in the form of a textual message at program startup or
sl@0
    21
 * in documentation (online or textual) provided with the package.
sl@0
    22
 * 
sl@0
    23
 * Redistribution and use in source and binary forms, with or without
sl@0
    24
 * modification, are permitted provided that the following conditions
sl@0
    25
 * are met:
sl@0
    26
 * 1. Redistributions of source code must retain the copyright
sl@0
    27
 *    notice, this list of conditions and the following disclaimer.
sl@0
    28
 * 2. Redistributions in binary form must reproduce the above copyright
sl@0
    29
 *    notice, this list of conditions and the following disclaimer in the
sl@0
    30
 *    documentation and/or other materials provided with the distribution.
sl@0
    31
 * 3. All advertising materials mentioning features or use of this software
sl@0
    32
 *    must display the following acknowledgement:
sl@0
    33
 *    "This product includes cryptographic software written by
sl@0
    34
 *     Eric Young (eay@cryptsoft.com)"
sl@0
    35
 *    The word 'cryptographic' can be left out if the rouines from the library
sl@0
    36
 *    being used are not cryptographic related :-).
sl@0
    37
 * 4. If you include any Windows specific code (or a derivative thereof) from 
sl@0
    38
 *    the apps directory (application code) you must include an acknowledgement:
sl@0
    39
 *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
sl@0
    40
 * 
sl@0
    41
 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
sl@0
    42
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
sl@0
    43
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
sl@0
    44
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
sl@0
    45
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
sl@0
    46
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
sl@0
    47
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
sl@0
    48
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
sl@0
    49
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
sl@0
    50
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
sl@0
    51
 * SUCH DAMAGE.
sl@0
    52
 * 
sl@0
    53
 * The licence and distribution terms for any publically available version or
sl@0
    54
 * derivative of this code cannot be changed.  i.e. this code cannot simply be
sl@0
    55
 * copied and put under another distribution licence
sl@0
    56
 * [including the GNU Public Licence.]
sl@0
    57
 */
sl@0
    58
/*
sl@0
    59
 © Portions copyright (c) 2006 Nokia Corporation.  All rights reserved.
sl@0
    60
 */
sl@0
    61
/* disable assert() unless BIO_DEBUG has been defined */
sl@0
    62
#ifndef BIO_DEBUG
sl@0
    63
# ifndef NDEBUG
sl@0
    64
#  define NDEBUG
sl@0
    65
# endif
sl@0
    66
#endif
sl@0
    67
sl@0
    68
/* 
sl@0
    69
 * Stolen from tjh's ssl/ssl_trc.c stuff.
sl@0
    70
 */
sl@0
    71
sl@0
    72
#include <stdio.h>
sl@0
    73
#include <string.h>
sl@0
    74
#include <ctype.h>
sl@0
    75
#include <assert.h>
sl@0
    76
#include <limits.h>
sl@0
    77
#include "cryptlib.h"
sl@0
    78
#ifndef NO_SYS_TYPES_H
sl@0
    79
#include <sys/types.h>
sl@0
    80
#endif
sl@0
    81
#include <openssl/bn.h>         /* To get BN_LLONG properly defined */
sl@0
    82
#include <openssl/bio.h>
sl@0
    83
sl@0
    84
#if defined(BN_LLONG) || defined(SIXTY_FOUR_BIT)
sl@0
    85
# ifndef HAVE_LONG_LONG
sl@0
    86
#  define HAVE_LONG_LONG 1
sl@0
    87
# endif
sl@0
    88
#endif
sl@0
    89
sl@0
    90
/***************************************************************************/
sl@0
    91
sl@0
    92
/*
sl@0
    93
 * Copyright Patrick Powell 1995
sl@0
    94
 * This code is based on code written by Patrick Powell <papowell@astart.com>
sl@0
    95
 * It may be used for any purpose as long as this notice remains intact
sl@0
    96
 * on all source code distributions.
sl@0
    97
 */
sl@0
    98
sl@0
    99
/*
sl@0
   100
 * This code contains numerious changes and enhancements which were
sl@0
   101
 * made by lots of contributors over the last years to Patrick Powell's
sl@0
   102
 * original code:
sl@0
   103
 *
sl@0
   104
 * o Patrick Powell <papowell@astart.com>      (1995)
sl@0
   105
 * o Brandon Long <blong@fiction.net>          (1996, for Mutt)
sl@0
   106
 * o Thomas Roessler <roessler@guug.de>        (1998, for Mutt)
sl@0
   107
 * o Michael Elkins <me@cs.hmc.edu>            (1998, for Mutt)
sl@0
   108
 * o Andrew Tridgell <tridge@samba.org>        (1998, for Samba)
sl@0
   109
 * o Luke Mewburn <lukem@netbsd.org>           (1999, for LukemFTP)
sl@0
   110
 * o Ralf S. Engelschall <rse@engelschall.com> (1999, for Pth)
sl@0
   111
 * o ...                                       (for OpenSSL)
sl@0
   112
 */
sl@0
   113
sl@0
   114
#ifdef HAVE_LONG_DOUBLE
sl@0
   115
#define LDOUBLE long double
sl@0
   116
#else
sl@0
   117
#define LDOUBLE double
sl@0
   118
#endif
sl@0
   119
sl@0
   120
#if HAVE_LONG_LONG
sl@0
   121
# if defined(OPENSSL_SYS_WIN32) && !defined(__GNUC__)
sl@0
   122
# define LLONG __int64
sl@0
   123
# else
sl@0
   124
# define LLONG long long
sl@0
   125
# endif
sl@0
   126
#else
sl@0
   127
#define LLONG long
sl@0
   128
#endif
sl@0
   129
sl@0
   130
static void fmtstr     (char **, char **, size_t *, size_t *,
sl@0
   131
			const char *, int, int, int);
sl@0
   132
static void fmtint     (char **, char **, size_t *, size_t *,
sl@0
   133
			LLONG, int, int, int, int);
sl@0
   134
static void fmtfp      (char **, char **, size_t *, size_t *,
sl@0
   135
			LDOUBLE, int, int, int);
sl@0
   136
static void doapr_outch (char **, char **, size_t *, size_t *, int);
sl@0
   137
static void _dopr(char **sbuffer, char **buffer,
sl@0
   138
		  size_t *maxlen, size_t *retlen, int *truncated,
sl@0
   139
		  const char *format, va_list args);
sl@0
   140
sl@0
   141
/* format read states */
sl@0
   142
#define DP_S_DEFAULT    0
sl@0
   143
#define DP_S_FLAGS      1
sl@0
   144
#define DP_S_MIN        2
sl@0
   145
#define DP_S_DOT        3
sl@0
   146
#define DP_S_MAX        4
sl@0
   147
#define DP_S_MOD        5
sl@0
   148
#define DP_S_CONV       6
sl@0
   149
#define DP_S_DONE       7
sl@0
   150
sl@0
   151
/* format flags - Bits */
sl@0
   152
#define DP_F_MINUS      (1 << 0)
sl@0
   153
#define DP_F_PLUS       (1 << 1)
sl@0
   154
#define DP_F_SPACE      (1 << 2)
sl@0
   155
#define DP_F_NUM        (1 << 3)
sl@0
   156
#define DP_F_ZERO       (1 << 4)
sl@0
   157
#define DP_F_UP         (1 << 5)
sl@0
   158
#define DP_F_UNSIGNED   (1 << 6)
sl@0
   159
sl@0
   160
/* conversion flags */
sl@0
   161
#define DP_C_SHORT      1
sl@0
   162
#define DP_C_LONG       2
sl@0
   163
#define DP_C_LDOUBLE    3
sl@0
   164
#define DP_C_LLONG      4
sl@0
   165
sl@0
   166
/* some handy macros */
sl@0
   167
#define char_to_int(p) (p - '0')
sl@0
   168
#define OSSL_MAX(p,q) ((p >= q) ? p : q)
sl@0
   169
sl@0
   170
static void
sl@0
   171
_dopr(
sl@0
   172
    char **sbuffer,
sl@0
   173
    char **buffer,
sl@0
   174
    size_t *maxlen,
sl@0
   175
    size_t *retlen,
sl@0
   176
    int *truncated,
sl@0
   177
    const char *format,
sl@0
   178
    va_list args)
sl@0
   179
{
sl@0
   180
    char ch;
sl@0
   181
    LLONG value;
sl@0
   182
    LDOUBLE fvalue;
sl@0
   183
    char *strvalue;
sl@0
   184
    int min;
sl@0
   185
    int max;
sl@0
   186
    int state;
sl@0
   187
    int flags;
sl@0
   188
    int cflags;
sl@0
   189
    size_t currlen;
sl@0
   190
sl@0
   191
    state = DP_S_DEFAULT;
sl@0
   192
    flags = currlen = cflags = min = 0;
sl@0
   193
    max = -1;
sl@0
   194
    ch = *format++;
sl@0
   195
sl@0
   196
    while (state != DP_S_DONE) {
sl@0
   197
        if (ch == '\0' || (buffer == NULL && currlen >= *maxlen))
sl@0
   198
            state = DP_S_DONE;
sl@0
   199
sl@0
   200
        switch (state) {
sl@0
   201
        case DP_S_DEFAULT:
sl@0
   202
            if (ch == '%')
sl@0
   203
                state = DP_S_FLAGS;
sl@0
   204
            else
sl@0
   205
                doapr_outch(sbuffer,buffer, &currlen, maxlen, ch);
sl@0
   206
            ch = *format++;
sl@0
   207
            break;
sl@0
   208
        case DP_S_FLAGS:
sl@0
   209
            switch (ch) {
sl@0
   210
            case '-':
sl@0
   211
                flags |= DP_F_MINUS;
sl@0
   212
                ch = *format++;
sl@0
   213
                break;
sl@0
   214
            case '+':
sl@0
   215
                flags |= DP_F_PLUS;
sl@0
   216
                ch = *format++;
sl@0
   217
                break;
sl@0
   218
            case ' ':
sl@0
   219
                flags |= DP_F_SPACE;
sl@0
   220
                ch = *format++;
sl@0
   221
                break;
sl@0
   222
            case '#':
sl@0
   223
                flags |= DP_F_NUM;
sl@0
   224
                ch = *format++;
sl@0
   225
                break;
sl@0
   226
            case '0':
sl@0
   227
                flags |= DP_F_ZERO;
sl@0
   228
                ch = *format++;
sl@0
   229
                break;
sl@0
   230
            default:
sl@0
   231
                state = DP_S_MIN;
sl@0
   232
                break;
sl@0
   233
            }
sl@0
   234
            break;
sl@0
   235
        case DP_S_MIN:
sl@0
   236
            if (isdigit((unsigned char)ch)) {
sl@0
   237
                min = 10 * min + char_to_int(ch);
sl@0
   238
                ch = *format++;
sl@0
   239
            } else if (ch == '*') {
sl@0
   240
                min = va_arg(args, int);
sl@0
   241
                ch = *format++;
sl@0
   242
                state = DP_S_DOT;
sl@0
   243
            } else
sl@0
   244
                state = DP_S_DOT;
sl@0
   245
            break;
sl@0
   246
        case DP_S_DOT:
sl@0
   247
            if (ch == '.') {
sl@0
   248
                state = DP_S_MAX;
sl@0
   249
                ch = *format++;
sl@0
   250
            } else
sl@0
   251
                state = DP_S_MOD;
sl@0
   252
            break;
sl@0
   253
        case DP_S_MAX:
sl@0
   254
            if (isdigit((unsigned char)ch)) {
sl@0
   255
                if (max < 0)
sl@0
   256
                    max = 0;
sl@0
   257
                max = 10 * max + char_to_int(ch);
sl@0
   258
                ch = *format++;
sl@0
   259
            } else if (ch == '*') {
sl@0
   260
                max = va_arg(args, int);
sl@0
   261
                ch = *format++;
sl@0
   262
                state = DP_S_MOD;
sl@0
   263
            } else
sl@0
   264
                state = DP_S_MOD;
sl@0
   265
            break;
sl@0
   266
        case DP_S_MOD:
sl@0
   267
            switch (ch) {
sl@0
   268
            case 'h':
sl@0
   269
                cflags = DP_C_SHORT;
sl@0
   270
                ch = *format++;
sl@0
   271
                break;
sl@0
   272
            case 'l':
sl@0
   273
                if (*format == 'l') {
sl@0
   274
                    cflags = DP_C_LLONG;
sl@0
   275
                    format++;
sl@0
   276
                } else
sl@0
   277
                    cflags = DP_C_LONG;
sl@0
   278
                ch = *format++;
sl@0
   279
                break;
sl@0
   280
            case 'q':
sl@0
   281
                cflags = DP_C_LLONG;
sl@0
   282
                ch = *format++;
sl@0
   283
                break;
sl@0
   284
            case 'L':
sl@0
   285
                cflags = DP_C_LDOUBLE;
sl@0
   286
                ch = *format++;
sl@0
   287
                break;
sl@0
   288
            default:
sl@0
   289
                break;
sl@0
   290
            }
sl@0
   291
            state = DP_S_CONV;
sl@0
   292
            break;
sl@0
   293
        case DP_S_CONV:
sl@0
   294
            switch (ch) {
sl@0
   295
            case 'd':
sl@0
   296
            case 'i':
sl@0
   297
                switch (cflags) {
sl@0
   298
                case DP_C_SHORT:
sl@0
   299
                    value = (short int)va_arg(args, int);
sl@0
   300
                    break;
sl@0
   301
                case DP_C_LONG:
sl@0
   302
                    value = va_arg(args, long int);
sl@0
   303
                    break;
sl@0
   304
                case DP_C_LLONG:
sl@0
   305
                    value = va_arg(args, LLONG);
sl@0
   306
                    break;
sl@0
   307
                default:
sl@0
   308
                    value = va_arg(args, int);
sl@0
   309
                    break;
sl@0
   310
                }
sl@0
   311
                fmtint(sbuffer, buffer, &currlen, maxlen,
sl@0
   312
                       value, 10, min, max, flags);
sl@0
   313
                break;
sl@0
   314
            case 'X':
sl@0
   315
                flags |= DP_F_UP;
sl@0
   316
                /* FALLTHROUGH */
sl@0
   317
            case 'x':
sl@0
   318
            case 'o':
sl@0
   319
            case 'u':
sl@0
   320
                flags |= DP_F_UNSIGNED;
sl@0
   321
                switch (cflags) {
sl@0
   322
                case DP_C_SHORT:
sl@0
   323
                    value = (unsigned short int)va_arg(args, unsigned int);
sl@0
   324
                    break;
sl@0
   325
                case DP_C_LONG:
sl@0
   326
                    value = (LLONG) va_arg(args,
sl@0
   327
                        unsigned long int);
sl@0
   328
                    break;
sl@0
   329
                case DP_C_LLONG:
sl@0
   330
                    value = va_arg(args, unsigned LLONG);
sl@0
   331
                    break;
sl@0
   332
                default:
sl@0
   333
                    value = (LLONG) va_arg(args,
sl@0
   334
                        unsigned int);
sl@0
   335
                    break;
sl@0
   336
                }
sl@0
   337
                fmtint(sbuffer, buffer, &currlen, maxlen, value,
sl@0
   338
                       ch == 'o' ? 8 : (ch == 'u' ? 10 : 16),
sl@0
   339
                       min, max, flags);
sl@0
   340
                break;
sl@0
   341
            case 'f':
sl@0
   342
                if (cflags == DP_C_LDOUBLE)
sl@0
   343
                    fvalue = va_arg(args, LDOUBLE);
sl@0
   344
                else
sl@0
   345
                    fvalue = va_arg(args, double);
sl@0
   346
                fmtfp(sbuffer, buffer, &currlen, maxlen,
sl@0
   347
                      fvalue, min, max, flags);
sl@0
   348
                break;
sl@0
   349
            case 'E':
sl@0
   350
                flags |= DP_F_UP;
sl@0
   351
            case 'e':
sl@0
   352
                if (cflags == DP_C_LDOUBLE)
sl@0
   353
                    fvalue = va_arg(args, LDOUBLE);
sl@0
   354
                else
sl@0
   355
                    fvalue = va_arg(args, double);
sl@0
   356
                break;
sl@0
   357
            case 'G':
sl@0
   358
                flags |= DP_F_UP;
sl@0
   359
            case 'g':
sl@0
   360
                if (cflags == DP_C_LDOUBLE)
sl@0
   361
                    fvalue = va_arg(args, LDOUBLE);
sl@0
   362
                else
sl@0
   363
                    fvalue = va_arg(args, double);
sl@0
   364
                break;
sl@0
   365
            case 'c':
sl@0
   366
                doapr_outch(sbuffer, buffer, &currlen, maxlen,
sl@0
   367
                    va_arg(args, int));
sl@0
   368
                break;
sl@0
   369
            case 's':
sl@0
   370
                strvalue = va_arg(args, char *);
sl@0
   371
                if (max < 0) {
sl@0
   372
		    if (buffer)
sl@0
   373
			max = INT_MAX;
sl@0
   374
		    else
sl@0
   375
			max = *maxlen;
sl@0
   376
		}
sl@0
   377
                fmtstr(sbuffer, buffer, &currlen, maxlen, strvalue,
sl@0
   378
                       flags, min, max);
sl@0
   379
                break;
sl@0
   380
            case 'p':
sl@0
   381
                value = (long)va_arg(args, void *);
sl@0
   382
                fmtint(sbuffer, buffer, &currlen, maxlen,
sl@0
   383
                    value, 16, min, max, flags|DP_F_NUM);
sl@0
   384
                break;
sl@0
   385
            case 'n': /* XXX */
sl@0
   386
                if (cflags == DP_C_SHORT) {
sl@0
   387
                    short int *num;
sl@0
   388
                    num = va_arg(args, short int *);
sl@0
   389
                    *num = currlen;
sl@0
   390
                } else if (cflags == DP_C_LONG) { /* XXX */
sl@0
   391
                    long int *num;
sl@0
   392
                    num = va_arg(args, long int *);
sl@0
   393
                    *num = (long int) currlen;
sl@0
   394
                } else if (cflags == DP_C_LLONG) { /* XXX */
sl@0
   395
                    LLONG *num;
sl@0
   396
                    num = va_arg(args, LLONG *);
sl@0
   397
                    *num = (LLONG) currlen;
sl@0
   398
                } else {
sl@0
   399
                    int    *num;
sl@0
   400
                    num = va_arg(args, int *);
sl@0
   401
                    *num = currlen;
sl@0
   402
                }
sl@0
   403
                break;
sl@0
   404
            case '%':
sl@0
   405
                doapr_outch(sbuffer, buffer, &currlen, maxlen, ch);
sl@0
   406
                break;
sl@0
   407
            case 'w':
sl@0
   408
                /* not supported yet, treat as next char */
sl@0
   409
                ch = *format++;
sl@0
   410
                break;
sl@0
   411
            default:
sl@0
   412
                /* unknown, skip */
sl@0
   413
                break;
sl@0
   414
            }
sl@0
   415
            ch = *format++;
sl@0
   416
            state = DP_S_DEFAULT;
sl@0
   417
            flags = cflags = min = 0;
sl@0
   418
            max = -1;
sl@0
   419
            break;
sl@0
   420
        case DP_S_DONE:
sl@0
   421
            break;
sl@0
   422
        default:
sl@0
   423
            break;
sl@0
   424
        }
sl@0
   425
    }
sl@0
   426
    *truncated = (currlen > *maxlen - 1);
sl@0
   427
    if (*truncated)
sl@0
   428
        currlen = *maxlen - 1;
sl@0
   429
    doapr_outch(sbuffer, buffer, &currlen, maxlen, '\0');
sl@0
   430
    *retlen = currlen - 1;
sl@0
   431
    return;
sl@0
   432
}
sl@0
   433
sl@0
   434
static void
sl@0
   435
fmtstr(
sl@0
   436
    char **sbuffer,
sl@0
   437
    char **buffer,
sl@0
   438
    size_t *currlen,
sl@0
   439
    size_t *maxlen,
sl@0
   440
    const char *value,
sl@0
   441
    int flags,
sl@0
   442
    int min,
sl@0
   443
    int max)
sl@0
   444
{
sl@0
   445
    int padlen, strln;
sl@0
   446
    int cnt = 0;
sl@0
   447
sl@0
   448
    if (value == 0)
sl@0
   449
        value = "<NULL>";
sl@0
   450
    for (strln = 0; value[strln]; ++strln)
sl@0
   451
        ;
sl@0
   452
    padlen = min - strln;
sl@0
   453
    if (padlen < 0)
sl@0
   454
        padlen = 0;
sl@0
   455
    if (flags & DP_F_MINUS)
sl@0
   456
        padlen = -padlen;
sl@0
   457
sl@0
   458
    while ((padlen > 0) && (cnt < max)) {
sl@0
   459
        doapr_outch(sbuffer, buffer, currlen, maxlen, ' ');
sl@0
   460
        --padlen;
sl@0
   461
        ++cnt;
sl@0
   462
    }
sl@0
   463
    while (*value && (cnt < max)) {
sl@0
   464
        doapr_outch(sbuffer, buffer, currlen, maxlen, *value++);
sl@0
   465
        ++cnt;
sl@0
   466
    }
sl@0
   467
    while ((padlen < 0) && (cnt < max)) {
sl@0
   468
        doapr_outch(sbuffer, buffer, currlen, maxlen, ' ');
sl@0
   469
        ++padlen;
sl@0
   470
        ++cnt;
sl@0
   471
    }
sl@0
   472
}
sl@0
   473
sl@0
   474
static void
sl@0
   475
fmtint(
sl@0
   476
    char **sbuffer,
sl@0
   477
    char **buffer,
sl@0
   478
    size_t *currlen,
sl@0
   479
    size_t *maxlen,
sl@0
   480
    LLONG value,
sl@0
   481
    int base,
sl@0
   482
    int min,
sl@0
   483
    int max,
sl@0
   484
    int flags)
sl@0
   485
{
sl@0
   486
    int signvalue = 0;
sl@0
   487
    const char *prefix = "";
sl@0
   488
    unsigned LLONG uvalue;
sl@0
   489
    char convert[DECIMAL_SIZE(value)+3];
sl@0
   490
    int place = 0;
sl@0
   491
    int spadlen = 0;
sl@0
   492
    int zpadlen = 0;
sl@0
   493
    int caps = 0;
sl@0
   494
sl@0
   495
    if (max < 0)
sl@0
   496
        max = 0;
sl@0
   497
    uvalue = value;
sl@0
   498
    if (!(flags & DP_F_UNSIGNED)) {
sl@0
   499
        if (value < 0) {
sl@0
   500
            signvalue = '-';
sl@0
   501
            uvalue = -value;
sl@0
   502
        } else if (flags & DP_F_PLUS)
sl@0
   503
            signvalue = '+';
sl@0
   504
        else if (flags & DP_F_SPACE)
sl@0
   505
            signvalue = ' ';
sl@0
   506
    }
sl@0
   507
    if (flags & DP_F_NUM) {
sl@0
   508
	if (base == 8) prefix = "0";
sl@0
   509
	if (base == 16) prefix = "0x";
sl@0
   510
    }
sl@0
   511
    if (flags & DP_F_UP)
sl@0
   512
        caps = 1;
sl@0
   513
    do {
sl@0
   514
        convert[place++] =
sl@0
   515
            (caps ? "0123456789ABCDEF" : "0123456789abcdef")
sl@0
   516
            [uvalue % (unsigned) base];
sl@0
   517
        uvalue = (uvalue / (unsigned) base);
sl@0
   518
    } while (uvalue && (place < (int)sizeof(convert)));
sl@0
   519
    if (place == sizeof(convert))
sl@0
   520
        place--;
sl@0
   521
    convert[place] = 0;
sl@0
   522
sl@0
   523
    zpadlen = max - place;
sl@0
   524
    spadlen = min - OSSL_MAX(max, place) - (signvalue ? 1 : 0) - strlen(prefix);
sl@0
   525
    if (zpadlen < 0)
sl@0
   526
        zpadlen = 0;
sl@0
   527
    if (spadlen < 0)
sl@0
   528
        spadlen = 0;
sl@0
   529
    if (flags & DP_F_ZERO) {
sl@0
   530
        zpadlen = OSSL_MAX(zpadlen, spadlen);
sl@0
   531
        spadlen = 0;
sl@0
   532
    }
sl@0
   533
    if (flags & DP_F_MINUS)
sl@0
   534
        spadlen = -spadlen;
sl@0
   535
sl@0
   536
    /* spaces */
sl@0
   537
    while (spadlen > 0) {
sl@0
   538
        doapr_outch(sbuffer, buffer, currlen, maxlen, ' ');
sl@0
   539
        --spadlen;
sl@0
   540
    }
sl@0
   541
sl@0
   542
    /* sign */
sl@0
   543
    if (signvalue)
sl@0
   544
        doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue);
sl@0
   545
sl@0
   546
    /* prefix */
sl@0
   547
    while (*prefix) {
sl@0
   548
	doapr_outch(sbuffer, buffer, currlen, maxlen, *prefix);
sl@0
   549
	prefix++;
sl@0
   550
    }
sl@0
   551
sl@0
   552
    /* zeros */
sl@0
   553
    if (zpadlen > 0) {
sl@0
   554
        while (zpadlen > 0) {
sl@0
   555
            doapr_outch(sbuffer, buffer, currlen, maxlen, '0');
sl@0
   556
            --zpadlen;
sl@0
   557
        }
sl@0
   558
    }
sl@0
   559
    /* digits */
sl@0
   560
    while (place > 0)
sl@0
   561
        doapr_outch(sbuffer, buffer, currlen, maxlen, convert[--place]);
sl@0
   562
sl@0
   563
    /* left justified spaces */
sl@0
   564
    while (spadlen < 0) {
sl@0
   565
        doapr_outch(sbuffer, buffer, currlen, maxlen, ' ');
sl@0
   566
        ++spadlen;
sl@0
   567
    }
sl@0
   568
    return;
sl@0
   569
}
sl@0
   570
sl@0
   571
static LDOUBLE
sl@0
   572
abs_val(LDOUBLE value)
sl@0
   573
{
sl@0
   574
    LDOUBLE result = value;
sl@0
   575
    if (value < 0)
sl@0
   576
        result = -value;
sl@0
   577
    return result;
sl@0
   578
}
sl@0
   579
sl@0
   580
static LDOUBLE
sl@0
   581
pow_10(int in_exp)
sl@0
   582
{
sl@0
   583
    LDOUBLE result = 1;
sl@0
   584
    while (in_exp) {
sl@0
   585
        result *= 10;
sl@0
   586
        in_exp--;
sl@0
   587
    }
sl@0
   588
    return result;
sl@0
   589
}
sl@0
   590
sl@0
   591
static long
sl@0
   592
roundv(LDOUBLE value)
sl@0
   593
{
sl@0
   594
    long intpart;
sl@0
   595
    intpart = (long) value;
sl@0
   596
    value = value - intpart;
sl@0
   597
    if (value >= 0.5)
sl@0
   598
        intpart++;
sl@0
   599
    return intpart;
sl@0
   600
}
sl@0
   601
sl@0
   602
static void
sl@0
   603
fmtfp(
sl@0
   604
    char **sbuffer,
sl@0
   605
    char **buffer,
sl@0
   606
    size_t *currlen,
sl@0
   607
    size_t *maxlen,
sl@0
   608
    LDOUBLE fvalue,
sl@0
   609
    int min,
sl@0
   610
    int max,
sl@0
   611
    int flags)
sl@0
   612
{
sl@0
   613
    int signvalue = 0;
sl@0
   614
    LDOUBLE ufvalue;
sl@0
   615
    char iconvert[20];
sl@0
   616
    char fconvert[20];
sl@0
   617
    int iplace = 0;
sl@0
   618
    int fplace = 0;
sl@0
   619
    int padlen = 0;
sl@0
   620
    int zpadlen = 0;
sl@0
   621
    int caps = 0;
sl@0
   622
    long intpart;
sl@0
   623
    long fracpart;
sl@0
   624
    long max10;
sl@0
   625
sl@0
   626
    if (max < 0)
sl@0
   627
        max = 6;
sl@0
   628
    ufvalue = abs_val(fvalue);
sl@0
   629
    if (fvalue < 0)
sl@0
   630
        signvalue = '-';
sl@0
   631
    else if (flags & DP_F_PLUS)
sl@0
   632
        signvalue = '+';
sl@0
   633
    else if (flags & DP_F_SPACE)
sl@0
   634
        signvalue = ' ';
sl@0
   635
sl@0
   636
    intpart = (long)ufvalue;
sl@0
   637
sl@0
   638
    /* sorry, we only support 9 digits past the decimal because of our
sl@0
   639
       conversion method */
sl@0
   640
    if (max > 9)
sl@0
   641
        max = 9;
sl@0
   642
sl@0
   643
    /* we "cheat" by converting the fractional part to integer by
sl@0
   644
       multiplying by a factor of 10 */
sl@0
   645
    max10 = roundv(pow_10(max));
sl@0
   646
    fracpart = roundv(pow_10(max) * (ufvalue - intpart));
sl@0
   647
sl@0
   648
    if (fracpart >= max10) {
sl@0
   649
        intpart++;
sl@0
   650
        fracpart -= max10;
sl@0
   651
    }
sl@0
   652
sl@0
   653
    /* convert integer part */
sl@0
   654
    do {
sl@0
   655
        iconvert[iplace++] =
sl@0
   656
            (caps ? "0123456789ABCDEF"
sl@0
   657
              : "0123456789abcdef")[intpart % 10];
sl@0
   658
        intpart = (intpart / 10);
sl@0
   659
    } while (intpart && (iplace < (int)sizeof(iconvert)));
sl@0
   660
    if (iplace == sizeof iconvert)
sl@0
   661
        iplace--;
sl@0
   662
    iconvert[iplace] = 0;
sl@0
   663
sl@0
   664
    /* convert fractional part */
sl@0
   665
    do {
sl@0
   666
        fconvert[fplace++] =
sl@0
   667
            (caps ? "0123456789ABCDEF"
sl@0
   668
              : "0123456789abcdef")[fracpart % 10];
sl@0
   669
        fracpart = (fracpart / 10);
sl@0
   670
    } while (fplace < max);
sl@0
   671
    if (fplace == sizeof fconvert)
sl@0
   672
        fplace--;
sl@0
   673
    fconvert[fplace] = 0;
sl@0
   674
sl@0
   675
    /* -1 for decimal point, another -1 if we are printing a sign */
sl@0
   676
    padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0);
sl@0
   677
    zpadlen = max - fplace;
sl@0
   678
    if (zpadlen < 0)
sl@0
   679
        zpadlen = 0;
sl@0
   680
    if (padlen < 0)
sl@0
   681
        padlen = 0;
sl@0
   682
    if (flags & DP_F_MINUS)
sl@0
   683
        padlen = -padlen;
sl@0
   684
sl@0
   685
    if ((flags & DP_F_ZERO) && (padlen > 0)) {
sl@0
   686
        if (signvalue) {
sl@0
   687
            doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue);
sl@0
   688
            --padlen;
sl@0
   689
            signvalue = 0;
sl@0
   690
        }
sl@0
   691
        while (padlen > 0) {
sl@0
   692
            doapr_outch(sbuffer, buffer, currlen, maxlen, '0');
sl@0
   693
            --padlen;
sl@0
   694
        }
sl@0
   695
    }
sl@0
   696
    while (padlen > 0) {
sl@0
   697
        doapr_outch(sbuffer, buffer, currlen, maxlen, ' ');
sl@0
   698
        --padlen;
sl@0
   699
    }
sl@0
   700
    if (signvalue)
sl@0
   701
        doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue);
sl@0
   702
sl@0
   703
    while (iplace > 0)
sl@0
   704
        doapr_outch(sbuffer, buffer, currlen, maxlen, iconvert[--iplace]);
sl@0
   705
sl@0
   706
    /*
sl@0
   707
     * Decimal point. This should probably use locale to find the correct
sl@0
   708
     * char to print out.
sl@0
   709
     */
sl@0
   710
    if (max > 0 || (flags & DP_F_NUM)) {
sl@0
   711
        doapr_outch(sbuffer, buffer, currlen, maxlen, '.');
sl@0
   712
sl@0
   713
        while (fplace > 0)
sl@0
   714
            doapr_outch(sbuffer, buffer, currlen, maxlen, fconvert[--fplace]);
sl@0
   715
    }
sl@0
   716
    while (zpadlen > 0) {
sl@0
   717
        doapr_outch(sbuffer, buffer, currlen, maxlen, '0');
sl@0
   718
        --zpadlen;
sl@0
   719
    }
sl@0
   720
sl@0
   721
    while (padlen < 0) {
sl@0
   722
        doapr_outch(sbuffer, buffer, currlen, maxlen, ' ');
sl@0
   723
        ++padlen;
sl@0
   724
    }
sl@0
   725
}
sl@0
   726
sl@0
   727
static void
sl@0
   728
doapr_outch(
sl@0
   729
    char **sbuffer,
sl@0
   730
    char **buffer,
sl@0
   731
    size_t *currlen,
sl@0
   732
    size_t *maxlen,
sl@0
   733
    int c)
sl@0
   734
{
sl@0
   735
    /* If we haven't at least one buffer, someone has doe a big booboo */
sl@0
   736
    assert(*sbuffer != NULL || buffer != NULL);
sl@0
   737
sl@0
   738
    if (buffer) {
sl@0
   739
	while (*currlen >= *maxlen) {
sl@0
   740
	    if (*buffer == NULL) {
sl@0
   741
		if (*maxlen == 0)
sl@0
   742
		    *maxlen = 1024;
sl@0
   743
		*buffer = OPENSSL_malloc(*maxlen);
sl@0
   744
		if (*currlen > 0) {
sl@0
   745
		    assert(*sbuffer != NULL);
sl@0
   746
		    memcpy(*buffer, *sbuffer, *currlen);
sl@0
   747
		}
sl@0
   748
		*sbuffer = NULL;
sl@0
   749
	    } else {
sl@0
   750
		*maxlen += 1024;
sl@0
   751
		*buffer = OPENSSL_realloc(*buffer, *maxlen);
sl@0
   752
	    }
sl@0
   753
	}
sl@0
   754
	/* What to do if *buffer is NULL? */
sl@0
   755
	assert(*sbuffer != NULL || *buffer != NULL);
sl@0
   756
    }
sl@0
   757
sl@0
   758
    if (*currlen < *maxlen) {
sl@0
   759
	if (*sbuffer)
sl@0
   760
	    (*sbuffer)[(*currlen)++] = (char)c;
sl@0
   761
	else
sl@0
   762
	    (*buffer)[(*currlen)++] = (char)c;
sl@0
   763
    }
sl@0
   764
sl@0
   765
    return;
sl@0
   766
}
sl@0
   767
sl@0
   768
/***************************************************************************/
sl@0
   769
sl@0
   770
EXPORT_C int BIO_printf (BIO *bio, const char *format, ...)
sl@0
   771
	{
sl@0
   772
	va_list args;
sl@0
   773
	int ret;
sl@0
   774
sl@0
   775
	va_start(args, format);
sl@0
   776
sl@0
   777
	ret = BIO_vprintf(bio, format, args);
sl@0
   778
sl@0
   779
	va_end(args);
sl@0
   780
	return(ret);
sl@0
   781
	}
sl@0
   782
sl@0
   783
EXPORT_C int BIO_vprintf (BIO *bio, const char *format, va_list args)
sl@0
   784
	{
sl@0
   785
	int ret;
sl@0
   786
	size_t retlen;
sl@0
   787
	#ifndef SYMBIAN
sl@0
   788
	char hugebuf[1024*2];	/* Was previously 10k, which is unreasonable
sl@0
   789
				   in small-stack environments, like threads
sl@0
   790
				   or DOS programs. */
sl@0
   791
#else
sl@0
   792
  char hugebuf[512];
sl@0
   793
#endif				   
sl@0
   794
	char *hugebufp = hugebuf;
sl@0
   795
	size_t hugebufsize = sizeof(hugebuf);
sl@0
   796
	char *dynbuf = NULL;
sl@0
   797
	int ignored;
sl@0
   798
sl@0
   799
	dynbuf = NULL;
sl@0
   800
	CRYPTO_push_info("doapr()");
sl@0
   801
	_dopr(&hugebufp, &dynbuf, &hugebufsize,
sl@0
   802
		&retlen, &ignored, format, args);
sl@0
   803
	if (dynbuf)
sl@0
   804
		{
sl@0
   805
		ret=BIO_write(bio, dynbuf, (int)retlen);
sl@0
   806
		OPENSSL_free(dynbuf);
sl@0
   807
		}
sl@0
   808
	else
sl@0
   809
		{
sl@0
   810
		ret=BIO_write(bio, hugebuf, (int)retlen);
sl@0
   811
		}
sl@0
   812
	CRYPTO_pop_info();
sl@0
   813
	return(ret);
sl@0
   814
	}
sl@0
   815
sl@0
   816
/* As snprintf is not available everywhere, we provide our own implementation.
sl@0
   817
 * This function has nothing to do with BIOs, but it's closely related
sl@0
   818
 * to BIO_printf, and we need *some* name prefix ...
sl@0
   819
 * (XXX  the function should be renamed, but to what?) */
sl@0
   820
EXPORT_C int BIO_snprintf(char *buf, size_t n, const char *format, ...)
sl@0
   821
	{
sl@0
   822
	va_list args;
sl@0
   823
	int ret;
sl@0
   824
sl@0
   825
	va_start(args, format);
sl@0
   826
sl@0
   827
	ret = BIO_vsnprintf(buf, n, format, args);
sl@0
   828
sl@0
   829
	va_end(args);
sl@0
   830
	return(ret);
sl@0
   831
	}
sl@0
   832
sl@0
   833
EXPORT_C int BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args)
sl@0
   834
	{
sl@0
   835
	size_t retlen;
sl@0
   836
	int truncated;
sl@0
   837
sl@0
   838
	_dopr(&buf, NULL, &n, &retlen, &truncated, format, args);
sl@0
   839
sl@0
   840
	if (truncated)
sl@0
   841
		/* In case of truncation, return -1 like traditional snprintf.
sl@0
   842
		 * (Current drafts for ISO/IEC 9899 say snprintf should return
sl@0
   843
		 * the number of characters that would have been written,
sl@0
   844
		 * had the buffer been large enough.) */
sl@0
   845
		return -1;
sl@0
   846
	else
sl@0
   847
		return (retlen <= INT_MAX) ? (int)retlen : -1;
sl@0
   848
	}