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