1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-08-08 17:42:12 +03:00
2003-06-11  Ulrich Drepper  <drepper@redhat.com>

	* time/tzfile.c: Add a couple of __builtin_expect.

	Remove warnings gcc 3.3 shows.
	* argp/argp-help.c (hol_entry_short_iterate): Don't inline.
	* elf/dl-load.c (fillin_rpath): Likewise.
	(add_path): Likewise.
	* elf/dl-version.c (find_needed): Always inline.
	* elf/do-lookup.c (FCT): Don't inline.
	* iconv/Makefile: Extend vpath to intl subdir.
	(iconvconfig-modules): Add hash-string.
	* iconv/gconv_charset.h (strip): Don't inline.
	(upstr): Always inline.
	Move __gconv_compare_alias prototype to...
	* iconv/gconv_int.h: ...here.
	* iconv/gconv_db.c: Don't include gconv_charset.h.
	* iconv/gconv_conf.c (add_alias): Don't inline.
	(insert_module): Likewise.
	* iconv/gconv_simple.c (internal_ucs4_loop): Always inline.
	(internal_ucs4_loop_unaligned): Likewise.
	(internal_ucs4_loop_single): Likewise.
	(ucs4_internal_loop): Likewise.
	(ucs4_internal_loop_unaligned): Likewise.
	(ucs4_internal_loop_single): Likewise.
	(internal_ucs4le_loop): Always inline.
	(internal_ucs4le_loop_unaligned): Likewise.
	(internal_ucs4le_loop_single): Likewise.
	(ucs4le_internal_loop): Likewise.
	(ucs4le_internal_loop_unaligned): Likewise.
	(ucs4le_internal_loop_single): Likewise.
	* iconv/loop.c: Always inline the defined functions.
	* iconvdata/cns11642.h: Likewise.
	* iconvdata/cns11642l1.h: Likewise.
	* iconvdata/euc-kr.c: Likewise.
	* iconvdata/gb2312.h: Likewise.
	* iconvdata/jis0201.h: Likewise.
	* iconvdata/jis0208.h: Likewise.
	* iconvdata/jis0212.h: Likewise.
	* iconvdata/jisx0213.h: Likewise.
	* iconvdata/ksc5601.h: Likewise.
	* iconvdata/utf-7.c (base64): Don't inline.
	* include/libc-symbols.h (symbol_set_first_element): Add cast
	(symbol_set_end_p): Likewise.
	* include/set-hooks (RUN_HOOK): Likewise.
	* inet/Makefile (aux): Add ifreq.
	* intl/Makefile (aux): Add some entries from routines.  Add
	hash-string.
	* intl/hash-string.c: New file.
	* intl/hash-string.h: Remove hash_string definition.  Declare
	__hash_string.
	* iconv/gconv_cache.c (find_module_idx): Adjust hash_string caller.
	* iconv/iconvconfig.c (new_name): Likewise.
	* intl/dcigettext.c (_nl_find_msg): Likewise.
	* intl/loadmsgcat.c (_nl_load_domain): Likewise.
	* io/ftw.c (open_dir_stream): Always inline.
	(process_entry): Don't inline.
	* locale/findlocale.c: Include gconv_int.h.
	* locale/setlocale.c (new_composite_name): Don't inline.
	* locale/weight.h (findidx): Always inline.
	* locale/weightwc.h (findidx): Likewise.
	* locale/programs/linereader.c (lr_ignore_rest): Define here.
	* locale/programs/linereader.h (lr_ignore_rest): Don't define here,
	just declare it.
	(lr_getc): Always inline.
	(lr_ungetc): Likewise.
	* nss/nss_files/files-parse.c (parse_list): Likewise.
	* stdio-common/Makefile (aux): Add printf-parsemb and
	printf-parsewc.
	* stdio-common/_itoa.h (_itoa_word): Always inline.
	(_fitoa_word, _fitoa): Don't define here, only declare.
	* stdio-common/_itoa.c (_iftoa_word): Add here.
	(_fitoa): Likewise.
	* stdio-common/_itowa.h (_itowa_word): Always inline.
	* stdio-common/printf-parse.h (read_int): Don't inline.
	(find_spec): Don't define.
	Declare __find_specmb and __find_specwc.
	(parse_one_spec): Don't define.
	Declare __parse_one_specmb and __parse_one_specwc.
	* stdio-common/printf-parsemb.c: New file.
	* stdio-common/printf-parsewc.c: New file.
	* stdio-common/vfprintf.c: Update calls to find_spec and
	parse_one_spec for new names.
	* stdio-common/printf-prs.c: Likewise.  Define DONT_NEED_READ_INT.
	* stdlib/Makefile (aux): Add grouping and groupingwc.
	* stdlib/grouping.c: New file.
	* stdlib/groupingwc.c: New file.
	* stdlib/grouping.h (correctly_grouped_prefix): Don't define here.
	Just prototype.
	* stdlib/rpmatch.c (try): Don't inline.
	* stdlib/strtod.c (round_and_return): Don't line.
	(str_to_mpn): Likewise.
	(__mpn_lshift_1): Always inline.  Optimize only for constant count.
	Adjust for name change of correctly_grouped_prefix.
	* sysdeps/generic/strtol.c: Adjust for name change of
	correctly_grouped_prefix.
	* string/strxfrm.c (utf8_encode): Don't inline.
	* sysdeps/generic/dl-cache.c: Define _dl_cache_libcmp.
	* sysdeps/generic/dl-cache.h: Just declare _dl_cache_libcmp.
	* sysdeps/generic/ifreq.c: New file.
	* sysdeps/unix/sysv/linux/ifreq.c: New file.
	* sysdeps/generic/ifreq.h (__ifreq): Only declare here.
	* sysdeps/unix/sysv/linux/ifreq.h: Likewise.
	* sysdeps/generic/ldsodefs.h (_dl_name_match_p): Always inline.
	* sysdeps/generic/unwind-dw2-fde.c (start_fde_sort): Don't inline.
	(fde_split): Likewise.
	(fde_merge): Likewise.
	(end_fde_sort): Likewise.
	(init_object): Likewise.
	(binary_search_unencoded_fdes): Likewise.
	(binary_search_single_encoding_fdes): Likewise.
	(binary_search_mixed_encoding_fdes): Likewise.
	* sysdeps/generic/wordexp.c (w_addchar): Don't inline.
	* sysdeps/i386/dl-machine.c (elf_machine_runtime_setup): Always inline.
	* sysdeps/posix/sprofil.c (profil_count): Don't inline.
	* sysdeps/unix/sysv/linux/Makefile [subdir=io] (sysdep_routines):
	Add xstatconv.
	* sysdeps/unix/sysv/linux/xstatconv.h: New file.
	* sysdeps/unix/sysv/linux/xstatconv.c: Don't inline the function.
	Export them.  Prepend __ to name.
	* sysdeps/unix/sysv/linux/Dist: Add xstatconv.h.
	* sysdeps/unix/sysv/linux/fxstat.c: Adjust for name change of
	conversion functions.
	* sysdeps/unix/sysv/linux/fxstat64.c: Likewise.
	* sysdeps/unix/sysv/linux/lxstat.c: Likewise.
	* sysdeps/unix/sysv/linux/lxstat64.c: Likewise.
	* sysdeps/unix/sysv/linux/xstat.c: Likewise.
	* sysdeps/unix/sysv/linux/xstat64.c: Likewise.
	* sysdeps/unix/sysv/linux/i386/fxstat.c: Likewise.
	* sysdeps/unix/sysv/linux/i386/lxstat.c: Likewise.
	* sysdeps/unix/sysv/linux/i386/xstat.c: Likewise.
	* sysdeps/unix/sysv/linux/pathconf.c (__statfs_link_max,
	__statfs_filesize_max, __statfs_symlinks): Define here.  __ prepended
	to name.  Change callers.
	* sysdeps/unix/sysv/linux/pathconf.h (__statfs_link_max,
	__statfs_filesize_max, __statfs_symlinks): Don't define here, just
	declare.
	* sysdeps/unix/sysv/linux/fpathconf.c: Change all callers.
	* time/tzfile.c (decode): Always inline.
	* wcsmbs/wcsnrtombs.c: Change type of inbuf to unsigned char*.
	Remove cast in tomb function call.
	* wcsmbs/wcsrtombs.c Likewise.
	* wcsmbs/wcstob.c: Introduce new temp variable to take pointer in
	tomb function call.
