/[zanavi_public1]/navit/intl/vasnprintf.c
ZANavi

Contents of /navit/intl/vasnprintf.c

Parent Directory Parent Directory | Revision Log Revision Log


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

   
Visit the ZANavi Wiki