LCOV - code coverage report
Current view: top level - home/branden/src/GIT/groff/lib - printf-parse.c (source / functions) Hit Total Coverage
Test: GNU roff Lines: 113 288 39.2 %
Date: 2026-01-16 17:51:41 Functions: 1 1 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* Formatted output to strings.
       2             :    Copyright (C) 1999-2000, 2002-2003, 2006-2025 Free Software Foundation, Inc.
       3             : 
       4             :    This file is free software: you can redistribute it and/or modify
       5             :    it under the terms of the GNU Lesser General Public License as
       6             :    published by the Free Software Foundation; either version 2.1 of the
       7             :    License, or (at your option) any later version.
       8             : 
       9             :    This file 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
      12             :    GNU Lesser General Public License for more details.
      13             : 
      14             :    You should have received a copy of the GNU Lesser General Public License
      15             :    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
      16             : 
      17             : /* This file can be parametrized with the following macros:
      18             :      CHAR_T             The element type of the format string.
      19             :      CHAR_T_ONLY_ASCII  Set to 1 to enable verification that all characters
      20             :                         in the format string are ASCII.
      21             :      DIRECTIVE          Structure denoting a format directive.
      22             :                         Depends on CHAR_T.
      23             :      DIRECTIVES         Structure denoting the set of format directives of a
      24             :                         format string.  Depends on CHAR_T.
      25             :      PRINTF_PARSE       Function that parses a format string.
      26             :                         Depends on CHAR_T.
      27             :      STATIC             Set to 'static' to declare the function static.
      28             :      ENABLE_UNISTDIO    Set to 1 to enable the unistdio extensions.  */
      29             : 
      30             : #ifndef PRINTF_PARSE
      31             : # include <config.h>
      32             : #endif
      33             : 
      34             : /* Specification.  */
      35             : #ifndef PRINTF_PARSE
      36             : # include "printf-parse.h"
      37             : #endif
      38             : 
      39             : /* Default parameters.  */
      40             : #ifndef PRINTF_PARSE
      41             : # define PRINTF_PARSE printf_parse
      42             : # define CHAR_T char
      43             : # define DIRECTIVE char_directive
      44             : # define DIRECTIVES char_directives
      45             : #endif
      46             : 
      47             : /* Get size_t, NULL.  */
      48             : #include <stddef.h>
      49             : 
      50             : /* Get intmax_t.  */
      51             : #include <stdint.h>
      52             : 
      53             : /* malloc(), realloc(), free().  */
      54             : #include <stdlib.h>
      55             : 
      56             : /* memcpy().  */
      57             : #include <string.h>
      58             : 
      59             : /* errno.  */
      60             : #include <errno.h>
      61             : 
      62             : /* Checked size_t computations.  */
      63             : #include "xsize.h"
      64             : 
      65             : #if CHAR_T_ONLY_ASCII
      66             : /* c_isascii().  */
      67             : # include "c-ctype.h"
      68             : #endif
      69             : 
      70             : #ifdef STATIC
      71             : STATIC
      72             : #endif
      73             : int
      74       14391 : PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a)
      75             : {
      76       14391 :   const CHAR_T *cp = format;    /* pointer into format */
      77       14391 :   size_t arg_posn = 0;          /* number of regular arguments consumed */
      78             :   size_t d_allocated;           /* allocated elements of d->dir */
      79             :   size_t a_allocated;           /* allocated elements of a->arg */
      80       14391 :   size_t max_width_length = 0;
      81       14391 :   size_t max_precision_length = 0;
      82             : 
      83       14391 :   d->count = 0;
      84       14391 :   d_allocated = N_DIRECT_ALLOC_DIRECTIVES;
      85       14391 :   d->dir = d->direct_alloc_dir;
      86             : 
      87       14391 :   a->count = 0;
      88       14391 :   a_allocated = N_DIRECT_ALLOC_ARGUMENTS;
      89       14391 :   a->arg = a->direct_alloc_arg;
      90             : 
      91             : #define REGISTER_ARG(_index_,_type_) \
      92             :   {                                                                     \
      93             :     size_t n = (_index_);                                               \
      94             :     if (n >= a_allocated)                                               \
      95             :       {                                                                 \
      96             :         size_t memory_size;                                             \
      97             :         argument *memory;                                               \
      98             :                                                                         \
      99             :         a_allocated = xtimes (a_allocated, 2);                          \
     100             :         if (a_allocated <= n)                                           \
     101             :           a_allocated = xsum (n, 1);                                    \
     102             :         memory_size = xtimes (a_allocated, sizeof (argument));          \
     103             :         if (size_overflow_p (memory_size))                              \
     104             :           /* Overflow, would lead to out of memory.  */                 \
     105             :           goto out_of_memory;                                           \
     106             :         memory = (argument *) (a->arg != a->direct_alloc_arg            \
     107             :                                ? realloc (a->arg, memory_size)          \
     108             :                                : malloc (memory_size));                 \
     109             :         if (memory == NULL)                                             \
     110             :           /* Out of memory.  */                                         \
     111             :           goto out_of_memory;                                           \
     112             :         if (a->arg == a->direct_alloc_arg)                              \
     113             :           memcpy (memory, a->arg, a->count * sizeof (argument));        \
     114             :         a->arg = memory;                                                \
     115             :       }                                                                 \
     116             :     while (a->count <= n)                                               \
     117             :       a->arg[a->count++].type = TYPE_NONE;                              \
     118             :     if (a->arg[n].type == TYPE_NONE)                                    \
     119             :       a->arg[n].type = (_type_);                                        \
     120             :     else if (a->arg[n].type != (_type_))                                \
     121             :       /* Ambiguous type for positional argument.  */                    \
     122             :       goto error;                                                       \
     123             :   }
     124             : 
     125       40944 :   while (*cp != '\0')
     126             :     {
     127       26553 :       CHAR_T c = *cp++;
     128       26553 :       if (c == '%')
     129             :         {
     130       15407 :           size_t arg_index = ARG_NONE;
     131       15407 :           DIRECTIVE *dp = &d->dir[d->count]; /* pointer to next directive */
     132             : 
     133             :           /* Initialize the next directive.  */
     134       15407 :           dp->dir_start = cp - 1;
     135       15407 :           dp->flags = 0;
     136       15407 :           dp->width_start = NULL;
     137       15407 :           dp->width_end = NULL;
     138       15407 :           dp->width_arg_index = ARG_NONE;
     139       15407 :           dp->precision_start = NULL;
     140       15407 :           dp->precision_end = NULL;
     141       15407 :           dp->precision_arg_index = ARG_NONE;
     142       15407 :           dp->arg_index = ARG_NONE;
     143             : 
     144             :           /* Test for positional argument.  */
     145       15407 :           if (*cp >= '0' && *cp <= '9')
     146             :             {
     147             :               const CHAR_T *np;
     148             : 
     149       40875 :               for (np = cp; *np >= '0' && *np <= '9'; np++)
     150             :                 ;
     151       13625 :               if (*np == '$')
     152             :                 {
     153           0 :                   size_t n = 0;
     154             : 
     155           0 :                   for (np = cp; *np >= '0' && *np <= '9'; np++)
     156           0 :                     n = xsum (xtimes (n, 10), *np - '0');
     157           0 :                   if (n == 0)
     158             :                     /* Positional argument 0.  */
     159           0 :                     goto error;
     160           0 :                   if (size_overflow_p (n))
     161             :                     /* n too large, would lead to out of memory later.  */
     162           0 :                     goto error;
     163           0 :                   arg_index = n - 1;
     164           0 :                   cp = np + 1;
     165             :                 }
     166             :             }
     167             : 
     168             :           /* Read the flags.  */
     169             :           for (;;)
     170             :             {
     171       29032 :               if (*cp == '\'')
     172             :                 {
     173           0 :                   dp->flags |= FLAG_GROUP;
     174           0 :                   cp++;
     175             :                 }
     176       29032 :               else if (*cp == '-')
     177             :                 {
     178           0 :                   dp->flags |= FLAG_LEFT;
     179           0 :                   cp++;
     180             :                 }
     181       29032 :               else if (*cp == '+')
     182             :                 {
     183           0 :                   dp->flags |= FLAG_SHOWSIGN;
     184           0 :                   cp++;
     185             :                 }
     186       29032 :               else if (*cp == ' ')
     187             :                 {
     188           0 :                   dp->flags |= FLAG_SPACE;
     189           0 :                   cp++;
     190             :                 }
     191       29032 :               else if (*cp == '#')
     192             :                 {
     193           0 :                   dp->flags |= FLAG_ALT;
     194           0 :                   cp++;
     195             :                 }
     196       29032 :               else if (*cp == '0')
     197             :                 {
     198       13625 :                   dp->flags |= FLAG_ZERO;
     199       13625 :                   cp++;
     200             :                 }
     201             : #if __GLIBC__ >= 2 && !defined __UCLIBC__
     202       15407 :               else if (*cp == 'I')
     203             :                 {
     204           0 :                   dp->flags |= FLAG_LOCALIZED;
     205           0 :                   cp++;
     206             :                 }
     207             : #endif
     208             :               else
     209       15407 :                 break;
     210             :             }
     211             : 
     212             :           /* Parse the field width.  */
     213       15407 :           if (*cp == '*')
     214             :             {
     215           0 :               dp->width_start = cp;
     216           0 :               cp++;
     217           0 :               dp->width_end = cp;
     218           0 :               if (max_width_length < 1)
     219           0 :                 max_width_length = 1;
     220             : 
     221             :               /* Test for positional argument.  */
     222           0 :               if (*cp >= '0' && *cp <= '9')
     223             :                 {
     224             :                   const CHAR_T *np;
     225             : 
     226           0 :                   for (np = cp; *np >= '0' && *np <= '9'; np++)
     227             :                     ;
     228           0 :                   if (*np == '$')
     229             :                     {
     230           0 :                       size_t n = 0;
     231             : 
     232           0 :                       for (np = cp; *np >= '0' && *np <= '9'; np++)
     233           0 :                         n = xsum (xtimes (n, 10), *np - '0');
     234           0 :                       if (n == 0)
     235             :                         /* Positional argument 0.  */
     236           0 :                         goto error;
     237           0 :                       if (size_overflow_p (n))
     238             :                         /* n too large, would lead to out of memory later.  */
     239           0 :                         goto error;
     240           0 :                       dp->width_arg_index = n - 1;
     241           0 :                       cp = np + 1;
     242             :                     }
     243             :                 }
     244           0 :               if (dp->width_arg_index == ARG_NONE)
     245             :                 {
     246           0 :                   dp->width_arg_index = arg_posn++;
     247           0 :                   if (dp->width_arg_index == ARG_NONE)
     248             :                     /* arg_posn wrapped around.  */
     249           0 :                     goto error;
     250             :                 }
     251           0 :               REGISTER_ARG (dp->width_arg_index, TYPE_INT);
     252             :             }
     253       15407 :           else if (*cp >= '0' && *cp <= '9')
     254             :             {
     255             :               size_t width_length;
     256             : 
     257       13625 :               dp->width_start = cp;
     258       27250 :               for (; *cp >= '0' && *cp <= '9'; cp++)
     259             :                 ;
     260       13625 :               dp->width_end = cp;
     261       13625 :               width_length = dp->width_end - dp->width_start;
     262       13625 :               if (max_width_length < width_length)
     263       13625 :                 max_width_length = width_length;
     264             :             }
     265             : 
     266             :           /* Parse the precision.  */
     267       15407 :           if (*cp == '.')
     268             :             {
     269          10 :               cp++;
     270          10 :               if (*cp == '*')
     271             :                 {
     272           0 :                   dp->precision_start = cp - 1;
     273           0 :                   cp++;
     274           0 :                   dp->precision_end = cp;
     275           0 :                   if (max_precision_length < 2)
     276           0 :                     max_precision_length = 2;
     277             : 
     278             :                   /* Test for positional argument.  */
     279           0 :                   if (*cp >= '0' && *cp <= '9')
     280             :                     {
     281             :                       const CHAR_T *np;
     282             : 
     283           0 :                       for (np = cp; *np >= '0' && *np <= '9'; np++)
     284             :                         ;
     285           0 :                       if (*np == '$')
     286             :                         {
     287           0 :                           size_t n = 0;
     288             : 
     289           0 :                           for (np = cp; *np >= '0' && *np <= '9'; np++)
     290           0 :                             n = xsum (xtimes (n, 10), *np - '0');
     291           0 :                           if (n == 0)
     292             :                             /* Positional argument 0.  */
     293           0 :                             goto error;
     294           0 :                           if (size_overflow_p (n))
     295             :                             /* n too large, would lead to out of memory
     296             :                                later.  */
     297           0 :                             goto error;
     298           0 :                           dp->precision_arg_index = n - 1;
     299           0 :                           cp = np + 1;
     300             :                         }
     301             :                     }
     302           0 :                   if (dp->precision_arg_index == ARG_NONE)
     303             :                     {
     304           0 :                       dp->precision_arg_index = arg_posn++;
     305           0 :                       if (dp->precision_arg_index == ARG_NONE)
     306             :                         /* arg_posn wrapped around.  */
     307           0 :                         goto error;
     308             :                     }
     309           0 :                   REGISTER_ARG (dp->precision_arg_index, TYPE_INT);
     310             :                 }
     311             :               else
     312             :                 {
     313             :                   size_t precision_length;
     314             : 
     315          10 :                   dp->precision_start = cp - 1;
     316          20 :                   for (; *cp >= '0' && *cp <= '9'; cp++)
     317             :                     ;
     318          10 :                   dp->precision_end = cp;
     319          10 :                   precision_length = dp->precision_end - dp->precision_start;
     320          10 :                   if (max_precision_length < precision_length)
     321          10 :                     max_precision_length = precision_length;
     322             :                 }
     323             :             }
     324             : 
     325             :           {
     326             :             arg_type type;
     327             : 
     328             :             /* Parse argument type/size specifiers.  */
     329             :             /* Relevant for the conversion characters d, i.  */
     330       15407 :             arg_type signed_type = TYPE_INT;
     331             :             /* Relevant for the conversion characters b, o, u, x, X.  */
     332       15407 :             arg_type unsigned_type = TYPE_UINT;
     333             :             /* Relevant for the conversion characters n.  */
     334       15407 :             arg_type pointer_type = TYPE_COUNT_INT_POINTER;
     335             :             /* Relevant for the conversion characters a, A, e, E, f, F, g, G.  */
     336       15407 :             arg_type floatingpoint_type = TYPE_DOUBLE;
     337             : 
     338       15407 :             if (*cp == 'h')
     339             :               {
     340           0 :                 if (cp[1] == 'h')
     341             :                   {
     342           0 :                     signed_type = TYPE_SCHAR;
     343           0 :                     unsigned_type = TYPE_UCHAR;
     344           0 :                     pointer_type = TYPE_COUNT_SCHAR_POINTER;
     345           0 :                     cp += 2;
     346             :                   }
     347             :                 else
     348             :                   {
     349           0 :                     signed_type = TYPE_SHORT;
     350           0 :                     unsigned_type = TYPE_USHORT;
     351           0 :                     pointer_type = TYPE_COUNT_SHORT_POINTER;
     352           0 :                     cp++;
     353             :                   }
     354             :               }
     355       15407 :             else if (*cp == 'l')
     356             :               {
     357           0 :                 if (cp[1] == 'l')
     358             :                   {
     359           0 :                     signed_type = TYPE_LONGLONGINT;
     360           0 :                     unsigned_type = TYPE_ULONGLONGINT;
     361           0 :                     pointer_type = TYPE_COUNT_LONGLONGINT_POINTER;
     362             :                     /* For backward compatibility only.  */
     363           0 :                     floatingpoint_type = TYPE_LONGDOUBLE;
     364           0 :                     cp += 2;
     365             :                   }
     366             :                 else
     367             :                   {
     368           0 :                     signed_type = TYPE_LONGINT;
     369           0 :                     unsigned_type = TYPE_ULONGINT;
     370           0 :                     pointer_type = TYPE_COUNT_LONGINT_POINTER;
     371           0 :                     cp++;
     372             :                   }
     373             :               }
     374       15407 :             else if (*cp == 'j')
     375             :               {
     376             :                 if (sizeof (intmax_t) > sizeof (long))
     377             :                   {
     378             :                     /* intmax_t = long long */
     379             :                     signed_type = TYPE_LONGLONGINT;
     380             :                     unsigned_type = TYPE_ULONGLONGINT;
     381             :                     pointer_type = TYPE_COUNT_LONGLONGINT_POINTER;
     382             :                     /* For backward compatibility only.  */
     383             :                     floatingpoint_type = TYPE_LONGDOUBLE;
     384             :                   }
     385             :                 else if (sizeof (intmax_t) > sizeof (int))
     386             :                   {
     387             :                     /* intmax_t = long */
     388           0 :                     signed_type = TYPE_LONGINT;
     389           0 :                     unsigned_type = TYPE_ULONGINT;
     390           0 :                     pointer_type = TYPE_COUNT_LONGINT_POINTER;
     391             :                   }
     392           0 :                 cp++;
     393             :               }
     394       15407 :             else if (*cp == 'z' || *cp == 'Z')
     395             :               {
     396             :                 /* 'z' is standardized in ISO C 99, but glibc uses 'Z'
     397             :                    because the warning facility in gcc-2.95.2 understands
     398             :                    only 'Z' (see gcc-2.95.2/gcc/c-common.c:1784).  */
     399             :                 if (sizeof (size_t) > sizeof (long))
     400             :                   {
     401             :                     /* size_t = unsigned long long */
     402             :                     signed_type = TYPE_LONGLONGINT;
     403             :                     unsigned_type = TYPE_ULONGLONGINT;
     404             :                     pointer_type = TYPE_COUNT_LONGLONGINT_POINTER;
     405             :                     /* For backward compatibility only.  */
     406             :                     floatingpoint_type = TYPE_LONGDOUBLE;
     407             :                   }
     408             :                 else if (sizeof (size_t) > sizeof (int))
     409             :                   {
     410             :                     /* size_t = unsigned long */
     411           0 :                     signed_type = TYPE_LONGINT;
     412           0 :                     unsigned_type = TYPE_ULONGINT;
     413           0 :                     pointer_type = TYPE_COUNT_LONGINT_POINTER;
     414             :                   }
     415           0 :                 cp++;
     416             :               }
     417       15407 :             else if (*cp == 't')
     418             :               {
     419             :                 if (sizeof (ptrdiff_t) > sizeof (long))
     420             :                   {
     421             :                     /* ptrdiff_t = long long */
     422             :                     signed_type = TYPE_LONGLONGINT;
     423             :                     unsigned_type = TYPE_ULONGLONGINT;
     424             :                     pointer_type = TYPE_COUNT_LONGLONGINT_POINTER;
     425             :                     /* For backward compatibility only.  */
     426             :                     floatingpoint_type = TYPE_LONGDOUBLE;
     427             :                   }
     428             :                 else if (sizeof (ptrdiff_t) > sizeof (int))
     429             :                   {
     430             :                     /* ptrdiff_t = long */
     431           0 :                     signed_type = TYPE_LONGINT;
     432           0 :                     unsigned_type = TYPE_ULONGINT;
     433           0 :                     pointer_type = TYPE_COUNT_LONGINT_POINTER;
     434             :                   }
     435           0 :                 cp++;
     436             :               }
     437       15407 :             else if (*cp == 'w')
     438             :               {
     439             :                 /* wN and wfN are standardized in ISO C 23.  */
     440           0 :                 if (cp[1] == 'f')
     441             :                   {
     442           0 :                     if (cp[2] == '8')
     443             :                       {
     444           0 :                         signed_type = TYPE_INT_FAST8_T;
     445           0 :                         unsigned_type = TYPE_UINT_FAST8_T;
     446           0 :                         pointer_type = TYPE_COUNT_INT_FAST8_T_POINTER;
     447           0 :                         cp += 3;
     448             :                       }
     449           0 :                     else if (cp[2] == '1' && cp[3] == '6')
     450             :                       {
     451           0 :                         signed_type = TYPE_INT_FAST16_T;
     452           0 :                         unsigned_type = TYPE_UINT_FAST16_T;
     453           0 :                         pointer_type = TYPE_COUNT_INT_FAST16_T_POINTER;
     454           0 :                         cp += 4;
     455             :                       }
     456           0 :                     else if (cp[2] == '3' && cp[3] == '2')
     457             :                       {
     458           0 :                         signed_type = TYPE_INT_FAST32_T;
     459           0 :                         unsigned_type = TYPE_UINT_FAST32_T;
     460           0 :                         pointer_type = TYPE_COUNT_INT_FAST32_T_POINTER;
     461           0 :                         cp += 4;
     462             :                       }
     463           0 :                     else if (cp[2] == '6' && cp[3] == '4')
     464             :                       {
     465           0 :                         signed_type = TYPE_INT_FAST64_T;
     466           0 :                         unsigned_type = TYPE_UINT_FAST64_T;
     467           0 :                         pointer_type = TYPE_COUNT_INT_FAST64_T_POINTER;
     468           0 :                         cp += 4;
     469             :                       }
     470             :                   }
     471             :                 else
     472             :                   {
     473           0 :                     if (cp[1] == '8')
     474             :                       {
     475           0 :                         signed_type = TYPE_INT8_T;
     476           0 :                         unsigned_type = TYPE_UINT8_T;
     477           0 :                         pointer_type = TYPE_COUNT_INT8_T_POINTER;
     478           0 :                         cp += 2;
     479             :                       }
     480           0 :                     else if (cp[1] == '1' && cp[2] == '6')
     481             :                       {
     482           0 :                         signed_type = TYPE_INT16_T;
     483           0 :                         unsigned_type = TYPE_UINT16_T;
     484           0 :                         pointer_type = TYPE_COUNT_INT16_T_POINTER;
     485           0 :                         cp += 3;
     486             :                       }
     487           0 :                     else if (cp[1] == '3' && cp[2] == '2')
     488             :                       {
     489           0 :                         signed_type = TYPE_INT32_T;
     490           0 :                         unsigned_type = TYPE_UINT32_T;
     491           0 :                         pointer_type = TYPE_COUNT_INT32_T_POINTER;
     492           0 :                         cp += 3;
     493             :                       }
     494           0 :                     else if (cp[1] == '6' && cp[2] == '4')
     495             :                       {
     496           0 :                         signed_type = TYPE_INT64_T;
     497           0 :                         unsigned_type = TYPE_UINT64_T;
     498           0 :                         pointer_type = TYPE_COUNT_INT64_T_POINTER;
     499           0 :                         cp += 3;
     500             :                       }
     501             :                   }
     502             :               }
     503       15407 :             else if (*cp == 'L')
     504             :               {
     505           0 :                 signed_type = TYPE_LONGLONGINT;
     506           0 :                 unsigned_type = TYPE_ULONGLONGINT;
     507           0 :                 pointer_type = TYPE_COUNT_LONGLONGINT_POINTER;
     508           0 :                 floatingpoint_type = TYPE_LONGDOUBLE;
     509           0 :                 cp++;
     510             :               }
     511             : #if defined __APPLE__ && defined __MACH__
     512             :             /* On Mac OS X 10.3, PRIdMAX is defined as "qd".
     513             :                We cannot change it to "lld" because PRIdMAX must also
     514             :                be understood by the system's printf routines.  */
     515             :             else if (*cp == 'q')
     516             :               {
     517             :                 if (64 / 8 > sizeof (long))
     518             :                   {
     519             :                     /* int64_t = long long */
     520             :                     signed_type = TYPE_LONGLONGINT;
     521             :                     unsigned_type = TYPE_ULONGLONGINT;
     522             :                     pointer_type = TYPE_COUNT_LONGLONGINT_POINTER;
     523             :                     /* For backward compatibility only.  */
     524             :                     floatingpoint_type = TYPE_LONGDOUBLE;
     525             :                   }
     526             :                 else
     527             :                   {
     528             :                     /* int64_t = long */
     529             :                     signed_type = TYPE_LONGINT;
     530             :                     unsigned_type = TYPE_ULONGINT;
     531             :                     pointer_type = TYPE_COUNT_LONGINT_POINTER;
     532             :                   }
     533             :                 cp++;
     534             :               }
     535             : #endif
     536             : #if defined _WIN32 && ! defined __CYGWIN__
     537             :             /* On native Windows, PRIdMAX is defined as "I64d".
     538             :                We cannot change it to "lld" because PRIdMAX must also
     539             :                be understood by the system's printf routines.  */
     540             :             else if (*cp == 'I' && cp[1] == '6' && cp[2] == '4')
     541             :               {
     542             :                 if (64 / 8 > sizeof (long))
     543             :                   {
     544             :                     /* __int64_t = long long */
     545             :                     signed_type = TYPE_LONGLONGINT;
     546             :                     unsigned_type = TYPE_ULONGLONGINT;
     547             :                     pointer_type = TYPE_COUNT_LONGLONGINT_POINTER;
     548             :                     /* For backward compatibility only.  */
     549             :                     floatingpoint_type = TYPE_LONGDOUBLE;
     550             :                   }
     551             :                 else
     552             :                   {
     553             :                     /* __int64_t = long */
     554             :                     signed_type = TYPE_LONGINT;
     555             :                     unsigned_type = TYPE_ULONGINT;
     556             :                     pointer_type = TYPE_COUNT_LONGINT_POINTER;
     557             :                   }
     558             :                 cp += 3;
     559             :               }
     560             : #endif
     561             :             (void) pointer_type;
     562             : 
     563             :             /* Read the conversion character.  */
     564       15407 :             c = *cp++;
     565       15407 :             switch (c)
     566             :               {
     567         755 :               case 'd': case 'i':
     568         755 :                 type = signed_type;
     569         755 :                 break;
     570       13705 :               case 'b': case 'o': case 'u': case 'x': case 'X':
     571             :               #if SUPPORT_GNU_PRINTF_DIRECTIVES \
     572             :                   || (__GLIBC__ + (__GLIBC_MINOR__ >= 35) > 2)
     573             :               case 'B':
     574             :               #endif
     575       13705 :                 type = unsigned_type;
     576       13705 :                 break;
     577          43 :               case 'f': case 'F': case 'e': case 'E': case 'g': case 'G':
     578             :               case 'a': case 'A':
     579          43 :                 type = floatingpoint_type;
     580          43 :                 break;
     581          31 :               case 'c':
     582          31 :                 if (signed_type == TYPE_LONGINT
     583             :                     /* For backward compatibility only.  */
     584          31 :                     || signed_type == TYPE_LONGLONGINT)
     585             : #if HAVE_WINT_T
     586           0 :                   type = TYPE_WIDE_CHAR;
     587             : #else
     588             :                   goto error;
     589             : #endif
     590             :                 else
     591          31 :                   type = TYPE_CHAR;
     592          31 :                 break;
     593             : #if HAVE_WINT_T
     594           0 :               case 'C':
     595           0 :                 type = TYPE_WIDE_CHAR;
     596           0 :                 c = 'c';
     597           0 :                 break;
     598             : #endif
     599         713 :               case 's':
     600         713 :                 if (signed_type == TYPE_LONGINT
     601             :                     /* For backward compatibility only.  */
     602         713 :                     || signed_type == TYPE_LONGLONGINT)
     603           0 :                   type = TYPE_WIDE_STRING;
     604             :                 else
     605         713 :                   type = TYPE_STRING;
     606         713 :                 break;
     607           0 :               case 'S':
     608           0 :                 type = TYPE_WIDE_STRING;
     609           0 :                 c = 's';
     610           0 :                 break;
     611           0 :               case 'p':
     612           0 :                 type = TYPE_POINTER;
     613           0 :                 break;
     614             : #if NEED_PRINTF_WITH_N_DIRECTIVE
     615             :               case 'n':
     616             :                 type = pointer_type;
     617             :                 break;
     618             : #endif
     619             : #if ENABLE_UNISTDIO
     620             :               /* The unistdio extensions.  */
     621             :               case 'U':
     622             :                 if (signed_type == TYPE_LONGLONGINT)
     623             :                   type = TYPE_U32_STRING;
     624             :                 else if (signed_type == TYPE_LONGINT)
     625             :                   type = TYPE_U16_STRING;
     626             :                 else
     627             :                   type = TYPE_U8_STRING;
     628             :                 break;
     629             : #endif
     630         160 :               case '%':
     631         160 :                 type = TYPE_NONE;
     632         160 :                 break;
     633           0 :               default:
     634             :                 /* Unknown conversion character.  */
     635           0 :                 goto error;
     636             :               }
     637             : 
     638       15407 :             if (type != TYPE_NONE)
     639             :               {
     640       15247 :                 dp->arg_index = arg_index;
     641       15247 :                 if (dp->arg_index == ARG_NONE)
     642             :                   {
     643       15247 :                     dp->arg_index = arg_posn++;
     644       15247 :                     if (dp->arg_index == ARG_NONE)
     645             :                       /* arg_posn wrapped around.  */
     646           0 :                       goto error;
     647             :                   }
     648       30494 :                 REGISTER_ARG (dp->arg_index, type);
     649             :               }
     650       15407 :             dp->conversion = c;
     651       15407 :             dp->dir_end = cp;
     652             :           }
     653             : 
     654       15407 :           d->count++;
     655       15407 :           if (d->count >= d_allocated)
     656             :             {
     657             :               size_t memory_size;
     658             :               DIRECTIVE *memory;
     659             : 
     660          99 :               d_allocated = xtimes (d_allocated, 2);
     661          99 :               memory_size = xtimes (d_allocated, sizeof (DIRECTIVE));
     662          99 :               if (size_overflow_p (memory_size))
     663             :                 /* Overflow, would lead to out of memory.  */
     664           0 :                 goto out_of_memory;
     665          99 :               memory = (DIRECTIVE *) (d->dir != d->direct_alloc_dir
     666           0 :                                       ? realloc (d->dir, memory_size)
     667          99 :                                       : malloc (memory_size));
     668          99 :               if (memory == NULL)
     669             :                 /* Out of memory.  */
     670           0 :                 goto out_of_memory;
     671          99 :               if (d->dir == d->direct_alloc_dir)
     672          99 :                 memcpy (memory, d->dir, d->count * sizeof (DIRECTIVE));
     673          99 :               d->dir = memory;
     674             :             }
     675             :         }
     676             : #if CHAR_T_ONLY_ASCII
     677             :       else if (!c_isascii (c))
     678             :         {
     679             :           /* Non-ASCII character.  Not supported.  */
     680             :           goto error;
     681             :         }
     682             : #endif
     683             :     }
     684       14391 :   d->dir[d->count].dir_start = cp;
     685             : 
     686       14391 :   d->max_width_length = max_width_length;
     687       14391 :   d->max_precision_length = max_precision_length;
     688       14391 :   return 0;
     689             : 
     690           0 : error:
     691           0 :   if (a->arg != a->direct_alloc_arg)
     692           0 :     free (a->arg);
     693           0 :   if (d->dir != d->direct_alloc_dir)
     694           0 :     free (d->dir);
     695           0 :   errno = EINVAL;
     696           0 :   return -1;
     697             : 
     698           0 : out_of_memory:
     699           0 :   if (a->arg != a->direct_alloc_arg)
     700           0 :     free (a->arg);
     701           0 :   if (d->dir != d->direct_alloc_dir)
     702           0 :     free (d->dir);
     703           0 :   errno = ENOMEM;
     704           0 :   return -1;
     705             : }
     706             : 
     707             : #undef PRINTF_PARSE
     708             : #undef DIRECTIVES
     709             : #undef DIRECTIVE
     710             : #undef CHAR_T_ONLY_ASCII
     711             : #undef CHAR_T

Generated by: LCOV version 1.14