This commit is contained in:
Ulrich Drepper
2003-06-11 23:22:36 +00:00
parent dd9423a67a
commit 9c7ff11a5c
53 changed files with 1367 additions and 963 deletions

View File

@@ -40,7 +40,7 @@ install-others = $(inst_includedir)/bits/stdio_lim.h
include ../Makeconfig
aux := errlist siglist
aux := errlist siglist printf-parsemb printf-parsewc
distribute := _itoa.h _itowa.h _i18n_number.h \
printf-parse.h stdio_lim.h.in tst-unbputc.sh tst-printf.sh

View File

@@ -424,3 +424,23 @@ _itoa (value, buflim, base, upper_case)
return buflim;
}
char *
_fitoa_word (unsigned long value, char *buf, unsigned int base, int upper_case)
{
char tmpbuf[sizeof (value) * 4]; /* Worst case length: base 2. */
char *cp = _itoa_word (value, tmpbuf + sizeof (value) * 4, base, upper_case);
while (cp < tmpbuf + sizeof (value) * 4)
*buf++ = *cp++;
return buf;
}
char *
_fitoa (unsigned long long value, char *buf, unsigned int base, int upper_case)
{
char tmpbuf[sizeof (value) * 4]; /* Worst case length: base 2. */
char *cp = _itoa (value, tmpbuf + sizeof (value) * 4, base, upper_case);
while (cp < tmpbuf + sizeof (value) * 4)
*buf++ = *cp++;
return buf;
}

