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