summary refs log tree commit diff
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2003-06-11 23:22:36 +0000
committerUlrich Drepper <drepper@redhat.com>2003-06-11 23:22:36 +0000
commit9c7ff11a5cd628ffbe31a7b2de3027ec5b030d8b (patch)
treeea5cb10211192245fd1b92b9b2f07a3d045f3548
parentdd9423a67a7650a9b0f50d8151e4f3797c5a14f8 (diff)
downloadglibc-9c7ff11a5cd628ffbe31a7b2de3027ec5b030d8b.tar.gz
glibc-9c7ff11a5cd628ffbe31a7b2de3027ec5b030d8b.tar.xz
glibc-9c7ff11a5cd628ffbe31a7b2de3027ec5b030d8b.zip
Update.
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.
-rw-r--r--ChangeLog145
-rw-r--r--linuxthreads/ChangeLog5
-rw-r--r--linuxthreads/sysdeps/powerpc/pspinlock.c4
-rw-r--r--nss/nss_files/files-parse.c3
-rw-r--r--stdio-common/Makefile2
-rw-r--r--stdio-common/_itoa.c20
-rw-r--r--stdio-common/_itoa.h29
-rw-r--r--stdio-common/_itowa.h4
-rw-r--r--stdio-common/printf-parse.h382
-rw-r--r--stdio-common/printf-parsemb.c407
-rw-r--r--stdio-common/printf-parsewc.c2
-rw-r--r--stdio-common/printf-prs.c7
-rw-r--r--stdio-common/vfprintf.c14
-rw-r--r--stdlib/Makefile5
-rw-r--r--stdlib/grouping.c202
-rw-r--r--stdlib/grouping.h176
-rw-r--r--stdlib/groupingwc.c2
-rw-r--r--stdlib/rpmatch.c10
-rw-r--r--stdlib/strtod.c23
-rw-r--r--string/strxfrm.c2
-rw-r--r--sysdeps/generic/dl-cache.c41
-rw-r--r--sysdeps/generic/dl-cache.h42
-rw-r--r--sysdeps/generic/ifreq.c80
-rw-r--r--sysdeps/generic/ifreq.h61
-rw-r--r--sysdeps/generic/ldsodefs.h2
-rw-r--r--sysdeps/generic/strtol.c8
-rw-r--r--sysdeps/generic/unwind-dw2-fde.c19
-rw-r--r--sysdeps/generic/wordexp.c9
-rw-r--r--sysdeps/i386/dl-machine.h2
-rw-r--r--sysdeps/posix/sprofil.c4
-rw-r--r--sysdeps/unix/sysv/linux/Dist1
-rw-r--r--sysdeps/unix/sysv/linux/Makefile4
-rw-r--r--sysdeps/unix/sysv/linux/alpha/xstatconv.c10
-rw-r--r--sysdeps/unix/sysv/linux/fpathconf.c6
-rw-r--r--sysdeps/unix/sysv/linux/fxstat.c6
-rw-r--r--sysdeps/unix/sysv/linux/fxstat64.c6
-rw-r--r--sysdeps/unix/sysv/linux/i386/fxstat.c10
-rw-r--r--sysdeps/unix/sysv/linux/i386/lxstat.c10
-rw-r--r--sysdeps/unix/sysv/linux/i386/xstat.c10
-rw-r--r--sysdeps/unix/sysv/linux/ifreq.c93
-rw-r--r--sysdeps/unix/sysv/linux/ifreq.h74
-rw-r--r--sysdeps/unix/sysv/linux/lxstat.c6
-rw-r--r--sysdeps/unix/sysv/linux/lxstat64.c6
-rw-r--r--sysdeps/unix/sysv/linux/pathconf.c137
-rw-r--r--sysdeps/unix/sysv/linux/pathconf.h125
-rw-r--r--sysdeps/unix/sysv/linux/xstat.c7
-rw-r--r--sysdeps/unix/sysv/linux/xstat64.c6
-rw-r--r--sysdeps/unix/sysv/linux/xstatconv.c20
-rw-r--r--sysdeps/unix/sysv/linux/xstatconv.h25
-rw-r--r--time/tzfile.c39
-rw-r--r--wcsmbs/wcsnrtombs.c6
-rw-r--r--wcsmbs/wcsrtombs.c6
-rw-r--r--wcsmbs/wctob.c9
53 files changed, 1369 insertions, 965 deletions
diff --git a/ChangeLog b/ChangeLog
index dac7a28d36..521ffeeab7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,148 @@
+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.
+
 2003-06-10  Ulrich Drepper  <drepper@redhat.com>
 
 	* po/zh_CN.po: Update from translation team.
diff --git a/linuxthreads/ChangeLog b/linuxthreads/ChangeLog
index be8bf8ca45..20f387b3e8 100644
--- a/linuxthreads/ChangeLog
+++ b/linuxthreads/ChangeLog
@@ -1,3 +1,8 @@
+2003-06-11  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/powerpc/pspinlock.c (__pthread_spin_init): Fix
+	initializer [PR libc/5052].
+
 2003-06-09  Andreas Schwab  <schwab@suse.de>
 
 	* Makefile: Move inclusion of ../Rules down after extra-objs is
diff --git a/linuxthreads/sysdeps/powerpc/pspinlock.c b/linuxthreads/sysdeps/powerpc/pspinlock.c
index 15db1413ef..15fd545c14 100644
--- a/linuxthreads/sysdeps/powerpc/pspinlock.c
+++ b/linuxthreads/sysdeps/powerpc/pspinlock.c
@@ -1,5 +1,5 @@
 /* POSIX spinlock implementation.  PowerPC version.
-   Copyright (C) 2000 Free Software Foundation, Inc.
+   Copyright (C) 2000, 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
@@ -55,7 +55,7 @@ __pthread_spin_init (pthread_spinlock_t *lock, int pshared)
   /* We can ignore the `pshared' parameter.  Since we are busy-waiting
      all processes which can access the memory location `lock' points
      to can use the spinlock.  */
-  *lock = 1;
+  *lock = 0;
   return 0;
 }
 weak_alias (__pthread_spin_init, pthread_spin_init)
