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