printf-parse.c | printf-parse.c | |||
---|---|---|---|---|
/* Formatted output to strings. | /* Formatted output to strings. | |||
Copyright (C) 1999-2000, 2002-2003, 2006-2010 Free Software Foundation, Inc. | Copyright (C) 1999-2000, 2002-2003, 2006-2014 Free Software Foundation, Inc. | |||
This program is free software; you can redistribute it and/or modify | This program is free software; you can redistribute it and/or modify | |||
it under the terms of the GNU Lesser General Public License as published by | it under the terms of the GNU Lesser General Public License as published by | |||
the Free Software Foundation; either version 2, or (at your option) | the Free Software Foundation; either version 2, or (at your option) | |||
any later version. | any later version. | |||
This program is distributed in the hope that it will be useful, | This program is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU Lesser General Public License for more details. | GNU Lesser General Public License for more details. | |||
You should have received a copy of the GNU Lesser General Public License along | You should have received a copy of the GNU Lesser General Public License along | |||
with this program; if not, write to the Free Software Foundation, | with this program; if not, see <http://www.gnu.org/licenses/>. */ | |||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ | ||||
/* This file can be parametrized with the following macros: | /* This file can be parametrized with the following macros: | |||
CHAR_T The element type of the format string. | CHAR_T The element type of the format string. | |||
CHAR_T_ONLY_ASCII Set to 1 to enable verification that all characters | CHAR_T_ONLY_ASCII Set to 1 to enable verification that all characters | |||
in the format string are ASCII. | in the format string are ASCII. | |||
DIRECTIVE Structure denoting a format directive. | DIRECTIVE Structure denoting a format directive. | |||
Depends on CHAR_T. | Depends on CHAR_T. | |||
DIRECTIVES Structure denoting the set of format directives of a | DIRECTIVES Structure denoting the set of format directives of a | |||
format string. Depends on CHAR_T. | format string. Depends on CHAR_T. | |||
PRINTF_PARSE Function that parses a format string. | PRINTF_PARSE Function that parses a format string. | |||
skipping to change at line 66 | skipping to change at line 65 | |||
# if HAVE_INTTYPES_H_WITH_UINTMAX | # if HAVE_INTTYPES_H_WITH_UINTMAX | |||
# include <inttypes.h> | # include <inttypes.h> | |||
# endif | # endif | |||
#else | #else | |||
# include <stdint.h> | # include <stdint.h> | |||
#endif | #endif | |||
/* malloc(), realloc(), free(). */ | /* malloc(), realloc(), free(). */ | |||
#include <stdlib.h> | #include <stdlib.h> | |||
/* memcpy(). */ | ||||
#include <string.h> | ||||
/* errno. */ | /* errno. */ | |||
#include <errno.h> | #include <errno.h> | |||
/* Checked size_t computations. */ | /* Checked size_t computations. */ | |||
#include "xsize.h" | #include "xsize.h" | |||
#if CHAR_T_ONLY_ASCII | #if CHAR_T_ONLY_ASCII | |||
/* c_isascii(). */ | /* c_isascii(). */ | |||
# include "c-ctype.h" | # include "c-ctype.h" | |||
#endif | #endif | |||
#ifdef STATIC | #ifdef STATIC | |||
STATIC | STATIC | |||
#endif | #endif | |||
int | int | |||
PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a) | PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a) | |||
{ | { | |||
const CHAR_T *cp = format; /* pointer into format */ | const CHAR_T *cp = format; /* pointer into format */ | |||
size_t arg_posn = 0; /* number of regular arguments consumed */ | size_t arg_posn = 0; /* number of regular arguments consumed */ | |||
size_t d_allocated; /* allocated elements of d->dir */ | size_t d_allocated; /* allocated elements of d->dir */ | |||
size_t a_allocated; /* allocated elements of a->arg */ | size_t a_allocated; /* allocated elements of a->arg */ | |||
size_t max_width_length = 0; | size_t max_width_length = 0; | |||
size_t max_precision_length = 0; | size_t max_precision_length = 0; | |||
d->count = 0; | d->count = 0; | |||
d_allocated = 1; | d_allocated = N_DIRECT_ALLOC_DIRECTIVES; | |||
d->dir = (DIRECTIVE *) malloc (d_allocated * sizeof (DIRECTIVE)); | d->dir = d->direct_alloc_dir; | |||
if (d->dir == NULL) | ||||
/* Out of memory. */ | ||||
goto out_of_memory_1; | ||||
a->count = 0; | a->count = 0; | |||
a_allocated = 0; | a_allocated = N_DIRECT_ALLOC_ARGUMENTS; | |||
a->arg = NULL; | a->arg = a->direct_alloc_arg; | |||
#define REGISTER_ARG(_index_,_type_) \ | #define REGISTER_ARG(_index_,_type_) \ | |||
{ \ | { \ | |||
size_t n = (_index_); \ | size_t n = (_index_); \ | |||
if (n >= a_allocated) \ | if (n >= a_allocated) \ | |||
{ \ | { \ | |||
size_t memory_size; \ | size_t memory_size; \ | |||
argument *memory; \ | argument *memory; \ | |||
\ | \ | |||
a_allocated = xtimes (a_allocated, 2); \ | a_allocated = xtimes (a_allocated, 2); \ | |||
if (a_allocated <= n) \ | if (a_allocated <= n) \ | |||
a_allocated = xsum (n, 1); \ | a_allocated = xsum (n, 1); \ | |||
memory_size = xtimes (a_allocated, sizeof (argument)); \ | memory_size = xtimes (a_allocated, sizeof (argument)); \ | |||
if (size_overflow_p (memory_size)) \ | if (size_overflow_p (memory_size)) \ | |||
/* Overflow, would lead to out of memory. */ \ | /* Overflow, would lead to out of memory. */ \ | |||
goto out_of_memory; \ | goto out_of_memory; \ | |||
memory = (argument *) (a->arg \ | memory = (argument *) (a->arg != a->direct_alloc_arg \ | |||
? realloc (a->arg, memory_size) \ | ? realloc (a->arg, memory_size) \ | |||
: malloc (memory_size)); \ | : malloc (memory_size)); \ | |||
if (memory == NULL) \ | if (memory == NULL) \ | |||
/* Out of memory. */ \ | /* Out of memory. */ \ | |||
goto out_of_memory; \ | goto out_of_memory; \ | |||
if (a->arg == a->direct_alloc_arg) \ | ||||
memcpy (memory, a->arg, a->count * sizeof (argument)); \ | ||||
a->arg = memory; \ | a->arg = memory; \ | |||
} \ | } \ | |||
while (a->count <= n) \ | while (a->count <= n) \ | |||
a->arg[a->count++].type = TYPE_NONE; \ | a->arg[a->count++].type = TYPE_NONE; \ | |||
if (a->arg[n].type == TYPE_NONE) \ | if (a->arg[n].type == TYPE_NONE) \ | |||
a->arg[n].type = (_type_); \ | a->arg[n].type = (_type_); \ | |||
else if (a->arg[n].type != (_type_)) \ | else if (a->arg[n].type != (_type_)) \ | |||
/* Ambiguous type for positional argument. */ \ | /* Ambiguous type for positional argument. */ \ | |||
goto error; \ | goto error; \ | |||
} | } | |||
skipping to change at line 209 | skipping to change at line 210 | |||
else if (*cp == '#') | else if (*cp == '#') | |||
{ | { | |||
dp->flags |= FLAG_ALT; | dp->flags |= FLAG_ALT; | |||
cp++; | cp++; | |||
} | } | |||
else if (*cp == '0') | else if (*cp == '0') | |||
{ | { | |||
dp->flags |= FLAG_ZERO; | dp->flags |= FLAG_ZERO; | |||
cp++; | cp++; | |||
} | } | |||
#if __GLIBC__ >= 2 && !defined __UCLIBC__ | ||||
else if (*cp == 'I') | ||||
{ | ||||
dp->flags |= FLAG_LOCALIZED; | ||||
cp++; | ||||
} | ||||
#endif | ||||
else | else | |||
break; | break; | |||
} | } | |||
/* Parse the field width. */ | /* Parse the field width. */ | |||
if (*cp == '*') | if (*cp == '*') | |||
{ | { | |||
dp->width_start = cp; | dp->width_start = cp; | |||
cp++; | cp++; | |||
dp->width_end = cp; | dp->width_end = cp; | |||
skipping to change at line 396 | skipping to change at line 404 | |||
flags += 16; | flags += 16; | |||
} | } | |||
else if (sizeof (ptrdiff_t) > sizeof (int)) | else if (sizeof (ptrdiff_t) > sizeof (int)) | |||
{ | { | |||
/* ptrdiff_t = long */ | /* ptrdiff_t = long */ | |||
flags += 8; | flags += 8; | |||
} | } | |||
cp++; | cp++; | |||
} | } | |||
#if defined __APPLE__ && defined __MACH__ | #if defined __APPLE__ && defined __MACH__ | |||
/* On MacOS X 10.3, PRIdMAX is defined as "qd". | /* On Mac OS X 10.3, PRIdMAX is defined as "qd". | |||
We cannot change it to "lld" because PRIdMAX must also | We cannot change it to "lld" because PRIdMAX must also | |||
be understood by the system's printf routines. */ | be understood by the system's printf routines. */ | |||
else if (*cp == 'q') | else if (*cp == 'q') | |||
{ | { | |||
if (64 / 8 > sizeof (long)) | if (64 / 8 > sizeof (long)) | |||
{ | { | |||
/* int64_t = long long */ | /* int64_t = long long */ | |||
flags += 16; | flags += 16; | |||
} | } | |||
else | else | |||
{ | { | |||
/* int64_t = long */ | /* int64_t = long */ | |||
flags += 8; | flags += 8; | |||
} | } | |||
cp++; | cp++; | |||
} | } | |||
#endif | #endif | |||
#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ | #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ | |||
/* On native Win32, PRIdMAX is defined as "I64d". | /* On native Windows, PRIdMAX is defined as "I64d". | |||
We cannot change it to "lld" because PRIdMAX must also | We cannot change it to "lld" because PRIdMAX must also | |||
be understood by the system's printf routines. */ | be understood by the system's printf routines. */ | |||
else if (*cp == 'I' && cp[1] == '6' && cp[2] == '4') | else if (*cp == 'I' && cp[1] == '6' && cp[2] == '4') | |||
{ | { | |||
if (64 / 8 > sizeof (long)) | if (64 / 8 > sizeof (long)) | |||
{ | { | |||
/* __int64 = long long */ | /* __int64 = long long */ | |||
flags += 16; | flags += 16; | |||
} | } | |||
else | else | |||
skipping to change at line 584 | skipping to change at line 592 | |||
if (d->count >= d_allocated) | if (d->count >= d_allocated) | |||
{ | { | |||
size_t memory_size; | size_t memory_size; | |||
DIRECTIVE *memory; | DIRECTIVE *memory; | |||
d_allocated = xtimes (d_allocated, 2); | d_allocated = xtimes (d_allocated, 2); | |||
memory_size = xtimes (d_allocated, sizeof (DIRECTIVE)); | memory_size = xtimes (d_allocated, sizeof (DIRECTIVE)); | |||
if (size_overflow_p (memory_size)) | if (size_overflow_p (memory_size)) | |||
/* Overflow, would lead to out of memory. */ | /* Overflow, would lead to out of memory. */ | |||
goto out_of_memory; | goto out_of_memory; | |||
memory = (DIRECTIVE *) realloc (d->dir, memory_size); | memory = (DIRECTIVE *) (d->dir != d->direct_alloc_dir | |||
? realloc (d->dir, memory_size) | ||||
: malloc (memory_size)); | ||||
if (memory == NULL) | if (memory == NULL) | |||
/* Out of memory. */ | /* Out of memory. */ | |||
goto out_of_memory; | goto out_of_memory; | |||
if (d->dir == d->direct_alloc_dir) | ||||
memcpy (memory, d->dir, d->count * sizeof (DIRECTIVE)); | ||||
d->dir = memory; | d->dir = memory; | |||
} | } | |||
} | } | |||
#if CHAR_T_ONLY_ASCII | #if CHAR_T_ONLY_ASCII | |||
else if (!c_isascii (c)) | else if (!c_isascii (c)) | |||
{ | { | |||
/* Non-ASCII character. Not supported. */ | /* Non-ASCII character. Not supported. */ | |||
goto error; | goto error; | |||
} | } | |||
#endif | #endif | |||
} | } | |||
d->dir[d->count].dir_start = cp; | d->dir[d->count].dir_start = cp; | |||
d->max_width_length = max_width_length; | d->max_width_length = max_width_length; | |||
d->max_precision_length = max_precision_length; | d->max_precision_length = max_precision_length; | |||
return 0; | return 0; | |||
error: | error: | |||
if (a->arg) | if (a->arg != a->direct_alloc_arg) | |||
free (a->arg); | free (a->arg); | |||
if (d->dir) | if (d->dir != d->direct_alloc_dir) | |||
free (d->dir); | free (d->dir); | |||
errno = EINVAL; | errno = EINVAL; | |||
return -1; | return -1; | |||
out_of_memory: | out_of_memory: | |||
if (a->arg) | if (a->arg != a->direct_alloc_arg) | |||
free (a->arg); | free (a->arg); | |||
if (d->dir) | if (d->dir != d->direct_alloc_dir) | |||
free (d->dir); | free (d->dir); | |||
out_of_memory_1: | ||||
errno = ENOMEM; | errno = ENOMEM; | |||
return -1; | return -1; | |||
} | } | |||
#undef PRINTF_PARSE | #undef PRINTF_PARSE | |||
#undef DIRECTIVES | #undef DIRECTIVES | |||
#undef DIRECTIVE | #undef DIRECTIVE | |||
#undef CHAR_T_ONLY_ASCII | #undef CHAR_T_ONLY_ASCII | |||
#undef CHAR_T | #undef CHAR_T | |||
End of changes. 19 change blocks. | ||||
22 lines changed or deleted | 33 lines changed or added | |||
This html diff was produced by rfcdiff 1.41. The latest version is available from http://tools.ietf.org/tools/rfcdiff/ |