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,
23 #include "gst-printf.h"
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. */ \
96 char_directive *dp = &d->dir[d->count]; /* pointer to next directive */
98 /* Initialize the next directive. */
99 dp->dir_start = cp - 1;
101 dp->width_start = NULL;
102 dp->width_end = NULL;
103 dp->width_arg_index = -1;
104 dp->precision_start = NULL;
105 dp->precision_end = NULL;
106 dp->precision_arg_index = -1;
109 /* Test for positional argument. */
110 if (*cp >= '0' && *cp <= '9') {
113 for (np = cp; *np >= '0' && *np <= '9'; np++);
117 for (np = cp; *np >= '0' && *np <= '9'; np++)
118 n = 10 * n + (*np - '0');
120 /* Positional argument 0. */
127 /* Read the flags. */
130 dp->flags |= FLAG_GROUP;
132 } else if (*cp == '-') {
133 dp->flags |= FLAG_LEFT;
135 } else if (*cp == '+') {
136 dp->flags |= FLAG_SHOWSIGN;
138 } else if (*cp == ' ') {
139 dp->flags |= FLAG_SPACE;
141 } else if (*cp == '#') {
142 dp->flags |= FLAG_ALT;
144 } else if (*cp == '0') {
145 dp->flags |= FLAG_ZERO;
151 /* Parse the field width. */
153 dp->width_start = cp;
156 if (max_width_length < 1)
157 max_width_length = 1;
159 /* Test for positional argument. */
160 if (*cp >= '0' && *cp <= '9') {
163 for (np = cp; *np >= '0' && *np <= '9'; np++);
167 for (np = cp; *np >= '0' && *np <= '9'; np++)
168 n = 10 * n + (*np - '0');
170 /* Positional argument 0. */
172 dp->width_arg_index = n - 1;
176 if (dp->width_arg_index < 0)
177 dp->width_arg_index = arg_posn++;
178 REGISTER_ARG (dp->width_arg_index, TYPE_INT);
179 } else if (*cp >= '0' && *cp <= '9') {
180 unsigned int width_length;
182 dp->width_start = cp;
183 for (; *cp >= '0' && *cp <= '9'; cp++);
185 width_length = dp->width_end - dp->width_start;
186 if (max_width_length < width_length)
187 max_width_length = width_length;
190 /* Parse the precision. */
194 dp->precision_start = cp - 1;
196 dp->precision_end = cp;
197 if (max_precision_length < 2)
198 max_precision_length = 2;
200 /* Test for positional argument. */
201 if (*cp >= '0' && *cp <= '9') {
204 for (np = cp; *np >= '0' && *np <= '9'; np++);
208 for (np = cp; *np >= '0' && *np <= '9'; np++)
209 n = 10 * n + (*np - '0');
211 /* Positional argument 0. */
213 dp->precision_arg_index = n - 1;
217 if (dp->precision_arg_index < 0)
218 dp->precision_arg_index = arg_posn++;
219 REGISTER_ARG (dp->precision_arg_index, TYPE_INT);
221 unsigned int precision_length;
223 dp->precision_start = cp - 1;
224 for (; *cp >= '0' && *cp <= '9'; cp++);
225 dp->precision_end = cp;
226 precision_length = dp->precision_end - dp->precision_start;
227 if (max_precision_length < precision_length)
228 max_precision_length = precision_length;
235 /* Parse argument type/size specifiers. */
241 flags |= (1 << (flags & 1));
243 } else if (*cp == 'L') {
246 } else if (*cp == 'l') {
250 #ifdef HAVE_INT64_AND_I64
251 else if (cp[0] == 'I' && cp[1] == '6' && cp[2] == '4') {
257 else if (*cp == 'j') {
258 if (sizeof (intmax_t) > sizeof (long)) {
259 /* intmax_t = long long */
261 } else if (sizeof (intmax_t) > sizeof (int)) {
262 /* intmax_t = long */
268 else if (*cp == 'z' || *cp == 'Z') {
269 /* 'z' is standardized in ISO C 99, but glibc uses 'Z'
270 because the warning facility in gcc-2.95.2 understands
271 only 'Z' (see gcc-2.95.2/gcc/c-common.c:1784). */
272 if (sizeof (size_t) > sizeof (long)) {
273 /* size_t = long long */
275 } else if (sizeof (size_t) > sizeof (int)) {
280 } else if (*cp == 't') {
281 if (sizeof (ptrdiff_t) > sizeof (long)) {
282 /* ptrdiff_t = long long */
284 } else if (sizeof (ptrdiff_t) > sizeof (int)) {
285 /* ptrdiff_t = long */
293 /* Read the conversion character. */
298 #ifdef HAVE_INT64_AND_I64
303 #ifdef HAVE_LONG_LONG
304 if (flags >= 16 || (flags & 4))
305 type = TYPE_LONGLONGINT;
321 #ifdef HAVE_INT64_AND_I64
326 #ifdef HAVE_LONG_LONG
327 if (flags >= 16 || (flags & 4))
328 type = TYPE_ULONGLONGINT;
332 type = TYPE_ULONGINT;
348 #ifdef HAVE_LONG_DOUBLE
349 if (flags >= 16 || (flags & 4))
350 type = TYPE_LONGDOUBLE;
358 type = TYPE_WIDE_CHAR;
367 type = TYPE_WIDE_CHAR;
374 type = TYPE_WIDE_STRING;
383 type = TYPE_WIDE_STRING;
391 #ifdef HAVE_LONG_LONG
392 if (flags >= 16 || (flags & 4))
393 type = TYPE_COUNT_LONGLONGINT_POINTER;
397 type = TYPE_COUNT_LONGINT_POINTER;
399 type = TYPE_COUNT_SCHAR_POINTER;
401 type = TYPE_COUNT_SHORT_POINTER;
403 type = TYPE_COUNT_INT_POINTER;
409 /* Unknown conversion character. */
414 if (type != TYPE_NONE) {
415 dp->arg_index = arg_index;
416 if (dp->arg_index < 0)
417 dp->arg_index = arg_posn++;
418 REGISTER_ARG (dp->arg_index, type);
425 if (d->count >= d_allocated) {
426 char_directive *memory;
428 d_allocated = 2 * d_allocated;
429 memory = realloc (d->dir, d_allocated * sizeof (char_directive));
437 d->dir[d->count].dir_start = cp;
439 d->max_width_length = max_width_length;
440 d->max_precision_length = max_precision_length;