1 /* Formatted output to strings.
2 This file is intended to provide exactly the same functionality
3 as the version in gnulib, but without the need for the xsize module.
5 Copyright (C) 1999-2000, 2002-2003, 2006-2007 Free Software Foundation, Inc.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License along
18 with this program; if not, write to the Free Software Foundation,
19 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
25 # include "wprintf-parse.h"
27 # include "printf-parse.h"
30 /* Get size_t, NULL. */
33 /* Get intmax_t, SIZE_MAX. */
36 /* malloc(), realloc(), free(). */
40 # define PRINTF_PARSE wprintf_parse
41 # define CHAR_T wchar_t
42 # define DIRECTIVE wchar_t_directive
43 # define DIRECTIVES wchar_t_directives
45 # define PRINTF_PARSE printf_parse
47 # define DIRECTIVE char_directive
48 # define DIRECTIVES char_directives
55 PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a)
57 const CHAR_T *cp = format; /* pointer into format */
58 size_t arg_posn = 0; /* number of regular arguments consumed */
59 size_t d_allocated; /* allocated elements of d->dir */
60 size_t a_allocated; /* allocated elements of a->arg */
61 size_t max_width_length = 0;
62 size_t max_precision_length = 0;
66 d->dir = malloc (d_allocated * sizeof (DIRECTIVE));
75 #define REGISTER_ARG(_index_,_type_) \
77 size_t n = (_index_); \
78 if (n >= a_allocated) \
84 if (a_allocated <= n) \
85 a_allocated = n + 1; \
86 if (SIZE_MAX / sizeof (argument) < a_allocated) \
87 /* Overflow, would lead to out of memory. */ \
89 memory_size = a_allocated * sizeof (argument); \
91 ? realloc (a->arg, memory_size) \
92 : malloc (memory_size)); \
94 /* Out of memory. */ \
98 while (a->count <= n) \
99 a->arg[a->count++].type = TYPE_NONE; \
100 if (a->arg[n].type == TYPE_NONE) \
101 a->arg[n].type = (_type_); \
102 else if (a->arg[n].type != (_type_)) \
103 /* Ambiguous type for positional argument. */ \
112 size_t arg_index = ARG_NONE;
113 DIRECTIVE *dp = &d->dir[d->count];/* pointer to next directive */
115 /* Initialize the next directive. */
116 dp->dir_start = cp - 1;
118 dp->width_start = NULL;
119 dp->width_end = NULL;
120 dp->width_arg_index = ARG_NONE;
121 dp->precision_start = NULL;
122 dp->precision_end = NULL;
123 dp->precision_arg_index = ARG_NONE;
124 dp->arg_index = ARG_NONE;
126 /* Test for positional argument. */
127 if (*cp >= '0' && *cp <= '9')
131 for (np = cp; *np >= '0' && *np <= '9'; np++)
137 for (np = cp; *np >= '0' && *np <= '9'; np++)
138 if (n < SIZE_MAX / 10)
139 n = 10 * n + (*np - '0');
141 /* n too large for memory. */
144 /* Positional argument 0. */
151 /* Read the flags. */
156 dp->flags |= FLAG_GROUP;
161 dp->flags |= FLAG_LEFT;
166 dp->flags |= FLAG_SHOWSIGN;
171 dp->flags |= FLAG_SPACE;
176 dp->flags |= FLAG_ALT;
181 dp->flags |= FLAG_ZERO;
188 /* Parse the field width. */
191 dp->width_start = cp;
194 if (max_width_length < 1)
195 max_width_length = 1;
197 /* Test for positional argument. */
198 if (*cp >= '0' && *cp <= '9')
202 for (np = cp; *np >= '0' && *np <= '9'; np++)
208 for (np = cp; *np >= '0' && *np <= '9'; np++)
209 if (n < SIZE_MAX / 10)
210 n = 10 * n + (*np - '0');
212 /* n too large for memory. */
215 /* Positional argument 0. */
217 dp->width_arg_index = n - 1;
221 if (dp->width_arg_index == ARG_NONE)
223 dp->width_arg_index = arg_posn++;
224 if (dp->width_arg_index == ARG_NONE)
225 /* arg_posn wrapped around. */
228 REGISTER_ARG (dp->width_arg_index, TYPE_INT);
230 else if (*cp >= '0' && *cp <= '9')
234 dp->width_start = cp;
235 for (; *cp >= '0' && *cp <= '9'; cp++)
238 width_length = dp->width_end - dp->width_start;
239 if (max_width_length < width_length)
240 max_width_length = width_length;
243 /* Parse the precision. */
249 dp->precision_start = cp - 1;
251 dp->precision_end = cp;
252 if (max_precision_length < 2)
253 max_precision_length = 2;
255 /* Test for positional argument. */
256 if (*cp >= '0' && *cp <= '9')
260 for (np = cp; *np >= '0' && *np <= '9'; np++)
266 for (np = cp; *np >= '0' && *np <= '9'; np++)
267 if (n < SIZE_MAX / 10)
268 n = 10 * n + (*np - '0');
270 /* n too large for memory. */
273 /* Positional argument 0. */
275 dp->precision_arg_index = n - 1;
279 if (dp->precision_arg_index == ARG_NONE)
281 dp->precision_arg_index = arg_posn++;
282 if (dp->precision_arg_index == ARG_NONE)
283 /* arg_posn wrapped around. */
286 REGISTER_ARG (dp->precision_arg_index, TYPE_INT);
290 size_t precision_length;
292 dp->precision_start = cp - 1;
293 for (; *cp >= '0' && *cp <= '9'; cp++)
295 dp->precision_end = cp;
296 precision_length = dp->precision_end - dp->precision_start;
297 if (max_precision_length < precision_length)
298 max_precision_length = precision_length;
305 /* Parse argument type/size specifiers. */
313 flags |= (1 << (flags & 1));
329 if (sizeof (intmax_t) > sizeof (long))
331 /* intmax_t = long long */
334 else if (sizeof (intmax_t) > sizeof (int))
336 /* intmax_t = long */
342 else if (*cp == 'z' || *cp == 'Z')
344 /* 'z' is standardized in ISO C 99, but glibc uses 'Z'
345 because the warning facility in gcc-2.95.2 understands
346 only 'Z' (see gcc-2.95.2/gcc/c-common.c:1784). */
347 if (sizeof (size_t) > sizeof (long))
349 /* size_t = long long */
352 else if (sizeof (size_t) > sizeof (int))
361 if (sizeof (ptrdiff_t) > sizeof (long))
363 /* ptrdiff_t = long long */
366 else if (sizeof (ptrdiff_t) > sizeof (int))
368 /* ptrdiff_t = long */
377 /* Read the conversion character. */
382 #if HAVE_LONG_LONG_INT
383 /* If 'long long' exists and is larger than 'long': */
384 if (flags >= 16 || (flags & 4))
385 type = TYPE_LONGLONGINT;
388 /* If 'long long' exists and is the same as 'long', we parse
389 "lld" into TYPE_LONGINT. */
399 case 'o': case 'u': case 'x': case 'X':
400 #if HAVE_LONG_LONG_INT
401 /* If 'long long' exists and is larger than 'long': */
402 if (flags >= 16 || (flags & 4))
403 type = TYPE_ULONGLONGINT;
406 /* If 'unsigned long long' exists and is the same as
407 'unsigned long', we parse "llu" into TYPE_ULONGINT. */
409 type = TYPE_ULONGINT;
417 case 'f': case 'F': case 'e': case 'E': case 'g': case 'G':
420 if (flags >= 16 || (flags & 4))
421 type = TYPE_LONGDOUBLE;
429 type = TYPE_WIDE_CHAR;
438 type = TYPE_WIDE_CHAR;
445 type = TYPE_WIDE_STRING;
454 type = TYPE_WIDE_STRING;
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_COUNT_LONGLONGINT_POINTER;
468 /* If 'long long' exists and is the same as 'long', we parse
469 "lln" into TYPE_COUNT_LONGINT_POINTER. */
471 type = TYPE_COUNT_LONGINT_POINTER;
473 type = TYPE_COUNT_SCHAR_POINTER;
475 type = TYPE_COUNT_SHORT_POINTER;
477 type = TYPE_COUNT_INT_POINTER;
483 /* Unknown conversion character. */
488 if (type != TYPE_NONE)
490 dp->arg_index = arg_index;
491 if (dp->arg_index == ARG_NONE)
493 dp->arg_index = arg_posn++;
494 if (dp->arg_index == ARG_NONE)
495 /* arg_posn wrapped around. */
498 REGISTER_ARG (dp->arg_index, type);
505 if (d->count >= d_allocated)
509 if (SIZE_MAX / (2 * sizeof (DIRECTIVE)) < d_allocated)
510 /* Overflow, would lead to out of memory. */
513 memory = realloc (d->dir, d_allocated * sizeof (DIRECTIVE));
521 d->dir[d->count].dir_start = cp;
523 d->max_width_length = max_width_length;
524 d->max_precision_length = max_precision_length;