Branch data Line data Source code
1 : : /* crypto/bio/b_print.c */
2 : : /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 : : * All rights reserved.
4 : : *
5 : : * This package is an SSL implementation written
6 : : * by Eric Young (eay@cryptsoft.com).
7 : : * The implementation was written so as to conform with Netscapes SSL.
8 : : *
9 : : * This library is free for commercial and non-commercial use as long as
10 : : * the following conditions are aheared to. The following conditions
11 : : * apply to all code found in this distribution, be it the RC4, RSA,
12 : : * lhash, DES, etc., code; not just the SSL code. The SSL documentation
13 : : * included with this distribution is covered by the same copyright terms
14 : : * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15 : : *
16 : : * Copyright remains Eric Young's, and as such any Copyright notices in
17 : : * the code are not to be removed.
18 : : * If this package is used in a product, Eric Young should be given attribution
19 : : * as the author of the parts of the library used.
20 : : * This can be in the form of a textual message at program startup or
21 : : * in documentation (online or textual) provided with the package.
22 : : *
23 : : * Redistribution and use in source and binary forms, with or without
24 : : * modification, are permitted provided that the following conditions
25 : : * are met:
26 : : * 1. Redistributions of source code must retain the copyright
27 : : * notice, this list of conditions and the following disclaimer.
28 : : * 2. Redistributions in binary form must reproduce the above copyright
29 : : * notice, this list of conditions and the following disclaimer in the
30 : : * documentation and/or other materials provided with the distribution.
31 : : * 3. All advertising materials mentioning features or use of this software
32 : : * must display the following acknowledgement:
33 : : * "This product includes cryptographic software written by
34 : : * Eric Young (eay@cryptsoft.com)"
35 : : * The word 'cryptographic' can be left out if the rouines from the library
36 : : * being used are not cryptographic related :-).
37 : : * 4. If you include any Windows specific code (or a derivative thereof) from
38 : : * the apps directory (application code) you must include an acknowledgement:
39 : : * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40 : : *
41 : : * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42 : : * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43 : : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44 : : * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45 : : * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46 : : * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47 : : * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 : : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49 : : * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50 : : * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51 : : * SUCH DAMAGE.
52 : : *
53 : : * The licence and distribution terms for any publically available version or
54 : : * derivative of this code cannot be changed. i.e. this code cannot simply be
55 : : * copied and put under another distribution licence
56 : : * [including the GNU Public Licence.]
57 : : */
58 : :
59 : : /* disable assert() unless BIO_DEBUG has been defined */
60 : : #ifndef BIO_DEBUG
61 : : # ifndef NDEBUG
62 : : # define NDEBUG
63 : : # endif
64 : : #endif
65 : :
66 : : /*
67 : : * Stolen from tjh's ssl/ssl_trc.c stuff.
68 : : */
69 : :
70 : : #include <stdio.h>
71 : : #include <string.h>
72 : : #include <ctype.h>
73 : : #include <assert.h>
74 : : #include <limits.h>
75 : : #include "cryptlib.h"
76 : : #ifndef NO_SYS_TYPES_H
77 : : #include <sys/types.h>
78 : : #endif
79 : : #include <openssl/bn.h> /* To get BN_LLONG properly defined */
80 : : #include <openssl/bio.h>
81 : :
82 : : #if defined(BN_LLONG) || defined(SIXTY_FOUR_BIT)
83 : : # ifndef HAVE_LONG_LONG
84 : : # define HAVE_LONG_LONG 1
85 : : # endif
86 : : #endif
87 : :
88 : : /***************************************************************************/
89 : :
90 : : /*
91 : : * Copyright Patrick Powell 1995
92 : : * This code is based on code written by Patrick Powell <papowell@astart.com>
93 : : * It may be used for any purpose as long as this notice remains intact
94 : : * on all source code distributions.
95 : : */
96 : :
97 : : /*
98 : : * This code contains numerious changes and enhancements which were
99 : : * made by lots of contributors over the last years to Patrick Powell's
100 : : * original code:
101 : : *
102 : : * o Patrick Powell <papowell@astart.com> (1995)
103 : : * o Brandon Long <blong@fiction.net> (1996, for Mutt)
104 : : * o Thomas Roessler <roessler@guug.de> (1998, for Mutt)
105 : : * o Michael Elkins <me@cs.hmc.edu> (1998, for Mutt)
106 : : * o Andrew Tridgell <tridge@samba.org> (1998, for Samba)
107 : : * o Luke Mewburn <lukem@netbsd.org> (1999, for LukemFTP)
108 : : * o Ralf S. Engelschall <rse@engelschall.com> (1999, for Pth)
109 : : * o ... (for OpenSSL)
110 : : */
111 : :
112 : : #ifdef HAVE_LONG_DOUBLE
113 : : #define LDOUBLE long double
114 : : #else
115 : : #define LDOUBLE double
116 : : #endif
117 : :
118 : : #ifdef HAVE_LONG_LONG
119 : : # if defined(_WIN32) && !defined(__GNUC__)
120 : : # define LLONG __int64
121 : : # else
122 : : # define LLONG long long
123 : : # endif
124 : : #else
125 : : #define LLONG long
126 : : #endif
127 : :
128 : : static void fmtstr (char **, char **, size_t *, size_t *,
129 : : const char *, int, int, int);
130 : : static void fmtint (char **, char **, size_t *, size_t *,
131 : : LLONG, int, int, int, int);
132 : : static void fmtfp (char **, char **, size_t *, size_t *,
133 : : LDOUBLE, int, int, int);
134 : : static void doapr_outch (char **, char **, size_t *, size_t *, int);
135 : : static void _dopr(char **sbuffer, char **buffer,
136 : : size_t *maxlen, size_t *retlen, int *truncated,
137 : : const char *format, va_list args);
138 : :
139 : : /* format read states */
140 : : #define DP_S_DEFAULT 0
141 : : #define DP_S_FLAGS 1
142 : : #define DP_S_MIN 2
143 : : #define DP_S_DOT 3
144 : : #define DP_S_MAX 4
145 : : #define DP_S_MOD 5
146 : : #define DP_S_CONV 6
147 : : #define DP_S_DONE 7
148 : :
149 : : /* format flags - Bits */
150 : : #define DP_F_MINUS (1 << 0)
151 : : #define DP_F_PLUS (1 << 1)
152 : : #define DP_F_SPACE (1 << 2)
153 : : #define DP_F_NUM (1 << 3)
154 : : #define DP_F_ZERO (1 << 4)
155 : : #define DP_F_UP (1 << 5)
156 : : #define DP_F_UNSIGNED (1 << 6)
157 : :
158 : : /* conversion flags */
159 : : #define DP_C_SHORT 1
160 : : #define DP_C_LONG 2
161 : : #define DP_C_LDOUBLE 3
162 : : #define DP_C_LLONG 4
163 : :
164 : : /* some handy macros */
165 : : #define char_to_int(p) (p - '0')
166 : : #define OSSL_MAX(p,q) ((p >= q) ? p : q)
167 : :
168 : : static void
169 : 26658 : _dopr(
170 : : char **sbuffer,
171 : : char **buffer,
172 : : size_t *maxlen,
173 : : size_t *retlen,
174 : : int *truncated,
175 : : const char *format,
176 : : va_list args)
177 : : {
178 : : char ch;
179 : : LLONG value;
180 : : LDOUBLE fvalue;
181 : : char *strvalue;
182 : : int min;
183 : : int max;
184 : : int state;
185 : : int flags;
186 : : int cflags;
187 : : size_t currlen;
188 : :
189 : 26658 : state = DP_S_DEFAULT;
190 : 26658 : flags = currlen = cflags = min = 0;
191 : 26658 : max = -1;
192 : 26658 : ch = *format++;
193 : :
194 [ + + ]: 681914 : while (state != DP_S_DONE) {
195 [ + + ][ + + ]: 655256 : if (ch == '\0' || (buffer == NULL && currlen >= *maxlen))
[ - + ]
196 : 26658 : state = DP_S_DONE;
197 : :
198 [ + + + + : 655256 : switch (state) {
+ + + + ]
199 : : case DP_S_DEFAULT:
200 [ + + ]: 174082 : if (ch == '%')
201 : : state = DP_S_FLAGS;
202 : : else
203 : 102048 : doapr_outch(sbuffer,buffer, &currlen, maxlen, ch);
204 : 174082 : ch = *format++;
205 : 174082 : break;
206 : : case DP_S_FLAGS:
207 [ - - - - : 118996 : switch (ch) {
+ + ]
208 : : case '-':
209 : 0 : flags |= DP_F_MINUS;
210 : 0 : ch = *format++;
211 : 0 : break;
212 : : case '+':
213 : 0 : flags |= DP_F_PLUS;
214 : 0 : ch = *format++;
215 : 0 : break;
216 : : case ' ':
217 : 0 : flags |= DP_F_SPACE;
218 : 0 : ch = *format++;
219 : 0 : break;
220 : : case '#':
221 : 0 : flags |= DP_F_NUM;
222 : 0 : ch = *format++;
223 : 0 : break;
224 : : case '0':
225 : 46962 : flags |= DP_F_ZERO;
226 : 46962 : ch = *format++;
227 : 46962 : break;
228 : : default:
229 : : state = DP_S_MIN;
230 : : break;
231 : : }
232 : : break;
233 : : case DP_S_MIN:
234 [ + + ]: 119281 : if (isdigit((unsigned char)ch)) {
235 : 47247 : min = 10 * min + char_to_int(ch);
236 : 47247 : ch = *format++;
237 [ + + ]: 72034 : } else if (ch == '*') {
238 [ + - ]: 500 : min = va_arg(args, int);
239 : 500 : ch = *format++;
240 : 500 : state = DP_S_DOT;
241 : : } else
242 : : state = DP_S_DOT;
243 : : break;
244 : : case DP_S_DOT:
245 [ + + ]: 72034 : if (ch == '.') {
246 : 71 : state = DP_S_MAX;
247 : 71 : ch = *format++;
248 : : } else
249 : : state = DP_S_MOD;
250 : : break;
251 : : case DP_S_MAX:
252 [ + + ]: 137 : if (isdigit((unsigned char)ch)) {
253 [ + - ]: 66 : if (max < 0)
254 : 66 : max = 0;
255 : 66 : max = 10 * max + char_to_int(ch);
256 : 66 : ch = *format++;
257 [ + + ]: 71 : } else if (ch == '*') {
258 [ - + ]: 5 : max = va_arg(args, int);
259 : 5 : ch = *format++;
260 : 5 : state = DP_S_MOD;
261 : : } else
262 : : state = DP_S_MOD;
263 : : break;
264 : : case DP_S_MOD:
265 [ - + - - : 72034 : switch (ch) {
+ ]
266 : : case 'h':
267 : 0 : cflags = DP_C_SHORT;
268 : 0 : ch = *format++;
269 : 0 : break;
270 : : case 'l':
271 [ - + ]: 1731 : if (*format == 'l') {
272 : 0 : cflags = DP_C_LLONG;
273 : 0 : format++;
274 : : } else
275 : : cflags = DP_C_LONG;
276 : 1731 : ch = *format++;
277 : 1731 : break;
278 : : case 'q':
279 : 0 : cflags = DP_C_LLONG;
280 : 0 : ch = *format++;
281 : 0 : break;
282 : : case 'L':
283 : 0 : cflags = DP_C_LDOUBLE;
284 : 0 : ch = *format++;
285 : 0 : break;
286 : : default:
287 : : break;
288 : : }
289 : : state = DP_S_CONV;
290 : : break;
291 : : case DP_S_CONV:
292 [ + + + + : 72034 : switch (ch) {
- - + + -
- - - - ]
293 : : case 'd':
294 : : case 'i':
295 [ - + - + ]: 39301 : switch (cflags) {
296 : : case DP_C_SHORT:
297 [ # # ]: 0 : value = (short int)va_arg(args, int);
298 : 0 : break;
299 : : case DP_C_LONG:
300 [ + - ]: 907 : value = va_arg(args, long int);
301 : 907 : break;
302 : : case DP_C_LLONG:
303 [ # # ]: 0 : value = va_arg(args, LLONG);
304 : 0 : break;
305 : : default:
306 [ + + ]: 38394 : value = va_arg(args, int);
307 : 38394 : break;
308 : : }
309 : 39301 : fmtint(sbuffer, buffer, &currlen, maxlen,
310 : : value, 10, min, max, flags);
311 : 39301 : break;
312 : : case 'X':
313 : 566 : flags |= DP_F_UP;
314 : : /* FALLTHROUGH */
315 : : case 'x':
316 : : case 'o':
317 : : case 'u':
318 : 11588 : flags |= DP_F_UNSIGNED;
319 [ - + - + ]: 11588 : switch (cflags) {
320 : : case DP_C_SHORT:
321 [ # # ]: 0 : value = (unsigned short int)va_arg(args, unsigned int);
322 : 0 : break;
323 : : case DP_C_LONG:
324 [ + + ]: 824 : value = (LLONG) va_arg(args,
325 : : unsigned long int);
326 : 824 : break;
327 : : case DP_C_LLONG:
328 [ # # ]: 0 : value = va_arg(args, unsigned LLONG);
329 : 0 : break;
330 : : default:
331 [ + - ]: 10764 : value = (LLONG) va_arg(args,
332 : : unsigned int);
333 : 10764 : break;
334 : : }
335 [ + - ]: 23176 : fmtint(sbuffer, buffer, &currlen, maxlen, value,
336 [ + + ]: 11588 : ch == 'o' ? 8 : (ch == 'u' ? 10 : 16),
337 : : min, max, flags);
338 : 11588 : break;
339 : : case 'f':
340 [ - + ]: 66 : if (cflags == DP_C_LDOUBLE)
341 [ # # ]: 0 : fvalue = va_arg(args, LDOUBLE);
342 : : else
343 [ + - ]: 66 : fvalue = va_arg(args, double);
344 : 66 : fmtfp(sbuffer, buffer, &currlen, maxlen,
345 : : fvalue, min, max, flags);
346 : 66 : break;
347 : : case 'E':
348 : : flags |= DP_F_UP;
349 : : case 'e':
350 [ # # ]: 0 : if (cflags == DP_C_LDOUBLE)
351 [ # # ]: 0 : fvalue = va_arg(args, LDOUBLE);
352 : : else
353 [ # # ]: 0 : fvalue = va_arg(args, double);
354 : : break;
355 : : case 'G':
356 : : flags |= DP_F_UP;
357 : : case 'g':
358 [ # # ]: 0 : if (cflags == DP_C_LDOUBLE)
359 [ # # ]: 0 : fvalue = va_arg(args, LDOUBLE);
360 : : else
361 [ # # ]: 0 : fvalue = va_arg(args, double);
362 : : break;
363 : : case 'c':
364 [ + - ]: 498 : doapr_outch(sbuffer, buffer, &currlen, maxlen,
365 : : va_arg(args, int));
366 : 498 : break;
367 : : case 's':
368 [ + + ]: 20581 : strvalue = va_arg(args, char *);
369 [ + + ]: 20581 : if (max < 0) {
370 [ + + ]: 20576 : if (buffer)
371 : : max = INT_MAX;
372 : : else
373 : 2802 : max = *maxlen;
374 : : }
375 : 20581 : fmtstr(sbuffer, buffer, &currlen, maxlen, strvalue,
376 : : flags, min, max);
377 : 20581 : break;
378 : : case 'p':
379 [ # # ]: 0 : value = (long)va_arg(args, void *);
380 : 0 : fmtint(sbuffer, buffer, &currlen, maxlen,
381 : : value, 16, min, max, flags|DP_F_NUM);
382 : 0 : break;
383 : : case 'n': /* XXX */
384 [ # # ]: 0 : if (cflags == DP_C_SHORT) {
385 : : short int *num;
386 [ # # ]: 0 : num = va_arg(args, short int *);
387 : 0 : *num = currlen;
388 [ # # ]: 0 : } else if (cflags == DP_C_LONG) { /* XXX */
389 : : long int *num;
390 [ # # ]: 0 : num = va_arg(args, long int *);
391 : 0 : *num = (long int) currlen;
392 [ # # ]: 0 : } else if (cflags == DP_C_LLONG) { /* XXX */
393 : : LLONG *num;
394 [ # # ]: 0 : num = va_arg(args, LLONG *);
395 : 0 : *num = (LLONG) currlen;
396 : : } else {
397 : : int *num;
398 [ # # ]: 0 : num = va_arg(args, int *);
399 : 0 : *num = currlen;
400 : : }
401 : : break;
402 : : case '%':
403 : 0 : doapr_outch(sbuffer, buffer, &currlen, maxlen, ch);
404 : 0 : break;
405 : : case 'w':
406 : : /* not supported yet, treat as next char */
407 : 0 : ch = *format++;
408 : 0 : break;
409 : : default:
410 : : /* unknown, skip */
411 : : break;
412 : : }
413 : 72034 : ch = *format++;
414 : 72034 : state = DP_S_DEFAULT;
415 : 72034 : flags = cflags = min = 0;
416 : 72034 : max = -1;
417 : 655256 : break;
418 : : case DP_S_DONE:
419 : : break;
420 : : default:
421 : : break;
422 : : }
423 : : }
424 : 26658 : *truncated = (currlen > *maxlen - 1);
425 [ - + ]: 26658 : if (*truncated)
426 : 0 : currlen = *maxlen - 1;
427 : 26658 : doapr_outch(sbuffer, buffer, &currlen, maxlen, '\0');
428 : 26658 : *retlen = currlen - 1;
429 : 26658 : return;
430 : : }
431 : :
432 : : static void
433 : 20581 : fmtstr(
434 : : char **sbuffer,
435 : : char **buffer,
436 : : size_t *currlen,
437 : : size_t *maxlen,
438 : : const char *value,
439 : : int flags,
440 : : int min,
441 : : int max)
442 : : {
443 : : int padlen, strln;
444 : 20581 : int cnt = 0;
445 : :
446 [ + + ]: 20581 : if (value == 0)
447 : 5 : value = "<NULL>";
448 [ + + ]: 127633 : for (strln = 0; value[strln]; ++strln)
449 : : ;
450 : 20581 : padlen = min - strln;
451 [ + + ]: 20581 : if (padlen < 0)
452 : 18557 : padlen = 0;
453 [ - + ]: 20581 : if (flags & DP_F_MINUS)
454 : 20581 : padlen = -padlen;
455 : :
456 [ + + ]: 28405 : while ((padlen > 0) && (cnt < max)) {
457 : 7824 : doapr_outch(sbuffer, buffer, currlen, maxlen, ' ');
458 : 7824 : --padlen;
459 : 7824 : ++cnt;
460 : : }
461 [ + + ][ + + ]: 127603 : while (*value && (cnt < max)) {
462 : 107022 : doapr_outch(sbuffer, buffer, currlen, maxlen, *value++);
463 : 107022 : ++cnt;
464 : : }
465 [ - + ]: 20581 : while ((padlen < 0) && (cnt < max)) {
466 : 0 : doapr_outch(sbuffer, buffer, currlen, maxlen, ' ');
467 : 0 : ++padlen;
468 : 0 : ++cnt;
469 : : }
470 : 20581 : }
471 : :
472 : : static void
473 : 50889 : fmtint(
474 : : char **sbuffer,
475 : : char **buffer,
476 : : size_t *currlen,
477 : : size_t *maxlen,
478 : : LLONG value,
479 : : int base,
480 : : int min,
481 : : int max,
482 : : int flags)
483 : : {
484 : 50889 : int signvalue = 0;
485 : 50889 : const char *prefix = "";
486 : : unsigned LLONG uvalue;
487 : : char convert[DECIMAL_SIZE(value)+3];
488 : 50889 : int place = 0;
489 : 50889 : int spadlen = 0;
490 : 50889 : int zpadlen = 0;
491 : 50889 : int caps = 0;
492 : :
493 [ + - ]: 50889 : if (max < 0)
494 : 50889 : max = 0;
495 : 50889 : uvalue = value;
496 [ + + ]: 50889 : if (!(flags & DP_F_UNSIGNED)) {
497 [ - + ]: 39301 : if (value < 0) {
498 : 0 : signvalue = '-';
499 : 0 : uvalue = -value;
500 [ + - ]: 39301 : } else if (flags & DP_F_PLUS)
501 : : signvalue = '+';
502 [ - + ]: 39301 : else if (flags & DP_F_SPACE)
503 : 0 : signvalue = ' ';
504 : : }
505 [ - + ]: 50889 : if (flags & DP_F_NUM) {
506 [ # # ]: 0 : if (base == 8) prefix = "0";
507 [ # # ]: 0 : if (base == 16) prefix = "0x";
508 : : }
509 [ + + ]: 50889 : if (flags & DP_F_UP)
510 : 50889 : caps = 1;
511 : : do {
512 : 198846 : convert[place++] =
513 [ + + ]: 99423 : (caps ? "0123456789ABCDEF" : "0123456789abcdef")
514 : 99423 : [uvalue % (unsigned) base];
515 : 99423 : uvalue = (uvalue / (unsigned) base);
516 [ + + ]: 99423 : } while (uvalue && (place < (int)sizeof(convert)));
517 [ - + ]: 50889 : if (place == sizeof(convert))
518 : 0 : place--;
519 : 50889 : convert[place] = 0;
520 : :
521 : 50889 : zpadlen = max - place;
522 : 50889 : spadlen = min - OSSL_MAX(max, place) - (signvalue ? 1 : 0) - strlen(prefix);
523 [ + - ]: 50889 : if (zpadlen < 0)
524 : 50889 : zpadlen = 0;
525 [ + + ]: 50889 : if (spadlen < 0)
526 : 3836 : spadlen = 0;
527 [ + + ]: 50889 : if (flags & DP_F_ZERO) {
528 : 46962 : zpadlen = OSSL_MAX(zpadlen, spadlen);
529 : 46962 : spadlen = 0;
530 : : }
531 [ - + ]: 50889 : if (flags & DP_F_MINUS)
532 : 50889 : spadlen = -spadlen;
533 : :
534 : : /* spaces */
535 [ + + ]: 50940 : while (spadlen > 0) {
536 : 51 : doapr_outch(sbuffer, buffer, currlen, maxlen, ' ');
537 : 51 : --spadlen;
538 : : }
539 : :
540 : : /* sign */
541 [ - + ]: 50889 : if (signvalue)
542 : 50889 : doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue);
543 : :
544 : : /* prefix */
545 [ - + ]: 50889 : while (*prefix) {
546 : 0 : doapr_outch(sbuffer, buffer, currlen, maxlen, *prefix);
547 : 0 : prefix++;
548 : : }
549 : :
550 : : /* zeros */
551 [ + + ]: 50889 : if (zpadlen > 0) {
552 [ + + ]: 63644 : while (zpadlen > 0) {
553 : 12755 : doapr_outch(sbuffer, buffer, currlen, maxlen, '0');
554 : 12755 : --zpadlen;
555 : : }
556 : : }
557 : : /* digits */
558 [ + + ]: 150312 : while (place > 0)
559 : 99423 : doapr_outch(sbuffer, buffer, currlen, maxlen, convert[--place]);
560 : :
561 : : /* left justified spaces */
562 [ - + ]: 50889 : while (spadlen < 0) {
563 : 0 : doapr_outch(sbuffer, buffer, currlen, maxlen, ' ');
564 : 0 : ++spadlen;
565 : : }
566 : 50889 : return;
567 : : }
568 : :
569 : : static LDOUBLE
570 : 66 : abs_val(LDOUBLE value)
571 : : {
572 : 66 : LDOUBLE result = value;
573 [ - + ]: 66 : if (value < 0)
574 : 0 : result = -value;
575 : 66 : return result;
576 : : }
577 : :
578 : : static LDOUBLE
579 : 66 : pow_10(int in_exp)
580 : : {
581 : 66 : LDOUBLE result = 1;
582 [ + + ]: 198 : while (in_exp) {
583 : 132 : result *= 10;
584 : 132 : in_exp--;
585 : : }
586 : 66 : return result;
587 : : }
588 : :
589 : : static long
590 : 132 : roundv(LDOUBLE value)
591 : : {
592 : : long intpart;
593 : 132 : intpart = (long) value;
594 : 132 : value = value - intpart;
595 [ - + ]: 132 : if (value >= 0.5)
596 : 0 : intpart++;
597 : 132 : return intpart;
598 : : }
599 : :
600 : : static void
601 : 66 : fmtfp(
602 : : char **sbuffer,
603 : : char **buffer,
604 : : size_t *currlen,
605 : : size_t *maxlen,
606 : : LDOUBLE fvalue,
607 : : int min,
608 : : int max,
609 : : int flags)
610 : : {
611 : 66 : int signvalue = 0;
612 : : LDOUBLE ufvalue;
613 : : char iconvert[20];
614 : : char fconvert[20];
615 : 66 : int iplace = 0;
616 : 66 : int fplace = 0;
617 : 66 : int padlen = 0;
618 : 66 : int zpadlen = 0;
619 : 66 : int caps = 0;
620 : : long intpart;
621 : : long fracpart;
622 : : long max10;
623 : :
624 [ - + ]: 66 : if (max < 0)
625 : 0 : max = 6;
626 : 66 : ufvalue = abs_val(fvalue);
627 [ + - ]: 66 : if (fvalue < 0)
628 : : signvalue = '-';
629 [ + - ]: 66 : else if (flags & DP_F_PLUS)
630 : : signvalue = '+';
631 [ - + ]: 66 : else if (flags & DP_F_SPACE)
632 : 0 : signvalue = ' ';
633 : :
634 : 66 : intpart = (long)ufvalue;
635 : :
636 : : /* sorry, we only support 9 digits past the decimal because of our
637 : : conversion method */
638 [ - + ]: 66 : if (max > 9)
639 : 0 : max = 9;
640 : :
641 : : /* we "cheat" by converting the fractional part to integer by
642 : : multiplying by a factor of 10 */
643 : 66 : max10 = roundv(pow_10(max));
644 : 66 : fracpart = roundv(pow_10(max) * (ufvalue - intpart));
645 : :
646 [ - + ]: 66 : if (fracpart >= max10) {
647 : 0 : intpart++;
648 : 66 : fracpart -= max10;
649 : : }
650 : :
651 : : /* convert integer part */
652 : : do {
653 : 132 : iconvert[iplace++] =
654 : : (caps ? "0123456789ABCDEF"
655 : 66 : : "0123456789abcdef")[intpart % 10];
656 : 66 : intpart = (intpart / 10);
657 [ - + ]: 66 : } while (intpart && (iplace < (int)sizeof(iconvert)));
658 [ - + ]: 66 : if (iplace == sizeof iconvert)
659 : 0 : iplace--;
660 : 66 : iconvert[iplace] = 0;
661 : :
662 : : /* convert fractional part */
663 : : do {
664 : 264 : fconvert[fplace++] =
665 : : (caps ? "0123456789ABCDEF"
666 : 132 : : "0123456789abcdef")[fracpart % 10];
667 : 132 : fracpart = (fracpart / 10);
668 [ + + ]: 132 : } while (fplace < max);
669 [ - + ]: 66 : if (fplace == sizeof fconvert)
670 : 0 : fplace--;
671 : 66 : fconvert[fplace] = 0;
672 : :
673 : : /* -1 for decimal point, another -1 if we are printing a sign */
674 : 66 : padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0);
675 : 66 : zpadlen = max - fplace;
676 [ - + ]: 66 : if (zpadlen < 0)
677 : 0 : zpadlen = 0;
678 [ - + ]: 66 : if (padlen < 0)
679 : 0 : padlen = 0;
680 [ - + ]: 66 : if (flags & DP_F_MINUS)
681 : 0 : padlen = -padlen;
682 : :
683 [ - + ][ # # ]: 66 : if ((flags & DP_F_ZERO) && (padlen > 0)) {
684 [ # # ]: 0 : if (signvalue) {
685 : 0 : doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue);
686 : 0 : --padlen;
687 : 0 : signvalue = 0;
688 : : }
689 [ # # ]: 0 : while (padlen > 0) {
690 : 0 : doapr_outch(sbuffer, buffer, currlen, maxlen, '0');
691 : 0 : --padlen;
692 : : }
693 : : }
694 [ + + ]: 198 : while (padlen > 0) {
695 : 132 : doapr_outch(sbuffer, buffer, currlen, maxlen, ' ');
696 : 132 : --padlen;
697 : : }
698 [ - + ]: 66 : if (signvalue)
699 : 66 : doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue);
700 : :
701 [ + + ]: 132 : while (iplace > 0)
702 : 66 : doapr_outch(sbuffer, buffer, currlen, maxlen, iconvert[--iplace]);
703 : :
704 : : /*
705 : : * Decimal point. This should probably use locale to find the correct
706 : : * char to print out.
707 : : */
708 [ - + ][ # # ]: 66 : if (max > 0 || (flags & DP_F_NUM)) {
709 : 66 : doapr_outch(sbuffer, buffer, currlen, maxlen, '.');
710 : :
711 [ + + ]: 198 : while (fplace > 0)
712 : 132 : doapr_outch(sbuffer, buffer, currlen, maxlen, fconvert[--fplace]);
713 : : }
714 [ - + ]: 66 : while (zpadlen > 0) {
715 : 0 : doapr_outch(sbuffer, buffer, currlen, maxlen, '0');
716 : 0 : --zpadlen;
717 : : }
718 : :
719 [ - + ]: 66 : while (padlen < 0) {
720 : 0 : doapr_outch(sbuffer, buffer, currlen, maxlen, ' ');
721 : 0 : ++padlen;
722 : : }
723 : 66 : }
724 : :
725 : : static void
726 : 356675 : doapr_outch(
727 : : char **sbuffer,
728 : : char **buffer,
729 : : size_t *currlen,
730 : : size_t *maxlen,
731 : : int c)
732 : : {
733 : : /* If we haven't at least one buffer, someone has doe a big booboo */
734 : : assert(*sbuffer != NULL || buffer != NULL);
735 : :
736 [ + + ]: 356675 : if (buffer) {
737 [ - + ]: 218726 : while (*currlen >= *maxlen) {
738 [ # # ]: 0 : if (*buffer == NULL) {
739 [ # # ]: 0 : if (*maxlen == 0)
740 : 0 : *maxlen = 1024;
741 : 0 : *buffer = OPENSSL_malloc(*maxlen);
742 [ # # ]: 0 : if (*currlen > 0) {
743 : : assert(*sbuffer != NULL);
744 : 0 : memcpy(*buffer, *sbuffer, *currlen);
745 : : }
746 : 0 : *sbuffer = NULL;
747 : : } else {
748 : 0 : *maxlen += 1024;
749 : 0 : *buffer = OPENSSL_realloc(*buffer, *maxlen);
750 : : }
751 : : }
752 : : /* What to do if *buffer is NULL? */
753 : : assert(*sbuffer != NULL || *buffer != NULL);
754 : : }
755 : :
756 [ + - ]: 356675 : if (*currlen < *maxlen) {
757 [ + - ]: 356675 : if (*sbuffer)
758 : 356675 : (*sbuffer)[(*currlen)++] = (char)c;
759 : : else
760 : 0 : (*buffer)[(*currlen)++] = (char)c;
761 : : }
762 : :
763 : 356675 : return;
764 : : }
765 : :
766 : : /***************************************************************************/
767 : :
768 : 19084 : int BIO_printf (BIO *bio, const char *format, ...)
769 : : {
770 : : va_list args;
771 : : int ret;
772 : :
773 : 19084 : va_start(args, format);
774 : :
775 : 19084 : ret = BIO_vprintf(bio, format, args);
776 : :
777 : 19084 : va_end(args);
778 : 19084 : return(ret);
779 : : }
780 : :
781 : 19084 : int BIO_vprintf (BIO *bio, const char *format, va_list args)
782 : : {
783 : : int ret;
784 : : size_t retlen;
785 : : char hugebuf[1024*2]; /* Was previously 10k, which is unreasonable
786 : : in small-stack environments, like threads
787 : : or DOS programs. */
788 : 19084 : char *hugebufp = hugebuf;
789 : 19084 : size_t hugebufsize = sizeof(hugebuf);
790 : 19084 : char *dynbuf = NULL;
791 : : int ignored;
792 : :
793 : : dynbuf = NULL;
794 : 19084 : CRYPTO_push_info("doapr()");
795 : 19084 : _dopr(&hugebufp, &dynbuf, &hugebufsize,
796 : : &retlen, &ignored, format, args);
797 [ - + ]: 19084 : if (dynbuf)
798 : : {
799 : 0 : ret=BIO_write(bio, dynbuf, (int)retlen);
800 : 0 : OPENSSL_free(dynbuf);
801 : : }
802 : : else
803 : : {
804 : 19084 : ret=BIO_write(bio, hugebuf, (int)retlen);
805 : : }
806 : 19084 : CRYPTO_pop_info();
807 : 19084 : return(ret);
808 : : }
809 : :
810 : : /* As snprintf is not available everywhere, we provide our own implementation.
811 : : * This function has nothing to do with BIOs, but it's closely related
812 : : * to BIO_printf, and we need *some* name prefix ...
813 : : * (XXX the function should be renamed, but to what?) */
814 : 7574 : int BIO_snprintf(char *buf, size_t n, const char *format, ...)
815 : : {
816 : : va_list args;
817 : : int ret;
818 : :
819 : 7574 : va_start(args, format);
820 : :
821 : 7574 : ret = BIO_vsnprintf(buf, n, format, args);
822 : :
823 : 7574 : va_end(args);
824 : 7574 : return(ret);
825 : : }
826 : :
827 : 7574 : int BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args)
828 : : {
829 : : size_t retlen;
830 : : int truncated;
831 : :
832 : 7574 : _dopr(&buf, NULL, &n, &retlen, &truncated, format, args);
833 : :
834 [ + - ]: 7574 : if (truncated)
835 : : /* In case of truncation, return -1 like traditional snprintf.
836 : : * (Current drafts for ISO/IEC 9899 say snprintf should return
837 : : * the number of characters that would have been written,
838 : : * had the buffer been large enough.) */
839 : : return -1;
840 : : else
841 [ + - ]: 7574 : return (retlen <= INT_MAX) ? (int)retlen : -1;
842 : : }
|