~ubuntu-branches/debian/squeeze/libgpg-error/squeeze

« back to all changes in this revision

Viewing changes to intl/vasnprintf.c

  • Committer: Bazaar Package Importer
  • Author(s): Jose Carlos Garcia Sogo
  • Date: 2006-09-24 16:33:03 UTC
  • mfrom: (1.2.1 upstream) (2.1.3 edgy)
  • Revision ID: james.westby@ubuntu.com-20060924163303-2secsa8lts3hhhct
Tags: 1.4-1
* New upstream version.
* Bumped Standards-Version to 3.7.2. No changes needed.
* Use {binary:Version} field in libgpg-error-dev dependecy field. (Closes: #384376)
* Fix typo in upstream URL at debian/copyright file (Closes: #387735)
* debian/patches: Disable m4_macros and 10_relibtoolize patches.
  Upstream uses now a quite current copy of gettext.
* Update FSF address in debian/copyright file.

Show diffs side-by-side

added added

removed removed

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