1
/* Formatted output to strings.
2
Copyright (C) 1999-2000, 2002-2003, 2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
23
# include "wprintf-parse.h"
25
# 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(). */
42
/* Checked size_t computations. */
46
# define PRINTF_PARSE wprintf_parse
47
# define CHAR_T wchar_t
48
# define DIRECTIVE wchar_t_directive
49
# define DIRECTIVES wchar_t_directives
51
# define PRINTF_PARSE printf_parse
53
# define DIRECTIVE char_directive
54
# define DIRECTIVES char_directives
61
PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a)
63
const CHAR_T *cp = format; /* pointer into format */
64
size_t arg_posn = 0; /* number of regular arguments consumed */
65
size_t d_allocated; /* allocated elements of d->dir */
66
size_t a_allocated; /* allocated elements of a->arg */
67
size_t max_width_length = 0;
68
size_t max_precision_length = 0;
72
d->dir = malloc (d_allocated * sizeof (DIRECTIVE));
81
#define REGISTER_ARG(_index_,_type_) \
83
size_t n = (_index_); \
84
if (n >= a_allocated) \
89
a_allocated = xtimes (a_allocated, 2); \
90
if (a_allocated <= n) \
91
a_allocated = xsum (n, 1); \
92
memory_size = xtimes (a_allocated, sizeof (argument)); \
93
if (size_overflow_p (memory_size)) \
94
/* Overflow, would lead to out of memory. */ \
97
? realloc (a->arg, memory_size) \
98
: malloc (memory_size)); \
100
/* Out of memory. */ \
104
while (a->count <= n) \
105
a->arg[a->count++].type = TYPE_NONE; \
106
if (a->arg[n].type == TYPE_NONE) \
107
a->arg[n].type = (_type_); \
108
else if (a->arg[n].type != (_type_)) \
109
/* Ambiguous type for positional argument. */ \
118
size_t arg_index = ARG_NONE;
119
DIRECTIVE *dp = &d->dir[d->count];/* pointer to next directive */
121
/* Initialize the next directive. */
122
dp->dir_start = cp - 1;
124
dp->width_start = NULL;
125
dp->width_end = NULL;
126
dp->width_arg_index = ARG_NONE;
127
dp->precision_start = NULL;
128
dp->precision_end = NULL;
129
dp->precision_arg_index = ARG_NONE;
130
dp->arg_index = ARG_NONE;
132
/* Test for positional argument. */
133
if (*cp >= '0' && *cp <= '9')
137
for (np = cp; *np >= '0' && *np <= '9'; np++)
143
for (np = cp; *np >= '0' && *np <= '9'; np++)
144
n = xsum (xtimes (n, 10), *np - '0');
146
/* Positional argument 0. */
148
if (size_overflow_p (n))
149
/* n too large, would lead to out of memory later. */
156
/* Read the flags. */
161
dp->flags |= FLAG_GROUP;
166
dp->flags |= FLAG_LEFT;
171
dp->flags |= FLAG_SHOWSIGN;
176
dp->flags |= FLAG_SPACE;
181
dp->flags |= FLAG_ALT;
186
dp->flags |= FLAG_ZERO;
193
/* Parse the field width. */
196
dp->width_start = cp;
199
if (max_width_length < 1)
200
max_width_length = 1;
202
/* Test for positional argument. */
203
if (*cp >= '0' && *cp <= '9')
207
for (np = cp; *np >= '0' && *np <= '9'; np++)
213
for (np = cp; *np >= '0' && *np <= '9'; np++)
214
n = xsum (xtimes (n, 10), *np - '0');
216
/* Positional argument 0. */
218
if (size_overflow_p (n))
219
/* n too large, would lead to out of memory later. */
221
dp->width_arg_index = n - 1;
225
if (dp->width_arg_index == ARG_NONE)
227
dp->width_arg_index = arg_posn++;
228
if (dp->width_arg_index == ARG_NONE)
229
/* arg_posn wrapped around. */
232
REGISTER_ARG (dp->width_arg_index, TYPE_INT);
234
else if (*cp >= '0' && *cp <= '9')
238
dp->width_start = cp;
239
for (; *cp >= '0' && *cp <= '9'; cp++)
242
width_length = dp->width_end - dp->width_start;
243
if (max_width_length < width_length)
244
max_width_length = width_length;
247
/* Parse the precision. */
253
dp->precision_start = cp - 1;
255
dp->precision_end = cp;
256
if (max_precision_length < 2)
257
max_precision_length = 2;
259
/* Test for positional argument. */
260
if (*cp >= '0' && *cp <= '9')
264
for (np = cp; *np >= '0' && *np <= '9'; np++)
270
for (np = cp; *np >= '0' && *np <= '9'; np++)
271
n = xsum (xtimes (n, 10), *np - '0');
273
/* Positional argument 0. */
275
if (size_overflow_p (n))
276
/* n too large, would lead to out of memory
279
dp->precision_arg_index = n - 1;
283
if (dp->precision_arg_index == ARG_NONE)
285
dp->precision_arg_index = arg_posn++;
286
if (dp->precision_arg_index == ARG_NONE)
287
/* arg_posn wrapped around. */
290
REGISTER_ARG (dp->precision_arg_index, TYPE_INT);
294
size_t precision_length;
296
dp->precision_start = cp - 1;
297
for (; *cp >= '0' && *cp <= '9'; cp++)
299
dp->precision_end = cp;
300
precision_length = dp->precision_end - dp->precision_start;
301
if (max_precision_length < precision_length)
302
max_precision_length = precision_length;
309
/* Parse argument type/size specifiers. */
317
flags |= (1 << (flags & 1));
333
if (sizeof (intmax_t) > sizeof (long))
335
/* intmax_t = long long */
338
else if (sizeof (intmax_t) > sizeof (int))
340
/* intmax_t = long */
346
else if (*cp == 'z' || *cp == 'Z')
348
/* 'z' is standardized in ISO C 99, but glibc uses 'Z'
349
because the warning facility in gcc-2.95.2 understands
350
only 'Z' (see gcc-2.95.2/gcc/c-common.c:1784). */
351
if (sizeof (size_t) > sizeof (long))
353
/* size_t = long long */
356
else if (sizeof (size_t) > sizeof (int))
365
if (sizeof (ptrdiff_t) > sizeof (long))
367
/* ptrdiff_t = long long */
370
else if (sizeof (ptrdiff_t) > sizeof (int))
372
/* ptrdiff_t = long */
381
/* Read the conversion character. */
386
#ifdef HAVE_LONG_LONG_INT
387
/* If 'long long' exists and is larger than 'long': */
388
if (flags >= 16 || (flags & 4))
389
type = TYPE_LONGLONGINT;
392
/* If 'long long' exists and is the same as 'long', we parse
393
"lld" into TYPE_LONGINT. */
403
case 'o': case 'u': case 'x': case 'X':
404
#ifdef HAVE_LONG_LONG_INT
405
/* If 'long long' exists and is larger than 'long': */
406
if (flags >= 16 || (flags & 4))
407
type = TYPE_ULONGLONGINT;
410
/* If 'unsigned long long' exists and is the same as
411
'unsigned long', we parse "llu" into TYPE_ULONGINT. */
413
type = TYPE_ULONGINT;
421
case 'f': case 'F': case 'e': case 'E': case 'g': case 'G':
423
#ifdef HAVE_LONG_DOUBLE
424
if (flags >= 16 || (flags & 4))
425
type = TYPE_LONGDOUBLE;
433
type = TYPE_WIDE_CHAR;
442
type = TYPE_WIDE_CHAR;
449
type = TYPE_WIDE_STRING;
458
type = TYPE_WIDE_STRING;
466
#ifdef HAVE_LONG_LONG_INT
467
/* If 'long long' exists and is larger than 'long': */
468
if (flags >= 16 || (flags & 4))
469
type = TYPE_COUNT_LONGLONGINT_POINTER;
472
/* If 'long long' exists and is the same as 'long', we parse
473
"lln" into TYPE_COUNT_LONGINT_POINTER. */
475
type = TYPE_COUNT_LONGINT_POINTER;
477
type = TYPE_COUNT_SCHAR_POINTER;
479
type = TYPE_COUNT_SHORT_POINTER;
481
type = TYPE_COUNT_INT_POINTER;
487
/* Unknown conversion character. */
492
if (type != TYPE_NONE)
494
dp->arg_index = arg_index;
495
if (dp->arg_index == ARG_NONE)
497
dp->arg_index = arg_posn++;
498
if (dp->arg_index == ARG_NONE)
499
/* arg_posn wrapped around. */
502
REGISTER_ARG (dp->arg_index, type);
509
if (d->count >= d_allocated)
514
d_allocated = xtimes (d_allocated, 2);
515
memory_size = xtimes (d_allocated, sizeof (DIRECTIVE));
516
if (size_overflow_p (memory_size))
517
/* Overflow, would lead to out of memory. */
519
memory = realloc (d->dir, memory_size);
527
d->dir[d->count].dir_start = cp;
529
d->max_width_length = max_width_length;
530
d->max_precision_length = max_precision_length;