Coverage Report

Created: 2026-08-25 07:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gstreamer/subprojects/gstreamer/gst/printf/vasnprintf.c
Line
Count
Source
1
/* vsprintf with automatic memory allocation.
2
   Copyright (C) 1999, 2002-2003 Free Software Foundation, Inc.
3
4
   This program is free software; you can redistribute it and/or modify it
5
   under the terms of the GNU Library General Public License as published
6
   by the Free Software Foundation; either version 2, or (at your option)
7
   any later version.
8
9
   This program is distributed in the hope that it will be useful,
10
   but WITHOUT ANY WARRANTY; without even the implied warranty of
11
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
   Library General Public License for more details.
13
14
   You should have received a copy of the GNU Library General Public
15
   License along with this program; if not, write to the Free Software
16
   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
17
   USA.  */
18
19
#ifndef _WIN32
20
/* Tell glibc's <stdio.h> to provide a prototype for snprintf().
21
   This must come before <config.h> because <config.h> may include
22
   <features.h>, and once <features.h> has been included, it's too late.  */
23
#ifndef _GNU_SOURCE
24
# define _GNU_SOURCE    1
25
#endif
26
#endif
27
28
#ifdef HAVE_CONFIG_H
29
# include <config.h>
30
#endif
31
32
#include "gst-printf.h"
33
34
/* Specification.  */
35
#include "vasnprintf.h"
36
37
#include <stdio.h>              /* snprintf(), sprintf() */
38
#include <stdlib.h>             /* abort(), malloc(), realloc(), free() */
39
#include <string.h>             /* memcpy(), strlen() */
40
#include <errno.h>              /* errno */
41
#include <limits.h>             /* CHAR_BIT */
42
#include <float.h>              /* DBL_MAX_EXP, LDBL_MAX_EXP */
43
#include "printf-parse.h"
44
#include "printf-extension.h"
45
46
#ifdef HAVE_WCHAR_T
47
# ifdef HAVE_WCSLEN
48
#  define local_wcslen wcslen
49
# else
50
   /* Solaris 2.5.1 has wcslen() in a separate library libw.so. To avoid
51
      a dependency towards this library, here is a local substitute.
52
      Define this substitute only once, even if this file is included
53
      twice in the same compilation unit.  */
54
#  ifndef local_wcslen_defined
55
#   define local_wcslen_defined 1
56
static size_t
57
local_wcslen (const wchar_t *s)
58
{
59
  const wchar_t *ptr;
60
61
  for (ptr = s; *ptr != (wchar_t) 0; ptr++);
62
  return ptr - s;
63
}
64
#  endif
65
# endif
66
#endif
67
68
/* For those losing systems which don't have 'alloca' we have to add
69
   some additional code emulating it.  */
70
#if defined (alloca) || defined (GLIB_HAVE_ALLOCA_H)
71
# define freea(p)               /* nothing */
72
#else
73
# define alloca(n) malloc (n)
74
# define freea(p) free (p)
75
#endif
76
77
#ifndef HAVE_LONG_LONG_FORMAT
78
static inline int
79
print_long_long (char *buf,
80
    int len,
81
    int width,
82
    int precision,
83
    unsigned long flags, char conversion, unsigned long long number)
