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.c162
1 files changed, 123 insertions, 39 deletions
diff --git a/gl/printf-parse.c b/gl/printf-parse.c
index 9a86f773..28b9bd41 100644
--- a/gl/printf-parse.c
+++ b/gl/printf-parse.c
@@ -1,9 +1,9 @@
1/* Formatted output to strings. 1/* Formatted output to strings.
2 Copyright (C) 1999-2000, 2002-2003, 2006 Free Software Foundation, Inc. 2 Copyright (C) 1999-2000, 2002-2003, 2006-2008 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
6 the Free Software Foundation; either version 2, or (at your option) 6 the Free Software Foundation; either version 3, or (at your option)
7 any later version. 7 any later version.
8 8
9 This program is distributed in the hope that it will be useful, 9 This program is distributed in the hope that it will be useful,
@@ -15,42 +15,63 @@
15 with this program; if not, write to the Free Software Foundation, 15 with this program; if not, write to the Free Software Foundation,
16 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ 16 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
17 17
18#include <config.h> 18/* This file can be parametrized with the following macros:
19 CHAR_T The element type of the format string.
20 CHAR_T_ONLY_ASCII Set to 1 to enable verification that all characters
21 in the format string are ASCII.
22 DIRECTIVE Structure denoting a format directive.
23 Depends on CHAR_T.
24 DIRECTIVES Structure denoting the set of format directives of a
25 format string. Depends on CHAR_T.
26 PRINTF_PARSE Function that parses a format string.
27 Depends on CHAR_T.
28 STATIC Set to 'static' to declare the function static.
29 ENABLE_UNISTDIO Set to 1 to enable the unistdio extensions. */
30
31#ifndef PRINTF_PARSE
32# include <config.h>
33#endif
19 34
20/* Specification. */ 35/* Specification. */
21#if WIDE_CHAR_VERSION 36#ifndef PRINTF_PARSE
22# include "wprintf-parse.h"
23#else
24# include "printf-parse.h" 37# include "printf-parse.h"
25#endif 38#endif
26 39
40/* Default parameters. */
41#ifndef PRINTF_PARSE
42# define PRINTF_PARSE printf_parse
43# define CHAR_T char
44# define DIRECTIVE char_directive
45# define DIRECTIVES char_directives
46#endif
47
27/* Get size_t, NULL. */ 48/* Get size_t, NULL. */
28#include <stddef.h> 49#include <stddef.h>
29 50
30/* Get intmax_t. */ 51/* Get intmax_t. */
31#if HAVE_STDINT_H_WITH_UINTMAX 52#if defined IN_LIBINTL || defined IN_LIBASPRINTF
53# if HAVE_STDINT_H_WITH_UINTMAX
54# include <stdint.h>
55# endif
56# if HAVE_INTTYPES_H_WITH_UINTMAX
57# include <inttypes.h>
58# endif
59#else
32# include <stdint.h> 60# include <stdint.h>
33#endif 61#endif
34#if HAVE_INTTYPES_H_WITH_UINTMAX
35# include <inttypes.h>
36#endif
37 62
38/* malloc(), realloc(), free(). */ 63/* malloc(), realloc(), free(). */
39#include <stdlib.h> 64#include <stdlib.h>
40 65
66/* errno. */
67#include <errno.h>
68
41/* Checked size_t computations. */ 69/* Checked size_t computations. */
42#include "xsize.h" 70#include "xsize.h"
43 71
44#if WIDE_CHAR_VERSION 72#if CHAR_T_ONLY_ASCII
45# define PRINTF_PARSE wprintf_parse 73/* c_isascii(). */
46# define CHAR_T wchar_t 74# include "c-ctype.h"
47# define DIRECTIVE wchar_t_directive
48# define DIRECTIVES wchar_t_directives
49#else
50# define PRINTF_PARSE printf_parse
51# define CHAR_T char
52# define DIRECTIVE char_directive
53# define DIRECTIVES char_directives
54#endif 75#endif
55 76
56#ifdef STATIC 77#ifdef STATIC
@@ -71,7 +92,7 @@ PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a)
71 d->dir = (DIRECTIVE *) malloc (d_allocated * sizeof (DIRECTIVE)); 92 d->dir = (DIRECTIVE *) malloc (d_allocated * sizeof (DIRECTIVE));
72 if (d->dir == NULL) 93 if (d->dir == NULL)
73 /* Out of memory. */ 94 /* Out of memory. */
74 return -1; 95 goto out_of_memory_1;
75 96
76 a->count = 0; 97 a->count = 0;
77 a_allocated = 0; 98 a_allocated = 0;
@@ -91,13 +112,13 @@ PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a)
91 memory_size = xtimes (a_allocated, sizeof (argument)); \ 112 memory_size = xtimes (a_allocated, sizeof (argument)); \
92 if (size_overflow_p (memory_size)) \ 113 if (size_overflow_p (memory_size)) \
93 /* Overflow, would lead to out of memory. */ \ 114 /* Overflow, would lead to out of memory. */ \
94 goto error; \ 115 goto out_of_memory; \
95 memory = (argument *) (a->arg \ 116 memory = (argument *) (a->arg \
96 ? realloc (a->arg, memory_size) \ 117 ? realloc (a->arg, memory_size) \
97 : malloc (memory_size)); \ 118 : malloc (memory_size)); \
98 if (memory == NULL) \ 119 if (memory == NULL) \
99 /* Out of memory. */ \ 120 /* Out of memory. */ \
100 goto error; \ 121 goto out_of_memory; \
101 a->arg = memory; \ 122 a->arg = memory; \
102 } \ 123 } \
103 while (a->count <= n) \ 124 while (a->count <= n) \
@@ -115,7 +136,7 @@ PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a)
115 if (c == '%') 136 if (c == '%')
116 { 137 {
117 size_t arg_index = ARG_NONE; 138 size_t arg_index = ARG_NONE;
118 DIRECTIVE *dp = &d->dir[d->count];/* pointer to next directive */ 139 DIRECTIVE *dp = &d->dir[d->count]; /* pointer to next directive */
119 140
120 /* Initialize the next directive. */ 141 /* Initialize the next directive. */
121 dp->dir_start = cp - 1; 142 dp->dir_start = cp - 1;
@@ -326,7 +347,6 @@ PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a)
326 flags += 8; 347 flags += 8;
327 cp++; 348 cp++;
328 } 349 }
329#ifdef HAVE_INTMAX_T
330 else if (*cp == 'j') 350 else if (*cp == 'j')
331 { 351 {
332 if (sizeof (intmax_t) > sizeof (long)) 352 if (sizeof (intmax_t) > sizeof (long))
@@ -341,7 +361,6 @@ PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a)
341 } 361 }
342 cp++; 362 cp++;
343 } 363 }
344#endif
345 else if (*cp == 'z' || *cp == 'Z') 364 else if (*cp == 'z' || *cp == 'Z')
346 { 365 {
347 /* 'z' is standardized in ISO C 99, but glibc uses 'Z' 366 /* 'z' is standardized in ISO C 99, but glibc uses 'Z'
@@ -373,6 +392,44 @@ PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a)
373 } 392 }
374 cp++; 393 cp++;
375 } 394 }
395#if defined __APPLE__ && defined __MACH__
396 /* On MacOS X 10.3, PRIdMAX is defined as "qd".
397 We cannot change it to "lld" because PRIdMAX must also
398 be understood by the system's printf routines. */
399 else if (*cp == 'q')
400 {
401 if (64 / 8 > sizeof (long))
402 {
403 /* int64_t = long long */
404 flags += 16;
405 }
406 else
407 {
408 /* int64_t = long */
409 flags += 8;
410 }
411 cp++;
412 }
413#endif
414#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
415 /* On native Win32, PRIdMAX is defined as "I64d".
416 We cannot change it to "lld" because PRIdMAX must also
417 be understood by the system's printf routines. */
418 else if (*cp == 'I' && cp[1] == '6' && cp[2] == '4')
419 {
420 if (64 / 8 > sizeof (long))
421 {
422 /* __int64 = long long */
423 flags += 16;
424 }
425 else
426 {
427 /* __int64 = long */
428 flags += 8;
429 }
430 cp += 3;
431 }
432#endif
376 else 433 else
377 break; 434 break;
378 } 435 }
@@ -382,7 +439,7 @@ PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a)
382 switch (c) 439 switch (c)
383 { 440 {
384 case 'd': case 'i': 441 case 'd': case 'i':
385#ifdef HAVE_LONG_LONG_INT 442#if HAVE_LONG_LONG_INT
386 /* If 'long long' exists and is larger than 'long': */ 443 /* If 'long long' exists and is larger than 'long': */
387 if (flags >= 16 || (flags & 4)) 444 if (flags >= 16 || (flags & 4))
388 type = TYPE_LONGLONGINT; 445 type = TYPE_LONGLONGINT;
@@ -400,7 +457,7 @@ PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a)
400 type = TYPE_INT; 457 type = TYPE_INT;
401 break; 458 break;
402 case 'o': case 'u': case 'x': case 'X': 459 case 'o': case 'u': case 'x': case 'X':
403#ifdef HAVE_LONG_LONG_INT 460#if HAVE_LONG_LONG_INT
404 /* If 'long long' exists and is larger than 'long': */ 461 /* If 'long long' exists and is larger than 'long': */
405 if (flags >= 16 || (flags & 4)) 462 if (flags >= 16 || (flags & 4))
406 type = TYPE_ULONGLONGINT; 463 type = TYPE_ULONGLONGINT;
@@ -419,16 +476,14 @@ PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a)
419 break; 476 break;
420 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':
421 case 'a': case 'A': 478 case 'a': case 'A':
422#ifdef HAVE_LONG_DOUBLE
423 if (flags >= 16 || (flags & 4)) 479 if (flags >= 16 || (flags & 4))
424 type = TYPE_LONGDOUBLE; 480 type = TYPE_LONGDOUBLE;
425 else 481 else
426#endif 482 type = TYPE_DOUBLE;
427 type = TYPE_DOUBLE;
428 break; 483 break;
429 case 'c': 484 case 'c':
430 if (flags >= 8) 485 if (flags >= 8)
431#ifdef HAVE_WINT_T 486#if HAVE_WINT_T
432 type = TYPE_WIDE_CHAR; 487 type = TYPE_WIDE_CHAR;
433#else 488#else
434 goto error; 489 goto error;
@@ -436,7 +491,7 @@ PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a)
436 else 491 else
437 type = TYPE_CHAR; 492 type = TYPE_CHAR;
438 break; 493 break;
439#ifdef HAVE_WINT_T 494#if HAVE_WINT_T
440 case 'C': 495 case 'C':
441 type = TYPE_WIDE_CHAR; 496 type = TYPE_WIDE_CHAR;
442 c = 'c'; 497 c = 'c';
@@ -444,7 +499,7 @@ PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a)
444#endif 499#endif
445 case 's': 500 case 's':
446 if (flags >= 8) 501 if (flags >= 8)
447#ifdef HAVE_WCHAR_T 502#if HAVE_WCHAR_T
448 type = TYPE_WIDE_STRING; 503 type = TYPE_WIDE_STRING;
449#else 504#else
450 goto error; 505 goto error;
@@ -452,7 +507,7 @@ PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a)
452 else 507 else
453 type = TYPE_STRING; 508 type = TYPE_STRING;
454 break; 509 break;
455#ifdef HAVE_WCHAR_T 510#if HAVE_WCHAR_T
456 case 'S': 511 case 'S':
457 type = TYPE_WIDE_STRING; 512 type = TYPE_WIDE_STRING;
458 c = 's'; 513 c = 's';
@@ -462,7 +517,7 @@ PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a)
462 type = TYPE_POINTER; 517 type = TYPE_POINTER;
463 break; 518 break;
464 case 'n': 519 case 'n':
465#ifdef HAVE_LONG_LONG_INT 520#if HAVE_LONG_LONG_INT
466 /* If 'long long' exists and is larger than 'long': */ 521 /* If 'long long' exists and is larger than 'long': */
467 if (flags >= 16 || (flags & 4)) 522 if (flags >= 16 || (flags & 4))
468 type = TYPE_COUNT_LONGLONGINT_POINTER; 523 type = TYPE_COUNT_LONGLONGINT_POINTER;
@@ -479,6 +534,17 @@ PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a)
479 else 534 else
480 type = TYPE_COUNT_INT_POINTER; 535 type = TYPE_COUNT_INT_POINTER;
481 break; 536 break;
537#if ENABLE_UNISTDIO
538 /* The unistdio extensions. */
539 case 'U':
540 if (flags >= 16)
541 type = TYPE_U32_STRING;
542 else if (flags >= 8)
543 type = TYPE_U16_STRING;
544 else
545 type = TYPE_U8_STRING;
546 break;
547#endif
482 case '%': 548 case '%':
483 type = TYPE_NONE; 549 type = TYPE_NONE;
484 break; 550 break;
@@ -514,14 +580,21 @@ PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a)
514 memory_size = xtimes (d_allocated, sizeof (DIRECTIVE)); 580 memory_size = xtimes (d_allocated, sizeof (DIRECTIVE));
515 if (size_overflow_p (memory_size)) 581 if (size_overflow_p (memory_size))
516 /* Overflow, would lead to out of memory. */ 582 /* Overflow, would lead to out of memory. */
517 goto error; 583 goto out_of_memory;
518 memory = (DIRECTIVE *) realloc (d->dir, memory_size); 584 memory = (DIRECTIVE *) realloc (d->dir, memory_size);
519 if (memory == NULL) 585 if (memory == NULL)
520 /* Out of memory. */ 586 /* Out of memory. */
521 goto error; 587 goto out_of_memory;
522 d->dir = memory; 588 d->dir = memory;
523 } 589 }
524 } 590 }
591#if CHAR_T_ONLY_ASCII
592 else if (!c_isascii (c))
593 {
594 /* Non-ASCII character. Not supported. */
595 goto error;
596 }
597#endif
525 } 598 }
526 d->dir[d->count].dir_start = cp; 599 d->dir[d->count].dir_start = cp;
527 600
@@ -534,10 +607,21 @@ error:
534 free (a->arg); 607 free (a->arg);
535 if (d->dir) 608 if (d->dir)
536 free (d->dir); 609 free (d->dir);
610 errno = EINVAL;
611 return -1;
612
613out_of_memory:
614 if (a->arg)
615 free (a->arg);
616 if (d->dir)
617 free (d->dir);
618out_of_memory_1:
619 errno = ENOMEM;
537 return -1; 620 return -1;
538} 621}
539 622
623#undef PRINTF_PARSE
540#undef DIRECTIVES 624#undef DIRECTIVES
541#undef DIRECTIVE 625#undef DIRECTIVE
626#undef CHAR_T_ONLY_ASCII
542#undef CHAR_T 627#undef CHAR_T
543#undef PRINTF_PARSE