Line data Source code
1 : /* estream-printf.c - Versatile mostly C-99 compliant printf formatting
2 : * Copyright (C) 2007, 2008, 2009, 2010, 2012, 2014 g10 Code GmbH
3 : *
4 : * This file is part of Libestream.
5 : *
6 : * Libestream is free software; you can redistribute it and/or modify
7 : * it under the terms of the GNU Lesser General Public License as
8 : * published by the Free Software Foundation; either version 2.1 of
9 : * the License, or (at your option) any later version.
10 : *
11 : * Libestream is distributed in the hope that it will be useful, but
12 : * WITHOUT ANY WARRANTY; without even the implied warranty of
13 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 : * Lesser General Public License for more details.
15 : *
16 : * You should have received a copy of the GNU Lesser General Public
17 : * License along with Libestream; if not, see <https://www.gnu.org/licenses/>.
18 : *
19 : * ALTERNATIVELY, Libestream may be distributed under the terms of the
20 : * following license, in which case the provisions of this license are
21 : * required INSTEAD OF the GNU General Public License. If you wish to
22 : * allow use of your version of this file only under the terms of the
23 : * GNU General Public License, and not to allow others to use your
24 : * version of this file under the terms of the following license,
25 : * indicate your decision by deleting this paragraph and the license
26 : * below.
27 : *
28 : * Redistribution and use in source and binary forms, with or without
29 : * modification, are permitted provided that the following conditions
30 : * are met:
31 : * 1. Redistributions of source code must retain the above copyright
32 : * notice, and the entire permission notice in its entirety,
33 : * including the disclaimer of warranties.
34 : * 2. Redistributions in binary form must reproduce the above copyright
35 : * notice, this list of conditions and the following disclaimer in the
36 : * documentation and/or other materials provided with the distribution.
37 : * 3. The name of the author may not be used to endorse or promote
38 : * products derived from this software without specific prior
39 : * written permission.
40 : *
41 : * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
42 : * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
43 : * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
44 : * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
45 : * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
46 : * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
47 : * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49 : * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50 : * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51 : * OF THE POSSIBILITY OF SUCH DAMAGE.
52 : */
53 :
54 : /* Required autoconf tests:
55 :
56 : AC_TYPE_LONG_LONG_INT defines HAVE_LONG_LONG_INT
57 : AC_TYPE_LONG_DOUBLE defines HAVE_LONG_DOUBLE
58 : AC_TYPE_INTMAX_T defines HAVE_INTMAX_T
59 : AC_TYPE_UINTMAX_T defines HAVE_UINTMAX_T
60 : AC_CHECK_TYPES([ptrdiff_t]) defines HAVE_PTRDIFF_T
61 : AC_CHECK_SIZEOF([unsigned long]) defines SIZEOF_UNSIGNED_LONG
62 : AC_CHECK_SIZEOF([void *]) defines SIZEOF_VOID_P
63 : HAVE_LANGINFO_THOUSANDS_SEP
64 :
65 : Note that the file estream.m4 provides the autoconf macro
66 : ESTREAM_PRINTF_INIT which runs all required checks.
67 : See estream-printf.h for ways to tune this code.
68 :
69 : Missing stuff: wchar and wint_t
70 : thousands_sep in pr_float.
71 :
72 : */
73 :
74 : #ifdef HAVE_CONFIG_H
75 : # include <config.h>
76 : #endif
77 :
78 : #if defined(_WIN32) && !defined(HAVE_W32_SYSTEM)
79 : # define HAVE_W32_SYSTEM 1
80 : # if defined(__MINGW32CE__) && !defined (HAVE_W32CE_SYSTEM)
81 : # define HAVE_W32CE_SYSTEM
82 : # endif
83 : #endif
84 :
85 : #include <stdio.h>
86 : #include <stdlib.h>
87 : #include <string.h>
88 : #include <unistd.h>
89 : #include <stdarg.h>
90 : #include <errno.h>
91 : #include <stddef.h>
92 : #include <assert.h>
93 : #if defined(HAVE_INTMAX_T) || defined(HAVE_UINTMAX_T)
94 : # ifdef HAVE_STDINT_H
95 : # include <stdint.h>
96 : # endif
97 : #endif
98 : #ifdef HAVE_LANGINFO_THOUSANDS_SEP
99 : #include <langinfo.h>
100 : #endif
101 : #ifdef HAVE_W32CE_SYSTEM
102 : #include <gpg-error.h> /* ERRNO replacement. */
103 : #endif
104 : #ifdef _ESTREAM_PRINTF_EXTRA_INCLUDE
105 : # include _ESTREAM_PRINTF_EXTRA_INCLUDE
106 : #endif
107 : #include "estream-printf.h"
108 :
109 : /* #define DEBUG 1 */
110 :
111 :
112 : /* Allow redefinition of asprintf used realloc function. */
113 : #if defined(_ESTREAM_PRINTF_REALLOC)
114 : #define my_printf_realloc(a,b) _ESTREAM_PRINTF_REALLOC((a),(b))
115 : #else
116 : #define my_printf_realloc(a,b) fixed_realloc((a),(b))
117 : #endif
118 :
119 : /* A wrapper to set ERRNO. */
120 : #ifdef HAVE_W32CE_SYSTEM
121 : # define _set_errno(a) gpg_err_set_errno ((a))
122 : #else
123 : # define _set_errno(a) do { errno = (a); } while (0)
124 : #endif
125 :
126 :
127 : /* Calculate array dimension. */
128 : #ifndef DIM
129 : #define DIM(array) (sizeof (array) / sizeof (*array))
130 : #endif
131 :
132 :
133 : /* We allow for that many args without requiring malloced memory. */
134 : #define DEFAULT_MAX_ARGSPECS 5
135 :
136 : /* We allow for that many values without requiring malloced memory. */
137 : #define DEFAULT_MAX_VALUES 8
138 :
139 : /* We allocate this many new array argspec elements each time. */
140 : #define ARGSPECS_BUMP_VALUE 10
141 :
142 : /* Special values for the field width and the precision. */
143 : #define NO_FIELD_VALUE (-1)
144 : #define STAR_FIELD_VALUE (-2)
145 :
146 : /* Bit valuues used for the conversion flags. */
147 : #define FLAG_GROUPING 1
148 : #define FLAG_LEFT_JUST 2
149 : #define FLAG_PLUS_SIGN 4
150 : #define FLAG_SPACE_PLUS 8
151 : #define FLAG_ALT_CONV 16
152 : #define FLAG_ZERO_PAD 32
153 :
154 : /* Constants used the length modifiers. */
155 : typedef enum
156 : {
157 : LENMOD_NONE = 0,
158 : LENMOD_CHAR, /* "hh" */
159 : LENMOD_SHORT, /* "h" */
160 : LENMOD_LONG, /* "l" */
161 : LENMOD_LONGLONG, /* "ll" */
162 : LENMOD_INTMAX, /* "j" */
163 : LENMOD_SIZET, /* "z" */
164 : LENMOD_PTRDIFF, /* "t" */
165 : LENMOD_LONGDBL /* "L" */
166 : } lenmod_t;
167 :
168 : /* All the conversion specifiers. */
169 : typedef enum
170 : {
171 : CONSPEC_UNKNOWN = 0,
172 : CONSPEC_DECIMAL,
173 : CONSPEC_OCTAL,
174 : CONSPEC_UNSIGNED,
175 : CONSPEC_HEX,
176 : CONSPEC_HEX_UP,
177 : CONSPEC_FLOAT,
178 : CONSPEC_FLOAT_UP,
179 : CONSPEC_EXP,
180 : CONSPEC_EXP_UP,
181 : CONSPEC_F_OR_G,
182 : CONSPEC_F_OR_G_UP,
183 : CONSPEC_HEX_EXP,
184 : CONSPEC_HEX_EXP_UP,
185 : CONSPEC_CHAR,
186 : CONSPEC_STRING,
187 : CONSPEC_POINTER,
188 : CONSPEC_STRERROR,
189 : CONSPEC_BYTES_SO_FAR
190 : } conspec_t;
191 :
192 :
193 : /* Constants describing all the suppoorted types. Note that we list
194 : all the types we know about even if certain types are not available
195 : on this system. */
196 : typedef enum
197 : {
198 : VALTYPE_UNSUPPORTED = 0, /* Artificial type for error detection. */
199 : VALTYPE_CHAR,
200 : VALTYPE_SCHAR,
201 : VALTYPE_UCHAR,
202 : VALTYPE_SHORT,
203 : VALTYPE_USHORT,
204 : VALTYPE_INT,
205 : VALTYPE_UINT,
206 : VALTYPE_LONG,
207 : VALTYPE_ULONG,
208 : VALTYPE_LONGLONG,
209 : VALTYPE_ULONGLONG,
210 : VALTYPE_DOUBLE,
211 : VALTYPE_LONGDOUBLE,
212 : VALTYPE_STRING,
213 : VALTYPE_INTMAX,
214 : VALTYPE_UINTMAX,
215 : VALTYPE_SIZE,
216 : VALTYPE_PTRDIFF,
217 : VALTYPE_POINTER,
218 : VALTYPE_CHAR_PTR,
219 : VALTYPE_SCHAR_PTR,
220 : VALTYPE_SHORT_PTR,
221 : VALTYPE_INT_PTR,
222 : VALTYPE_LONG_PTR,
223 : VALTYPE_LONGLONG_PTR,
224 : VALTYPE_INTMAX_PTR,
225 : VALTYPE_SIZE_PTR,
226 : VALTYPE_PTRDIFF_PTR
227 : } valtype_t;
228 :
229 :
230 : /* A union used to store the actual values. */
231 : typedef union
232 : {
233 : char a_char;
234 : signed char a_schar;
235 : unsigned char a_uchar;
236 : short a_short;
237 : unsigned short a_ushort;
238 : int a_int;
239 : unsigned int a_uint;
240 : long int a_long;
241 : unsigned long int a_ulong;
242 : #ifdef HAVE_LONG_LONG_INT
243 : long long int a_longlong;
244 : unsigned long long int a_ulonglong;
245 : #endif
246 : double a_double;
247 : #ifdef HAVE_LONG_DOUBLE
248 : long double a_longdouble;
249 : #endif
250 : const char *a_string;
251 : #ifdef HAVE_INTMAX_T
252 : intmax_t a_intmax;
253 : #endif
254 : #ifdef HAVE_UINTMAX_T
255 : intmax_t a_uintmax;
256 : #endif
257 : size_t a_size;
258 : #ifdef HAVE_PTRDIFF_T
259 : ptrdiff_t a_ptrdiff;
260 : #endif
261 : void *a_void_ptr;
262 : char *a_char_ptr;
263 : signed char *a_schar_ptr;
264 : short *a_short_ptr;
265 : int *a_int_ptr;
266 : long *a_long_ptr;
267 : #ifdef HAVE_LONG_LONG_INT
268 : long long int *a_longlong_ptr;
269 : #endif
270 : #ifdef HAVE_INTMAX_T
271 : intmax_t *a_intmax_ptr;
272 : #endif
273 : size_t *a_size_ptr;
274 : #ifdef HAVE_PTRDIFF_T
275 : ptrdiff_t *a_ptrdiff_ptr;
276 : #endif
277 : } value_t;
278 :
279 : /* An object used to keep track of a format option and arguments. */
280 : struct argspec_s
281 : {
282 : size_t length; /* The length of these args including the percent. */
283 : unsigned int flags; /* The conversion flags (bits defined by FLAG_foo). */
284 : int width; /* The field width. */
285 : int precision; /* The precision. */
286 : lenmod_t lenmod; /* The length modifier. */
287 : conspec_t conspec; /* The conversion specifier. */
288 : int arg_pos; /* The position of the argument. This one may
289 : be -1 to indicate that no value is expected
290 : (e.g. for "%m"). */
291 : int width_pos; /* The position of the argument for a field
292 : width star's value. 0 for not used. */
293 : int precision_pos; /* The position of the argument for the a
294 : precision star's value. 0 for not used. */
295 : valtype_t vt; /* The type of the corresponding argument. */
296 : };
297 : typedef struct argspec_s *argspec_t;
298 :
299 : /* An object to build up a table of values and their types. */
300 : struct valueitem_s
301 : {
302 : valtype_t vt; /* The type of the value. */
303 : value_t value; /* The value. */
304 : };
305 : typedef struct valueitem_s *valueitem_t;
306 :
307 :
308 : /* Not all systems have a C-90 compliant realloc. To cope with this
309 : we use this simple wrapper. */
310 : #ifndef _ESTREAM_PRINTF_REALLOC
311 : static void *
312 : fixed_realloc (void *a, size_t n)
313 : {
314 : if (!a)
315 : return malloc (n);
316 :
317 : if (!n)
318 : {
319 : free (a);
320 : return NULL;
321 : }
322 :
323 : return realloc (a, n);
324 : }
325 : #endif /*!_ESTREAM_PRINTF_REALLOC*/
326 :
327 :
328 : #ifdef DEBUG
329 : static void
330 : dump_argspecs (argspec_t arg, size_t argcount)
331 : {
332 : int idx;
333 :
334 : for (idx=0; argcount; argcount--, arg++, idx++)
335 : fprintf (stderr,
336 : "%2d: len=%u flags=%u width=%d prec=%d mod=%d "
337 : "con=%d vt=%d pos=%d-%d-%d\n",
338 : idx,
339 : (unsigned int)arg->length,
340 : arg->flags,
341 : arg->width,
342 : arg->precision,
343 : arg->lenmod,
344 : arg->conspec,
345 : arg->vt,
346 : arg->arg_pos,
347 : arg->width_pos,
348 : arg->precision_pos);
349 : }
350 : #endif /*DEBUG*/
351 :
352 :
353 : /* Set the vt field for ARG. */
354 : static void
355 0 : compute_type (argspec_t arg)
356 : {
357 0 : switch (arg->conspec)
358 : {
359 : case CONSPEC_UNKNOWN:
360 0 : arg->vt = VALTYPE_UNSUPPORTED;
361 : break;
362 :
363 : case CONSPEC_DECIMAL:
364 0 : switch (arg->lenmod)
365 : {
366 0 : case LENMOD_CHAR: arg->vt = VALTYPE_SCHAR; break;
367 0 : case LENMOD_SHORT: arg->vt = VALTYPE_SHORT; break;
368 0 : case LENMOD_LONG: arg->vt = VALTYPE_LONG; break;
369 0 : case LENMOD_LONGLONG: arg->vt = VALTYPE_LONGLONG; break;
370 0 : case LENMOD_INTMAX: arg->vt = VALTYPE_INTMAX; break;
371 0 : case LENMOD_SIZET: arg->vt = VALTYPE_SIZE; break;
372 0 : case LENMOD_PTRDIFF: arg->vt = VALTYPE_PTRDIFF; break;
373 0 : default: arg->vt = VALTYPE_INT; break;
374 : }
375 : break;
376 :
377 : case CONSPEC_OCTAL:
378 : case CONSPEC_UNSIGNED:
379 : case CONSPEC_HEX:
380 : case CONSPEC_HEX_UP:
381 0 : switch (arg->lenmod)
382 : {
383 0 : case LENMOD_CHAR: arg->vt = VALTYPE_UCHAR; break;
384 0 : case LENMOD_SHORT: arg->vt = VALTYPE_USHORT; break;
385 0 : case LENMOD_LONG: arg->vt = VALTYPE_ULONG; break;
386 0 : case LENMOD_LONGLONG: arg->vt = VALTYPE_ULONGLONG; break;
387 0 : case LENMOD_INTMAX: arg->vt = VALTYPE_UINTMAX; break;
388 0 : case LENMOD_SIZET: arg->vt = VALTYPE_SIZE; break;
389 0 : case LENMOD_PTRDIFF: arg->vt = VALTYPE_PTRDIFF; break;
390 0 : default: arg->vt = VALTYPE_UINT; break;
391 : }
392 : break;
393 :
394 : case CONSPEC_FLOAT:
395 : case CONSPEC_FLOAT_UP:
396 : case CONSPEC_EXP:
397 : case CONSPEC_EXP_UP:
398 : case CONSPEC_F_OR_G:
399 : case CONSPEC_F_OR_G_UP:
400 : case CONSPEC_HEX_EXP:
401 : case CONSPEC_HEX_EXP_UP:
402 0 : switch (arg->lenmod)
403 : {
404 0 : case LENMOD_LONGDBL: arg->vt = VALTYPE_LONGDOUBLE; break;
405 0 : case LENMOD_LONG: arg->vt = VALTYPE_DOUBLE; break;
406 0 : default: arg->vt = VALTYPE_DOUBLE; break;
407 : }
408 : break;
409 :
410 : case CONSPEC_CHAR:
411 0 : arg->vt = VALTYPE_INT;
412 : break;
413 :
414 : case CONSPEC_STRING:
415 0 : arg->vt = VALTYPE_STRING;
416 : break;
417 :
418 : case CONSPEC_POINTER:
419 0 : arg->vt = VALTYPE_POINTER;
420 : break;
421 :
422 : case CONSPEC_STRERROR:
423 0 : arg->vt = VALTYPE_STRING;
424 : break;
425 :
426 : case CONSPEC_BYTES_SO_FAR:
427 0 : switch (arg->lenmod)
428 : {
429 0 : case LENMOD_CHAR: arg->vt = VALTYPE_SCHAR_PTR; break;
430 0 : case LENMOD_SHORT: arg->vt = VALTYPE_SHORT_PTR; break;
431 0 : case LENMOD_LONG: arg->vt = VALTYPE_LONG_PTR; break;
432 0 : case LENMOD_LONGLONG: arg->vt = VALTYPE_LONGLONG_PTR; break;
433 0 : case LENMOD_INTMAX: arg->vt = VALTYPE_INTMAX_PTR; break;
434 0 : case LENMOD_SIZET: arg->vt = VALTYPE_SIZE_PTR; break;
435 0 : case LENMOD_PTRDIFF: arg->vt = VALTYPE_PTRDIFF_PTR; break;
436 0 : default: arg->vt = VALTYPE_INT_PTR; break;
437 : }
438 : break;
439 :
440 : }
441 0 : }
442 :
443 :
444 :
445 : /* Parse the FORMAT string and populate the specification array stored
446 : at the address ARGSPECS_ADDR. The caller has provided enough space
447 : to store up to MAX_ARGSPECS in that buffer. The function may
448 : however ignore the provided buffer and malloc a larger one. On
449 : success the address of that larger buffer will be stored at
450 : ARGSPECS_ADDR. The actual number of specifications will be
451 : returned at R_ARGSPECS_COUNT. */
452 : static int
453 0 : parse_format (const char *format,
454 : argspec_t *argspecs_addr, size_t max_argspecs,
455 : size_t *r_argspecs_count)
456 : {
457 : const char *s;
458 0 : argspec_t argspecs = *argspecs_addr;
459 : argspec_t arg;
460 : size_t argcount = 0;
461 :
462 0 : if (!format)
463 : goto leave_einval;
464 :
465 0 : for (; *format; format++)
466 : {
467 : unsigned int flags;
468 : int width, precision;
469 : lenmod_t lenmod;
470 : conspec_t conspec;
471 : int arg_pos, width_pos, precision_pos;
472 :
473 0 : if (*format != '%')
474 0 : continue;
475 0 : s = ++format;
476 0 : if (!*s)
477 : goto leave_einval;
478 0 : if (*s == '%')
479 0 : continue; /* Just a quoted percent. */
480 :
481 : /* First check whether there is a positional argument. */
482 : arg_pos = 0; /* No positional argument given. */
483 0 : if (*s >= '1' && *s <= '9')
484 : {
485 : const char *save_s = s;
486 :
487 0 : arg_pos = (*s++ - '0');
488 0 : for (; *s >= '0' && *s <= '9'; s++)
489 0 : arg_pos = 10*arg_pos + (*s - '0');
490 0 : if (arg_pos < 0)
491 : goto leave_einval; /* Overflow during conversion. */
492 0 : if (*s == '$')
493 0 : s++;
494 : else
495 : {
496 : arg_pos = 0;
497 : s = save_s;
498 : }
499 : }
500 :
501 : /* Parse the flags. */
502 : flags = 0;
503 0 : for ( ; *s; s++)
504 : {
505 0 : switch (*s)
506 : {
507 0 : case '\'': flags |= FLAG_GROUPING; break;
508 0 : case '-': flags |= FLAG_LEFT_JUST; break;
509 0 : case '+': flags |= FLAG_PLUS_SIGN; break;
510 0 : case ' ': flags |= FLAG_SPACE_PLUS; break;
511 0 : case '#': flags |= FLAG_ALT_CONV; break;
512 0 : case '0': flags |= FLAG_ZERO_PAD; break;
513 : default:
514 : goto flags_parsed;
515 : }
516 : }
517 : flags_parsed:
518 :
519 : /* Parse the field width. */
520 : width_pos = 0;
521 0 : if (*s == '*')
522 : {
523 : width = STAR_FIELD_VALUE;
524 0 : s++;
525 : /* If we have a positional argument, another one might also
526 : be used to give the position of the star's value. */
527 0 : if (arg_pos && *s >= '1' && *s <= '9')
528 : {
529 0 : width_pos = (*s++ - '0');
530 0 : for (; *s >= '0' && *s <= '9'; s++)
531 0 : width_pos = 10*width_pos + (*s - '0');
532 0 : if (width_pos < 1)
533 : goto leave_einval; /* Overflow during conversion. */
534 0 : if (*s != '$')
535 : goto leave_einval; /* Not followed by $. */
536 0 : s++;
537 : }
538 : }
539 0 : else if ( *s >= '0' && *s <= '9')
540 : {
541 0 : width = (*s++ - '0');
542 0 : for (; *s >= '0' && *s <= '9'; s++)
543 : {
544 0 : if (!width && *s == '0')
545 : goto leave_einval; /* Leading zeroes are not allowed.
546 : Fixme: check what other
547 : implementations do. */
548 0 : width = 10*width + (*s - '0');
549 : }
550 0 : if (width < 0)
551 : goto leave_einval; /* Overflow during conversion. */
552 : }
553 : else
554 : width = NO_FIELD_VALUE;
555 :
556 : /* Parse the precision. */
557 : precision_pos = 0;
558 : precision = NO_FIELD_VALUE;
559 0 : if (*s == '.')
560 : {
561 0 : int ignore_value = (s[1] == '-');
562 :
563 0 : s++;
564 0 : if (*s == '*')
565 : {
566 : precision = STAR_FIELD_VALUE;
567 0 : s++;
568 : /* If we have a positional argument, another one might also
569 : be used to give the position of the star's value. */
570 0 : if (arg_pos && *s >= '1' && *s <= '9')
571 : {
572 0 : precision_pos = (*s++ - '0');
573 0 : for (; *s >= '0' && *s <= '9'; s++)
574 0 : precision_pos = 10*precision_pos + (*s - '0');
575 0 : if (precision_pos < 1)
576 : goto leave_einval; /* Overflow during conversion. */
577 0 : if (*s != '$')
578 : goto leave_einval; /* Not followed by $. */
579 0 : s++;
580 : }
581 : }
582 0 : else if ( *s >= '0' && *s <= '9')
583 : {
584 0 : precision = (*s++ - '0');
585 0 : for (; *s >= '0' && *s <= '9'; s++)
586 : {
587 0 : if (!precision && *s == '0')
588 : goto leave_einval; /* Leading zeroes are not allowed.
589 : Fixme: check what other
590 : implementations do. */
591 0 : precision = 10*precision + (*s - '0');
592 : }
593 0 : if (precision < 0)
594 : goto leave_einval; /* Overflow during conversion. */
595 : }
596 : else
597 : precision = 0;
598 0 : if (ignore_value)
599 : precision = NO_FIELD_VALUE;
600 : }
601 :
602 : /* Parse the length modifiers. */
603 0 : switch (*s)
604 : {
605 : case 'h':
606 0 : if (s[1] == 'h')
607 : {
608 : lenmod = LENMOD_CHAR;
609 0 : s++;
610 : }
611 : else
612 : lenmod = LENMOD_SHORT;
613 0 : s++;
614 0 : break;
615 : case 'l':
616 0 : if (s[1] == 'l')
617 : {
618 : lenmod = LENMOD_LONGLONG;
619 0 : s++;
620 : }
621 : else
622 : lenmod = LENMOD_LONG;
623 0 : s++;
624 0 : break;
625 0 : case 'j': lenmod = LENMOD_INTMAX; s++; break;
626 0 : case 'z': lenmod = LENMOD_SIZET; s++; break;
627 0 : case 't': lenmod = LENMOD_PTRDIFF; s++; break;
628 0 : case 'L': lenmod = LENMOD_LONGDBL; s++; break;
629 : default: lenmod = LENMOD_NONE; break;
630 : }
631 :
632 : /* Parse the conversion specifier. */
633 0 : switch (*s)
634 : {
635 : case 'd':
636 : case 'i': conspec = CONSPEC_DECIMAL; break;
637 0 : case 'o': conspec = CONSPEC_OCTAL; break;
638 0 : case 'u': conspec = CONSPEC_UNSIGNED; break;
639 0 : case 'x': conspec = CONSPEC_HEX; break;
640 0 : case 'X': conspec = CONSPEC_HEX_UP; break;
641 0 : case 'f': conspec = CONSPEC_FLOAT; break;
642 0 : case 'F': conspec = CONSPEC_FLOAT_UP; break;
643 0 : case 'e': conspec = CONSPEC_EXP; break;
644 0 : case 'E': conspec = CONSPEC_EXP_UP; break;
645 0 : case 'g': conspec = CONSPEC_F_OR_G; break;
646 0 : case 'G': conspec = CONSPEC_F_OR_G_UP; break;
647 0 : case 'a': conspec = CONSPEC_HEX_EXP; break;
648 0 : case 'A': conspec = CONSPEC_HEX_EXP_UP; break;
649 0 : case 'c': conspec = CONSPEC_CHAR; break;
650 0 : case 's': conspec = CONSPEC_STRING; break;
651 0 : case 'p': conspec = CONSPEC_POINTER; break;
652 0 : case 'n': conspec = CONSPEC_BYTES_SO_FAR; break;
653 0 : case 'C': conspec = CONSPEC_CHAR; lenmod = LENMOD_LONG; break;
654 0 : case 'S': conspec = CONSPEC_STRING; lenmod = LENMOD_LONG; break;
655 0 : case 'm': conspec = CONSPEC_STRERROR; arg_pos = -1; break;
656 : default: conspec = CONSPEC_UNKNOWN;
657 : }
658 :
659 : /* Save the args. */
660 0 : if (argcount >= max_argspecs)
661 : {
662 : /* We either need to allocate a new array instead of the
663 : caller provided one or realloc the array. Instead of
664 : using realloc we allocate a new one and release the
665 : original one then. */
666 : size_t n, newmax;
667 : argspec_t newarg;
668 :
669 0 : newmax = max_argspecs + ARGSPECS_BUMP_VALUE;
670 0 : if (newmax <= max_argspecs)
671 : goto leave_einval; /* Too many arguments. */
672 0 : newarg = calloc (newmax, sizeof *newarg);
673 0 : if (!newarg)
674 : goto leave;
675 0 : for (n=0; n < argcount; n++)
676 0 : newarg[n] = argspecs[n];
677 0 : if (argspecs != *argspecs_addr)
678 0 : free (argspecs);
679 : argspecs = newarg;
680 : max_argspecs = newmax;
681 : }
682 :
683 0 : arg = argspecs + argcount;
684 0 : arg->length = s - format + 2;
685 0 : arg->flags = flags;
686 0 : arg->width = width;
687 0 : arg->precision = precision;
688 0 : arg->lenmod = lenmod;
689 0 : arg->conspec = conspec;
690 0 : arg->arg_pos = arg_pos;
691 0 : arg->width_pos = width_pos;
692 0 : arg->precision_pos = precision_pos;
693 0 : compute_type (arg);
694 0 : argcount++;
695 : format = s;
696 : }
697 :
698 0 : *argspecs_addr = argspecs;
699 0 : *r_argspecs_count = argcount;
700 0 : return 0; /* Success. */
701 :
702 : leave_einval:
703 0 : _set_errno (EINVAL);
704 : leave:
705 0 : if (argspecs != *argspecs_addr)
706 0 : free (argspecs);
707 0 : *argspecs_addr = NULL;
708 0 : return -1;
709 : }
710 :
711 :
712 : /* This function reads all the values as specified by VALUETABLE into
713 : VALUETABLE. The values are expected in VAARGS. The function
714 : returns -1 if a specified type is not supported. */
715 : static int
716 0 : read_values (valueitem_t valuetable, size_t valuetable_len, va_list vaargs)
717 : {
718 : int validx;
719 :
720 0 : for (validx=0; validx < valuetable_len; validx++)
721 : {
722 0 : value_t *value = &valuetable[validx].value;
723 0 : valtype_t vt = valuetable[validx].vt;
724 :
725 0 : switch (vt)
726 : {
727 0 : case VALTYPE_CHAR: value->a_char = va_arg (vaargs, int); break;
728 : case VALTYPE_CHAR_PTR:
729 0 : value->a_char_ptr = va_arg (vaargs, char *);
730 0 : break;
731 0 : case VALTYPE_SCHAR: value->a_schar = va_arg (vaargs, int); break;
732 : case VALTYPE_SCHAR_PTR:
733 0 : value->a_schar_ptr = va_arg (vaargs, signed char *);
734 0 : break;
735 0 : case VALTYPE_UCHAR: value->a_uchar = va_arg (vaargs, int); break;
736 0 : case VALTYPE_SHORT: value->a_short = va_arg (vaargs, int); break;
737 0 : case VALTYPE_USHORT: value->a_ushort = va_arg (vaargs, int); break;
738 : case VALTYPE_SHORT_PTR:
739 0 : value->a_short_ptr = va_arg (vaargs, short *);
740 0 : break;
741 : case VALTYPE_INT:
742 0 : value->a_int = va_arg (vaargs, int);
743 0 : break;
744 : case VALTYPE_INT_PTR:
745 0 : value->a_int_ptr = va_arg (vaargs, int *);
746 0 : break;
747 : case VALTYPE_UINT:
748 0 : value->a_uint = va_arg (vaargs, unsigned int);
749 0 : break;
750 : case VALTYPE_LONG:
751 0 : value->a_long = va_arg (vaargs, long);
752 0 : break;
753 : case VALTYPE_ULONG:
754 0 : value->a_ulong = va_arg (vaargs, unsigned long);
755 0 : break;
756 : case VALTYPE_LONG_PTR:
757 0 : value->a_long_ptr = va_arg (vaargs, long *);
758 0 : break;
759 : #ifdef HAVE_LONG_LONG_INT
760 : case VALTYPE_LONGLONG:
761 0 : value->a_longlong = va_arg (vaargs, long long int);
762 0 : break;
763 : case VALTYPE_ULONGLONG:
764 0 : value->a_ulonglong = va_arg (vaargs, unsigned long long int);
765 0 : break;
766 : case VALTYPE_LONGLONG_PTR:
767 0 : value->a_longlong_ptr = va_arg (vaargs, long long *);
768 0 : break;
769 : #endif
770 : case VALTYPE_DOUBLE:
771 0 : value->a_double = va_arg (vaargs, double);
772 0 : break;
773 : #ifdef HAVE_LONG_DOUBLE
774 : case VALTYPE_LONGDOUBLE:
775 0 : value->a_longdouble = va_arg (vaargs, long double);
776 0 : break;
777 : #endif
778 : case VALTYPE_STRING:
779 0 : value->a_string = va_arg (vaargs, const char *);
780 0 : break;
781 : case VALTYPE_POINTER:
782 0 : value->a_void_ptr = va_arg (vaargs, void *);
783 0 : break;
784 : #ifdef HAVE_INTMAX_T
785 : case VALTYPE_INTMAX:
786 0 : value->a_intmax = va_arg (vaargs, intmax_t);
787 0 : break;
788 : case VALTYPE_INTMAX_PTR:
789 0 : value->a_intmax_ptr = va_arg (vaargs, intmax_t *);
790 0 : break;
791 : #endif
792 : #ifdef HAVE_UINTMAX_T
793 : case VALTYPE_UINTMAX:
794 0 : value->a_uintmax = va_arg (vaargs, uintmax_t);
795 0 : break;
796 : #endif
797 : case VALTYPE_SIZE:
798 0 : value->a_size = va_arg (vaargs, size_t);
799 0 : break;
800 : case VALTYPE_SIZE_PTR:
801 0 : value->a_size_ptr = va_arg (vaargs, size_t *);
802 0 : break;
803 : #ifdef HAVE_PTRDIFF_T
804 : case VALTYPE_PTRDIFF:
805 0 : value->a_ptrdiff = va_arg (vaargs, ptrdiff_t);
806 0 : break;
807 : case VALTYPE_PTRDIFF_PTR:
808 0 : value->a_ptrdiff_ptr = va_arg (vaargs, ptrdiff_t *);
809 0 : break;
810 : #endif
811 : default: /* Unsupported type. */
812 : return -1;
813 : }
814 : }
815 : return 0;
816 : }
817 :
818 :
819 :
820 : /* Output COUNT padding characters PADCHAR and update NBYTES by the
821 : number of bytes actually written. */
822 : static int
823 0 : pad_out (estream_printf_out_t outfnc, void *outfncarg,
824 : int padchar, int count, size_t *nbytes)
825 : {
826 : char buf[32];
827 : size_t n;
828 : int rc;
829 :
830 0 : while (count > 0)
831 : {
832 0 : n = (count <= sizeof buf)? count : sizeof buf;
833 0 : memset (buf, padchar, n);
834 0 : rc = outfnc (outfncarg, buf, n);
835 0 : if (rc)
836 : return rc;
837 0 : *nbytes += n;
838 0 : count -= n;
839 : }
840 :
841 : return 0;
842 : }
843 :
844 :
845 : /* "d,i,o,u,x,X" formatting. OUTFNC and OUTFNCARG describes the
846 : output routine, ARG gives the argument description and VALUE the
847 : actual value (its type is available through arg->vt). */
848 : static int
849 0 : pr_integer (estream_printf_out_t outfnc, void *outfncarg,
850 : argspec_t arg, value_t value, size_t *nbytes)
851 : {
852 : int rc;
853 : #ifdef HAVE_LONG_LONG_INT
854 : unsigned long long aulong;
855 : #else
856 : unsigned long aulong;
857 : #endif
858 : char numbuf[100];
859 : char *p, *pend;
860 : size_t n;
861 0 : char signchar = 0;
862 : int n_prec; /* Number of extra precision digits required. */
863 : int n_extra; /* Extra number of prefix or sign characters. */
864 :
865 0 : if (arg->conspec == CONSPEC_DECIMAL)
866 : {
867 : #ifdef HAVE_LONG_LONG_INT
868 : long long along;
869 : #else
870 : long along;
871 : #endif
872 :
873 0 : switch (arg->vt)
874 : {
875 0 : case VALTYPE_SHORT: along = value.a_short; break;
876 0 : case VALTYPE_INT: along = value.a_int; break;
877 0 : case VALTYPE_LONG: along = value.a_long; break;
878 : #ifdef HAVE_LONG_LONG_INT
879 0 : case VALTYPE_LONGLONG: along = value.a_longlong; break;
880 0 : case VALTYPE_SIZE: along = value.a_size; break;
881 : # ifdef HAVE_INTMAX_T
882 0 : case VALTYPE_INTMAX: along = value.a_intmax; break;
883 : # endif
884 : # ifdef HAVE_PTRDIFF_T
885 0 : case VALTYPE_PTRDIFF: along = value.a_ptrdiff; break;
886 : # endif
887 : #endif /*HAVE_LONG_LONG_INT*/
888 : default:
889 : return -1;
890 : }
891 0 : if (along < 0)
892 : {
893 0 : aulong = -along;
894 0 : signchar = '-';
895 : }
896 : else
897 0 : aulong = along;
898 : }
899 : else
900 : {
901 0 : switch (arg->vt)
902 : {
903 0 : case VALTYPE_USHORT: aulong = value.a_ushort; break;
904 0 : case VALTYPE_UINT: aulong = value.a_uint; break;
905 0 : case VALTYPE_ULONG: aulong = value.a_ulong; break;
906 : #ifdef HAVE_LONG_LONG_INT
907 0 : case VALTYPE_ULONGLONG: aulong = value.a_ulonglong; break;
908 0 : case VALTYPE_SIZE: aulong = value.a_size; break;
909 : # ifdef HAVE_UINTMAX_T
910 0 : case VALTYPE_UINTMAX: aulong = value.a_uintmax; break;
911 : # endif
912 : # ifdef HAVE_PTRDIFF_T
913 0 : case VALTYPE_PTRDIFF: aulong = value.a_ptrdiff; break;
914 : # endif
915 : #endif /*HAVE_LONG_LONG_INT*/
916 : default:
917 : return -1;
918 : }
919 : }
920 :
921 0 : if (signchar == '-')
922 : ;
923 0 : else if ((arg->flags & FLAG_PLUS_SIGN))
924 0 : signchar = '+';
925 0 : else if ((arg->flags & FLAG_SPACE_PLUS))
926 0 : signchar = ' ';
927 :
928 0 : n_extra = !!signchar;
929 :
930 : /* We build the string up backwards. */
931 : p = pend = numbuf + DIM(numbuf);
932 0 : if ((!aulong && !arg->precision))
933 : ;
934 0 : else if (arg->conspec == CONSPEC_DECIMAL
935 0 : || arg->conspec == CONSPEC_UNSIGNED)
936 : {
937 : int grouping = -1;
938 0 : const char * grouping_string =
939 : #ifdef HAVE_LANGINFO_THOUSANDS_SEP
940 : nl_langinfo(THOUSANDS_SEP);
941 : #else
942 : "'";
943 : #endif
944 :
945 : do
946 : {
947 0 : if ((arg->flags & FLAG_GROUPING)
948 0 : && (++grouping == 3) && *grouping_string)
949 : {
950 0 : *--p = *grouping_string;
951 : grouping = 0;
952 : }
953 0 : *--p = '0' + (aulong % 10);
954 0 : aulong /= 10;
955 : }
956 0 : while (aulong);
957 : }
958 0 : else if (arg->conspec == CONSPEC_OCTAL)
959 : {
960 : do
961 : {
962 0 : *--p = '0' + (aulong % 8);
963 0 : aulong /= 8;
964 : }
965 0 : while (aulong);
966 0 : if ((arg->flags & FLAG_ALT_CONV) && *p != '0')
967 0 : *--p = '0';
968 : }
969 : else /* HEX or HEXUP */
970 : {
971 0 : const char *digits = ((arg->conspec == CONSPEC_HEX)
972 : ? "0123456789abcdef" : "0123456789ABCDEF");
973 : do
974 : {
975 0 : *--p = digits[(aulong % 16)];
976 0 : aulong /= 16;
977 : }
978 0 : while (aulong);
979 0 : if ((arg->flags & FLAG_ALT_CONV))
980 0 : n_extra += 2;
981 : }
982 :
983 0 : n = pend - p;
984 :
985 0 : if ((arg->flags & FLAG_ZERO_PAD)
986 0 : && arg->precision == NO_FIELD_VALUE && !(arg->flags & FLAG_LEFT_JUST)
987 0 : && n && arg->width - n_extra > n )
988 0 : n_prec = arg->width - n_extra - n;
989 0 : else if (arg->precision > 0 && arg->precision > n)
990 0 : n_prec = arg->precision - n;
991 : else
992 : n_prec = 0;
993 :
994 0 : if (!(arg->flags & FLAG_LEFT_JUST)
995 0 : && arg->width >= 0 && arg->width - n_extra > n
996 0 : && arg->width - n_extra - n >= n_prec )
997 : {
998 0 : rc = pad_out (outfnc, outfncarg, ' ',
999 0 : arg->width - n_extra - n - n_prec, nbytes);
1000 0 : if (rc)
1001 : return rc;
1002 : }
1003 :
1004 0 : if (signchar)
1005 : {
1006 0 : rc = outfnc (outfncarg, &signchar, 1);
1007 0 : if (rc)
1008 : return rc;
1009 0 : *nbytes += 1;
1010 : }
1011 :
1012 0 : if ((arg->flags & FLAG_ALT_CONV)
1013 0 : && (arg->conspec == CONSPEC_HEX || arg->conspec == CONSPEC_HEX_UP))
1014 : {
1015 0 : rc = outfnc (outfncarg, arg->conspec == CONSPEC_HEX? "0x": "0X", 2);
1016 0 : if (rc)
1017 : return rc;
1018 0 : *nbytes += 2;
1019 : }
1020 :
1021 0 : if (n_prec)
1022 : {
1023 0 : rc = pad_out (outfnc, outfncarg, '0', n_prec, nbytes);
1024 0 : if (rc)
1025 : return rc;
1026 : }
1027 :
1028 0 : rc = outfnc (outfncarg, p, pend - p);
1029 0 : if (rc)
1030 : return rc;
1031 0 : *nbytes += pend - p;
1032 :
1033 0 : if ((arg->flags & FLAG_LEFT_JUST)
1034 0 : && arg->width >= 0 && arg->width - n_extra - n_prec > n)
1035 : {
1036 0 : rc = pad_out (outfnc, outfncarg, ' ',
1037 0 : arg->width - n_extra - n_prec - n, nbytes);
1038 0 : if (rc)
1039 : return rc;
1040 : }
1041 :
1042 : return 0;
1043 : }
1044 :
1045 :
1046 : /* "e,E,f,F,g,G,a,A" formatting. OUTFNC and OUTFNCARG describes the
1047 : output routine, ARG gives the argument description and VALUE the
1048 : actual value (its type is available through arg->vt). For
1049 : portability reasons sprintf is used for the actual formatting.
1050 : This is useful because sprint is the only standard function to
1051 : convert a floating number into its ascii representation. To avoid
1052 : using malloc we just pass the precision to sprintf and do the final
1053 : formatting with our own code. */
1054 : static int
1055 0 : pr_float (estream_printf_out_t outfnc, void *outfncarg,
1056 : argspec_t arg, value_t value, size_t *nbytes)
1057 : {
1058 : int rc;
1059 : #ifdef HAVE_LONG_DOUBLE
1060 : long double adblfloat = 0; /* Just to please gcc. */
1061 : int use_dbl = 0;
1062 : #endif
1063 : double afloat;
1064 : char numbuf[350];
1065 : char formatstr[20];
1066 : char *p, *pend;
1067 : size_t n;
1068 0 : char signchar = 0;
1069 : int n_extra; /* Extra number of prefix or sign characters. */
1070 :
1071 0 : switch (arg->vt)
1072 : {
1073 0 : case VALTYPE_DOUBLE: afloat = value.a_double; break;
1074 : #ifdef HAVE_LONG_DOUBLE
1075 : case VALTYPE_LONGDOUBLE:
1076 : afloat = 0; /* Just to please gcc. */
1077 0 : adblfloat = value.a_longdouble;
1078 0 : use_dbl=1; break;
1079 : #endif
1080 : default:
1081 : return -1;
1082 : }
1083 :
1084 : /* We build the string using sprint. */
1085 : p = formatstr + sizeof formatstr;
1086 0 : *--p = 0;
1087 0 : switch (arg->conspec)
1088 : {
1089 0 : case CONSPEC_FLOAT: *--p = 'f'; break;
1090 0 : case CONSPEC_FLOAT_UP: *--p = 'F'; break;
1091 0 : case CONSPEC_EXP: *--p = 'e'; break;
1092 0 : case CONSPEC_EXP_UP: *--p = 'E'; break;
1093 0 : case CONSPEC_F_OR_G: *--p = 'g'; break;
1094 0 : case CONSPEC_F_OR_G_UP: *--p = 'G'; break;
1095 0 : case CONSPEC_HEX_EXP: *--p = 'a'; break;
1096 0 : case CONSPEC_HEX_EXP_UP: *--p = 'A'; break;
1097 : default:
1098 : return -1; /* Actually a bug. */
1099 : }
1100 : #ifdef HAVE_LONG_DOUBLE
1101 0 : if (use_dbl)
1102 0 : *--p = 'L';
1103 : #endif
1104 0 : if (arg->precision != NO_FIELD_VALUE)
1105 : {
1106 : /* Limit it to a meaningful value so that even a stupid sprintf
1107 : won't overflow our buffer. */
1108 0 : n = arg->precision <= 100? arg->precision : 100;
1109 : do
1110 : {
1111 0 : *--p = '0' + (n % 10);
1112 0 : n /= 10;
1113 : }
1114 0 : while (n);
1115 0 : *--p = '.';
1116 : }
1117 0 : if ((arg->flags & FLAG_ALT_CONV))
1118 0 : *--p = '#';
1119 0 : *--p = '%';
1120 : #ifdef HAVE_LONG_DOUBLE
1121 0 : if (use_dbl)
1122 0 : sprintf (numbuf, p, adblfloat);
1123 : else
1124 : #endif /*HAVE_LONG_DOUBLE*/
1125 0 : sprintf (numbuf, p, afloat);
1126 : p = numbuf;
1127 0 : n = strlen (numbuf);
1128 0 : pend = p + n;
1129 :
1130 0 : if (*p =='-')
1131 : {
1132 0 : signchar = '-';
1133 : p++;
1134 0 : n--;
1135 : }
1136 0 : else if ((arg->flags & FLAG_PLUS_SIGN))
1137 0 : signchar = '+';
1138 0 : else if ((arg->flags & FLAG_SPACE_PLUS))
1139 0 : signchar = ' ';
1140 :
1141 0 : n_extra = !!signchar;
1142 :
1143 0 : if (!(arg->flags & FLAG_LEFT_JUST)
1144 0 : && arg->width >= 0 && arg->width - n_extra > n)
1145 : {
1146 0 : rc = pad_out (outfnc, outfncarg, ' ', arg->width - n_extra - n, nbytes);
1147 0 : if (rc)
1148 : return rc;
1149 : }
1150 :
1151 0 : if (signchar)
1152 : {
1153 0 : rc = outfnc (outfncarg, &signchar, 1);
1154 0 : if (rc)
1155 : return rc;
1156 0 : *nbytes += 1;
1157 : }
1158 :
1159 0 : rc = outfnc (outfncarg, p, pend - p);
1160 0 : if (rc)
1161 : return rc;
1162 0 : *nbytes += pend - p;
1163 :
1164 0 : if ((arg->flags & FLAG_LEFT_JUST)
1165 0 : && arg->width >= 0 && arg->width - n_extra > n)
1166 : {
1167 0 : rc = pad_out (outfnc, outfncarg, ' ', arg->width - n_extra - n, nbytes);
1168 0 : if (rc)
1169 : return rc;
1170 : }
1171 :
1172 : return 0;
1173 : }
1174 :
1175 :
1176 : /* "c" formatting. */
1177 : static int
1178 : pr_char (estream_printf_out_t outfnc, void *outfncarg,
1179 : argspec_t arg, value_t value, size_t *nbytes)
1180 : {
1181 : int rc;
1182 : char buf[1];
1183 :
1184 0 : if (arg->vt != VALTYPE_INT)
1185 : return -1;
1186 0 : buf[0] = (unsigned int)value.a_int;
1187 0 : rc = outfnc (outfncarg, buf, 1);
1188 0 : if(rc)
1189 : return rc;
1190 0 : *nbytes += 1;
1191 :
1192 : return 0;
1193 : }
1194 :
1195 :
1196 : /* "s" formatting. */
1197 : static int
1198 0 : pr_string (estream_printf_out_t outfnc, void *outfncarg,
1199 : argspec_t arg, value_t value, size_t *nbytes)
1200 : {
1201 : int rc;
1202 : size_t n;
1203 : const char *string, *s;
1204 :
1205 0 : if (arg->vt != VALTYPE_STRING)
1206 : return -1;
1207 0 : string = value.a_string;
1208 0 : if (!string)
1209 : string = "(null)";
1210 0 : if (arg->precision >= 0)
1211 : {
1212 : /* Test for nul after N so that we can pass a non-nul terminated
1213 : string. */
1214 0 : for (n=0,s=string; n < arg->precision && *s; s++)
1215 0 : n++;
1216 : }
1217 : else
1218 0 : n = strlen (string);
1219 :
1220 0 : if (!(arg->flags & FLAG_LEFT_JUST)
1221 0 : && arg->width >= 0 && arg->width > n )
1222 : {
1223 0 : rc = pad_out (outfnc, outfncarg, ' ', arg->width - n, nbytes);
1224 0 : if (rc)
1225 : return rc;
1226 : }
1227 :
1228 0 : rc = outfnc (outfncarg, string, n);
1229 0 : if (rc)
1230 : return rc;
1231 0 : *nbytes += n;
1232 :
1233 0 : if ((arg->flags & FLAG_LEFT_JUST)
1234 0 : && arg->width >= 0 && arg->width > n)
1235 : {
1236 0 : rc = pad_out (outfnc, outfncarg, ' ', arg->width - n, nbytes);
1237 0 : if (rc)
1238 : return rc;
1239 : }
1240 :
1241 : return 0;
1242 : }
1243 :
1244 :
1245 : /* "p" formatting. */
1246 : static int
1247 0 : pr_pointer (estream_printf_out_t outfnc, void *outfncarg,
1248 : argspec_t arg, value_t value, size_t *nbytes)
1249 : {
1250 : int rc;
1251 : #if defined(HAVE_LONG_LONG_INT) && (SIZEOF_UNSIGNED_LONG < SIZEOF_VOID_P)
1252 : unsigned long long aulong;
1253 : #else
1254 : unsigned long aulong;
1255 : #endif
1256 : char numbuf[100];
1257 : char *p, *pend;
1258 :
1259 0 : if (arg->vt != VALTYPE_POINTER)
1260 : return -1;
1261 : /* We assume that a pointer can be converted to an unsigned long.
1262 : That is not correct for a 64 bit Windows, but then we assume that
1263 : long long is supported and usable for storing a pointer. */
1264 : #if defined(HAVE_LONG_LONG_INT) && (SIZEOF_UNSIGNED_LONG < SIZEOF_VOID_P)
1265 : aulong = (unsigned long long)value.a_void_ptr;
1266 : #else
1267 0 : aulong = (unsigned long)value.a_void_ptr;
1268 : #endif
1269 :
1270 : p = pend = numbuf + DIM(numbuf);
1271 : do
1272 : {
1273 0 : *--p = "0123456789abcdefx"[(aulong % 16)];
1274 0 : aulong /= 16;
1275 : }
1276 0 : while (aulong);
1277 0 : while ((pend-p) < 2*sizeof (aulong))
1278 0 : *--p = '0';
1279 0 : *--p = 'x';
1280 0 : *--p = '0';
1281 :
1282 0 : rc = outfnc (outfncarg, p, pend - p);
1283 0 : if (rc)
1284 : return rc;
1285 0 : *nbytes += pend - p;
1286 :
1287 : return 0;
1288 : }
1289 :
1290 : /* "n" pesudo format operation. */
1291 : static int
1292 0 : pr_bytes_so_far (estream_printf_out_t outfnc, void *outfncarg,
1293 : argspec_t arg, value_t value, size_t *nbytes)
1294 : {
1295 : (void)outfnc;
1296 : (void)outfncarg;
1297 :
1298 0 : switch (arg->vt)
1299 : {
1300 : case VALTYPE_SCHAR_PTR:
1301 0 : *value.a_schar_ptr = (signed char)(unsigned int)(*nbytes);
1302 : break;
1303 : case VALTYPE_SHORT_PTR:
1304 0 : *value.a_short_ptr = (short)(unsigned int)(*nbytes);
1305 : break;
1306 : case VALTYPE_LONG_PTR:
1307 0 : *value.a_long_ptr = (long)(*nbytes);
1308 : break;
1309 : #ifdef HAVE_LONG_LONG_INT
1310 : case VALTYPE_LONGLONG_PTR:
1311 0 : *value.a_longlong_ptr = (long long)(*nbytes);
1312 : break;
1313 : #endif
1314 : #ifdef HAVE_INTMAX_T
1315 : case VALTYPE_INTMAX_PTR:
1316 0 : *value.a_intmax_ptr = (intmax_t)(*nbytes);
1317 : break;
1318 : #endif
1319 : case VALTYPE_SIZE_PTR:
1320 0 : *value.a_size_ptr = (*nbytes);
1321 : break;
1322 : #ifdef HAVE_PTRDIFF_T
1323 : case VALTYPE_PTRDIFF_PTR:
1324 0 : *value.a_ptrdiff_ptr = (ptrdiff_t)(*nbytes);
1325 : break;
1326 : #endif
1327 : case VALTYPE_INT_PTR:
1328 0 : *value.a_int_ptr = (int)(*nbytes);
1329 : break;
1330 : default:
1331 : return -1; /* An unsupported type has been used. */
1332 : }
1333 :
1334 : return 0;
1335 : }
1336 :
1337 :
1338 :
1339 : /* Run the actual formatting. OUTFNC and OUTFNCARG are the output
1340 : functions. FORMAT is format string ARGSPECS is the parsed format
1341 : string, ARGSPECS_LEN the number of items in ARGSPECS. VALUETABLE
1342 : holds the values and may be directly addressed using the position
1343 : arguments given by ARGSPECS. MYERRNO is used for the "%m"
1344 : conversion. NBYTES well be updated to reflect the number of bytes
1345 : send to the output function. */
1346 : static int
1347 0 : do_format (estream_printf_out_t outfnc, void *outfncarg,
1348 : const char *format, argspec_t argspecs, size_t argspecs_len,
1349 : valueitem_t valuetable, int myerrno, size_t *nbytes)
1350 : {
1351 : int rc = 0;
1352 : const char *s;
1353 : argspec_t arg = argspecs;
1354 : int argidx = 0; /* Only used for assertion. */
1355 : size_t n;
1356 : value_t value;
1357 :
1358 : s = format;
1359 0 : while ( *s )
1360 : {
1361 0 : if (*s != '%')
1362 : {
1363 0 : s++;
1364 0 : continue;
1365 : }
1366 0 : if (s != format)
1367 : {
1368 0 : rc = outfnc (outfncarg, format, (n=s-format));
1369 0 : if (rc)
1370 : return rc;
1371 0 : *nbytes += n;
1372 : }
1373 0 : if (s[1] == '%')
1374 : {
1375 : /* Note that this code ignores one trailing percent escape -
1376 : this is however okay as the args parser must have
1377 : detected this already. */
1378 0 : rc = outfnc (outfncarg, s, 1);
1379 0 : if (rc)
1380 : return rc;
1381 0 : *nbytes += 1;
1382 0 : s += 2;
1383 : format = s;
1384 0 : continue;
1385 : }
1386 :
1387 : /* Save the next start. */
1388 0 : s += arg->length;
1389 : format = s;
1390 :
1391 0 : assert (argidx < argspecs_len);
1392 0 : argidx++;
1393 :
1394 : /* Apply indirect field width and precision values. */
1395 0 : if (arg->width == STAR_FIELD_VALUE)
1396 : {
1397 0 : assert (valuetable[arg->width_pos-1].vt == VALTYPE_INT);
1398 0 : arg->width = valuetable[arg->width_pos-1].value.a_int;
1399 0 : if (arg->width < 0)
1400 : {
1401 0 : arg->width = -arg->width;
1402 0 : arg->flags |= FLAG_LEFT_JUST;
1403 : }
1404 : }
1405 0 : if (arg->precision == STAR_FIELD_VALUE)
1406 : {
1407 0 : assert (valuetable[arg->precision_pos-1].vt == VALTYPE_INT);
1408 0 : arg->precision = valuetable[arg->precision_pos-1].value.a_int;
1409 0 : if (arg->precision < 0)
1410 0 : arg->precision = NO_FIELD_VALUE;
1411 : }
1412 :
1413 0 : if (arg->arg_pos == -1 && arg->conspec == CONSPEC_STRERROR)
1414 0 : value.a_string = strerror (myerrno);
1415 : else
1416 : {
1417 0 : assert (arg->vt == valuetable[arg->arg_pos-1].vt);
1418 0 : value = valuetable[arg->arg_pos-1].value;
1419 : }
1420 :
1421 0 : switch (arg->conspec)
1422 : {
1423 0 : case CONSPEC_UNKNOWN: assert (!"bug"); break;
1424 :
1425 : case CONSPEC_DECIMAL:
1426 : case CONSPEC_UNSIGNED:
1427 : case CONSPEC_OCTAL:
1428 : case CONSPEC_HEX:
1429 : case CONSPEC_HEX_UP:
1430 0 : rc = pr_integer (outfnc, outfncarg, arg, value, nbytes);
1431 0 : break;
1432 : case CONSPEC_FLOAT:
1433 : case CONSPEC_FLOAT_UP:
1434 : case CONSPEC_EXP:
1435 : case CONSPEC_EXP_UP:
1436 : case CONSPEC_F_OR_G:
1437 : case CONSPEC_F_OR_G_UP:
1438 : case CONSPEC_HEX_EXP:
1439 : case CONSPEC_HEX_EXP_UP:
1440 0 : rc = pr_float (outfnc, outfncarg, arg, value, nbytes);
1441 0 : break;
1442 : case CONSPEC_CHAR:
1443 : rc = pr_char (outfnc, outfncarg, arg, value, nbytes);
1444 0 : break;
1445 : case CONSPEC_STRING:
1446 : case CONSPEC_STRERROR:
1447 0 : rc = pr_string (outfnc, outfncarg, arg, value, nbytes);
1448 0 : break;
1449 : case CONSPEC_POINTER:
1450 0 : rc = pr_pointer (outfnc, outfncarg, arg, value, nbytes);
1451 0 : break;
1452 : case CONSPEC_BYTES_SO_FAR:
1453 0 : rc = pr_bytes_so_far (outfnc, outfncarg, arg, value, nbytes);
1454 0 : break;
1455 : }
1456 0 : if (rc)
1457 : return rc;
1458 0 : arg++;
1459 : }
1460 :
1461 : /* Print out any trailing stuff. */
1462 0 : n = s - format;
1463 0 : rc = n? outfnc (outfncarg, format, n) : 0;
1464 0 : if (!rc)
1465 0 : *nbytes += n;
1466 :
1467 : return rc;
1468 : }
1469 :
1470 :
1471 :
1472 :
1473 : /* The versatile printf formatting routine. It expects a callback
1474 : function OUTFNC and an opaque argument OUTFNCARG used for actual
1475 : output of the formatted stuff. FORMAT is the format specification
1476 : and VAARGS a variable argumemt list matching the arguments of
1477 : FORMAT. */
1478 : int
1479 0 : _gpgrt_estream_format (estream_printf_out_t outfnc,
1480 : void *outfncarg,
1481 : const char *format, va_list vaargs)
1482 : {
1483 : /* Buffer to hold the argspecs and a pointer to it.*/
1484 : struct argspec_s argspecs_buffer[DEFAULT_MAX_ARGSPECS];
1485 0 : argspec_t argspecs = argspecs_buffer;
1486 : size_t argspecs_len; /* Number of specifications in ARGSPECS. */
1487 :
1488 : /* Buffer to hold the description for the values. */
1489 : struct valueitem_s valuetable_buffer[DEFAULT_MAX_VALUES];
1490 : valueitem_t valuetable = valuetable_buffer;
1491 :
1492 : int rc; /* Return code. */
1493 : size_t argidx; /* Used to index the argspecs array. */
1494 : size_t validx; /* Used to index the valuetable. */
1495 : int max_pos;/* Highest argument position. */
1496 :
1497 0 : size_t nbytes = 0; /* Keep track of the number of bytes passed to
1498 : the output function. */
1499 :
1500 0 : int myerrno = errno; /* Save the errno for use with "%m". */
1501 :
1502 :
1503 : /* Parse the arguments to come up with descriptive list. We can't
1504 : do this on the fly because we need to support positional
1505 : arguments. */
1506 0 : rc = parse_format (format, &argspecs, DIM(argspecs_buffer), &argspecs_len);
1507 0 : if (rc)
1508 : goto leave;
1509 :
1510 : /* Check that all ARG_POS fields are set. */
1511 0 : for (argidx=0,max_pos=0; argidx < argspecs_len; argidx++)
1512 : {
1513 0 : if (argspecs[argidx].arg_pos != -1
1514 0 : && argspecs[argidx].arg_pos > max_pos)
1515 : max_pos = argspecs[argidx].arg_pos;
1516 0 : if (argspecs[argidx].width_pos > max_pos)
1517 : max_pos = argspecs[argidx].width_pos;
1518 0 : if (argspecs[argidx].precision_pos > max_pos)
1519 : max_pos = argspecs[argidx].precision_pos;
1520 : }
1521 0 : if (!max_pos)
1522 : {
1523 : /* Fill in all the positions. */
1524 0 : for (argidx=0; argidx < argspecs_len; argidx++)
1525 : {
1526 0 : if (argspecs[argidx].width == STAR_FIELD_VALUE)
1527 0 : argspecs[argidx].width_pos = ++max_pos;
1528 0 : if (argspecs[argidx].precision == STAR_FIELD_VALUE)
1529 0 : argspecs[argidx].precision_pos = ++max_pos;
1530 0 : if (argspecs[argidx].arg_pos != -1 )
1531 0 : argspecs[argidx].arg_pos = ++max_pos;
1532 : }
1533 : }
1534 : else
1535 : {
1536 : /* Check that they are all filled. More test are done later. */
1537 0 : for (argidx=0; argidx < argspecs_len; argidx++)
1538 : {
1539 0 : if (!argspecs[argidx].arg_pos
1540 0 : || (argspecs[argidx].width == STAR_FIELD_VALUE
1541 0 : && !argspecs[argidx].width_pos)
1542 0 : || (argspecs[argidx].precision == STAR_FIELD_VALUE
1543 0 : && !argspecs[argidx].precision_pos))
1544 : goto leave_einval;
1545 : }
1546 : }
1547 : /* Check that there is no overflow in max_pos and that it has a
1548 : reasonable length. There may never be more elements than the
1549 : number of characters in FORMAT. */
1550 0 : if (max_pos < 0 || max_pos >= strlen (format))
1551 : goto leave_einval;
1552 :
1553 : #ifdef DEBUG
1554 : dump_argspecs (argspecs, argspecs_len);
1555 : #endif
1556 :
1557 : /* Allocate a table to hold the values. If it is small enough we
1558 : use a stack allocated buffer. */
1559 0 : if (max_pos > DIM(valuetable_buffer))
1560 : {
1561 0 : valuetable = calloc (max_pos, sizeof *valuetable);
1562 0 : if (!valuetable)
1563 : goto leave_error;
1564 : }
1565 : else
1566 : {
1567 0 : for (validx=0; validx < DIM(valuetable_buffer); validx++)
1568 0 : valuetable[validx].vt = VALTYPE_UNSUPPORTED;
1569 : }
1570 0 : for (argidx=0; argidx < argspecs_len; argidx++)
1571 : {
1572 0 : if (argspecs[argidx].arg_pos != - 1)
1573 : {
1574 0 : validx = argspecs[argidx].arg_pos - 1;
1575 0 : if (valuetable[validx].vt)
1576 : goto leave_einval; /* Already defined. */
1577 0 : valuetable[validx].vt = argspecs[argidx].vt;
1578 : }
1579 0 : if (argspecs[argidx].width == STAR_FIELD_VALUE)
1580 : {
1581 0 : validx = argspecs[argidx].width_pos - 1;
1582 0 : if (valuetable[validx].vt)
1583 : goto leave_einval; /* Already defined. */
1584 0 : valuetable[validx].vt = VALTYPE_INT;
1585 : }
1586 0 : if (argspecs[argidx].precision == STAR_FIELD_VALUE)
1587 : {
1588 0 : validx = argspecs[argidx].precision_pos - 1;
1589 0 : if (valuetable[validx].vt)
1590 : goto leave_einval; /* Already defined. */
1591 0 : valuetable[validx].vt = VALTYPE_INT;
1592 : }
1593 : }
1594 :
1595 : /* Read all the arguments. This will error out for unsupported
1596 : types and for not given positional arguments. */
1597 0 : rc = read_values (valuetable, max_pos, vaargs);
1598 0 : if (rc)
1599 : goto leave_einval;
1600 :
1601 : /* for (validx=0; validx < max_pos; validx++) */
1602 : /* fprintf (stderr, "%2d: vt=%d\n", validx, valuetable[validx].vt); */
1603 :
1604 : /* Everything has been collected, go ahead with the formatting. */
1605 0 : rc = do_format (outfnc, outfncarg, format,
1606 : argspecs, argspecs_len, valuetable, myerrno, &nbytes);
1607 :
1608 0 : goto leave;
1609 :
1610 : leave_einval:
1611 0 : _set_errno (EINVAL);
1612 : leave_error:
1613 : rc = -1;
1614 : leave:
1615 0 : if (valuetable != valuetable_buffer)
1616 0 : free (valuetable);
1617 0 : if (argspecs != argspecs_buffer)
1618 0 : free (argspecs);
1619 0 : return rc;
1620 : }
1621 :
1622 :
1623 :
1624 :
1625 : /* A simple output handler utilizing stdio. */
1626 : static int
1627 0 : plain_stdio_out (void *outfncarg, const char *buf, size_t buflen)
1628 : {
1629 : FILE *fp = (FILE*)outfncarg;
1630 :
1631 0 : if ( fwrite (buf, buflen, 1, fp) != 1 )
1632 : return -1;
1633 0 : return 0;
1634 : }
1635 :
1636 :
1637 : /* A replacement for printf. */
1638 : int
1639 0 : _gpgrt_estream_printf (const char *format, ...)
1640 : {
1641 : int rc;
1642 : va_list arg_ptr;
1643 :
1644 0 : va_start (arg_ptr, format);
1645 0 : rc = _gpgrt_estream_format (plain_stdio_out, stderr, format, arg_ptr);
1646 0 : va_end (arg_ptr);
1647 :
1648 0 : return rc;
1649 : }
1650 :
1651 : /* A replacement for fprintf. */
1652 : int
1653 0 : _gpgrt_estream_fprintf (FILE *fp, const char *format, ...)
1654 : {
1655 : int rc;
1656 : va_list arg_ptr;
1657 :
1658 0 : va_start (arg_ptr, format);
1659 0 : rc = _gpgrt_estream_format (plain_stdio_out, fp, format, arg_ptr);
1660 0 : va_end (arg_ptr);
1661 :
1662 0 : return rc;
1663 : }
1664 :
1665 : /* A replacement for vfprintf. */
1666 : int
1667 0 : _gpgrt_estream_vfprintf (FILE *fp, const char *format, va_list arg_ptr)
1668 : {
1669 0 : return _gpgrt_estream_format (plain_stdio_out, fp, format, arg_ptr);
1670 : }
1671 :
1672 :
1673 :
1674 : /* Communication object used between estream_snprintf and
1675 : fixed_buffer_out. */
1676 : struct fixed_buffer_parm_s
1677 : {
1678 : size_t size; /* Size of the buffer. */
1679 : size_t count; /* Number of bytes requested for output. */
1680 : size_t used; /* Used size of the buffer. */
1681 : char *buffer; /* Provided buffer. */
1682 : };
1683 :
1684 : /* A simple malloced buffer output handler. */
1685 : static int
1686 0 : fixed_buffer_out (void *outfncarg, const char *buf, size_t buflen)
1687 : {
1688 : struct fixed_buffer_parm_s *parm = outfncarg;
1689 :
1690 0 : parm->count += buflen;
1691 :
1692 0 : if (!parm->buffer)
1693 : ;
1694 0 : else if (parm->used + buflen < parm->size)
1695 : {
1696 : /* Handle the common case that everything fits into the buffer
1697 : separately. */
1698 0 : memcpy (parm->buffer + parm->used, buf, buflen);
1699 0 : parm->used += buflen;
1700 : }
1701 : else
1702 : {
1703 : /* The slow version of above. */
1704 0 : for ( ;buflen && parm->used < parm->size; buflen--)
1705 0 : parm->buffer[parm->used++] = *buf++;
1706 : }
1707 :
1708 0 : return 0;
1709 : }
1710 :
1711 :
1712 : /* A replacement for vsnprintf. */
1713 : int
1714 0 : _gpgrt_estream_vsnprintf (char *buf, size_t bufsize,
1715 : const char *format, va_list arg_ptr)
1716 : {
1717 : struct fixed_buffer_parm_s parm;
1718 : int rc;
1719 :
1720 0 : parm.size = bufsize;
1721 0 : parm.count = 0;
1722 0 : parm.used = 0;
1723 0 : parm.buffer = bufsize?buf:NULL;
1724 0 : rc = _gpgrt_estream_format (fixed_buffer_out, &parm, format, arg_ptr);
1725 0 : if (!rc)
1726 0 : rc = fixed_buffer_out (&parm, "", 1); /* Print terminating Nul. */
1727 0 : if (rc == -1)
1728 : return -1;
1729 0 : if (bufsize && buf && parm.size && parm.count >= parm.size)
1730 0 : buf[parm.size-1] = 0;
1731 :
1732 0 : parm.count--; /* Do not count the trailing nul. */
1733 0 : return (int)parm.count; /* Return number of bytes which would have
1734 : been written. */
1735 : }
1736 :
1737 : /* A replacement for snprintf. */
1738 : int
1739 0 : _gpgrt_estream_snprintf (char *buf, size_t bufsize, const char *format, ...)
1740 : {
1741 : int rc;
1742 : va_list arg_ptr;
1743 :
1744 0 : va_start (arg_ptr, format);
1745 0 : rc = _gpgrt_estream_vsnprintf (buf, bufsize, format, arg_ptr);
1746 0 : va_end (arg_ptr);
1747 :
1748 0 : return rc;
1749 : }
1750 :
1751 :
1752 :
1753 : /* Communication object used between estream_asprintf and
1754 : dynamic_buffer_out. */
1755 : struct dynamic_buffer_parm_s
1756 : {
1757 : int error_flag; /* Internal helper. */
1758 : size_t alloced; /* Allocated size of the buffer. */
1759 : size_t used; /* Used size of the buffer. */
1760 : char *buffer; /* Malloced buffer. */
1761 : };
1762 :
1763 : /* A simple malloced buffer output handler. */
1764 : static int
1765 0 : dynamic_buffer_out (void *outfncarg, const char *buf, size_t buflen)
1766 : {
1767 : struct dynamic_buffer_parm_s *parm = outfncarg;
1768 :
1769 0 : if (parm->error_flag)
1770 : {
1771 : /* Just in case some formatting routine did not checked for an
1772 : error. */
1773 0 : _set_errno (parm->error_flag);
1774 0 : return -1;
1775 : }
1776 :
1777 0 : if (parm->used + buflen >= parm->alloced)
1778 : {
1779 : char *p;
1780 :
1781 0 : parm->alloced += buflen + 512;
1782 0 : p = my_printf_realloc (parm->buffer, parm->alloced);
1783 0 : if (!p)
1784 : {
1785 0 : parm->error_flag = errno ? errno : ENOMEM;
1786 : /* Wipe out what we already accumulated. This is useful in
1787 : case sensitive data is formatted. */
1788 0 : memset (parm->buffer, 0, parm->used);
1789 0 : return -1;
1790 : }
1791 0 : parm->buffer = p;
1792 : }
1793 0 : memcpy (parm->buffer + parm->used, buf, buflen);
1794 0 : parm->used += buflen;
1795 :
1796 0 : return 0;
1797 : }
1798 :
1799 :
1800 : /* A replacement for vasprintf. As with the BSD version of vasprintf
1801 : -1 will be returned on error and NULL stored at BUFP. On success
1802 : the number of bytes printed will be returned. */
1803 : int
1804 0 : _gpgrt_estream_vasprintf (char **bufp, const char *format, va_list arg_ptr)
1805 : {
1806 : struct dynamic_buffer_parm_s parm;
1807 : int rc;
1808 :
1809 0 : parm.error_flag = 0;
1810 0 : parm.alloced = 512;
1811 0 : parm.used = 0;
1812 0 : parm.buffer = my_printf_realloc (NULL, parm.alloced);
1813 0 : if (!parm.buffer)
1814 : {
1815 0 : *bufp = NULL;
1816 0 : return -1;
1817 : }
1818 :
1819 0 : rc = _gpgrt_estream_format (dynamic_buffer_out, &parm, format, arg_ptr);
1820 0 : if (!rc)
1821 0 : rc = dynamic_buffer_out (&parm, "", 1); /* Print terminating Nul. */
1822 : /* Fixme: Should we shrink the resulting buffer? */
1823 0 : if (rc != -1 && parm.error_flag)
1824 : {
1825 : rc = -1;
1826 0 : _set_errno (parm.error_flag);
1827 : }
1828 0 : if (rc == -1)
1829 : {
1830 0 : memset (parm.buffer, 0, parm.used);
1831 0 : if (parm.buffer)
1832 0 : my_printf_realloc (parm.buffer, 0);
1833 0 : *bufp = NULL;
1834 0 : return -1;
1835 : }
1836 0 : assert (parm.used); /* We have at least the terminating Nul. */
1837 0 : *bufp = parm.buffer;
1838 0 : return parm.used - 1; /* Do not include that Nul. */
1839 : }
1840 :
1841 : /* A replacement for asprintf. As with the BSD of asprintf version -1
1842 : will be returned on error and NULL stored at BUFP. On success the
1843 : number of bytes printed will be returned. */
1844 : int
1845 0 : _gpgrt_estream_asprintf (char **bufp, const char *format, ...)
1846 : {
1847 : int rc;
1848 : va_list arg_ptr;
1849 :
1850 0 : va_start (arg_ptr, format);
1851 0 : rc = _gpgrt_estream_vasprintf (bufp, format, arg_ptr);
1852 0 : va_end (arg_ptr);
1853 :
1854 0 : return rc;
1855 : }
1856 :
1857 : /* A variant of asprintf. The function returns the allocated buffer
1858 : or NULL on error; ERRNO is set in the error case. The caller
1859 : should use es_free to release the buffer. This function actually
1860 : belongs into estream-printf but we put it here as a convenience
1861 : and because es_free is required anyway. */
1862 : char *
1863 0 : _gpgrt_estream_bsprintf (const char *format, ...)
1864 : {
1865 : int rc;
1866 : va_list ap;
1867 : char *buf;
1868 :
1869 0 : va_start (ap, format);
1870 0 : rc = _gpgrt_estream_vasprintf (&buf, format, ap);
1871 0 : va_end (ap);
1872 0 : if (rc < 0)
1873 : return NULL;
1874 0 : return buf;
1875 : }
|