1 /* Formatted output to strings.
2 Copyright (C) 1999-2000, 2002-2003 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify it
5 under the terms of the GNU Library General Public License as published
6 by the Free Software Foundation; either version 2, or (at your option)
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 GNU
12 Library General Public License for more details.
14 You should have received a copy of the GNU Library General Public
15 License along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
26 #include "printf-parse.h"
28 /* Get size_t, NULL. */
32 #if HAVE_STDINT_H_WITH_UINTMAX
35 #if HAVE_INTTYPES_H_WITH_UINTMAX
36 # include <inttypes.h>
39 /* malloc(), realloc(), free(). */
46 printf_parse (const char *format, char_directives *d, arguments *a)
48 const char *cp = format; /* pointer into format */
49 int arg_posn = 0; /* number of regular arguments consumed */
50 unsigned int d_allocated; /* allocated elements of d->dir */
51 unsigned int a_allocated; /* allocated elements of a->arg */
52 unsigned int max_width_length = 0;
53 unsigned int max_precision_length = 0;
57 d->dir = malloc (d_allocated * sizeof (char_directive));
66 #define REGISTER_ARG(_index_,_type_) \
68 unsigned int n = (_index_); \
69 if (n >= a_allocated) \
72 a_allocated = 2 * a_allocated; \
73 if (a_allocated <= n) \
74 a_allocated = n + 1; \
76 ? realloc (a->arg, a_allocated * sizeof (argument)) \
77 : malloc (a_allocated * sizeof (argument))); \
79 /* Out of memory. */ \
83 while (a->count <= n) \
84 a->arg[a->count++].type = TYPE_NONE; \
85 if (a->arg[n].type == TYPE_NONE) \
86 a->arg[n].type = (_type_); \
87 else if (a->arg[n].type != (_type_)) \
88 /* Ambiguous type for positional argument. */ \
98 char_directive *dp = &d->dir[d->count];/* pointer to next directive */
100 /* Initialize the next directive. */
101 dp->dir_start = cp - 1;
103 dp->width_start = NULL;
104 dp->width_end = NULL;
105 dp->width_arg_index = -1;
106 dp->precision_start = NULL;
107 dp->precision_end = NULL;
108 dp->precision_arg_index = -1;
111 /* Test for positional argument. */
112 if (*cp >= '0' && *cp <= '9')
116 for (np = cp; *np >= '0' && *np <= '9'; np++)
122 for (np = cp; *np >= '0' && *np <= '9'; np++)
123 n = 10 * n + (*np - '0');
125 /* Positional argument 0. */
132 /* Read the flags. */
137 dp->flags |= FLAG_GROUP;
142 dp->flags |= FLAG_LEFT;
147 dp->flags |= FLAG_SHOWSIGN;
152 dp->flags |= FLAG_SPACE;
157 dp->flags |= FLAG_ALT;
162 dp->flags |= FLAG_ZERO;
169 /* Parse the field width. */
172 dp->width_start = cp;
175 if (max_width_length < 1)
176 max_width_length = 1;
178 /* Test for positional argument. */
179 if (*cp >= '0' && *cp <= '9')
183 for (np = cp; *np >= '0' && *np <= '9'; np++)
189 for (np = cp; *np >= '0' && *np <= '9'; np++)
190 n = 10 * n + (*np - '0');
192 /* Positional argument 0. */
194 dp->width_arg_index = n - 1;
198 if (dp->width_arg_index < 0)
199 dp->width_arg_index = arg_posn++;
200 REGISTER_ARG (dp->width_arg_index, TYPE_INT);
202 else if (*cp >= '0' && *cp <= '9')
204 unsigned int width_length;
206 dp->width_start = cp;
207 for (; *cp >= '0' && *cp <= '9'; cp++)
210 width_length = dp->width_end - dp->width_start;
211 if (max_width_length < width_length)
212 max_width_length = width_length;
215 /* Parse the precision. */
221 dp->precision_start = cp - 1;
223 dp->precision_end = cp;
224 if (max_precision_length < 2)
225 max_precision_length = 2;
227 /* Test for positional argument. */
228 if (*cp >= '0' && *cp <= '9')
232 for (np = cp; *np >= '0' && *np <= '9'; np++)
238 for (np = cp; *np >= '0' && *np <= '9'; np++)
239 n = 10 * n + (*np - '0');
241 /* Positional argument 0. */
243 dp->precision_arg_index = n - 1;
247 if (dp->precision_arg_index < 0)
248 dp->precision_arg_index = arg_posn++;
249 REGISTER_ARG (dp->precision_arg_index, TYPE_INT);
253 unsigned int precision_length;
255 dp->precision_start = cp - 1;
256 for (; *cp >= '0' && *cp <= '9'; cp++)
258 dp->precision_end = cp;
259 precision_length = dp->precision_end - dp->precision_start;
260 if (max_precision_length < precision_length)
261 max_precision_length = precision_length;
268 /* Parse argument type/size specifiers. */
276 flags |= (1 << (flags & 1));
289 #ifdef HAVE_INT64_AND_I64
290 else if (cp[0] == 'I' &&
301 if (sizeof (intmax_t) > sizeof (long))
303 /* intmax_t = long long */
306 else if (sizeof (intmax_t) > sizeof (int))
308 /* intmax_t = long */
314 else if (*cp == 'z' || *cp == 'Z')
316 /* 'z' is standardized in ISO C 99, but glibc uses 'Z'
317 because the warning facility in gcc-2.95.2 understands
318 only 'Z' (see gcc-2.95.2/gcc/c-common.c:1784). */
319 if (sizeof (size_t) > sizeof (long))
321 /* size_t = long long */
324 else if (sizeof (size_t) > sizeof (int))
333 if (sizeof (ptrdiff_t) > sizeof (long))
335 /* ptrdiff_t = long long */
338 else if (sizeof (ptrdiff_t) > sizeof (int))
340 /* ptrdiff_t = long */
349 /* Read the conversion character. */
354 #ifdef HAVE_INT64_AND_I64
359 #ifdef HAVE_LONG_LONG
360 if (flags >= 16 || (flags & 4))
361 type = TYPE_LONGLONGINT;
373 case 'o': case 'u': case 'x': case 'X':
374 #ifdef HAVE_INT64_AND_I64
379 #ifdef HAVE_LONG_LONG
380 if (flags >= 16 || (flags & 4))
381 type = TYPE_ULONGLONGINT;
385 type = TYPE_ULONGINT;
393 case 'f': case 'F': case 'e': case 'E': case 'g': case 'G':
395 #ifdef HAVE_LONG_DOUBLE
396 if (flags >= 16 || (flags & 4))
397 type = TYPE_LONGDOUBLE;
405 type = TYPE_WIDE_CHAR;
414 type = TYPE_WIDE_CHAR;
421 type = TYPE_WIDE_STRING;
430 type = TYPE_WIDE_STRING;
438 #ifdef HAVE_LONG_LONG
439 if (flags >= 16 || (flags & 4))
440 type = TYPE_COUNT_LONGLONGINT_POINTER;
444 type = TYPE_COUNT_LONGINT_POINTER;
446 type = TYPE_COUNT_SCHAR_POINTER;
448 type = TYPE_COUNT_SHORT_POINTER;
450 type = TYPE_COUNT_INT_POINTER;
456 /* Unknown conversion character. */
461 if (type != TYPE_NONE)
463 dp->arg_index = arg_index;
464 if (dp->arg_index < 0)
465 dp->arg_index = arg_posn++;
466 REGISTER_ARG (dp->arg_index, type);
473 if (d->count >= d_allocated)
475 char_directive *memory;
477 d_allocated = 2 * d_allocated;
478 memory = realloc (d->dir, d_allocated * sizeof (char_directive));
486 d->dir[d->count].dir_start = cp;
488 d->max_width_length = max_width_length;
489 d->max_precision_length = max_precision_length;