| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2017-08-21 05:19:17 +08:00
										 |  |  |  * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. | 
					
						
							| 
									
										
										
										
											2016-05-18 02:52:22 +08:00
										 |  |  |  * | 
					
						
							|  |  |  |  * Licensed under the OpenSSL license (the "License").  You may not use | 
					
						
							|  |  |  |  * this file except in compliance with the License.  You can obtain a copy | 
					
						
							|  |  |  |  * in the file LICENSE in the source distribution or at | 
					
						
							|  |  |  |  * https://www.openssl.org/source/license.html
 | 
					
						
							| 
									
										
										
										
											1998-12-21 18:52:47 +08:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <stdio.h>
 | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  | #include <string.h>
 | 
					
						
							| 
									
										
										
										
											2017-08-21 05:19:17 +08:00
										 |  |  | #include "internal/ctype.h"
 | 
					
						
							| 
									
										
										
										
											2016-05-21 09:46:43 +08:00
										 |  |  | #include "internal/numbers.h"
 | 
					
						
							| 
									
										
										
										
											2015-05-14 22:56:48 +08:00
										 |  |  | #include "internal/cryptlib.h"
 | 
					
						
							| 
									
										
										
										
											1999-04-24 06:13:45 +08:00
										 |  |  | #include <openssl/bio.h>
 | 
					
						
							| 
									
										
										
										
											1998-12-21 18:52:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-02-25 06:23:45 +08:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Copyright Patrick Powell 1995 | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |  * This code is based on code written by Patrick Powell <papowell@astart.com> | 
					
						
							| 
									
										
										
										
											2000-02-25 06:23:45 +08:00
										 |  |  |  * It may be used for any purpose as long as this notice remains intact | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |  * on all source code distributions. | 
					
						
							| 
									
										
										
										
											2000-02-25 06:23:45 +08:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-08-02 19:13:37 +08:00
										 |  |  | #ifdef HAVE_LONG_DOUBLE
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | # define LDOUBLE long double
 | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | # define LDOUBLE double
 | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-25 21:09:46 +08:00
										 |  |  | static int fmtstr(char **, char **, size_t *, size_t *, | 
					
						
							|  |  |  |                   const char *, int, int, int); | 
					
						
							|  |  |  | static int fmtint(char **, char **, size_t *, size_t *, | 
					
						
							| 
									
										
										
										
											2017-03-31 03:44:55 +08:00
										 |  |  |                   int64_t, int, int, int, int); | 
					
						
							| 
									
										
										
										
											2016-02-25 21:09:46 +08:00
										 |  |  | static int fmtfp(char **, char **, size_t *, size_t *, | 
					
						
							| 
									
										
										
										
											2016-05-25 22:33:15 +08:00
										 |  |  |                  LDOUBLE, int, int, int, int); | 
					
						
							| 
									
										
										
										
											2016-02-25 21:09:46 +08:00
										 |  |  | static int doapr_outch(char **, char **, size_t *, size_t *, int); | 
					
						
							|  |  |  | static int _dopr(char **sbuffer, char **buffer, | 
					
						
							|  |  |  |                  size_t *maxlen, size_t *retlen, int *truncated, | 
					
						
							|  |  |  |                  const char *format, va_list args); | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-02-25 06:23:45 +08:00
										 |  |  | /* format read states */ | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  | #define DP_S_DEFAULT    0
 | 
					
						
							|  |  |  | #define DP_S_FLAGS      1
 | 
					
						
							|  |  |  | #define DP_S_MIN        2
 | 
					
						
							|  |  |  | #define DP_S_DOT        3
 | 
					
						
							|  |  |  | #define DP_S_MAX        4
 | 
					
						
							|  |  |  | #define DP_S_MOD        5
 | 
					
						
							|  |  |  | #define DP_S_CONV       6
 | 
					
						
							|  |  |  | #define DP_S_DONE       7
 | 
					
						
							| 
									
										
										
										
											2000-02-25 06:23:45 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* format flags - Bits */ | 
					
						
							| 
									
										
										
										
											2016-05-25 22:37:11 +08:00
										 |  |  | /* left-aligned padding */ | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  | #define DP_F_MINUS      (1 << 0)
 | 
					
						
							| 
									
										
										
										
											2016-05-25 22:37:11 +08:00
										 |  |  | /* print an explicit '+' for a value with positive sign */ | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  | #define DP_F_PLUS       (1 << 1)
 | 
					
						
							| 
									
										
										
										
											2016-05-25 22:37:11 +08:00
										 |  |  | /* print an explicit ' ' for a value with positive sign */ | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  | #define DP_F_SPACE      (1 << 2)
 | 
					
						
							| 
									
										
										
										
											2016-05-25 22:37:11 +08:00
										 |  |  | /* print 0/0x prefix for octal/hex and decimal point for floating point */ | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  | #define DP_F_NUM        (1 << 3)
 | 
					
						
							| 
									
										
										
										
											2016-05-25 22:37:11 +08:00
										 |  |  | /* print leading zeroes */ | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  | #define DP_F_ZERO       (1 << 4)
 | 
					
						
							| 
									
										
										
										
											2016-05-25 22:37:11 +08:00
										 |  |  | /* print HEX in UPPPERcase */ | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  | #define DP_F_UP         (1 << 5)
 | 
					
						
							| 
									
										
										
										
											2016-05-25 22:37:11 +08:00
										 |  |  | /* treat value as unsigned */ | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  | #define DP_F_UNSIGNED   (1 << 6)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* conversion flags */ | 
					
						
							|  |  |  | #define DP_C_SHORT      1
 | 
					
						
							|  |  |  | #define DP_C_LONG       2
 | 
					
						
							|  |  |  | #define DP_C_LDOUBLE    3
 | 
					
						
							|  |  |  | #define DP_C_LLONG      4
 | 
					
						
							| 
									
										
										
										
											2017-03-28 22:57:41 +08:00
										 |  |  | #define DP_C_SIZE       5
 | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-25 22:33:15 +08:00
										 |  |  | /* Floating point formats */ | 
					
						
							|  |  |  | #define F_FORMAT        0
 | 
					
						
							|  |  |  | #define E_FORMAT        1
 | 
					
						
							|  |  |  | #define G_FORMAT        2
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  | /* some handy macros */ | 
					
						
							| 
									
										
										
										
											2000-02-25 06:23:45 +08:00
										 |  |  | #define char_to_int(p) (p - '0')
 | 
					
						
							| 
									
										
										
										
											2000-10-22 20:44:12 +08:00
										 |  |  | #define OSSL_MAX(p,q) ((p >= q) ? p : q)
 | 
					
						
							| 
									
										
										
										
											2000-02-25 06:23:45 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-25 21:09:46 +08:00
										 |  |  | static int | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | _dopr(char **sbuffer, | 
					
						
							|  |  |  |       char **buffer, | 
					
						
							|  |  |  |       size_t *maxlen, | 
					
						
							|  |  |  |       size_t *retlen, int *truncated, const char *format, va_list args) | 
					
						
							| 
									
										
										
										
											2000-02-25 06:23:45 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |     char ch; | 
					
						
							| 
									
										
										
										
											2017-03-31 03:44:55 +08:00
										 |  |  |     int64_t value; | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |     LDOUBLE fvalue; | 
					
						
							|  |  |  |     char *strvalue; | 
					
						
							|  |  |  |     int min; | 
					
						
							|  |  |  |     int max; | 
					
						
							|  |  |  |     int state; | 
					
						
							|  |  |  |     int flags; | 
					
						
							|  |  |  |     int cflags; | 
					
						
							|  |  |  |     size_t currlen; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     state = DP_S_DEFAULT; | 
					
						
							|  |  |  |     flags = currlen = cflags = min = 0; | 
					
						
							|  |  |  |     max = -1; | 
					
						
							|  |  |  |     ch = *format++; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     while (state != DP_S_DONE) { | 
					
						
							| 
									
										
										
										
											2000-09-07 13:50:14 +08:00
										 |  |  |         if (ch == '\0' || (buffer == NULL && currlen >= *maxlen)) | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |             state = DP_S_DONE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         switch (state) { | 
					
						
							|  |  |  |         case DP_S_DEFAULT: | 
					
						
							|  |  |  |             if (ch == '%') | 
					
						
							|  |  |  |                 state = DP_S_FLAGS; | 
					
						
							|  |  |  |             else | 
					
						
							| 
									
										
										
										
											2017-08-26 23:56:44 +08:00
										 |  |  |                 if (!doapr_outch(sbuffer, buffer, &currlen, maxlen, ch)) | 
					
						
							| 
									
										
										
										
											2016-02-25 21:09:46 +08:00
										 |  |  |                     return 0; | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |             ch = *format++; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case DP_S_FLAGS: | 
					
						
							|  |  |  |             switch (ch) { | 
					
						
							|  |  |  |             case '-': | 
					
						
							|  |  |  |                 flags |= DP_F_MINUS; | 
					
						
							|  |  |  |                 ch = *format++; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case '+': | 
					
						
							|  |  |  |                 flags |= DP_F_PLUS; | 
					
						
							|  |  |  |                 ch = *format++; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case ' ': | 
					
						
							|  |  |  |                 flags |= DP_F_SPACE; | 
					
						
							|  |  |  |                 ch = *format++; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case '#': | 
					
						
							|  |  |  |                 flags |= DP_F_NUM; | 
					
						
							|  |  |  |                 ch = *format++; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case '0': | 
					
						
							|  |  |  |                 flags |= DP_F_ZERO; | 
					
						
							|  |  |  |                 ch = *format++; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             default: | 
					
						
							|  |  |  |                 state = DP_S_MIN; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case DP_S_MIN: | 
					
						
							| 
									
										
										
										
											2017-08-21 05:19:17 +08:00
										 |  |  |             if (ossl_isdigit(ch)) { | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |                 min = 10 * min + char_to_int(ch); | 
					
						
							|  |  |  |                 ch = *format++; | 
					
						
							|  |  |  |             } else if (ch == '*') { | 
					
						
							|  |  |  |                 min = va_arg(args, int); | 
					
						
							|  |  |  |                 ch = *format++; | 
					
						
							|  |  |  |                 state = DP_S_DOT; | 
					
						
							|  |  |  |             } else | 
					
						
							|  |  |  |                 state = DP_S_DOT; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case DP_S_DOT: | 
					
						
							|  |  |  |             if (ch == '.') { | 
					
						
							|  |  |  |                 state = DP_S_MAX; | 
					
						
							|  |  |  |                 ch = *format++; | 
					
						
							|  |  |  |             } else | 
					
						
							|  |  |  |                 state = DP_S_MOD; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case DP_S_MAX: | 
					
						
							| 
									
										
										
										
											2017-08-21 05:19:17 +08:00
										 |  |  |             if (ossl_isdigit(ch)) { | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |                 if (max < 0) | 
					
						
							|  |  |  |                     max = 0; | 
					
						
							|  |  |  |                 max = 10 * max + char_to_int(ch); | 
					
						
							|  |  |  |                 ch = *format++; | 
					
						
							|  |  |  |             } else if (ch == '*') { | 
					
						
							|  |  |  |                 max = va_arg(args, int); | 
					
						
							|  |  |  |                 ch = *format++; | 
					
						
							|  |  |  |                 state = DP_S_MOD; | 
					
						
							|  |  |  |             } else | 
					
						
							|  |  |  |                 state = DP_S_MOD; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case DP_S_MOD: | 
					
						
							|  |  |  |             switch (ch) { | 
					
						
							|  |  |  |             case 'h': | 
					
						
							|  |  |  |                 cflags = DP_C_SHORT; | 
					
						
							|  |  |  |                 ch = *format++; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case 'l': | 
					
						
							|  |  |  |                 if (*format == 'l') { | 
					
						
							|  |  |  |                     cflags = DP_C_LLONG; | 
					
						
							|  |  |  |                     format++; | 
					
						
							|  |  |  |                 } else | 
					
						
							|  |  |  |                     cflags = DP_C_LONG; | 
					
						
							|  |  |  |                 ch = *format++; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case 'q': | 
					
						
							| 
									
										
										
										
											2017-03-30 05:10:08 +08:00
										 |  |  |             case 'j': | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |                 cflags = DP_C_LLONG; | 
					
						
							|  |  |  |                 ch = *format++; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case 'L': | 
					
						
							|  |  |  |                 cflags = DP_C_LDOUBLE; | 
					
						
							|  |  |  |                 ch = *format++; | 
					
						
							|  |  |  |                 break; | 
					
						
							| 
									
										
										
										
											2017-03-28 22:57:41 +08:00
										 |  |  |             case 'z': | 
					
						
							|  |  |  |                 cflags = DP_C_SIZE; | 
					
						
							|  |  |  |                 ch = *format++; | 
					
						
							|  |  |  |                 break; | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |             default: | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             state = DP_S_CONV; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case DP_S_CONV: | 
					
						
							|  |  |  |             switch (ch) { | 
					
						
							|  |  |  |             case 'd': | 
					
						
							|  |  |  |             case 'i': | 
					
						
							|  |  |  |                 switch (cflags) { | 
					
						
							|  |  |  |                 case DP_C_SHORT: | 
					
						
							| 
									
										
										
										
											2000-02-28 07:17:18 +08:00
										 |  |  |                     value = (short int)va_arg(args, int); | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |                     break; | 
					
						
							|  |  |  |                 case DP_C_LONG: | 
					
						
							|  |  |  |                     value = va_arg(args, long int); | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 case DP_C_LLONG: | 
					
						
							| 
									
										
										
										
											2017-03-31 03:44:55 +08:00
										 |  |  |                     value = va_arg(args, int64_t); | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |                     break; | 
					
						
							| 
									
										
										
										
											2017-03-28 22:57:41 +08:00
										 |  |  |                 case DP_C_SIZE: | 
					
						
							|  |  |  |                     value = va_arg(args, ossl_ssize_t); | 
					
						
							|  |  |  |                     break; | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |                 default: | 
					
						
							|  |  |  |                     value = va_arg(args, int); | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2016-02-25 21:09:46 +08:00
										 |  |  |                 if (!fmtint(sbuffer, buffer, &currlen, maxlen, value, 10, min, | 
					
						
							|  |  |  |                             max, flags)) | 
					
						
							|  |  |  |                     return 0; | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |                 break; | 
					
						
							|  |  |  |             case 'X': | 
					
						
							|  |  |  |                 flags |= DP_F_UP; | 
					
						
							|  |  |  |                 /* FALLTHROUGH */ | 
					
						
							|  |  |  |             case 'x': | 
					
						
							|  |  |  |             case 'o': | 
					
						
							|  |  |  |             case 'u': | 
					
						
							|  |  |  |                 flags |= DP_F_UNSIGNED; | 
					
						
							|  |  |  |                 switch (cflags) { | 
					
						
							|  |  |  |                 case DP_C_SHORT: | 
					
						
							| 
									
										
										
										
											2000-02-28 19:30:31 +08:00
										 |  |  |                     value = (unsigned short int)va_arg(args, unsigned int); | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |                     break; | 
					
						
							|  |  |  |                 case DP_C_LONG: | 
					
						
							| 
									
										
										
										
											2017-03-31 03:44:55 +08:00
										 |  |  |                     value = va_arg(args, unsigned long int); | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |                     break; | 
					
						
							|  |  |  |                 case DP_C_LLONG: | 
					
						
							| 
									
										
										
										
											2017-03-31 03:44:55 +08:00
										 |  |  |                     value = va_arg(args, uint64_t); | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |                     break; | 
					
						
							| 
									
										
										
										
											2017-03-28 22:57:41 +08:00
										 |  |  |                 case DP_C_SIZE: | 
					
						
							| 
									
										
										
										
											2017-03-30 04:48:26 +08:00
										 |  |  |                     value = va_arg(args, size_t); | 
					
						
							| 
									
										
										
										
											2017-03-28 22:57:41 +08:00
										 |  |  |                     break; | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |                 default: | 
					
						
							| 
									
										
										
										
											2017-03-31 03:44:55 +08:00
										 |  |  |                     value = va_arg(args, unsigned int); | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |                     break; | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2016-02-25 21:09:46 +08:00
										 |  |  |                 if (!fmtint(sbuffer, buffer, &currlen, maxlen, value, | 
					
						
							|  |  |  |                             ch == 'o' ? 8 : (ch == 'u' ? 10 : 16), | 
					
						
							|  |  |  |                             min, max, flags)) | 
					
						
							|  |  |  |                     return 0; | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |                 break; | 
					
						
							|  |  |  |             case 'f': | 
					
						
							|  |  |  |                 if (cflags == DP_C_LDOUBLE) | 
					
						
							|  |  |  |                     fvalue = va_arg(args, LDOUBLE); | 
					
						
							|  |  |  |                 else | 
					
						
							|  |  |  |                     fvalue = va_arg(args, double); | 
					
						
							| 
									
										
										
										
											2016-02-25 21:09:46 +08:00
										 |  |  |                 if (!fmtfp(sbuffer, buffer, &currlen, maxlen, fvalue, min, max, | 
					
						
							| 
									
										
										
										
											2016-05-25 22:33:15 +08:00
										 |  |  |                            flags, F_FORMAT)) | 
					
						
							| 
									
										
										
										
											2016-02-25 21:09:46 +08:00
										 |  |  |                     return 0; | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |                 break; | 
					
						
							|  |  |  |             case 'E': | 
					
						
							|  |  |  |                 flags |= DP_F_UP; | 
					
						
							| 
									
										
										
										
											2017-05-11 22:21:37 +08:00
										 |  |  |                 /* fall thru */ | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |             case 'e': | 
					
						
							|  |  |  |                 if (cflags == DP_C_LDOUBLE) | 
					
						
							|  |  |  |                     fvalue = va_arg(args, LDOUBLE); | 
					
						
							|  |  |  |                 else | 
					
						
							|  |  |  |                     fvalue = va_arg(args, double); | 
					
						
							| 
									
										
										
										
											2016-05-25 22:37:11 +08:00
										 |  |  |                 if (!fmtfp(sbuffer, buffer, &currlen, maxlen, fvalue, min, max, | 
					
						
							| 
									
										
										
										
											2016-05-25 22:33:15 +08:00
										 |  |  |                            flags, E_FORMAT)) | 
					
						
							| 
									
										
										
										
											2016-05-25 22:37:11 +08:00
										 |  |  |                     return 0; | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |                 break; | 
					
						
							|  |  |  |             case 'G': | 
					
						
							|  |  |  |                 flags |= DP_F_UP; | 
					
						
							| 
									
										
										
										
											2017-05-11 22:21:37 +08:00
										 |  |  |                 /* fall thru */ | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |             case 'g': | 
					
						
							|  |  |  |                 if (cflags == DP_C_LDOUBLE) | 
					
						
							|  |  |  |                     fvalue = va_arg(args, LDOUBLE); | 
					
						
							|  |  |  |                 else | 
					
						
							|  |  |  |                     fvalue = va_arg(args, double); | 
					
						
							| 
									
										
										
										
											2016-05-25 22:37:11 +08:00
										 |  |  |                 if (!fmtfp(sbuffer, buffer, &currlen, maxlen, fvalue, min, max, | 
					
						
							| 
									
										
										
										
											2016-05-25 22:33:15 +08:00
										 |  |  |                            flags, G_FORMAT)) | 
					
						
							| 
									
										
										
										
											2016-05-25 22:37:11 +08:00
										 |  |  |                     return 0; | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |                 break; | 
					
						
							|  |  |  |             case 'c': | 
					
						
							| 
									
										
										
										
											2017-08-26 23:56:44 +08:00
										 |  |  |                 if (!doapr_outch(sbuffer, buffer, &currlen, maxlen, | 
					
						
							|  |  |  |                                  va_arg(args, int))) | 
					
						
							| 
									
										
										
										
											2016-02-25 21:09:46 +08:00
										 |  |  |                     return 0; | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |                 break; | 
					
						
							|  |  |  |             case 's': | 
					
						
							|  |  |  |                 strvalue = va_arg(args, char *); | 
					
						
							| 
									
										
										
										
											2000-09-07 13:50:14 +08:00
										 |  |  |                 if (max < 0) { | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |                     if (buffer) | 
					
						
							|  |  |  |                         max = INT_MAX; | 
					
						
							|  |  |  |                     else | 
					
						
							|  |  |  |                         max = *maxlen; | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2016-02-25 21:09:46 +08:00
										 |  |  |                 if (!fmtstr(sbuffer, buffer, &currlen, maxlen, strvalue, | 
					
						
							|  |  |  |                             flags, min, max)) | 
					
						
							|  |  |  |                     return 0; | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |                 break; | 
					
						
							|  |  |  |             case 'p': | 
					
						
							| 
									
										
										
										
											2015-09-30 16:36:21 +08:00
										 |  |  |                 value = (size_t)va_arg(args, void *); | 
					
						
							| 
									
										
										
										
											2016-02-25 21:09:46 +08:00
										 |  |  |                 if (!fmtint(sbuffer, buffer, &currlen, maxlen, | 
					
						
							|  |  |  |                             value, 16, min, max, flags | DP_F_NUM)) | 
					
						
							|  |  |  |                     return 0; | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |                 break; | 
					
						
							| 
									
										
										
										
											2017-03-31 03:44:55 +08:00
										 |  |  |             case 'n': | 
					
						
							|  |  |  |                 { | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |                     int *num; | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |                     num = va_arg(args, int *); | 
					
						
							|  |  |  |                     *num = currlen; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case '%': | 
					
						
							| 
									
										
										
										
											2017-08-26 23:56:44 +08:00
										 |  |  |                 if (!doapr_outch(sbuffer, buffer, &currlen, maxlen, ch)) | 
					
						
							| 
									
										
										
										
											2016-02-25 21:09:46 +08:00
										 |  |  |                     return 0; | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |                 break; | 
					
						
							|  |  |  |             case 'w': | 
					
						
							|  |  |  |                 /* not supported yet, treat as next char */ | 
					
						
							|  |  |  |                 ch = *format++; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             default: | 
					
						
							|  |  |  |                 /* unknown, skip */ | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             ch = *format++; | 
					
						
							|  |  |  |             state = DP_S_DEFAULT; | 
					
						
							|  |  |  |             flags = cflags = min = 0; | 
					
						
							|  |  |  |             max = -1; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case DP_S_DONE: | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         default: | 
					
						
							|  |  |  |             break; | 
					
						
							| 
									
										
										
										
											2000-02-25 06:23:45 +08:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-06-03 22:53:54 +08:00
										 |  |  |     /*
 | 
					
						
							|  |  |  |      * We have to truncate if there is no dynamic buffer and we have filled the | 
					
						
							|  |  |  |      * static buffer. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     if (buffer == NULL) { | 
					
						
							|  |  |  |         *truncated = (currlen > *maxlen - 1); | 
					
						
							|  |  |  |         if (*truncated) | 
					
						
							|  |  |  |             currlen = *maxlen - 1; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-08-26 23:56:44 +08:00
										 |  |  |     if (!doapr_outch(sbuffer, buffer, &currlen, maxlen, '\0')) | 
					
						
							| 
									
										
										
										
											2016-02-25 21:09:46 +08:00
										 |  |  |         return 0; | 
					
						
							| 
									
										
										
										
											2000-09-07 13:50:14 +08:00
										 |  |  |     *retlen = currlen - 1; | 
					
						
							| 
									
										
										
										
											2016-02-25 21:09:46 +08:00
										 |  |  |     return 1; | 
					
						
							| 
									
										
										
										
											2000-02-25 06:23:45 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-25 21:09:46 +08:00
										 |  |  | static int | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | fmtstr(char **sbuffer, | 
					
						
							|  |  |  |        char **buffer, | 
					
						
							|  |  |  |        size_t *currlen, | 
					
						
							|  |  |  |        size_t *maxlen, const char *value, int flags, int min, int max) | 
					
						
							| 
									
										
										
										
											2000-02-25 06:23:45 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-02-25 21:09:46 +08:00
										 |  |  |     int padlen; | 
					
						
							|  |  |  |     size_t strln; | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |     int cnt = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (value == 0) | 
					
						
							|  |  |  |         value = "<NULL>"; | 
					
						
							| 
									
										
										
										
											2016-02-25 21:09:46 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-21 09:46:43 +08:00
										 |  |  |     strln = OPENSSL_strnlen(value, max < 0 ? SIZE_MAX : (size_t)max); | 
					
						
							| 
									
										
										
										
											2016-02-25 21:09:46 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |     padlen = min - strln; | 
					
						
							| 
									
										
										
										
											2016-02-25 21:09:46 +08:00
										 |  |  |     if (min < 0 || padlen < 0) | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |         padlen = 0; | 
					
						
							| 
									
										
										
										
											2016-05-30 11:41:57 +08:00
										 |  |  |     if (max >= 0) { | 
					
						
							|  |  |  |         /*
 | 
					
						
							|  |  |  |          * Calculate the maximum output including padding. | 
					
						
							|  |  |  |          * Make sure max doesn't overflow into negativity | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |         if (max < INT_MAX - padlen) | 
					
						
							|  |  |  |             max += padlen; | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             max = INT_MAX; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |     if (flags & DP_F_MINUS) | 
					
						
							|  |  |  |         padlen = -padlen; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-21 09:46:43 +08:00
										 |  |  |     while ((padlen > 0) && (max < 0 || cnt < max)) { | 
					
						
							| 
									
										
										
										
											2017-08-26 23:56:44 +08:00
										 |  |  |         if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) | 
					
						
							| 
									
										
										
										
											2016-02-25 21:09:46 +08:00
										 |  |  |             return 0; | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |         --padlen; | 
					
						
							|  |  |  |         ++cnt; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-05-21 09:46:43 +08:00
										 |  |  |     while (strln > 0 && (max < 0 || cnt < max)) { | 
					
						
							| 
									
										
										
										
											2017-08-26 23:56:44 +08:00
										 |  |  |         if (!doapr_outch(sbuffer, buffer, currlen, maxlen, *value++)) | 
					
						
							| 
									
										
										
										
											2016-02-25 21:09:46 +08:00
										 |  |  |             return 0; | 
					
						
							| 
									
										
										
										
											2016-05-21 09:46:43 +08:00
										 |  |  |         --strln; | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |         ++cnt; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-05-21 09:46:43 +08:00
										 |  |  |     while ((padlen < 0) && (max < 0 || cnt < max)) { | 
					
						
							| 
									
										
										
										
											2017-08-26 23:56:44 +08:00
										 |  |  |         if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) | 
					
						
							| 
									
										
										
										
											2016-02-25 21:09:46 +08:00
										 |  |  |             return 0; | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |         ++padlen; | 
					
						
							|  |  |  |         ++cnt; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-02-25 21:09:46 +08:00
										 |  |  |     return 1; | 
					
						
							| 
									
										
										
										
											2000-02-25 06:23:45 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-25 21:09:46 +08:00
										 |  |  | static int | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | fmtint(char **sbuffer, | 
					
						
							|  |  |  |        char **buffer, | 
					
						
							|  |  |  |        size_t *currlen, | 
					
						
							| 
									
										
										
										
											2017-03-31 03:44:55 +08:00
										 |  |  |        size_t *maxlen, int64_t value, int base, int min, int max, int flags) | 
					
						
							| 
									
										
										
										
											2000-02-25 06:23:45 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |     int signvalue = 0; | 
					
						
							| 
									
										
										
										
											2005-04-05 18:29:43 +08:00
										 |  |  |     const char *prefix = ""; | 
					
						
							| 
									
										
										
										
											2017-03-31 03:44:55 +08:00
										 |  |  |     uint64_t uvalue; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     char convert[DECIMAL_SIZE(value) + 3]; | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |     int place = 0; | 
					
						
							|  |  |  |     int spadlen = 0; | 
					
						
							|  |  |  |     int zpadlen = 0; | 
					
						
							|  |  |  |     int caps = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (max < 0) | 
					
						
							|  |  |  |         max = 0; | 
					
						
							|  |  |  |     uvalue = value; | 
					
						
							|  |  |  |     if (!(flags & DP_F_UNSIGNED)) { | 
					
						
							|  |  |  |         if (value < 0) { | 
					
						
							|  |  |  |             signvalue = '-'; | 
					
						
							| 
									
										
										
										
											2017-03-31 03:44:55 +08:00
										 |  |  |             uvalue = 0 - (uint64_t)value; | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |         } else if (flags & DP_F_PLUS) | 
					
						
							|  |  |  |             signvalue = '+'; | 
					
						
							|  |  |  |         else if (flags & DP_F_SPACE) | 
					
						
							|  |  |  |             signvalue = ' '; | 
					
						
							| 
									
										
										
										
											2000-02-25 06:23:45 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2003-04-04 07:35:14 +08:00
										 |  |  |     if (flags & DP_F_NUM) { | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         if (base == 8) | 
					
						
							|  |  |  |             prefix = "0"; | 
					
						
							|  |  |  |         if (base == 16) | 
					
						
							|  |  |  |             prefix = "0x"; | 
					
						
							| 
									
										
										
										
											2003-04-04 07:35:14 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |     if (flags & DP_F_UP) | 
					
						
							|  |  |  |         caps = 1; | 
					
						
							|  |  |  |     do { | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         convert[place++] = (caps ? "0123456789ABCDEF" : "0123456789abcdef") | 
					
						
							|  |  |  |             [uvalue % (unsigned)base]; | 
					
						
							|  |  |  |         uvalue = (uvalue / (unsigned)base); | 
					
						
							| 
									
										
										
										
											2003-10-29 13:00:57 +08:00
										 |  |  |     } while (uvalue && (place < (int)sizeof(convert))); | 
					
						
							|  |  |  |     if (place == sizeof(convert)) | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |         place--; | 
					
						
							|  |  |  |     convert[place] = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     zpadlen = max - place; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     spadlen = | 
					
						
							|  |  |  |         min - OSSL_MAX(max, place) - (signvalue ? 1 : 0) - strlen(prefix); | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |     if (zpadlen < 0) | 
					
						
							|  |  |  |         zpadlen = 0; | 
					
						
							|  |  |  |     if (spadlen < 0) | 
					
						
							|  |  |  |         spadlen = 0; | 
					
						
							|  |  |  |     if (flags & DP_F_ZERO) { | 
					
						
							| 
									
										
										
										
											2000-10-22 20:44:12 +08:00
										 |  |  |         zpadlen = OSSL_MAX(zpadlen, spadlen); | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |         spadlen = 0; | 
					
						
							| 
									
										
										
										
											2000-02-25 06:23:45 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |     if (flags & DP_F_MINUS) | 
					
						
							|  |  |  |         spadlen = -spadlen; | 
					
						
							| 
									
										
										
										
											2000-02-25 06:23:45 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |     /* spaces */ | 
					
						
							|  |  |  |     while (spadlen > 0) { | 
					
						
							| 
									
										
										
										
											2017-08-26 23:56:44 +08:00
										 |  |  |         if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) | 
					
						
							| 
									
										
										
										
											2016-02-25 21:09:46 +08:00
										 |  |  |             return 0; | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |         --spadlen; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2000-02-25 06:23:45 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |     /* sign */ | 
					
						
							|  |  |  |     if (signvalue) | 
					
						
							| 
									
										
										
										
											2017-08-26 23:56:44 +08:00
										 |  |  |         if (!doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue)) | 
					
						
							| 
									
										
										
										
											2016-02-25 21:09:46 +08:00
										 |  |  |             return 0; | 
					
						
							| 
									
										
										
										
											2000-02-25 06:23:45 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-04-04 07:35:14 +08:00
										 |  |  |     /* prefix */ | 
					
						
							|  |  |  |     while (*prefix) { | 
					
						
							| 
									
										
										
										
											2017-08-26 23:56:44 +08:00
										 |  |  |         if (!doapr_outch(sbuffer, buffer, currlen, maxlen, *prefix)) | 
					
						
							| 
									
										
										
										
											2016-02-25 21:09:46 +08:00
										 |  |  |             return 0; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         prefix++; | 
					
						
							| 
									
										
										
										
											2003-04-04 07:35:14 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |     /* zeros */ | 
					
						
							|  |  |  |     if (zpadlen > 0) { | 
					
						
							|  |  |  |         while (zpadlen > 0) { | 
					
						
							| 
									
										
										
										
											2017-08-26 23:56:44 +08:00
										 |  |  |             if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0')) | 
					
						
							| 
									
										
										
										
											2016-02-25 21:09:46 +08:00
										 |  |  |                 return 0; | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |             --zpadlen; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /* digits */ | 
					
						
							| 
									
										
										
										
											2016-02-25 21:09:46 +08:00
										 |  |  |     while (place > 0) { | 
					
						
							|  |  |  |         if (!doapr_outch(sbuffer, buffer, currlen, maxlen, convert[--place])) | 
					
						
							|  |  |  |             return 0; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /* left justified spaces */ | 
					
						
							|  |  |  |     while (spadlen < 0) { | 
					
						
							| 
									
										
										
										
											2016-02-25 21:09:46 +08:00
										 |  |  |         if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) | 
					
						
							|  |  |  |             return 0; | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |         ++spadlen; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-02-25 21:09:46 +08:00
										 |  |  |     return 1; | 
					
						
							| 
									
										
										
										
											2000-02-25 06:23:45 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | static LDOUBLE abs_val(LDOUBLE value) | 
					
						
							| 
									
										
										
										
											2000-02-25 06:23:45 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |     LDOUBLE result = value; | 
					
						
							|  |  |  |     if (value < 0) | 
					
						
							|  |  |  |         result = -value; | 
					
						
							|  |  |  |     return result; | 
					
						
							| 
									
										
										
										
											2000-02-25 06:23:45 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | static LDOUBLE pow_10(int in_exp) | 
					
						
							| 
									
										
										
										
											2000-02-25 06:23:45 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |     LDOUBLE result = 1; | 
					
						
							| 
									
										
										
										
											2003-11-04 08:51:32 +08:00
										 |  |  |     while (in_exp) { | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |         result *= 10; | 
					
						
							| 
									
										
										
										
											2003-11-04 08:51:32 +08:00
										 |  |  |         in_exp--; | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |     } | 
					
						
							|  |  |  |     return result; | 
					
						
							| 
									
										
										
										
											2000-02-25 06:23:45 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | static long roundv(LDOUBLE value) | 
					
						
							| 
									
										
										
										
											2000-02-25 06:23:45 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |     long intpart; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     intpart = (long)value; | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |     value = value - intpart; | 
					
						
							|  |  |  |     if (value >= 0.5) | 
					
						
							|  |  |  |         intpart++; | 
					
						
							|  |  |  |     return intpart; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2000-02-25 06:23:45 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-25 21:09:46 +08:00
										 |  |  | static int | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | fmtfp(char **sbuffer, | 
					
						
							|  |  |  |       char **buffer, | 
					
						
							|  |  |  |       size_t *currlen, | 
					
						
							| 
									
										
										
										
											2016-05-25 22:33:15 +08:00
										 |  |  |       size_t *maxlen, LDOUBLE fvalue, int min, int max, int flags, int style) | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     int signvalue = 0; | 
					
						
							|  |  |  |     LDOUBLE ufvalue; | 
					
						
							| 
									
										
										
										
											2016-05-25 22:33:15 +08:00
										 |  |  |     LDOUBLE tmpvalue; | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |     char iconvert[20]; | 
					
						
							|  |  |  |     char fconvert[20]; | 
					
						
							| 
									
										
										
										
											2016-05-25 22:33:15 +08:00
										 |  |  |     char econvert[20]; | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |     int iplace = 0; | 
					
						
							|  |  |  |     int fplace = 0; | 
					
						
							| 
									
										
										
										
											2016-05-25 22:33:15 +08:00
										 |  |  |     int eplace = 0; | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |     int padlen = 0; | 
					
						
							|  |  |  |     int zpadlen = 0; | 
					
						
							| 
									
										
										
										
											2016-05-25 22:33:15 +08:00
										 |  |  |     long exp = 0; | 
					
						
							| 
									
										
										
										
											2016-05-25 23:20:48 +08:00
										 |  |  |     unsigned long intpart; | 
					
						
							|  |  |  |     unsigned long fracpart; | 
					
						
							|  |  |  |     unsigned long max10; | 
					
						
							| 
									
										
										
										
											2016-05-25 22:33:15 +08:00
										 |  |  |     int realstyle; | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (max < 0) | 
					
						
							|  |  |  |         max = 6; | 
					
						
							| 
									
										
										
										
											2016-05-25 22:33:15 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |     if (fvalue < 0) | 
					
						
							|  |  |  |         signvalue = '-'; | 
					
						
							|  |  |  |     else if (flags & DP_F_PLUS) | 
					
						
							|  |  |  |         signvalue = '+'; | 
					
						
							|  |  |  |     else if (flags & DP_F_SPACE) | 
					
						
							|  |  |  |         signvalue = ' '; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-25 22:33:15 +08:00
										 |  |  |     /*
 | 
					
						
							|  |  |  |      * G_FORMAT sometimes prints like E_FORMAT and sometimes like F_FORMAT | 
					
						
							|  |  |  |      * depending on the number to be printed. Work out which one it is and use | 
					
						
							|  |  |  |      * that from here on. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     if (style == G_FORMAT) { | 
					
						
							|  |  |  |         if (fvalue == 0.0) { | 
					
						
							|  |  |  |             realstyle = F_FORMAT; | 
					
						
							|  |  |  |         } else if (fvalue < 0.0001) { | 
					
						
							|  |  |  |             realstyle = E_FORMAT; | 
					
						
							|  |  |  |         } else if ((max == 0 && fvalue >= 10) | 
					
						
							|  |  |  |                     || (max > 0 && fvalue >= pow_10(max))) { | 
					
						
							|  |  |  |             realstyle = E_FORMAT; | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             realstyle = F_FORMAT; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         realstyle = style; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (style != F_FORMAT) { | 
					
						
							|  |  |  |         tmpvalue = fvalue; | 
					
						
							|  |  |  |         /* Calculate the exponent */ | 
					
						
							|  |  |  |         if (fvalue != 0.0) { | 
					
						
							|  |  |  |             while (tmpvalue < 1) { | 
					
						
							|  |  |  |                 tmpvalue *= 10; | 
					
						
							|  |  |  |                 exp--; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             while (tmpvalue > 10) { | 
					
						
							|  |  |  |                 tmpvalue /= 10; | 
					
						
							|  |  |  |                 exp++; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (style == G_FORMAT) { | 
					
						
							|  |  |  |             /*
 | 
					
						
							|  |  |  |              * In G_FORMAT the "precision" represents significant digits. We | 
					
						
							|  |  |  |              * always have at least 1 significant digit. | 
					
						
							|  |  |  |              */ | 
					
						
							|  |  |  |             if (max == 0) | 
					
						
							|  |  |  |                 max = 1; | 
					
						
							|  |  |  |             /* Now convert significant digits to decimal places */ | 
					
						
							|  |  |  |             if (realstyle == F_FORMAT) { | 
					
						
							|  |  |  |                 max -= (exp + 1); | 
					
						
							|  |  |  |                 if (max < 0) { | 
					
						
							|  |  |  |                     /*
 | 
					
						
							|  |  |  |                      * Should not happen. If we're in F_FORMAT then exp < max? | 
					
						
							|  |  |  |                      */ | 
					
						
							|  |  |  |                     return 0; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 /*
 | 
					
						
							|  |  |  |                  * In E_FORMAT there is always one significant digit in front | 
					
						
							|  |  |  |                  * of the decimal point, so: | 
					
						
							|  |  |  |                  * significant digits == 1 + decimal places | 
					
						
							|  |  |  |                  */ | 
					
						
							|  |  |  |                 max--; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (realstyle == E_FORMAT) | 
					
						
							|  |  |  |             fvalue = tmpvalue; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     ufvalue = abs_val(fvalue); | 
					
						
							| 
									
										
										
										
											2016-05-25 23:20:48 +08:00
										 |  |  |     if (ufvalue > ULONG_MAX) { | 
					
						
							|  |  |  |         /* Number too big */ | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     intpart = (unsigned long)ufvalue; | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     /*
 | 
					
						
							|  |  |  |      * sorry, we only support 9 digits past the decimal because of our | 
					
						
							|  |  |  |      * conversion method | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |     if (max > 9) | 
					
						
							|  |  |  |         max = 9; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     /*
 | 
					
						
							|  |  |  |      * we "cheat" by converting the fractional part to integer by multiplying | 
					
						
							|  |  |  |      * by a factor of 10 | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2005-05-06 04:57:37 +08:00
										 |  |  |     max10 = roundv(pow_10(max)); | 
					
						
							|  |  |  |     fracpart = roundv(pow_10(max) * (ufvalue - intpart)); | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-03-25 10:19:42 +08:00
										 |  |  |     if (fracpart >= max10) { | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |         intpart++; | 
					
						
							| 
									
										
										
										
											2004-03-25 10:19:42 +08:00
										 |  |  |         fracpart -= max10; | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2000-02-25 06:23:45 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |     /* convert integer part */ | 
					
						
							|  |  |  |     do { | 
					
						
							| 
									
										
										
										
											2015-03-12 22:08:21 +08:00
										 |  |  |         iconvert[iplace++] = "0123456789"[intpart % 10]; | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |         intpart = (intpart / 10); | 
					
						
							| 
									
										
										
										
											2003-12-12 02:01:03 +08:00
										 |  |  |     } while (intpart && (iplace < (int)sizeof(iconvert))); | 
					
						
							|  |  |  |     if (iplace == sizeof iconvert) | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |         iplace--; | 
					
						
							|  |  |  |     iconvert[iplace] = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* convert fractional part */ | 
					
						
							| 
									
										
										
										
											2016-05-25 22:33:15 +08:00
										 |  |  |     while (fplace < max) { | 
					
						
							|  |  |  |         if (style == G_FORMAT && fplace == 0 && (fracpart % 10) == 0) { | 
					
						
							|  |  |  |             /* We strip trailing zeros in G_FORMAT */ | 
					
						
							|  |  |  |             max--; | 
					
						
							|  |  |  |             fracpart = fracpart / 10; | 
					
						
							|  |  |  |             if (fplace < max) | 
					
						
							|  |  |  |                 continue; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2015-03-12 22:08:21 +08:00
										 |  |  |         fconvert[fplace++] = "0123456789"[fracpart % 10]; | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |         fracpart = (fracpart / 10); | 
					
						
							| 
									
										
										
										
											2016-05-25 22:33:15 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-12-12 02:01:03 +08:00
										 |  |  |     if (fplace == sizeof fconvert) | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |         fplace--; | 
					
						
							|  |  |  |     fconvert[fplace] = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-25 22:33:15 +08:00
										 |  |  |     /* convert exponent part */ | 
					
						
							|  |  |  |     if (realstyle == E_FORMAT) { | 
					
						
							|  |  |  |         int tmpexp; | 
					
						
							|  |  |  |         if (exp < 0) | 
					
						
							|  |  |  |             tmpexp = -exp; | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             tmpexp = exp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         do { | 
					
						
							|  |  |  |             econvert[eplace++] = "0123456789"[tmpexp % 10]; | 
					
						
							|  |  |  |             tmpexp = (tmpexp / 10); | 
					
						
							|  |  |  |         } while (tmpexp > 0 && eplace < (int)sizeof(econvert)); | 
					
						
							|  |  |  |         /* Exponent is huge!! Too big to print */ | 
					
						
							|  |  |  |         if (tmpexp > 0) | 
					
						
							|  |  |  |             return 0; | 
					
						
							|  |  |  |         /* Add a leading 0 for single digit exponents */ | 
					
						
							|  |  |  |         if (eplace == 1) | 
					
						
							|  |  |  |             econvert[eplace++] = '0'; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /*
 | 
					
						
							|  |  |  |      * -1 for decimal point (if we have one, i.e. max > 0), | 
					
						
							|  |  |  |      * another -1 if we are printing a sign | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     padlen = min - iplace - max - (max > 0 ? 1 : 0) - ((signvalue) ? 1 : 0); | 
					
						
							|  |  |  |     /* Take some off for exponent prefix "+e" and exponent */ | 
					
						
							|  |  |  |     if (realstyle == E_FORMAT) | 
					
						
							|  |  |  |         padlen -= 2 + eplace; | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |     zpadlen = max - fplace; | 
					
						
							|  |  |  |     if (zpadlen < 0) | 
					
						
							|  |  |  |         zpadlen = 0; | 
					
						
							|  |  |  |     if (padlen < 0) | 
					
						
							|  |  |  |         padlen = 0; | 
					
						
							|  |  |  |     if (flags & DP_F_MINUS) | 
					
						
							|  |  |  |         padlen = -padlen; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ((flags & DP_F_ZERO) && (padlen > 0)) { | 
					
						
							|  |  |  |         if (signvalue) { | 
					
						
							| 
									
										
										
										
											2016-02-25 21:09:46 +08:00
										 |  |  |             if (!doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue)) | 
					
						
							|  |  |  |                 return 0; | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |             --padlen; | 
					
						
							|  |  |  |             signvalue = 0; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         while (padlen > 0) { | 
					
						
							| 
									
										
										
										
											2016-02-25 21:09:46 +08:00
										 |  |  |             if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0')) | 
					
						
							|  |  |  |                 return 0; | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |             --padlen; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     while (padlen > 0) { | 
					
						
							| 
									
										
										
										
											2016-02-25 21:09:46 +08:00
										 |  |  |         if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) | 
					
						
							|  |  |  |             return 0; | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |         --padlen; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-02-25 21:09:46 +08:00
										 |  |  |     if (signvalue && !doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue)) | 
					
						
							|  |  |  |         return 0; | 
					
						
							| 
									
										
										
										
											2000-02-25 06:23:45 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-25 21:09:46 +08:00
										 |  |  |     while (iplace > 0) { | 
					
						
							|  |  |  |         if (!doapr_outch(sbuffer, buffer, currlen, maxlen, iconvert[--iplace])) | 
					
						
							|  |  |  |             return 0; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2000-02-25 06:23:45 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |     /*
 | 
					
						
							|  |  |  |      * Decimal point. This should probably use locale to find the correct | 
					
						
							|  |  |  |      * char to print out. | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2003-04-04 07:35:14 +08:00
										 |  |  |     if (max > 0 || (flags & DP_F_NUM)) { | 
					
						
							| 
									
										
										
										
											2016-02-25 21:09:46 +08:00
										 |  |  |         if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '.')) | 
					
						
							|  |  |  |             return 0; | 
					
						
							| 
									
										
										
										
											2000-02-25 06:23:45 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-25 21:09:46 +08:00
										 |  |  |         while (fplace > 0) { | 
					
						
							| 
									
										
										
										
											2017-08-26 23:56:44 +08:00
										 |  |  |             if (!doapr_outch(sbuffer, buffer, currlen, maxlen, | 
					
						
							|  |  |  |                              fconvert[--fplace])) | 
					
						
							| 
									
										
										
										
											2016-02-25 21:09:46 +08:00
										 |  |  |                 return 0; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |     } | 
					
						
							|  |  |  |     while (zpadlen > 0) { | 
					
						
							| 
									
										
										
										
											2016-02-25 21:09:46 +08:00
										 |  |  |         if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0')) | 
					
						
							|  |  |  |             return 0; | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |         --zpadlen; | 
					
						
							| 
									
										
										
										
											2000-02-25 06:23:45 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-05-25 22:33:15 +08:00
										 |  |  |     if (realstyle == E_FORMAT) { | 
					
						
							|  |  |  |         char ech; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if ((flags & DP_F_UP) == 0) | 
					
						
							|  |  |  |             ech = 'e'; | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             ech = 'E'; | 
					
						
							|  |  |  |         if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ech)) | 
					
						
							|  |  |  |                 return 0; | 
					
						
							|  |  |  |         if (exp < 0) { | 
					
						
							|  |  |  |             if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '-')) | 
					
						
							|  |  |  |                     return 0; | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '+')) | 
					
						
							|  |  |  |                     return 0; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         while (eplace > 0) { | 
					
						
							|  |  |  |             if (!doapr_outch(sbuffer, buffer, currlen, maxlen, | 
					
						
							|  |  |  |                              econvert[--eplace])) | 
					
						
							|  |  |  |                 return 0; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     while (padlen < 0) { | 
					
						
							| 
									
										
										
										
											2016-02-25 21:09:46 +08:00
										 |  |  |         if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) | 
					
						
							|  |  |  |             return 0; | 
					
						
							| 
									
										
										
										
											2000-02-25 22:00:24 +08:00
										 |  |  |         ++padlen; | 
					
						
							| 
									
										
										
										
											2000-02-25 06:23:45 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-02-25 21:09:46 +08:00
										 |  |  |     return 1; | 
					
						
							| 
									
										
										
										
											2000-02-25 06:23:45 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-25 21:09:46 +08:00
										 |  |  | #define BUFFER_INC  1024
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | doapr_outch(char **sbuffer, | 
					
						
							|  |  |  |             char **buffer, size_t *currlen, size_t *maxlen, int c) | 
					
						
							| 
									
										
										
										
											2000-02-25 06:23:45 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2017-08-02 22:29:31 +08:00
										 |  |  |     /* If we haven't at least one buffer, someone has done a big booboo */ | 
					
						
							| 
									
										
										
										
											2017-06-21 22:52:11 +08:00
										 |  |  |     if (!ossl_assert(*sbuffer != NULL || buffer != NULL)) | 
					
						
							|  |  |  |         return 0; | 
					
						
							| 
									
										
										
										
											2000-09-07 13:50:14 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-27 22:41:03 +08:00
										 |  |  |     /* |currlen| must always be <= |*maxlen| */ | 
					
						
							| 
									
										
										
										
											2017-06-21 22:52:11 +08:00
										 |  |  |     if (!ossl_assert(*currlen <= *maxlen)) | 
					
						
							|  |  |  |         return 0; | 
					
						
							| 
									
										
										
										
											2015-04-27 22:41:03 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (buffer && *currlen == *maxlen) { | 
					
						
							| 
									
										
										
										
											2016-02-25 21:09:46 +08:00
										 |  |  |         if (*maxlen > INT_MAX - BUFFER_INC) | 
					
						
							|  |  |  |             return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         *maxlen += BUFFER_INC; | 
					
						
							| 
									
										
										
										
											2015-04-27 22:41:03 +08:00
										 |  |  |         if (*buffer == NULL) { | 
					
						
							|  |  |  |             *buffer = OPENSSL_malloc(*maxlen); | 
					
						
							| 
									
										
										
										
											2016-02-25 21:09:46 +08:00
										 |  |  |             if (*buffer == NULL) | 
					
						
							|  |  |  |                 return 0; | 
					
						
							| 
									
										
										
										
											2015-04-27 22:41:03 +08:00
										 |  |  |             if (*currlen > 0) { | 
					
						
							| 
									
										
										
										
											2017-06-21 22:52:11 +08:00
										 |  |  |                 if (!ossl_assert(*sbuffer != NULL)) | 
					
						
							|  |  |  |                     return 0; | 
					
						
							| 
									
										
										
										
											2015-04-27 22:41:03 +08:00
										 |  |  |                 memcpy(*buffer, *sbuffer, *currlen); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             *sbuffer = NULL; | 
					
						
							|  |  |  |         } else { | 
					
						
							| 
									
										
										
										
											2016-02-25 21:09:46 +08:00
										 |  |  |             char *tmpbuf; | 
					
						
							|  |  |  |             tmpbuf = OPENSSL_realloc(*buffer, *maxlen); | 
					
						
							|  |  |  |             if (tmpbuf == NULL) | 
					
						
							|  |  |  |                 return 0; | 
					
						
							|  |  |  |             *buffer = tmpbuf; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2000-03-02 15:50:02 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2000-09-07 13:50:14 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (*currlen < *maxlen) { | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         if (*sbuffer) | 
					
						
							|  |  |  |             (*sbuffer)[(*currlen)++] = (char)c; | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             (*buffer)[(*currlen)++] = (char)c; | 
					
						
							| 
									
										
										
										
											2000-03-02 15:50:02 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-25 21:09:46 +08:00
										 |  |  |     return 1; | 
					
						
							| 
									
										
										
										
											2000-02-25 06:23:45 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2000-04-15 07:36:15 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | /***************************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | int BIO_printf(BIO *bio, const char *format, ...) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     va_list args; | 
					
						
							|  |  |  |     int ret; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     va_start(args, format); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ret = BIO_vprintf(bio, format, args); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     va_end(args); | 
					
						
							| 
									
										
										
										
											2017-10-17 22:04:09 +08:00
										 |  |  |     return ret; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int BIO_vprintf(BIO *bio, const char *format, va_list args) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int ret; | 
					
						
							|  |  |  |     size_t retlen; | 
					
						
							|  |  |  |     char hugebuf[1024 * 2];     /* Was previously 10k, which is unreasonable
 | 
					
						
							|  |  |  |                                  * in small-stack environments, like threads | 
					
						
							|  |  |  |                                  * or DOS programs. */ | 
					
						
							|  |  |  |     char *hugebufp = hugebuf; | 
					
						
							|  |  |  |     size_t hugebufsize = sizeof(hugebuf); | 
					
						
							|  |  |  |     char *dynbuf = NULL; | 
					
						
							|  |  |  |     int ignored; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     dynbuf = NULL; | 
					
						
							| 
									
										
										
										
											2016-02-25 21:09:46 +08:00
										 |  |  |     if (!_dopr(&hugebufp, &dynbuf, &hugebufsize, &retlen, &ignored, format, | 
					
						
							|  |  |  |                 args)) { | 
					
						
							|  |  |  |         OPENSSL_free(dynbuf); | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     if (dynbuf) { | 
					
						
							|  |  |  |         ret = BIO_write(bio, dynbuf, (int)retlen); | 
					
						
							|  |  |  |         OPENSSL_free(dynbuf); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         ret = BIO_write(bio, hugebuf, (int)retlen); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-10-17 22:04:09 +08:00
										 |  |  |     return ret; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * As snprintf is not available everywhere, we provide our own | 
					
						
							|  |  |  |  * implementation. This function has nothing to do with BIOs, but it's | 
					
						
							|  |  |  |  * closely related to BIO_printf, and we need *some* name prefix ... (XXX the | 
					
						
							|  |  |  |  * function should be renamed, but to what?) | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2000-04-15 07:36:15 +08:00
										 |  |  | int BIO_snprintf(char *buf, size_t n, const char *format, ...) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     va_list args; | 
					
						
							|  |  |  |     int ret; | 
					
						
							| 
									
										
										
										
											2000-08-18 17:36:59 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     va_start(args, format); | 
					
						
							| 
									
										
										
										
											2000-08-18 17:36:59 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     ret = BIO_vsnprintf(buf, n, format, args); | 
					
						
							| 
									
										
										
										
											2000-08-18 17:36:59 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     va_end(args); | 
					
						
							| 
									
										
										
										
											2017-10-17 22:04:09 +08:00
										 |  |  |     return ret; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2000-08-18 17:36:59 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | int BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     size_t retlen; | 
					
						
							|  |  |  |     int truncated; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-26 23:56:44 +08:00
										 |  |  |     if (!_dopr(&buf, NULL, &n, &retlen, &truncated, format, args)) | 
					
						
							| 
									
										
										
										
											2016-02-25 21:09:46 +08:00
										 |  |  |         return -1; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (truncated) | 
					
						
							|  |  |  |         /*
 | 
					
						
							|  |  |  |          * In case of truncation, return -1 like traditional snprintf. | 
					
						
							|  |  |  |          * (Current drafts for ISO/IEC 9899 say snprintf should return the | 
					
						
							|  |  |  |          * number of characters that would have been written, had the buffer | 
					
						
							|  |  |  |          * been large enough.) | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |         return (retlen <= INT_MAX) ? (int)retlen : -1; | 
					
						
							|  |  |  | } |