diff --git a/nss/nss_files/files-parse.c b/nss/nss_files/files-parse.c
index 739ee541aa..1800d364ce 100644
--- a/nss/nss_files/files-parse.c
+++ b/nss/nss_files/files-parse.c
@@ -1,5 +1,5 @@
 /* Common code for file-based database parsers in nss_files module.
-   Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
+   Copyright (C) 1996-2000, 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
@@ -171,6 +171,7 @@ nss_files_parse_hidden_def (parse_line)
 }
 
 static inline char **
+__attribute ((always_inline))
 parse_list (char *line, struct parser_data *data, size_t datalen, int *errnop)
 {
   char *eol, **list, **p;
diff --git a/stdio-common/Makefile b/stdio-common/Makefile
index 1c34605f65..f5ef190850 100644
--- a/stdio-common/Makefile
+++ b/stdio-common/Makefile
@@ -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
 
diff --git a/stdio-common/_itoa.c b/stdio-common/_itoa.c
index 7bc6c08115..e39d88df7f 100644
--- a/stdio-common/_itoa.c
+++ b/stdio-common/_itoa.c
@@ -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;
+}
diff --git a/stdio-common/_itoa.h b/stdio-common/_itoa.h
index 6249adca91..77f5b0c026 100644
--- a/stdio-common/_itoa.h
+++ b/stdio-common/_itoa.h
@@ -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 */
diff --git a/stdio-common/_itowa.h b/stdio-common/_itowa.h
index d3a5447304..009458b4be 100644
--- a/stdio-common/_itowa.h
+++ b/stdio-common/_itowa.h
@@ -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)
 {
diff --git a/stdio-common/printf-parse.h b/stdio-common/printf-parse.h
index ed0dc8bbc8..aa49c7a642 100644
--- a/stdio-common/printf-parse.h
+++ b/stdio-common/printf-parse.h
@@ -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;
-
-  /* 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_specmb (const unsigned char *format, size_t posn,
+				  struct printf_spec *spec,
+				  size_t *max_ref_arg, mbstate_t *ps)
+     attribute_hidden;
+
+extern size_t __parse_one_specwc (const unsigned int *format, size_t posn,
+				  struct printf_spec *spec,
+				  size_t *max_ref_arg) attribute_hidden;
diff --git a/stdio-common/printf-parsemb.c b/stdio-common/printf-parsemb.c
new file mode 100644
index 0000000000..0d01d5693e
--- /dev/null
+++ b/stdio-common/printf-parsemb.c
@@ -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;
+}
diff --git a/stdio-common/printf-parsewc.c b/stdio-common/printf-parsewc.c
new file mode 100644
index 0000000000..3de67d8081
--- /dev/null
+++ b/stdio-common/printf-parsewc.c
@@ -0,0 +1,2 @@
+#define COMPILE_WPRINTF	1
+#include "printf-parsemb.c"
diff --git a/stdio-common/printf-prs.c b/stdio-common/printf-prs.c
index ecbb47d41c..7aef42d819 100644
--- a/stdio-common/printf-prs.c
+++ b/stdio-common/printf-prs.c
@@ -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)
diff --git a/stdio-common/vfprintf.c b/stdio-common/vfprintf.c
index 63440f4b76..16f280ed4f 100644
--- a/stdio-common/vfprintf.c
+++ b/stdio-common/vfprintf.c
@@ -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
       }
 
diff --git a/stdlib/Makefile b/stdlib/Makefile
index 4d471c911b..7a155031d3 100644
--- a/stdlib/Makefile
+++ b/stdlib/Makefile
@@ -1,4 +1,4 @@
-# Copyright (C) 1991-1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+# Copyright (C) 1991-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
@@ -49,6 +49,7 @@ routines	:=							      \
 	rpmatch strfmon strfmon_l getsubopt xpg_basename fmtmsg		      \
 	strtoimax strtoumax wcstoimax wcstoumax				      \
 	getcontext setcontext makecontext swapcontext
+aux =	grouping groupingwc
 
 # These routines will be omitted from the libc shared object.
 # Instead the static object files will be included in a special archive
@@ -73,7 +74,7 @@ mpn-headers = longlong.h gmp.h gmp-impl.h gmp-mparam.h asm-syntax.h
 routines := $(strip $(routines) $(mpn-routines))	\
 	    dbl2mpn ldbl2mpn				\
 	    mpn2flt mpn2dbl mpn2ldbl
-aux := fpioconst mp_clz_tab
+aux += fpioconst mp_clz_tab
 distribute := $(distribute) $(mpn-headers) gen-mpn-copy fpioconst.h
 
 generated += isomac isomac.out
diff --git a/stdlib/grouping.c b/stdlib/grouping.c
new file mode 100644
index 0000000000..4e01dc3bdd
--- /dev/null
+++ b/stdlib/grouping.c
@@ -0,0 +1,202 @@
+/* Internal header for proving correct grouping in strings of numbers.
+   Copyright (C) 1995,1996,1997,1998,2000,2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
+
+   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 <limits.h>
+#include <stddef.h>
+#include <string.h>
+
+#ifndef MAX
+#define MAX(a,b)	({ typeof(a) _a = (a); typeof(b) _b = (b); \
+			   _a > _b ? _a : _b; })
+#endif
+
+#ifdef USE_WIDE_CHAR
+# include <wctype.h>
+# define L_(Ch) L##Ch
+# define UCHAR_TYPE wint_t
+# define STRING_TYPE wchar_t
+#else
+# define L_(Ch) Ch
+# define UCHAR_TYPE unsigned char
+# define STRING_TYPE char
+#endif
+
+#include "grouping.h"
+
+/* Find the maximum prefix of the string between BEGIN and END which
+   satisfies the grouping rules.  It is assumed that at least one digit
+   follows BEGIN directly.  */
+
+const STRING_TYPE *
+#ifdef USE_WIDE_CHAR
+__correctly_grouped_prefixwc (const STRING_TYPE *begin, const STRING_TYPE *end,
+			      wchar_t thousands,
+#else
+__correctly_grouped_prefixmb (const STRING_TYPE *begin, const STRING_TYPE *end,
+			      const char *thousands,
+#endif
+			      const char *grouping)
+{
+#ifndef USE_WIDE_CHAR
+  size_t thousands_len;
+  int cnt;
+#endif
+
+  if (grouping == NULL)
+    return end;
+
+#ifndef USE_WIDE_CHAR
+  thousands_len = strlen (thousands);
+#endif
+
+  while (end > begin)
+    {
+      const STRING_TYPE *cp = end - 1;
+      const char *gp = grouping;
+
+      /* Check first group.  */
+      while (cp >= begin)
+	{
+#ifdef USE_WIDE_CHAR
+	  if (*cp == thousands)
+	    break;
+#else
+	  if (cp[thousands_len - 1] == *thousands)
+	    {
+	      for (cnt = 1; thousands[cnt] != '\0'; ++cnt)
+		if (thousands[cnt] != cp[thousands_len - 1 - cnt])
+		  break;
+	      if (thousands[cnt] == '\0')
+		break;
+	    }
+#endif
+	  --cp;
+	}
+
+      /* We allow the representation to contain no grouping at all even if
+	 the locale specifies we can have grouping.  */
+      if (cp < begin)
+	return end;
+
+      if (end - cp == (int) *gp + 1)
+	{
+	  /* This group matches the specification.  */
+
+	  const STRING_TYPE *new_end;
+
+	  if (cp < begin)
+	    /* There is just one complete group.  We are done.  */
+	    return end;
+
+	  /* CP points to a thousands separator character.  The preceding
+	     remainder of the string from BEGIN to NEW_END is the part we
+	     will consider if there is a grouping error in this trailing
+	     portion from CP to END.  */
+	  new_end = cp - 1;
+
+	  /* Loop while the grouping is correct.  */
+	  while (1)
+	    {
+	      /* Get the next grouping rule.  */
+	      ++gp;
+	      if (*gp == 0)
+		/* If end is reached use last rule.  */
+	        --gp;
+
+	      /* Skip the thousands separator.  */
+	      --cp;
+
+	      if (*gp == CHAR_MAX
+#if CHAR_MIN < 0
+		  || *gp < 0
+#endif
+		  )
+	        {
+	          /* No more thousands separators are allowed to follow.  */
+	          while (cp >= begin)
+		    {
+#ifdef USE_WIDE_CHAR
+		      if (*cp == thousands)
+			break;
+#else
+		      for (cnt = 0; thousands[cnt] != '\0'; ++cnt)
+			if (thousands[cnt] != cp[thousands_len - cnt - 1])
+			  break;
+		      if (thousands[cnt] == '\0')
+			break;
+#endif
+		      --cp;
+		    }
+
+	          if (cp < begin)
+		    /* OK, only digits followed.  */
+		    return end;
+	        }
+	      else
+	        {
+		  /* Check the next group.  */
+	          const STRING_TYPE *group_end = cp;
+
+		  while (cp >= begin)
+		    {
+#ifdef USE_WIDE_CHAR
+		      if (*cp == thousands)
+			break;
+#else
+		      for (cnt = 0; thousands[cnt] != '\0'; ++cnt)
+			if (thousands[cnt] != cp[thousands_len - cnt - 1])
+			  break;
+		      if (thousands[cnt] == '\0')
+			break;
+#endif
+		      --cp;
+		    }
+
+		  if (cp < begin && group_end - cp <= (int) *gp)
+		    /* Final group is correct.  */
+		    return end;
+
+		  if (cp < begin || group_end - cp != (int) *gp)
+		    /* Incorrect group.  Punt.  */
+		    break;
+		}
+	    }
+
+	  /* The trailing portion of the string starting at NEW_END
+	     contains a grouping error.  So we will look for a correctly
+	     grouped number in the preceding portion instead.  */
+	  end = new_end;
+	}
+      else
+	{
+	  /* Even the first group was wrong; determine maximum shift.  */
+	  if (end - cp > (int) *gp + 1)
+	    end = cp + (int) *gp + 1;
+	  else if (cp < begin)
+	    /* This number does not fill the first group, but is correct.  */
+	    return end;
+	  else
+	    /* CP points to a thousands separator character.  */
+	    end = cp;
+	}
+    }
+
+  return MAX (begin, end);
+}
diff --git a/stdlib/grouping.h b/stdlib/grouping.h
index 830304d2f1..c0f8d47fba 100644
--- a/stdlib/grouping.h
+++ b/stdlib/grouping.h
@@ -1,5 +1,5 @@
 /* Internal header for proving correct grouping in strings of numbers.
-   Copyright (C) 1995, 1996, 1997, 1998, 2000 Free Software Foundation, Inc.
+   Copyright (C) 1995,1996,1997,1998,2000,2003 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
 
@@ -18,169 +18,17 @@
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
 
-#include <limits.h>
-
-#ifndef MAX
-#define MAX(a,b)	({ typeof(a) _a = (a); typeof(b) _b = (b); \
-			   _a > _b ? _a : _b; })
-#endif
-
 /* Find the maximum prefix of the string between BEGIN and END which
    satisfies the grouping rules.  It is assumed that at least one digit
    follows BEGIN directly.  */
-
-static inline const STRING_TYPE *
-correctly_grouped_prefix (const STRING_TYPE *begin, const STRING_TYPE *end,
-#ifdef USE_WIDE_CHAR
-			  wchar_t thousands,
-#else
-			  const char *thousands,
-#endif
-			  const char *grouping)
-{
-#ifndef USE_WIDE_CHAR
-  size_t thousands_len;
-  int cnt;
-#endif
-
-  if (grouping == NULL)
-    return end;
-
-#ifndef USE_WIDE_CHAR
-  thousands_len = strlen (thousands);
-#endif
-
-  while (end > begin)
-    {
-      const STRING_TYPE *cp = end - 1;
-      const char *gp = grouping;
-
-      /* Check first group.  */
-      while (cp >= begin)
-	{
-#ifdef USE_WIDE_CHAR
-	  if (*cp == thousands)
-	    break;
-#else
-	  if (cp[thousands_len - 1] == *thousands)
-	    {
-	      for (cnt = 1; thousands[cnt] != '\0'; ++cnt)
-		if (thousands[cnt] != cp[thousands_len - 1 - cnt])
-		  break;
-	      if (thousands[cnt] == '\0')
-		break;
-	    }
-#endif
-	  --cp;
-	}
-
-      /* We allow the representation to contain no grouping at all even if
-	 the locale specifies we can have grouping.  */
-      if (cp < begin)
-	return end;
-
-      if (end - cp == (int) *gp + 1)
-	{
-	  /* This group matches the specification.  */
-
-	  const STRING_TYPE *new_end;
-
-	  if (cp < begin)
-	    /* There is just one complete group.  We are done.  */
-	    return end;
-
-	  /* CP points to a thousands separator character.  The preceding
-	     remainder of the string from BEGIN to NEW_END is the part we
-	     will consider if there is a grouping error in this trailing
-	     portion from CP to END.  */
-	  new_end = cp - 1;
-
-	  /* Loop while the grouping is correct.  */
-	  while (1)
-	    {
-	      /* Get the next grouping rule.  */
-	      ++gp;
-	      if (*gp == 0)
-		/* If end is reached use last rule.  */
-	        --gp;
-
-	      /* Skip the thousands separator.  */
-	      --cp;
-
-	      if (*gp == CHAR_MAX
-#if CHAR_MIN < 0
-		  || *gp < 0
-#endif
-		  )
-	        {
-	          /* No more thousands separators are allowed to follow.  */
-	          while (cp >= begin)
-		    {
-#ifdef USE_WIDE_CHAR
-		      if (*cp == thousands)
-			break;
-#else
-		      for (cnt = 0; thousands[cnt] != '\0'; ++cnt)
-			if (thousands[cnt] != cp[thousands_len - cnt - 1])
-			  break;
-		      if (thousands[cnt] == '\0')
-			break;
-#endif
-		      --cp;
-		    }
-
-	          if (cp < begin)
-		    /* OK, only digits followed.  */
-		    return end;
-	        }
-	      else
-	        {
-		  /* Check the next group.  */
-	          const STRING_TYPE *group_end = cp;
-
-		  while (cp >= begin)
-		    {
-#ifdef USE_WIDE_CHAR
-		      if (*cp == thousands)
-			break;
-#else
-		      for (cnt = 0; thousands[cnt] != '\0'; ++cnt)
-			if (thousands[cnt] != cp[thousands_len - cnt - 1])
-			  break;
-		      if (thousands[cnt] == '\0')
-			break;
-#endif
-		      --cp;
-		    }
-
-		  if (cp < begin && group_end - cp <= (int) *gp)
-		    /* Final group is correct.  */
-		    return end;
-
-		  if (cp < begin || group_end - cp != (int) *gp)
-		    /* Incorrect group.  Punt.  */
-		    break;
-		}
-	    }
-
-	  /* The trailing portion of the string starting at NEW_END
-	     contains a grouping error.  So we will look for a correctly
-	     grouped number in the preceding portion instead.  */
-	  end = new_end;
-	}
-      else
-	{
-	  /* Even the first group was wrong; determine maximum shift.  */
-	  if (end - cp > (int) *gp + 1)
-	    end = cp + (int) *gp + 1;
-	  else if (cp < begin)
-	    /* This number does not fill the first group, but is correct.  */
-	    return end;
-	  else
-	    /* CP points to a thousands separator character.  */
-	    end = cp;
-	}
-    }
-
-  return MAX (begin, end);
-}
+extern const wchar_t *__correctly_grouped_prefixwc (const wchar_t *begin,
+						    const wchar_t *end,
+						    wchar_t thousands,
+						    const char *grouping)
+     attribute_hidden;
+
+extern const char *__correctly_grouped_prefixmb (const char *begin,
+						 const char *end,
+						 const char *thousands,
+						 const char *grouping)
+     attribute_hidden;
diff --git a/stdlib/groupingwc.c b/stdlib/groupingwc.c
new file mode 100644
index 0000000000..cd9675ee58
--- /dev/null
+++ b/stdlib/groupingwc.c
@@ -0,0 +1,2 @@
+#define USE_WIDE_CHAR	1
+#include "grouping.c"
diff --git a/stdlib/rpmatch.c b/stdlib/rpmatch.c
index f3cc520f8b..7714c2f497 100644
--- a/stdlib/rpmatch.c
+++ b/stdlib/rpmatch.c
@@ -1,7 +1,7 @@
 /* Determine whether string value is affirmation or negative response
    according to current locale's data.
    This file is part of the GNU C Library.
-   Copyright (C) 1996, 1997, 2000 Free Software Foundation, Inc.
+   Copyright (C) 1996, 1997, 2000, 2003 Free Software Foundation, Inc.
 
    The GNU C Library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
@@ -29,11 +29,11 @@ rpmatch (response)
 {
   /* Match against one of the response patterns, compiling the pattern
      first if necessary.  */
-  auto inline int try (const int tag, const int match, const int nomatch,
-		       const char **lastp, regex_t *re);
+  auto int try (const int tag, const int match, const int nomatch,
+		const char **lastp, regex_t *re);
 
-  inline int try (const int tag, const int match, const int nomatch,
-		  const char **lastp, regex_t *re)
+  int try (const int tag, const int match, const int nomatch,
+	   const char **lastp, regex_t *re)
     {
       const char *pattern = nl_langinfo (tag);
       if (pattern != *lastp)
diff --git a/stdlib/strtod.c b/stdlib/strtod.c
index 8d773ecb3d..63d7a4d5bb 100644
--- a/stdlib/strtod.c
+++ b/stdlib/strtod.c
@@ -207,7 +207,7 @@ static const mp_limb_t _tens_in_limb[MAX_DIG_PER_LIMB + 1] =
 
 /* Return a floating point number of the needed type according to the given
    multi-precision number after possible rounding.  */
-static inline FLOAT
+static FLOAT
 round_and_return (mp_limb_t *retval, int exponent, int negative,
 		  mp_limb_t round_limb, mp_size_t round_bit, int more_bits)
 {
@@ -302,7 +302,7 @@ round_and_return (mp_limb_t *retval, int exponent, int negative,
    character od the string that is not part of the integer as the function
    value.  If the EXPONENT is small enough to be taken as an additional
    factor for the resulting number (see code) multiply by it.  */
-static inline const STRING_TYPE *
+static const STRING_TYPE *
 str_to_mpn (const STRING_TYPE *str, int digcnt, mp_limb_t *n, mp_size_t *nsize,
 	    int *exponent
 #ifndef USE_WIDE_CHAR
@@ -401,10 +401,11 @@ str_to_mpn (const STRING_TYPE *str, int digcnt, mp_limb_t *n, mp_size_t *nsize,
    Tege doesn't like this function so I have to write it here myself. :)
    --drepper */
 static inline void
+__attribute ((always_inline))
 __mpn_lshift_1 (mp_limb_t *ptr, mp_size_t size, unsigned int count,
 		mp_limb_t limb)
 {
-  if (count == BITS_PER_MP_LIMB)
+  if (__builtin_constant_p (count) && count == BITS_PER_MP_LIMB)
     {
       /* Optimize the case of shifting by exactly a word:
 	 just copy words, with no actual bit-shifting.  */
@@ -692,7 +693,13 @@ INTERNAL (STRTOF) (nptr, endptr, group LOCALE_PARAM)
 			 || (CHAR_TYPE) TOLOWER (c) != L_('p')))
       && (base != 16 && (CHAR_TYPE) TOLOWER (c) != L_('e')))
     {
-      tp = correctly_grouped_prefix (start_of_digits, cp, thousands, grouping);
+#ifdef USE_WIDE_CHAR
+      tp = __correctly_grouped_prefixwc (start_of_digits, cp, thousands,
+					 grouping);
+#else
+      tp = __correctly_grouped_prefixmb (start_of_digits, cp, thousands,
+					 grouping);
+#endif
       /* If TP is at the start of the digits, there was no correctly
 	 grouped prefix of the string; so no number found.  */
       RETURN (0.0, tp == start_of_digits ? (base == 16 ? cp - 1 : nptr) : tp);
@@ -733,7 +740,13 @@ INTERNAL (STRTOF) (nptr, endptr, group LOCALE_PARAM)
   if (grouping && dig_no > 0)
     {
       /* Check the grouping of the digits.  */
-      tp = correctly_grouped_prefix (start_of_digits, cp, thousands, grouping);
+#ifdef USE_WIDE_CHAR
+      tp = __correctly_grouped_prefixwc (start_of_digits, cp, thousands,
+					 grouping);
+#else
+      tp = __correctly_grouped_prefixmb (start_of_digits, cp, thousands,
+					 grouping);
+#endif
       if (cp != tp)
         {
 	  /* Less than the entire string was correctly grouped.  */
diff --git a/string/strxfrm.c b/string/strxfrm.c
index 9db57829d9..549d68cc1c 100644
--- a/string/strxfrm.c
+++ b/string/strxfrm.c
@@ -51,7 +51,7 @@
 #ifndef WIDE_CHAR_VERSION
 
 /* We need UTF-8 encoding of numbers.  */
-static inline int
+static int
 utf8_encode (char *buf, int val)
 {
   int retval;
diff --git a/sysdeps/generic/dl-cache.c b/sysdeps/generic/dl-cache.c
index bf2e98c543..b17c18baf9 100644
--- a/sysdeps/generic/dl-cache.c
+++ b/sysdeps/generic/dl-cache.c
@@ -1,5 +1,5 @@
 /* Support for reading /etc/ld.so.cache files written by Linux ldconfig.
-   Copyright (C) 1996,1997,1998,1999,2000,2001,2002 Free Software Foundation, Inc.
+   Copyright (C) 1996-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
@@ -133,6 +133,45 @@ do									      \
 while (0)
 
 
+int
+internal_function
+_dl_cache_libcmp (const char *p1, const char *p2)
+{
+  while (*p1 != '\0')
+    {
+      if (*p1 >= '0' && *p1 <= '9')
+        {
+          if (*p2 >= '0' && *p2 <= '9')
+            {
+	      /* Must compare this numerically.  */
+	      int val1;
+	      int val2;
+
+	      val1 = *p1++ - '0';
+	      val2 = *p2++ - '0';
+	      while (*p1 >= '0' && *p1 <= '9')
+	        val1 = val1 * 10 + *p1++ - '0';
+	      while (*p2 >= '0' && *p2 <= '9')
+	        val2 = val2 * 10 + *p2++ - '0';
+	      if (val1 != val2)
+		return val1 - val2;
+	    }
+	  else
+            return 1;
+        }
+      else if (*p2 >= '0' && *p2 <= '9')
+        return -1;
+      else if (*p1 != *p2)
+        return *p1 - *p2;
+      else
+	{
+	  ++p1;
+	  ++p2;
+	}
+    }
+  return *p1 - *p2;
+}
+
 
 /* Look up NAME in ld.so.cache and return the file name stored there,
    or null if none is found.  */
diff --git a/sysdeps/generic/dl-cache.h b/sysdeps/generic/dl-cache.h
index 93bf0be6f4..946e5a9713 100644
--- a/sysdeps/generic/dl-cache.h
+++ b/sysdeps/generic/dl-cache.h
@@ -1,5 +1,5 @@
 /* Support for reading /etc/ld.so.cache files written by Linux ldconfig.
-   Copyright (C) 1999, 2000, 2002 Free Software Foundation, Inc.
+   Copyright (C) 1999, 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
@@ -97,41 +97,5 @@ struct cache_file_new
 (((addr) + __alignof__ (struct cache_file_new) -1)	\
  & (~(__alignof__ (struct cache_file_new) - 1)))
 
-static inline int
-__attribute__ ((__unused__))
-_dl_cache_libcmp (const char *p1, const char *p2)
-{
-  while (*p1 != '\0')
-    {
-      if (*p1 >= '0' && *p1 <= '9')
-        {
-          if (*p2 >= '0' && *p2 <= '9')
-            {
-	      /* Must compare this numerically.  */
-	      int val1;
-	      int val2;
-
-	      val1 = *p1++ - '0';
-	      val2 = *p2++ - '0';
-	      while (*p1 >= '0' && *p1 <= '9')
-	        val1 = val1 * 10 + *p1++ - '0';
-	      while (*p2 >= '0' && *p2 <= '9')
-	        val2 = val2 * 10 + *p2++ - '0';
-	      if (val1 != val2)
-		return val1 - val2;
-	    }
-	  else
-            return 1;
-        }
-      else if (*p2 >= '0' && *p2 <= '9')
-        return -1;
-      else if (*p1 != *p2)
-        return *p1 - *p2;
-      else
-	{
-	  ++p1;
-	  ++p2;
-	}
-    }
-  return *p1 - *p2;
-}
+extern int _dl_cache_libcmp (const char *p1, const char *p2)
+     internal_function;
diff --git a/sysdeps/generic/ifreq.c b/sysdeps/generic/ifreq.c
new file mode 100644
index 0000000000..be7c03cf08
--- /dev/null
+++ b/sysdeps/generic/ifreq.c
@@ -0,0 +1,80 @@
+/* Copyright (C) 1999, 2002, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Andreas Jaeger <aj@suse.de>.
+
+   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 "ifreq.h"
+
+
+void
+__ifreq (struct ifreq **ifreqs, int *num_ifs, int sockfd)
+{
+  int fd = sockfd;
+  struct ifconf ifc;
+  int rq_len;
+  int nifs;
+# define RQ_IFS	4
+
+  if (fd < 0)
+    fd = __opensock ();
+  if (fd < 0)
+    {
+      *num_ifs = 0;
+      *ifreqs = NULL;
+      return;
+    }
+
+  ifc.ifc_buf = NULL;
+  rq_len = RQ_IFS * sizeof (struct ifreq) / 2; /* Doubled in the loop.  */
+  do
+    {
+      ifc.ifc_len = rq_len *= 2;
+      ifc.ifc_buf = realloc (ifc.ifc_buf, ifc.ifc_len);
+      if (ifc.ifc_buf == NULL || __ioctl (fd, SIOCGIFCONF, &ifc) < 0)
+	{
+	  if (ifc.ifc_buf)
+	    free (ifc.ifc_buf);
+
+	  if (fd != sockfd)
+	    __close (fd);
+	  *num_ifs = 0;
+	  *ifreqs = NULL;
+	  return;
+	}
+    }
+  while (rq_len < sizeof (struct ifreq) + ifc.ifc_len);
+
+  if (fd != sockfd)
+    __close (fd);
+
+#ifdef _HAVE_SA_LEN
+  struct ifreq *ifr = ifreqs;
+  nifs = 0;
+  while ((char *) ifr < ifc.ifc_buf + ifc.ifc_len)
+    {
+      ++nifs;
+      ifr = __if_nextreq (ifr);
+      if (ifr == NULL)
+	break;
+    }
+#else
+  nifs = ifc.ifc_len / sizeof (struct ifreq);
+#endif
+
+  *num_ifs = nifs;
+  *ifreqs = realloc (ifc.ifc_buf, nifs * sizeof (struct ifreq));
+}
diff --git a/sysdeps/generic/ifreq.h b/sysdeps/generic/ifreq.h
index 4871c8d1d8..6e01fb463e 100644
--- a/sysdeps/generic/ifreq.h
+++ b/sysdeps/generic/ifreq.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1999,2002 Free Software Foundation, Inc.
+/* Copyright (C) 1999, 2002, 2003 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Andreas Jaeger <aj@suse.de>.
 
@@ -34,64 +34,7 @@ __if_nextreq (struct ifreq *ifr)
   return ifr + 1;
 }
 
-static inline void
-__ifreq (struct ifreq **ifreqs, int *num_ifs, int sockfd)
-{
-  int fd = sockfd;
-  struct ifconf ifc;
-  int rq_len;
-  int nifs;
-# define RQ_IFS	4
-
-  if (fd < 0)
-    fd = __opensock ();
-  if (fd < 0)
-    {
-      *num_ifs = 0;
-      *ifreqs = NULL;
-      return;
-    }
-
-  ifc.ifc_buf = NULL;
-  rq_len = RQ_IFS * sizeof (struct ifreq) / 2; /* Doubled in the loop.  */
-  do
-    {
-      ifc.ifc_len = rq_len *= 2;
-      ifc.ifc_buf = realloc (ifc.ifc_buf, ifc.ifc_len);
-      if (ifc.ifc_buf == NULL || __ioctl (fd, SIOCGIFCONF, &ifc) < 0)
-	{
-	  if (ifc.ifc_buf)
-	    free (ifc.ifc_buf);
-
-	  if (fd != sockfd)
-	    __close (fd);
-	  *num_ifs = 0;
-	  *ifreqs = NULL;
-	  return;
-	}
-    }
-  while (rq_len < sizeof (struct ifreq) + ifc.ifc_len);
-
-  if (fd != sockfd)
-    __close (fd);
-
-#ifdef _HAVE_SA_LEN
-  struct ifreq *ifr = ifreqs;
-  nifs = 0;
-  while ((char *) ifr < ifc.ifc_buf + ifc.ifc_len)
-    {
-      ++nifs;
-      ifr = __if_nextreq (ifr);
-      if (ifr == NULL)
-	break;
-    }
-#else
-  nifs = ifc.ifc_len / sizeof (struct ifreq);
-#endif
-
-  *num_ifs = nifs;
-  *ifreqs = realloc (ifc.ifc_buf, nifs * sizeof (struct ifreq));
-}
+extern void __ifreq (struct ifreq **ifreqs, int *num_ifs, int sockfd);
 
 
 static inline void
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
index 4b75f4672e..2a3cf2bd09 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -173,7 +173,7 @@ struct libname_list
 
 /* Test whether given NAME matches any of the names of the given object.  */
 static __inline int
