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

  1. /* Formatted output to strings.
  2.    Copyright (C) 1999-2000, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
  17.    USA.  */
  18.  
  19. #ifdef HAVE_CONFIG_H
  20. # include <config.h>
  21. #endif
  22.  
  23. /* Specification.  */
  24. #if WIDE_CHAR_VERSION
  25. # include "wprintf-parse.h"
  26. #else
  27. # include "printf-parse.h"
  28. #endif
  29.  
  30. /* Get size_t, NULL.  */
  31. #include <stddef.h>
  32.  
  33. /* Get intmax_t.  */
  34. #if HAVE_STDINT_H_WITH_UINTMAX
  35. # include <stdint.h>
  36. #endif
  37. #if HAVE_INTTYPES_H_WITH_UINTMAX
  38. # include <inttypes.h>
  39. #endif
  40.  
  41. /* malloc(), realloc(), free().  */
  42. #include <stdlib.h>
  43.  
  44. /* Checked size_t computations.  */
  45. #include "xsize.h"
  46.  
  47. #if WIDE_CHAR_VERSION
  48. # define PRINTF_PARSE wprintf_parse
  49. # define CHAR_T wchar_t
  50. # define DIRECTIVE wchar_t_directive
  51. # define DIRECTIVES wchar_t_directives
  52. #else
  53. # define PRINTF_PARSE printf_parse
  54. # define CHAR_T char
  55. # define DIRECTIVE char_directive
  56. # define DIRECTIVES char_directives
  57. #endif
  58.  
  59. #ifdef STATIC
  60. STATIC
  61. #endif
  62. int
  63. PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a)
  64. {
  65.   const CHAR_T *cp = format;        /* pointer into format */
  66.   size_t arg_posn = 0;        /* number of regular arguments consumed */
  67.   size_t d_allocated;            /* allocated elements of d->dir */
  68.   size_t a_allocated;            /* allocated elements of a->arg */
  69.   size_t max_width_length = 0;
  70.   size_t max_precision_length = 0;
  71.  
  72.   d->count = 0;
  73.   d_allocated = 1;
  74.   d->dir = malloc (d_allocated * sizeof (DIRECTIVE));
  75.   if (d->dir == NULL)
  76.     /* Out of memory.  */
  77.     return -1;
  78.  
  79.   a->count = 0;
  80.   a_allocated = 0;
  81.   a->arg = NULL;
  82.  
  83. #define REGISTER_ARG(_index_,_type_) \
  84.   {                                    \
  85.     size_t n = (_index_);                        \
  86.     if (n >= a_allocated)                        \
  87.       {                                    \
  88.     size_t memory_size;                        \
  89.     argument *memory;                        \
  90.                                     \
  91.     a_allocated = xtimes (a_allocated, 2);                \
  92.     if (a_allocated <= n)                        \
  93.       a_allocated = xsum (n, 1);                    \
  94.     memory_size = xtimes (a_allocated, sizeof (argument));        \
  95.     if (size_overflow_p (memory_size))                \
  96.       /* Overflow, would lead to out of memory.  */            \
  97.       goto error;                            \
  98.     memory = (a->arg                        \
  99.           ? realloc (a->arg, memory_size)            \
  100.           : malloc (memory_size));                \
  101.     if (memory == NULL)                        \
  102.       /* Out of memory.  */                        \
  103.       goto error;                            \
  104.     a->arg = memory;                        \
  105.       }                                    \
  106.     while (a->count <= n)                        \
  107.       a->arg[a->count++].type = TYPE_NONE;                \
  108.     if (a->arg[n].type == TYPE_NONE)                    \
  109.       a->arg[n].type = (_type_);                    \
  110.     else if (a->arg[n].type != (_type_))                \
  111.       /* Ambiguous type for positional argument.  */            \
  112.       goto error;                            \
  113.   }
  114.  
  115.   while (*cp != '\0')
  116.     {
  117.       CHAR_T c = *cp++;
  118.       if (c == '%')
  119.     {
  120.       size_t arg_index = ARG_NONE;
  121.       DIRECTIVE *dp = &d->dir[d->count];/* pointer to next directive */
  122.  
  123.       /* Initialize the next directive.  */
  124.       dp->dir_start = cp - 1;
  125.       dp->flags = 0;
  126.       dp->width_start = NULL;
  127.       dp->width_end = NULL;
  128.       dp->width_arg_index = ARG_NONE;
  129.       dp->precision_start = NULL;
  130.       dp->precision_end = NULL;
  131.       dp->precision_arg_index = ARG_NONE;
  132.       dp->arg_index = ARG_NONE;
  133.  
  134.       /* Test for positional argument.  */
  135.       if (*cp >= '0' && *cp <= '9')
  136.         {
  137.           const CHAR_T *np;
  138.  
  139.           for (np = cp; *np >= '0' && *np <= '9'; np++)
  140.         ;
  141.           if (*np == '$')
  142.         {
  143.           size_t n = 0;
  144.  
  145.           for (np = cp; *np >= '0' && *np <= '9'; np++)
  146.             n = xsum (xtimes (n, 10), *np - '0');
  147.           if (n == 0)
  148.             /* Positional argument 0.  */
  149.             goto error;
  150.           if (size_overflow_p (n))
  151.             /* n too large, would lead to out of memory later.  */
  152.             goto error;
  153.           arg_index = n - 1;
  154.           cp = np + 1;
  155.         }
  156.         }
  157.  
  158.       /* Read the flags.  */
  159.       for (;;)
  160.         {
  161.           if (*cp == '\'')
  162.         {
  163.           dp->flags |= FLAG_GROUP;
  164.           cp++;
  165.         }
  166.           else if (*cp == '-')
  167.         {
  168.           dp->flags |= FLAG_LEFT;
  169.           cp++;
  170.         }
  171.           else if (*cp == '+')
  172.         {
  173.           dp->flags |= FLAG_SHOWSIGN;
  174.           cp++;
  175.         }
  176.           else if (*cp == ' ')
  177.         {
  178.           dp->flags |= FLAG_SPACE;
  179.           cp++;
  180.         }
  181.           else if (*cp == '#')
  182.         {
  183.           dp->flags |= FLAG_ALT;
  184.           cp++;
  185.         }
  186.           else if (*cp == '0')
  187.         {
  188.           dp->flags |= FLAG_ZERO;
  189.           cp++;
  190.         }
  191.           else
  192.         break;
  193.         }
  194.  
  195.       /* Parse the field width.  */
  196.       if (*cp == '*')
  197.         {
  198.           dp->width_start = cp;
  199.           cp++;
  200.           dp->width_end = cp;
  201.           if (max_width_length < 1)
  202.         max_width_length = 1;
  203.  
  204.           /* Test for positional argument.  */
  205.           if (*cp >= '0' && *cp <= '9')
  206.         {
  207.           const CHAR_T *np;
  208.  
  209.           for (np = cp; *np >= '0' && *np <= '9'; np++)
  210.             ;
  211.           if (*np == '$')
  212.             {
  213.               size_t n = 0;
  214.  
  215.               for (np = cp; *np >= '0' && *np <= '9'; np++)
  216.             n = xsum (xtimes (n, 10), *np - '0');
  217.               if (n == 0)
  218.             /* Positional argument 0.  */
  219.             goto error;
  220.               if (size_overflow_p (n))
  221.             /* n too large, would lead to out of memory later.  */
  222.             goto error;
  223.               dp->width_arg_index = n - 1;
  224.               cp = np + 1;
  225.             }
  226.         }
  227.           if (dp->width_arg_index == ARG_NONE)
  228.         {
  229.           dp->width_arg_index = arg_posn++;
  230.           if (dp->width_arg_index == ARG_NONE)
  231.             /* arg_posn wrapped around.  */
  232.             goto error;
  233.         }
  234.           REGISTER_ARG (dp->width_arg_index, TYPE_INT);
  235.         }
  236.       else if (*cp >= '0' && *cp <= '9')
  237.         {
  238.           size_t width_length;
  239.  
  240.           dp->width_start = cp;
  241.           for (; *cp >= '0' && *cp <= '9'; cp++)
  242.         ;
  243.           dp->width_end = cp;
  244.           width_length = dp->width_end - dp->width_start;
  245.           if (max_width_length < width_length)
  246.         max_width_length = width_length;
  247.         }
  248.  
  249.       /* Parse the precision.  */
  250.       if (*cp == '.')
  251.         {
  252.           cp++;
  253.           if (*cp == '*')
  254.         {
  255.           dp->precision_start = cp - 1;
  256.           cp++;
  257.           dp->precision_end = cp;
  258.           if (max_precision_length < 2)
  259.             max_precision_length = 2;
  260.  
  261.           /* Test for positional argument.  */
  262.           if (*cp >= '0' && *cp <= '9')
  263.             {
  264.               const CHAR_T *np;
  265.  
  266.               for (np = cp; *np >= '0' && *np <= '9'; np++)
  267.             ;
  268.               if (*np == '$')
  269.             {
  270.               size_t n = 0;
  271.  
  272.               for (np = cp; *np >= '0' && *np <= '9'; np++)
  273.                 n = xsum (xtimes (n, 10), *np - '0');
  274.               if (n == 0)
  275.                 /* Positional argument 0.  */
  276.                 goto error;
  277.               if (size_overflow_p (n))
  278.                 /* n too large, would lead to out of memory
  279.                    later.  */
  280.                 goto error;
  281.               dp->precision_arg_index = n - 1;
  282.               cp = np + 1;
  283.             }
  284.             }
  285.           if (dp->precision_arg_index == ARG_NONE)
  286.             {
  287.               dp->precision_arg_index = arg_posn++;
  288.               if (dp->precision_arg_index == ARG_NONE)
  289.             /* arg_posn wrapped around.  */
  290.             goto error;
  291.             }
  292.           REGISTER_ARG (dp->precision_arg_index, TYPE_INT);
  293.         }
  294.           else
  295.         {
  296.           size_t precision_length;
  297.  
  298.           dp->precision_start = cp - 1;
  299.           for (; *cp >= '0' && *cp <= '9'; cp++)
  300.             ;
  301.           dp->precision_end = cp;
  302.           precision_length = dp->precision_end - dp->precision_start;
  303.           if (max_precision_length < precision_length)
  304.             max_precision_length = precision_length;
  305.         }
  306.         }
  307.  
  308.       {
  309.         arg_type type;
  310.  
  311.         /* Parse argument type/size specifiers.  */
  312.         {
  313.           int flags = 0;
  314.  
  315.           for (;;)
  316.         {
  317.           if (*cp == 'h')
  318.             {
  319.               flags |= (1 << (flags & 1));
  320.               cp++;
  321.             }
  322.           else if (*cp == 'L')
  323.             {
  324.               flags |= 4;
  325.               cp++;
  326.             }
  327.           else if (*cp == 'l')
  328.             {
  329.               flags += 8;
  330.               cp++;
  331.             }
  332. #ifdef HAVE_INTMAX_T
  333.           else if (*cp == 'j')
  334.             {
  335.               if (sizeof (intmax_t) > sizeof (long))
  336.             {
  337.               /* intmax_t = long long */
  338.               flags += 16;
  339.             }
  340.               else if (sizeof (intmax_t) > sizeof (int))
  341.             {
  342.               /* intmax_t = long */
  343.               flags += 8;
  344.             }
  345.               cp++;
  346.             }
  347. #endif
  348.           else if (*cp == 'z' || *cp == 'Z')
  349.             {
  350.               /* 'z' is standardized in ISO C 99, but glibc uses 'Z'
  351.              because the warning facility in gcc-2.95.2 understands
  352.              only 'Z' (see gcc-2.95.2/gcc/c-common.c:1784).  */
  353.               if (sizeof (size_t) > sizeof (long))
  354.             {
  355.               /* size_t = long long */
  356.               flags += 16;
  357.             }
  358.               else if (sizeof (size_t) > sizeof (int))
  359.             {
  360.               /* size_t = long */
  361.               flags += 8;
  362.             }
  363.               cp++;
  364.             }
  365.           else if (*cp == 't')
  366.             {
  367.               if (sizeof (ptrdiff_t) > sizeof (long))
  368.             {
  369.               /* ptrdiff_t = long long */
  370.               flags += 16;
  371.             }
  372.               else if (sizeof (ptrdiff_t) > sizeof (int))
  373.             {
  374.               /* ptrdiff_t = long */
  375.               flags += 8;
  376.             }
  377.               cp++;
  378.             }
  379.           else
  380.             break;
  381.         }
  382.  
  383.           /* Read the conversion character.  */
  384.           c = *cp++;
  385.           switch (c)
  386.         {
  387.         case 'd': case 'i':
  388. #ifdef HAVE_LONG_LONG
  389.           if (flags >= 16 || (flags & 4))
  390.             type = TYPE_LONGLONGINT;
  391.           else
  392. #endif
  393.           if (flags >= 8)
  394.             type = TYPE_LONGINT;
  395.           else if (flags & 2)
  396.             type = TYPE_SCHAR;
  397.           else if (flags & 1)
  398.             type = TYPE_SHORT;
  399.           else
  400.             type = TYPE_INT;
  401.           break;
  402.         case 'o': case 'u': case 'x': case 'X':
  403. #ifdef HAVE_LONG_LONG
  404.           if (flags >= 16 || (flags & 4))
  405.             type = TYPE_ULONGLONGINT;
  406.           else
  407. #endif
  408.           if (flags >= 8)
  409.             type = TYPE_ULONGINT;
  410.           else if (flags & 2)
  411.             type = TYPE_UCHAR;
  412.           else if (flags & 1)
  413.             type = TYPE_USHORT;
  414.           else
  415.             type = TYPE_UINT;
  416.           break;
  417.         case 'f': case 'F': case 'e': case 'E': case 'g': case 'G':
  418.         case 'a': case 'A':
  419. #ifdef HAVE_LONG_DOUBLE
  420.           if (flags >= 16 || (flags & 4))
  421.             type = TYPE_LONGDOUBLE;
  422.           else
  423. #endif
  424.           type = TYPE_DOUBLE;
  425.           break;
  426.         case 'c':
  427.           if (flags >= 8)
  428. #ifdef HAVE_WINT_T
  429.             type = TYPE_WIDE_CHAR;
  430. #else
  431.             goto error;
  432. #endif
  433.           else
  434.             type = TYPE_CHAR;
  435.           break;
  436. #ifdef HAVE_WINT_T
  437.         case 'C':
  438.           type = TYPE_WIDE_CHAR;
  439.           c = 'c';
  440.           break;
  441. #endif
  442.         case 's':
  443.           if (flags >= 8)
  444. #ifdef HAVE_WCHAR_T
  445.             type = TYPE_WIDE_STRING;
  446. #else
  447.             goto error;
  448. #endif
  449.           else
  450.             type = TYPE_STRING;
  451.           break;
  452. #ifdef HAVE_WCHAR_T
  453.         case 'S':
  454.           type = TYPE_WIDE_STRING;
  455.           c = 's';
  456.           break;
  457. #endif
  458.         case 'p':
  459.           type = TYPE_POINTER;
  460.           break;
  461.         case 'n':
  462. #ifdef HAVE_LONG_LONG
  463.           if (flags >= 16 || (flags & 4))
  464.             type = TYPE_COUNT_LONGLONGINT_POINTER;
  465.           else
  466. #endif
  467.           if (flags >= 8)
  468.             type = TYPE_COUNT_LONGINT_POINTER;
  469.           else if (flags & 2)
  470.             type = TYPE_COUNT_SCHAR_POINTER;
  471.           else if (flags & 1)
  472.             type = TYPE_COUNT_SHORT_POINTER;
  473.           else
  474.             type = TYPE_COUNT_INT_POINTER;
  475.           break;
  476.         case '%':
  477.           type = TYPE_NONE;
  478.           break;
  479.         default:
  480.           /* Unknown conversion character.  */
  481.           goto error;
  482.         }
  483.         }
  484.  
  485.         if (type != TYPE_NONE)
  486.           {
  487.         dp->arg_index = arg_index;
  488.         if (dp->arg_index == ARG_NONE)
  489.           {
  490.             dp->arg_index = arg_posn++;
  491.             if (dp->arg_index == ARG_NONE)
  492.               /* arg_posn wrapped around.  */
  493.               goto error;
  494.           }
  495.         REGISTER_ARG (dp->arg_index, type);
  496.           }
  497.         dp->conversion = c;
  498.         dp->dir_end = cp;
  499.       }
  500.  
  501.       d->count++;
  502.       if (d->count >= d_allocated)
  503.         {
  504.           size_t memory_size;
  505.           DIRECTIVE *memory;
  506.  
  507.           d_allocated = xtimes (d_allocated, 2);
  508.           memory_size = xtimes (d_allocated, sizeof (DIRECTIVE));
  509.           if (size_overflow_p (memory_size))
  510.         /* Overflow, would lead to out of memory.  */
  511.         goto error;
  512.           memory = realloc (d->dir, memory_size);
  513.           if (memory == NULL)
  514.         /* Out of memory.  */
  515.         goto error;
  516.           d->dir = memory;
  517.         }
  518.     }
  519.     }
  520.   d->dir[d->count].dir_start = cp;
  521.  
  522.   d->max_width_length = max_width_length;
  523.   d->max_precision_length = max_precision_length;
  524.   return 0;
  525.  
  526. error:
  527.   if (a->arg)
  528.     free (a->arg);
  529.   if (d->dir)
  530.     free (d->dir);
  531.   return -1;
  532. }
  533.  
  534. #undef DIRECTIVES
  535. #undef DIRECTIVE
  536. #undef CHAR_T
  537. #undef PRINTF_PARSE
  538.