~ubuntu-branches/ubuntu/wily/alsaplayer/wily

« back to all changes in this revision

Viewing changes to intl/vasnprintf.c

  • Committer: Bazaar Package Importer
  • Author(s): Hubert Chathi
  • Date: 2007-10-10 15:33:10 UTC
  • mto: (9.2.5 sid)
  • mto: This revision was merged to the branch mainline in revision 15.
  • Revision ID: james.westby@ubuntu.com-20071010153310-h3holq75eu2cigb0
Tags: upstream-0.99.80~rc4
ImportĀ upstreamĀ versionĀ 0.99.80~rc4

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* vsprintf with automatic memory allocation.
 
2
   Copyright (C) 1999, 2002-2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
 
17
   USA.  */
 
18
 
 
19
/* Tell glibc's <stdio.h> to provide a prototype for snprintf().
 
20
   This must come before <config.h> because <config.h> may include
 
21
   <features.h>, and once <features.h> has been included, it's too late.  */
 
22
#ifndef _GNU_SOURCE
 
23
# define _GNU_SOURCE    1
 
24
#endif
 
25
 
 
26
#include <config.h>
 
27
#ifndef IN_LIBINTL
 
28
# include <alloca.h>
 
29
#endif
 
30
 
 
31
/* Specification.  */
 
32
#if WIDE_CHAR_VERSION
 
33
# include "vasnwprintf.h"
 
34
#else
 
35
# include "vasnprintf.h"
 
36
#endif
 
37
 
 
38
#include <stdio.h>      /* snprintf(), sprintf() */
 
39
#include <stdlib.h>     /* abort(), malloc(), realloc(), free() */
 
40
#include <string.h>     /* memcpy(), strlen() */
 
41
#include <errno.h>      /* errno */
 
42
#include <limits.h>     /* CHAR_BIT */
 
43
#include <float.h>      /* DBL_MAX_EXP, LDBL_MAX_EXP */
 
44
#if WIDE_CHAR_VERSION
 
45
# include "wprintf-parse.h"
 
46
#else
 
47
# include "printf-parse.h"
 
48
#endif
 
49
 
 
50
/* Checked size_t computations.  */
 
51
#include "xsize.h"
 
52
 
 
53
#ifdef HAVE_WCHAR_T
 
54
# ifdef HAVE_WCSLEN
 
55
#  define local_wcslen wcslen
 
56
# else
 
57
   /* Solaris 2.5.1 has wcslen() in a separate library libw.so. To avoid
 
58
      a dependency towards this library, here is a local substitute.
 
59
      Define this substitute only once, even if this file is included
 
60
      twice in the same compilation unit.  */
 
61
#  ifndef local_wcslen_defined
 
62
#   define local_wcslen_defined 1
 
63
static size_t
 
64
local_wcslen (const wchar_t *s)
 
65
{
 
66
  const wchar_t *ptr;
 
67
 
 
68
  for (ptr = s; *ptr != (wchar_t) 0; ptr++)
 
69
    ;
 
70
  return ptr - s;
 
71
}
 
72
#  endif
 
73
# endif
 
74
#endif
 
75
 
 
76
#if WIDE_CHAR_VERSION
 
77
# define VASNPRINTF vasnwprintf
 
78
# define CHAR_T wchar_t
 
79
# define DIRECTIVE wchar_t_directive
 
80
# define DIRECTIVES wchar_t_directives
 
81
# define PRINTF_PARSE wprintf_parse
 
82
# define USE_SNPRINTF 1
 
83
# if HAVE_DECL__SNWPRINTF
 
84
   /* On Windows, the function swprintf() has a different signature than
 
85
      on Unix; we use the _snwprintf() function instead.  */
 
86
#  define SNPRINTF _snwprintf
 
87
# else
 
88
   /* Unix.  */
 
89
#  define SNPRINTF swprintf
 
90
# endif
 
91
#else
 
92
# define VASNPRINTF vasnprintf
 
93
# define CHAR_T char
 
94
# define DIRECTIVE char_directive
 
95
# define DIRECTIVES char_directives
 
96
# define PRINTF_PARSE printf_parse
 
97
# define USE_SNPRINTF (HAVE_DECL__SNPRINTF || HAVE_SNPRINTF)
 
98
# if HAVE_DECL__SNPRINTF
 
99
   /* Windows.  */
 
100
#  define SNPRINTF _snprintf
 
101
# else
 
102
   /* Unix.  */
 
103
#  define SNPRINTF snprintf
 
104
# endif
 
105
#endif
 
106
 
 
107
CHAR_T *
 
