home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2006 November (DVD) / PCWELT_11_2006.ISO / casper / filesystem.squashfs / usr / share / gettext / intl / vasnprintf.c < prev    next >
Encoding:
C/C++ Source or Header  |  2006-08-18  |  22.0 KB  |  903 lines

  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
  903.