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