84
0
{
85
0
  int negative = FALSE;
86
0
  char buffer[128];
87
0
  char *bufferend;
88
0
  char *pointer;
89
0
  int base;
90
0
  static const char *upper = "0123456789ABCDEFX";
91
0
  static const char *lower = "0123456789abcdefx";
92
0
  const char *digits;
93
0
  int i;
94
0
  char *p;
95
0
  int count;
96
97
0
#define EMIT(c)           \
98
0
  if (p - buf == len - 1) \
99
0
    {                     \
100
0
      *p++ = '\0';        \
101
0
      return len;         \
102
0
    }                     \
103
0
  else                    \
104
0
    *p++ = c;
105
106
0
  p = buf;
107
108
0
  switch (conversion) {
109
0
    case 'o':
110
0
      base = 8;
111
0
      digits = lower;
112
0
      negative = FALSE;
113
0
      break;
114
0
    case 'x':
115
0
      base = 16;
116
0
      digits = lower;
117
0
      negative = FALSE;
118
0
      break;
119
0
    case 'X':
120
0
      base = 16;
121
0
      digits = upper;
122
0
      negative = FALSE;
123
0
      break;
124
0
    case 'u':
125
0
      base = 10;
126
0
      digits = lower;
127
0
      negative = FALSE;
128
0
      break;
129
0
    default:
130
0
      base = 10;
131
0
      digits = lower;
132
0
      negative = (long long) number < 0;
133
0
      if (negative)
134
0
        number = -((long long) number);
135
0
      break;
136
0
  }
137
138
  /* Build number */
139
0
  pointer = bufferend = &buffer[sizeof (buffer) - 1];
140
0
  *pointer-- = '\0';
141
0
  for (i = 1; i < (int) sizeof (buffer); i++) {
142
0
    *pointer-- = digits[number % base];
143
0
    number /= base;
144
0
    if (number == 0)
145
0
      break;
146
0
  }
147
148
  /* Adjust width */
149
0
  width -= (bufferend - pointer) - 1;
150
151
  /* Adjust precision */
152
0
  if (precision != -1) {
153
0
    precision -= (bufferend - pointer) - 1;
154
0
    if (precision < 0)
155
0
      precision = 0;
156
0
    flags |= FLAG_ZERO;
157
0
  }
158
159
  /* Adjust width further */
160
0
  if (negative || (flags & FLAG_SHOWSIGN) || (flags & FLAG_SPACE))
161
0
    width--;
162
0
  if (flags & FLAG_ALT) {
163
0
    switch (base) {
164
0
      case 16:
165
0
        width -= 2;
166
0
        break;
167
0
      case 8:
168
0
        width--;
169
0
        break;
170
0
      default:
171
0
        break;
172
0
    }
173
0
  }
174
175
  /* Output prefixes spaces if needed */
176
0
  if (!((flags & FLAG_LEFT) || ((flags & FLAG_ZERO) && (precision == -1)))) {
177
0
    count = (precision == -1) ? 0 : precision;
178
0
    while (width-- > count)
179
0
      *p++ = ' ';
180
0
  }
181
182
  /* width has been adjusted for signs and alternatives */
183
0
  if (negative) {
184
0
    EMIT ('-');
185
0
  } else if (flags & FLAG_SHOWSIGN) {
186
0
    EMIT ('+');
187
0
  } else if (flags & FLAG_SPACE) {
188
0
    EMIT (' ');
189
0
  }
190
191
0
  if (flags & FLAG_ALT) {
192
0
    switch (base) {
193
0
      case 8:
194
0
        EMIT ('0');
195
0
        break;
196
0
      case 16:
197
0
        EMIT ('0');
198
0
        EMIT (digits[16]);
199
0
        break;
200
0
      default:
201
0
        break;
202
0
    }                           /* switch base */
203
0
  }
204
205
  /* Output prefixed zero padding if needed */
206
0
  if (flags & FLAG_ZERO) {
207
0
    if (precision == -1)
208
0
      precision = width;
209
0
    while (precision-- > 0) {
210
0
      EMIT ('0');
211
0
      width--;
212
0
    }
213
0
  }
214
215
  /* Output the number itself */
216
0
  while (*(++pointer)) {
217
0
    EMIT (*pointer);
218
0
  }
219
220
  /* Output trailing spaces if needed */
221
0
  if (flags & FLAG_LEFT) {
222
0
    while (width-- > 0)
223
0
      EMIT (' ');
224
0
  }
225
226
0
  EMIT ('\0');
227
228
0
  return p - buf - 1;
229
0
}
230
#endif
231
232
static void
233
printf_postprocess_args (char_directives * directives, arguments * arguments)
234
67.4k
{
235
67.4k
  int i;
236
237
92.2k
  for (i = 0; i < directives->count; ++i) {
238
24.7k
    char_directive *dp;
239
24.7k
    argument *a;
240
241
24.7k
    dp = &directives->dir[i];
242
243
    /* %% has no arguments, for example */
244
24.7k
    if (dp->arg_index < 0)
245
0
      continue;
246
247
24.7k
    a = &arguments->arg[dp->arg_index];
248
249
24.7k
    if (a->type == TYPE_POINTER_EXT) {
250
1.16k
      char fmt[4];
251
252
1.16k
      fmt[0] = 'p';
253
1.16k
      fmt[1] = POINTER_EXT_SIGNIFIER_CHAR;
254
1.16k
      fmt[2] = dp->ptr_ext_char;
255
1.16k
      fmt[3] = '\0';
256
257
1.16k
      a->ext_string =
258
1.16k
          __gst_printf_pointer_extension_serialize (fmt, a->a.a_pointer);
259
1.16k
    }
260
24.7k
  }
261
67.4k
}
262
263
static gboolean
264
gather_logging_arguments (const char *format, char_directives * d,
265
    arguments * a, va_list args)