-__attribute__ ((unused))
+__attribute__ ((unused, always_inline))
 _dl_name_match_p (const char *__name, struct link_map *__map)
 {
   int __found = strcmp (__name, __map->l_name) == 0;
diff --git a/sysdeps/generic/strtol.c b/sysdeps/generic/strtol.c
index 1b267753d9..953c6c4a90 100644
--- a/sysdeps/generic/strtol.c
+++ b/sysdeps/generic/strtol.c
@@ -1,5 +1,5 @@
 /* Convert string representation of a number into an integer value.
-   Copyright (C) 1991,92,94,95,96,97,98,99,2000,01,02
+   Copyright (C) 1991,92,94,95,96,97,98,99,2000,2001,2002,2003
    	Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
@@ -374,7 +374,11 @@ INTERNAL (strtol) (nptr, endptr, base, group LOCALE_PARAM)
 		    || (int) (TOUPPER (c) - L_('A') + 10) >= base))
 	      break;
 
-	  end = correctly_grouped_prefix (s, end, thousands, grouping);
+# ifdef USE_WIDE_CHAR
+	  end = __correctly_grouped_prefixwc (s, end, thousands, grouping);
+# else
+	  end = __correctly_grouped_prefixmb (s, end, thousands, grouping);
+# endif
 	}
     }
   else
diff --git a/sysdeps/generic/unwind-dw2-fde.c b/sysdeps/generic/unwind-dw2-fde.c
index 64c0846ccb..024ffd01c5 100644
--- a/sysdeps/generic/unwind-dw2-fde.c
+++ b/sysdeps/generic/unwind-dw2-fde.c
@@ -1,5 +1,6 @@
 /* Subroutines needed for unwinding stack frames for exception handling.  */
-/* Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+/* Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003
+   Free Software Foundation, Inc.
    Contributed by Jason Merrill <jason@cygnus.com>.
 
 This file is part of GCC.
@@ -423,7 +424,7 @@ struct fde_accumulator
   struct fde_vector *erratic;
 };
 
-static inline int
+static int
 start_fde_sort (struct fde_accumulator *accu, size_t count)
 {
   size_t size;
@@ -461,7 +462,7 @@ fde_insert (struct fde_accumulator *accu, fde *this_fde)
    chain to determine what should be placed in the ERRATIC array, and
    what is the linear sequence.  This overlay is safe from aliasing.  */
 
-static inline void
+static void
 fde_split (struct object *ob, fde_compare_t fde_compare,
 	   struct fde_vector *linear, struct fde_vector *erratic)
 {
@@ -571,7 +572,7 @@ frame_heapsort (struct object *ob, fde_compare_t fde_compare,
 }
 
 /* Merge V1 and V2, both sorted, and put the result into V1.  */
-static inline void
+static void
 fde_merge (struct object *ob, fde_compare_t fde_compare,
 	   struct fde_vector *v1, struct fde_vector *v2)
 {
@@ -598,7 +599,7 @@ fde_merge (struct object *ob, fde_compare_t fde_compare,
     }
 }
 
-static inline void
+static void
 end_fde_sort (struct object *ob, struct fde_accumulator *accu, size_t count)
 {
   fde_compare_t fde_compare;
@@ -753,7 +754,7 @@ add_fdes (struct object *ob, struct fde_accumulator *accu, fde *this_fde)
    be faster.  We can be called multiple times, should we have failed to
    allocate a sorted fde array on a previous occasion.  */
 
-static inline void
+static void
 init_object (struct object* ob)
 {
   struct fde_accumulator accu;
@@ -876,7 +877,7 @@ linear_search_fdes (struct object *ob, fde *this_fde, void *pc)
 /* Binary search for an FDE containing the given PC.  Here are three
    implementations of increasing complexity.  */
 
-static inline fde *
+static fde *
 binary_search_unencoded_fdes (struct object *ob, void *pc)
 {
   struct fde_vector *vec = ob->u.sort;
@@ -903,7 +904,7 @@ binary_search_unencoded_fdes (struct object *ob, void *pc)
   return NULL;
 }
 
-static inline fde *
+static fde *
 binary_search_single_encoding_fdes (struct object *ob, void *pc)
 {
   struct fde_vector *vec = ob->u.sort;
@@ -933,7 +934,7 @@ binary_search_single_encoding_fdes (struct object *ob, void *pc)
   return NULL;
 }
 
-static inline fde *
+static fde *
 binary_search_mixed_encoding_fdes (struct object *ob, void *pc)
 {
   struct fde_vector *vec = ob->u.sort;
diff --git a/sysdeps/generic/wordexp.c b/sysdeps/generic/wordexp.c
index 09f4e942d5..bb870c967d 100644
--- a/sysdeps/generic/wordexp.c
+++ b/sysdeps/generic/wordexp.c
@@ -1,5 +1,5 @@
 /* POSIX.2 wordexp implementation.
-   Copyright (C) 1997,1998,1999,2000,2001,2002 Free Software Foundation, Inc.
+   Copyright (C) 1997-2002, 2003 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Tim Waugh <tim@cyberelk.demon.co.uk>.
 
@@ -89,19 +89,18 @@ w_newword (size_t *actlen, size_t *maxlen)
   return NULL;
 }
 
-static inline char *
+static char *
 w_addchar (char *buffer, size_t *actlen, size_t *maxlen, char ch)
      /* (lengths exclude trailing zero) */
 {
-  /* Add a character to the buffer, allocating room for it if needed.
-   */
+  /* Add a character to the buffer, allocating room for it if needed.  */
 
   if (*actlen == *maxlen)
     {
       char *old_buffer = buffer;
       assert (buffer == NULL || *maxlen != 0);
       *maxlen += W_CHUNK;
-      buffer = realloc (buffer, 1 + *maxlen);
+      buffer = (char *) realloc (buffer, 1 + *maxlen);
 
       if (buffer == NULL)
 	free (old_buffer);
diff --git a/sysdeps/i386/dl-machine.h b/sysdeps/i386/dl-machine.h
index 095098376d..b0c3c7f94c 100644
--- a/sysdeps/i386/dl-machine.h
+++ b/sysdeps/i386/dl-machine.h
@@ -95,7 +95,7 @@ elf_machine_load_address (void)
 /* Set up the loaded object described by L so its unrelocated PLT
    entries will jump to the on-demand fixup code in dl-runtime.c.  */
 
-static inline int __attribute__ ((unused))
+static inline int __attribute__ ((unused, always_inline))
 elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
 {
   Elf32_Addr *got;
diff --git a/sysdeps/posix/sprofil.c b/sysdeps/posix/sprofil.c
index afb6d2f84e..84c797297a 100644
--- a/sysdeps/posix/sprofil.c
+++ b/sysdeps/posix/sprofil.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001,02 Free Software Foundation, Inc.
+/* Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
    Contributed by David Mosberger-Tang <davidm@hpl.hp.com>.
    This file is part of the GNU C Library.
 
@@ -104,7 +104,7 @@ index_to_pc (unsigned long int n, size_t offset, unsigned int scale,
   return pc;
 }
 
-static inline void
+static void
 profil_count (void *pcp, int prof_uint)
 {
   struct region *region, *r = prof_info.last;
diff --git a/sysdeps/unix/sysv/linux/Dist b/sysdeps/unix/sysv/linux/Dist
index f9f6a1a5f8..1cd482c1ff 100644
--- a/sysdeps/unix/sysv/linux/Dist
+++ b/sysdeps/unix/sysv/linux/Dist
@@ -78,6 +78,7 @@ sys/ultrasound.h
 sys/user.h
 sys/vt.h
 xstatconv.c
+xstatconv.h
 getdents64.c
 umount.S
 umount2.S
diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile
index 90671e404e..1085fe0d81 100644
--- a/sysdeps/unix/sysv/linux/Makefile
+++ b/sysdeps/unix/sysv/linux/Makefile
@@ -133,6 +133,10 @@ ifeq ($(subdir),nis)
 CFLAGS-ypclnt.c = -DUSE_BINDINGDIR=1
 endif
 
+ifeq ($(subdir),io)
+sysdep_routines += xstatconv
+endif
+
 ifeq ($(subdir),elf)
 sysdep-rtld-routines += dl-brk dl-sbrk
 
diff --git a/sysdeps/unix/sysv/linux/alpha/xstatconv.c b/sysdeps/unix/sysv/linux/alpha/xstatconv.c
index 31fe7a52ec..1084049dbe 100644
--- a/sysdeps/unix/sysv/linux/alpha/xstatconv.c
+++ b/sysdeps/unix/sysv/linux/alpha/xstatconv.c
@@ -1,5 +1,5 @@
 /* Convert between the kernel's `struct stat' format, and libc's.
-   Copyright (C) 1997 Free Software Foundation, Inc.
+   Copyright (C) 1997, 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
@@ -17,11 +17,15 @@
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
 
+#include <errno.h>
 #include <string.h>
+#include <sys/stat.h>
 
+#include <xstatconv.h>
 
-static inline int
-xstat_conv (int vers, struct kernel_stat *kbuf, void *ubuf)
+
+int
+__xstat_conv (int vers, struct kernel_stat *kbuf, void *ubuf)
 {
   switch (vers)
     {
diff --git a/sysdeps/unix/sysv/linux/fpathconf.c b/sysdeps/unix/sysv/linux/fpathconf.c
index 9eca7175cc..c1cdb1b899 100644
--- a/sysdeps/unix/sysv/linux/fpathconf.c
+++ b/sysdeps/unix/sysv/linux/fpathconf.c
@@ -37,13 +37,13 @@ __fpathconf (fd, name)
   switch (name)
     {
     case _PC_LINK_MAX:
-      return statfs_link_max (__fstatfs (fd, &fsbuf), &fsbuf);
+      return __statfs_link_max (__fstatfs (fd, &fsbuf), &fsbuf);
 
     case _PC_FILESIZEBITS:
-      return statfs_filesize_max (__fstatfs (fd, &fsbuf), &fsbuf);
+      return __statfs_filesize_max (__fstatfs (fd, &fsbuf), &fsbuf);
 
     case _PC_2_SYMLINKS:
-      return statfs_symlinks (__fstatfs (fd, &fsbuf), &fsbuf);
+      return __statfs_symlinks (__fstatfs (fd, &fsbuf), &fsbuf);
 
     default:
       return posix_fpathconf (fd, name);
diff --git a/sysdeps/unix/sysv/linux/fxstat.c b/sysdeps/unix/sysv/linux/fxstat.c
index b19450598d..6acafa261b 100644
--- a/sysdeps/unix/sysv/linux/fxstat.c
+++ b/sysdeps/unix/sysv/linux/fxstat.c
@@ -1,5 +1,5 @@
 /* fxstat using old-style Unix fstat system call.
-   Copyright (C) 1991,1995-1998,2000,2002 Free Software Foundation, Inc.
+   Copyright (C) 1991,1995-1998,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
@@ -31,7 +31,7 @@
 #include <sys/syscall.h>
 #include <bp-checks.h>
 
-#include <xstatconv.c>
+#include <xstatconv.h>
 
 extern int __syscall_fstat (int, struct kernel_stat *__unbounded);
 
@@ -51,7 +51,7 @@ __fxstat (int vers, int fd, struct stat *buf)
 
   result = INLINE_SYSCALL (fstat, 2, fd, __ptrvalue (&kbuf));
   if (result == 0)
-    result = xstat_conv (vers, &kbuf, buf);
+    result = __xstat_conv (vers, &kbuf, buf);
 
   return result;
 #endif
diff --git a/sysdeps/unix/sysv/linux/fxstat64.c b/sysdeps/unix/sysv/linux/fxstat64.c
index f5e16050b6..27e8ac2711 100644
--- a/sysdeps/unix/sysv/linux/fxstat64.c
+++ b/sysdeps/unix/sysv/linux/fxstat64.c
@@ -1,5 +1,5 @@
 /* fxstat64 using old-style Unix fstat system call.
-   Copyright (C) 1997,1998,1999,2000,2001,2002 Free Software Foundation, Inc.
+   Copyright (C) 1997-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
@@ -29,7 +29,7 @@
 #include "kernel-features.h"
 
 #if __ASSUME_STAT64_SYSCALL == 0
-# include <xstatconv.c>
+# include <xstatconv.h>
 #endif
 
 extern int __syscall_fstat (int, struct kernel_stat *__unbounded);
@@ -78,7 +78,7 @@ ___fxstat64 (int vers, int fd, struct stat64 *buf)
 # endif
   result = INLINE_SYSCALL (fstat, 2, fd, __ptrvalue (&kbuf));
   if (result == 0)
-    result = xstat64_conv (vers, &kbuf, buf);
+    result = __xstat64_conv (vers, &kbuf, buf);
 
   return result;
 #endif
diff --git a/sysdeps/unix/sysv/linux/i386/fxstat.c b/sysdeps/unix/sysv/linux/i386/fxstat.c
index 86dbd71175..13a3bc77b7 100644
--- a/sysdeps/unix/sysv/linux/i386/fxstat.c
+++ b/sysdeps/unix/sysv/linux/i386/fxstat.c
@@ -1,5 +1,5 @@
 /* fxstat using old-style Unix fstat system call.
-   Copyright (C) 1991,95,96,97,98,2000,2002 Free Software Foundation, Inc.
+   Copyright (C) 1991,1995-1998,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
@@ -32,7 +32,7 @@
 
 #include "kernel-features.h"
 
-#include <xstatconv.c>
+#include <xstatconv.h>
 
 extern int __syscall_fstat (int, struct kernel_stat *__unbounded);
 
@@ -62,7 +62,7 @@ __fxstat (int vers, int fd, struct stat *buf)
 
     result = INLINE_SYSCALL (fstat64, 2, fd, __ptrvalue (&buf64));
     if (result == 0)
-      result = xstat32_conv (vers, &buf64, buf);
+      result = __xstat32_conv (vers, &buf64, buf);
     return result;
   }
 #else
@@ -77,7 +77,7 @@ __fxstat (int vers, int fd, struct stat *buf)
       result = INLINE_SYSCALL (fstat64, 2, fd, __ptrvalue (&buf64));
 
       if (result == 0)
-	result = xstat32_conv (vers, &buf64, buf);
+	result = __xstat32_conv (vers, &buf64, buf);
 
       if (result != -1 || errno != ENOSYS)
 	return result;
@@ -88,7 +88,7 @@ __fxstat (int vers, int fd, struct stat *buf)
 
   result = INLINE_SYSCALL (fstat, 2, fd, __ptrvalue (&kbuf));
   if (result == 0)
-    result = xstat_conv (vers, &kbuf, buf);
+    result = __xstat_conv (vers, &kbuf, buf);
 
   return result;
 #endif  /* __ASSUME_STAT64_SYSCALL  */
diff --git a/sysdeps/unix/sysv/linux/i386/lxstat.c b/sysdeps/unix/sysv/linux/i386/lxstat.c
index 0da6312fa4..adf55dc5e8 100644
--- a/sysdeps/unix/sysv/linux/i386/lxstat.c
+++ b/sysdeps/unix/sysv/linux/i386/lxstat.c
@@ -1,5 +1,5 @@
 /* lxstat using old-style Unix lstat system call.
-   Copyright (C) 1991,95,96,97,98,2000,2002 Free Software Foundation, Inc.
+   Copyright (C) 1991,95,96,97,98,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
@@ -32,7 +32,7 @@
 
 #include "kernel-features.h"
 
-#include <xstatconv.c>
+#include <xstatconv.h>
 
 extern int __syscall_lstat (const char *__unbounded,
 			    struct kernel_stat *__unbounded);
@@ -65,7 +65,7 @@ __lxstat (int vers, const char *name, struct stat *buf)
 
     result = INLINE_SYSCALL (lstat64, 2, CHECK_STRING (name), __ptrvalue (&buf64));
     if (result == 0)
-      result = xstat32_conv (vers, &buf64, buf);
+      result = __xstat32_conv (vers, &buf64, buf);
     return result;
   }
 #else
@@ -79,7 +79,7 @@ __lxstat (int vers, const char *name, struct stat *buf)
       result = INLINE_SYSCALL (lstat64, 2, CHECK_STRING (name), __ptrvalue (&buf64));
 
       if (result == 0)
-	result = xstat32_conv (vers, &buf64, buf);
+	result = __xstat32_conv (vers, &buf64, buf);
 
       if (result != -1 || errno != ENOSYS)
 	return result;
@@ -90,7 +90,7 @@ __lxstat (int vers, const char *name, struct stat *buf)
 
   result = INLINE_SYSCALL (lstat, 2, CHECK_STRING (name), __ptrvalue (&kbuf));
   if (result == 0)
-    result = xstat_conv (vers, &kbuf, buf);
+    result = __xstat_conv (vers, &kbuf, buf);
 
   return result;
 #endif
diff --git a/sysdeps/unix/sysv/linux/i386/xstat.c b/sysdeps/unix/sysv/linux/i386/xstat.c
index cc383ec2fb..5442fc42b6 100644
--- a/sysdeps/unix/sysv/linux/i386/xstat.c
+++ b/sysdeps/unix/sysv/linux/i386/xstat.c
@@ -1,5 +1,5 @@
 /* xstat using old-style Unix stat system call.
-   Copyright (C) 1991,95,96,97,98,2000,2002 Free Software Foundation, Inc.
+   Copyright (C) 1991,95,96,97,98,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
@@ -32,7 +32,7 @@
 
 #include "kernel-features.h"
 
-#include <xstatconv.c>
+#include <xstatconv.h>
 
 extern int __syscall_stat (const char *__unbounded,
 			   struct kernel_stat *__unbounded);
@@ -65,7 +65,7 @@ __xstat (int vers, const char *name, struct stat *buf)
 
     result = INLINE_SYSCALL (stat64, 2, CHECK_STRING (name), __ptrvalue (&buf64));
     if (result == 0)
-      result = xstat32_conv (vers, &buf64, buf);
+      result = __xstat32_conv (vers, &buf64, buf);
     return result;
   }
 #else
@@ -79,7 +79,7 @@ __xstat (int vers, const char *name, struct stat *buf)
       result = INLINE_SYSCALL (stat64, 2, CHECK_STRING (name), __ptrvalue (&buf64));
 
       if (result == 0)
-	result = xstat32_conv (vers, &buf64, buf);
+	result = __xstat32_conv (vers, &buf64, buf);
 
       if (result != -1 || errno != ENOSYS)
 	return result;
@@ -89,7 +89,7 @@ __xstat (int vers, const char *name, struct stat *buf)
 # endif
   result = INLINE_SYSCALL (stat, 2, CHECK_STRING (name), __ptrvalue (&kbuf));
   if (result == 0)
-    result = xstat_conv (vers, &kbuf, buf);
+    result = __xstat_conv (vers, &kbuf, buf);
 
   return result;
 #endif  /* __ASSUME_STAT64_SYSCALL  */
diff --git a/sysdeps/unix/sysv/linux/ifreq.c b/sysdeps/unix/sysv/linux/ifreq.c
new file mode 100644
index 0000000000..ad408df070
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/ifreq.c
@@ -0,0 +1,93 @@
+/* Copyright (C) 1999, 2002, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Andreas Jaeger <aj@suse.de>.
+
+   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 "ifreq.h"
+
+
+void
+__ifreq (struct ifreq **ifreqs, int *num_ifs, int sockfd)
+{
+  int fd = sockfd;
+  struct ifconf ifc;
+  int rq_len;
+  int nifs;
+# define RQ_IFS	4
+
+  if (fd < 0)
+    fd = __opensock ();
+  if (fd < 0)
+    {
+      *num_ifs = 0;
+      *ifreqs = NULL;
+      return;
+    }
+
+  ifc.ifc_buf = NULL;
+
+  /* We may be able to get the needed buffer size directly, rather than
+     guessing.  */
+  if (! old_siocgifconf)
+    {
+      ifc.ifc_buf = NULL;
+      ifc.ifc_len = 0;
+      if (__ioctl (fd, SIOCGIFCONF, &ifc) < 0 || ifc.ifc_len == 0)
+	{
+# if __ASSUME_SIOCGIFNAME == 0
+	  old_siocgifconf = 1;
+# endif
+	  rq_len = RQ_IFS * sizeof (struct ifreq);
+	}
+      else
+	rq_len = ifc.ifc_len;
+    }
+  else
+    rq_len = RQ_IFS * sizeof (struct ifreq);
+
+  /* Read all the interfaces out of the kernel.  */
+  while (1)
+    {
+      ifc.ifc_len = rq_len;
+      ifc.ifc_buf = realloc (ifc.ifc_buf, ifc.ifc_len);
+      if (ifc.ifc_buf == NULL || __ioctl (fd, SIOCGIFCONF, &ifc) < 0)
+	{
+	  if (ifc.ifc_buf)
+	    free (ifc.ifc_buf);
+
+	  if (fd != sockfd)
+	    __close (fd);
+
+	  *num_ifs = 0;
+	  *ifreqs = NULL;
+	  return;
+	}
+
+      if (!old_siocgifconf || ifc.ifc_len < rq_len)
+	break;
+
+      rq_len *= 2;
+    }
+
+  nifs = ifc.ifc_len / sizeof (struct ifreq);
+
+  if (fd != sockfd)
+    __close (fd);
+
+  *num_ifs = nifs;
+  *ifreqs = realloc (ifc.ifc_buf, nifs * sizeof (struct ifreq));
+}
diff --git a/sysdeps/unix/sysv/linux/ifreq.h b/sysdeps/unix/sysv/linux/ifreq.h
index f498e5c32a..9e4f6622e9 100644
--- a/sysdeps/unix/sysv/linux/ifreq.h
+++ b/sysdeps/unix/sysv/linux/ifreq.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1999,2002 Free Software Foundation, Inc.
+/* Copyright (C) 1999, 2002, 2003 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Andreas Jaeger <aj@suse.de>.
 
@@ -33,77 +33,7 @@ static int old_siocgifconf;
 #endif
 
 
-static inline void
-__ifreq (struct ifreq **ifreqs, int *num_ifs, int sockfd)
-{
-  int fd = sockfd;
-  struct ifconf ifc;
-  int rq_len;
-  int nifs;
-# define RQ_IFS	4
-
-  if (fd < 0)
-    fd = __opensock ();
-  if (fd < 0)
-    {
-      *num_ifs = 0;
-      *ifreqs = NULL;
-      return;
-    }
-
-  ifc.ifc_buf = NULL;
-
-  /* We may be able to get the needed buffer size directly, rather than
-     guessing.  */
-  if (! old_siocgifconf)
-    {
-      ifc.ifc_buf = NULL;
-      ifc.ifc_len = 0;
-      if (__ioctl (fd, SIOCGIFCONF, &ifc) < 0 || ifc.ifc_len == 0)
-	{
-# if __ASSUME_SIOCGIFNAME == 0
-	  old_siocgifconf = 1;
-# endif
-	  rq_len = RQ_IFS * sizeof (struct ifreq);
-	}
-      else
-	rq_len = ifc.ifc_len;
-    }
-  else
-    rq_len = RQ_IFS * sizeof (struct ifreq);
-
-  /* Read all the interfaces out of the kernel.  */
-  while (1)
-    {
-      ifc.ifc_len = rq_len;
-      ifc.ifc_buf = realloc (ifc.ifc_buf, ifc.ifc_len);
-      if (ifc.ifc_buf == NULL || __ioctl (fd, SIOCGIFCONF, &ifc) < 0)
-	{
-	  if (ifc.ifc_buf)
-	    free (ifc.ifc_buf);
-
-	  if (fd != sockfd)
-	    __close (fd);
-
-	  *num_ifs = 0;
-	  *ifreqs = NULL;
-	  return;
-	}
-
-      if (!old_siocgifconf || ifc.ifc_len < rq_len)
-	break;
-
-      rq_len *= 2;
-    }
-
-  nifs = ifc.ifc_len / sizeof (struct ifreq);
-
-  if (fd != sockfd)
-    __close (fd);
-
-  *num_ifs = nifs;
-  *ifreqs = realloc (ifc.ifc_buf, nifs * sizeof (struct ifreq));
-}
+extern void __ifreq (struct ifreq **ifreqs, int *num_ifs, int sockfd);
 
 static inline struct ifreq *
 __if_nextreq (struct ifreq *ifr)
diff --git a/sysdeps/unix/sysv/linux/lxstat.c b/sysdeps/unix/sysv/linux/lxstat.c
index ece1a85f30..156850330e 100644
--- a/sysdeps/unix/sysv/linux/lxstat.c
+++ b/sysdeps/unix/sysv/linux/lxstat.c
@@ -1,5 +1,5 @@
 /* lxstat using old-style Unix lstat system call.
-   Copyright (C) 1991,1995-1998,2000,2002 Free Software Foundation, Inc.
+   Copyright (C) 1991,1995-1998,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
@@ -30,7 +30,7 @@
 #include <sys/syscall.h>
 #include <bp-checks.h>
 
-#include <xstatconv.c>
+#include <xstatconv.h>
 
 extern int __syscall_lstat (const char *__unbounded,
 			    struct kernel_stat *__unbounded);
@@ -52,7 +52,7 @@ __lxstat (int vers, const char *name, struct stat *buf)
 
   result = INLINE_SYSCALL (lstat, 2, CHECK_STRING (name), __ptrvalue (&kbuf));
   if (result == 0)
-    result = xstat_conv (vers, &kbuf, buf);
+    result = __xstat_conv (vers, &kbuf, buf);
 
   return result;
 #endif
diff --git a/sysdeps/unix/sysv/linux/lxstat64.c b/sysdeps/unix/sysv/linux/lxstat64.c
index e7f488848c..58ff6fff61 100644
--- a/sysdeps/unix/sysv/linux/lxstat64.c
+++ b/sysdeps/unix/sysv/linux/lxstat64.c
@@ -1,5 +1,5 @@
 /* lxstat64 using old-style Unix lstat system call.
-   Copyright (C) 1997,1998,1999,2000,2001,2002 Free Software Foundation, Inc.
+   Copyright (C) 1997-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
@@ -29,7 +29,7 @@
 #include "kernel-features.h"
 
 #if __ASSUME_STAT64_SYSCALL == 0
-# include <xstatconv.c>
+# include <xstatconv.h>
 #endif
 
 extern int __syscall_lstat (const char *__unbounded,
@@ -79,7 +79,7 @@ ___lxstat64 (int vers, const char *name, struct stat64 *buf)
 # endif
   result = INLINE_SYSCALL (lstat, 2, CHECK_STRING (name), __ptrvalue (&kbuf));
   if (result == 0)
-    result = xstat64_conv (vers, &kbuf, buf);
+    result = __xstat64_conv (vers, &kbuf, buf);
 
   return result;
 #endif
diff --git a/sysdeps/unix/sysv/linux/pathconf.c b/sysdeps/unix/sysv/linux/pathconf.c
index b4886158f3..d4159753a6 100644
--- a/sysdeps/unix/sysv/linux/pathconf.c
+++ b/sysdeps/unix/sysv/linux/pathconf.c
@@ -17,7 +17,10 @@
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
 
+#include <unistd.h>
+#include <errno.h>
 #include "pathconf.h"
+#include "linux_fsinfo.h"
 
 static long int posix_pathconf (const char *file, int name);
 
@@ -35,15 +38,143 @@ __pathconf (const char *file, int name)
   switch (name)
     {
     case _PC_LINK_MAX:
-      return statfs_link_max (__statfs (file, &fsbuf), &fsbuf);
+      return __statfs_link_max (__statfs (file, &fsbuf), &fsbuf);
 
     case _PC_FILESIZEBITS:
-      return statfs_filesize_max (__statfs (file, &fsbuf), &fsbuf);
+      return __statfs_filesize_max (__statfs (file, &fsbuf), &fsbuf);
 
     case _PC_2_SYMLINKS:
-      return statfs_symlinks (__statfs (file, &fsbuf), &fsbuf);
+      return __statfs_symlinks (__statfs (file, &fsbuf), &fsbuf);
 
     default:
       return posix_pathconf (file, name);
     }
 }
+
+
+/* Used like: return statfs_link_max (__statfs (name, &buf), &buf); */
+long int
+__statfs_link_max (int result, const struct statfs *fsbuf)
+{
+  if (result < 0)
+    {
+      if (errno == ENOSYS)
+	/* Not possible, return the default value.  */
+	return LINUX_LINK_MAX;
+
+      /* Some error occured.  */
+      return -1;
+    }
+
+  switch (fsbuf->f_type)
+    {
+    case EXT2_SUPER_MAGIC:
+      return EXT2_LINK_MAX;
+
+    case MINIX_SUPER_MAGIC:
+    case MINIX_SUPER_MAGIC2:
+      return MINIX_LINK_MAX;
+
+    case MINIX2_SUPER_MAGIC:
+    case MINIX2_SUPER_MAGIC2:
+      return MINIX2_LINK_MAX;
+
+    case XENIX_SUPER_MAGIC:
+      return XENIX_LINK_MAX;
+
+    case SYSV4_SUPER_MAGIC:
+    case SYSV2_SUPER_MAGIC:
+      return SYSV_LINK_MAX;
+
+    case COH_SUPER_MAGIC:
+      return COH_LINK_MAX;
+
+    case UFS_MAGIC:
+    case UFS_CIGAM:
+      return UFS_LINK_MAX;
+
+    case REISERFS_SUPER_MAGIC:
+      return REISERFS_LINK_MAX;
+
+    case XFS_SUPER_MAGIC:
+      return XFS_LINK_MAX;
+
+    default:
+      return LINUX_LINK_MAX;
+    }
+}
+
+
+/* Used like: return statfs_filesize_max (__statfs (name, &buf), &buf); */
+long int
+__statfs_filesize_max (int result, const struct statfs *fsbuf)
+{
+  if (result < 0)
+    {
+      if (errno == ENOSYS)
+	/* Not possible, return the default value.  */
+	return 32;
+
+      /* Some error occured.  */
+      return -1;
+    }
+
+  switch (fsbuf->f_type)
+    {
+    case EXT2_SUPER_MAGIC:
+    case UFS_MAGIC:
+    case UFS_CIGAM:
+    case REISERFS_SUPER_MAGIC:
+    case XFS_SUPER_MAGIC:
+    case SMB_SUPER_MAGIC:
+    case NTFS_SUPER_MAGIC:
+    case UDF_SUPER_MAGIC:
+    case JFS_SUPER_MAGIC:
+      return 64;
+
+    case MSDOS_SUPER_MAGIC:
+    case JFFS_SUPER_MAGIC:
+    case JFFS2_SUPER_MAGIC:
+    case NCP_SUPER_MAGIC:
+    case ROMFS_SUPER_MAGIC:
+      return 32;
+
+    default:
+      return 32;
+    }
+}
+
+
+/* Used like: return statfs_link_max (__statfs (name, &buf), &buf); */
+long int
+__statfs_symlinks (int result, const struct statfs *fsbuf)
+{
+  if (result < 0)
+    {
+      if (errno == ENOSYS)
+	/* Not possible, return the default value.  */
+	return 1;
+
+      /* Some error occured.  */
+      return -1;
+    }
+
+  switch (fsbuf->f_type)
+    {
+    case ADFS_SUPER_MAGIC:
+    case BFS_MAGIC:
+    case CRAMFS_MAGIC:
+    case DEVPTS_SUPER_MAGIC:
+    case EFS_SUPER_MAGIC:
+    case EFS_MAGIC:
+    case MSDOS_SUPER_MAGIC:
+    case NTFS_SUPER_MAGIC:
+    case QNX4_SUPER_MAGIC:
+    case ROMFS_SUPER_MAGIC:
+      /* No symlink support.  */
+      return 0;
+
+    default:
+      return 1;
+    }
+}
diff --git a/sysdeps/unix/sysv/linux/pathconf.h b/sysdeps/unix/sysv/linux/pathconf.h
index 80ec8fa4e0..20e23685eb 100644
--- a/sysdeps/unix/sysv/linux/pathconf.h
+++ b/sysdeps/unix/sysv/linux/pathconf.h
@@ -17,135 +17,18 @@
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
 
-#include <unistd.h>
 #include <errno.h>
+#include <unistd.h>
 #include <sys/statfs.h>
-#include "linux_fsinfo.h"
 
 
 /* Used like: return statfs_link_max (__statfs (name, &buf), &buf); */
-static inline long int
-statfs_link_max (int result, const struct statfs *fsbuf)
-{
-  if (result < 0)
-    {
-      if (errno == ENOSYS)
-	/* Not possible, return the default value.  */
-	return LINUX_LINK_MAX;
-
-      /* Some error occured.  */
-      return -1;
-    }
-
-  switch (fsbuf->f_type)
-    {
-    case EXT2_SUPER_MAGIC:
-      return EXT2_LINK_MAX;
-
-    case MINIX_SUPER_MAGIC:
-    case MINIX_SUPER_MAGIC2:
-      return MINIX_LINK_MAX;
-
-    case MINIX2_SUPER_MAGIC:
-    case MINIX2_SUPER_MAGIC2:
-      return MINIX2_LINK_MAX;
-
-    case XENIX_SUPER_MAGIC:
-      return XENIX_LINK_MAX;
-
-    case SYSV4_SUPER_MAGIC:
-    case SYSV2_SUPER_MAGIC:
-      return SYSV_LINK_MAX;
-
-    case COH_SUPER_MAGIC:
-      return COH_LINK_MAX;
-
-    case UFS_MAGIC:
-    case UFS_CIGAM:
-      return UFS_LINK_MAX;
-
-    case REISERFS_SUPER_MAGIC:
-      return REISERFS_LINK_MAX;
-
-    case XFS_SUPER_MAGIC:
-      return XFS_LINK_MAX;
-
-    default:
-      return LINUX_LINK_MAX;
-    }
-}
+extern long int __statfs_link_max (int result, const struct statfs *fsbuf);
 
 
 /* Used like: return statfs_filesize_max (__statfs (name, &buf), &buf); */
-static inline long int
-statfs_filesize_max (int result, const struct statfs *fsbuf)
-{
-  if (result < 0)
-    {
-      if (errno == ENOSYS)
-	/* Not possible, return the default value.  */
-	return 32;
-
-      /* Some error occured.  */
-      return -1;
-    }
-
-  switch (fsbuf->f_type)
-    {
-    case EXT2_SUPER_MAGIC:
-    case UFS_MAGIC:
-    case UFS_CIGAM:
-    case REISERFS_SUPER_MAGIC:
-    case XFS_SUPER_MAGIC:
-    case SMB_SUPER_MAGIC:
-    case NTFS_SUPER_MAGIC:
-    case UDF_SUPER_MAGIC:
-    case JFS_SUPER_MAGIC:
-      return 64;
-
-    case MSDOS_SUPER_MAGIC:
-    case JFFS_SUPER_MAGIC:
-    case JFFS2_SUPER_MAGIC:
-    case NCP_SUPER_MAGIC:
-    case ROMFS_SUPER_MAGIC:
-      return 32;
-
-    default:
-      return 32;
-    }
-}
+extern long int __statfs_filesize_max (int result, const struct statfs *fsbuf);
 
 
 /* Used like: return statfs_link_max (__statfs (name, &buf), &buf); */
-static inline long int
-statfs_symlinks (int result, const struct statfs *fsbuf)
-{
-  if (result < 0)
-    {
-      if (errno == ENOSYS)
-	/* Not possible, return the default value.  */
-	return 1;
-
-      /* Some error occured.  */
-      return -1;
-    }
-
-  switch (fsbuf->f_type)
-    {
-    case ADFS_SUPER_MAGIC:
-    case BFS_MAGIC:
-    case CRAMFS_MAGIC:
-    case DEVPTS_SUPER_MAGIC:
-    case EFS_SUPER_MAGIC:
-    case EFS_MAGIC:
-    case MSDOS_SUPER_MAGIC:
-    case NTFS_SUPER_MAGIC:
-    case QNX4_SUPER_MAGIC:
-    case ROMFS_SUPER_MAGIC:
-      /* No symlink support.  */
-      return 0;
-
-    default:
-      return 1;
-    }
-}
+extern long int __statfs_symlinks (int result, const struct statfs *fsbuf);
diff --git a/sysdeps/unix/sysv/linux/xstat.c b/sysdeps/unix/sysv/linux/xstat.c
index 05e170d17c..de6a57d7ac 100644
--- a/sysdeps/unix/sysv/linux/xstat.c
+++ b/sysdeps/unix/sysv/linux/xstat.c
@@ -1,6 +1,5 @@
 /* xstat using old-style Unix stat system call.
-   Copyright (C) 1991, 1995, 1996, 1997, 1998, 2000, 2002
-   Free Software Foundation, Inc.
+   Copyright (C) 1991,1995-1998,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
@@ -31,7 +30,7 @@
 #include <sys/syscall.h>
 #include <bp-checks.h>
 
-#include <xstatconv.c>
+#include <xstatconv.h>
 
 extern int __syscall_stat (const char *__unbounded,
 			   struct kernel_stat *__unbounded);
@@ -54,7 +53,7 @@ __xstat (int vers, const char *name, struct stat *buf)
   result = INLINE_SYSCALL (stat, 2, CHECK_STRING (name),
 			   __ptrvalue (&kbuf));
   if (result == 0)
-    result = xstat_conv (vers, &kbuf, buf);
+    result = __xstat_conv (vers, &kbuf, buf);
 
   return result;
 #endif
diff --git a/sysdeps/unix/sysv/linux/xstat64.c b/sysdeps/unix/sysv/linux/xstat64.c
index 7835fc2050..803aeb3104 100644
--- a/sysdeps/unix/sysv/linux/xstat64.c
+++ b/sysdeps/unix/sysv/linux/xstat64.c
@@ -1,5 +1,5 @@
 /* xstat64 using old-style Unix stat system call.
-   Copyright (C) 1991,95,96,97,98,99,2000,01,02 Free Software Foundation, Inc.
+   Copyright (C) 1991, 1995-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
@@ -29,7 +29,7 @@
 #include "kernel-features.h"
 
 #if __ASSUME_STAT64_SYSCALL == 0
-# include <xstatconv.c>
+# include <xstatconv.h>
 #endif
 
 extern int __syscall_stat (const char *__unbounded,
@@ -82,7 +82,7 @@ ___xstat64 (int vers, const char *name, struct stat64 *buf)
 
   result = INLINE_SYSCALL (stat, 2, CHECK_STRING (name), __ptrvalue (&kbuf));
   if (result == 0)
-    result = xstat64_conv (vers, &kbuf, buf);
+    result = __xstat64_conv (vers, &kbuf, buf);
 
   return result;
 #endif
diff --git a/sysdeps/unix/sysv/linux/xstatconv.c b/sysdeps/unix/sysv/linux/xstatconv.c
index 6253292e93..4e4defb489 100644
--- a/sysdeps/unix/sysv/linux/xstatconv.c
+++ b/sysdeps/unix/sysv/linux/xstatconv.c
@@ -1,5 +1,5 @@
 /* Convert between the kernel's `struct stat' format, and libc's.
-   Copyright (C) 1991,1995,1996,1997,2000,2002 Free Software Foundation, Inc.
+   Copyright (C) 1991,1995-1997,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
@@ -17,6 +17,10 @@
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
 
+#include <errno.h>
+#include <sys/stat.h>
+#include <kernel_stat.h>
+
 #ifdef STAT_IS_KERNEL_STAT
 
 /* Dummy.  */
@@ -27,8 +31,9 @@ struct kernel_stat;
 #include <string.h>
 
 
-static inline int
-xstat_conv (int vers, struct kernel_stat *kbuf, void *ubuf)
+#ifndef __ASSUME_STAT64_SYSCALL
+int
+__xstat_conv (int vers, struct kernel_stat *kbuf, void *ubuf)
 {
   switch (vers)
     {
@@ -97,9 +102,10 @@ xstat_conv (int vers, struct kernel_stat *kbuf, void *ubuf)
 
   return 0;
 }
+#endif
 
-static inline int
-xstat64_conv (int vers, struct kernel_stat *kbuf, void *ubuf)
+int
+__xstat64_conv (int vers, struct kernel_stat *kbuf, void *ubuf)
 {
 #ifdef XSTAT_IS_XSTAT64
   return xstat_conv (vers, kbuf, ubuf);
@@ -172,8 +178,8 @@ xstat64_conv (int vers, struct kernel_stat *kbuf, void *ubuf)
 #endif
 }
 
-static inline int
-xstat32_conv (int vers, struct stat64 *kbuf, struct stat *buf)
+int
+__xstat32_conv (int vers, struct stat64 *kbuf, struct stat *buf)
 {
   switch (vers)
     {
diff --git a/sysdeps/unix/sysv/linux/xstatconv.h b/sysdeps/unix/sysv/linux/xstatconv.h
new file mode 100644
index 0000000000..cb5cda0326
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/xstatconv.h
@@ -0,0 +1,25 @@
+/* Convert between the kernel's `struct stat' format, and libc's.
+   Copyright (C) 1991,1995-1997,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
+   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 "kernel-features.h"
+
+
+extern int __xstat_conv (int vers, struct kernel_stat *kbuf, void *ubuf);
+extern int __xstat64_conv (int vers, struct kernel_stat *kbuf, void *ubuf);
+extern int __xstat32_conv (int vers, struct stat64 *kbuf, struct stat *buf);
diff --git a/time/tzfile.c b/time/tzfile.c
index 39b3c2f211..2d1775b05b 100644
--- a/time/tzfile.c
+++ b/time/tzfile.c
@@ -64,6 +64,7 @@ static struct leap *leaps;
 
 /* Decode the four bytes at PTR as a signed integer in network byte order.  */
 static inline int
+__attribute ((always_inline))
 decode (const void *ptr)
 {
   if ((BYTE_ORDER == BIG_ENDIAN) && sizeof (int) == 4)
@@ -154,7 +155,8 @@ __tzfile_read (const char *file, size_t extra, char **extrap)
   /* No threads reading this stream.  */
   __fsetlocking (f, FSETLOCKING_BYCALLER);
 
-  if (fread_unlocked ((void *) &tzhead, sizeof (tzhead), 1, f) != 1)
+  if (__builtin_expect (fread_unlocked ((void *) &tzhead, sizeof (tzhead),
+					1, f) != 1, 0))
     goto lose;
 
   num_transitions = (size_t) decode (tzhead.tzh_timecnt);
@@ -193,23 +195,24 @@ __tzfile_read (const char *file, size_t extra, char **extrap)
 
   if (sizeof (time_t) == 4)
     {
-      if (fread_unlocked (transitions, 1, (4 + 1) * num_transitions, f)
-	  != (4 + 1) * num_transitions)
+      if (__builtin_expect (fread_unlocked (transitions, 1,
+					    (4 + 1) * num_transitions, f)
+			    != (4 + 1) * num_transitions, 0))
 	goto lose;
     }
   else
     {
-      if (fread_unlocked (transitions, 4, num_transitions, f)
-	  != num_transitions
-	  || fread_unlocked (type_idxs, 1, num_transitions, f)
-	  != num_transitions)
+      if (__builtin_expect (fread_unlocked (transitions, 4, num_transitions, f)
+			    != num_transitions, 0)
+	  || __builtin_expect (fread_unlocked (type_idxs, 1, num_transitions,
+					       f) != num_transitions, 0))
 	goto lose;
     }
 
   /* Check for bogus indices in the data file, so we can hereafter
      safely use type_idxs[T] as indices into `types' and never crash.  */
   for (i = 0; i < num_transitions; ++i)
-    if (type_idxs[i] >= num_types)
+    if (__builtin_expect (type_idxs[i] >= num_types, 0))
       goto lose;
 
   if (BYTE_ORDER != BIG_ENDIAN || sizeof (time_t) != 4)
@@ -227,29 +230,33 @@ __tzfile_read (const char *file, size_t extra, char **extrap)
     {
       unsigned char x[4];
       int c;
-      if (fread_unlocked (x, 1, sizeof (x), f) != sizeof (x))
+      if (__builtin_expect (fread_unlocked (x, 1, sizeof (x), f) != sizeof (x),
+			    0))
 	goto lose;
       c = getc_unlocked (f);
-      if ((unsigned int) c > 1u)
+      if (__builtin_expect ((unsigned int) c > 1u, 0))
 	goto lose;
       types[i].isdst = c;
       c = getc_unlocked (f);
-      if ((size_t) c > chars) /* Bogus index in data file.  */
+      if (__builtin_expect ((size_t) c > chars, 0))
+	/* Bogus index in data file.  */
 	goto lose;
       types[i].idx = c;
       types[i].offset = (long int) decode (x);
     }
 
-  if (fread_unlocked (zone_names, 1, chars, f) != chars)
+  if (__builtin_expect (fread_unlocked (zone_names, 1, chars, f) != chars, 0))
     goto lose;
 
   for (i = 0; i < num_leaps; ++i)
     {
       unsigned char x[4];
-      if (fread_unlocked (x, 1, sizeof (x), f) != sizeof (x))
+      if (__builtin_expect (fread_unlocked (x, 1, sizeof (x), f) != sizeof (x),
+			    0))
 	goto lose;
       leaps[i].transition = (time_t) decode (x);
-      if (fread_unlocked (x, 1, sizeof (x), f) != sizeof (x))
+      if (__builtin_expect (fread_unlocked (x, 1, sizeof (x), f) != sizeof (x),
+			    0))
 	goto lose;
       leaps[i].change = (long int) decode (x);
     }
@@ -257,7 +264,7 @@ __tzfile_read (const char *file, size_t extra, char **extrap)
   for (i = 0; i < num_isstd; ++i)
     {
       int c = getc_unlocked (f);
-      if (c == EOF)
+      if (__builtin_expect (c == EOF, 0))
 	goto lose;
       types[i].isstd = c != 0;
     }
@@ -267,7 +274,7 @@ __tzfile_read (const char *file, size_t extra, char **extrap)
   for (i = 0; i < num_isgmt; ++i)
     {
       int c = getc_unlocked (f);
-      if (c == EOF)
+      if (__builtin_expect (c == EOF, 0))
 	goto lose;
       types[i].isgmt = c != 0;
     }
diff --git a/wcsmbs/wcsnrtombs.c b/wcsmbs/wcsnrtombs.c
index bb2ca1d08b..0ff26d6671 100644
--- a/wcsmbs/wcsnrtombs.c
+++ b/wcsmbs/wcsnrtombs.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1996,1997,1998,1999,2000,2002 Free Software Foundation, Inc.
+/* Copyright (C) 1996-2000, 2002, 2003 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@gnu.org>, 1996.
 
@@ -72,7 +72,7 @@ __wcsnrtombs (dst, src, nwc, len, ps)
   if (dst == NULL)
     {
       unsigned char buf[256];		/* Just an arbitrary value.  */
-      const wchar_t *inbuf = *src;
+      const unsigned char *inbuf = (const unsigned char *) *src;
       size_t dummy;
 
       result = 0;
@@ -83,7 +83,7 @@ __wcsnrtombs (dst, src, nwc, len, ps)
 	  data.__outbuf = buf;
 
 	  status = DL_CALL_FCT (tomb->__fct,
-				(tomb, &data, (const unsigned char **) &inbuf,
+				(tomb, &data, &inbuf,
 				 (const unsigned char *) srcend, NULL,
 				 &dummy, 0, 1));
 
diff --git a/wcsmbs/wcsrtombs.c b/wcsmbs/wcsrtombs.c
index dda115dfd3..8b444ed8a2 100644
--- a/wcsmbs/wcsrtombs.c
+++ b/wcsmbs/wcsrtombs.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1996,1997,1998,1999,2000,2002 Free Software Foundation, Inc.
+/* Copyright (C) 1996-2000, 2002, 2003 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@gnu.org>, 1996.
 
@@ -66,7 +66,7 @@ __wcsrtombs (dst, src, len, ps)
       mbstate_t temp_state;
       unsigned char buf[256];		/* Just an arbitrary value.  */
       const wchar_t *srcend = *src + __wcslen (*src) + 1;
-      const wchar_t *inbuf = *src;
+      const unsigned char *inbuf = (const unsigned char *) *src;
       size_t dummy;
 
       temp_state = *data.__statep;
@@ -80,7 +80,7 @@ __wcsrtombs (dst, src, len, ps)
 	  data.__outbuf = buf;
 
 	  status = DL_CALL_FCT (tomb->__fct,
-				(tomb, &data, (const unsigned char **) &inbuf,
+				(tomb, &data, &inbuf,
 				 (const unsigned char *) srcend, NULL,
 				 &dummy, 0, 1));
 
diff --git a/wcsmbs/wctob.c b/wcsmbs/wctob.c
index d053b9a28f..b85ba6dd8f 100644
--- a/wcsmbs/wctob.c
+++ b/wcsmbs/wctob.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1996,1997,1998,1999,2000,2002 Free Software Foundation, Inc.
+/* Copyright (C) 1996-2000, 2002, 2003 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1996.
 
@@ -58,11 +58,10 @@ wctob (c)
   /* Create the input string.  */
   inbuf[0] = c;
 
+  const unsigned char *argptr = (const unsigned char *) inptr;
   status = DL_CALL_FCT (fcts->tomb->__fct,
-			(fcts->tomb, &data,
-			 (const unsigned char **) &inptr,
-			 (const unsigned char *) &inbuf[1],
-			 NULL, &dummy, 0, 1));
+			(fcts->tomb, &data, &argptr,
+			 argptr + sizeof (inbuf[0]), NULL, &dummy, 0, 1));
 
   /* The conversion failed or the output is too long.  */
   if ((status != __GCONV_OK && status != __GCONV_FULL_OUTPUT