186d7f5d3SJohn Marino /* Formatted output to strings.
286d7f5d3SJohn Marino Copyright (C) 1999-2000, 2002-2003 Free Software Foundation, Inc.
386d7f5d3SJohn Marino
486d7f5d3SJohn Marino This program is free software; you can redistribute it and/or modify
586d7f5d3SJohn Marino it under the terms of the GNU General Public License as published by
686d7f5d3SJohn Marino the Free Software Foundation; either version 2, or (at your option)
786d7f5d3SJohn Marino any later version.
886d7f5d3SJohn Marino
986d7f5d3SJohn Marino This program is distributed in the hope that it will be useful,
1086d7f5d3SJohn Marino but WITHOUT ANY WARRANTY; without even the implied warranty of
1186d7f5d3SJohn Marino MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1286d7f5d3SJohn Marino GNU General Public License for more details.
1386d7f5d3SJohn Marino
1486d7f5d3SJohn Marino You should have received a copy of the GNU General Public License along
1586d7f5d3SJohn Marino with this program; if not, write to the Free Software Foundation,
1686d7f5d3SJohn Marino Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
1786d7f5d3SJohn Marino
1886d7f5d3SJohn Marino #ifdef HAVE_CONFIG_H
1986d7f5d3SJohn Marino # include <config.h>
2086d7f5d3SJohn Marino #endif
2186d7f5d3SJohn Marino
2286d7f5d3SJohn Marino /* Specification. */
2386d7f5d3SJohn Marino #if WIDE_CHAR_VERSION
2486d7f5d3SJohn Marino # include "wprintf-parse.h"
2586d7f5d3SJohn Marino #else
2686d7f5d3SJohn Marino # include "printf-parse.h"
2786d7f5d3SJohn Marino #endif
2886d7f5d3SJohn Marino
2986d7f5d3SJohn Marino /* Get size_t, NULL. */
3086d7f5d3SJohn Marino #include <stddef.h>
3186d7f5d3SJohn Marino
3286d7f5d3SJohn Marino /* Get intmax_t. */
3386d7f5d3SJohn Marino #if HAVE_STDINT_H_WITH_UINTMAX
3486d7f5d3SJohn Marino # include <stdint.h>
3586d7f5d3SJohn Marino #endif
3686d7f5d3SJohn Marino #if HAVE_INTTYPES_H_WITH_UINTMAX
3786d7f5d3SJohn Marino # include <inttypes.h>
3886d7f5d3SJohn Marino #endif
3986d7f5d3SJohn Marino
4086d7f5d3SJohn Marino /* malloc(), realloc(), free(). */
4186d7f5d3SJohn Marino #include <stdlib.h>
4286d7f5d3SJohn Marino
4386d7f5d3SJohn Marino /* Checked size_t computations. */
4486d7f5d3SJohn Marino #include "xsize.h"
4586d7f5d3SJohn Marino
4686d7f5d3SJohn Marino #if WIDE_CHAR_VERSION
4786d7f5d3SJohn Marino # define PRINTF_PARSE wprintf_parse
4886d7f5d3SJohn Marino # define CHAR_T wchar_t
4986d7f5d3SJohn Marino # define DIRECTIVE wchar_t_directive
5086d7f5d3SJohn Marino # define DIRECTIVES wchar_t_directives
5186d7f5d3SJohn Marino #else
5286d7f5d3SJohn Marino # define PRINTF_PARSE printf_parse
5386d7f5d3SJohn Marino # define CHAR_T char
5486d7f5d3SJohn Marino # define DIRECTIVE char_directive
5586d7f5d3SJohn Marino # define DIRECTIVES char_directives
5686d7f5d3SJohn Marino #endif
5786d7f5d3SJohn Marino
5886d7f5d3SJohn Marino #ifdef STATIC
5986d7f5d3SJohn Marino STATIC
6086d7f5d3SJohn Marino #endif
6186d7f5d3SJohn Marino int
PRINTF_PARSE(const CHAR_T * format,DIRECTIVES * d,arguments * a)6286d7f5d3SJohn Marino PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a)
6386d7f5d3SJohn Marino {
6486d7f5d3SJohn Marino const CHAR_T *cp = format; /* pointer into format */
6586d7f5d3SJohn Marino size_t arg_posn = 0; /* number of regular arguments consumed */
6686d7f5d3SJohn Marino size_t d_allocated; /* allocated elements of d->dir */
6786d7f5d3SJohn Marino size_t a_allocated; /* allocated elements of a->arg */
6886d7f5d3SJohn Marino size_t max_width_length = 0;
6986d7f5d3SJohn Marino size_t max_precision_length = 0;
7086d7f5d3SJohn Marino
7186d7f5d3SJohn Marino d->count = 0;
7286d7f5d3SJohn Marino d_allocated = 1;
7386d7f5d3SJohn Marino d->dir = malloc (d_allocated * sizeof (DIRECTIVE));
7486d7f5d3SJohn Marino if (d->dir == NULL)
7586d7f5d3SJohn Marino /* Out of memory. */
7686d7f5d3SJohn Marino return -1;
7786d7f5d3SJohn Marino
7886d7f5d3SJohn Marino a->count = 0;
7986d7f5d3SJohn Marino a_allocated = 0;
8086d7f5d3SJohn Marino a->arg = NULL;
8186d7f5d3SJohn Marino
8286d7f5d3SJohn Marino #define REGISTER_ARG(_index_,_type_) \
8386d7f5d3SJohn Marino { \
8486d7f5d3SJohn Marino size_t n = (_index_); \
8586d7f5d3SJohn Marino if (n >= a_allocated) \
8686d7f5d3SJohn Marino { \
8786d7f5d3SJohn Marino size_t memory_size; \
8886d7f5d3SJohn Marino argument *memory; \
8986d7f5d3SJohn Marino \
9086d7f5d3SJohn Marino a_allocated = xtimes (a_allocated, 2); \
9186d7f5d3SJohn Marino if (a_allocated <= n) \
9286d7f5d3SJohn Marino a_allocated = xsum (n, 1); \
9386d7f5d3SJohn Marino memory_size = xtimes (a_allocated, sizeof (argument)); \
9486d7f5d3SJohn Marino if (size_overflow_p (memory_size)) \
9586d7f5d3SJohn Marino /* Overflow, would lead to out of memory. */ \
9686d7f5d3SJohn Marino goto error; \
9786d7f5d3SJohn Marino memory = (a->arg \
9886d7f5d3SJohn Marino ? realloc (a->arg, memory_size) \
9986d7f5d3SJohn Marino : malloc (memory_size)); \
10086d7f5d3SJohn Marino if (memory == NULL) \
10186d7f5d3SJohn Marino /* Out of memory. */ \
10286d7f5d3SJohn Marino goto error; \
10386d7f5d3SJohn Marino a->arg = memory; \
10486d7f5d3SJohn Marino } \
10586d7f5d3SJohn Marino while (a->count <= n) \
10686d7f5d3SJohn Marino a->arg[a->count++].type = TYPE_NONE; \
10786d7f5d3SJohn Marino if (a->arg[n].type == TYPE_NONE) \
10886d7f5d3SJohn Marino a->arg[n].type = (_type_); \
10986d7f5d3SJohn Marino else if (a->arg[n].type != (_type_)) \
11086d7f5d3SJohn Marino /* Ambiguous type for positional argument. */ \
11186d7f5d3SJohn Marino goto error; \
11286d7f5d3SJohn Marino }
11386d7f5d3SJohn Marino
11486d7f5d3SJohn Marino while (*cp != '\0')
11586d7f5d3SJohn Marino {
11686d7f5d3SJohn Marino CHAR_T c = *cp++;
11786d7f5d3SJohn Marino if (c == '%')
11886d7f5d3SJohn Marino {
11986d7f5d3SJohn Marino size_t arg_index = ARG_NONE;
12086d7f5d3SJohn Marino DIRECTIVE *dp = &d->dir[d->count];/* pointer to next directive */
12186d7f5d3SJohn Marino
12286d7f5d3SJohn Marino /* Initialize the next directive. */
12386d7f5d3SJohn Marino dp->dir_start = cp - 1;
12486d7f5d3SJohn Marino dp->flags = 0;
12586d7f5d3SJohn Marino dp->width_start = NULL;
12686d7f5d3SJohn Marino dp->width_end = NULL;
12786d7f5d3SJohn Marino dp->width_arg_index = ARG_NONE;
12886d7f5d3SJohn Marino dp->precision_start = NULL;
12986d7f5d3SJohn Marino dp->precision_end = NULL;
13086d7f5d3SJohn Marino dp->precision_arg_index = ARG_NONE;
13186d7f5d3SJohn Marino dp->arg_index = ARG_NONE;
13286d7f5d3SJohn Marino
13386d7f5d3SJohn Marino /* Test for positional argument. */
13486d7f5d3SJohn Marino if (*cp >= '0' && *cp <= '9')
13586d7f5d3SJohn Marino {
13686d7f5d3SJohn Marino const CHAR_T *np;
13786d7f5d3SJohn Marino
13886d7f5d3SJohn Marino for (np = cp; *np >= '0' && *np <= '9'; np++)
13986d7f5d3SJohn Marino ;
14086d7f5d3SJohn Marino if (*np == '$')
14186d7f5d3SJohn Marino {
14286d7f5d3SJohn Marino size_t n = 0;
14386d7f5d3SJohn Marino
14486d7f5d3SJohn Marino for (np = cp; *np >= '0' && *np <= '9'; np++)
14586d7f5d3SJohn Marino n = xsum (xtimes (n, 10), *np - '0');
14686d7f5d3SJohn Marino if (n == 0)
14786d7f5d3SJohn Marino /* Positional argument 0. */
14886d7f5d3SJohn Marino goto error;
14986d7f5d3SJohn Marino if (size_overflow_p (n))
15086d7f5d3SJohn Marino /* n too large, would lead to out of memory later. */
15186d7f5d3SJohn Marino goto error;
15286d7f5d3SJohn Marino arg_index = n - 1;
15386d7f5d3SJohn Marino cp = np + 1;
15486d7f5d3SJohn Marino }
15586d7f5d3SJohn Marino }
15686d7f5d3SJohn Marino
15786d7f5d3SJohn Marino /* Read the flags. */
15886d7f5d3SJohn Marino for (;;)
15986d7f5d3SJohn Marino {
16086d7f5d3SJohn Marino if (*cp == '\'')
16186d7f5d3SJohn Marino {
16286d7f5d3SJohn Marino dp->flags |= FLAG_GROUP;
16386d7f5d3SJohn Marino cp++;
16486d7f5d3SJohn Marino }
16586d7f5d3SJohn Marino else if (*cp == '-')
16686d7f5d3SJohn Marino {
16786d7f5d3SJohn Marino dp->flags |= FLAG_LEFT;
16886d7f5d3SJohn Marino cp++;
16986d7f5d3SJohn Marino }
17086d7f5d3SJohn Marino else if (*cp == '+')
17186d7f5d3SJohn Marino {
17286d7f5d3SJohn Marino dp->flags |= FLAG_SHOWSIGN;
17386d7f5d3SJohn Marino cp++;
17486d7f5d3SJohn Marino }
17586d7f5d3SJohn Marino else if (*cp == ' ')
17686d7f5d3SJohn Marino {
17786d7f5d3SJohn Marino dp->flags |= FLAG_SPACE;
17886d7f5d3SJohn Marino cp++;
17986d7f5d3SJohn Marino }
18086d7f5d3SJohn Marino else if (*cp == '#')
18186d7f5d3SJohn Marino {
18286d7f5d3SJohn Marino dp->flags |= FLAG_ALT;
18386d7f5d3SJohn Marino cp++;
18486d7f5d3SJohn Marino }
18586d7f5d3SJohn Marino else if (*cp == '0')
18686d7f5d3SJohn Marino {
18786d7f5d3SJohn Marino dp->flags |= FLAG_ZERO;
18886d7f5d3SJohn Marino cp++;
18986d7f5d3SJohn Marino }
19086d7f5d3SJohn Marino else
19186d7f5d3SJohn Marino break;
19286d7f5d3SJohn Marino }
19386d7f5d3SJohn Marino
19486d7f5d3SJohn Marino /* Parse the field width. */
19586d7f5d3SJohn Marino if (*cp == '*')
19686d7f5d3SJohn Marino {
19786d7f5d3SJohn Marino dp->width_start = cp;
19886d7f5d3SJohn Marino cp++;
19986d7f5d3SJohn Marino dp->width_end = cp;
20086d7f5d3SJohn Marino if (max_width_length < 1)
20186d7f5d3SJohn Marino max_width_length = 1;
20286d7f5d3SJohn Marino
20386d7f5d3SJohn Marino /* Test for positional argument. */
20486d7f5d3SJohn Marino if (*cp >= '0' && *cp <= '9')
20586d7f5d3SJohn Marino {
20686d7f5d3SJohn Marino const CHAR_T *np;
20786d7f5d3SJohn Marino
20886d7f5d3SJohn Marino for (np = cp; *np >= '0' && *np <= '9'; np++)
20986d7f5d3SJohn Marino ;
21086d7f5d3SJohn Marino if (*np == '$')
21186d7f5d3SJohn Marino {
21286d7f5d3SJohn Marino size_t n = 0;
21386d7f5d3SJohn Marino
21486d7f5d3SJohn Marino for (np = cp; *np >= '0' && *np <= '9'; np++)
21586d7f5d3SJohn Marino n = xsum (xtimes (n, 10), *np - '0');
21686d7f5d3SJohn Marino if (n == 0)
21786d7f5d3SJohn Marino /* Positional argument 0. */
21886d7f5d3SJohn Marino goto error;
21986d7f5d3SJohn Marino if (size_overflow_p (n))
22086d7f5d3SJohn Marino /* n too large, would lead to out of memory later. */
22186d7f5d3SJohn Marino goto error;
22286d7f5d3SJohn Marino dp->width_arg_index = n - 1;
22386d7f5d3SJohn Marino cp = np + 1;
22486d7f5d3SJohn Marino }
22586d7f5d3SJohn Marino }
22686d7f5d3SJohn Marino if (dp->width_arg_index == ARG_NONE)
22786d7f5d3SJohn Marino {
22886d7f5d3SJohn Marino dp->width_arg_index = arg_posn++;
22986d7f5d3SJohn Marino if (dp->width_arg_index == ARG_NONE)
23086d7f5d3SJohn Marino /* arg_posn wrapped around. */
23186d7f5d3SJohn Marino goto error;
23286d7f5d3SJohn Marino }
23386d7f5d3SJohn Marino REGISTER_ARG (dp->width_arg_index, TYPE_INT);
23486d7f5d3SJohn Marino }
23586d7f5d3SJohn Marino else if (*cp >= '0' && *cp <= '9')
23686d7f5d3SJohn Marino {
23786d7f5d3SJohn Marino size_t width_length;
23886d7f5d3SJohn Marino
23986d7f5d3SJohn Marino dp->width_start = cp;
24086d7f5d3SJohn Marino for (; *cp >= '0' && *cp <= '9'; cp++)
24186d7f5d3SJohn Marino ;
24286d7f5d3SJohn Marino dp->width_end = cp;
24386d7f5d3SJohn Marino width_length = dp->width_end - dp->width_start;
24486d7f5d3SJohn Marino if (max_width_length < width_length)
24586d7f5d3SJohn Marino max_width_length = width_length;
24686d7f5d3SJohn Marino }
24786d7f5d3SJohn Marino
24886d7f5d3SJohn Marino /* Parse the precision. */
24986d7f5d3SJohn Marino if (*cp == '.')
25086d7f5d3SJohn Marino {
25186d7f5d3SJohn Marino cp++;
25286d7f5d3SJohn Marino if (*cp == '*')
25386d7f5d3SJohn Marino {
25486d7f5d3SJohn Marino dp->precision_start = cp - 1;
25586d7f5d3SJohn Marino cp++;
25686d7f5d3SJohn Marino dp->precision_end = cp;
25786d7f5d3SJohn Marino if (max_precision_length < 2)
25886d7f5d3SJohn Marino max_precision_length = 2;
25986d7f5d3SJohn Marino
26086d7f5d3SJohn Marino /* Test for positional argument. */
26186d7f5d3SJohn Marino if (*cp >= '0' && *cp <= '9')
26286d7f5d3SJohn Marino {
26386d7f5d3SJohn Marino const CHAR_T *np;
26486d7f5d3SJohn Marino
26586d7f5d3SJohn Marino for (np = cp; *np >= '0' && *np <= '9'; np++)
26686d7f5d3SJohn Marino ;
26786d7f5d3SJohn Marino if (*np == '$')
26886d7f5d3SJohn Marino {
26986d7f5d3SJohn Marino size_t n = 0;
27086d7f5d3SJohn Marino
27186d7f5d3SJohn Marino for (np = cp; *np >= '0' && *np <= '9'; np++)
27286d7f5d3SJohn Marino n = xsum (xtimes (n, 10), *np - '0');
27386d7f5d3SJohn Marino if (n == 0)
27486d7f5d3SJohn Marino /* Positional argument 0. */
27586d7f5d3SJohn Marino goto error;
27686d7f5d3SJohn Marino if (size_overflow_p (n))
27786d7f5d3SJohn Marino /* n too large, would lead to out of memory
27886d7f5d3SJohn Marino later. */
27986d7f5d3SJohn Marino goto error;
28086d7f5d3SJohn Marino dp->precision_arg_index = n - 1;
28186d7f5d3SJohn Marino cp = np + 1;
28286d7f5d3SJohn Marino }
28386d7f5d3SJohn Marino }
28486d7f5d3SJohn Marino if (dp->precision_arg_index == ARG_NONE)
28586d7f5d3SJohn Marino {
28686d7f5d3SJohn Marino dp->precision_arg_index = arg_posn++;
28786d7f5d3SJohn Marino if (dp->precision_arg_index == ARG_NONE)
28886d7f5d3SJohn Marino /* arg_posn wrapped around. */
28986d7f5d3SJohn Marino goto error;
29086d7f5d3SJohn Marino }
29186d7f5d3SJohn Marino REGISTER_ARG (dp->precision_arg_index, TYPE_INT);
29286d7f5d3SJohn Marino }
29386d7f5d3SJohn Marino else
29486d7f5d3SJohn Marino {
29586d7f5d3SJohn Marino size_t precision_length;
29686d7f5d3SJohn Marino
29786d7f5d3SJohn Marino dp->precision_start = cp - 1;
29886d7f5d3SJohn Marino for (; *cp >= '0' && *cp <= '9'; cp++)
29986d7f5d3SJohn Marino ;
30086d7f5d3SJohn Marino dp->precision_end = cp;
30186d7f5d3SJohn Marino precision_length = dp->precision_end - dp->precision_start;
30286d7f5d3SJohn Marino if (max_precision_length < precision_length)
30386d7f5d3SJohn Marino max_precision_length = precision_length;
30486d7f5d3SJohn Marino }
30586d7f5d3SJohn Marino }
30686d7f5d3SJohn Marino
30786d7f5d3SJohn Marino {
30886d7f5d3SJohn Marino arg_type type;
30986d7f5d3SJohn Marino
31086d7f5d3SJohn Marino /* Parse argument type/size specifiers. */
31186d7f5d3SJohn Marino {
31286d7f5d3SJohn Marino int flags = 0;
31386d7f5d3SJohn Marino
31486d7f5d3SJohn Marino for (;;)
31586d7f5d3SJohn Marino {
31686d7f5d3SJohn Marino if (*cp == 'h')
31786d7f5d3SJohn Marino {
31886d7f5d3SJohn Marino flags |= (1 << (flags & 1));
31986d7f5d3SJohn Marino cp++;
32086d7f5d3SJohn Marino }
32186d7f5d3SJohn Marino else if (*cp == 'L')
32286d7f5d3SJohn Marino {
32386d7f5d3SJohn Marino flags |= 4;
32486d7f5d3SJohn Marino cp++;
32586d7f5d3SJohn Marino }
32686d7f5d3SJohn Marino else if (*cp == 'l')
32786d7f5d3SJohn Marino {
32886d7f5d3SJohn Marino flags += 8;
32986d7f5d3SJohn Marino cp++;
33086d7f5d3SJohn Marino }
33186d7f5d3SJohn Marino #ifdef HAVE_INTMAX_T
33286d7f5d3SJohn Marino else if (*cp == 'j')
33386d7f5d3SJohn Marino {
33486d7f5d3SJohn Marino if (sizeof (intmax_t) > sizeof (long))
33586d7f5d3SJohn Marino {
33686d7f5d3SJohn Marino /* intmax_t = long long */
33786d7f5d3SJohn Marino flags += 16;
33886d7f5d3SJohn Marino }
33986d7f5d3SJohn Marino else if (sizeof (intmax_t) > sizeof (int))
34086d7f5d3SJohn Marino {
34186d7f5d3SJohn Marino /* intmax_t = long */
34286d7f5d3SJohn Marino flags += 8;
34386d7f5d3SJohn Marino }
34486d7f5d3SJohn Marino cp++;
34586d7f5d3SJohn Marino }
34686d7f5d3SJohn Marino #endif
34786d7f5d3SJohn Marino else if (*cp == 'z' || *cp == 'Z')
34886d7f5d3SJohn Marino {
34986d7f5d3SJohn Marino /* 'z' is standardized in ISO C 99, but glibc uses 'Z'
35086d7f5d3SJohn Marino because the warning facility in gcc-2.95.2 understands
35186d7f5d3SJohn Marino only 'Z' (see gcc-2.95.2/gcc/c-common.c:1784). */
35286d7f5d3SJohn Marino if (sizeof (size_t) > sizeof (long))
35386d7f5d3SJohn Marino {
35486d7f5d3SJohn Marino /* size_t = long long */
35586d7f5d3SJohn Marino flags += 16;
35686d7f5d3SJohn Marino }
35786d7f5d3SJohn Marino else if (sizeof (size_t) > sizeof (int))
35886d7f5d3SJohn Marino {
35986d7f5d3SJohn Marino /* size_t = long */
36086d7f5d3SJohn Marino flags += 8;
36186d7f5d3SJohn Marino }
36286d7f5d3SJohn Marino cp++;
36386d7f5d3SJohn Marino }
36486d7f5d3SJohn Marino else if (*cp == 't')
36586d7f5d3SJohn Marino {
36686d7f5d3SJohn Marino if (sizeof (ptrdiff_t) > sizeof (long))
36786d7f5d3SJohn Marino {
36886d7f5d3SJohn Marino /* ptrdiff_t = long long */
36986d7f5d3SJohn Marino flags += 16;
37086d7f5d3SJohn Marino }
37186d7f5d3SJohn Marino else if (sizeof (ptrdiff_t) > sizeof (int))
37286d7f5d3SJohn Marino {
37386d7f5d3SJohn Marino /* ptrdiff_t = long */
37486d7f5d3SJohn Marino flags += 8;
37586d7f5d3SJohn Marino }
37686d7f5d3SJohn Marino cp++;
37786d7f5d3SJohn Marino }
37886d7f5d3SJohn Marino else
37986d7f5d3SJohn Marino break;
38086d7f5d3SJohn Marino }
38186d7f5d3SJohn Marino
38286d7f5d3SJohn Marino /* Read the conversion character. */
38386d7f5d3SJohn Marino c = *cp++;
38486d7f5d3SJohn Marino switch (c)
38586d7f5d3SJohn Marino {
38686d7f5d3SJohn Marino case 'd': case 'i':
38786d7f5d3SJohn Marino #ifdef HAVE_LONG_LONG
38886d7f5d3SJohn Marino if (flags >= 16 || (flags & 4))
38986d7f5d3SJohn Marino type = TYPE_LONGLONGINT;
39086d7f5d3SJohn Marino else
39186d7f5d3SJohn Marino #endif
39286d7f5d3SJohn Marino if (flags >= 8)
39386d7f5d3SJohn Marino type = TYPE_LONGINT;
39486d7f5d3SJohn Marino else if (flags & 2)
39586d7f5d3SJohn Marino type = TYPE_SCHAR;
39686d7f5d3SJohn Marino else if (flags & 1)
39786d7f5d3SJohn Marino type = TYPE_SHORT;
39886d7f5d3SJohn Marino else
39986d7f5d3SJohn Marino type = TYPE_INT;
40086d7f5d3SJohn Marino break;
40186d7f5d3SJohn Marino case 'o': case 'u': case 'x': case 'X':
40286d7f5d3SJohn Marino #ifdef HAVE_LONG_LONG
40386d7f5d3SJohn Marino if (flags >= 16 || (flags & 4))
40486d7f5d3SJohn Marino type = TYPE_ULONGLONGINT;
40586d7f5d3SJohn Marino else
40686d7f5d3SJohn Marino #endif
40786d7f5d3SJohn Marino if (flags >= 8)
40886d7f5d3SJohn Marino type = TYPE_ULONGINT;
40986d7f5d3SJohn Marino else if (flags & 2)
41086d7f5d3SJohn Marino type = TYPE_UCHAR;
41186d7f5d3SJohn Marino else if (flags & 1)
41286d7f5d3SJohn Marino type = TYPE_USHORT;
41386d7f5d3SJohn Marino else
41486d7f5d3SJohn Marino type = TYPE_UINT;
41586d7f5d3SJohn Marino break;
41686d7f5d3SJohn Marino case 'f': case 'F': case 'e': case 'E': case 'g': case 'G':
41786d7f5d3SJohn Marino case 'a': case 'A':
41886d7f5d3SJohn Marino #ifdef HAVE_LONG_DOUBLE
41986d7f5d3SJohn Marino if (flags >= 16 || (flags & 4))
42086d7f5d3SJohn Marino type = TYPE_LONGDOUBLE;
42186d7f5d3SJohn Marino else
42286d7f5d3SJohn Marino #endif
42386d7f5d3SJohn Marino type = TYPE_DOUBLE;
42486d7f5d3SJohn Marino break;
42586d7f5d3SJohn Marino case 'c':
42686d7f5d3SJohn Marino if (flags >= 8)
42786d7f5d3SJohn Marino #ifdef HAVE_WINT_T
42886d7f5d3SJohn Marino type = TYPE_WIDE_CHAR;
42986d7f5d3SJohn Marino #else
43086d7f5d3SJohn Marino goto error;
43186d7f5d3SJohn Marino #endif
43286d7f5d3SJohn Marino else
43386d7f5d3SJohn Marino type = TYPE_CHAR;
43486d7f5d3SJohn Marino break;
43586d7f5d3SJohn Marino #ifdef HAVE_WINT_T
43686d7f5d3SJohn Marino case 'C':
43786d7f5d3SJohn Marino type = TYPE_WIDE_CHAR;
43886d7f5d3SJohn Marino c = 'c';
43986d7f5d3SJohn Marino break;
44086d7f5d3SJohn Marino #endif
44186d7f5d3SJohn Marino case 's':
44286d7f5d3SJohn Marino if (flags >= 8)
44386d7f5d3SJohn Marino #ifdef HAVE_WCHAR_T
44486d7f5d3SJohn Marino type = TYPE_WIDE_STRING;
44586d7f5d3SJohn Marino #else
44686d7f5d3SJohn Marino goto error;
44786d7f5d3SJohn Marino #endif
44886d7f5d3SJohn Marino else
44986d7f5d3SJohn Marino type = TYPE_STRING;
45086d7f5d3SJohn Marino break;
45186d7f5d3SJohn Marino #ifdef HAVE_WCHAR_T
45286d7f5d3SJohn Marino case 'S':
45386d7f5d3SJohn Marino type = TYPE_WIDE_STRING;
45486d7f5d3SJohn Marino c = 's';
45586d7f5d3SJohn Marino break;
45686d7f5d3SJohn Marino #endif
45786d7f5d3SJohn Marino case 'p':
45886d7f5d3SJohn Marino type = TYPE_POINTER;
45986d7f5d3SJohn Marino break;
46086d7f5d3SJohn Marino case 'n':
46186d7f5d3SJohn Marino #ifdef HAVE_LONG_LONG
46286d7f5d3SJohn Marino if (flags >= 16 || (flags & 4))
46386d7f5d3SJohn Marino type = TYPE_COUNT_LONGLONGINT_POINTER;
46486d7f5d3SJohn Marino else
46586d7f5d3SJohn Marino #endif
46686d7f5d3SJohn Marino if (flags >= 8)
46786d7f5d3SJohn Marino type = TYPE_COUNT_LONGINT_POINTER;
46886d7f5d3SJohn Marino else if (flags & 2)
46986d7f5d3SJohn Marino type = TYPE_COUNT_SCHAR_POINTER;
47086d7f5d3SJohn Marino else if (flags & 1)
47186d7f5d3SJohn Marino type = TYPE_COUNT_SHORT_POINTER;
47286d7f5d3SJohn Marino else
47386d7f5d3SJohn Marino type = TYPE_COUNT_INT_POINTER;
47486d7f5d3SJohn Marino break;
47586d7f5d3SJohn Marino case '%':
47686d7f5d3SJohn Marino type = TYPE_NONE;
47786d7f5d3SJohn Marino break;
47886d7f5d3SJohn Marino default:
47986d7f5d3SJohn Marino /* Unknown conversion character. */
48086d7f5d3SJohn Marino goto error;
48186d7f5d3SJohn Marino }
48286d7f5d3SJohn Marino }
48386d7f5d3SJohn Marino
48486d7f5d3SJohn Marino if (type != TYPE_NONE)
48586d7f5d3SJohn Marino {
48686d7f5d3SJohn Marino dp->arg_index = arg_index;
48786d7f5d3SJohn Marino if (dp->arg_index == ARG_NONE)
48886d7f5d3SJohn Marino {
48986d7f5d3SJohn Marino dp->arg_index = arg_posn++;
49086d7f5d3SJohn Marino if (dp->arg_index == ARG_NONE)
49186d7f5d3SJohn Marino /* arg_posn wrapped around. */
49286d7f5d3SJohn Marino goto error;
49386d7f5d3SJohn Marino }
49486d7f5d3SJohn Marino REGISTER_ARG (dp->arg_index, type);
49586d7f5d3SJohn Marino }
49686d7f5d3SJohn Marino dp->conversion = c;
49786d7f5d3SJohn Marino dp->dir_end = cp;
49886d7f5d3SJohn Marino }
49986d7f5d3SJohn Marino
50086d7f5d3SJohn Marino d->count++;
50186d7f5d3SJohn Marino if (d->count >= d_allocated)
50286d7f5d3SJohn Marino {
50386d7f5d3SJohn Marino size_t memory_size;
50486d7f5d3SJohn Marino DIRECTIVE *memory;
50586d7f5d3SJohn Marino
50686d7f5d3SJohn Marino d_allocated = xtimes (d_allocated, 2);
50786d7f5d3SJohn Marino memory_size = xtimes (d_allocated, sizeof (DIRECTIVE));
50886d7f5d3SJohn Marino if (size_overflow_p (memory_size))
50986d7f5d3SJohn Marino /* Overflow, would lead to out of memory. */
51086d7f5d3SJohn Marino goto error;
51186d7f5d3SJohn Marino memory = realloc (d->dir, memory_size);
51286d7f5d3SJohn Marino if (memory == NULL)
51386d7f5d3SJohn Marino /* Out of memory. */
51486d7f5d3SJohn Marino goto error;
51586d7f5d3SJohn Marino d->dir = memory;
51686d7f5d3SJohn Marino }
51786d7f5d3SJohn Marino }
51886d7f5d3SJohn Marino }
51986d7f5d3SJohn Marino d->dir[d->count].dir_start = cp;
52086d7f5d3SJohn Marino
52186d7f5d3SJohn Marino d->max_width_length = max_width_length;
52286d7f5d3SJohn Marino d->max_precision_length = max_precision_length;
52386d7f5d3SJohn Marino return 0;
52486d7f5d3SJohn Marino
52586d7f5d3SJohn Marino error:
52686d7f5d3SJohn Marino if (a->arg)
52786d7f5d3SJohn Marino free (a->arg);
52886d7f5d3SJohn Marino if (d->dir)
52986d7f5d3SJohn Marino free (d->dir);
53086d7f5d3SJohn Marino return -1;
53186d7f5d3SJohn Marino }
53286d7f5d3SJohn Marino
53386d7f5d3SJohn Marino #undef DIRECTIVES
53486d7f5d3SJohn Marino #undef DIRECTIVE
53586d7f5d3SJohn Marino #undef CHAR_T
53686d7f5d3SJohn Marino #undef PRINTF_PARSE
537