Import upstream version 1.26
[debian/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-2011 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 /* memcpy().  */
69 #include <string.h>
70
71 /* errno.  */
72 #include <errno.h>
73
74 /* Checked size_t computations.  */
75 #include "xsize.h"
76
77 #if CHAR_T_ONLY_ASCII
78 /* c_isascii().  */
79 # include "c-ctype.h"
80 #endif
81
82 #ifdef STATIC
83 STATIC
84 #endif
85 int
86 PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a)
87 {
88   const CHAR_T *cp = format;    /* pointer into format */
89   size_t arg_posn = 0;          /* number of regular arguments consumed */
90   size_t d_allocated;           /* allocated elements of d->dir */
91   size_t a_allocated;           /* allocated elements of a->arg */
92   size_t max_width_length = 0;
93   size_t max_precision_length = 0;
94
95   d->count = 0;
96   d_allocated = N_DIRECT_ALLOC_DIRECTIVES;
97   d->dir = d->direct_alloc_dir;
98
99   a->count = 0;
100   a_allocated = N_DIRECT_ALLOC_ARGUMENTS;
101   a->arg = a->direct_alloc_arg;
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 != a->direct_alloc_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         if (a->arg == a->direct_alloc_arg)                              \
125           memcpy (memory, a->arg, a->count * sizeof (argument));        \
126         a->arg = memory;                                                \
127       }                                                                 \
128     while (a->count <= n)                                               \
129       a->arg[a->count++].type = TYPE_NONE;                              \
130     if (a->arg[n].type == TYPE_NONE)                                    \
131       a->arg[n].type = (_type_);                                        \
132     else if (a->arg[n].type != (_type_))                                \
133       /* Ambiguous type for positional argument.  */                    \
134       goto error;                                                       \
135   }
136
137   while (*cp != '\0')
138     {
139       CHAR_T c = *cp++;
140       if (c == '%')
141         {
142           size_t arg_index = ARG_NONE;
143           DIRECTIVE *dp = &d->dir[d->count]; /* pointer to next directive */
144
145           /* Initialize the next directive.  */
146           dp->dir_start = cp - 1;
147           dp->flags = 0;
148           dp->width_start = NULL;
149           dp->width_end = NULL;
150           dp->width_arg_index = ARG_NONE;
151           dp->precision_start = NULL;
152           dp->precision_end = NULL;
153           dp->precision_arg_index = ARG_NONE;
154           dp->arg_index = ARG_NONE;
155
156           /* Test for positional argument.  */
157           if (*cp >= '0' && *cp <= '9')
158             {
159               const CHAR_T *np;
160
161               for (np = cp; *np >= '0' && *np <= '9'; np++)
162                 ;
163               if (*np == '$')
164                 {
165                   size_t n = 0;
166
167                   for (np = cp; *np >= '0' && *np <= '9'; np++)
168                     n = xsum (xtimes (n, 10), *np - '0');
169                   if (n == 0)
170                     /* Positional argument 0.  */
171                     goto error;
172                   if (size_overflow_p (n))
173                     /* n too large, would lead to out of memory later.  */
174                     goto error;
175                   arg_index = n - 1;
176                   cp = np + 1;
177                 }
178             }
179
180           /* Read the flags.  */
181           for (;;)
182             {
183               if (*cp == '\'')
184                 {
185                   dp->flags |= FLAG_GROUP;
186                   cp++;
187                 }
188               else if (*cp == '-')
189                 {
190                   dp->flags |= FLAG_LEFT;
191                   cp++;
192                 }
193               else if (*cp == '+')
194                 {
195                   dp->flags |= FLAG_SHOWSIGN;
196                   cp++;
197                 }
198               else if (*cp == ' ')
199                 {
200                   dp->flags |= FLAG_SPACE;
201                   cp++;
202                 }
203               else if (*cp == '#')
204                 {
205                   dp->flags |= FLAG_ALT;
206                   cp++;
207                 }
208               else if (*cp == '0')
209                 {
210                   dp->flags |= FLAG_ZERO;
211                   cp++;
212                 }
213 #if __GLIBC__ >= 2 && !defined __UCLIBC__
214               else if (*cp == 'I')
215                 {
216                   dp->flags |= FLAG_LOCALIZED;
217                   cp++;
218                 }
219 #endif
220               else
221                 break;
222             }
223
224           /* Parse the field width.  */
225           if (*cp == '*')
226             {
227               dp->width_start = cp;
228               cp++;
229               dp->width_end = cp;
230               if (max_width_length < 1)
231                 max_width_length = 1;
232
233               /* Test for positional argument.  */
234               if (*cp >= '0' && *cp <= '9')
235                 {
236                   const CHAR_T *np;
237
238                   for (np = cp; *np >= '0' && *np <= '9'; np++)
239                     ;
240                   if (*np == '$')
241                     {
242                       size_t n = 0;
243
244                       for (np = cp; *np >= '0' && *np <= '9'; np++)
245                         n = xsum (xtimes (n, 10), *np - '0');
246                       if (n == 0)
247                         /* Positional argument 0.  */
248                         goto error;
249                       if (size_overflow_p (n))
250                         /* n too large, would lead to out of memory later.  */
251                         goto error;
252                       dp->width_arg_index = n - 1;
253                       cp = np + 1;
254                     }
255                 }
256               if (dp->width_arg_index == ARG_NONE)
257                 {
258                   dp->width_arg_index = arg_posn++;
259                   if (dp->width_arg_index == ARG_NONE)
260                     /* arg_posn wrapped around.  */
261                     goto error;
262                 }
263               REGISTER_ARG (dp->width_arg_index, TYPE_INT);
264             }
265           else if (*cp >= '0' && *cp <= '9')
266             {
267               size_t width_length;
268
269               dp->width_start = cp;
270               for (; *cp >= '0' && *cp <= '9'; cp++)
271                 ;
272               dp->width_end = cp;
273               width_length = dp->width_end - dp->width_start;
274               if (max_width_length < width_length)
275                 max_width_length = width_length;
276             }
277
278           /* Parse the precision.  */
279           if (*cp == '.')
280             {
281               cp++;
282               if (*cp == '*')
283                 {
284                   dp->precision_start = cp - 1;
285                   cp++;
286                   dp->precision_end = cp;
287                   if (max_precision_length < 2)
288                     max_precision_length = 2;
289
290                   /* Test for positional argument.  */
291                   if (*cp >= '0' && *cp <= '9')
292                     {
293                       const CHAR_T *np;
294
295                       for (np = cp; *np >= '0' && *np <= '9'; np++)
296                         ;
297                       if (*np == '$')
298                         {
299                           size_t n = 0;
300
301                           for (np = cp; *np >= '0' && *np <= '9'; np++)
302                             n = xsum (xtimes (n, 10), *np - '0');
303                           if (n == 0)
304                             /* Positional argument 0.  */
305                             goto error;
306                           if (size_overflow_p (n))
307                             /* n too large, would lead to out of memory
308                                later.  */
309                             goto error;
310                           dp->precision_arg_index = n - 1;
311                           cp = np + 1;
312                         }
313                     }
314                   if (dp->precision_arg_index == ARG_NONE)
315                     {
316                       dp->precision_arg_index = arg_posn++;
317                       if (dp->precision_arg_index == ARG_NONE)
318                         /* arg_posn wrapped around.  */
319                         goto error;
320                     }
321                   REGISTER_ARG (dp->precision_arg_index, TYPE_INT);
322                 }
323               else
324                 {
325                   size_t precision_length;
326
327                   dp->precision_start = cp - 1;
328                   for (; *cp >= '0' && *cp <= '9'; cp++)
329                     ;
330                   dp->precision_end = cp;
331                   precision_length = dp->precision_end - dp->precision_start;
332                   if (max_precision_length < precision_length)
333                     max_precision_length = precision_length;
334                 }
335             }
336
337           {
338             arg_type type;
339
340             /* Parse argument type/size specifiers.  */
341             {
342               int flags = 0;
343
344               for (;;)
345                 {
346                   if (*cp == 'h')
347                     {
348                       flags |= (1 << (flags & 1));
349                       cp++;
350                     }
351                   else if (*cp == 'L')
352                     {
353                       flags |= 4;
354                       cp++;
355                     }
356                   else if (*cp == 'l')
357                     {
358                       flags += 8;
359                       cp++;
360                     }
361                   else if (*cp == 'j')
362                     {
363                       if (sizeof (intmax_t) > sizeof (long))
364                         {
365                           /* intmax_t = long long */
366                           flags += 16;
367                         }
368                       else if (sizeof (intmax_t) > sizeof (int))
369                         {
370                           /* intmax_t = long */
371                           flags += 8;
372                         }
373                       cp++;
374                     }
375                   else if (*cp == 'z' || *cp == 'Z')
376                     {
377                       /* 'z' is standardized in ISO C 99, but glibc uses 'Z'
378                          because the warning facility in gcc-2.95.2 understands
379                          only 'Z' (see gcc-2.95.2/gcc/c-common.c:1784).  */
380                       if (sizeof (size_t) > sizeof (long))
381                         {
382                           /* size_t = long long */
383                           flags += 16;
384                         }
385                       else if (sizeof (size_t) > sizeof (int))
386                         {
387                           /* size_t = long */
388                           flags += 8;
389                         }
390                       cp++;
391                     }
392                   else if (*cp == 't')
393                     {
394                       if (sizeof (ptrdiff_t) > sizeof (long))
395                         {
396                           /* ptrdiff_t = long long */
397                           flags += 16;
398                         }
399                       else if (sizeof (ptrdiff_t) > sizeof (int))
400                         {
401                           /* ptrdiff_t = long */
402                           flags += 8;
403                         }
404                       cp++;
405                     }
406 #if defined __APPLE__ && defined __MACH__
407                   /* On MacOS X 10.3, PRIdMAX is defined as "qd".
408                      We cannot change it to "lld" because PRIdMAX must also
409                      be understood by the system's printf routines.  */
410                   else if (*cp == 'q')
411                     {
412                       if (64 / 8 > sizeof (long))
413                         {
414                           /* int64_t = long long */
415                           flags += 16;
416                         }
417                       else
418                         {
419                           /* int64_t = long */
420                           flags += 8;
421                         }
422                       cp++;
423                     }
424 #endif
425 #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
426                   /* On native Win32, PRIdMAX is defined as "I64d".
427                      We cannot change it to "lld" because PRIdMAX must also
428                      be understood by the system's printf routines.  */
429                   else if (*cp == 'I' && cp[1] == '6' && cp[2] == '4')
430                     {
431                       if (64 / 8 > sizeof (long))
432                         {
433                           /* __int64 = long long */
434                           flags += 16;
435                         }
436                       else
437                         {
438                           /* __int64 = long */
439                           flags += 8;
440                         }
441                       cp += 3;
442                     }
443 #endif
444                   else
445                     break;
446                 }
447
448               /* Read the conversion character.  */
449               c = *cp++;
450               switch (c)
451                 {
452                 case 'd': case 'i':
453 #if HAVE_LONG_LONG_INT
454                   /* If 'long long' exists and is larger than 'long':  */
455                   if (flags >= 16 || (flags & 4))
456                     type = TYPE_LONGLONGINT;
457                   else
458 #endif
459                   /* If 'long long' exists and is the same as 'long', we parse
460                      "lld" into TYPE_LONGINT.  */
461                   if (flags >= 8)
462                     type = TYPE_LONGINT;
463                   else if (flags & 2)
464                     type = TYPE_SCHAR;
465                   else if (flags & 1)
466                     type = TYPE_SHORT;
467                   else
468                     type = TYPE_INT;
469                   break;
470                 case 'o': case 'u': case 'x': case 'X':
471 #if HAVE_LONG_LONG_INT
472                   /* If 'long long' exists and is larger than 'long':  */
473                   if (flags >= 16 || (flags & 4))
474                     type = TYPE_ULONGLONGINT;
475                   else
476 #endif
477                   /* If 'unsigned long long' exists and is the same as
478                      'unsigned long', we parse "llu" into TYPE_ULONGINT.  */
479                   if (flags >= 8)
480                     type = TYPE_ULONGINT;
481                   else if (flags & 2)
482                     type = TYPE_UCHAR;
483                   else if (flags & 1)
484                     type = TYPE_USHORT;
485                   else
486                     type = TYPE_UINT;
487                   break;
488                 case 'f': case 'F': case 'e': case 'E': case 'g': case 'G':
489                 case 'a': case 'A':
490                   if (flags >= 16 || (flags & 4))
491                     type = TYPE_LONGDOUBLE;
492                   else
493                     type = TYPE_DOUBLE;
494                   break;
495                 case 'c':
496                   if (flags >= 8)
497 #if HAVE_WINT_T
498                     type = TYPE_WIDE_CHAR;
499 #else
500                     goto error;
501 #endif
502                   else
503                     type = TYPE_CHAR;
504                   break;
505 #if HAVE_WINT_T
506                 case 'C':
507                   type = TYPE_WIDE_CHAR;
508                   c = 'c';
509                   break;
510 #endif
511                 case 's':
512                   if (flags >= 8)
513 #if HAVE_WCHAR_T
514                     type = TYPE_WIDE_STRING;
515 #else
516                     goto error;
517 #endif
518                   else
519                     type = TYPE_STRING;
520                   break;
521 #if HAVE_WCHAR_T
522                 case 'S':
523                   type = TYPE_WIDE_STRING;
524                   c = 's';
525                   break;
526 #endif
527                 case 'p':
528                   type = TYPE_POINTER;
529                   break;
530                 case 'n':
531 #if HAVE_LONG_LONG_INT
532                   /* If 'long long' exists and is larger than 'long':  */
533                   if (flags >= 16 || (flags & 4))
534                     type = TYPE_COUNT_LONGLONGINT_POINTER;
535                   else
536 #endif
537                   /* If 'long long' exists and is the same as 'long', we parse
538                      "lln" into TYPE_COUNT_LONGINT_POINTER.  */
539                   if (flags >= 8)
540                     type = TYPE_COUNT_LONGINT_POINTER;
541                   else if (flags & 2)
542                     type = TYPE_COUNT_SCHAR_POINTER;
543                   else if (flags & 1)
544                     type = TYPE_COUNT_SHORT_POINTER;
545                   else
546                     type = TYPE_COUNT_INT_POINTER;
547                   break;
548 #if ENABLE_UNISTDIO
549                 /* The unistdio extensions.  */
550                 case 'U':
551                   if (flags >= 16)
552                     type = TYPE_U32_STRING;
553                   else if (flags >= 8)
554                     type = TYPE_U16_STRING;
555                   else
556                     type = TYPE_U8_STRING;
557                   break;
558 #endif
559                 case '%':
560                   type = TYPE_NONE;
561                   break;
562                 default:
563                   /* Unknown conversion character.  */
564                   goto error;
565                 }
566             }
567
568             if (type != TYPE_NONE)
569               {
570                 dp->arg_index = arg_index;
571                 if (dp->arg_index == ARG_NONE)
572                   {
573                     dp->arg_index = arg_posn++;
574                     if (dp->arg_index == ARG_NONE)
575                       /* arg_posn wrapped around.  */
576                       goto error;
577                   }
578                 REGISTER_ARG (dp->arg_index, type);
579               }
580             dp->conversion = c;
581             dp->dir_end = cp;
582           }
583
584           d->count++;
585           if (d->count >= d_allocated)
586             {
587               size_t memory_size;
588               DIRECTIVE *memory;
589
590               d_allocated = xtimes (d_allocated, 2);
591               memory_size = xtimes (d_allocated, sizeof (DIRECTIVE));
592               if (size_overflow_p (memory_size))
593                 /* Overflow, would lead to out of memory.  */
594                 goto out_of_memory;
595               memory = (DIRECTIVE *) (d->dir != d->direct_alloc_dir
596                                       ? realloc (d->dir, memory_size)
597                                       : malloc (memory_size));
598               if (memory == NULL)
599                 /* Out of memory.  */
600                 goto out_of_memory;
601               if (d->dir == d->direct_alloc_dir)
602                 memcpy (memory, d->dir, d->count * sizeof (DIRECTIVE));
603               d->dir = memory;
604             }
605         }
606 #if CHAR_T_ONLY_ASCII
607       else if (!c_isascii (c))
608         {
609           /* Non-ASCII character.  Not supported.  */
610           goto error;
611         }
612 #endif
613     }
614   d->dir[d->count].dir_start = cp;
615
616   d->max_width_length = max_width_length;
617   d->max_precision_length = max_precision_length;
618   return 0;
619
620 error:
621   if (a->arg != a->direct_alloc_arg)
622     free (a->arg);
623   if (d->dir != d->direct_alloc_dir)
624     free (d->dir);
625   errno = EINVAL;
626   return -1;
627
628 out_of_memory:
629   if (a->arg != a->direct_alloc_arg)
630     free (a->arg);
631   if (d->dir != d->direct_alloc_dir)
632     free (d->dir);
633   errno = ENOMEM;
634   return -1;
635 }
636
637 #undef PRINTF_PARSE
638 #undef DIRECTIVES
639 #undef DIRECTIVE
640 #undef CHAR_T_ONLY_ASCII
641 #undef CHAR_T