]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/bio/b_print.c
Consistency
[thirdparty/openssl.git] / crypto / bio / b_print.c
CommitLineData
d02b48c6 1/* crypto/bio/b_print.c */
58964a49 2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
d02b48c6
RE
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/*
60 * Stolen from tjh's ssl/ssl_trc.c stuff.
61 */
62
63#include <stdio.h>
b478e91f
UM
64#include <string.h>
65#include <ctype.h>
5ee0d9c4
RL
66#include <assert.h>
67#include <limits.h>
d02b48c6 68#include "cryptlib.h"
a1990dd7
RL
69#ifndef NO_SYS_TYPES_H
70#include <sys/types.h>
71#endif
ec577822 72#include <openssl/bio.h>
d02b48c6 73
b478e91f
UM
74#ifdef BN_LLONG
75# ifndef HAVE_LONG_LONG
96723a3a 76# define HAVE_LONG_LONG 1
b478e91f
UM
77# endif
78#endif
79
e5c84d51 80/***************************************************************************/
d02b48c6 81
9fd4ee5d
UM
82/*
83 * Copyright Patrick Powell 1995
b478e91f 84 * This code is based on code written by Patrick Powell <papowell@astart.com>
9fd4ee5d 85 * It may be used for any purpose as long as this notice remains intact
b478e91f 86 * on all source code distributions.
9fd4ee5d
UM
87 */
88
9fd4ee5d 89/*
b478e91f
UM
90 * This code contains numerious changes and enhancements which were
91 * made by lots of contributors over the last years to Patrick Powell's
92 * original code:
93 *
94 * o Patrick Powell <papowell@astart.com> (1995)
95 * o Brandon Long <blong@fiction.net> (1996, for Mutt)
96 * o Thomas Roessler <roessler@guug.de> (1998, for Mutt)
97 * o Michael Elkins <me@cs.hmc.edu> (1998, for Mutt)
98 * o Andrew Tridgell <tridge@samba.org> (1998, for Samba)
99 * o Luke Mewburn <lukem@netbsd.org> (1999, for LukemFTP)
100 * o Ralf S. Engelschall <rse@engelschall.com> (1999, for Pth)
e5c84d51 101 * o ... (for OpenSSL)
9fd4ee5d
UM
102 */
103
b478e91f
UM
104#if HAVE_LONG_DOUBLE
105#define LDOUBLE long double
106#else
107#define LDOUBLE double
108#endif
109
110#if HAVE_LONG_LONG
111#define LLONG long long
112#else
113#define LLONG long
114#endif
115
5ee0d9c4 116static void fmtstr (void (*)(char **, size_t *, size_t *, int),
938d90db
UM
117 char **, size_t *, size_t *, const char *, int, int,
118 int);
5ee0d9c4
RL
119static void fmtint (void (*)(char **, size_t *, size_t *, int),
120 char **, size_t *, size_t *, LLONG, int, int, int, int);
121static void fmtfp (void (*)(char **, size_t *, size_t *, int),
122 char **, size_t *, size_t *, LDOUBLE, int, int, int);
123static int dopr_isbig (size_t, size_t);
5ee0d9c4 124static int dopr_copy (size_t);
5ee0d9c4 125static void dopr_outch (char **, size_t *, size_t *, int);
e5c84d51 126#ifdef USE_ALLOCATING_PRINT
938d90db
UM
127static int doapr_isbig (size_t, size_t);
128static int doapr_copy (size_t);
5ee0d9c4 129static void doapr_outch (char **, size_t *, size_t *, int);
938d90db 130#endif
5ee0d9c4
RL
131static void _dopr(void (*)(char **, size_t *, size_t *, int),
132 int (*)(size_t, size_t), int (*)(size_t),
e5c84d51 133 char **buffer, size_t *maxlen, size_t *retlen, int *truncated,
5ee0d9c4 134 const char *format, va_list args);
b478e91f 135
9fd4ee5d 136/* format read states */
b478e91f
UM
137#define DP_S_DEFAULT 0
138#define DP_S_FLAGS 1
139#define DP_S_MIN 2
140#define DP_S_DOT 3
141#define DP_S_MAX 4
142#define DP_S_MOD 5
143#define DP_S_CONV 6
144#define DP_S_DONE 7
9fd4ee5d
UM
145
146/* format flags - Bits */
b478e91f
UM
147#define DP_F_MINUS (1 << 0)
148#define DP_F_PLUS (1 << 1)
149#define DP_F_SPACE (1 << 2)
150#define DP_F_NUM (1 << 3)
151#define DP_F_ZERO (1 << 4)
152#define DP_F_UP (1 << 5)
153#define DP_F_UNSIGNED (1 << 6)
154
155/* conversion flags */
156#define DP_C_SHORT 1
157#define DP_C_LONG 2
158#define DP_C_LDOUBLE 3
159#define DP_C_LLONG 4
160
161/* some handy macros */
9fd4ee5d
UM
162#define char_to_int(p) (p - '0')
163#define MAX(p,q) ((p >= q) ? p : q)
164
3916800f 165#ifndef USE_ALLOCATING_PRINT
b478e91f
UM
166static void
167dopr(
168 char *buffer,
169 size_t maxlen,
170 size_t *retlen,
171 const char *format,
172 va_list args)
5ee0d9c4 173{
e5c84d51 174 int ignored;
5ee0d9c4 175 _dopr(dopr_outch, dopr_isbig, dopr_copy,
e5c84d51 176 &buffer, &maxlen, retlen, &ignored, format, args);
5ee0d9c4
RL
177}
178
3916800f 179#else
5ee0d9c4
RL
180static void
181doapr(
182 char **buffer,
183 size_t *retlen,
184 const char *format,
185 va_list args)
186{
187 size_t dummy_maxlen = 0;
e5c84d51 188 int ignored;
5ee0d9c4 189 _dopr(doapr_outch, doapr_isbig, doapr_copy,
e5c84d51 190 buffer, &dummy_maxlen, retlen, &ignored, format, args);
5ee0d9c4 191}
938d90db 192#endif
5ee0d9c4
RL
193
194static void
195_dopr(
196 void (*outch_fn)(char **, size_t *, size_t *, int),
197 int (*isbig_fn)(size_t, size_t),
198 int (*copy_fn)(size_t),
199 char **buffer,
200 size_t *maxlen,
201 size_t *retlen,
e5c84d51 202 int *truncated,
5ee0d9c4
RL
203 const char *format,
204 va_list args)
9fd4ee5d 205{
b478e91f
UM
206 char ch;
207 LLONG value;
208 LDOUBLE fvalue;
209 char *strvalue;
210 int min;
211 int max;
212 int state;
213 int flags;
214 int cflags;
215 size_t currlen;
216
217 state = DP_S_DEFAULT;
218 flags = currlen = cflags = min = 0;
219 max = -1;
220 ch = *format++;
221
222 while (state != DP_S_DONE) {
5ee0d9c4 223 if ((ch == '\0') || (*isbig_fn)(currlen, *maxlen))
b478e91f
UM
224 state = DP_S_DONE;
225
226 switch (state) {
227 case DP_S_DEFAULT:
228 if (ch == '%')
229 state = DP_S_FLAGS;
230 else
5ee0d9c4 231 (*outch_fn)(buffer, &currlen, maxlen, ch);
b478e91f
UM
232 ch = *format++;
233 break;
234 case DP_S_FLAGS:
235 switch (ch) {
236 case '-':
237 flags |= DP_F_MINUS;
238 ch = *format++;
239 break;
240 case '+':
241 flags |= DP_F_PLUS;
242 ch = *format++;
243 break;
244 case ' ':
245 flags |= DP_F_SPACE;
246 ch = *format++;
247 break;
248 case '#':
249 flags |= DP_F_NUM;
250 ch = *format++;
251 break;
252 case '0':
253 flags |= DP_F_ZERO;
254 ch = *format++;
255 break;
256 default:
257 state = DP_S_MIN;
258 break;
259 }
260 break;
261 case DP_S_MIN:
262 if (isdigit((unsigned char)ch)) {
263 min = 10 * min + char_to_int(ch);
264 ch = *format++;
265 } else if (ch == '*') {
266 min = va_arg(args, int);
267 ch = *format++;
268 state = DP_S_DOT;
269 } else
270 state = DP_S_DOT;
271 break;
272 case DP_S_DOT:
273 if (ch == '.') {
274 state = DP_S_MAX;
275 ch = *format++;
276 } else
277 state = DP_S_MOD;
278 break;
279 case DP_S_MAX:
280 if (isdigit((unsigned char)ch)) {
281 if (max < 0)
282 max = 0;
283 max = 10 * max + char_to_int(ch);
284 ch = *format++;
285 } else if (ch == '*') {
286 max = va_arg(args, int);
287 ch = *format++;
288 state = DP_S_MOD;
289 } else
290 state = DP_S_MOD;
291 break;
292 case DP_S_MOD:
293 switch (ch) {
294 case 'h':
295 cflags = DP_C_SHORT;
296 ch = *format++;
297 break;
298 case 'l':
299 if (*format == 'l') {
300 cflags = DP_C_LLONG;
301 format++;
302 } else
303 cflags = DP_C_LONG;
304 ch = *format++;
305 break;
306 case 'q':
307 cflags = DP_C_LLONG;
308 ch = *format++;
309 break;
310 case 'L':
311 cflags = DP_C_LDOUBLE;
312 ch = *format++;
313 break;
314 default:
315 break;
316 }
317 state = DP_S_CONV;
318 break;
319 case DP_S_CONV:
320 switch (ch) {
321 case 'd':
322 case 'i':
323 switch (cflags) {
324 case DP_C_SHORT:
1b7aee1d 325 value = (short int)va_arg(args, int);
b478e91f
UM
326 break;
327 case DP_C_LONG:
328 value = va_arg(args, long int);
329 break;
330 case DP_C_LLONG:
331 value = va_arg(args, LLONG);
332 break;
333 default:
334 value = va_arg(args, int);
335 break;
336 }
5ee0d9c4 337 fmtint(outch_fn, buffer, &currlen, maxlen,
e5c84d51 338 value, 10, min, max, flags);
b478e91f
UM
339 break;
340 case 'X':
341 flags |= DP_F_UP;
342 /* FALLTHROUGH */
343 case 'x':
344 case 'o':
345 case 'u':
346 flags |= DP_F_UNSIGNED;
347 switch (cflags) {
348 case DP_C_SHORT:
42a9af38 349 value = (unsigned short int)va_arg(args, unsigned int);
b478e91f
UM
350 break;
351 case DP_C_LONG:
352 value = (LLONG) va_arg(args,
353 unsigned long int);
354 break;
355 case DP_C_LLONG:
356 value = va_arg(args, unsigned LLONG);
357 break;
358 default:
359 value = (LLONG) va_arg(args,
360 unsigned int);
361 break;
362 }
5ee0d9c4 363 fmtint(outch_fn, buffer, &currlen, maxlen, value,
b478e91f
UM
364 ch == 'o' ? 8 : (ch == 'u' ? 10 : 16),
365 min, max, flags);
366 break;
367 case 'f':
368 if (cflags == DP_C_LDOUBLE)
369 fvalue = va_arg(args, LDOUBLE);
370 else
371 fvalue = va_arg(args, double);
5ee0d9c4 372 fmtfp(outch_fn, buffer, &currlen, maxlen,
e5c84d51 373 fvalue, min, max, flags);
b478e91f
UM
374 break;
375 case 'E':
376 flags |= DP_F_UP;
377 case 'e':
378 if (cflags == DP_C_LDOUBLE)
379 fvalue = va_arg(args, LDOUBLE);
380 else
381 fvalue = va_arg(args, double);
382 break;
383 case 'G':
384 flags |= DP_F_UP;
385 case 'g':
386 if (cflags == DP_C_LDOUBLE)
387 fvalue = va_arg(args, LDOUBLE);
388 else
389 fvalue = va_arg(args, double);
390 break;
391 case 'c':
5ee0d9c4 392 (*outch_fn)(buffer, &currlen, maxlen,
b478e91f
UM
393 va_arg(args, int));
394 break;
395 case 's':
396 strvalue = va_arg(args, char *);
397 if (max < 0)
5ee0d9c4
RL
398 max = (*copy_fn)(*maxlen);
399 fmtstr(outch_fn, buffer, &currlen, maxlen, strvalue,
e5c84d51 400 flags, min, max);
b478e91f
UM
401 break;
402 case 'p':
403 value = (long)va_arg(args, void *);
5ee0d9c4 404 fmtint(outch_fn, buffer, &currlen, maxlen,
b478e91f
UM
405 value, 16, min, max, flags);
406 break;
407 case 'n': /* XXX */
408 if (cflags == DP_C_SHORT) {
409 short int *num;
410 num = va_arg(args, short int *);
411 *num = currlen;
412 } else if (cflags == DP_C_LONG) { /* XXX */
413 long int *num;
414 num = va_arg(args, long int *);
415 *num = (long int) currlen;
416 } else if (cflags == DP_C_LLONG) { /* XXX */
417 LLONG *num;
418 num = va_arg(args, LLONG *);
419 *num = (LLONG) currlen;
420 } else {
421 int *num;
422 num = va_arg(args, int *);
423 *num = currlen;
424 }
425 break;
426 case '%':
5ee0d9c4 427 (*outch_fn)(buffer, &currlen, maxlen, ch);
b478e91f
UM
428 break;
429 case 'w':
430 /* not supported yet, treat as next char */
431 ch = *format++;
432 break;
433 default:
434 /* unknown, skip */
435 break;
436 }
437 ch = *format++;
438 state = DP_S_DEFAULT;
439 flags = cflags = min = 0;
440 max = -1;
441 break;
442 case DP_S_DONE:
443 break;
444 default:
445 break;
9fd4ee5d 446 }
9fd4ee5d 447 }
e5c84d51
BM
448 *truncated = (currlen > *maxlen - 1);
449 if (*truncated)
5ee0d9c4
RL
450 currlen = *maxlen - 1;
451 (*buffer)[currlen] = '\0';
b478e91f
UM
452 *retlen = currlen;
453 return;
9fd4ee5d
UM
454}
455
b478e91f
UM
456static void
457fmtstr(
5ee0d9c4
RL
458 void (*outch_fn)(char **, size_t *, size_t *, int),
459 char **buffer,
b478e91f 460 size_t *currlen,
5ee0d9c4 461 size_t *maxlen,
938d90db 462 const char *value,
b478e91f
UM
463 int flags,
464 int min,
465 int max)
9fd4ee5d 466{
b478e91f
UM
467 int padlen, strln;
468 int cnt = 0;
469
470 if (value == 0)
471 value = "<NULL>";
472 for (strln = 0; value[strln]; ++strln)
473 ;
474 padlen = min - strln;
475 if (padlen < 0)
476 padlen = 0;
477 if (flags & DP_F_MINUS)
478 padlen = -padlen;
479
480 while ((padlen > 0) && (cnt < max)) {
5ee0d9c4 481 (*outch_fn)(buffer, currlen, maxlen, ' ');
b478e91f
UM
482 --padlen;
483 ++cnt;
484 }
485 while (*value && (cnt < max)) {
5ee0d9c4 486 (*outch_fn)(buffer, currlen, maxlen, *value++);
b478e91f
UM
487 ++cnt;
488 }
489 while ((padlen < 0) && (cnt < max)) {
5ee0d9c4 490 (*outch_fn)(buffer, currlen, maxlen, ' ');
b478e91f
UM
491 ++padlen;
492 ++cnt;
493 }
9fd4ee5d
UM
494}
495
b478e91f
UM
496static void
497fmtint(
5ee0d9c4
RL
498 void (*outch_fn)(char **, size_t *, size_t *, int),
499 char **buffer,
b478e91f 500 size_t *currlen,
5ee0d9c4 501 size_t *maxlen,
b478e91f
UM
502 LLONG value,
503 int base,
504 int min,
505 int max,
506 int flags)
9fd4ee5d 507{
b478e91f
UM
508 int signvalue = 0;
509 unsigned LLONG uvalue;
510 char convert[20];
511 int place = 0;
512 int spadlen = 0;
513 int zpadlen = 0;
514 int caps = 0;
515
516 if (max < 0)
517 max = 0;
518 uvalue = value;
519 if (!(flags & DP_F_UNSIGNED)) {
520 if (value < 0) {
521 signvalue = '-';
522 uvalue = -value;
523 } else if (flags & DP_F_PLUS)
524 signvalue = '+';
525 else if (flags & DP_F_SPACE)
526 signvalue = ' ';
9fd4ee5d 527 }
b478e91f
UM
528 if (flags & DP_F_UP)
529 caps = 1;
530 do {
531 convert[place++] =
532 (caps ? "0123456789ABCDEF" : "0123456789abcdef")
533 [uvalue % (unsigned) base];
534 uvalue = (uvalue / (unsigned) base);
535 } while (uvalue && (place < 20));
536 if (place == 20)
537 place--;
538 convert[place] = 0;
539
540 zpadlen = max - place;
541 spadlen = min - MAX(max, place) - (signvalue ? 1 : 0);
542 if (zpadlen < 0)
543 zpadlen = 0;
544 if (spadlen < 0)
545 spadlen = 0;
546 if (flags & DP_F_ZERO) {
547 zpadlen = MAX(zpadlen, spadlen);
548 spadlen = 0;
9fd4ee5d 549 }
b478e91f
UM
550 if (flags & DP_F_MINUS)
551 spadlen = -spadlen;
9fd4ee5d 552
b478e91f
UM
553 /* spaces */
554 while (spadlen > 0) {
5ee0d9c4 555 (*outch_fn)(buffer, currlen, maxlen, ' ');
b478e91f
UM
556 --spadlen;
557 }
9fd4ee5d 558
b478e91f
UM
559 /* sign */
560 if (signvalue)
5ee0d9c4 561 (*outch_fn)(buffer, currlen, maxlen, signvalue);
9fd4ee5d 562
b478e91f
UM
563 /* zeros */
564 if (zpadlen > 0) {
565 while (zpadlen > 0) {
5ee0d9c4 566 (*outch_fn)(buffer, currlen, maxlen, '0');
b478e91f
UM
567 --zpadlen;
568 }
569 }
570 /* digits */
571 while (place > 0)
5ee0d9c4 572 (*outch_fn)(buffer, currlen, maxlen, convert[--place]);
b478e91f
UM
573
574 /* left justified spaces */
575 while (spadlen < 0) {
5ee0d9c4 576 (*outch_fn)(buffer, currlen, maxlen, ' ');
b478e91f
UM
577 ++spadlen;
578 }
579 return;
9fd4ee5d
UM
580}
581
b478e91f
UM
582static LDOUBLE
583abs_val(LDOUBLE value)
9fd4ee5d 584{
b478e91f
UM
585 LDOUBLE result = value;
586 if (value < 0)
587 result = -value;
588 return result;
9fd4ee5d
UM
589}
590
b478e91f
UM
591static LDOUBLE
592pow10(int exp)
9fd4ee5d 593{
b478e91f
UM
594 LDOUBLE result = 1;
595 while (exp) {
596 result *= 10;
597 exp--;
598 }
599 return result;
9fd4ee5d
UM
600}
601
b478e91f
UM
602static long
603round(LDOUBLE value)
9fd4ee5d 604{
b478e91f
UM
605 long intpart;
606 intpart = (long) value;
607 value = value - intpart;
608 if (value >= 0.5)
609 intpart++;
610 return intpart;
611}
9fd4ee5d 612
b478e91f
UM
613static void
614fmtfp(
5ee0d9c4
RL
615 void (*outch_fn)(char **, size_t *, size_t *, int),
616 char **buffer,
b478e91f 617 size_t *currlen,
5ee0d9c4 618 size_t *maxlen,
b478e91f
UM
619 LDOUBLE fvalue,
620 int min,
621 int max,
622 int flags)
623{
624 int signvalue = 0;
625 LDOUBLE ufvalue;
626 char iconvert[20];
627 char fconvert[20];
628 int iplace = 0;
629 int fplace = 0;
630 int padlen = 0;
631 int zpadlen = 0;
632 int caps = 0;
633 long intpart;
634 long fracpart;
635
636 if (max < 0)
637 max = 6;
638 ufvalue = abs_val(fvalue);
639 if (fvalue < 0)
640 signvalue = '-';
641 else if (flags & DP_F_PLUS)
642 signvalue = '+';
643 else if (flags & DP_F_SPACE)
644 signvalue = ' ';
645
646 intpart = (long)ufvalue;
647
648 /* sorry, we only support 9 digits past the decimal because of our
649 conversion method */
650 if (max > 9)
651 max = 9;
652
653 /* we "cheat" by converting the fractional part to integer by
654 multiplying by a factor of 10 */
655 fracpart = round((pow10(max)) * (ufvalue - intpart));
656
657 if (fracpart >= pow10(max)) {
658 intpart++;
7dce5a72 659 fracpart -= (long)pow10(max);
b478e91f 660 }
9fd4ee5d 661
b478e91f
UM
662 /* convert integer part */
663 do {
664 iconvert[iplace++] =
665 (caps ? "0123456789ABCDEF"
666 : "0123456789abcdef")[intpart % 10];
667 intpart = (intpart / 10);
668 } while (intpart && (iplace < 20));
669 if (iplace == 20)
670 iplace--;
671 iconvert[iplace] = 0;
672
673 /* convert fractional part */
674 do {
675 fconvert[fplace++] =
676 (caps ? "0123456789ABCDEF"
677 : "0123456789abcdef")[fracpart % 10];
678 fracpart = (fracpart / 10);
679 } while (fracpart && (fplace < 20));
680 if (fplace == 20)
681 fplace--;
682 fconvert[fplace] = 0;
683
684 /* -1 for decimal point, another -1 if we are printing a sign */
685 padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0);
686 zpadlen = max - fplace;
687 if (zpadlen < 0)
688 zpadlen = 0;
689 if (padlen < 0)
690 padlen = 0;
691 if (flags & DP_F_MINUS)
692 padlen = -padlen;
693
694 if ((flags & DP_F_ZERO) && (padlen > 0)) {
695 if (signvalue) {
5ee0d9c4 696 (*outch_fn)(buffer, currlen, maxlen, signvalue);
b478e91f
UM
697 --padlen;
698 signvalue = 0;
699 }
700 while (padlen > 0) {
5ee0d9c4 701 (*outch_fn)(buffer, currlen, maxlen, '0');
b478e91f
UM
702 --padlen;
703 }
704 }
705 while (padlen > 0) {
5ee0d9c4 706 (*outch_fn)(buffer, currlen, maxlen, ' ');
b478e91f
UM
707 --padlen;
708 }
709 if (signvalue)
5ee0d9c4 710 (*outch_fn)(buffer, currlen, maxlen, signvalue);
9fd4ee5d 711
b478e91f 712 while (iplace > 0)
5ee0d9c4 713 (*outch_fn)(buffer, currlen, maxlen, iconvert[--iplace]);
9fd4ee5d 714
b478e91f
UM
715 /*
716 * Decimal point. This should probably use locale to find the correct
717 * char to print out.
718 */
719 if (max > 0) {
5ee0d9c4 720 (*outch_fn)(buffer, currlen, maxlen, '.');
9fd4ee5d 721
b478e91f 722 while (fplace > 0)
5ee0d9c4 723 (*outch_fn)(buffer, currlen, maxlen, fconvert[--fplace]);
b478e91f
UM
724 }
725 while (zpadlen > 0) {
5ee0d9c4 726 (*outch_fn)(buffer, currlen, maxlen, '0');
b478e91f 727 --zpadlen;
9fd4ee5d 728 }
b478e91f
UM
729
730 while (padlen < 0) {
5ee0d9c4 731 (*outch_fn)(buffer, currlen, maxlen, ' ');
b478e91f 732 ++padlen;
9fd4ee5d 733 }
9fd4ee5d
UM
734}
735
5ee0d9c4
RL
736static int
737dopr_copy(
738 size_t len)
739{
740 return len;
741}
742
938d90db 743#ifdef USE_ALLOCATING_PRINT
5ee0d9c4
RL
744static int
745doapr_copy(
746 size_t len)
747{
748 /* Return as high an integer as possible */
749 return INT_MAX;
750}
938d90db 751#endif
5ee0d9c4
RL
752
753static int
754dopr_isbig(
755 size_t currlen,
756 size_t maxlen)
757{
758 return currlen > maxlen;
759}
760
938d90db 761#ifdef USE_ALLOCATING_PRINT
5ee0d9c4
RL
762static int
763doapr_isbig(
764 size_t currlen,
765 size_t maxlen)
766{
767 return 0;
768}
938d90db 769#endif
5ee0d9c4 770
b478e91f
UM
771static void
772dopr_outch(
5ee0d9c4 773 char **buffer,
b478e91f 774 size_t *currlen,
5ee0d9c4
RL
775 size_t *maxlen,
776 int c)
777{
778 if (*currlen < *maxlen)
779 (*buffer)[(*currlen)++] = (char)c;
780 return;
781}
782
938d90db 783#ifdef USE_ALLOCATING_PRINT
5ee0d9c4
RL
784static void
785doapr_outch(
786 char **buffer,
787 size_t *currlen,
788 size_t *maxlen,
b478e91f 789 int c)
9fd4ee5d 790{
5ee0d9c4
RL
791 if (*buffer == NULL) {
792 if (*maxlen == 0)
793 *maxlen = 1024;
26a3a48d 794 *buffer = OPENSSL_malloc(*maxlen);
5ee0d9c4
RL
795 }
796 while (*currlen >= *maxlen) {
797 *maxlen += 1024;
26a3a48d 798 *buffer = OPENSSL_realloc(*buffer, *maxlen);
5ee0d9c4
RL
799 }
800 /* What to do if *buffer is NULL? */
801 assert(*buffer != NULL);
802
803 (*buffer)[(*currlen)++] = (char)c;
b478e91f 804 return;
9fd4ee5d 805}
938d90db 806#endif
e5c84d51
BM
807
808/***************************************************************************/
809
810int BIO_printf (BIO *bio, const char *format, ...)
811 {
812 va_list args;
813 int ret;
e6629837
RL
814
815 va_start(args, format);
816
817 ret = BIO_vprintf(bio, format, args);
818
819 va_end(args);
820 return(ret);
821 }
822
823int BIO_vprintf (BIO *bio, const char *format, va_list args)
824 {
825 int ret;
e5c84d51
BM
826 size_t retlen;
827#ifdef USE_ALLOCATING_PRINT
828 char *hugebuf;
829#else
affadbef 830 MS_STATIC char hugebuf[1024*2];
e5c84d51
BM
831#endif
832
e5c84d51
BM
833#ifndef USE_ALLOCATING_PRINT
834 hugebuf[0]='\0';
835 dopr(hugebuf, sizeof(hugebuf), &retlen, format, args);
836#else
837 hugebuf = NULL;
838 CRYPTO_push_info("doapr()");
839 doapr(&hugebuf, &retlen, format, args);
840 if (hugebuf)
841 {
842#endif
843 ret=BIO_write(bio, hugebuf, (int)retlen);
844
845#ifdef USE_ALLOCATING_PRINT
26a3a48d 846 OPENSSL_free(hugebuf);
e5c84d51
BM
847 }
848 CRYPTO_pop_info();
849#endif
e5c84d51
BM
850 return(ret);
851 }
852
853/* As snprintf is not available everywhere, we provide our own implementation.
854 * This function has nothing to do with BIOs, but it's closely related
855 * to BIO_printf, and we need *some* name prefix ...
856 * (XXX the function should be renamed, but to what?) */
857int BIO_snprintf(char *buf, size_t n, const char *format, ...)
858 {
859 va_list args;
e6629837
RL
860 int ret;
861
862 va_start(args, format);
863
864 ret = BIO_vsnprintf(buf, n, format, args);
865
866 va_end(args);
867 return(ret);
868 }
869
870int BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args)
871 {
e5c84d51
BM
872 size_t retlen;
873 int truncated;
874
e5c84d51
BM
875 _dopr(dopr_outch, dopr_isbig, dopr_copy,
876 &buf, &n, &retlen, &truncated, format, args);
877 if (truncated)
878 /* In case of truncation, return -1 like traditional snprintf.
879 * (Current drafts for ISO/IEC 9899 say snprintf should return
880 * the number of characters that would have been written,
881 * had the buffer been large enough.) */
882 return -1;
883 else
884 return (retlen <= INT_MAX) ? retlen : -1;
885 }