~ubuntu-branches/ubuntu/utopic/glib2.0/utopic

« back to all changes in this revision

Viewing changes to glib/gnulib/vasnprintf.c

Tags: upstream-2.12.12
ImportĀ upstreamĀ versionĀ 2.12.12

Show diffs side-by-side

added added

removed removed

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