summaryrefslogtreecommitdiffstats
path: root/gl/printf-parse.c
diff options
context:
space:
mode:
Diffstat (limited to 'gl/printf-parse.c')
-rw-r--r--gl/printf-parse.c940
1 files changed, 470 insertions, 470 deletions
diff --git a/gl/printf-parse.c b/gl/printf-parse.c
index 28b9bd4..f612beb 100644
--- a/gl/printf-parse.c
+++ b/gl/printf-parse.c
@@ -1,5 +1,5 @@
1/* Formatted output to strings. 1/* Formatted output to strings.
2 Copyright (C) 1999-2000, 2002-2003, 2006-2008 Free Software Foundation, Inc. 2 Copyright (C) 1999-2000, 2002-2003, 2006-2010 Free Software Foundation, Inc.
3 3
4 This program is free software; you can redistribute it and/or modify 4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by 5 it under the terms of the GNU General Public License as published by
@@ -80,10 +80,10 @@ STATIC
80int 80int
81PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a) 81PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a)
82{ 82{
83 const CHAR_T *cp = format; /* pointer into format */ 83 const CHAR_T *cp = format; /* pointer into format */
84 size_t arg_posn = 0; /* number of regular arguments consumed */ 84 size_t arg_posn = 0; /* number of regular arguments consumed */
85 size_t d_allocated; /* allocated elements of d->dir */ 85 size_t d_allocated; /* allocated elements of d->dir */
86 size_t a_allocated; /* allocated elements of a->arg */ 86 size_t a_allocated; /* allocated elements of a->arg */
87 size_t max_width_length = 0; 87 size_t max_width_length = 0;
88 size_t max_precision_length = 0; 88 size_t max_precision_length = 0;
89 89
@@ -99,501 +99,501 @@ PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a)
99 a->arg = NULL; 99 a->arg = NULL;
100 100
101#define REGISTER_ARG(_index_,_type_) \ 101#define REGISTER_ARG(_index_,_type_) \
102 { \ 102 { \
103 size_t n = (_index_); \ 103 size_t n = (_index_); \
104 if (n >= a_allocated) \ 104 if (n >= a_allocated) \
105 { \ 105 { \
106 size_t memory_size; \ 106 size_t memory_size; \
107 argument *memory; \ 107 argument *memory; \
108 \ 108 \
109 a_allocated = xtimes (a_allocated, 2); \ 109 a_allocated = xtimes (a_allocated, 2); \
110 if (a_allocated <= n) \ 110 if (a_allocated <= n) \
111 a_allocated = xsum (n, 1); \ 111 a_allocated = xsum (n, 1); \
112 memory_size = xtimes (a_allocated, sizeof (argument)); \ 112 memory_size = xtimes (a_allocated, sizeof (argument)); \
113 if (size_overflow_p (memory_size)) \ 113 if (size_overflow_p (memory_size)) \
114 /* Overflow, would lead to out of memory. */ \ 114 /* Overflow, would lead to out of memory. */ \
115 goto out_of_memory; \ 115 goto out_of_memory; \
116 memory = (argument *) (a->arg \ 116 memory = (argument *) (a->arg \
117 ? realloc (a->arg, memory_size) \ 117 ? realloc (a->arg, memory_size) \
118 : malloc (memory_size)); \ 118 : malloc (memory_size)); \
119 if (memory == NULL) \ 119 if (memory == NULL) \
120 /* Out of memory. */ \ 120 /* Out of memory. */ \
121 goto out_of_memory; \ 121 goto out_of_memory; \
122 a->arg = memory; \ 122 a->arg = memory; \
123 } \ 123 } \
124 while (a->count <= n) \ 124 while (a->count <= n) \
125 a->arg[a->count++].type = TYPE_NONE; \ 125 a->arg[a->count++].type = TYPE_NONE; \
126 if (a->arg[n].type == TYPE_NONE) \ 126 if (a->arg[n].type == TYPE_NONE) \
127 a->arg[n].type = (_type_); \ 127 a->arg[n].type = (_type_); \
128 else if (a->arg[n].type != (_type_)) \ 128 else if (a->arg[n].type != (_type_)) \
129 /* Ambiguous type for positional argument. */ \ 129 /* Ambiguous type for positional argument. */ \
130 goto error; \ 130 goto error; \
131 } 131 }
132 132
133 while (*cp != '\0') 133 while (*cp != '\0')
134 { 134 {
135 CHAR_T c = *cp++; 135 CHAR_T c = *cp++;
136 if (c == '%') 136 if (c == '%')
137 { 137 {
138 size_t arg_index = ARG_NONE; 138 size_t arg_index = ARG_NONE;
139 DIRECTIVE *dp = &d->dir[d->count]; /* pointer to next directive */ 139 DIRECTIVE *dp = &d->dir[d->count]; /* pointer to next directive */
140 140
141 /* Initialize the next directive. */ 141 /* Initialize the next directive. */
142 dp->dir_start = cp - 1; 142 dp->dir_start = cp - 1;
143 dp->flags = 0; 143 dp->flags = 0;
144 dp->width_start = NULL; 144 dp->width_start = NULL;
145 dp->width_end = NULL; 145 dp->width_end = NULL;
146 dp->width_arg_index = ARG_NONE; 146 dp->width_arg_index = ARG_NONE;
147 dp->precision_start = NULL; 147 dp->precision_start = NULL;
148 dp->precision_end = NULL; 148 dp->precision_end = NULL;
149 dp->precision_arg_index = ARG_NONE; 149 dp->precision_arg_index = ARG_NONE;
150 dp->arg_index = ARG_NONE; 150 dp->arg_index = ARG_NONE;
151 151
152 /* Test for positional argument. */ 152 /* Test for positional argument. */
153 if (*cp >= '0' && *cp <= '9') 153 if (*cp >= '0' && *cp <= '9')
154 { 154 {
155 const CHAR_T *np; 155 const CHAR_T *np;
156 156
157 for (np = cp; *np >= '0' && *np <= '9'; np++) 157 for (np = cp; *np >= '0' && *np <= '9'; np++)
158 ; 158 ;
159 if (*np == '$') 159 if (*np == '$')
160 { 160 {
161 size_t n = 0; 161 size_t n = 0;
162 162
163 for (np = cp; *np >= '0' && *np <= '9'; np++) 163 for (np = cp; *np >= '0' && *np <= '9'; np++)
164 n = xsum (xtimes (n, 10), *np - '0'); 164 n = xsum (xtimes (n, 10), *np - '0');
165 if (n == 0) 165 if (n == 0)
166 /* Positional argument 0. */ 166 /* Positional argument 0. */
167 goto error; 167 goto error;
168 if (size_overflow_p (n)) 168 if (size_overflow_p (n))
169 /* n too large, would lead to out of memory later. */ 169 /* n too large, would lead to out of memory later. */
170 goto error; 170 goto error;
171 arg_index = n - 1; 171 arg_index = n - 1;
172 cp = np + 1; 172 cp = np + 1;
173 } 173 }
174 } 174 }
175 175
176 /* Read the flags. */ 176 /* Read the flags. */
177 for (;;) 177 for (;;)
178 { 178 {
179 if (*cp == '\'') 179 if (*cp == '\'')
180 { 180 {
181 dp->flags |= FLAG_GROUP; 181 dp->flags |= FLAG_GROUP;
182 cp++; 182 cp++;
183 } 183 }
184 else if (*cp == '-') 184 else if (*cp == '-')
185 { 185 {
186 dp->flags |= FLAG_LEFT; 186 dp->flags |= FLAG_LEFT;
187 cp++; 187 cp++;
188 } 188 }
189 else if (*cp == '+') 189 else if (*cp == '+')
190 { 190 {
191 dp->flags |= FLAG_SHOWSIGN; 191 dp->flags |= FLAG_SHOWSIGN;
192 cp++; 192 cp++;
193 } 193 }
194 else if (*cp == ' ') 194 else if (*cp == ' ')
195 { 195 {
196 dp->flags |= FLAG_SPACE; 196 dp->flags |= FLAG_SPACE;
197 cp++; 197 cp++;
198 } 198 }
199 else if (*cp == '#') 199 else if (*cp == '#')
200 { 200 {
201 dp->flags |= FLAG_ALT; 201 dp->flags |= FLAG_ALT;
202 cp++; 202 cp++;
203 } 203 }
204 else if (*cp == '0') 204 else if (*cp == '0')
205 { 205 {
206 dp->flags |= FLAG_ZERO; 206 dp->flags |= FLAG_ZERO;
207 cp++; 207 cp++;
208 } 208 }
209 else 209 else
210 break; 210 break;
211 } 211 }
212 212
213 /* Parse the field width. */ 213 /* Parse the field width. */
214 if (*cp == '*') 214 if (*cp == '*')
215 { 215 {
216 dp->width_start = cp; 216 dp->width_start = cp;
217 cp++; 217 cp++;
218 dp->width_end = cp; 218 dp->width_end = cp;
219 if (max_width_length < 1) 219 if (max_width_length < 1)
220 max_width_length = 1; 220 max_width_length = 1;
221 221
222 /* Test for positional argument. */ 222 /* Test for positional argument. */
223 if (*cp >= '0' && *cp <= '9') 223 if (*cp >= '0' && *cp <= '9')
224 { 224 {
225 const CHAR_T *np; 225 const CHAR_T *np;
226 226
227 for (np = cp; *np >= '0' && *np <= '9'; np++) 227 for (np = cp; *np >= '0' && *np <= '9'; np++)
228 ; 228 ;
229 if (*np == '$') 229 if (*np == '$')
230 { 230 {
231 size_t n = 0; 231 size_t n = 0;
232 232
233 for (np = cp; *np >= '0' && *np <= '9'; np++) 233 for (np = cp; *np >= '0' && *np <= '9'; np++)
234 n = xsum (xtimes (n, 10), *np - '0'); 234 n = xsum (xtimes (n, 10), *np - '0');
235 if (n == 0) 235 if (n == 0)
236 /* Positional argument 0. */ 236 /* Positional argument 0. */
237 goto error; 237 goto error;
238 if (size_overflow_p (n)) 238 if (size_overflow_p (n))
239 /* n too large, would lead to out of memory later. */ 239 /* n too large, would lead to out of memory later. */
240 goto error; 240 goto error;
241 dp->width_arg_index = n - 1; 241 dp->width_arg_index = n - 1;
242 cp = np + 1; 242 cp = np + 1;
243 } 243 }
244 } 244 }
245 if (dp->width_arg_index == ARG_NONE) 245 if (dp->width_arg_index == ARG_NONE)
246 { 246 {
247 dp->width_arg_index = arg_posn++; 247 dp->width_arg_index = arg_posn++;
248 if (dp->width_arg_index == ARG_NONE) 248 if (dp->width_arg_index == ARG_NONE)
249 /* arg_posn wrapped around. */ 249 /* arg_posn wrapped around. */
250 goto error; 250 goto error;
251 } 251 }
252 REGISTER_ARG (dp->width_arg_index, TYPE_INT); 252 REGISTER_ARG (dp->width_arg_index, TYPE_INT);
253 } 253 }
254 else if (*cp >= '0' && *cp <= '9') 254 else if (*cp >= '0' && *cp <= '9')
255 { 255 {
256 size_t width_length; 256 size_t width_length;
257 257
258 dp->width_start = cp; 258 dp->width_start = cp;
259 for (; *cp >= '0' && *cp <= '9'; cp++) 259 for (; *cp >= '0' && *cp <= '9'; cp++)
260 ; 260 ;
261 dp->width_end = cp; 261 dp->width_end = cp;
262 width_length = dp->width_end - dp->width_start; 262 width_length = dp->width_end - dp->width_start;
263 if (max_width_length < width_length) 263 if (max_width_length < width_length)
264 max_width_length = width_length; 264 max_width_length = width_length;
265 } 265 }
266 266
267 /* Parse the precision. */ 267 /* Parse the precision. */
268 if (*cp == '.') 268 if (*cp == '.')
269 { 269 {
270 cp++; 270 cp++;
271 if (*cp == '*') 271 if (*cp == '*')
272 { 272 {
273 dp->precision_start = cp - 1; 273 dp->precision_start = cp - 1;
274 cp++; 274 cp++;
275 dp->precision_end = cp; 275 dp->precision_end = cp;
276 if (max_precision_length < 2) 276 if (max_precision_length < 2)
277 max_precision_length = 2; 277 max_precision_length = 2;
278 278
279 /* Test for positional argument. */ 279 /* Test for positional argument. */
280 if (*cp >= '0' && *cp <= '9') 280 if (*cp >= '0' && *cp <= '9')
281 { 281 {
282 const CHAR_T *np; 282 const CHAR_T *np;
283 283
284 for (np = cp; *np >= '0' && *np <= '9'; np++) 284 for (np = cp; *np >= '0' && *np <= '9'; np++)
285 ; 285 ;
286 if (*np == '$') 286 if (*np == '$')
287 { 287 {
288 size_t n = 0; 288 size_t n = 0;
289 289
290 for (np = cp; *np >= '0' && *np <= '9'; np++) 290 for (np = cp; *np >= '0' && *np <= '9'; np++)
291 n = xsum (xtimes (n, 10), *np - '0'); 291 n = xsum (xtimes (n, 10), *np - '0');
292 if (n == 0) 292 if (n == 0)
293 /* Positional argument 0. */ 293 /* Positional argument 0. */
294 goto error; 294 goto error;
295 if (size_overflow_p (n)) 295 if (size_overflow_p (n))
296 /* n too large, would lead to out of memory 296 /* n too large, would lead to out of memory
297 later. */ 297 later. */
298 goto error; 298 goto error;
299 dp->precision_arg_index = n - 1; 299 dp->precision_arg_index = n - 1;
300 cp = np + 1; 300 cp = np + 1;
301 } 301 }
302 } 302 }
303 if (dp->precision_arg_index == ARG_NONE) 303 if (dp->precision_arg_index == ARG_NONE)
304 { 304 {
305 dp->precision_arg_index = arg_posn++; 305 dp->precision_arg_index = arg_posn++;
306 if (dp->precision_arg_index == ARG_NONE) 306 if (dp->precision_arg_index == ARG_NONE)
307 /* arg_posn wrapped around. */ 307 /* arg_posn wrapped around. */
308 goto error; 308 goto error;
309 } 309 }
310 REGISTER_ARG (dp->precision_arg_index, TYPE_INT); 310 REGISTER_ARG (dp->precision_arg_index, TYPE_INT);
311 } 311 }
312 else 312 else
313 { 313 {
314 size_t precision_length; 314 size_t precision_length;
315 315
316 dp->precision_start = cp - 1; 316 dp->precision_start = cp - 1;
317 for (; *cp >= '0' && *cp <= '9'; cp++) 317 for (; *cp >= '0' && *cp <= '9'; cp++)
318 ; 318 ;
319 dp->precision_end = cp; 319 dp->precision_end = cp;
320 precision_length = dp->precision_end - dp->precision_start; 320 precision_length = dp->precision_end - dp->precision_start;
321 if (max_precision_length < precision_length) 321 if (max_precision_length < precision_length)
322 max_precision_length = precision_length; 322 max_precision_length = precision_length;
323 } 323 }
324 } 324 }
325 325
326 { 326 {
327 arg_type type; 327 arg_type type;
328 328
329 /* Parse argument type/size specifiers. */ 329 /* Parse argument type/size specifiers. */
330 { 330 {
331 int flags = 0; 331 int flags = 0;
332 332
333 for (;;) 333 for (;;)
334 { 334 {
335 if (*cp == 'h') 335 if (*cp == 'h')
336 { 336 {
337 flags |= (1 << (flags & 1)); 337 flags |= (1 << (flags & 1));
338 cp++; 338 cp++;
339 } 339 }
340 else if (*cp == 'L') 340 else if (*cp == 'L')
341 { 341 {
342 flags |= 4; 342 flags |= 4;
343 cp++; 343 cp++;
344 } 344 }
345 else if (*cp == 'l') 345 else if (*cp == 'l')
346 { 346 {
347 flags += 8; 347 flags += 8;
348 cp++; 348 cp++;
349 } 349 }
350 else if (*cp == 'j') 350 else if (*cp == 'j')
351 { 351 {
352 if (sizeof (intmax_t) > sizeof (long)) 352 if (sizeof (intmax_t) > sizeof (long))
353 { 353 {
354 /* intmax_t = long long */ 354 /* intmax_t = long long */
355 flags += 16; 355 flags += 16;
356 } 356 }
357 else if (sizeof (intmax_t) > sizeof (int)) 357 else if (sizeof (intmax_t) > sizeof (int))
358 { 358 {
359 /* intmax_t = long */ 359 /* intmax_t = long */
360 flags += 8; 360 flags += 8;
361 } 361 }
362 cp++; 362 cp++;
363 } 363 }
364 else if (*cp == 'z' || *cp == 'Z') 364 else if (*cp == 'z' || *cp == 'Z')
365 { 365 {
366 /* 'z' is standardized in ISO C 99, but glibc uses 'Z' 366 /* 'z' is standardized in ISO C 99, but glibc uses 'Z'
367 because the warning facility in gcc-2.95.2 understands 367 because the warning facility in gcc-2.95.2 understands
368 only 'Z' (see gcc-2.95.2/gcc/c-common.c:1784). */ 368 only 'Z' (see gcc-2.95.2/gcc/c-common.c:1784). */
369 if (sizeof (size_t) > sizeof (long)) 369 if (sizeof (size_t) > sizeof (long))
370 { 370 {
371 /* size_t = long long */ 371 /* size_t = long long */
372 flags += 16; 372 flags += 16;
373 } 373 }
374 else if (sizeof (size_t) > sizeof (int)) 374 else if (sizeof (size_t) > sizeof (int))
375 { 375 {
376 /* size_t = long */ 376 /* size_t = long */
377 flags += 8; 377 flags += 8;
378 } 378 }
379 cp++; 379 cp++;
380 } 380 }
381 else if (*cp == 't') 381 else if (*cp == 't')
382 { 382 {
383 if (sizeof (ptrdiff_t) > sizeof (long)) 383 if (sizeof (ptrdiff_t) > sizeof (long))
384 { 384 {
385 /* ptrdiff_t = long long */ 385 /* ptrdiff_t = long long */
386 flags += 16; 386 flags += 16;
387 } 387 }
388 else if (sizeof (ptrdiff_t) > sizeof (int)) 388 else if (sizeof (ptrdiff_t) > sizeof (int))
389 { 389 {
390 /* ptrdiff_t = long */ 390 /* ptrdiff_t = long */
391 flags += 8; 391 flags += 8;
392 } 392 }
393 cp++; 393 cp++;
394 } 394 }
395#if defined __APPLE__ && defined __MACH__ 395#if defined __APPLE__ && defined __MACH__
396 /* On MacOS X 10.3, PRIdMAX is defined as "qd". 396 /* On MacOS X 10.3, PRIdMAX is defined as "qd".
397 We cannot change it to "lld" because PRIdMAX must also 397 We cannot change it to "lld" because PRIdMAX must also
398 be understood by the system's printf routines. */ 398 be understood by the system's printf routines. */
399 else if (*cp == 'q') 399 else if (*cp == 'q')
400 { 400 {
401 if (64 / 8 > sizeof (long)) 401 if (64 / 8 > sizeof (long))
402 { 402 {
403 /* int64_t = long long */ 403 /* int64_t = long long */
404 flags += 16; 404 flags += 16;
405 } 405 }
406 else 406 else
407 { 407 {
408 /* int64_t = long */ 408 /* int64_t = long */
409 flags += 8; 409 flags += 8;
410 } 410 }
411 cp++; 411 cp++;
412 } 412 }
413#endif 413#endif
414#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ 414#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
415 /* On native Win32, PRIdMAX is defined as "I64d". 415 /* On native Win32, PRIdMAX is defined as "I64d".
416 We cannot change it to "lld" because PRIdMAX must also 416 We cannot change it to "lld" because PRIdMAX must also
417 be understood by the system's printf routines. */ 417 be understood by the system's printf routines. */
418 else if (*cp == 'I' && cp[1] == '6' && cp[2] == '4') 418 else if (*cp == 'I' && cp[1] == '6' && cp[2] == '4')
419 { 419 {
420 if (64 / 8 > sizeof (long)) 420 if (64 / 8 > sizeof (long))
421 { 421 {
422 /* __int64 = long long */ 422 /* __int64 = long long */
423 flags += 16; 423 flags += 16;
424 } 424 }
425 else 425 else
426 { 426 {
427 /* __int64 = long */ 427 /* __int64 = long */
428 flags += 8; 428 flags += 8;
429 } 429 }
430 cp += 3; 430 cp += 3;
431 } 431 }
432#endif 432#endif
433 else 433 else
434 break; 434 break;
435 } 435 }
436 436
437 /* Read the conversion character. */ 437 /* Read the conversion character. */
438 c = *cp++; 438 c = *cp++;
439 switch (c) 439 switch (c)
440 { 440 {
441 case 'd': case 'i': 441 case 'd': case 'i':
442#if HAVE_LONG_LONG_INT 442#if HAVE_LONG_LONG_INT
443 /* If 'long long' exists and is larger than 'long': */ 443 /* If 'long long' exists and is larger than 'long': */
444 if (flags >= 16 || (flags & 4)) 444 if (flags >= 16 || (flags & 4))
445 type = TYPE_LONGLONGINT; 445 type = TYPE_LONGLONGINT;
446 else 446 else
447#endif 447#endif
448 /* If 'long long' exists and is the same as 'long', we parse 448 /* If 'long long' exists and is the same as 'long', we parse
449 "lld" into TYPE_LONGINT. */ 449 "lld" into TYPE_LONGINT. */
450 if (flags >= 8) 450 if (flags >= 8)
451 type = TYPE_LONGINT; 451 type = TYPE_LONGINT;
452 else if (flags & 2) 452 else if (flags & 2)
453 type = TYPE_SCHAR; 453 type = TYPE_SCHAR;
454 else if (flags & 1) 454 else if (flags & 1)
455 type = TYPE_SHORT; 455 type = TYPE_SHORT;
456 else 456 else
457 type = TYPE_INT; 457 type = TYPE_INT;
458 break; 458 break;
459 case 'o': case 'u': case 'x': case 'X': 459 case 'o': case 'u': case 'x': case 'X':
460#if HAVE_LONG_LONG_INT 460#if HAVE_LONG_LONG_INT
461 /* If 'long long' exists and is larger than 'long': */ 461 /* If 'long long' exists and is larger than 'long': */
462 if (flags >= 16 || (flags & 4)) 462 if (flags >= 16 || (flags & 4))
463 type = TYPE_ULONGLONGINT; 463 type = TYPE_ULONGLONGINT;
464 else 464 else
465#endif 465#endif
466 /* If 'unsigned long long' exists and is the same as 466 /* If 'unsigned long long' exists and is the same as
467 'unsigned long', we parse "llu" into TYPE_ULONGINT. */ 467 'unsigned long', we parse "llu" into TYPE_ULONGINT. */
468 if (flags >= 8) 468 if (flags >= 8)
469 type = TYPE_ULONGINT; 469 type = TYPE_ULONGINT;
470 else if (flags & 2) 470 else if (flags & 2)
471 type = TYPE_UCHAR; 471 type = TYPE_UCHAR;
472 else if (flags & 1) 472 else if (flags & 1)
473 type = TYPE_USHORT; 473 type = TYPE_USHORT;
474 else 474 else
475 type = TYPE_UINT; 475 type = TYPE_UINT;
476 break; 476 break;
477 case 'f': case 'F': case 'e': case 'E': case 'g': case 'G': 477 case 'f': case 'F': case 'e': case 'E': case 'g': case 'G':
478 case 'a': case 'A': 478 case 'a': case 'A':
479 if (flags >= 16 || (flags & 4)) 479 if (flags >= 16 || (flags & 4))
480 type = TYPE_LONGDOUBLE; 480 type = TYPE_LONGDOUBLE;
481 else 481 else
482 type = TYPE_DOUBLE; 482 type = TYPE_DOUBLE;
483 break; 483 break;
484 case 'c': 484 case 'c':
485 if (flags >= 8) 485 if (flags >= 8)
486#if HAVE_WINT_T 486#if HAVE_WINT_T
487 type = TYPE_WIDE_CHAR; 487 type = TYPE_WIDE_CHAR;
488#else 488#else
489 goto error; 489 goto error;
490#endif 490#endif
491 else 491 else
492 type = TYPE_CHAR; 492 type = TYPE_CHAR;
493 break; 493 break;
494#if HAVE_WINT_T 494#if HAVE_WINT_T
495 case 'C': 495 case 'C':
496 type = TYPE_WIDE_CHAR; 496 type = TYPE_WIDE_CHAR;
497 c = 'c'; 497 c = 'c';
498 break; 498 break;
499#endif 499#endif
500 case 's': 500 case 's':
501 if (flags >= 8) 501 if (flags >= 8)
502#if HAVE_WCHAR_T 502#if HAVE_WCHAR_T
503 type = TYPE_WIDE_STRING; 503 type = TYPE_WIDE_STRING;
504#else 504#else
505 goto error; 505 goto error;
506#endif 506#endif
507 else 507 else
508 type = TYPE_STRING; 508 type = TYPE_STRING;
509 break; 509 break;
510#if HAVE_WCHAR_T 510#if HAVE_WCHAR_T
511 case 'S': 511 case 'S':
512 type = TYPE_WIDE_STRING; 512 type = TYPE_WIDE_STRING;
513 c = 's'; 513 c = 's';
514 break; 514 break;
515#endif 515#endif
516 case 'p': 516 case 'p':
517 type = TYPE_POINTER; 517 type = TYPE_POINTER;
518 break; 518 break;
519 case 'n': 519 case 'n':
520#if HAVE_LONG_LONG_INT 520#if HAVE_LONG_LONG_INT
521 /* If 'long long' exists and is larger than 'long': */ 521 /* If 'long long' exists and is larger than 'long': */
522 if (flags >= 16 || (flags & 4)) 522 if (flags >= 16 || (flags & 4))
523 type = TYPE_COUNT_LONGLONGINT_POINTER; 523 type = TYPE_COUNT_LONGLONGINT_POINTER;
524 else 524 else
525#endif 525#endif
526 /* If 'long long' exists and is the same as 'long', we parse 526 /* If 'long long' exists and is the same as 'long', we parse
527 "lln" into TYPE_COUNT_LONGINT_POINTER. */ 527 "lln" into TYPE_COUNT_LONGINT_POINTER. */
528 if (flags >= 8) 528 if (flags >= 8)
529 type = TYPE_COUNT_LONGINT_POINTER; 529 type = TYPE_COUNT_LONGINT_POINTER;
530 else if (flags & 2) 530 else if (flags & 2)
531 type = TYPE_COUNT_SCHAR_POINTER; 531 type = TYPE_COUNT_SCHAR_POINTER;
532 else if (flags & 1) 532 else if (flags & 1)
533 type = TYPE_COUNT_SHORT_POINTER; 533 type = TYPE_COUNT_SHORT_POINTER;
534 else 534 else
535 type = TYPE_COUNT_INT_POINTER; 535 type = TYPE_COUNT_INT_POINTER;
536 break; 536 break;
537#if ENABLE_UNISTDIO 537#if ENABLE_UNISTDIO
538 /* The unistdio extensions. */ 538 /* The unistdio extensions. */
539 case 'U': 539 case 'U':
540 if (flags >= 16) 540 if (flags >= 16)
541 type = TYPE_U32_STRING; 541 type = TYPE_U32_STRING;
542 else if (flags >= 8) 542 else if (flags >= 8)
543 type = TYPE_U16_STRING; 543 type = TYPE_U16_STRING;
544 else 544 else
545 type = TYPE_U8_STRING; 545 type = TYPE_U8_STRING;
546 break; 546 break;
547#endif 547#endif
548 case '%': 548 case '%':
549 type = TYPE_NONE; 549 type = TYPE_NONE;
550 break; 550 break;
551 default: 551 default:
552 /* Unknown conversion character. */ 552 /* Unknown conversion character. */
553 goto error; 553 goto error;
554 } 554 }
555 } 555 }
556 556
557 if (type != TYPE_NONE) 557 if (type != TYPE_NONE)
558 { 558 {
559 dp->arg_index = arg_index; 559 dp->arg_index = arg_index;
560 if (dp->arg_index == ARG_NONE) 560 if (dp->arg_index == ARG_NONE)
561 { 561 {
562 dp->arg_index = arg_posn++; 562 dp->arg_index = arg_posn++;
563 if (dp->arg_index == ARG_NONE) 563 if (dp->arg_index == ARG_NONE)
564 /* arg_posn wrapped around. */ 564 /* arg_posn wrapped around. */
565 goto error; 565 goto error;
566 } 566 }
567 REGISTER_ARG (dp->arg_index, type); 567 REGISTER_ARG (dp->arg_index, type);
568 } 568 }
569 dp->conversion = c; 569 dp->conversion = c;
570 dp->dir_end = cp; 570 dp->dir_end = cp;
571 } 571 }
572 572
573 d->count++; 573 d->count++;
574 if (d->count >= d_allocated) 574 if (d->count >= d_allocated)
575 { 575 {
576 size_t memory_size; 576 size_t memory_size;
577 DIRECTIVE *memory; 577 DIRECTIVE *memory;
578 578
579 d_allocated = xtimes (d_allocated, 2); 579 d_allocated = xtimes (d_allocated, 2);
580 memory_size = xtimes (d_allocated, sizeof (DIRECTIVE)); 580 memory_size = xtimes (d_allocated, sizeof (DIRECTIVE));
581 if (size_overflow_p (memory_size)) 581 if (size_overflow_p (memory_size))
582 /* Overflow, would lead to out of memory. */ 582 /* Overflow, would lead to out of memory. */
583 goto out_of_memory; 583 goto out_of_memory;
584 memory = (DIRECTIVE *) realloc (d->dir, memory_size); 584 memory = (DIRECTIVE *) realloc (d->dir, memory_size);
585 if (memory == NULL) 585 if (memory == NULL)
586 /* Out of memory. */ 586 /* Out of memory. */
587 goto out_of_memory; 587 goto out_of_memory;
588 d->dir = memory; 588 d->dir = memory;
589 } 589 }
590 } 590 }
591#if CHAR_T_ONLY_ASCII 591#if CHAR_T_ONLY_ASCII
592 else if (!c_isascii (c)) 592 else if (!c_isascii (c))
593 { 593 {
594 /* Non-ASCII character. Not supported. */ 594 /* Non-ASCII character. Not supported. */
595 goto error; 595 goto error;
596 } 596 }
597#endif 597#endif
598 } 598 }
599 d->dir[d->count].dir_start = cp; 599 d->dir[d->count].dir_start = cp;