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