xref: /third_party/openssl/crypto/bio/bio_print.c (revision e1051a39)
1e1051a39Sopenharmony_ci/*
2e1051a39Sopenharmony_ci * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
3e1051a39Sopenharmony_ci *
4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License").  You may not use
5e1051a39Sopenharmony_ci * this file except in compliance with the License.  You can obtain a copy
6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at
7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html
8e1051a39Sopenharmony_ci */
9e1051a39Sopenharmony_ci
10e1051a39Sopenharmony_ci#include <stdio.h>
11e1051a39Sopenharmony_ci#include <string.h>
12e1051a39Sopenharmony_ci#include "internal/cryptlib.h"
13e1051a39Sopenharmony_ci#include "crypto/ctype.h"
14e1051a39Sopenharmony_ci#include "internal/numbers.h"
15e1051a39Sopenharmony_ci#include <openssl/bio.h>
16e1051a39Sopenharmony_ci#include <openssl/configuration.h>
17e1051a39Sopenharmony_ci
18e1051a39Sopenharmony_ci/*
19e1051a39Sopenharmony_ci * Copyright Patrick Powell 1995
20e1051a39Sopenharmony_ci * This code is based on code written by Patrick Powell <papowell@astart.com>
21e1051a39Sopenharmony_ci * It may be used for any purpose as long as this notice remains intact
22e1051a39Sopenharmony_ci * on all source code distributions.
23e1051a39Sopenharmony_ci */
24e1051a39Sopenharmony_ci
25e1051a39Sopenharmony_ci#ifdef HAVE_LONG_DOUBLE
26e1051a39Sopenharmony_ci# define LDOUBLE long double
27e1051a39Sopenharmony_ci#else
28e1051a39Sopenharmony_ci# define LDOUBLE double
29e1051a39Sopenharmony_ci#endif
30e1051a39Sopenharmony_ci
31e1051a39Sopenharmony_cistatic int fmtstr(char **, char **, size_t *, size_t *,
32e1051a39Sopenharmony_ci                  const char *, int, int, int);
33e1051a39Sopenharmony_cistatic int fmtint(char **, char **, size_t *, size_t *,
34e1051a39Sopenharmony_ci                  int64_t, int, int, int, int);
35e1051a39Sopenharmony_ci#ifndef OPENSSL_SYS_UEFI
36e1051a39Sopenharmony_cistatic int fmtfp(char **, char **, size_t *, size_t *,
37e1051a39Sopenharmony_ci                 LDOUBLE, int, int, int, int);
38e1051a39Sopenharmony_ci#endif
39e1051a39Sopenharmony_cistatic int doapr_outch(char **, char **, size_t *, size_t *, int);
40e1051a39Sopenharmony_cistatic int _dopr(char **sbuffer, char **buffer,
41e1051a39Sopenharmony_ci                 size_t *maxlen, size_t *retlen, int *truncated,
42e1051a39Sopenharmony_ci                 const char *format, va_list args);
43e1051a39Sopenharmony_ci
44e1051a39Sopenharmony_ci/* format read states */
45e1051a39Sopenharmony_ci#define DP_S_DEFAULT    0
46e1051a39Sopenharmony_ci#define DP_S_FLAGS      1
47e1051a39Sopenharmony_ci#define DP_S_MIN        2
48e1051a39Sopenharmony_ci#define DP_S_DOT        3
49e1051a39Sopenharmony_ci#define DP_S_MAX        4
50e1051a39Sopenharmony_ci#define DP_S_MOD        5
51e1051a39Sopenharmony_ci#define DP_S_CONV       6
52e1051a39Sopenharmony_ci#define DP_S_DONE       7
53e1051a39Sopenharmony_ci
54e1051a39Sopenharmony_ci/* format flags - Bits */
55e1051a39Sopenharmony_ci/* left-aligned padding */
56e1051a39Sopenharmony_ci#define DP_F_MINUS      (1 << 0)
57e1051a39Sopenharmony_ci/* print an explicit '+' for a value with positive sign */
58e1051a39Sopenharmony_ci#define DP_F_PLUS       (1 << 1)
59e1051a39Sopenharmony_ci/* print an explicit ' ' for a value with positive sign */
60e1051a39Sopenharmony_ci#define DP_F_SPACE      (1 << 2)
61e1051a39Sopenharmony_ci/* print 0/0x prefix for octal/hex and decimal point for floating point */
62e1051a39Sopenharmony_ci#define DP_F_NUM        (1 << 3)
63e1051a39Sopenharmony_ci/* print leading zeroes */
64e1051a39Sopenharmony_ci#define DP_F_ZERO       (1 << 4)
65e1051a39Sopenharmony_ci/* print HEX in UPPPERcase */
66e1051a39Sopenharmony_ci#define DP_F_UP         (1 << 5)
67e1051a39Sopenharmony_ci/* treat value as unsigned */
68e1051a39Sopenharmony_ci#define DP_F_UNSIGNED   (1 << 6)
69e1051a39Sopenharmony_ci
70e1051a39Sopenharmony_ci/* conversion flags */
71e1051a39Sopenharmony_ci#define DP_C_SHORT      1
72e1051a39Sopenharmony_ci#define DP_C_LONG       2
73e1051a39Sopenharmony_ci#define DP_C_LDOUBLE    3
74e1051a39Sopenharmony_ci#define DP_C_LLONG      4
75e1051a39Sopenharmony_ci#define DP_C_SIZE       5
76e1051a39Sopenharmony_ci
77e1051a39Sopenharmony_ci/* Floating point formats */
78e1051a39Sopenharmony_ci#define F_FORMAT        0
79e1051a39Sopenharmony_ci#define E_FORMAT        1
80e1051a39Sopenharmony_ci#define G_FORMAT        2
81e1051a39Sopenharmony_ci
82e1051a39Sopenharmony_ci/* some handy macros */
83e1051a39Sopenharmony_ci#define char_to_int(p) (p - '0')
84e1051a39Sopenharmony_ci#define OSSL_MAX(p,q) ((p >= q) ? p : q)
85e1051a39Sopenharmony_ci
86e1051a39Sopenharmony_cistatic int
87e1051a39Sopenharmony_ci_dopr(char **sbuffer,
88e1051a39Sopenharmony_ci      char **buffer,
89e1051a39Sopenharmony_ci      size_t *maxlen,
90e1051a39Sopenharmony_ci      size_t *retlen, int *truncated, const char *format, va_list args)
91e1051a39Sopenharmony_ci{
92e1051a39Sopenharmony_ci    char ch;
93e1051a39Sopenharmony_ci    int64_t value;
94e1051a39Sopenharmony_ci#ifndef OPENSSL_SYS_UEFI
95e1051a39Sopenharmony_ci    LDOUBLE fvalue;
96e1051a39Sopenharmony_ci#endif
97e1051a39Sopenharmony_ci    char *strvalue;
98e1051a39Sopenharmony_ci    int min;
99e1051a39Sopenharmony_ci    int max;
100e1051a39Sopenharmony_ci    int state;
101e1051a39Sopenharmony_ci    int flags;
102e1051a39Sopenharmony_ci    int cflags;
103e1051a39Sopenharmony_ci    size_t currlen;
104e1051a39Sopenharmony_ci
105e1051a39Sopenharmony_ci    state = DP_S_DEFAULT;
106e1051a39Sopenharmony_ci    flags = currlen = cflags = min = 0;
107e1051a39Sopenharmony_ci    max = -1;
108e1051a39Sopenharmony_ci    ch = *format++;
109e1051a39Sopenharmony_ci
110e1051a39Sopenharmony_ci    while (state != DP_S_DONE) {
111e1051a39Sopenharmony_ci        if (ch == '\0' || (buffer == NULL && currlen >= *maxlen))
112e1051a39Sopenharmony_ci            state = DP_S_DONE;
113e1051a39Sopenharmony_ci
114e1051a39Sopenharmony_ci        switch (state) {
115e1051a39Sopenharmony_ci        case DP_S_DEFAULT:
116e1051a39Sopenharmony_ci            if (ch == '%')
117e1051a39Sopenharmony_ci                state = DP_S_FLAGS;
118e1051a39Sopenharmony_ci            else
119e1051a39Sopenharmony_ci                if (!doapr_outch(sbuffer, buffer, &currlen, maxlen, ch))
120e1051a39Sopenharmony_ci                    return 0;
121e1051a39Sopenharmony_ci            ch = *format++;
122e1051a39Sopenharmony_ci            break;
123e1051a39Sopenharmony_ci        case DP_S_FLAGS:
124e1051a39Sopenharmony_ci            switch (ch) {
125e1051a39Sopenharmony_ci            case '-':
126e1051a39Sopenharmony_ci                flags |= DP_F_MINUS;
127e1051a39Sopenharmony_ci                ch = *format++;
128e1051a39Sopenharmony_ci                break;
129e1051a39Sopenharmony_ci            case '+':
130e1051a39Sopenharmony_ci                flags |= DP_F_PLUS;
131e1051a39Sopenharmony_ci                ch = *format++;
132e1051a39Sopenharmony_ci                break;
133e1051a39Sopenharmony_ci            case ' ':
134e1051a39Sopenharmony_ci                flags |= DP_F_SPACE;
135e1051a39Sopenharmony_ci                ch = *format++;
136e1051a39Sopenharmony_ci                break;
137e1051a39Sopenharmony_ci            case '#':
138e1051a39Sopenharmony_ci                flags |= DP_F_NUM;
139e1051a39Sopenharmony_ci                ch = *format++;
140e1051a39Sopenharmony_ci                break;
141e1051a39Sopenharmony_ci            case '0':
142e1051a39Sopenharmony_ci                flags |= DP_F_ZERO;
143e1051a39Sopenharmony_ci                ch = *format++;
144e1051a39Sopenharmony_ci                break;
145e1051a39Sopenharmony_ci            default:
146e1051a39Sopenharmony_ci                state = DP_S_MIN;
147e1051a39Sopenharmony_ci                break;
148e1051a39Sopenharmony_ci            }
149e1051a39Sopenharmony_ci            break;
150e1051a39Sopenharmony_ci        case DP_S_MIN:
151e1051a39Sopenharmony_ci            if (ossl_isdigit(ch)) {
152e1051a39Sopenharmony_ci                min = 10 * min + char_to_int(ch);
153e1051a39Sopenharmony_ci                ch = *format++;
154e1051a39Sopenharmony_ci            } else if (ch == '*') {
155e1051a39Sopenharmony_ci                min = va_arg(args, int);
156e1051a39Sopenharmony_ci                ch = *format++;
157e1051a39Sopenharmony_ci                state = DP_S_DOT;
158e1051a39Sopenharmony_ci            } else
159e1051a39Sopenharmony_ci                state = DP_S_DOT;
160e1051a39Sopenharmony_ci            break;
161e1051a39Sopenharmony_ci        case DP_S_DOT:
162e1051a39Sopenharmony_ci            if (ch == '.') {
163e1051a39Sopenharmony_ci                state = DP_S_MAX;
164e1051a39Sopenharmony_ci                ch = *format++;
165e1051a39Sopenharmony_ci            } else
166e1051a39Sopenharmony_ci                state = DP_S_MOD;
167e1051a39Sopenharmony_ci            break;
168e1051a39Sopenharmony_ci        case DP_S_MAX:
169e1051a39Sopenharmony_ci            if (ossl_isdigit(ch)) {
170e1051a39Sopenharmony_ci                if (max < 0)
171e1051a39Sopenharmony_ci                    max = 0;
172e1051a39Sopenharmony_ci                max = 10 * max + char_to_int(ch);
173e1051a39Sopenharmony_ci                ch = *format++;
174e1051a39Sopenharmony_ci            } else if (ch == '*') {
175e1051a39Sopenharmony_ci                max = va_arg(args, int);
176e1051a39Sopenharmony_ci                ch = *format++;
177e1051a39Sopenharmony_ci                state = DP_S_MOD;
178e1051a39Sopenharmony_ci            } else
179e1051a39Sopenharmony_ci                state = DP_S_MOD;
180e1051a39Sopenharmony_ci            break;
181e1051a39Sopenharmony_ci        case DP_S_MOD:
182e1051a39Sopenharmony_ci            switch (ch) {
183e1051a39Sopenharmony_ci            case 'h':
184e1051a39Sopenharmony_ci                cflags = DP_C_SHORT;
185e1051a39Sopenharmony_ci                ch = *format++;
186e1051a39Sopenharmony_ci                break;
187e1051a39Sopenharmony_ci            case 'l':
188e1051a39Sopenharmony_ci                if (*format == 'l') {
189e1051a39Sopenharmony_ci                    cflags = DP_C_LLONG;
190e1051a39Sopenharmony_ci                    format++;
191e1051a39Sopenharmony_ci                } else
192e1051a39Sopenharmony_ci                    cflags = DP_C_LONG;
193e1051a39Sopenharmony_ci                ch = *format++;
194e1051a39Sopenharmony_ci                break;
195e1051a39Sopenharmony_ci            case 'q':
196e1051a39Sopenharmony_ci            case 'j':
197e1051a39Sopenharmony_ci                cflags = DP_C_LLONG;
198e1051a39Sopenharmony_ci                ch = *format++;
199e1051a39Sopenharmony_ci                break;
200e1051a39Sopenharmony_ci            case 'L':
201e1051a39Sopenharmony_ci                cflags = DP_C_LDOUBLE;
202e1051a39Sopenharmony_ci                ch = *format++;
203e1051a39Sopenharmony_ci                break;
204e1051a39Sopenharmony_ci            case 'z':
205e1051a39Sopenharmony_ci                cflags = DP_C_SIZE;
206e1051a39Sopenharmony_ci                ch = *format++;
207e1051a39Sopenharmony_ci                break;
208e1051a39Sopenharmony_ci            default:
209e1051a39Sopenharmony_ci                break;
210e1051a39Sopenharmony_ci            }
211e1051a39Sopenharmony_ci            state = DP_S_CONV;
212e1051a39Sopenharmony_ci            break;
213e1051a39Sopenharmony_ci        case DP_S_CONV:
214e1051a39Sopenharmony_ci            switch (ch) {
215e1051a39Sopenharmony_ci            case 'd':
216e1051a39Sopenharmony_ci            case 'i':
217e1051a39Sopenharmony_ci                switch (cflags) {
218e1051a39Sopenharmony_ci                case DP_C_SHORT:
219e1051a39Sopenharmony_ci                    value = (short int)va_arg(args, int);
220e1051a39Sopenharmony_ci                    break;
221e1051a39Sopenharmony_ci                case DP_C_LONG:
222e1051a39Sopenharmony_ci                    value = va_arg(args, long int);
223e1051a39Sopenharmony_ci                    break;
224e1051a39Sopenharmony_ci                case DP_C_LLONG:
225e1051a39Sopenharmony_ci                    value = va_arg(args, int64_t);
226e1051a39Sopenharmony_ci                    break;
227e1051a39Sopenharmony_ci                case DP_C_SIZE:
228e1051a39Sopenharmony_ci                    value = va_arg(args, ossl_ssize_t);
229e1051a39Sopenharmony_ci                    break;
230e1051a39Sopenharmony_ci                default:
231e1051a39Sopenharmony_ci                    value = va_arg(args, int);
232e1051a39Sopenharmony_ci                    break;
233e1051a39Sopenharmony_ci                }
234e1051a39Sopenharmony_ci                if (!fmtint(sbuffer, buffer, &currlen, maxlen, value, 10, min,
235e1051a39Sopenharmony_ci                            max, flags))
236e1051a39Sopenharmony_ci                    return 0;
237e1051a39Sopenharmony_ci                break;
238e1051a39Sopenharmony_ci            case 'X':
239e1051a39Sopenharmony_ci                flags |= DP_F_UP;
240e1051a39Sopenharmony_ci                /* FALLTHROUGH */
241e1051a39Sopenharmony_ci            case 'x':
242e1051a39Sopenharmony_ci            case 'o':
243e1051a39Sopenharmony_ci            case 'u':
244e1051a39Sopenharmony_ci                flags |= DP_F_UNSIGNED;
245e1051a39Sopenharmony_ci                switch (cflags) {
246e1051a39Sopenharmony_ci                case DP_C_SHORT:
247e1051a39Sopenharmony_ci                    value = (unsigned short int)va_arg(args, unsigned int);
248e1051a39Sopenharmony_ci                    break;
249e1051a39Sopenharmony_ci                case DP_C_LONG:
250e1051a39Sopenharmony_ci                    value = va_arg(args, unsigned long int);
251e1051a39Sopenharmony_ci                    break;
252e1051a39Sopenharmony_ci                case DP_C_LLONG:
253e1051a39Sopenharmony_ci                    value = va_arg(args, uint64_t);
254e1051a39Sopenharmony_ci                    break;
255e1051a39Sopenharmony_ci                case DP_C_SIZE:
256e1051a39Sopenharmony_ci                    value = va_arg(args, size_t);
257e1051a39Sopenharmony_ci                    break;
258e1051a39Sopenharmony_ci                default:
259e1051a39Sopenharmony_ci                    value = va_arg(args, unsigned int);
260e1051a39Sopenharmony_ci                    break;
261e1051a39Sopenharmony_ci                }
262e1051a39Sopenharmony_ci                if (!fmtint(sbuffer, buffer, &currlen, maxlen, value,
263e1051a39Sopenharmony_ci                            ch == 'o' ? 8 : (ch == 'u' ? 10 : 16),
264e1051a39Sopenharmony_ci                            min, max, flags))
265e1051a39Sopenharmony_ci                    return 0;
266e1051a39Sopenharmony_ci                break;
267e1051a39Sopenharmony_ci#ifndef OPENSSL_SYS_UEFI
268e1051a39Sopenharmony_ci            case 'f':
269e1051a39Sopenharmony_ci                if (cflags == DP_C_LDOUBLE)
270e1051a39Sopenharmony_ci                    fvalue = va_arg(args, LDOUBLE);
271e1051a39Sopenharmony_ci                else
272e1051a39Sopenharmony_ci                    fvalue = va_arg(args, double);
273e1051a39Sopenharmony_ci                if (!fmtfp(sbuffer, buffer, &currlen, maxlen, fvalue, min, max,
274e1051a39Sopenharmony_ci                           flags, F_FORMAT))
275e1051a39Sopenharmony_ci                    return 0;
276e1051a39Sopenharmony_ci                break;
277e1051a39Sopenharmony_ci            case 'E':
278e1051a39Sopenharmony_ci                flags |= DP_F_UP;
279e1051a39Sopenharmony_ci                /* fall thru */
280e1051a39Sopenharmony_ci            case 'e':
281e1051a39Sopenharmony_ci                if (cflags == DP_C_LDOUBLE)
282e1051a39Sopenharmony_ci                    fvalue = va_arg(args, LDOUBLE);
283e1051a39Sopenharmony_ci                else
284e1051a39Sopenharmony_ci                    fvalue = va_arg(args, double);
285e1051a39Sopenharmony_ci                if (!fmtfp(sbuffer, buffer, &currlen, maxlen, fvalue, min, max,
286e1051a39Sopenharmony_ci                           flags, E_FORMAT))
287e1051a39Sopenharmony_ci                    return 0;
288e1051a39Sopenharmony_ci                break;
289e1051a39Sopenharmony_ci            case 'G':
290e1051a39Sopenharmony_ci                flags |= DP_F_UP;
291e1051a39Sopenharmony_ci                /* fall thru */
292e1051a39Sopenharmony_ci            case 'g':
293e1051a39Sopenharmony_ci                if (cflags == DP_C_LDOUBLE)
294e1051a39Sopenharmony_ci                    fvalue = va_arg(args, LDOUBLE);
295e1051a39Sopenharmony_ci                else
296e1051a39Sopenharmony_ci                    fvalue = va_arg(args, double);
297e1051a39Sopenharmony_ci                if (!fmtfp(sbuffer, buffer, &currlen, maxlen, fvalue, min, max,
298e1051a39Sopenharmony_ci                           flags, G_FORMAT))
299e1051a39Sopenharmony_ci                    return 0;
300e1051a39Sopenharmony_ci                break;
301e1051a39Sopenharmony_ci#else
302e1051a39Sopenharmony_ci            case 'f':
303e1051a39Sopenharmony_ci            case 'E':
304e1051a39Sopenharmony_ci            case 'e':
305e1051a39Sopenharmony_ci            case 'G':
306e1051a39Sopenharmony_ci            case 'g':
307e1051a39Sopenharmony_ci                /* not implemented for UEFI */
308e1051a39Sopenharmony_ci                ERR_raise(ERR_LIB_BIO, ERR_R_UNSUPPORTED);
309e1051a39Sopenharmony_ci                return 0;
310e1051a39Sopenharmony_ci#endif
311e1051a39Sopenharmony_ci            case 'c':
312e1051a39Sopenharmony_ci                if (!doapr_outch(sbuffer, buffer, &currlen, maxlen,
313e1051a39Sopenharmony_ci                                 va_arg(args, int)))
314e1051a39Sopenharmony_ci                    return 0;
315e1051a39Sopenharmony_ci                break;
316e1051a39Sopenharmony_ci            case 's':
317e1051a39Sopenharmony_ci                strvalue = va_arg(args, char *);
318e1051a39Sopenharmony_ci                if (max < 0) {
319e1051a39Sopenharmony_ci                    if (buffer)
320e1051a39Sopenharmony_ci                        max = INT_MAX;
321e1051a39Sopenharmony_ci                    else
322e1051a39Sopenharmony_ci                        max = *maxlen;
323e1051a39Sopenharmony_ci                }
324e1051a39Sopenharmony_ci                if (!fmtstr(sbuffer, buffer, &currlen, maxlen, strvalue,
325e1051a39Sopenharmony_ci                            flags, min, max))
326e1051a39Sopenharmony_ci                    return 0;
327e1051a39Sopenharmony_ci                break;
328e1051a39Sopenharmony_ci            case 'p':
329e1051a39Sopenharmony_ci                value = (size_t)va_arg(args, void *);
330e1051a39Sopenharmony_ci                if (!fmtint(sbuffer, buffer, &currlen, maxlen,
331e1051a39Sopenharmony_ci                            value, 16, min, max, flags | DP_F_NUM))
332e1051a39Sopenharmony_ci                    return 0;
333e1051a39Sopenharmony_ci                break;
334e1051a39Sopenharmony_ci            case 'n':
335e1051a39Sopenharmony_ci                {
336e1051a39Sopenharmony_ci                    int *num;
337e1051a39Sopenharmony_ci                    num = va_arg(args, int *);
338e1051a39Sopenharmony_ci                    *num = currlen;
339e1051a39Sopenharmony_ci                }
340e1051a39Sopenharmony_ci                break;
341e1051a39Sopenharmony_ci            case '%':
342e1051a39Sopenharmony_ci                if (!doapr_outch(sbuffer, buffer, &currlen, maxlen, ch))
343e1051a39Sopenharmony_ci                    return 0;
344e1051a39Sopenharmony_ci                break;
345e1051a39Sopenharmony_ci            case 'w':
346e1051a39Sopenharmony_ci                /* not supported yet, treat as next char */
347e1051a39Sopenharmony_ci                format++;
348e1051a39Sopenharmony_ci                break;
349e1051a39Sopenharmony_ci            default:
350e1051a39Sopenharmony_ci                /* unknown, skip */
351e1051a39Sopenharmony_ci                break;
352e1051a39Sopenharmony_ci            }
353e1051a39Sopenharmony_ci            ch = *format++;
354e1051a39Sopenharmony_ci            state = DP_S_DEFAULT;
355e1051a39Sopenharmony_ci            flags = cflags = min = 0;
356e1051a39Sopenharmony_ci            max = -1;
357e1051a39Sopenharmony_ci            break;
358e1051a39Sopenharmony_ci        case DP_S_DONE:
359e1051a39Sopenharmony_ci            break;
360e1051a39Sopenharmony_ci        default:
361e1051a39Sopenharmony_ci            break;
362e1051a39Sopenharmony_ci        }
363e1051a39Sopenharmony_ci    }
364e1051a39Sopenharmony_ci    /*
365e1051a39Sopenharmony_ci     * We have to truncate if there is no dynamic buffer and we have filled the
366e1051a39Sopenharmony_ci     * static buffer.
367e1051a39Sopenharmony_ci     */
368e1051a39Sopenharmony_ci    if (buffer == NULL) {
369e1051a39Sopenharmony_ci        *truncated = (currlen > *maxlen - 1);
370e1051a39Sopenharmony_ci        if (*truncated)
371e1051a39Sopenharmony_ci            currlen = *maxlen - 1;
372e1051a39Sopenharmony_ci    }
373e1051a39Sopenharmony_ci    if (!doapr_outch(sbuffer, buffer, &currlen, maxlen, '\0'))
374e1051a39Sopenharmony_ci        return 0;
375e1051a39Sopenharmony_ci    *retlen = currlen - 1;
376e1051a39Sopenharmony_ci    return 1;
377e1051a39Sopenharmony_ci}
378e1051a39Sopenharmony_ci
379e1051a39Sopenharmony_cistatic int
380e1051a39Sopenharmony_cifmtstr(char **sbuffer,
381e1051a39Sopenharmony_ci       char **buffer,
382e1051a39Sopenharmony_ci       size_t *currlen,
383e1051a39Sopenharmony_ci       size_t *maxlen, const char *value, int flags, int min, int max)
384e1051a39Sopenharmony_ci{
385e1051a39Sopenharmony_ci    int padlen;
386e1051a39Sopenharmony_ci    size_t strln;
387e1051a39Sopenharmony_ci    int cnt = 0;
388e1051a39Sopenharmony_ci
389e1051a39Sopenharmony_ci    if (value == 0)
390e1051a39Sopenharmony_ci        value = "<NULL>";
391e1051a39Sopenharmony_ci
392e1051a39Sopenharmony_ci    strln = OPENSSL_strnlen(value, max < 0 ? SIZE_MAX : (size_t)max);
393e1051a39Sopenharmony_ci
394e1051a39Sopenharmony_ci    padlen = min - strln;
395e1051a39Sopenharmony_ci    if (min < 0 || padlen < 0)
396e1051a39Sopenharmony_ci        padlen = 0;
397e1051a39Sopenharmony_ci    if (max >= 0) {
398e1051a39Sopenharmony_ci        /*
399e1051a39Sopenharmony_ci         * Calculate the maximum output including padding.
400e1051a39Sopenharmony_ci         * Make sure max doesn't overflow into negativity
401e1051a39Sopenharmony_ci         */
402e1051a39Sopenharmony_ci        if (max < INT_MAX - padlen)
403e1051a39Sopenharmony_ci            max += padlen;
404e1051a39Sopenharmony_ci        else
405e1051a39Sopenharmony_ci            max = INT_MAX;
406e1051a39Sopenharmony_ci    }
407e1051a39Sopenharmony_ci    if (flags & DP_F_MINUS)
408e1051a39Sopenharmony_ci        padlen = -padlen;
409e1051a39Sopenharmony_ci
410e1051a39Sopenharmony_ci    while ((padlen > 0) && (max < 0 || cnt < max)) {
411e1051a39Sopenharmony_ci        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
412e1051a39Sopenharmony_ci            return 0;
413e1051a39Sopenharmony_ci        --padlen;
414e1051a39Sopenharmony_ci        ++cnt;
415e1051a39Sopenharmony_ci    }
416e1051a39Sopenharmony_ci    while (strln > 0 && (max < 0 || cnt < max)) {
417e1051a39Sopenharmony_ci        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, *value++))
418e1051a39Sopenharmony_ci            return 0;
419e1051a39Sopenharmony_ci        --strln;
420e1051a39Sopenharmony_ci        ++cnt;
421e1051a39Sopenharmony_ci    }
422e1051a39Sopenharmony_ci    while ((padlen < 0) && (max < 0 || cnt < max)) {
423e1051a39Sopenharmony_ci        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
424e1051a39Sopenharmony_ci            return 0;
425e1051a39Sopenharmony_ci        ++padlen;
426e1051a39Sopenharmony_ci        ++cnt;
427e1051a39Sopenharmony_ci    }
428e1051a39Sopenharmony_ci    return 1;
429e1051a39Sopenharmony_ci}
430e1051a39Sopenharmony_ci
431e1051a39Sopenharmony_cistatic int
432e1051a39Sopenharmony_cifmtint(char **sbuffer,
433e1051a39Sopenharmony_ci       char **buffer,
434e1051a39Sopenharmony_ci       size_t *currlen,
435e1051a39Sopenharmony_ci       size_t *maxlen, int64_t value, int base, int min, int max, int flags)
436e1051a39Sopenharmony_ci{
437e1051a39Sopenharmony_ci    int signvalue = 0;
438e1051a39Sopenharmony_ci    const char *prefix = "";
439e1051a39Sopenharmony_ci    uint64_t uvalue;
440e1051a39Sopenharmony_ci    char convert[DECIMAL_SIZE(value) + 3];
441e1051a39Sopenharmony_ci    int place = 0;
442e1051a39Sopenharmony_ci    int spadlen = 0;
443e1051a39Sopenharmony_ci    int zpadlen = 0;
444e1051a39Sopenharmony_ci    int caps = 0;
445e1051a39Sopenharmony_ci
446e1051a39Sopenharmony_ci    if (max < 0)
447e1051a39Sopenharmony_ci        max = 0;
448e1051a39Sopenharmony_ci    uvalue = value;
449e1051a39Sopenharmony_ci    if (!(flags & DP_F_UNSIGNED)) {
450e1051a39Sopenharmony_ci        if (value < 0) {
451e1051a39Sopenharmony_ci            signvalue = '-';
452e1051a39Sopenharmony_ci            uvalue = 0 - (uint64_t)value;
453e1051a39Sopenharmony_ci        } else if (flags & DP_F_PLUS)
454e1051a39Sopenharmony_ci            signvalue = '+';
455e1051a39Sopenharmony_ci        else if (flags & DP_F_SPACE)
456e1051a39Sopenharmony_ci            signvalue = ' ';
457e1051a39Sopenharmony_ci    }
458e1051a39Sopenharmony_ci    if (flags & DP_F_NUM) {
459e1051a39Sopenharmony_ci        if (base == 8)
460e1051a39Sopenharmony_ci            prefix = "0";
461e1051a39Sopenharmony_ci        if (base == 16)
462e1051a39Sopenharmony_ci            prefix = "0x";
463e1051a39Sopenharmony_ci    }
464e1051a39Sopenharmony_ci    if (flags & DP_F_UP)
465e1051a39Sopenharmony_ci        caps = 1;
466e1051a39Sopenharmony_ci    do {
467e1051a39Sopenharmony_ci        convert[place++] = (caps ? "0123456789ABCDEF" : "0123456789abcdef")
468e1051a39Sopenharmony_ci            [uvalue % (unsigned)base];
469e1051a39Sopenharmony_ci        uvalue = (uvalue / (unsigned)base);
470e1051a39Sopenharmony_ci    } while (uvalue && (place < (int)sizeof(convert)));
471e1051a39Sopenharmony_ci    if (place == sizeof(convert))
472e1051a39Sopenharmony_ci        place--;
473e1051a39Sopenharmony_ci    convert[place] = 0;
474e1051a39Sopenharmony_ci
475e1051a39Sopenharmony_ci    zpadlen = max - place;
476e1051a39Sopenharmony_ci    spadlen =
477e1051a39Sopenharmony_ci        min - OSSL_MAX(max, place) - (signvalue ? 1 : 0) - strlen(prefix);
478e1051a39Sopenharmony_ci    if (zpadlen < 0)
479e1051a39Sopenharmony_ci        zpadlen = 0;
480e1051a39Sopenharmony_ci    if (spadlen < 0)
481e1051a39Sopenharmony_ci        spadlen = 0;
482e1051a39Sopenharmony_ci    if (flags & DP_F_ZERO) {
483e1051a39Sopenharmony_ci        zpadlen = OSSL_MAX(zpadlen, spadlen);
484e1051a39Sopenharmony_ci        spadlen = 0;
485e1051a39Sopenharmony_ci    }
486e1051a39Sopenharmony_ci    if (flags & DP_F_MINUS)
487e1051a39Sopenharmony_ci        spadlen = -spadlen;
488e1051a39Sopenharmony_ci
489e1051a39Sopenharmony_ci    /* spaces */
490e1051a39Sopenharmony_ci    while (spadlen > 0) {
491e1051a39Sopenharmony_ci        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
492e1051a39Sopenharmony_ci            return 0;
493e1051a39Sopenharmony_ci        --spadlen;
494e1051a39Sopenharmony_ci    }
495e1051a39Sopenharmony_ci
496e1051a39Sopenharmony_ci    /* sign */
497e1051a39Sopenharmony_ci    if (signvalue)
498e1051a39Sopenharmony_ci        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue))
499e1051a39Sopenharmony_ci            return 0;
500e1051a39Sopenharmony_ci
501e1051a39Sopenharmony_ci    /* prefix */
502e1051a39Sopenharmony_ci    while (*prefix) {
503e1051a39Sopenharmony_ci        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, *prefix))
504e1051a39Sopenharmony_ci            return 0;
505e1051a39Sopenharmony_ci        prefix++;
506e1051a39Sopenharmony_ci    }
507e1051a39Sopenharmony_ci
508e1051a39Sopenharmony_ci    /* zeros */
509e1051a39Sopenharmony_ci    if (zpadlen > 0) {
510e1051a39Sopenharmony_ci        while (zpadlen > 0) {
511e1051a39Sopenharmony_ci            if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0'))
512e1051a39Sopenharmony_ci                return 0;
513e1051a39Sopenharmony_ci            --zpadlen;
514e1051a39Sopenharmony_ci        }
515e1051a39Sopenharmony_ci    }
516e1051a39Sopenharmony_ci    /* digits */
517e1051a39Sopenharmony_ci    while (place > 0) {
518e1051a39Sopenharmony_ci        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, convert[--place]))
519e1051a39Sopenharmony_ci            return 0;
520e1051a39Sopenharmony_ci    }
521e1051a39Sopenharmony_ci
522e1051a39Sopenharmony_ci    /* left justified spaces */
523e1051a39Sopenharmony_ci    while (spadlen < 0) {
524e1051a39Sopenharmony_ci        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
525e1051a39Sopenharmony_ci            return 0;
526e1051a39Sopenharmony_ci        ++spadlen;
527e1051a39Sopenharmony_ci    }
528e1051a39Sopenharmony_ci    return 1;
529e1051a39Sopenharmony_ci}
530e1051a39Sopenharmony_ci
531e1051a39Sopenharmony_ci#ifndef OPENSSL_SYS_UEFI
532e1051a39Sopenharmony_ci
533e1051a39Sopenharmony_cistatic LDOUBLE abs_val(LDOUBLE value)
534e1051a39Sopenharmony_ci{
535e1051a39Sopenharmony_ci    LDOUBLE result = value;
536e1051a39Sopenharmony_ci    if (value < 0)
537e1051a39Sopenharmony_ci        result = -value;
538e1051a39Sopenharmony_ci    return result;
539e1051a39Sopenharmony_ci}
540e1051a39Sopenharmony_ci
541e1051a39Sopenharmony_cistatic LDOUBLE pow_10(int in_exp)
542e1051a39Sopenharmony_ci{
543e1051a39Sopenharmony_ci    LDOUBLE result = 1;
544e1051a39Sopenharmony_ci    while (in_exp) {
545e1051a39Sopenharmony_ci        result *= 10;
546e1051a39Sopenharmony_ci        in_exp--;
547e1051a39Sopenharmony_ci    }
548e1051a39Sopenharmony_ci    return result;
549e1051a39Sopenharmony_ci}
550e1051a39Sopenharmony_ci
551e1051a39Sopenharmony_cistatic long roundv(LDOUBLE value)
552e1051a39Sopenharmony_ci{
553e1051a39Sopenharmony_ci    long intpart;
554e1051a39Sopenharmony_ci    intpart = (long)value;
555e1051a39Sopenharmony_ci    value = value - intpart;
556e1051a39Sopenharmony_ci    if (value >= 0.5)
557e1051a39Sopenharmony_ci        intpart++;
558e1051a39Sopenharmony_ci    return intpart;
559e1051a39Sopenharmony_ci}
560e1051a39Sopenharmony_ci
561e1051a39Sopenharmony_cistatic int
562e1051a39Sopenharmony_cifmtfp(char **sbuffer,
563e1051a39Sopenharmony_ci      char **buffer,
564e1051a39Sopenharmony_ci      size_t *currlen,
565e1051a39Sopenharmony_ci      size_t *maxlen, LDOUBLE fvalue, int min, int max, int flags, int style)
566e1051a39Sopenharmony_ci{
567e1051a39Sopenharmony_ci    int signvalue = 0;
568e1051a39Sopenharmony_ci    LDOUBLE ufvalue;
569e1051a39Sopenharmony_ci    LDOUBLE tmpvalue;
570e1051a39Sopenharmony_ci    char iconvert[20];
571e1051a39Sopenharmony_ci    char fconvert[20];
572e1051a39Sopenharmony_ci    char econvert[20];
573e1051a39Sopenharmony_ci    int iplace = 0;
574e1051a39Sopenharmony_ci    int fplace = 0;
575e1051a39Sopenharmony_ci    int eplace = 0;
576e1051a39Sopenharmony_ci    int padlen = 0;
577e1051a39Sopenharmony_ci    int zpadlen = 0;
578e1051a39Sopenharmony_ci    long exp = 0;
579e1051a39Sopenharmony_ci    unsigned long intpart;
580e1051a39Sopenharmony_ci    unsigned long fracpart;
581e1051a39Sopenharmony_ci    unsigned long max10;
582e1051a39Sopenharmony_ci    int realstyle;
583e1051a39Sopenharmony_ci
584e1051a39Sopenharmony_ci    if (max < 0)
585e1051a39Sopenharmony_ci        max = 6;
586e1051a39Sopenharmony_ci
587e1051a39Sopenharmony_ci    if (fvalue < 0)
588e1051a39Sopenharmony_ci        signvalue = '-';
589e1051a39Sopenharmony_ci    else if (flags & DP_F_PLUS)
590e1051a39Sopenharmony_ci        signvalue = '+';
591e1051a39Sopenharmony_ci    else if (flags & DP_F_SPACE)
592e1051a39Sopenharmony_ci        signvalue = ' ';
593e1051a39Sopenharmony_ci
594e1051a39Sopenharmony_ci    /*
595e1051a39Sopenharmony_ci     * G_FORMAT sometimes prints like E_FORMAT and sometimes like F_FORMAT
596e1051a39Sopenharmony_ci     * depending on the number to be printed. Work out which one it is and use
597e1051a39Sopenharmony_ci     * that from here on.
598e1051a39Sopenharmony_ci     */
599e1051a39Sopenharmony_ci    if (style == G_FORMAT) {
600e1051a39Sopenharmony_ci        if (fvalue == 0.0) {
601e1051a39Sopenharmony_ci            realstyle = F_FORMAT;
602e1051a39Sopenharmony_ci        } else if (fvalue < 0.0001) {
603e1051a39Sopenharmony_ci            realstyle = E_FORMAT;
604e1051a39Sopenharmony_ci        } else if ((max == 0 && fvalue >= 10)
605e1051a39Sopenharmony_ci                    || (max > 0 && fvalue >= pow_10(max))) {
606e1051a39Sopenharmony_ci            realstyle = E_FORMAT;
607e1051a39Sopenharmony_ci        } else {
608e1051a39Sopenharmony_ci            realstyle = F_FORMAT;
609e1051a39Sopenharmony_ci        }
610e1051a39Sopenharmony_ci    } else {
611e1051a39Sopenharmony_ci        realstyle = style;
612e1051a39Sopenharmony_ci    }
613e1051a39Sopenharmony_ci
614e1051a39Sopenharmony_ci    if (style != F_FORMAT) {
615e1051a39Sopenharmony_ci        tmpvalue = fvalue;
616e1051a39Sopenharmony_ci        /* Calculate the exponent */
617e1051a39Sopenharmony_ci        if (fvalue != 0.0) {
618e1051a39Sopenharmony_ci            while (tmpvalue < 1) {
619e1051a39Sopenharmony_ci                tmpvalue *= 10;
620e1051a39Sopenharmony_ci                exp--;
621e1051a39Sopenharmony_ci            }
622e1051a39Sopenharmony_ci            while (tmpvalue > 10) {
623e1051a39Sopenharmony_ci                tmpvalue /= 10;
624e1051a39Sopenharmony_ci                exp++;
625e1051a39Sopenharmony_ci            }
626e1051a39Sopenharmony_ci        }
627e1051a39Sopenharmony_ci        if (style == G_FORMAT) {
628e1051a39Sopenharmony_ci            /*
629e1051a39Sopenharmony_ci             * In G_FORMAT the "precision" represents significant digits. We
630e1051a39Sopenharmony_ci             * always have at least 1 significant digit.
631e1051a39Sopenharmony_ci             */
632e1051a39Sopenharmony_ci            if (max == 0)
633e1051a39Sopenharmony_ci                max = 1;
634e1051a39Sopenharmony_ci            /* Now convert significant digits to decimal places */
635e1051a39Sopenharmony_ci            if (realstyle == F_FORMAT) {
636e1051a39Sopenharmony_ci                max -= (exp + 1);
637e1051a39Sopenharmony_ci                if (max < 0) {
638e1051a39Sopenharmony_ci                    /*
639e1051a39Sopenharmony_ci                     * Should not happen. If we're in F_FORMAT then exp < max?
640e1051a39Sopenharmony_ci                     */
641e1051a39Sopenharmony_ci                    (void)doapr_outch(sbuffer, buffer, currlen, maxlen, '\0');
642e1051a39Sopenharmony_ci                    return 0;
643e1051a39Sopenharmony_ci                }
644e1051a39Sopenharmony_ci            } else {
645e1051a39Sopenharmony_ci                /*
646e1051a39Sopenharmony_ci                 * In E_FORMAT there is always one significant digit in front
647e1051a39Sopenharmony_ci                 * of the decimal point, so:
648e1051a39Sopenharmony_ci                 * significant digits == 1 + decimal places
649e1051a39Sopenharmony_ci                 */
650e1051a39Sopenharmony_ci                max--;
651e1051a39Sopenharmony_ci            }
652e1051a39Sopenharmony_ci        }
653e1051a39Sopenharmony_ci        if (realstyle == E_FORMAT)
654e1051a39Sopenharmony_ci            fvalue = tmpvalue;
655e1051a39Sopenharmony_ci    }
656e1051a39Sopenharmony_ci    ufvalue = abs_val(fvalue);
657e1051a39Sopenharmony_ci    /*
658e1051a39Sopenharmony_ci     * By subtracting 65535 (2^16-1) we cancel the low order 15 bits
659e1051a39Sopenharmony_ci     * of ULONG_MAX to avoid using imprecise floating point values.
660e1051a39Sopenharmony_ci     */
661e1051a39Sopenharmony_ci    if (ufvalue >= (double)(ULONG_MAX - 65535) + 65536.0) {
662e1051a39Sopenharmony_ci        /* Number too big */
663e1051a39Sopenharmony_ci        (void)doapr_outch(sbuffer, buffer, currlen, maxlen, '\0');
664e1051a39Sopenharmony_ci        return 0;
665e1051a39Sopenharmony_ci    }
666e1051a39Sopenharmony_ci    intpart = (unsigned long)ufvalue;
667e1051a39Sopenharmony_ci
668e1051a39Sopenharmony_ci    /*
669e1051a39Sopenharmony_ci     * sorry, we only support 9 digits past the decimal because of our
670e1051a39Sopenharmony_ci     * conversion method
671e1051a39Sopenharmony_ci     */
672e1051a39Sopenharmony_ci    if (max > 9)
673e1051a39Sopenharmony_ci        max = 9;
674e1051a39Sopenharmony_ci
675e1051a39Sopenharmony_ci    /*
676e1051a39Sopenharmony_ci     * we "cheat" by converting the fractional part to integer by multiplying
677e1051a39Sopenharmony_ci     * by a factor of 10
678e1051a39Sopenharmony_ci     */
679e1051a39Sopenharmony_ci    max10 = roundv(pow_10(max));
680e1051a39Sopenharmony_ci    fracpart = roundv(pow_10(max) * (ufvalue - intpart));
681e1051a39Sopenharmony_ci
682e1051a39Sopenharmony_ci    if (fracpart >= max10) {
683e1051a39Sopenharmony_ci        intpart++;
684e1051a39Sopenharmony_ci        fracpart -= max10;
685e1051a39Sopenharmony_ci    }
686e1051a39Sopenharmony_ci
687e1051a39Sopenharmony_ci    /* convert integer part */
688e1051a39Sopenharmony_ci    do {
689e1051a39Sopenharmony_ci        iconvert[iplace++] = "0123456789"[intpart % 10];
690e1051a39Sopenharmony_ci        intpart = (intpart / 10);
691e1051a39Sopenharmony_ci    } while (intpart && (iplace < (int)sizeof(iconvert)));
692e1051a39Sopenharmony_ci    if (iplace == sizeof(iconvert))
693e1051a39Sopenharmony_ci        iplace--;
694e1051a39Sopenharmony_ci    iconvert[iplace] = 0;
695e1051a39Sopenharmony_ci
696e1051a39Sopenharmony_ci    /* convert fractional part */
697e1051a39Sopenharmony_ci    while (fplace < max) {
698e1051a39Sopenharmony_ci        if (style == G_FORMAT && fplace == 0 && (fracpart % 10) == 0) {
699e1051a39Sopenharmony_ci            /* We strip trailing zeros in G_FORMAT */
700e1051a39Sopenharmony_ci            max--;
701e1051a39Sopenharmony_ci            fracpart = fracpart / 10;
702e1051a39Sopenharmony_ci            if (fplace < max)
703e1051a39Sopenharmony_ci                continue;
704e1051a39Sopenharmony_ci            break;
705e1051a39Sopenharmony_ci        }
706e1051a39Sopenharmony_ci        fconvert[fplace++] = "0123456789"[fracpart % 10];
707e1051a39Sopenharmony_ci        fracpart = (fracpart / 10);
708e1051a39Sopenharmony_ci    }
709e1051a39Sopenharmony_ci
710e1051a39Sopenharmony_ci    if (fplace == sizeof(fconvert))
711e1051a39Sopenharmony_ci        fplace--;
712e1051a39Sopenharmony_ci    fconvert[fplace] = 0;
713e1051a39Sopenharmony_ci
714e1051a39Sopenharmony_ci    /* convert exponent part */
715e1051a39Sopenharmony_ci    if (realstyle == E_FORMAT) {
716e1051a39Sopenharmony_ci        int tmpexp;
717e1051a39Sopenharmony_ci        if (exp < 0)
718e1051a39Sopenharmony_ci            tmpexp = -exp;
719e1051a39Sopenharmony_ci        else
720e1051a39Sopenharmony_ci            tmpexp = exp;
721e1051a39Sopenharmony_ci
722e1051a39Sopenharmony_ci        do {
723e1051a39Sopenharmony_ci            econvert[eplace++] = "0123456789"[tmpexp % 10];
724e1051a39Sopenharmony_ci            tmpexp = (tmpexp / 10);
725e1051a39Sopenharmony_ci        } while (tmpexp > 0 && eplace < (int)sizeof(econvert));
726e1051a39Sopenharmony_ci        /* Exponent is huge!! Too big to print */
727e1051a39Sopenharmony_ci        if (tmpexp > 0) {
728e1051a39Sopenharmony_ci            (void)doapr_outch(sbuffer, buffer, currlen, maxlen, '\0');
729e1051a39Sopenharmony_ci            return 0;
730e1051a39Sopenharmony_ci        }
731e1051a39Sopenharmony_ci        /* Add a leading 0 for single digit exponents */
732e1051a39Sopenharmony_ci        if (eplace == 1)
733e1051a39Sopenharmony_ci            econvert[eplace++] = '0';
734e1051a39Sopenharmony_ci    }
735e1051a39Sopenharmony_ci
736e1051a39Sopenharmony_ci    /*
737e1051a39Sopenharmony_ci     * -1 for decimal point (if we have one, i.e. max > 0),
738e1051a39Sopenharmony_ci     * another -1 if we are printing a sign
739e1051a39Sopenharmony_ci     */
740e1051a39Sopenharmony_ci    padlen = min - iplace - max - (max > 0 ? 1 : 0) - ((signvalue) ? 1 : 0);
741e1051a39Sopenharmony_ci    /* Take some off for exponent prefix "+e" and exponent */
742e1051a39Sopenharmony_ci    if (realstyle == E_FORMAT)
743e1051a39Sopenharmony_ci        padlen -= 2 + eplace;
744e1051a39Sopenharmony_ci    zpadlen = max - fplace;
745e1051a39Sopenharmony_ci    if (zpadlen < 0)
746e1051a39Sopenharmony_ci        zpadlen = 0;
747e1051a39Sopenharmony_ci    if (padlen < 0)
748e1051a39Sopenharmony_ci        padlen = 0;
749e1051a39Sopenharmony_ci    if (flags & DP_F_MINUS)
750e1051a39Sopenharmony_ci        padlen = -padlen;
751e1051a39Sopenharmony_ci
752e1051a39Sopenharmony_ci    if ((flags & DP_F_ZERO) && (padlen > 0)) {
753e1051a39Sopenharmony_ci        if (signvalue) {
754e1051a39Sopenharmony_ci            if (!doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue))
755e1051a39Sopenharmony_ci                return 0;
756e1051a39Sopenharmony_ci            --padlen;
757e1051a39Sopenharmony_ci            signvalue = 0;
758e1051a39Sopenharmony_ci        }
759e1051a39Sopenharmony_ci        while (padlen > 0) {
760e1051a39Sopenharmony_ci            if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0'))
761e1051a39Sopenharmony_ci                return 0;
762e1051a39Sopenharmony_ci            --padlen;
763e1051a39Sopenharmony_ci        }
764e1051a39Sopenharmony_ci    }
765e1051a39Sopenharmony_ci    while (padlen > 0) {
766e1051a39Sopenharmony_ci        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
767e1051a39Sopenharmony_ci            return 0;
768e1051a39Sopenharmony_ci        --padlen;
769e1051a39Sopenharmony_ci    }
770e1051a39Sopenharmony_ci    if (signvalue && !doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue))
771e1051a39Sopenharmony_ci        return 0;
772e1051a39Sopenharmony_ci
773e1051a39Sopenharmony_ci    while (iplace > 0) {
774e1051a39Sopenharmony_ci        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, iconvert[--iplace]))
775e1051a39Sopenharmony_ci            return 0;
776e1051a39Sopenharmony_ci    }
777e1051a39Sopenharmony_ci
778e1051a39Sopenharmony_ci    /*
779e1051a39Sopenharmony_ci     * Decimal point. This should probably use locale to find the correct
780e1051a39Sopenharmony_ci     * char to print out.
781e1051a39Sopenharmony_ci     */
782e1051a39Sopenharmony_ci    if (max > 0 || (flags & DP_F_NUM)) {
783e1051a39Sopenharmony_ci        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '.'))
784e1051a39Sopenharmony_ci            return 0;
785e1051a39Sopenharmony_ci
786e1051a39Sopenharmony_ci        while (fplace > 0) {
787e1051a39Sopenharmony_ci            if (!doapr_outch(sbuffer, buffer, currlen, maxlen,
788e1051a39Sopenharmony_ci                             fconvert[--fplace]))
789e1051a39Sopenharmony_ci                return 0;
790e1051a39Sopenharmony_ci        }
791e1051a39Sopenharmony_ci    }
792e1051a39Sopenharmony_ci    while (zpadlen > 0) {
793e1051a39Sopenharmony_ci        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0'))
794e1051a39Sopenharmony_ci            return 0;
795e1051a39Sopenharmony_ci        --zpadlen;
796e1051a39Sopenharmony_ci    }
797e1051a39Sopenharmony_ci    if (realstyle == E_FORMAT) {
798e1051a39Sopenharmony_ci        char ech;
799e1051a39Sopenharmony_ci
800e1051a39Sopenharmony_ci        if ((flags & DP_F_UP) == 0)
801e1051a39Sopenharmony_ci            ech = 'e';
802e1051a39Sopenharmony_ci        else
803e1051a39Sopenharmony_ci            ech = 'E';
804e1051a39Sopenharmony_ci        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ech))
805e1051a39Sopenharmony_ci                return 0;
806e1051a39Sopenharmony_ci        if (exp < 0) {
807e1051a39Sopenharmony_ci            if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '-'))
808e1051a39Sopenharmony_ci                    return 0;
809e1051a39Sopenharmony_ci        } else {
810e1051a39Sopenharmony_ci            if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '+'))
811e1051a39Sopenharmony_ci                    return 0;
812e1051a39Sopenharmony_ci        }
813e1051a39Sopenharmony_ci        while (eplace > 0) {
814e1051a39Sopenharmony_ci            if (!doapr_outch(sbuffer, buffer, currlen, maxlen,
815e1051a39Sopenharmony_ci                             econvert[--eplace]))
816e1051a39Sopenharmony_ci                return 0;
817e1051a39Sopenharmony_ci        }
818e1051a39Sopenharmony_ci    }
819e1051a39Sopenharmony_ci
820e1051a39Sopenharmony_ci    while (padlen < 0) {
821e1051a39Sopenharmony_ci        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
822e1051a39Sopenharmony_ci            return 0;
823e1051a39Sopenharmony_ci        ++padlen;
824e1051a39Sopenharmony_ci    }
825e1051a39Sopenharmony_ci    return 1;
826e1051a39Sopenharmony_ci}
827e1051a39Sopenharmony_ci
828e1051a39Sopenharmony_ci#endif /* OPENSSL_SYS_UEFI */
829e1051a39Sopenharmony_ci
830e1051a39Sopenharmony_ci#define BUFFER_INC  1024
831e1051a39Sopenharmony_ci
832e1051a39Sopenharmony_cistatic int
833e1051a39Sopenharmony_cidoapr_outch(char **sbuffer,
834e1051a39Sopenharmony_ci            char **buffer, size_t *currlen, size_t *maxlen, int c)
835e1051a39Sopenharmony_ci{
836e1051a39Sopenharmony_ci    /* If we haven't at least one buffer, someone has done a big booboo */
837e1051a39Sopenharmony_ci    if (!ossl_assert(*sbuffer != NULL || buffer != NULL))
838e1051a39Sopenharmony_ci        return 0;
839e1051a39Sopenharmony_ci
840e1051a39Sopenharmony_ci    /* |currlen| must always be <= |*maxlen| */
841e1051a39Sopenharmony_ci    if (!ossl_assert(*currlen <= *maxlen))
842e1051a39Sopenharmony_ci        return 0;
843e1051a39Sopenharmony_ci
844e1051a39Sopenharmony_ci    if (buffer && *currlen == *maxlen) {
845e1051a39Sopenharmony_ci        if (*maxlen > INT_MAX - BUFFER_INC)
846e1051a39Sopenharmony_ci            return 0;
847e1051a39Sopenharmony_ci
848e1051a39Sopenharmony_ci        *maxlen += BUFFER_INC;
849e1051a39Sopenharmony_ci        if (*buffer == NULL) {
850e1051a39Sopenharmony_ci            if ((*buffer = OPENSSL_malloc(*maxlen)) == NULL) {
851e1051a39Sopenharmony_ci                ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE);
852e1051a39Sopenharmony_ci                return 0;
853e1051a39Sopenharmony_ci            }
854e1051a39Sopenharmony_ci            if (*currlen > 0) {
855e1051a39Sopenharmony_ci                if (!ossl_assert(*sbuffer != NULL))
856e1051a39Sopenharmony_ci                    return 0;
857e1051a39Sopenharmony_ci                memcpy(*buffer, *sbuffer, *currlen);
858e1051a39Sopenharmony_ci            }
859e1051a39Sopenharmony_ci            *sbuffer = NULL;
860e1051a39Sopenharmony_ci        } else {
861e1051a39Sopenharmony_ci            char *tmpbuf;
862e1051a39Sopenharmony_ci
863e1051a39Sopenharmony_ci            tmpbuf = OPENSSL_realloc(*buffer, *maxlen);
864e1051a39Sopenharmony_ci            if (tmpbuf == NULL) {
865e1051a39Sopenharmony_ci                ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE);
866e1051a39Sopenharmony_ci                return 0;
867e1051a39Sopenharmony_ci            }
868e1051a39Sopenharmony_ci            *buffer = tmpbuf;
869e1051a39Sopenharmony_ci        }
870e1051a39Sopenharmony_ci    }
871e1051a39Sopenharmony_ci
872e1051a39Sopenharmony_ci    if (*currlen < *maxlen) {
873e1051a39Sopenharmony_ci        if (*sbuffer)
874e1051a39Sopenharmony_ci            (*sbuffer)[(*currlen)++] = (char)c;
875e1051a39Sopenharmony_ci        else
876e1051a39Sopenharmony_ci            (*buffer)[(*currlen)++] = (char)c;
877e1051a39Sopenharmony_ci    }
878e1051a39Sopenharmony_ci
879e1051a39Sopenharmony_ci    return 1;
880e1051a39Sopenharmony_ci}
881e1051a39Sopenharmony_ci
882e1051a39Sopenharmony_ci/***************************************************************************/
883e1051a39Sopenharmony_ci
884e1051a39Sopenharmony_ciint BIO_printf(BIO *bio, const char *format, ...)
885e1051a39Sopenharmony_ci{
886e1051a39Sopenharmony_ci    va_list args;
887e1051a39Sopenharmony_ci    int ret;
888e1051a39Sopenharmony_ci
889e1051a39Sopenharmony_ci    va_start(args, format);
890e1051a39Sopenharmony_ci
891e1051a39Sopenharmony_ci    ret = BIO_vprintf(bio, format, args);
892e1051a39Sopenharmony_ci
893e1051a39Sopenharmony_ci    va_end(args);
894e1051a39Sopenharmony_ci    return ret;
895e1051a39Sopenharmony_ci}
896e1051a39Sopenharmony_ci
897e1051a39Sopenharmony_ciint BIO_vprintf(BIO *bio, const char *format, va_list args)
898e1051a39Sopenharmony_ci{
899e1051a39Sopenharmony_ci    int ret;
900e1051a39Sopenharmony_ci    size_t retlen;
901e1051a39Sopenharmony_ci    char hugebuf[1024 * 2];     /* Was previously 10k, which is unreasonable
902e1051a39Sopenharmony_ci                                 * in small-stack environments, like threads
903e1051a39Sopenharmony_ci                                 * or DOS programs. */
904e1051a39Sopenharmony_ci    char *hugebufp = hugebuf;
905e1051a39Sopenharmony_ci    size_t hugebufsize = sizeof(hugebuf);
906e1051a39Sopenharmony_ci    char *dynbuf = NULL;
907e1051a39Sopenharmony_ci    int ignored;
908e1051a39Sopenharmony_ci
909e1051a39Sopenharmony_ci    dynbuf = NULL;
910e1051a39Sopenharmony_ci    if (!_dopr(&hugebufp, &dynbuf, &hugebufsize, &retlen, &ignored, format,
911e1051a39Sopenharmony_ci                args)) {
912e1051a39Sopenharmony_ci        OPENSSL_free(dynbuf);
913e1051a39Sopenharmony_ci        return -1;
914e1051a39Sopenharmony_ci    }
915e1051a39Sopenharmony_ci    if (dynbuf) {
916e1051a39Sopenharmony_ci        ret = BIO_write(bio, dynbuf, (int)retlen);
917e1051a39Sopenharmony_ci        OPENSSL_free(dynbuf);
918e1051a39Sopenharmony_ci    } else {
919e1051a39Sopenharmony_ci        ret = BIO_write(bio, hugebuf, (int)retlen);
920e1051a39Sopenharmony_ci    }
921e1051a39Sopenharmony_ci    return ret;
922e1051a39Sopenharmony_ci}
923e1051a39Sopenharmony_ci
924e1051a39Sopenharmony_ci/*
925e1051a39Sopenharmony_ci * As snprintf is not available everywhere, we provide our own
926e1051a39Sopenharmony_ci * implementation. This function has nothing to do with BIOs, but it's
927e1051a39Sopenharmony_ci * closely related to BIO_printf, and we need *some* name prefix ... (XXX the
928e1051a39Sopenharmony_ci * function should be renamed, but to what?)
929e1051a39Sopenharmony_ci */
930e1051a39Sopenharmony_ciint BIO_snprintf(char *buf, size_t n, const char *format, ...)
931e1051a39Sopenharmony_ci{
932e1051a39Sopenharmony_ci    va_list args;
933e1051a39Sopenharmony_ci    int ret;
934e1051a39Sopenharmony_ci
935e1051a39Sopenharmony_ci    va_start(args, format);
936e1051a39Sopenharmony_ci
937e1051a39Sopenharmony_ci    ret = BIO_vsnprintf(buf, n, format, args);
938e1051a39Sopenharmony_ci
939e1051a39Sopenharmony_ci    va_end(args);
940e1051a39Sopenharmony_ci    return ret;
941e1051a39Sopenharmony_ci}
942e1051a39Sopenharmony_ci
943e1051a39Sopenharmony_ciint BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args)
944e1051a39Sopenharmony_ci{
945e1051a39Sopenharmony_ci    size_t retlen;
946e1051a39Sopenharmony_ci    int truncated;
947e1051a39Sopenharmony_ci
948e1051a39Sopenharmony_ci    if (!_dopr(&buf, NULL, &n, &retlen, &truncated, format, args))
949e1051a39Sopenharmony_ci        return -1;
950e1051a39Sopenharmony_ci
951e1051a39Sopenharmony_ci    if (truncated)
952e1051a39Sopenharmony_ci        /*
953e1051a39Sopenharmony_ci         * In case of truncation, return -1 like traditional snprintf.
954e1051a39Sopenharmony_ci         * (Current drafts for ISO/IEC 9899 say snprintf should return the
955e1051a39Sopenharmony_ci         * number of characters that would have been written, had the buffer
956e1051a39Sopenharmony_ci         * been large enough.)
957e1051a39Sopenharmony_ci         */
958e1051a39Sopenharmony_ci        return -1;
959e1051a39Sopenharmony_ci    return (retlen <= INT_MAX) ? (int)retlen : -1;
960e1051a39Sopenharmony_ci}
961