b_print.c revision 120631
1191783Srmacklem/* crypto/bio/b_print.c */ 2191783Srmacklem/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 3191783Srmacklem * All rights reserved. 4191783Srmacklem * 5191783Srmacklem * This package is an SSL implementation written 6191783Srmacklem * by Eric Young (eay@cryptsoft.com). 7191783Srmacklem * The implementation was written so as to conform with Netscapes SSL. 8191783Srmacklem * 9191783Srmacklem * This library is free for commercial and non-commercial use as long as 10191783Srmacklem * the following conditions are aheared to. The following conditions 11191783Srmacklem * apply to all code found in this distribution, be it the RC4, RSA, 12191783Srmacklem * lhash, DES, etc., code; not just the SSL code. The SSL documentation 13191783Srmacklem * included with this distribution is covered by the same copyright terms 14191783Srmacklem * except that the holder is Tim Hudson (tjh@cryptsoft.com). 15191783Srmacklem * 16191783Srmacklem * Copyright remains Eric Young's, and as such any Copyright notices in 17191783Srmacklem * the code are not to be removed. 18191783Srmacklem * If this package is used in a product, Eric Young should be given attribution 19191783Srmacklem * as the author of the parts of the library used. 20191783Srmacklem * This can be in the form of a textual message at program startup or 21191783Srmacklem * in documentation (online or textual) provided with the package. 22191783Srmacklem * 23191783Srmacklem * Redistribution and use in source and binary forms, with or without 24191783Srmacklem * modification, are permitted provided that the following conditions 25191783Srmacklem * are met: 26191783Srmacklem * 1. Redistributions of source code must retain the copyright 27191783Srmacklem * notice, this list of conditions and the following disclaimer. 28191783Srmacklem * 2. Redistributions in binary form must reproduce the above copyright 29191783Srmacklem * notice, this list of conditions and the following disclaimer in the 30191783Srmacklem * documentation and/or other materials provided with the distribution. 31191783Srmacklem * 3. All advertising materials mentioning features or use of this software 32191783Srmacklem * must display the following acknowledgement: 33191783Srmacklem * "This product includes cryptographic software written by 34191783Srmacklem * Eric Young (eay@cryptsoft.com)" 35191783Srmacklem * The word 'cryptographic' can be left out if the rouines from the library 36191783Srmacklem * being used are not cryptographic related :-). 37191783Srmacklem * 4. If you include any Windows specific code (or a derivative thereof) from 38191783Srmacklem * the apps directory (application code) you must include an acknowledgement: 39191783Srmacklem * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 40191783Srmacklem * 41191783Srmacklem * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 42221523Smav * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43191783Srmacklem * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 44191783Srmacklem * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 45191783Srmacklem * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 46191783Srmacklem * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 47191783Srmacklem * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48191783Srmacklem * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 49191783Srmacklem * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 50191783Srmacklem * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 51191783Srmacklem * SUCH DAMAGE. 52191783Srmacklem * 53269398Srmacklem * The licence and distribution terms for any publically available version or 54269398Srmacklem * derivative of this code cannot be changed. i.e. this code cannot simply be 55191783Srmacklem * copied and put under another distribution licence 56191783Srmacklem * [including the GNU Public Licence.] 57191783Srmacklem */ 58191783Srmacklem 59191783Srmacklem/* disable assert() unless BIO_DEBUG has been defined */ 60191783Srmacklem#ifndef BIO_DEBUG 61220739Srmacklem# ifndef NDEBUG 62191783Srmacklem# define NDEBUG 63191783Srmacklem# endif 64191783Srmacklem#endif 65191783Srmacklem 66191783Srmacklem/* 67191783Srmacklem * Stolen from tjh's ssl/ssl_trc.c stuff. 68191783Srmacklem */ 69191783Srmacklem 70191783Srmacklem#include <stdio.h> 71191783Srmacklem#include <string.h> 72191783Srmacklem#include <ctype.h> 73191783Srmacklem#include <assert.h> 74191783Srmacklem#include <limits.h> 75191783Srmacklem#include "cryptlib.h" 76220683Srmacklem#ifndef NO_SYS_TYPES_H 77220683Srmacklem#include <sys/types.h> 78220683Srmacklem#endif 79191783Srmacklem#include <openssl/bn.h> /* To get BN_LLONG properly defined */ 80191783Srmacklem#include <openssl/bio.h> 81191783Srmacklem 82191783Srmacklem#ifdef BN_LLONG 83191783Srmacklem# ifndef HAVE_LONG_LONG 84191783Srmacklem# define HAVE_LONG_LONG 1 85191783Srmacklem# endif 86191783Srmacklem#endif 87191783Srmacklem 88191783Srmacklem/***************************************************************************/ 89191783Srmacklem 90191783Srmacklem/* 91191783Srmacklem * Copyright Patrick Powell 1995 92191783Srmacklem * This code is based on code written by Patrick Powell <papowell@astart.com> 93191783Srmacklem * It may be used for any purpose as long as this notice remains intact 94191783Srmacklem * on all source code distributions. 95269398Srmacklem */ 96269398Srmacklem 97269398Srmacklem/* 98191783Srmacklem * This code contains numerious changes and enhancements which were 99191783Srmacklem * made by lots of contributors over the last years to Patrick Powell's 100191783Srmacklem * original code: 101191783Srmacklem * 102191783Srmacklem * o Patrick Powell <papowell@astart.com> (1995) 103191783Srmacklem * o Brandon Long <blong@fiction.net> (1996, for Mutt) 104191783Srmacklem * o Thomas Roessler <roessler@guug.de> (1998, for Mutt) 105191783Srmacklem * o Michael Elkins <me@cs.hmc.edu> (1998, for Mutt) 106191783Srmacklem * o Andrew Tridgell <tridge@samba.org> (1998, for Samba) 107191783Srmacklem * o Luke Mewburn <lukem@netbsd.org> (1999, for LukemFTP) 108244042Srmacklem * o Ralf S. Engelschall <rse@engelschall.com> (1999, for Pth) 109244042Srmacklem * o ... (for OpenSSL) 110244042Srmacklem */ 111191783Srmacklem 112191783Srmacklem#ifdef HAVE_LONG_DOUBLE 113191783Srmacklem#define LDOUBLE long double 114191783Srmacklem#else 115191783Srmacklem#define LDOUBLE double 116191783Srmacklem#endif 117191783Srmacklem 118191783Srmacklem#if HAVE_LONG_LONG 119191783Srmacklem# if defined(OPENSSL_SYS_WIN32) && !defined(__GNUC__) 120191783Srmacklem# define LLONG _int64 121191783Srmacklem# else 122191783Srmacklem# define LLONG long long 123191783Srmacklem# endif 124191783Srmacklem#else 125191783Srmacklem#define LLONG long 126191783Srmacklem#endif 127191783Srmacklem 128191783Srmacklemstatic void fmtstr (char **, char **, size_t *, size_t *, 129191783Srmacklem const char *, int, int, int); 130191783Srmacklemstatic void fmtint (char **, char **, size_t *, size_t *, 131191783Srmacklem LLONG, int, int, int, int); 132191783Srmacklemstatic void fmtfp (char **, char **, size_t *, size_t *, 133191783Srmacklem LDOUBLE, int, int, int); 134191783Srmacklemstatic void doapr_outch (char **, char **, size_t *, size_t *, int); 135191783Srmacklemstatic void _dopr(char **sbuffer, char **buffer, 136191783Srmacklem size_t *maxlen, size_t *retlen, int *truncated, 137191783Srmacklem const char *format, va_list args); 138191783Srmacklem 139191783Srmacklem/* format read states */ 140191783Srmacklem#define DP_S_DEFAULT 0 141191783Srmacklem#define DP_S_FLAGS 1 142191783Srmacklem#define DP_S_MIN 2 143191783Srmacklem#define DP_S_DOT 3 144191783Srmacklem#define DP_S_MAX 4 145191783Srmacklem#define DP_S_MOD 5 146191783Srmacklem#define DP_S_CONV 6 147191783Srmacklem#define DP_S_DONE 7 148191783Srmacklem 149191783Srmacklem/* format flags - Bits */ 150191783Srmacklem#define DP_F_MINUS (1 << 0) 151191783Srmacklem#define DP_F_PLUS (1 << 1) 152191783Srmacklem#define DP_F_SPACE (1 << 2) 153191783Srmacklem#define DP_F_NUM (1 << 3) 154191783Srmacklem#define DP_F_ZERO (1 << 4) 155191783Srmacklem#define DP_F_UP (1 << 5) 156191783Srmacklem#define DP_F_UNSIGNED (1 << 6) 157191783Srmacklem 158191783Srmacklem/* conversion flags */ 159191783Srmacklem#define DP_C_SHORT 1 160191783Srmacklem#define DP_C_LONG 2 161191783Srmacklem#define DP_C_LDOUBLE 3 162191783Srmacklem#define DP_C_LLONG 4 163191783Srmacklem 164191783Srmacklem/* some handy macros */ 165191783Srmacklem#define char_to_int(p) (p - '0') 166191783Srmacklem#define OSSL_MAX(p,q) ((p >= q) ? p : q) 167191783Srmacklem 168191783Srmacklemstatic void 169191783Srmacklem_dopr( 170192000Srmacklem char **sbuffer, 171191783Srmacklem char **buffer, 172191783Srmacklem size_t *maxlen, 173191783Srmacklem size_t *retlen, 174191783Srmacklem int *truncated, 175191783Srmacklem const char *format, 176191783Srmacklem va_list args) 177191783Srmacklem{ 178191783Srmacklem char ch; 179191783Srmacklem LLONG value; 180191783Srmacklem LDOUBLE fvalue; 181191783Srmacklem char *strvalue; 182191783Srmacklem int min; 183191783Srmacklem int max; 184191783Srmacklem int state; 185191783Srmacklem int flags; 186191783Srmacklem int cflags; 187191783Srmacklem size_t currlen; 188191783Srmacklem 189191783Srmacklem state = DP_S_DEFAULT; 190191783Srmacklem flags = currlen = cflags = min = 0; 191191783Srmacklem max = -1; 192191783Srmacklem ch = *format++; 193191783Srmacklem 194191783Srmacklem while (state != DP_S_DONE) { 195191783Srmacklem if (ch == '\0' || (buffer == NULL && currlen >= *maxlen)) 196191783Srmacklem state = DP_S_DONE; 197191783Srmacklem 198191783Srmacklem switch (state) { 199191783Srmacklem case DP_S_DEFAULT: 200191783Srmacklem if (ch == '%') 201191783Srmacklem state = DP_S_FLAGS; 202191783Srmacklem else 203191783Srmacklem doapr_outch(sbuffer,buffer, &currlen, maxlen, ch); 204191783Srmacklem ch = *format++; 205191783Srmacklem break; 206191783Srmacklem case DP_S_FLAGS: 207191783Srmacklem switch (ch) { 208191783Srmacklem case '-': 209191783Srmacklem flags |= DP_F_MINUS; 210191783Srmacklem ch = *format++; 211191783Srmacklem break; 212191783Srmacklem case '+': 213191783Srmacklem flags |= DP_F_PLUS; 214191783Srmacklem ch = *format++; 215191783Srmacklem break; 216191783Srmacklem case ' ': 217191783Srmacklem flags |= DP_F_SPACE; 218191783Srmacklem ch = *format++; 219191783Srmacklem break; 220191783Srmacklem case '#': 221191783Srmacklem flags |= DP_F_NUM; 222191783Srmacklem ch = *format++; 223191783Srmacklem break; 224191783Srmacklem case '0': 225191783Srmacklem flags |= DP_F_ZERO; 226191783Srmacklem ch = *format++; 227191783Srmacklem break; 228191783Srmacklem default: 229191783Srmacklem state = DP_S_MIN; 230191783Srmacklem break; 231191783Srmacklem } 232191783Srmacklem break; 233191783Srmacklem case DP_S_MIN: 234191783Srmacklem if (isdigit((unsigned char)ch)) { 235191783Srmacklem min = 10 * min + char_to_int(ch); 236191783Srmacklem ch = *format++; 237191783Srmacklem } else if (ch == '*') { 238191783Srmacklem min = va_arg(args, int); 239191783Srmacklem ch = *format++; 240191783Srmacklem state = DP_S_DOT; 241191783Srmacklem } else 242191783Srmacklem state = DP_S_DOT; 243191783Srmacklem break; 244191783Srmacklem case DP_S_DOT: 245191783Srmacklem if (ch == '.') { 246191783Srmacklem state = DP_S_MAX; 247191783Srmacklem ch = *format++; 248191783Srmacklem } else 249191783Srmacklem state = DP_S_MOD; 250191783Srmacklem break; 251191783Srmacklem case DP_S_MAX: 252191783Srmacklem if (isdigit((unsigned char)ch)) { 253191783Srmacklem if (max < 0) 254191783Srmacklem max = 0; 255191783Srmacklem max = 10 * max + char_to_int(ch); 256191783Srmacklem ch = *format++; 257191783Srmacklem } else if (ch == '*') { 258191783Srmacklem max = va_arg(args, int); 259191783Srmacklem ch = *format++; 260191783Srmacklem state = DP_S_MOD; 261191783Srmacklem } else 262191783Srmacklem state = DP_S_MOD; 263191783Srmacklem break; 264191783Srmacklem case DP_S_MOD: 265191783Srmacklem switch (ch) { 266191783Srmacklem case 'h': 267191783Srmacklem cflags = DP_C_SHORT; 268191783Srmacklem ch = *format++; 269191783Srmacklem break; 270191783Srmacklem case 'l': 271191783Srmacklem if (*format == 'l') { 272191783Srmacklem cflags = DP_C_LLONG; 273191783Srmacklem format++; 274191783Srmacklem } else 275191783Srmacklem cflags = DP_C_LONG; 276191783Srmacklem ch = *format++; 277191783Srmacklem break; 278191783Srmacklem case 'q': 279191783Srmacklem cflags = DP_C_LLONG; 280191783Srmacklem ch = *format++; 281191783Srmacklem break; 282191783Srmacklem case 'L': 283269398Srmacklem cflags = DP_C_LDOUBLE; 284269398Srmacklem ch = *format++; 285191783Srmacklem break; 286191783Srmacklem default: 287191783Srmacklem break; 288191783Srmacklem } 289191783Srmacklem state = DP_S_CONV; 290191783Srmacklem break; 291191783Srmacklem case DP_S_CONV: 292191783Srmacklem switch (ch) { 293191783Srmacklem case 'd': 294191783Srmacklem case 'i': 295191783Srmacklem switch (cflags) { 296191783Srmacklem case DP_C_SHORT: 297191783Srmacklem value = (short int)va_arg(args, int); 298191783Srmacklem break; 299191783Srmacklem case DP_C_LONG: 300191783Srmacklem value = va_arg(args, long int); 301191783Srmacklem break; 302191783Srmacklem case DP_C_LLONG: 303191783Srmacklem value = va_arg(args, LLONG); 304191783Srmacklem break; 305191783Srmacklem default: 306191783Srmacklem value = va_arg(args, int); 307191783Srmacklem break; 308191783Srmacklem } 309191783Srmacklem fmtint(sbuffer, buffer, &currlen, maxlen, 310191783Srmacklem value, 10, min, max, flags); 311191783Srmacklem break; 312191783Srmacklem case 'X': 313191783Srmacklem flags |= DP_F_UP; 314191783Srmacklem /* FALLTHROUGH */ 315191783Srmacklem case 'x': 316191783Srmacklem case 'o': 317191783Srmacklem case 'u': 318191783Srmacklem flags |= DP_F_UNSIGNED; 319191783Srmacklem switch (cflags) { 320191783Srmacklem case DP_C_SHORT: 321191783Srmacklem value = (unsigned short int)va_arg(args, unsigned int); 322191783Srmacklem break; 323191783Srmacklem case DP_C_LONG: 324191783Srmacklem value = (LLONG) va_arg(args, 325191783Srmacklem unsigned long int); 326191783Srmacklem break; 327269398Srmacklem case DP_C_LLONG: 328269398Srmacklem value = va_arg(args, unsigned LLONG); 329269398Srmacklem break; 330269398Srmacklem default: 331269398Srmacklem value = (LLONG) va_arg(args, 332191783Srmacklem unsigned int); 333191783Srmacklem break; 334191783Srmacklem } 335191783Srmacklem fmtint(sbuffer, buffer, &currlen, maxlen, value, 336191783Srmacklem ch == 'o' ? 8 : (ch == 'u' ? 10 : 16), 337191783Srmacklem min, max, flags); 338191783Srmacklem break; 339191783Srmacklem case 'f': 340191783Srmacklem if (cflags == DP_C_LDOUBLE) 341191783Srmacklem fvalue = va_arg(args, LDOUBLE); 342191783Srmacklem else 343191783Srmacklem fvalue = va_arg(args, double); 344191783Srmacklem fmtfp(sbuffer, buffer, &currlen, maxlen, 345191783Srmacklem fvalue, min, max, flags); 346191783Srmacklem break; 347191783Srmacklem case 'E': 348191783Srmacklem flags |= DP_F_UP; 349191783Srmacklem case 'e': 350191783Srmacklem if (cflags == DP_C_LDOUBLE) 351191783Srmacklem fvalue = va_arg(args, LDOUBLE); 352191783Srmacklem else 353191783Srmacklem fvalue = va_arg(args, double); 354191783Srmacklem break; 355269398Srmacklem case 'G': 356191783Srmacklem flags |= DP_F_UP; 357191783Srmacklem case 'g': 358191783Srmacklem if (cflags == DP_C_LDOUBLE) 359191783Srmacklem fvalue = va_arg(args, LDOUBLE); 360191783Srmacklem else 361269398Srmacklem fvalue = va_arg(args, double); 362269398Srmacklem break; 363269398Srmacklem case 'c': 364269398Srmacklem doapr_outch(sbuffer, buffer, &currlen, maxlen, 365269398Srmacklem va_arg(args, int)); 366269398Srmacklem break; 367269398Srmacklem case 's': 368269398Srmacklem strvalue = va_arg(args, char *); 369269398Srmacklem if (max < 0) { 370269398Srmacklem if (buffer) 371269398Srmacklem max = INT_MAX; 372269398Srmacklem else 373191783Srmacklem max = *maxlen; 374191783Srmacklem } 375269398Srmacklem fmtstr(sbuffer, buffer, &currlen, maxlen, strvalue, 376269398Srmacklem flags, min, max); 377269398Srmacklem break; 378269398Srmacklem case 'p': 379191783Srmacklem value = (long)va_arg(args, void *); 380191783Srmacklem fmtint(sbuffer, buffer, &currlen, maxlen, 381191783Srmacklem value, 16, min, max, flags|DP_F_NUM); 382269398Srmacklem break; 383191783Srmacklem case 'n': /* XXX */ 384269398Srmacklem if (cflags == DP_C_SHORT) { 385269398Srmacklem short int *num; 386269398Srmacklem num = va_arg(args, short int *); 387269398Srmacklem *num = currlen; 388269398Srmacklem } else if (cflags == DP_C_LONG) { /* XXX */ 389191783Srmacklem long int *num; 390269398Srmacklem num = va_arg(args, long int *); 391269398Srmacklem *num = (long int) currlen; 392269398Srmacklem } else if (cflags == DP_C_LLONG) { /* XXX */ 393269398Srmacklem LLONG *num; 394269398Srmacklem num = va_arg(args, LLONG *); 395191783Srmacklem *num = (LLONG) currlen; 396269398Srmacklem } else { 397269398Srmacklem int *num; 398269398Srmacklem num = va_arg(args, int *); 399269398Srmacklem *num = currlen; 400269398Srmacklem } 401191783Srmacklem break; 402269398Srmacklem case '%': 403269398Srmacklem doapr_outch(sbuffer, buffer, &currlen, maxlen, ch); 404269398Srmacklem break; 405269398Srmacklem case 'w': 406269398Srmacklem /* not supported yet, treat as next char */ 407269398Srmacklem ch = *format++; 408269398Srmacklem break; 409269398Srmacklem default: 410269398Srmacklem /* unknown, skip */ 411191783Srmacklem break; 412269398Srmacklem } 413269398Srmacklem ch = *format++; 414269398Srmacklem state = DP_S_DEFAULT; 415269398Srmacklem flags = cflags = min = 0; 416269398Srmacklem max = -1; 417191783Srmacklem break; 418269398Srmacklem case DP_S_DONE: 419269398Srmacklem break; 420269398Srmacklem default: 421269398Srmacklem break; 422269398Srmacklem } 423191783Srmacklem } 424269398Srmacklem *truncated = (currlen > *maxlen - 1); 425269398Srmacklem if (*truncated) 426269398Srmacklem currlen = *maxlen - 1; 427269398Srmacklem doapr_outch(sbuffer, buffer, &currlen, maxlen, '\0'); 428269398Srmacklem *retlen = currlen - 1; 429191783Srmacklem return; 430269398Srmacklem} 431269398Srmacklem 432269398Srmacklemstatic void 433269398Srmacklemfmtstr( 434269398Srmacklem char **sbuffer, 435191783Srmacklem char **buffer, 436269398Srmacklem size_t *currlen, 437269398Srmacklem size_t *maxlen, 438269398Srmacklem const char *value, 439269398Srmacklem int flags, 440269398Srmacklem int min, 441191783Srmacklem int max) 442269398Srmacklem{ 443269398Srmacklem int padlen, strln; 444269398Srmacklem int cnt = 0; 445269398Srmacklem 446269398Srmacklem if (value == 0) 447191783Srmacklem value = "<NULL>"; 448191783Srmacklem for (strln = 0; value[strln]; ++strln) 449269398Srmacklem ; 450269398Srmacklem padlen = min - strln; 451269398Srmacklem if (padlen < 0) 452191783Srmacklem padlen = 0; 453269398Srmacklem if (flags & DP_F_MINUS) 454269398Srmacklem padlen = -padlen; 455269398Srmacklem 456269398Srmacklem while ((padlen > 0) && (cnt < max)) { 457269398Srmacklem doapr_outch(sbuffer, buffer, currlen, maxlen, ' '); 458191783Srmacklem --padlen; 459269398Srmacklem ++cnt; 460269398Srmacklem } 461269398Srmacklem while (*value && (cnt < max)) { 462269398Srmacklem doapr_outch(sbuffer, buffer, currlen, maxlen, *value++); 463269398Srmacklem ++cnt; 464191783Srmacklem } 465269398Srmacklem while ((padlen < 0) && (cnt < max)) { 466269398Srmacklem doapr_outch(sbuffer, buffer, currlen, maxlen, ' '); 467269398Srmacklem ++padlen; 468269398Srmacklem ++cnt; 469191783Srmacklem } 470191783Srmacklem} 471194523Srmacklem 472194541Srmacklemstatic void 473194523Srmacklemfmtint( 474191783Srmacklem char **sbuffer, 475191783Srmacklem char **buffer, 476191783Srmacklem size_t *currlen, 477194541Srmacklem size_t *maxlen, 478191783Srmacklem LLONG value, 479191783Srmacklem int base, 480191783Srmacklem int min, 481191783Srmacklem int max, 482191783Srmacklem int flags) 483191783Srmacklem{ 484191783Srmacklem int signvalue = 0; 485191783Srmacklem char *prefix = ""; 486191783Srmacklem unsigned LLONG uvalue; 487191783Srmacklem char convert[DECIMAL_SIZE(value)+3]; 488191783Srmacklem int place = 0; 489191783Srmacklem int spadlen = 0; 490191783Srmacklem int zpadlen = 0; 491191783Srmacklem int caps = 0; 492191783Srmacklem 493191783Srmacklem if (max < 0) 494191783Srmacklem max = 0; 495191783Srmacklem uvalue = value; 496191783Srmacklem if (!(flags & DP_F_UNSIGNED)) { 497191783Srmacklem if (value < 0) { 498191783Srmacklem signvalue = '-'; 499191783Srmacklem uvalue = -value; 500191783Srmacklem } else if (flags & DP_F_PLUS) 501191783Srmacklem signvalue = '+'; 502191783Srmacklem else if (flags & DP_F_SPACE) 503191783Srmacklem signvalue = ' '; 504191783Srmacklem } 505191783Srmacklem if (flags & DP_F_NUM) { 506191783Srmacklem if (base == 8) prefix = "0"; 507191783Srmacklem if (base == 16) prefix = "0x"; 508191783Srmacklem } 509191783Srmacklem if (flags & DP_F_UP) 510191783Srmacklem caps = 1; 511191783Srmacklem do { 512191783Srmacklem convert[place++] = 513191783Srmacklem (caps ? "0123456789ABCDEF" : "0123456789abcdef") 514191783Srmacklem [uvalue % (unsigned) base]; 515191783Srmacklem uvalue = (uvalue / (unsigned) base); 516191783Srmacklem } while (uvalue && (place < sizeof convert)); 517191783Srmacklem if (place == sizeof convert) 518191783Srmacklem place--; 519191783Srmacklem convert[place] = 0; 520191783Srmacklem 521191783Srmacklem zpadlen = max - place; 522191783Srmacklem spadlen = min - OSSL_MAX(max, place) - (signvalue ? 1 : 0) - strlen(prefix); 523191783Srmacklem if (zpadlen < 0) 524191783Srmacklem zpadlen = 0; 525191783Srmacklem if (spadlen < 0) 526191783Srmacklem spadlen = 0; 527253049Srmacklem if (flags & DP_F_ZERO) { 528191783Srmacklem zpadlen = OSSL_MAX(zpadlen, spadlen); 529191783Srmacklem spadlen = 0; 530191783Srmacklem } 531191783Srmacklem if (flags & DP_F_MINUS) 532191783Srmacklem spadlen = -spadlen; 533191783Srmacklem 534191783Srmacklem /* spaces */ 535191783Srmacklem while (spadlen > 0) { 536191783Srmacklem doapr_outch(sbuffer, buffer, currlen, maxlen, ' '); 537191783Srmacklem --spadlen; 538191783Srmacklem } 539191783Srmacklem 540191783Srmacklem /* sign */ 541191783Srmacklem if (signvalue) 542191783Srmacklem doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue); 543191783Srmacklem 544191783Srmacklem /* prefix */ 545192581Srmacklem while (*prefix) { 546191783Srmacklem doapr_outch(sbuffer, buffer, currlen, maxlen, *prefix); 547191783Srmacklem prefix++; 548191783Srmacklem } 549191783Srmacklem 550191783Srmacklem /* zeros */ 551191783Srmacklem if (zpadlen > 0) { 552191783Srmacklem while (zpadlen > 0) { 553191783Srmacklem doapr_outch(sbuffer, buffer, currlen, maxlen, '0'); 554191783Srmacklem --zpadlen; 555191783Srmacklem } 556191783Srmacklem } 557191783Srmacklem /* digits */ 558191783Srmacklem while (place > 0) 559191783Srmacklem doapr_outch(sbuffer, buffer, currlen, maxlen, convert[--place]); 560191783Srmacklem 561191783Srmacklem /* left justified spaces */ 562191783Srmacklem while (spadlen < 0) { 563191783Srmacklem doapr_outch(sbuffer, buffer, currlen, maxlen, ' '); 564191783Srmacklem ++spadlen; 565191783Srmacklem } 566191783Srmacklem return; 567191783Srmacklem} 568191783Srmacklem 569191783Srmacklemstatic LDOUBLE 570191783Srmacklemabs_val(LDOUBLE value) 571191783Srmacklem{ 572191783Srmacklem LDOUBLE result = value; 573191783Srmacklem if (value < 0) 574191783Srmacklem result = -value; 575191783Srmacklem return result; 576191783Srmacklem} 577191783Srmacklem 578191783Srmacklemstatic LDOUBLE 579191783Srmacklempow10(int exp) 580191783Srmacklem{ 581191783Srmacklem LDOUBLE result = 1; 582191783Srmacklem while (exp) { 583191783Srmacklem result *= 10; 584191783Srmacklem exp--; 585191783Srmacklem } 586191783Srmacklem return result; 587191783Srmacklem} 588191783Srmacklem 589191783Srmacklemstatic long 590191783Srmacklemroundv(LDOUBLE value) 591191783Srmacklem{ 592191783Srmacklem long intpart; 593191783Srmacklem intpart = (long) value; 594244042Srmacklem value = value - intpart; 595269398Srmacklem if (value >= 0.5) 596269398Srmacklem intpart++; 597269398Srmacklem return intpart; 598191783Srmacklem} 599191783Srmacklem 600191783Srmacklemstatic void 601191783Srmacklemfmtfp( 602191783Srmacklem char **sbuffer, 603191783Srmacklem char **buffer, 604191783Srmacklem size_t *currlen, 605191783Srmacklem size_t *maxlen, 606191783Srmacklem LDOUBLE fvalue, 607191783Srmacklem int min, 608191783Srmacklem int max, 609191783Srmacklem int flags) 610191783Srmacklem{ 611191783Srmacklem int signvalue = 0; 612191783Srmacklem LDOUBLE ufvalue; 613191783Srmacklem char iconvert[20]; 614191783Srmacklem char fconvert[20]; 615191783Srmacklem int iplace = 0; 616191783Srmacklem int fplace = 0; 617191783Srmacklem int padlen = 0; 618191783Srmacklem int zpadlen = 0; 619191783Srmacklem int caps = 0; 620191783Srmacklem long intpart; 621191783Srmacklem long fracpart; 622191783Srmacklem 623192121Srmacklem if (max < 0) 624192121Srmacklem max = 6; 625192121Srmacklem ufvalue = abs_val(fvalue); 626192121Srmacklem if (fvalue < 0) 627192121Srmacklem signvalue = '-'; 628240720Srmacklem else if (flags & DP_F_PLUS) 629244042Srmacklem signvalue = '+'; 630244042Srmacklem else if (flags & DP_F_SPACE) 631269398Srmacklem signvalue = ' '; 632269398Srmacklem 633191783Srmacklem intpart = (long)ufvalue; 634191783Srmacklem 635191783Srmacklem /* sorry, we only support 9 digits past the decimal because of our 636191783Srmacklem conversion method */ 637191783Srmacklem if (max > 9) 638191783Srmacklem max = 9; 639191783Srmacklem 640191783Srmacklem /* we "cheat" by converting the fractional part to integer by 641191783Srmacklem multiplying by a factor of 10 */ 642191783Srmacklem fracpart = roundv((pow10(max)) * (ufvalue - intpart)); 643191783Srmacklem 644216700Srmacklem if (fracpart >= pow10(max)) { 645244042Srmacklem intpart++; 646191783Srmacklem fracpart -= (long)pow10(max); 647191783Srmacklem } 648191783Srmacklem 649191783Srmacklem /* convert integer part */ 650191783Srmacklem do { 651191783Srmacklem iconvert[iplace++] = 652191783Srmacklem (caps ? "0123456789ABCDEF" 653191783Srmacklem : "0123456789abcdef")[intpart % 10]; 654191783Srmacklem intpart = (intpart / 10); 655191783Srmacklem } while (intpart && (iplace < sizeof iplace)); 656191783Srmacklem if (iplace == sizeof iplace) 657191783Srmacklem iplace--; 658191783Srmacklem iconvert[iplace] = 0; 659191783Srmacklem 660191783Srmacklem /* convert fractional part */ 661191783Srmacklem do { 662191783Srmacklem fconvert[fplace++] = 663191783Srmacklem (caps ? "0123456789ABCDEF" 664191783Srmacklem : "0123456789abcdef")[fracpart % 10]; 665191783Srmacklem fracpart = (fracpart / 10); 666191783Srmacklem } while (fplace < max); 667191783Srmacklem if (fplace == sizeof fplace) 668191783Srmacklem fplace--; 669191783Srmacklem fconvert[fplace] = 0; 670191783Srmacklem 671191783Srmacklem /* -1 for decimal point, another -1 if we are printing a sign */ 672191783Srmacklem padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0); 673191783Srmacklem zpadlen = max - fplace; 674191783Srmacklem if (zpadlen < 0) 675191783Srmacklem zpadlen = 0; 676191783Srmacklem if (padlen < 0) 677191783Srmacklem padlen = 0; 678191783Srmacklem if (flags & DP_F_MINUS) 679191783Srmacklem padlen = -padlen; 680191783Srmacklem 681191783Srmacklem if ((flags & DP_F_ZERO) && (padlen > 0)) { 682191783Srmacklem if (signvalue) { 683191783Srmacklem doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue); 684191783Srmacklem --padlen; 685191783Srmacklem signvalue = 0; 686191783Srmacklem } 687191783Srmacklem while (padlen > 0) { 688191783Srmacklem doapr_outch(sbuffer, buffer, currlen, maxlen, '0'); 689191783Srmacklem --padlen; 690191783Srmacklem } 691191783Srmacklem } 692191783Srmacklem while (padlen > 0) { 693191783Srmacklem doapr_outch(sbuffer, buffer, currlen, maxlen, ' '); 694191783Srmacklem --padlen; 695191783Srmacklem } 696191783Srmacklem if (signvalue) 697191783Srmacklem doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue); 698191783Srmacklem 699191783Srmacklem while (iplace > 0) 700191783Srmacklem doapr_outch(sbuffer, buffer, currlen, maxlen, iconvert[--iplace]); 701191783Srmacklem 702191783Srmacklem /* 703191783Srmacklem * Decimal point. This should probably use locale to find the correct 704191783Srmacklem * char to print out. 705191783Srmacklem */ 706191783Srmacklem if (max > 0 || (flags & DP_F_NUM)) { 707191783Srmacklem doapr_outch(sbuffer, buffer, currlen, maxlen, '.'); 708191783Srmacklem 709191783Srmacklem while (fplace > 0) 710191783Srmacklem doapr_outch(sbuffer, buffer, currlen, maxlen, fconvert[--fplace]); 711191783Srmacklem } 712191783Srmacklem while (zpadlen > 0) { 713191783Srmacklem doapr_outch(sbuffer, buffer, currlen, maxlen, '0'); 714191783Srmacklem --zpadlen; 715191783Srmacklem } 716191783Srmacklem 717191783Srmacklem while (padlen < 0) { 718191783Srmacklem doapr_outch(sbuffer, buffer, currlen, maxlen, ' '); 719244042Srmacklem ++padlen; 720244042Srmacklem } 721244042Srmacklem} 722244042Srmacklem 723244042Srmacklemstatic void 724244042Srmacklemdoapr_outch( 725244042Srmacklem char **sbuffer, 726244042Srmacklem char **buffer, 727244042Srmacklem size_t *currlen, 728191783Srmacklem size_t *maxlen, 729191783Srmacklem int c) 730191783Srmacklem{ 731 /* If we haven't at least one buffer, someone has doe a big booboo */ 732 assert(*sbuffer != NULL || buffer != NULL); 733 734 if (buffer) { 735 while (*currlen >= *maxlen) { 736 if (*buffer == NULL) { 737 if (*maxlen == 0) 738 *maxlen = 1024; 739 *buffer = OPENSSL_malloc(*maxlen); 740 if (*currlen > 0) { 741 assert(*sbuffer != NULL); 742 memcpy(*buffer, *sbuffer, *currlen); 743 } 744 *sbuffer = NULL; 745 } else { 746 *maxlen += 1024; 747 *buffer = OPENSSL_realloc(*buffer, *maxlen); 748 } 749 } 750 /* What to do if *buffer is NULL? */ 751 assert(*sbuffer != NULL || *buffer != NULL); 752 } 753 754 if (*currlen < *maxlen) { 755 if (*sbuffer) 756 (*sbuffer)[(*currlen)++] = (char)c; 757 else 758 (*buffer)[(*currlen)++] = (char)c; 759 } 760 761 return; 762} 763 764/***************************************************************************/ 765 766int BIO_printf (BIO *bio, const char *format, ...) 767 { 768 va_list args; 769 int ret; 770 771 va_start(args, format); 772 773 ret = BIO_vprintf(bio, format, args); 774 775 va_end(args); 776 return(ret); 777 } 778 779int BIO_vprintf (BIO *bio, const char *format, va_list args) 780 { 781 int ret; 782 size_t retlen; 783 char hugebuf[1024*2]; /* Was previously 10k, which is unreasonable 784 in small-stack environments, like threads 785 or DOS programs. */ 786 char *hugebufp = hugebuf; 787 size_t hugebufsize = sizeof(hugebuf); 788 char *dynbuf = NULL; 789 int ignored; 790 791 dynbuf = NULL; 792 CRYPTO_push_info("doapr()"); 793 _dopr(&hugebufp, &dynbuf, &hugebufsize, 794 &retlen, &ignored, format, args); 795 if (dynbuf) 796 { 797 ret=BIO_write(bio, dynbuf, (int)retlen); 798 OPENSSL_free(dynbuf); 799 } 800 else 801 { 802 ret=BIO_write(bio, hugebuf, (int)retlen); 803 } 804 CRYPTO_pop_info(); 805 return(ret); 806 } 807 808/* As snprintf is not available everywhere, we provide our own implementation. 809 * This function has nothing to do with BIOs, but it's closely related 810 * to BIO_printf, and we need *some* name prefix ... 811 * (XXX the function should be renamed, but to what?) */ 812int BIO_snprintf(char *buf, size_t n, const char *format, ...) 813 { 814 va_list args; 815 int ret; 816 817 va_start(args, format); 818 819 ret = BIO_vsnprintf(buf, n, format, args); 820 821 va_end(args); 822 return(ret); 823 } 824 825int BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args) 826 { 827 size_t retlen; 828 int truncated; 829 830 _dopr(&buf, NULL, &n, &retlen, &truncated, format, args); 831 832 if (truncated) 833 /* In case of truncation, return -1 like traditional snprintf. 834 * (Current drafts for ISO/IEC 9899 say snprintf should return 835 * the number of characters that would have been written, 836 * had the buffer been large enough.) */ 837 return -1; 838 else 839 return (retlen <= INT_MAX) ? (int)retlen : -1; 840 } 841