os/ossrv/ssl/libcrypto/src/crypto/bio/b_print.c
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     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 	}