108
VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list args)
 
109
{
 
110
  DIRECTIVES d;
 
111
  arguments a;
 
112
 
 
113
  if (PRINTF_PARSE (format, &d, &a) < 0)
 
114
    {
 
115
      errno = EINVAL;
 
116
      return NULL;
 
117
    }
 
118
 
 
119
#define CLEANUP() \
 
120
  free (d.dir);                                                         \
 
121
  if (a.arg)                                                            \
 
122
    free (a.arg);
 
123
 
 
124
  if (printf_fetchargs (args, &a) < 0)
 
125
    {
 
126
      CLEANUP ();
 
127
      errno = EINVAL;
 
128
      return NULL;
 
129
    }
 
130
 
 
131
  {
 
132
    size_t buf_neededlength;
 
133
    CHAR_T *buf;
 
134
    CHAR_T *buf_malloced;
 
135
    const CHAR_T *cp;
 
136
    size_t i;
 
137
    DIRECTIVE *dp;
 
138
    /* Output string accumulator.  */
 
139
    CHAR_T *result;
 
140
    size_t allocated;
 
141
    size_t length;
 
142
 
 
143
    /* Allocate a small buffer that will hold a directive passed to
 
144
       sprintf or snprintf.  */
 
145
    buf_neededlength =
 
146
      xsum4 (7, d.max_width_length, d.max_precision_length, 6);
 
147
#if HAVE_ALLOCA
 
148
    if (buf_neededlength < 4000 / sizeof (CHAR_T))
 
149
      {
 
150
        buf = (CHAR_T *) alloca (buf_neededlength * sizeof (CHAR_T));
 
151
        buf_malloced = NULL;
 
152
      }
 
153
    else
 
154
#endif
 
155
      {
 
156
        size_t buf_memsize = xtimes (buf_neededlength, sizeof (CHAR_T));
 
157
        if (size_overflow_p (buf_memsize))
 
158
          goto out_of_memory_1;
 
159
        buf = (CHAR_T *) malloc (buf_memsize);
 
160
        if (buf == NULL)
 
161
          goto out_of_memory_1;
 
162
        buf_malloced = buf;
 
163
      }
 
164
 
 
165
    if (resultbuf != NULL)
 
166
      {
 
167
        result = resultbuf;
 
168
        allocated = *lengthp;
 
169
      }
 
170
    else
 
171
      {
 
172
        result = NULL;
 
173
        allocated = 0;
 
174
      }
 
175
    length = 0;
 
176
    /* Invariants:
 
177
       result is either == resultbuf or == NULL or malloc-allocated.
 
178
       If length > 0, then result != NULL.  */
 
179
 
 
180
    /* Ensures that allocated >= needed.  Aborts through a jump to
 
181
       out_of_memory if needed is SIZE_MAX or otherwise too big.  */
 
182
#define ENSURE_ALLOCATION(needed) \
 
183
    if ((needed) > allocated)                                                \
 
184
      {                                                                      \
 
185
        size_t memory_size;                                                  \
 
186
        CHAR_T *memory;                                                      \
 
187
                                                                             \
 
188
        allocated = (allocated > 0 ? xtimes (allocated, 2) : 12);            \
 
189
        if ((needed) > allocated)                                            \
 
190
          allocated = (needed);                                              \
 
191
        memory_size = xtimes (allocated, sizeof (CHAR_T));                   \
 
192
        if (size_overflow_p (memory_size))                                   \
 
193
          goto out_of_memory;                                                \
 
194
        if (result == resultbuf || result == NULL)                           \
 
195
          memory = (CHAR_T *) malloc (memory_size);                          \
 
196
        else                                                                 \
 
197
          memory = (CHAR_T *) realloc (result, memory_size);                 \
 
198
        if (memory == NULL)                                                  \
 
199
          goto out_of_memory;                                                \
 
200
        if (result == resultbuf && length > 0)                               \
 
201
          memcpy (memory, result, length * sizeof (CHAR_T));                 \
 
202
        result = memory;                                                     \
 
203
      }
 
204
 
 
205
    for (cp = format, i = 0, dp = &d.dir[0]; ; cp = dp->dir_end, i++, dp++)
 
206
      {
 
207
        if (cp != dp->dir_start)
 
208
          {
 
209
            size_t n = dp->dir_start - cp;
 
210
            size_t augmented_length = xsum (length, n);
 
211
 
 
212
            ENSURE_ALLOCATION (augmented_length);
 
213
            memcpy (result + length, cp, n * sizeof (CHAR_T));
 
214
            length = augmented_length;
 
215
          }
 
216
        if (i == d.count)
 
217
          break;
 
218
 
 
219
        /* Execute a single directive.  */
 
220
        if (dp->conversion == '%')
 
221
          {
 
222
            size_t augmented_length;
 
223
 
 
224
            if (!(dp->arg_index == ARG_NONE))
 
225
              abort ();
 
226
            augmented_length = xsum (length, 1);
 
227
            ENSURE_ALLOCATION (augmented_length);
 
228
            result[length] = '%';
 
229
            length = augmented_length;
 
230
          }
 
231
        else
 
232
          {
 
233
            if (!(dp->arg_index != ARG_NONE))
 
234
              abort ();
 
235
 
 
236
            if (dp->conversion == 'n')
 
237
              {
 
238
                switch (a.arg[dp->arg_index].type)
 
239
                  {
 
240
                  case TYPE_COUNT_SCHAR_POINTER:
 
241
                    *a.arg[dp->arg_index].a.a_count_schar_pointer = length;
 
242
                    break;
 
243
                  case TYPE_COUNT_SHORT_POINTER:
 
244
                    *a.arg[dp->arg_index].a.a_count_short_pointer = length;
 
245
                    break;
 
246
                  case TYPE_COUNT_INT_POINTER:
 
247
                    *a.arg[dp->arg_index].a.a_count_int_pointer = length;
 
248
                    break;
 
249
                  case TYPE_COUNT_LONGINT_POINTER:
 
250
                    *a.arg[dp->arg_index].a.a_count_longint_pointer = length;
 
251
                    break;
 
252
#ifdef HAVE_LONG_LONG_INT
 
253
                  case TYPE_COUNT_LONGLONGINT_POINTER:
 
254
                    *a.arg[dp->arg_index].a.a_count_longlongint_pointer = length;
 
255
                    break;
 
256
#endif
 
257
                  default:
 
258
                    abort ();
 
259
                  }
 
260
              }
 
261
            else
 
262
              {
 
263
                arg_type type = a.arg[dp->arg_index].type;
 
264
                CHAR_T *p;
 
265
                unsigned int prefix_count;
 
266
                int prefixes[2];
 
267
#if !USE_SNPRINTF
 
268
                size_t tmp_length;
 
269
                CHAR_T tmpbuf[700];
 
270
                CHAR_T *tmp;
 
271
 
 
272
                /* Allocate a temporary buffer of sufficient size for calling
 
273
                   sprintf.  */
 
274
                {
 
275
                  size_t width;
 
276
                  size_t precision;
 
277
 
 
278
                  width = 0;
 
279
                  if (dp->width_start != dp->width_end)
 
280
                    {
 
281
                      if (dp->width_arg_index != ARG_NONE)
 
282
                        {
 
283
                          int arg;
 
284
 
 
285
                          if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
 
286
                            abort ();
 
287
                          arg = a.arg[dp->width_arg_index].a.a_int;
 
288
                          width = (arg < 0 ? (unsigned int) (-arg) : arg);
 
289
                        }
 
290
                      else
 
291
                        {
 
292
                          const CHAR_T *digitp = dp->width_start;
 
293
 
 
294
                          do
 
295
                            width = xsum (xtimes (width, 10), *digitp++ - '0');
 
296
                          while (digitp != dp->width_end);
 
297
                        }
 
298
                    }
 
299
 
 
300
                  precision = 6;
 
301
                  if (dp->precision_start != dp->precision_end)
 
302
                    {
 
303
                      if (dp->precision_arg_index != ARG_NONE)
 
304
                        {
 
305
                          int arg;
 
306
 
 
307
                          if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
 
308
                            abort ();
 
309
                          arg = a.arg[dp->precision_arg_index].a.a_int;
 
310
                          precision = (arg < 0 ? 0 : arg);
 
311
                        }
 
312
                      else
 
313
                        {
 
314
                          const CHAR_T *digitp = dp->precision_start + 1;
 
315
 
 
316
                          precision = 0;
 
317
                          while (digitp != dp->precision_end)
 
318
                            precision = xsum (xtimes (precision, 10), *digitp++ - '0');
 
319
                        }
 
320
                    }
 
321
 
 
322
                  switch (dp->conversion)
 
323
                    {
 
324
 
 
325
                    case 'd': case 'i': case 'u':
 
326
# ifdef HAVE_LONG_LONG_INT
 
327
                      if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
 
328
                        tmp_length =
 
329
                          (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
 
330
                                          * 0.30103 /* binary -> decimal */
 
331
                                         )
 
332
                          + 1; /* turn floor into ceil */
 
333
                      else
 
334
# endif
 
335
                      if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
 
336
                        tmp_length =
 
337
                          (unsigned int) (sizeof (unsigned long) * CHAR_BIT
 
338
                                          * 0.30103 /* binary -> decimal */
 
339
                                         )
 
340
                          + 1; /* turn floor into ceil */
 
341
                      else
 
342
                        tmp_length =
 
343
                          (unsigned int) (sizeof (unsigned int) * CHAR_BIT
 
344
                                          * 0.30103 /* binary -> decimal */
 
345
                                         )
 
346
                          + 1; /* turn floor into ceil */
 
347
                      if (tmp_length < precision)
 
348
                        tmp_length = precision;
 
349
                      /* Multiply by 2, as an estimate for FLAG_GROUP.  */
 
350
                      tmp_length = xsum (tmp_length, tmp_length);
 
351
                      /* Add 1, to account for a leading sign.  */
 
352
                      tmp_length = xsum (tmp_length, 1);
 
353
                      break;
 
354
 
 
355
                    case 'o':
 
356
# ifdef HAVE_LONG_LONG_INT
 
357
                      if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
 
358
                        tmp_length =
 
359
                          (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
 
360
                                          * 0.333334 /* binary -> octal */
 
361
                                         )
 
362
                          + 1; /* turn floor into ceil */
 
363
                      else
 
364
# endif
 
365
                      if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
 
366
                        tmp_length =
 
367
                          (unsigned int) (sizeof (unsigned long) * CHAR_BIT
 
368
                                          * 0.333334 /* binary -> octal */
 
369
                                         )
 
370
                          + 1; /* turn floor into ceil */
 
371
                      else
 
372
                        tmp_length =
 
373
                          (unsigned int) (sizeof (unsigned int) * CHAR_BIT
 
374
                                          * 0.333334 /* binary -> octal */
 
375
                                         )
 
376
                          + 1; /* turn floor into ceil */
 
377
                      if (tmp_length < precision)
 
378
                        tmp_length = precision;
 
379
                      /* Add 1, to account for a leading sign.  */
 
380
                      tmp_length = xsum (tmp_length, 1);
 
381
                      break;
 
382
 
 
383
                    case 'x': case 'X':
 
384
# ifdef HAVE_LONG_LONG_INT
 
385
                      if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
 
386
                        tmp_length =
 
387
                          (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
 
388
                                          * 0.25 /* binary -> hexadecimal */
 
389
                                         )
 
390
                          + 1; /* turn floor into ceil */
 
391
                      else
 
392
# endif
 
393
                      if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
 
394
                        tmp_length =
 
395
                          (unsigned int) (sizeof (unsigned long) * CHAR_BIT
 
396
                                          * 0.25 /* binary -> hexadecimal */
 
397
                                         )
 
398
                          + 1; /* turn floor into ceil */
 
399
                      else
 
400
                        tmp_length =
 
401
                          (unsigned int) (sizeof (unsigned int) * CHAR_BIT
 
402
                                          * 0.25 /* binary -> hexadecimal */
 
403
                                         )
 
404
                          + 1; /* turn floor into ceil */
 
405
                      if (tmp_length < precision)
 
406
                        tmp_length = precision;
 
407
                      /* Add 2, to account for a leading sign or alternate form.  */
 
408
                      tmp_length = xsum (tmp_length, 2);
 
409
                      break;
 
410
 
 
411
                    case 'f': case 'F':
 
412
# ifdef HAVE_LONG_DOUBLE
 
413
                      if (type == TYPE_LONGDOUBLE)
 
414
                        tmp_length =
 
415
                          (unsigned int) (LDBL_MAX_EXP
 
416
                                          * 0.30103 /* binary -> decimal */
 
417
                                          * 2 /* estimate for FLAG_GROUP */
 
418
                                         )
 
419
                          + 1 /* turn floor into ceil */
 
420
                          + 10; /* sign, decimal point etc. */
 
421
                      else
 
422
# endif
 
423
                        tmp_length =
 
424
                          (unsigned int) (DBL_MAX_EXP
 
425
                                          * 0.30103 /* binary -> decimal */
 
426
                                          * 2 /* estimate for FLAG_GROUP */
 
427
                                         )
 
428
                          + 1 /* turn floor into ceil */
 
429
                          + 10; /* sign, decimal point etc. */
 
430
                      tmp_length = xsum (tmp_length, precision);
 
431
                      break;
 
432
 
 
433
                    case 'e': case 'E': case 'g': case 'G':
 
434
                    case 'a': case 'A':
 
435
                      tmp_length =
 
436
                        12; /* sign, decimal point, exponent etc. */
 
437
                      tmp_length = xsum (tmp_length, precision);
 
438
                      break;
 
439
 
 
440
                    case 'c':
 
441
# if defined HAVE_WINT_T && !WIDE_CHAR_VERSION
 
442
                      if (type == TYPE_WIDE_CHAR)
 
443
                        tmp_length = MB_CUR_MAX;
 
444
                      else
 
445
# endif
 
446
                        tmp_length = 1;
 
447
                      break;
 
448
 
 
449
                    case 's':
 
450
# ifdef HAVE_WCHAR_T
 
451
                      if (type == TYPE_WIDE_STRING)
 
452
                        {
 
453
                          tmp_length =
 
454
                            local_wcslen (a.arg[dp->arg_index].a.a_wide_string);
 
455
 
 
456
#  if !WIDE_CHAR_VERSION
 
457
                          tmp_length = xtimes (tmp_length, MB_CUR_MAX);
 
458
#  endif
 
459
                        }
 
460
                      else
 
461
# endif
 
462
                        tmp_length = strlen (a.arg[dp->arg_index].a.a_string);
 
463
                      break;
 
464
 
 
465
                    case 'p':
 
466
                      tmp_length =
 
467
                        (unsigned int) (sizeof (void *) * CHAR_BIT
 
468
                                        * 0.25 /* binary -> hexadecimal */
 
469
                                       )
 
470
                          + 1 /* turn floor into ceil */
 
471
                          + 2; /* account for leading 0x */
 
472
                      break;
 
473
 
 
474
                    default:
 
475
                      abort ();
 
476
                    }
 
477
 
 
478
                  if (tmp_length < width)
 
479
                    tmp_length = width;
 
480
 
 
481
                  tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */
 
482
                }
 
483
 
 
484
                if (tmp_length <= sizeof (tmpbuf) / sizeof (CHAR_T))
 
485
                  tmp = tmpbuf;
 
486
                else
 
487
                  {
 
488
                    size_t tmp_memsize = xtimes (tmp_length, sizeof (CHAR_T));
 
489
 
 
490
                    if (size_overflow_p (tmp_memsize))
 
491
                      /* Overflow, would lead to out of memory.  */
 
492
                      goto out_of_memory;
 
493
                    tmp = (CHAR_T *) malloc (tmp_memsize);
 
494
                    if (tmp == NULL)
 
495
                      /* Out of memory.  */
 
496
                      goto out_of_memory;
 
497
                  }
 
498
#endif
 
499
 
 
500
                /* Construct the format string for calling snprintf or
 
501
                   sprintf.  */
 
502
                p = buf;
 
503
                *p++ = '%';
 
504
                if (dp->flags & FLAG_GROUP)
 
505
                  *p++ = '\'';
 
506
                if (dp->flags & FLAG_LEFT)
 
507
                  *p++ = '-';
 
508
                if (dp->flags & FLAG_SHOWSIGN)
 
509
                  *p++ = '+';
 
510
                if (dp->flags & FLAG_SPACE)
 
511
                  *p++ = ' ';
 
512
                if (dp->flags & FLAG_ALT)
 
513
                  *p++ = '#';
 
514
                if (dp->flags & FLAG_ZERO)
 
515
                  *p++ = '0';
 
516
                if (dp->width_start != dp->width_end)
 
517
                  {
 
518
                    size_t n = dp->width_end - dp->width_start;
 
519
                    memcpy (p, dp->width_start, n * sizeof (CHAR_T));
 
520
                    p += n;
 
521
                  }
 
522
                if (dp->precision_start != dp->precision_end)
 
523
                  {
 
524
                    size_t n = dp->precision_end - dp->precision_start;
 
525
                    memcpy (p, dp->precision_start, n * sizeof (CHAR_T));
 
526
                    p += n;
 
527
                  }
 
528
 
 
529
                switch (type)
 
530
                  {
 
531
#ifdef HAVE_LONG_LONG_INT
 
532
                  case TYPE_LONGLONGINT:
 
533
                  case TYPE_ULONGLONGINT:
 
534
                    *p++ = 'l';
 
535
                    /*FALLTHROUGH*/
 
536
#endif
 
537
                  case TYPE_LONGINT:
 
538
                  case TYPE_ULONGINT:
 
539
#ifdef HAVE_WINT_T
 
540
                  case TYPE_WIDE_CHAR:
 
541
#endif
 
542
#ifdef HAVE_WCHAR_T
 
543
                  case TYPE_WIDE_STRING:
 
544
#endif
 
545
                    *p++ = 'l';
 
546
                    break;
 
547
#ifdef HAVE_LONG_DOUBLE
 
548
                  case TYPE_LONGDOUBLE:
 
549
                    *p++ = 'L';
 
550
                    break;
 
551
#endif
 
552
                  default:
 
553
                    break;
 
554
                  }
 
555
                *p = dp->conversion;
 
556
#if USE_SNPRINTF
 
557
                p[1] = '%';
 
558
                p[2] = 'n';
 
559
                p[3] = '\0';
 
560
#else
 
561
                p[1] = '\0';
 
562
#endif
 
563
 
 
564
                /* Construct the arguments for calling snprintf or sprintf.  */
 
565
                prefix_count = 0;
 
566
                if (dp->width_arg_index != ARG_NONE)
 
567
                  {
 
568
                    if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
 
569
                      abort ();
 
570
                    prefixes[prefix_count++] = a.arg[dp->width_arg_index].a.a_int;
 
571
                  }
 
572
                if (dp->precision_arg_index != ARG_NONE)
 
573
                  {
 
574
                    if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
 
575
                      abort ();
 
576
                    prefixes[prefix_count++] = a.arg[dp->precision_arg_index].a.a_int;
 
577
                  }
 
578
 
 
579
#if USE_SNPRINTF
 
580
                /* Prepare checking whether snprintf returns the count
 
581
                   via %n.  */
 
582
                ENSURE_ALLOCATION (xsum (length, 1));
 
583
                result[length] = '\0';
 
584
#endif
 
585
 
 
586
                for (;;)
 
587
                  {
 
588
                    size_t maxlen;
 
589
                    int count;
 
590
                    int retcount;
 
591
 
 
592
                    maxlen = allocated - length;
 
593
                    count = -1;
 
594
                    retcount = 0;
 
595
 
 
596
#if USE_SNPRINTF
 
597
# define SNPRINTF_BUF(arg) \
 
598
                    switch (prefix_count)                                   \
 
599
                      {                                                     \
 
600
                      case 0:                                               \
 
601
                        retcount = SNPRINTF (result + length, maxlen, buf,  \
 
602
                                             arg, &count);                  \
 
603
                        break;                                              \
 
604
                      case 1:                                               \
 
605
                        retcount = SNPRINTF (result + length, maxlen, buf,  \
 
606
                                             prefixes[0], arg, &count);     \
 
607
                        break;                                              \
 
608
                      case 2:                                               \
 
609
                        retcount = SNPRINTF (result + length, maxlen, buf,  \
 
610
                                             prefixes[0], prefixes[1], arg, \
 
611
                                             &count);                       \
 
612
                        break;                                              \
 
613
                      default:                                              \
 
614
                        abort ();                                           \
 
615
                      }
 
616
#else
 
617
# define SNPRINTF_BUF(arg) \
 
618
                    switch (prefix_count)                                   \
 
619
                      {                                                     \
 
620
                      case 0:                                               \
 
621
                        count = sprintf (tmp, buf, arg);                    \
 
622
                        break;                                              \
 
623
                      case 1:                                               \
 
624
                        count = sprintf (tmp, buf, prefixes[0], arg);       \
 
625
                        break;                                              \
 
626
                      case 2:                                               \
 
627
                        count = sprintf (tmp, buf, prefixes[0], prefixes[1],\
 
628
                                         arg);                              \
 
629
                        break;                                              \
 
630
                      default:                                              \
 
631
                        abort ();                                           \
 
632
                      }
 
633
#endif
 
634
 
 
635
                    switch (type)
 
636
                      {
 
637
                      case TYPE_SCHAR:
 
638
                        {
 
639
                          int arg = a.arg[dp->arg_index].a.a_schar;
 
640
                          SNPRINTF_BUF (arg);
 
641
                        }
 
642
                        break;
 
643
                      case TYPE_UCHAR:
 
644
                        {
 
645
                          unsigned int arg = a.arg[dp->arg_index].a.a_uchar;
 
646
                          SNPRINTF_BUF (arg);
 
647
                        }
 
648
                        break;
 
649
                      case TYPE_SHORT:
 
650
                        {
 
651
                          int arg = a.arg[dp->arg_index].a.a_short;
 
652
                          SNPRINTF_BUF (arg);
 
653
                        }
 
654
                        break;
 
655
                      case TYPE_USHORT:
 
656
                        {
 
657
                          unsigned int arg = a.arg[dp->arg_index].a.a_ushort;
 
658
                          SNPRINTF_BUF (arg);
 
659
                        }
 
660
                        break;
 
661
                      case TYPE_INT:
 
662
                        {
 
663
                          int arg = a.arg[dp->arg_index].a.a_int;
 
664
                          SNPRINTF_BUF (arg);
 
665
                        }
 
666
                        break;
 
667
                      case TYPE_UINT:
 
668
                        {
 
669
                          unsigned int arg = a.arg[dp->arg_index].a.a_uint;
 
670
                          SNPRINTF_BUF (arg);
 
671
                        }
 
672
                        break;
 
673
                      case TYPE_LONGINT:
 
674
                        {
 
675
                          long int arg = a.arg[dp->arg_index].a.a_longint;
 
676
                          SNPRINTF_BUF (arg);
 
677
                        }
 
678
                        break;
 
679
                      case TYPE_ULONGINT:
 
680
                        {
 
681
                          unsigned long int arg = a.arg[dp->arg_index].a.a_ulongint;
 
682
                          SNPRINTF_BUF (arg);
 
683
                        }
 
684
                        break;
 
685
#ifdef HAVE_LONG_LONG_INT
 
686
                      case TYPE_LONGLONGINT:
 
687
                        {
 
688
                          long long int arg = a.arg[dp->arg_index].a.a_longlongint;
 
689
                          SNPRINTF_BUF (arg);
 
690
                        }
 
691
                        break;
 
692
                      case TYPE_ULONGLONGINT:
 
693
                        {
 
694
                          unsigned long long int arg = a.arg[dp->arg_index].a.a_ulonglongint;
 
695
                          SNPRINTF_BUF (arg);
 
696
                        }
 
697
                        break;
 
698
#endif
 
699
                      case TYPE_DOUBLE:
 
700
                        {
 
701
                          double arg = a.arg[dp->arg_index].a.a_double;
 
702
                          SNPRINTF_BUF (arg);
 
703
                        }
 
704
                        break;
 
705
#ifdef HAVE_LONG_DOUBLE
 
706
                      case TYPE_LONGDOUBLE:
 
707
                        {
 
708
                          long double arg = a.arg[dp->arg_index].a.a_longdouble;
 
709
                          SNPRINTF_BUF (arg);
 
710
                        }
 
711
                        break;
 
712
#endif
 
713
                      case TYPE_CHAR:
 
714
                        {
 
715
                          int arg = a.arg[dp->arg_index].a.a_char;
 
716
                          SNPRINTF_BUF (arg);
 
717
                        }
 
718
                        break;
 
719
#ifdef HAVE_WINT_T
 
720
                      case TYPE_WIDE_CHAR:
 
721
                        {
 
722
                          wint_t arg = a.arg[dp->arg_index].a.a_wide_char;
 
723
                          SNPRINTF_BUF (arg);
 
724
                        }
 
725
                        break;
 
726
#endif
 
727
                      case TYPE_STRING:
 
728
                        {
 
729
                          const char *arg = a.arg[dp->arg_index].a.a_string;
 
730
                          SNPRINTF_BUF (arg);
 
731
                        }
 
732
                        break;
 
733
#ifdef HAVE_WCHAR_T
 
734
                      case TYPE_WIDE_STRING:
 
735
                        {
 
736
                          const wchar_t *arg = a.arg[dp->arg_index].a.a_wide_string;
 
737
                          SNPRINTF_BUF (arg);
 
738
                        }
 
739
                        break;
 
740
#endif
 
741
                      case TYPE_POINTER:
 
742
                        {
 
743
                          void *arg = a.arg[dp->arg_index].a.a_pointer;
 
744
                          SNPRINTF_BUF (arg);
 
745
                        }
 
746
                        break;
 
747
                      default:
 
748
                        abort ();
 
749
                      }
 
750
 
 
751
#if USE_SNPRINTF
 
752
                    /* Portability: Not all implementations of snprintf()
 
753
                       are ISO C 99 compliant.  Determine the number of
 
754
                       bytes that snprintf() has produced or would have
 
755
                       produced.  */
 
756
                    if (count >= 0)
 
757
                      {
 
758
                        /* Verify that snprintf() has NUL-terminated its
 
759
                           result.  */
 
760
                        if (count < maxlen && result[length + count] != '\0')
 
761
                          abort ();
 
762
                        /* Portability hack.  */
 
763
                        if (retcount > count)
 
764
                          count = retcount;
 
765
                      }
 
766
                    else
 
767
                      {
 
768
                        /* snprintf() doesn't understand the '%n'
 
769
                           directive.  */
 
770
                        if (p[1] != '\0')
 
771
                          {
 
772
                            /* Don't use the '%n' directive; instead, look
 
773
                               at the snprintf() return value.  */
 
774
                            p[1] = '\0';
 
775
                            continue;
 
776
                          }
 
777
                        else
 
778
                          {
 
779
                            /* Look at the snprintf() return value.  */
 
780
                            if (retcount < 0)
 
781
                              {
 
782
                                /* HP-UX 10.20 snprintf() is doubly deficient:
 
783
                                   It doesn't understand the '%n' directive,
 
784
                                   *and* it returns -1 (rather than the length
 
785
                                   that would have been required) when the
 
786
                                   buffer is too small.  */
 
787
                                size_t bigger_need =
 
788
                                  xsum (xtimes (allocated, 2), 12);
 
789
                                ENSURE_ALLOCATION (bigger_need);
 
790
                                continue;
 
791
                              }
 
792
                            else
 
793
                              count = retcount;
 
794
                          }
 
795
                      }
 
796
#endif
 
797
 
 
798
                    /* Attempt to handle failure.  */
 
799
                    if (count < 0)
 
800
                      {
 
801
                        if (!(result == resultbuf || result == NULL))
 
802
                          free (result);
 
803
                        if (buf_malloced != NULL)
 
804
                          free (buf_malloced);
 
805
                        CLEANUP ();
 
806
                        errno = EINVAL;
 
807
                        return NULL;
 
808
                      }
 
809
 
 
810
#if !USE_SNPRINTF
 
811
                    if (count >= tmp_length)
 
812
                      /* tmp_length was incorrectly calculated - fix the
 
813
                         code above!  */
 
814
                      abort ();
 
815
#endif
 
816
 
 
817
                    /* Make room for the result.  */
 
818
                    if (count >= maxlen)
 
819
                      {
 
820
                        /* Need at least count bytes.  But allocate
 
821
                           proportionally, to avoid looping eternally if
 
822
                           snprintf() reports a too small count.  */
 
823
                        size_t n =
 
824
                          xmax (xsum (length, count), xtimes (allocated, 2));
 
825
 
 
826
                        ENSURE_ALLOCATION (n);
 
827
#if USE_SNPRINTF
 
828
                        continue;
 
829
#endif
 
830
                      }
 
831
 
 
832
#if USE_SNPRINTF
 
833
                    /* The snprintf() result did fit.  */
 
834
#else
 
835
                    /* Append the sprintf() result.  */
 
836
                    memcpy (result + length, tmp, count * sizeof (CHAR_T));
 
837
                    if (tmp != tmpbuf)
 
838
                      free (tmp);
 
839
#endif
 
840
 
 
841
                    length += count;
 
842
                    break;
 
843
                  }
 
844
              }
 
845
          }
 
846
      }
 
847
 
 
848
    /* Add the final NUL.  */
 
849
    ENSURE_ALLOCATION (xsum (length, 1));
 
850
    result[length] = '\0';
 
851
 
 
852
    if (result != resultbuf && length + 1 < allocated)
 
853
      {
 
854
        /* Shrink the allocated memory if possible.  */
 
855
        CHAR_T *memory;
 
856
 
 
857
        memory = (CHAR_T *) realloc (result, (length + 1) * sizeof (CHAR_T));
 
858
        if (memory != NULL)
 
859
          result = memory;
 
860
      }
 
861
 
 
862
    if (buf_malloced != NULL)
 
863
      free (buf_malloced);
 
864
    CLEANUP ();
 
865
    *lengthp = length;
 
866
    /* Note that we can produce a big string of a length > INT_MAX.  POSIX
 
867
       says that snprintf() fails with errno = EOVERFLOW in this case, but
 
868
       that's only because snprintf() returns an 'int'.  This function does
 
869
       not have this limitation.  */
 
870
    return result;
 
871
 
 
872
  out_of_memory:
 
873
    if (!(result == resultbuf || result == NULL))
 
874
      free (result);
 
875
    if (buf_malloced != NULL)
 
876
      free (buf_malloced);
 
877
  out_of_memory_1:
 
878
    CLEANUP ();
 
879
    errno = ENOMEM;
 
880
    return NULL;
 
881
  }
 
882
}
 
883
 
 
884
#undef SNPRINTF
 
885
#undef USE_SNPRINTF
 
886
#undef PRINTF_PARSE
 
887
#undef DIRECTIVES
 
888
#undef DIRECTIVE
 
889
#undef CHAR_T
 
890
#undef VASNPRINTF