View File

@@ -1,5 +1,5 @@
/* Internal function for converting integers to ASCII.
Copyright (C) 1994, 95, 96, 97, 98, 99, 2002 Free Software Foundation, Inc.
Copyright (C) 1994,95,96,97,98,99,2002,2003 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -34,7 +34,7 @@ extern const char _itoa_upper_digits_internal[] attribute_hidden;
extern const char _itoa_lower_digits[];
extern const char _itoa_lower_digits_internal[] attribute_hidden;
static inline char * __attribute__ ((unused))
static inline char * __attribute__ ((unused, always_inline))
_itoa_word (unsigned long value, char *buflim,
unsigned int base, int upper_case)
{
@@ -69,24 +69,11 @@ _itoa_word (unsigned long value, char *buflim,
}
#undef SPECIAL
static inline char * __attribute__ ((unused))
_fitoa_word (unsigned long value, char *buf, unsigned int base, int upper_case)
{
char tmpbuf[sizeof (value) * 4]; /* Worst case length: base 2. */
char *cp = _itoa_word (value, tmpbuf + sizeof (value) * 4, base, upper_case);
while (cp < tmpbuf + sizeof (value) * 4)
*buf++ = *cp++;
return buf;
}
static inline char * __attribute__ ((unused))
_fitoa (unsigned long long value, char *buf, unsigned int base, int upper_case)
{
char tmpbuf[sizeof (value) * 4]; /* Worst case length: base 2. */
char *cp = _itoa (value, tmpbuf + sizeof (value) * 4, base, upper_case);
while (cp < tmpbuf + sizeof (value) * 4)
*buf++ = *cp++;
return buf;
}
/* Similar to the _itoa functions, but output starts at buf and pointer
after the last written character is returned. */
extern char *_fitoa_word (unsigned long value, char *buf, unsigned int base,
int upper_case) attribute_hidden;
extern char *_fitoa (unsigned long long value, char *buf, unsigned int base,
int upper_case) attribute_hidden;
#endif /* itoa.h */

View File