266
67.4k
{
267
67.4k
  if (printf_parse (format, d, a) < 0) {
268
0
    errno = EINVAL;
269
0
    return FALSE;
270
0
  }
271
272
67.4k
#define LOCAL_CLEANUP()                         \
273
67.4k
  if (d->dir != d->direct_alloc_dir) \
274
0
    free (d->dir);                           \
275
0
  while (a->count--) {                   \
276
0
    if (a->arg[a->count].ext_string)      \
277
0
      free (a->arg[a->count].ext_string); \
278
0
  }                                     \
279
0
  if (a->arg != a->direct_alloc_arg) {                            \
280
0
    free (a->arg);                         \
281
0
  }
282
283
67.4k
  if (printf_fetchargs (args, a) < 0) {
284
0
    LOCAL_CLEANUP ();
285
0
    errno = EINVAL;
286
0
    return FALSE;
287
0
  }
288
289
  /* collect TYPE_POINTER_EXT argument strings */
290
67.4k
  printf_postprocess_args (d, a);
291
292
67.4k
  return TRUE;
293
67.4k
}
294
295
char *
296
vasnprintf (char *resultbuf, size_t *lengthp, const char *format, va_list args)
297
67.4k
{
298
67.4k
  char_directives d;
299
67.4k
  arguments a;
300
301
67.4k
  if (!gather_logging_arguments (format, &d, &a, args)) {
302
0
    return NULL;
303
0
  }
304
305
67.4k
#define CLEANUP()                         \
306
67.4k
  if (d.dir != d.direct_alloc_dir)        \
307
67.4k
    free (d.dir);                           \
308
92.2k
  while (a.count--) {                   \
309
24.7k
    if (a.arg[a.count].ext_string)      \
310
24.7k
      free (a.arg[a.count].ext_string); \
311
24.7k
  }                                     \
312
67.4k
  if (a.arg != a.direct_alloc_arg) {                            \
313
0
    free (a.arg);                         \
314
0
  }
315
316
67.4k
  {
317
67.4k
    char *buf =
318
67.4k
        (char *) alloca (7 + d.max_width_length + d.max_precision_length + 6);
319
67.4k
    const char *cp;
320
67.4k
    unsigned int i;
321
67.4k
    char_directive *dp;
322
    /* Output string accumulator.  */
323
67.4k
    char *result;
324
67.4k
    size_t allocated;
325
67.4k
    size_t length;
326
327
67.4k
    if (resultbuf != NULL) {
328
6.63k
      result = resultbuf;
329
6.63k
      allocated = *lengthp;
330
60.8k
    } else {
331
60.8k
      result = NULL;
332
60.8k
      allocated = 0;
333
60.8k
    }
334
67.4k
    length = 0;
335
    /* Invariants:
336
       result is either == resultbuf or == NULL or malloc-allocated.
337
       If length > 0, then result != NULL.  */
338
339
67.4k
#define ENSURE_ALLOCATION(needed) \
340
176k
    if ((needed) > allocated)           \
341
176k
      {                 \
342
64.3k
  char *memory;             \
343
64.3k
                  \
344
64.3k
  allocated = (allocated > 0 ? 2 * allocated : 320);    \
345
64.3k
  if ((needed) > allocated)         \
346
64.3k
    allocated = (needed);           \
347
64.3k
  if (result == resultbuf || result == NULL)     \
348
64.3k
    memory = (char *) malloc (allocated);       \
349
64.3k
  else                \
350
64.3k
    memory = (char *) realloc (result, allocated);   \
351
64.3k
                  \
352
64.3k
  if (memory == NULL)           \
353
64.3k
    {               \
354
0
      if (!(result == resultbuf || result == NULL))    \
355
0
        free (result);           \
356
0
      freea (buf);            \
357
0
      CLEANUP ();              \
358
0
      errno = ENOMEM;           \
359
0
      return NULL;            \
360
0
    }                \
361
64.3k
  if (result == resultbuf && length > 0)       \
362
64.3k
    memcpy (memory, result, length);       \
363
64.3k
  result = memory;            \
364
64.3k
      }
365
366
92.2k
    for (cp = format, i = 0, dp = &d.dir[0];; cp = dp->dir_end, i++, dp++) {
367
92.2k
      if (cp != dp->dir_start) {
368
80.7k
        size_t n = dp->dir_start - cp;
369
370
80.7k
        ENSURE_ALLOCATION (length + n);
371
80.7k
        memcpy (result + length, cp, n);
372
80.7k
        length += n;
373
80.7k
      }
374
92.2k
      if (i == d.count)
375
67.4k
        break;
376
377
      /* Execute a single directive.  */
378
24.7k
      if (dp->conversion == '%') {
379
0
        if (!(dp->arg_index < 0))
380
0
          abort ();
381
0
        ENSURE_ALLOCATION (length + 1);
382
0
        result[length] = '%';
383
0
        length += 1;
384
24.7k
      } else {
385
24.7k
        if (!(dp->arg_index >= 0))
386
0
          abort ();
387
388
24.7k
        if (dp->conversion == 'n') {
389
0
          switch (a.arg[dp->arg_index].type) {
390
0
            case TYPE_COUNT_SCHAR_POINTER:
391
0
              *a.arg[dp->arg_index].a.a_count_schar_pointer = length;
392
0
              break;
393
0
            case TYPE_COUNT_SHORT_POINTER:
394
0
              *a.arg[dp->arg_index].a.a_count_short_pointer = length;
395
0
              break;
396
0
            case TYPE_COUNT_INT_POINTER:
397
0
              *a.arg[dp->arg_index].a.a_count_int_pointer = length;
398
0
              break;
399
0
            case TYPE_COUNT_LONGINT_POINTER:
400
0
              *a.arg[dp->arg_index].a.a_count_longint_pointer = length;
401
0
              break;
402
0
#ifdef HAVE_LONG_LONG
403
0
            case TYPE_COUNT_LONGLONGINT_POINTER:
404
0
              *a.arg[dp->arg_index].a.a_count_longlongint_pointer = length;
405
0
              break;
406
0
#endif
407
0
            default:
408
0
              abort ();
409
0
          }
410
24.7k
        } else {
411
24.7k
          arg_type type = a.arg[dp->arg_index].type;
412
24.7k
          char *p;
413
24.7k
          unsigned int prefix_count;
414
24.7k
          int prefixes[2];
415
#ifndef HAVE_SNPRINTF
416
          unsigned int tmp_length;
417
          char tmpbuf[700];
418
          char *tmp;
419
420
          /* Allocate a temporary buffer of sufficient size for calling
421
             sprintf.  */
422
          {
423
            unsigned int width;
424
            unsigned int precision;
425
426
            width = 0;
427
            if (dp->width_start != dp->width_end) {
428
              if (dp->width_arg_index >= 0) {
429
                int arg;
430
431
                if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
432
                  abort ();
433
                arg = a.arg[dp->width_arg_index].a.a_int;
434
                width = (arg < 0 ? -arg : arg);
435
              } else {
436
                const char *digitp = dp->width_start;
437
438
                do
439
                  width = width * 10 + (*digitp++ - '0');
440
                while (digitp != dp->width_end);
441
              }
442
            }
443
444
            precision = 6;
445
            if (dp->precision_start != dp->precision_end) {
446
              if (dp->precision_arg_index >= 0) {
447
                int arg;
448
449
                if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
450
                  abort ();
451
                arg = a.arg[dp->precision_arg_index].a.a_int;
452
                precision = (arg < 0 ? 0 : arg);
453
              } else {
454
                const char *digitp = dp->precision_start + 1;
455
456
                precision = 0;
457
                while (digitp != dp->precision_end)
458
                  precision = precision * 10 + (*digitp++ - '0');
459
              }
460
            }
461
462
            switch (dp->conversion) {
463
              case 'd':
464
              case 'i':
465
              case 'u':
466
# ifdef HAVE_LONG_LONG
467
                if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
468
                  tmp_length = (unsigned int) (sizeof (unsigned long long) * CHAR_BIT * 0.30103 /* binary -> decimal */
469
                      * 2       /* estimate for FLAG_GROUP */
470
                      )
471
                      + 1       /* turn floor into ceil */
472
                      + 1;      /* account for leading sign */
473
                else
474
# endif
475
                if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
476
                  tmp_length = (unsigned int) (sizeof (unsigned long) * CHAR_BIT * 0.30103      /* binary -> decimal */
477
                      * 2       /* estimate for FLAG_GROUP */
478
                      )
479
                      + 1       /* turn floor into ceil */
480
                      + 1;      /* account for leading sign */
481
                else
482
                  tmp_length = (unsigned int) (sizeof (unsigned int) * CHAR_BIT * 0.30103       /* binary -> decimal */
483
                      * 2       /* estimate for FLAG_GROUP */
484
                      )
485
                      + 1       /* turn floor into ceil */
486
                      + 1;      /* account for leading sign */
487
                break;
488
489
              case 'o':
490
# ifdef HAVE_LONG_LONG
491
                if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
492
                  tmp_length = (unsigned int) (sizeof (unsigned long long) * CHAR_BIT * 0.333334        /* binary -> octal */
493
                      )
494
                      + 1       /* turn floor into ceil */
495
                      + 1;      /* account for leading sign */
496
                else
497
# endif
498
                if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
499
                  tmp_length = (unsigned int) (sizeof (unsigned long) * CHAR_BIT * 0.333334     /* binary -> octal */
500
                      )
501
                      + 1       /* turn floor into ceil */
502
                      + 1;      /* account for leading sign */
503
                else
504
                  tmp_length = (unsigned int) (sizeof (unsigned int) * CHAR_BIT * 0.333334      /* binary -> octal */
505
                      )
506
                      + 1       /* turn floor into ceil */
507
                      + 1;      /* account for leading sign */
508
                break;
509
510
              case 'x':
511
              case 'X':
512
# ifdef HAVE_LONG_LONG
513
                if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
514
                  tmp_length = (unsigned int) (sizeof (unsigned long long) * CHAR_BIT * 0.25    /* binary -> hexadecimal */
515
                      )
516
                      + 1       /* turn floor into ceil */
517
                      + 2;      /* account for leading sign or alternate form */
518
                else
519
# endif
520
# ifdef HAVE_INT64_AND_I64
521
                if (type == TYPE_INT64 || type == TYPE_UINT64)
522
                  tmp_length = (unsigned int) (sizeof (unsigned __int64) * CHAR_BIT * 0.25      /* binary -> hexadecimal */
523
                      )
524
                      + 1       /* turn floor into ceil */
525
                      + 2;      /* account for leading sign or alternate form */
526
                else
527
# endif
528
                if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
529
                  tmp_length = (unsigned int) (sizeof (unsigned long) * CHAR_BIT * 0.25 /* binary -> hexadecimal */
530
                      )
531
                      + 1       /* turn floor into ceil */
532
                      + 2;      /* account for leading sign or alternate form */
533
                else
534
                  tmp_length = (unsigned int) (sizeof (unsigned int) * CHAR_BIT * 0.25  /* binary -> hexadecimal */
535
                      )
536
                      + 1       /* turn floor into ceil */
537
                      + 2;      /* account for leading sign or alternate form */
538
                break;
539
540
              case 'f':
541
              case 'F':
542
# ifdef HAVE_LONG_DOUBLE
543
                if (type == TYPE_LONGDOUBLE)
544
                  tmp_length = (unsigned int) (LDBL_MAX_EXP * 0.30103   /* binary -> decimal */
545
                      * 2       /* estimate for FLAG_GROUP */
546
                      )
547
                      + 1       /* turn floor into ceil */
548
                      + precision + 10; /* sign, decimal point etc. */
549
                else
550
# endif
551
                  tmp_length = (unsigned int) (DBL_MAX_EXP * 0.30103    /* binary -> decimal */
552
                      * 2       /* estimate for FLAG_GROUP */
553
                      )
554
                      + 1       /* turn floor into ceil */
555
                      + precision + 10; /* sign, decimal point etc. */
556
                break;
557
558
              case 'e':
559
              case 'E':
560
              case 'g':
561
              case 'G':
562
              case 'a':
563
              case 'A':
564
                tmp_length = precision + 12;    /* sign, decimal point, exponent etc. */
565
                break;
566
567
              case 'c':
568
# ifdef HAVE_WINT_T
569
                if (type == TYPE_WIDE_CHAR)
570
                  tmp_length = MB_CUR_MAX;
571
                else
572
# endif
573
                  tmp_length = 1;
574
                break;
575
576
              case 's':
577
# ifdef HAVE_WCHAR_T
578
                if (type == TYPE_WIDE_STRING)
579
                  tmp_length = (a.arg[dp->arg_index].a.a_wide_string == NULL ? 6        /* wcslen(L"(null)") */
580
                      : local_wcslen (a.arg[dp->arg_index].a.a_wide_string))
581
                      * MB_CUR_MAX;
582
                else
583
# endif
584
                  tmp_length = a.arg[dp->arg_index].a.a_string == NULL ? 6      /* strlen("(null)") */
585
                      : strlen (a.arg[dp->arg_index].a.a_string);
586
                break;
587
588
              case 'p':
589
                tmp_length = (unsigned int) (sizeof (void *) * CHAR_BIT * 0.25  /* binary -> hexadecimal */
590
                    )
591
                    + 1         /* turn floor into ceil */
592
                    + 2;        /* account for leading 0x */
593
594
                /* make sure we always have enough space for a plain %p, so + */
595
                if (dp->flags & FLAG_PTR_EXT && a.arg[dp->arg_index].ext_string)
596
                  tmp_length += strlen (a.arg[dp->arg_index].ext_string);
597
                break;
598
599
              default:
600
                abort ();
601
            }
602
603
            if (tmp_length < width)
604
              tmp_length = width;
605
606
            tmp_length++;       /* account for trailing NUL */
607
          }
608
609
          if (tmp_length <= sizeof (tmpbuf))
610
            tmp = tmpbuf;
611
          else {
612
            tmp = (char *) malloc (tmp_length);
613
            if (tmp == NULL) {
614
              /* Out of memory.  */
615
              if (!(result == resultbuf || result == NULL))
616
                free (result);
617
              freea (buf);
618
              CLEANUP ();
619
              errno = ENOMEM;
620
              return NULL;
621
            }
622
          }
623
#endif
624
625
          /* Construct the format string for calling snprintf or
626
             sprintf.  */
627
24.7k
          p = buf;
628
24.7k
          *p++ = '%';
629
24.7k
          if (dp->flags & FLAG_GROUP)
630
0
            *p++ = '\'';
631
24.7k
          if (dp->flags & FLAG_LEFT)
632
0
            *p++ = '-';
633
24.7k
          if (dp->flags & FLAG_SHOWSIGN)
634
0
            *p++ = '+';
635
24.7k
          if (dp->flags & FLAG_SPACE)
636
0
            *p++ = ' ';
637
24.7k
          if (dp->flags & FLAG_ALT)
638
0
            *p++ = '#';
639
24.7k
          if (dp->flags & FLAG_ZERO)
640
2.17k
            *p++ = '0';
641
24.7k
          if (dp->width_start != dp->width_end) {
642
2.17k
            size_t n = dp->width_end - dp->width_start;
643
2.17k
            memcpy (p, dp->width_start, n);
644
2.17k
            p += n;
645
2.17k
          }
646
24.7k
          if (dp->precision_start != dp->precision_end) {
647
0
            size_t n = dp->precision_end - dp->precision_start;
648
0
            memcpy (p, dp->precision_start, n);
649
0
            p += n;
650
0
          }
651
652
24.7k
          switch (type) {
653
#ifdef HAVE_INT64_AND_I64
654
            case TYPE_INT64:
655
            case TYPE_UINT64:
656
              *p++ = 'I';
657
              *p++ = '6';
658
              *p++ = '4';
659
              break;
660
#endif
661
0
#ifdef HAVE_LONG_LONG
662
0
            case TYPE_LONGLONGINT:
663
0
            case TYPE_ULONGLONGINT:
664
#ifdef HAVE_INT64_AND_I64       /* The system (sn)printf uses %I64. Also assume
665
                                 * that long long == __int64.
666
                                 */
667
              *p++ = 'I';
668
              *p++ = '6';
669
              *p++ = '4';
670
              break;
671
#else
672
0
              *p++ = 'l';
673
0
              G_GNUC_FALLTHROUGH;
674
0
#endif
675
0
#endif
676
792
            case TYPE_LONGINT:
677
1.06k
            case TYPE_ULONGINT:
678
#ifdef HAVE_WINT_T
679
            case TYPE_WIDE_CHAR:
680
#endif
681
#ifdef HAVE_WCHAR_T
682
            case TYPE_WIDE_STRING:
683
#endif
684
1.06k
              *p++ = 'l';
685
1.06k
              break;
686
#ifdef HAVE_LONG_DOUBLE
687
            case TYPE_LONGDOUBLE:
688
              *p++ = 'L';
689
              break;
690
#endif
691
23.7k
            default:
692
23.7k
              break;
693
24.7k
          }
694
24.7k
          *p = dp->conversion;
695
24.7k
          p[1] = '\0';
696
697
          /* Construct the arguments for calling snprintf or sprintf.  */
698
24.7k
          prefix_count = 0;
699
24.7k
          if (dp->width_arg_index >= 0) {
700
0
            if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
701
0
              abort ();
702
0
            prefixes[prefix_count++] = a.arg[dp->width_arg_index].a.a_int;
703
0
          }
704
24.7k
          if (dp->precision_arg_index >= 0) {
705
0
            if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
706
0
              abort ();
707
0
            prefixes[prefix_count++] = a.arg[dp->precision_arg_index].a.a_int;
708
0
          }
709
24.7k
#ifdef HAVE_SNPRINTF
710
          /* Prepare checking whether snprintf returns the count
711
             via %n.  */
712
24.7k
          ENSURE_ALLOCATION (length + 1);
713
24.7k
          result[length] = '\0';
714
24.7k
#endif
715
716
28.2k
          for (;;) {
717
28.2k
            size_t maxlen;
718
28.2k
            int count;
719
28.2k
#ifdef HAVE_SNPRINTF
720
28.2k
            int retcount;
721
28.2k
#endif
722
723
28.2k
            maxlen = allocated - length;
724
28.2k
            count = -1;
725
726
28.2k
#ifdef HAVE_SNPRINTF
727
28.2k
            retcount = 0;
728
729
28.2k
#define SNPRINTF_BUF(arg) \
730
28.2k
        switch (prefix_count)           \
731
28.2k
          {                 \
732
28.2k
          case 0:               \
733
28.2k
      retcount = snprintf (result + length, maxlen, buf,  \
734
28.2k
               arg, &count);        \
735
28.2k
      break;               \
736
0
          case 1:               \
737
0
      retcount = snprintf (result + length, maxlen, buf,  \
738
0
               prefixes[0], arg, &count);     \
739
0
      break;               \
740
0
          case 2:               \
741
0
      retcount = snprintf (result + length, maxlen, buf,  \
742
0
               prefixes[0], prefixes[1], arg, \
743
0
               &count);         \
744
0
      break;               \
745
0
          default:                \
746
0
      abort ();             \
747
28.2k
          }
748
#else
749
#define SNPRINTF_BUF(arg) \
750
        switch (prefix_count)           \
751
          {                 \
752
          case 0:               \
753
      count = sprintf (tmp, buf, arg);        \
754
      break;                \
755
          case 1:               \
756
      count = sprintf (tmp, buf, prefixes[0], arg);     \
757
      break;                \
758
          case 2:               \
759
      count = sprintf (tmp, buf, prefixes[0], prefixes[1],\
760
           arg);            \
761
      break;                \
762
          default:                \
763
      abort ();             \
764
          }
765
#endif
766
767
28.2k
            switch (type) {
768
0
              case TYPE_SCHAR:
769
0
              {
770
0
                int arg = a.arg[dp->arg_index].a.a_schar;
771
0
                SNPRINTF_BUF (arg);
772
0
              }
773
0
                break;
774
0
              case TYPE_UCHAR:
775
0
              {
776
0
                unsigned int arg = a.arg[dp->arg_index].a.a_uchar;
777
0
                SNPRINTF_BUF (arg);
778
0
              }
779
0
                break;
780
0
              case TYPE_SHORT:
781
0
              {
782
0
                int arg = a.arg[dp->arg_index].a.a_short;
783
0
                SNPRINTF_BUF (arg);
784
0
              }
785
0
                break;
786
0
              case TYPE_USHORT:
787
0
              {
788
0
                unsigned int arg = a.arg[dp->arg_index].a.a_ushort;
789
0
                SNPRINTF_BUF (arg);
790
0
              }
791
0
                break;
792
2.14k
              case TYPE_INT:
793
2.14k
              {
794
2.14k
                int arg = a.arg[dp->arg_index].a.a_int;
795
2.14k
                SNPRINTF_BUF (arg);
796
2.14k
              }
797
0
                break;
798
5.18k
              case TYPE_UINT:
799
5.18k
              {
800
5.18k
                unsigned int arg = a.arg[dp->arg_index].a.a_uint;
801
5.18k
                SNPRINTF_BUF (arg);
802
5.18k
              }
803
0
                break;
804
792
              case TYPE_LONGINT:
805
792
              {
806
792
                long int arg = a.arg[dp->arg_index].a.a_longint;
807
792
                SNPRINTF_BUF (arg);
808
792
              }
809
0
                break;
810
270
              case TYPE_ULONGINT:
811
270
              {
812
270
                unsigned long int arg = a.arg[dp->arg_index].a.a_ulongint;
813
270
                SNPRINTF_BUF (arg);
814
270
              }
815
0
                break;
816
#ifdef HAVE_INT64_AND_I64
817
              case TYPE_INT64:
818
              {
819
                __int64 arg = a.arg[dp->arg_index].a.a_int64;
820
                SNPRINTF_BUF (arg);
821
              }
822
                break;
823
              case TYPE_UINT64:
824
              {
825
                unsigned __int64 arg = a.arg[dp->arg_index].a.a_uint64;
826
                SNPRINTF_BUF (arg);
827
              }
828
                break;
829
#endif
830
0
#ifdef HAVE_LONG_LONG
831
0
#ifndef HAVE_LONG_LONG_FORMAT
832
0
              case TYPE_LONGLONGINT:
833
0
              case TYPE_ULONGLONGINT:
834
0
              {
835
0
                unsigned long long int arg =
836
0
                    a.arg[dp->arg_index].a.a_ulonglongint;
837
0
                int width;
838
0
                int precision;
839
840
0
                width = 0;
841
0
                if (dp->width_start != dp->width_end) {
842
0
                  if (dp->width_arg_index >= 0) {
843
0
                    int arg;
844
845
0
                    if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
846
0
                      abort ();
847
0
                    arg = a.arg[dp->width_arg_index].a.a_int;
848
0
                    width = (arg < 0 ? -arg : arg);
849
0
                  } else {
850
0
                    const char *digitp = dp->width_start;
851
852
0
                    do
853
0
                      width = width * 10 + (*digitp++ - '0');
854
0
                    while (digitp != dp->width_end);
855
0
                  }
856
0
                }
857
858
0
                precision = -1;
859
0
                if (dp->precision_start != dp->precision_end) {
860
0
                  if (dp->precision_arg_index >= 0) {
861
0
                    int arg;
862
863
0
                    if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
864
0
                      abort ();
865
0
                    arg = a.arg[dp->precision_arg_index].a.a_int;
866
0
                    precision = (arg < 0 ? 0 : arg);
867
0
                  } else {
868
0
                    const char *digitp = dp->precision_start + 1;
869
870
0
                    precision = 0;
871
0
                    do
872
0
                      precision = precision * 10 + (*digitp++ - '0');
873
0
                    while (digitp != dp->precision_end);
874
0
                  }
875
0
                }
876
0
#ifdef HAVE_SNPRINTF
877
0
                count = print_long_long (result + length, maxlen,
878
0
                    width, precision, dp->flags, dp->conversion, arg);
879
#else
880
                count = print_long_long (tmp, tmp_length,
881
                    width, precision, dp->flags, dp->conversion, arg);
882
#endif
883
0
              }
884
0
                break;
885
#else
886
              case TYPE_LONGLONGINT:
887
              {
888
                long long int arg = a.arg[dp->arg_index].a.a_longlongint;
889
                SNPRINTF_BUF (arg);
890
              }
891
                break;
892
              case TYPE_ULONGLONGINT:
893
              {
894
                unsigned long long int arg =
895
                    a.arg[dp->arg_index].a.a_ulonglongint;
896
                SNPRINTF_BUF (arg);
897
              }
898
                break;
899
#endif
900
0
#endif
901
0
              case TYPE_DOUBLE:
902
0
              {
903
0
                double arg = a.arg[dp->arg_index].a.a_double;
904
0
                SNPRINTF_BUF (arg);
905
0
              }
906
0
                break;
907
#ifdef HAVE_LONG_DOUBLE
908
              case TYPE_LONGDOUBLE:
909
              {
910
                long double arg = a.arg[dp->arg_index].a.a_longdouble;
911
                SNPRINTF_BUF (arg);
912
              }
913
                break;
914
#endif
915
240
              case TYPE_CHAR:
916
240
              {
917
240
                int arg = a.arg[dp->arg_index].a.a_char;
918
240
                SNPRINTF_BUF (arg);
919
240
              }
920
0
                break;
921
#ifdef HAVE_WINT_T
922
              case TYPE_WIDE_CHAR:
923
              {
924
                wint_t arg = a.arg[dp->arg_index].a.a_wide_char;
925
                SNPRINTF_BUF (arg);
926
              }
927
                break;
928
#endif
929
17.9k
              case TYPE_STRING:
930
17.9k
              {
931
17.9k
                const char *arg = a.arg[dp->arg_index].a.a_string == NULL
932
17.9k
                    ? "(null)" : a.arg[dp->arg_index].a.a_string;
933
17.9k
                SNPRINTF_BUF (arg);
934
17.9k
              }
935
0
                break;
936
#ifdef HAVE_WCHAR_T
937
              case TYPE_WIDE_STRING:
938
              {
939
                const wchar_t *arg =
940
                    a.arg[dp->arg_index].a.a_wide_string ==
941
                    NULL ? L"(null)" : a.arg[dp->arg_index].a.a_wide_string;
942
                SNPRINTF_BUF (arg);
943
              }
944
                break;
945
#endif
946
0
              case TYPE_POINTER:
947
0
              {
948
0
                void *arg = a.arg[dp->arg_index].a.a_pointer;
949
0
                SNPRINTF_BUF (arg);
950
0
              }
951
0
                break;
952
1.63k
              case TYPE_POINTER_EXT:
953
1.63k
              {
954
1.63k
                void *arg = a.arg[dp->arg_index].a.a_pointer;
955
956
1.63k
                if (a.arg[dp->arg_index].ext_string != NULL) {
957
1.63k
                  arg = a.arg[dp->arg_index].ext_string;
958
1.63k
                  *p = 's';
959
1.63k
                }
960
961
1.63k
                SNPRINTF_BUF (arg);
962
1.63k
              }
963
0
                break;
964
0
              default:
965
0
                abort ();
966
28.2k
            }
967
968
28.2k
#ifdef HAVE_SNPRINTF
969
            /* Portability: Not all implementations of snprintf()
970
               are ISO C 99 compliant.  Determine the number of
971
               bytes that snprintf() has produced or would have
972
               produced.  */
973
28.2k
            if (count >= 0) {
974
              /* Verify that snprintf() has NUL-terminated its
975
                 result.  */
976
0
              if (count < maxlen && result[length + count] != '\0')
977
0
                abort ();
978
              /* Portability hack.  */
979
0
              if (retcount > count)
980
0
                count = retcount;
981
28.2k
            } else {
982
              /* snprintf() doesn't understand the '%n'
983
                 directive.  */
984
28.2k
              if (p[1] != '\0') {
985
                /* Don't use the '%n' directive; instead, look
986
                   at the snprintf() return value.  */
987
0
                p[1] = '\0';
988
0
                continue;
989
0
              }
990
28.2k
              count = retcount;
991
28.2k
            }
992
28.2k
#endif
993
994
            /* Attempt to handle failure.  */
995
28.2k
            if (count < 0) {
996
0
              if (!(result == resultbuf || result == NULL))
997
0
                free (result);
998
0
              freea (buf);
999
#ifndef HAVE_SNPRINTF
1000
              if (tmp != tmpbuf)
1001
                free (tmp);
1002
#endif
1003
0
              CLEANUP ();
1004
0
              errno = EINVAL;
1005
0
              return NULL;
1006
0
            }
1007
#ifndef HAVE_SNPRINTF
1008
            if (count >= tmp_length)
1009
              /* tmp_length was incorrectly calculated - fix the
1010
                 code above!  */
1011
              abort ();
1012
#endif
1013
1014
            /* Make room for the result.  */
1015
28.2k
            if (count >= maxlen) {
1016
              /* Need at least count bytes.  But allocate
1017
                 proportionally, to avoid looping eternally if
1018
                 snprintf() reports a too small count.  */
1019
3.45k
              size_t n = length + count;
1020
1021
3.45k
              if (n < 2 * allocated)
1022
2.71k
                n = 2 * allocated;
1023
1024
3.45k
              ENSURE_ALLOCATION (n);
1025
3.45k
#ifdef HAVE_SNPRINTF
1026
3.45k
              continue;
1027
3.45k
#endif
1028
3.45k
            }
1029
24.7k
#ifdef HAVE_SNPRINTF
1030
            /* The snprintf() result did fit.  */
1031
#else
1032
            /* Append the sprintf() result.  */
1033
            memcpy (result + length, tmp, count);
1034
            if (tmp != tmpbuf)
1035
              free (tmp);
1036
#endif
1037
1038
24.7k
            length += count;
1039
24.7k
            break;
1040
28.2k
          }
1041
24.7k
        }
1042
24.7k
      }
1043
24.7k
    }
1044
1045
    /* Add the final NUL.  */
1046
67.4k
    ENSURE_ALLOCATION (length + 1);
1047
67.4k
    result[length] = '\0';
1048
1049
67.4k
    freea (buf);
1050
67.4k
    CLEANUP ();
1051
67.4k
    *lengthp = length;
1052
67.4k
    return result;
1053
67.4k
  }
1054
67.4k
}