@@ -1,5 +1,5 @@
/* Internal function for converting integers to ASCII.
Copyright (C) 1994, 95, 96, 97, 98, 99, 2002 Free Software Foundation, Inc.
Copyright (C) 1994,95,96,97,98,99,2002,2003 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -31,7 +31,7 @@ extern wchar_t *_itowa (unsigned long long int value, wchar_t *buflim,
unsigned int base, int upper_case);
static inline wchar_t *
__attribute__ ((unused))
__attribute__ ((unused, always_inline))
_itowa_word (unsigned long value, wchar_t *buflim,
unsigned int base, int upper_case)
{

View File

@@ -1,5 +1,5 @@
/* Internal header for parsing printf format strings.
Copyright (C) 1995-1999, 2000, 2002 Free Software Foundation, Inc.
Copyright (C) 1995-1999, 2000, 2002, 2003 Free Software Foundation, Inc.
This file is part of th GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -17,15 +17,9 @@
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <ctype.h>
#include <limits.h>
#include <printf.h>
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#define NDEBUG 1
#include <assert.h>
struct printf_spec
@@ -66,9 +60,10 @@ union printf_arg
};
#ifndef DONT_NEED_READ_INT
/* Read a simple integer from a string and update the string pointer.
It is assumed that the first character is a digit. */
static inline unsigned int
static unsigned int
read_int (const UCHAR_T * *pstr)
{
unsigned int retval = **pstr - L_('0');
@@ -81,35 +76,7 @@ read_int (const UCHAR_T * *pstr)
return retval;
}
/* Find the next spec in FORMAT, or the end of the string. Returns
a pointer into FORMAT, to a '%' or a '\0'. */
static inline const UCHAR_T *
#ifdef COMPILE_WPRINTF
find_spec (const UCHAR_T *format)
#else
find_spec (const UCHAR_T *format, mbstate_t *ps)
#endif
{
#ifdef COMPILE_WPRINTF
return (const UCHAR_T *) __wcschrnul ((const CHAR_T *) format, L'%');
#else
while (*format != L_('\0') && *format != L_('%'))
{
int len;
/* Remove any hints of a wrong encoding. */
ps->__count = 0;
if (! isascii (*format) && (len = __mbrlen (format, MB_CUR_MAX, ps)) > 0)
format += len;
else
++format;
}
return format;
#endif
}
/* These are defined in reg-printf.c. */
@@ -117,334 +84,25 @@ extern printf_arginfo_function **__printf_arginfo_table attribute_hidden;
extern printf_function **__printf_function_table attribute_hidden;
/* Find the next spec in FORMAT, or the end of the string. Returns
a pointer into FORMAT, to a '%' or a '\0'. */
extern const unsigned char *__find_specmb (const UCHAR_T *format,
mbstate_t *ps) attribute_hidden;
extern const unsigned int *__find_specwc (const UCHAR_T *format)
attribute_hidden;
/* FORMAT must point to a '%' at the beginning of a spec. Fills in *SPEC
with the parsed details. POSN is the number of arguments already
consumed. At most MAXTYPES - POSN types are filled in TYPES. Return
the number of args consumed by this spec; *MAX_REF_ARG is updated so it
remains the highest argument index used. */
static inline size_t
#ifdef COMPILE_WPRINTF
parse_one_spec (const UCHAR_T *format, size_t posn, struct printf_spec *spec,
size_t *max_ref_arg)
#else
parse_one_spec (const UCHAR_T *format, size_t posn, struct printf_spec *spec,
size_t *max_ref_arg, mbstate_t *ps)
#endif
{
unsigned int n;
size_t nargs = 0;
extern size_t __parse_one_specmb (const unsigned char *format, size_t posn,
struct printf_spec *spec,
size_t *max_ref_arg, mbstate_t *ps)
attribute_hidden;
/* Skip the '%'. */
++format;
/* Clear information structure. */
spec->data_arg = -1;
spec->info.alt = 0;
spec->info.space = 0;
spec->info.left = 0;
spec->info.showsign = 0;
spec->info.group = 0;
spec->info.i18n = 0;
spec->info.pad = ' ';
spec->info.wide = sizeof (UCHAR_T) > 1;
/* Test for positional argument. */
if (ISDIGIT (*format))
{
const UCHAR_T *begin = format;
n = read_int (&format);
if (n > 0 && *format == L_('$'))
/* Is positional parameter. */
{
++format; /* Skip the '$'. */
spec->data_arg = n - 1;
*max_ref_arg = MAX (*max_ref_arg, n);
}
else
/* Oops; that was actually the width and/or 0 padding flag.
Step back and read it again. */
format = begin;
}
/* Check for spec modifiers. */
do
{
switch (*format)
{
case L_(' '):
/* Output a space in place of a sign, when there is no sign. */
spec->info.space = 1;
continue;
case L_('+'):
/* Always output + or - for numbers. */
spec->info.showsign = 1;
continue;
case L_('-'):
/* Left-justify things. */
spec->info.left = 1;
continue;
case L_('#'):
/* Use the "alternate form":
Hex has 0x or 0X, FP always has a decimal point. */
spec->info.alt = 1;
continue;
case L_('0'):
/* Pad with 0s. */
spec->info.pad = '0';
continue;
case L_('\''):
/* Show grouping in numbers if the locale information
indicates any. */
spec->info.group = 1;
continue;
case L_('I'):
/* Use the internationalized form of the output. Currently
means to use the `outdigits' of the current locale. */
spec->info.i18n = 1;
continue;
default:
break;
}
break;
}
while (*++format);
if (spec->info.left)
spec->info.pad = ' ';
/* Get the field width. */
spec->width_arg = -1;
spec->info.width = 0;
if (*format == L_('*'))
{
/* The field width is given in an argument.
A negative field width indicates left justification. */
const UCHAR_T *begin = ++format;
if (ISDIGIT (*format))
{
/* The width argument might be found in a positional parameter. */
n = read_int (&format);
if (n > 0 && *format == L_('$'))
{
spec->width_arg = n - 1;
*max_ref_arg = MAX (*max_ref_arg, n);
++format; /* Skip '$'. */
}
}
if (spec->width_arg < 0)
{
/* Not in a positional parameter. Consume one argument. */
spec->width_arg = posn++;
++nargs;
format = begin; /* Step back and reread. */
}
}
else if (ISDIGIT (*format))
/* Constant width specification. */
spec->info.width = read_int (&format);
/* Get the precision. */
spec->prec_arg = -1;
/* -1 means none given; 0 means explicit 0. */
spec->info.prec = -1;
if (*format == L_('.'))
{
++format;
if (*format == L_('*'))
{
/* The precision is given in an argument. */
const UCHAR_T *begin = ++format;
if (ISDIGIT (*format))
{
n = read_int (&format);
if (n > 0 && *format == L_('$'))
{
spec->prec_arg = n - 1;
*max_ref_arg = MAX (*max_ref_arg, n);
++format;
}
}
if (spec->prec_arg < 0)
{
/* Not in a positional parameter. */
spec->prec_arg = posn++;
++nargs;
format = begin;
}
}
else if (ISDIGIT (*format))
spec->info.prec = read_int (&format);
else
/* "%.?" is treated like "%.0?". */
spec->info.prec = 0;
}
/* Check for type modifiers. */
spec->info.is_long_double = 0;
spec->info.is_short = 0;
spec->info.is_long = 0;
spec->info.is_char = 0;
switch (*format++)
{
case L_('h'):
/* ints are short ints or chars. */
if (*format != L_('h'))
spec->info.is_short = 1;
else
{
++format;
spec->info.is_char = 1;
}
break;
case L_('l'):
/* ints are long ints. */
spec->info.is_long = 1;
if (*format != L_('l'))
break;
++format;
/* FALLTHROUGH */
case L_('L'):
/* doubles are long doubles, and ints are long long ints. */
case L_('q'):
/* 4.4 uses this for long long. */
spec->info.is_long_double = 1;
break;
case L_('z'):
case L_('Z'):
/* ints are size_ts. */
assert (sizeof (size_t) <= sizeof (unsigned long long int));
#if LONG_MAX != LONG_LONG_MAX
spec->info.is_long_double = sizeof (size_t) > sizeof (unsigned long int);
#endif
spec->info.is_long = sizeof (size_t) > sizeof (unsigned int);
break;
case L_('t'):
assert (sizeof (ptrdiff_t) <= sizeof (long long int));
#if LONG_MAX != LONG_LONG_MAX
spec->info.is_long_double = (sizeof (ptrdiff_t) > sizeof (long int));
#endif
spec->info.is_long = sizeof (ptrdiff_t) > sizeof (int);
break;
case L_('j'):
assert (sizeof (uintmax_t) <= sizeof (unsigned long long int));
#if LONG_MAX != LONG_LONG_MAX
spec->info.is_long_double = (sizeof (uintmax_t)
> sizeof (unsigned long int));
#endif
spec->info.is_long = sizeof (uintmax_t) > sizeof (unsigned int);
break;
default:
/* Not a recognized modifier. Backup. */
--format;
break;
}
/* Get the format specification. */
spec->info.spec = (wchar_t) *format++;
if (__builtin_expect (__printf_function_table != NULL, 0)
&& spec->info.spec <= UCHAR_MAX
&& __printf_arginfo_table[spec->info.spec] != NULL)
/* We don't try to get the types for all arguments if the format
uses more than one. The normal case is covered though. */
spec->ndata_args = (*__printf_arginfo_table[spec->info.spec])
(&spec->info, 1, &spec->data_arg_type);
else
{
/* Find the data argument types of a built-in spec. */
spec->ndata_args = 1;
switch (spec->info.spec)
{
case L'i':
case L'd':
case L'u':
case L'o':
case L'X':
case L'x':
#if LONG_MAX != LONG_LONG_MAX
if (spec->info.is_long_double)
spec->data_arg_type = PA_INT|PA_FLAG_LONG_LONG;
else
#endif
if (spec->info.is_long)
spec->data_arg_type = PA_INT|PA_FLAG_LONG;
else if (spec->info.is_short)
spec->data_arg_type = PA_INT|PA_FLAG_SHORT;
else if (spec->info.is_char)
spec->data_arg_type = PA_CHAR;
else
spec->data_arg_type = PA_INT;
break;
case L'e':
case L'E':
case L'f':
case L'F':
case L'g':
case L'G':
case L'a':
case L'A':
if (spec->info.is_long_double)
spec->data_arg_type = PA_DOUBLE|PA_FLAG_LONG_DOUBLE;
else
spec->data_arg_type = PA_DOUBLE;
break;
case L'c':
spec->data_arg_type = PA_CHAR;
break;
case L'C':
spec->data_arg_type = PA_WCHAR;
break;
case L's':
spec->data_arg_type = PA_STRING;
break;
case L'S':
spec->data_arg_type = PA_WSTRING;
break;
case L'p':
spec->data_arg_type = PA_POINTER;
break;
case L'n':
spec->data_arg_type = PA_INT|PA_FLAG_PTR;
break;
case L'm':
default:
/* An unknown spec will consume no args. */
spec->ndata_args = 0;
break;
}
}
if (spec->data_arg == -1 && spec->ndata_args > 0)
{
/* There are args consumed, but no positional spec. Use the
next sequential arg position. */
spec->data_arg = posn;
nargs += spec->ndata_args;
}
if (spec->info.spec == L'\0')
/* Format ended before this spec was complete. */
spec->end_of_fmt = spec->next_fmt = format - 1;
else
{
/* Find the next format spec. */
spec->end_of_fmt = format;
#ifdef COMPILE_WPRINTF
spec->next_fmt = find_spec (format);
#else
spec->next_fmt = find_spec (format, ps);
#endif
}
return nargs;
}
extern size_t __parse_one_specwc (const unsigned int *format, size_t posn,
struct printf_spec *spec,
size_t *max_ref_arg) attribute_hidden;

View File

@@ -0,0 +1,407 @@
/* Internal header for parsing printf format strings.
Copyright (C) 1995-1999, 2000, 2002, 2003 Free Software Foundation, Inc.
This file is part of th GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <ctype.h>
#include <limits.h>
#include <string.h>
#include <wchar.h>
#include <wctype.h>
#ifndef COMPILE_WPRINTF
# define CHAR_T char
# define UCHAR_T unsigned char
# define INT_T int
# define L_(Str) Str
# define ISDIGIT(Ch) isdigit (Ch)
#else
# define CHAR_T wchar_t
# define UCHAR_T unsigned int
# define INT_T wint_t
# define L_(Str) L##Str
# define ISDIGIT(Ch) iswdigit (Ch)
#endif
#include "printf-parse.h"
#define NDEBUG 1
#include <assert.h>
/* Find the next spec in FORMAT, or the end of the string. Returns
a pointer into FORMAT, to a '%' or a '\0'. */
const UCHAR_T *
#ifdef COMPILE_WPRINTF
__find_specwc (const UCHAR_T *format)
#else
__find_specmb (const UCHAR_T *format, mbstate_t *ps)
#endif
{
#ifdef COMPILE_WPRINTF
return (const UCHAR_T *) __wcschrnul ((const CHAR_T *) format, L'%');
#else
while (*format != L_('\0') && *format != L_('%'))
{
int len;
/* Remove any hints of a wrong encoding. */
ps->__count = 0;
if (! isascii (*format) && (len = __mbrlen (format, MB_CUR_MAX, ps)) > 0)
format += len;
else
++format;
}
return format;
#endif
}
/* FORMAT must point to a '%' at the beginning of a spec. Fills in *SPEC
with the parsed details. POSN is the number of arguments already
consumed. At most MAXTYPES - POSN types are filled in TYPES. Return
the number of args consumed by this spec; *MAX_REF_ARG is updated so it
remains the highest argument index used. */
size_t
attribute_hidden
#ifdef COMPILE_WPRINTF
__parse_one_specwc (const UCHAR_T *format, size_t posn,
struct printf_spec *spec, size_t *max_ref_arg)
#else
__parse_one_specmb (const UCHAR_T *format, size_t posn,
struct printf_spec *spec, size_t *max_ref_arg,
mbstate_t *ps)
#endif
{
unsigned int n;
size_t nargs = 0;
/* Skip the '%'. */
++format;
/* Clear information structure. */
spec->data_arg = -1;
spec->info.alt = 0;
spec->info.space = 0;
spec->info.left = 0;
spec->info.showsign = 0;
spec->info.group = 0;
spec->info.i18n = 0;
spec->info.pad = ' ';
spec->info.wide = sizeof (UCHAR_T) > 1;
/* Test for positional argument. */
if (ISDIGIT (*format))
{
const UCHAR_T *begin = format;
n = read_int (&format);
if (n > 0 && *format == L_('$'))
/* Is positional parameter. */
{
++format; /* Skip the '$'. */
spec->data_arg = n - 1;
*max_ref_arg = MAX (*max_ref_arg, n);
}
else
/* Oops; that was actually the width and/or 0 padding flag.
Step back and read it again. */
format = begin;
}
/* Check for spec modifiers. */
do
{
switch (*format)
{
case L_(' '):
/* Output a space in place of a sign, when there is no sign. */
spec->info.space = 1;
continue;
case L_('+'):
/* Always output + or - for numbers. */
spec->info.showsign = 1;
continue;
case L_('-'):
/* Left-justify things. */
spec->info.left = 1;
continue;
case L_('#'):
/* Use the "alternate form":
Hex has 0x or 0X, FP always has a decimal point. */
spec->info.alt = 1;
continue;
case L_('0'):
/* Pad with 0s. */
spec->info.pad = '0';
continue;
case L_('\''):
/* Show grouping in numbers if the locale information
indicates any. */
spec->info.group = 1;
continue;
case L_('I'):
/* Use the internationalized form of the output. Currently
means to use the `outdigits' of the current locale. */
spec->info.i18n = 1;
continue;
default:
break;
}
break;
}
while (*++format);
if (spec->info.left)
spec->info.pad = ' ';
/* Get the field width. */
spec->width_arg = -1;
spec->info.width = 0;
if (*format == L_('*'))
{
/* The field width is given in an argument.
A negative field width indicates left justification. */
const UCHAR_T *begin = ++format;
if (ISDIGIT (*format))
{
/* The width argument might be found in a positional parameter. */
n = read_int (&format);
if (n > 0 && *format == L_('$'))
{
spec->width_arg = n - 1;
*max_ref_arg = MAX (*max_ref_arg, n);
++format; /* Skip '$'. */
}
}
if (spec->width_arg < 0)
{
/* Not in a positional parameter. Consume one argument. */
spec->width_arg = posn++;
++nargs;
format = begin; /* Step back and reread. */
}
}
else if (ISDIGIT (*format))
/* Constant width specification. */
spec->info.width = read_int (&format);
/* Get the precision. */
spec->prec_arg = -1;
/* -1 means none given; 0 means explicit 0. */
spec->info.prec = -1;
if (*format == L_('.'))
{
++format;
if (*format == L_('*'))
{
/* The precision is given in an argument. */
const UCHAR_T *begin = ++format;
if (ISDIGIT (*format))
{
n = read_int (&format);
if (n > 0 && *format == L_('$'))
{
spec->prec_arg = n - 1;
*max_ref_arg = MAX (*max_ref_arg, n);
++format;
}
}
if (spec->prec_arg < 0)
{
/* Not in a positional parameter. */
spec->prec_arg = posn++;
++nargs;
format = begin;
}
}
else if (ISDIGIT (*format))
spec->info.prec = read_int (&format);
else
/* "%.?" is treated like "%.0?". */
spec->info.prec = 0;
}
/* Check for type modifiers. */
spec->info.is_long_double = 0;
spec->info.is_short = 0;
spec->info.is_long = 0;
spec->info.is_char = 0;
switch (*format++)
{
case L_('h'):
/* ints are short ints or chars. */
if (*format != L_('h'))
spec->info.is_short = 1;
else
{
++format;
spec->info.is_char = 1;
}
break;
case L_('l'):
/* ints are long ints. */
spec->info.is_long = 1;
if (*format != L_('l'))
break;
++format;
/* FALLTHROUGH */
case L_('L'):
/* doubles are long doubles, and ints are long long ints. */
case L_('q'):
/* 4.4 uses this for long long. */
spec->info.is_long_double = 1;
break;
case L_('z'):
case L_('Z'):
/* ints are size_ts. */
assert (sizeof (size_t) <= sizeof (unsigned long long int));
#if LONG_MAX != LONG_LONG_MAX
spec->info.is_long_double = sizeof (size_t) > sizeof (unsigned long int);
#endif
spec->info.is_long = sizeof (size_t) > sizeof (unsigned int);
break;
case L_('t'):
assert (sizeof (ptrdiff_t) <= sizeof (long long int));
#if LONG_MAX != LONG_LONG_MAX
spec->info.is_long_double = (sizeof (ptrdiff_t) > sizeof (long int));
#endif
spec->info.is_long = sizeof (ptrdiff_t) > sizeof (int);
break;
case L_('j'):
assert (sizeof (uintmax_t) <= sizeof (unsigned long long int));
#if LONG_MAX != LONG_LONG_MAX
spec->info.is_long_double = (sizeof (uintmax_t)
> sizeof (unsigned long int));
#endif
spec->info.is_long = sizeof (uintmax_t) > sizeof (unsigned int);
break;
default:
/* Not a recognized modifier. Backup. */
--format;
break;
}
/* Get the format specification. */
spec->info.spec = (wchar_t) *format++;
if (__builtin_expect (__printf_function_table != NULL, 0)
&& spec->info.spec <= UCHAR_MAX
&& __printf_arginfo_table[spec->info.spec] != NULL)
/* We don't try to get the types for all arguments if the format
uses more than one. The normal case is covered though. */
spec->ndata_args = (*__printf_arginfo_table[spec->info.spec])
(&spec->info, 1, &spec->data_arg_type);
else
{
/* Find the data argument types of a built-in spec. */
spec->ndata_args = 1;
switch (spec->info.spec)
{
case L'i':
case L'd':
case L'u':
case L'o':
case L'X':
case L'x':
#if LONG_MAX != LONG_LONG_MAX
if (spec->info.is_long_double)
spec->data_arg_type = PA_INT|PA_FLAG_LONG_LONG;
else
#endif
if (spec->info.is_long)
spec->data_arg_type = PA_INT|PA_FLAG_LONG;
else if (spec->info.is_short)
spec->data_arg_type = PA_INT|PA_FLAG_SHORT;
else if (spec->info.is_char)
spec->data_arg_type = PA_CHAR;
else
spec->data_arg_type = PA_INT;
break;
case L'e':
case L'E':
case L'f':
case L'F':
case L'g':
case L'G':
case L'a':
case L'A':
if (spec->info.is_long_double)
spec->data_arg_type = PA_DOUBLE|PA_FLAG_LONG_DOUBLE;
else
spec->data_arg_type = PA_DOUBLE;
break;
case L'c':
spec->data_arg_type = PA_CHAR;
break;
case L'C':
spec->data_arg_type = PA_WCHAR;
break;
case L's':
spec->data_arg_type = PA_STRING;
break;
case L'S':
spec->data_arg_type = PA_WSTRING;
break;
case L'p':
spec->data_arg_type = PA_POINTER;
break;
case L'n':
spec->data_arg_type = PA_INT|PA_FLAG_PTR;
break;
case L'm':
default:
/* An unknown spec will consume no args. */
spec->ndata_args = 0;
break;
}
}
if (spec->data_arg == -1 && spec->ndata_args > 0)
{
/* There are args consumed, but no positional spec. Use the
next sequential arg position. */
spec->data_arg = posn;
nargs += spec->ndata_args;
}
if (spec->info.spec == L'\0')
/* Format ended before this spec was complete. */
spec->end_of_fmt = spec->next_fmt = format - 1;
else
{
/* Find the next format spec. */
spec->end_of_fmt = format;
#ifdef COMPILE_WPRINTF
spec->next_fmt = __find_specwc (format);
#else
spec->next_fmt = __find_specmb (format, ps);
#endif
}
return nargs;
}

View File

@@ -0,0 +1,2 @@
#define COMPILE_WPRINTF 1
#include "printf-parsemb.c"

View File

@@ -1,4 +1,4 @@
/* Copyright (C) 1991,92,95,96,99,2000,2002 Free Software Foundation, Inc.
/* Copyright (C) 1991,92,95,96,99,2000,2002,2003 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -70,6 +70,7 @@ ssize_t __wprintf_pad __P ((FILE *, wchar_t pad, size_t n));
# endif
#endif
#define DONT_NEED_READ_INT
#include "printf-parse.h"
@@ -88,10 +89,10 @@ parse_printf_format (fmt, n, argtypes)
max_ref_arg = 0;
/* Search for format specifications. */
for (fmt = find_spec (fmt, &mbstate); *fmt != '\0'; fmt = spec.next_fmt)
for (fmt = __find_specmb (fmt, &mbstate); *fmt != '\0'; fmt = spec.next_fmt)
{
/* Parse this spec. */
nargs += parse_one_spec (fmt, nargs, &spec, &max_ref_arg, &mbstate);
nargs += __parse_one_specmb (fmt, nargs, &spec, &max_ref_arg, &mbstate);
/* If the width is determined by an argument this is an int. */
if (spec.width_arg != -1 && (size_t) spec.width_arg < n)

View File

@@ -1294,13 +1294,13 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
#ifdef COMPILE_WPRINTF
/* Find the first format specifier. */
f = lead_str_end = find_spec ((const UCHAR_T *) format);
f = lead_str_end = __find_specwc ((const UCHAR_T *) format);
#else
/* Put state for processing format string in initial state. */
memset (&mbstate, '\0', sizeof (mbstate_t));
/* Find the first format specifier. */
f = lead_str_end = find_spec (format, &mbstate);
f = lead_str_end = __find_specmb (format, &mbstate);
#endif
/* Lock stream. */
@@ -1596,9 +1596,9 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
/* Look for next format specifier. */
#ifdef COMPILE_WPRINTF
f = find_spec ((end_of_spec = ++f));
f = __find_specwc ((end_of_spec = ++f));
#else
f = find_spec ((end_of_spec = ++f), &mbstate);
f = __find_specmb ((end_of_spec = ++f), &mbstate);
#endif
/* Write the following constant string. */
@@ -1677,10 +1677,10 @@ do_positional:
/* Parse the format specifier. */
#ifdef COMPILE_WPRINTF
nargs += parse_one_spec (f, nargs, &specs[nspecs], &max_ref_arg);
nargs += __parse_one_specwc (f, nargs, &specs[nspecs], &max_ref_arg);
#else
nargs += parse_one_spec (f, nargs, &specs[nspecs], &max_ref_arg,
&mbstate);
nargs += __parse_one_specmb (f, nargs, &specs[nspecs], &max_ref_arg,
&mbstate);
#endif
}