summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog59
-rw-r--r--intl/Makefile12
-rw-r--r--intl/bindtextdom.c6
-rw-r--r--intl/dcigettext.c21
-rw-r--r--intl/finddomain.c14
-rw-r--r--intl/gettextP.h16
-rw-r--r--intl/l10nflist.c7
-rw-r--r--intl/loadinfo.h9
-rw-r--r--intl/loadmsgcat.c232
-rw-r--r--intl/tst-codeset.c56
-rw-r--r--intl/tst-codeset.sh42
-rw-r--r--intl/tstcodeset.po8
-rw-r--r--libio/freopen.c16
-rw-r--r--libio/freopen64.c17
-rw-r--r--locale/findlocale.c4
-rw-r--r--manual/stdio.texi2
-rw-r--r--misc/error.c14
-rw-r--r--sysdeps/generic/fd_to_filename.h26
-rw-r--r--sysdeps/sparc/sparc32/sparcv9/Makefile4
-rw-r--r--sysdeps/sparc/sparc32/sparcv9/hp-timing.c24
-rw-r--r--sysdeps/sparc/sparc32/sparcv9/hp-timing.h89
-rw-r--r--sysdeps/sparc/sparc64/Makefile4
-rw-r--r--sysdeps/sparc/sparc64/hp-timing.c24
-rw-r--r--sysdeps/sparc/sparc64/hp-timing.h84
-rw-r--r--sysdeps/unix/sysv/linux/fd_to_filename.h46
25 files changed, 703 insertions, 133 deletions
diff --git a/ChangeLog b/ChangeLog
index 6c1f55be36..525d1aa9d7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,62 @@
+2001-04-05 David S. Miller <davem@redhat.com>
+
+ Add hp-timing support for sparcv9/sparc64 targets.
+ * sysdeps/sparc/sparc32/sparcv9/hp-timing.c: New file
+ * sysdeps/sparc/sparc32/sparcv9/hp-timing.h: New file
+ * sysdeps/sparc/sparc64/hp-timing.c: New file
+ * sysdeps/sparc/sparc64/hp-timing.h: New file
+ * sysdeps/sparc/sparc32/sparcv9/Makefile: Build hp-timing.
+ * sysdeps/sparc/sparc64/Makefile: Likewise.
+
+2001-04-09 Jakub Jelinek <jakub@redhat.com>
+
+ * sysdeps/generic/fd_to_filename.h: New file.
+ * sysdeps/unix/sysv/linux/fd_to_filename.h: New file.
+ * libio/freopen.c (freopen): If FILENAME is NULL, try to get
+ filename from the open file descriptor.
+ * libio/freopen64.c (freopen64): Likewise.
+
+2001-04-09 Bruno Haible <haible@clisp.cons.org>
+
+ * misc/error.c (error): fflush stdout also if
+ error_print_progname != NULL.
+ (error_at_line): Likewise.
+
+2001-04-07 Bruno Haible <haible@clisp.cons.org>
+
+ * intl/gettextP.h (struct loaded_domain): Add codeset_cntr field.
+ (struct binding): Add codeset_cntr field.
+ (_nl_load_domain): Add domainbinding argument.
+ (_nl_init_domain_conv, _nl_free_domain_conv): New declarations.
+ (_nl_find_msg): New declaration, moved here from loadinfo.h.
+ * intl/loadinfo.h (struct loaded_l10nfile): Remove domainbinding field.
+ (_nl_make_l10nflist): Remove domainbinding argument.
+ (_nl_find_msg): Move declaration to gettextP.h.
+ * intl/bindtextdom.c (set_binding_values): Initialize ->codeset_cntr
+ to 0. Increment it when ->codeset is changed.
+ * intl/dcigettext.c (DCIGETTEXT): Pass binding to _nl_find_msg.
+ (_nl_find_msg): Add domainbinding argument. Reinitialize the converter
+ if domainbinding->codeset_cntr has been incremented.
+ * intl/finddomain.c (_nl_find_domain): Don't pass domainbinding to
+ _nl_make_l10nflist(). Pass it to _nl_load_domain() instead.
+ * intl/l10nflist.c (_nl_make_l10nflist): Remove domainbinding argument.
+ * intl/loadmsgcat.c (_nl_init_domain_conv): New function, extracted
+ from _nl_load_domain. Append //TRANSLIT also when using libiconv.
+ (_nl_free_domain_conv): New function, extracted from _nl_unload_domain.
+ (_nl_load_domain): Add domainbinding argument. Call
+ _nl_init_domain_conv.
+ (_nl_unload_domain): Call _nl_free_domain_conv.
+ * intl/Makefile (distribute): Add tst-codeset.sh, tstcodeset.po.
+ (test-srcs): Add tst-codeset.
+ (tests): Depend on tst-codeset.out.
+ (tst-codeset.out): New rule.
+ (CFLAGS-tst-codeset.c): New variable.
+ * intl/tst-codeset.sh: New file.
+ * intl/tstcodeset.po: New file.
+ * intl/tst-codeset.c: New file.
+ * locale/findlocale.c (_nl_find_locale): Update _nl_make_l10nflist
+ calls.
+
2001-04-07 Roland McGrath <roland@frob.com>
* mach/msgserver.c (__mach_msg_server_timeout): Add an assert.
diff --git a/intl/Makefile b/intl/Makefile
index fc428c60fe..86ac97fd87 100644
--- a/intl/Makefile
+++ b/intl/Makefile
@@ -25,10 +25,10 @@ routines = bindtextdom dcgettext dgettext gettext \
finddomain loadmsgcat localealias textdomain \
l10nflist explodename plural
distribute = gettext.h gettextP.h hash-string.h loadinfo.h locale.alias \
- plural.y po2test.sed tst-gettext.sh tst-translit.sh \
- translit.po tst-gettext2.sh tstlang1.po tstlang2.po
+ plural.y po2test.sed tst-gettext.sh tst-translit.sh tst-codeset.sh \
+ translit.po tst-gettext2.sh tstlang1.po tstlang2.po tstcodeset.po
-test-srcs := tst-gettext tst-translit tst-gettext2
+test-srcs := tst-gettext tst-translit tst-gettext2 tst-codeset
tests = tst-ngettext
before-compile = $(objpfx)msgs.h
@@ -54,7 +54,8 @@ include ../Rules
ifeq (no,$(cross-compiling))
ifeq (yes,$(build-shared))
ifneq ($(strip $(MSGFMT)),:)
-tests: $(objpfx)tst-translit.out $(objpfx)tst-gettext2.out
+tests: $(objpfx)tst-translit.out $(objpfx)tst-gettext2.out \
+ $(objpfx)tst-codeset.out
endif
ifneq (no,$(PERL))
tests: $(objpfx)mtrace-tst-gettext
@@ -68,6 +69,8 @@ $(objpfx)tst-translit.out: tst-translit.sh $(objpfx)tst-translit
$(SHELL) -e $< $(common-objpfx) $(common-objpfx)intl/
$(objpfx)tst-gettext2.out: tst-gettext2.sh $(objpfx)tst-gettext2
$(SHELL) -e $< $(common-objpfx) $(common-objpfx)intl/
+$(objpfx)tst-codeset.out: tst-codeset.sh $(objpfx)tst-codeset
+ $(SHELL) -e $< $(common-objpfx) $(common-objpfx)intl/
endif
endif
@@ -78,6 +81,7 @@ $(objpfx)msgs.h: po2test.sed ../po/de.po
CFLAGS-tst-gettext.c = -DTESTSTRS_H=\"$(objpfx)msgs.h\"
CFLAGS-tst-gettext2.c = -DOBJPFX=\"$(objpfx)\"
CFLAGS-tst-translit.c = -DOBJPFX=\"$(objpfx)\"
+CFLAGS-tst-codeset.c = -DOBJPFX=\"$(objpfx)\"
$(objpfx)tst-translit.out: $(objpfx)tst-gettext.out
diff --git a/intl/bindtextdom.c b/intl/bindtextdom.c
index 1b22bfc648..b1b1d87fa3 100644
--- a/intl/bindtextdom.c
+++ b/intl/bindtextdom.c
@@ -100,7 +100,7 @@ __libc_rwlock_define (extern, _nl_state_lock)
static void set_binding_values PARAMS ((const char *domainname,
const char **dirnamep,
const char **codesetp));
-
+
/* Specifies the directory name *DIRNAMEP and the output codeset *CODESETP
to be used for the DOMAINNAME message catalog.
If *DIRNAMEP or *CODESETP is NULL, the corresponding attribute is not
@@ -218,6 +218,7 @@ set_binding_values (domainname, dirnamep, codesetp)
free (binding->codeset);
binding->codeset = result;
+ ++binding->codeset_cntr;
modified = 1;
}
}
@@ -281,6 +282,8 @@ set_binding_values (domainname, dirnamep, codesetp)
/* The default value. */
new_binding->dirname = (char *) _nl_default_dirname;
+ new_binding->codeset_cntr = 0;
+
if (codesetp)
{
const char *codeset = *codesetp;
@@ -301,6 +304,7 @@ set_binding_values (domainname, dirnamep, codesetp)
memcpy (result, codeset, len);
#endif
codeset = result;
+ ++new_binding->codeset_cntr;
}
*codesetp = codeset;
new_binding->codeset = (char *) codeset;
diff --git a/intl/dcigettext.c b/intl/dcigettext.c
index dcdc93c25d..944983decc 100644
--- a/intl/dcigettext.c
+++ b/intl/dcigettext.c
@@ -574,7 +574,7 @@ DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
if (domain != NULL)
{
- retval = _nl_find_msg (domain, msgid1, &retlen);
+ retval = _nl_find_msg (domain, binding, msgid1, &retlen);
if (retval == NULL)
{
@@ -582,8 +582,8 @@ DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
for (cnt = 0; domain->successor[cnt] != NULL; ++cnt)
{
- retval = _nl_find_msg (domain->successor[cnt], msgid1,
- &retlen);
+ retval = _nl_find_msg (domain->successor[cnt], binding,
+ msgid1, &retlen);
if (retval != NULL)
{
@@ -652,8 +652,9 @@ DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
char *
internal_function
-_nl_find_msg (domain_file, msgid, lengthp)
+_nl_find_msg (domain_file, domainbinding, msgid, lengthp)
struct loaded_l10nfile *domain_file;
+ struct binding *domainbinding;
const char *msgid;
size_t *lengthp;
{
@@ -663,7 +664,7 @@ _nl_find_msg (domain_file, msgid, lengthp)
size_t resultlen;
if (domain_file->decided == 0)
- _nl_load_domain (domain_file);
+ _nl_load_domain (domain_file, domainbinding);
if (domain_file->data == NULL)
return NULL;
@@ -742,6 +743,16 @@ _nl_find_msg (domain_file, msgid, lengthp)
resultlen = W (domain->must_swap, domain->trans_tab[act].length) + 1;
#if defined _LIBC || HAVE_ICONV
+ if (domain->codeset_cntr
+ != (domainbinding != NULL ? domainbinding->codeset_cntr : 0))
+ {
+ /* The domain's codeset has changed through bind_textdomain_codeset()
+ since the message catalog was initialized or last accessed. We
+ have to reinitialize the converter. */
+ _nl_free_domain_conv (domain);
+ _nl_init_domain_conv (domain_file, domain, domainbinding);
+ }
+
if (
# ifdef _LIBC
domain->conv != (__gconv_t) -1
diff --git a/intl/finddomain.c b/intl/finddomain.c
index cc82391d17..29bbcf9580 100644
--- a/intl/finddomain.c
+++ b/intl/finddomain.c
@@ -107,15 +107,14 @@ _nl_find_domain (dirname, locale, domainname, domainbinding)
be one data set in the list of loaded domains. */
retval = _nl_make_l10nflist (&_nl_loaded_domains, dirname,
strlen (dirname) + 1, 0, locale, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, domainname,
- domainbinding, 0);
+ NULL, NULL, NULL, NULL, NULL, domainname, 0);
if (retval != NULL)
{
/* We know something about this locale. */
int cnt;
if (retval->decided == 0)
- _nl_load_domain (retval);
+ _nl_load_domain (retval, domainbinding);
if (retval->data != NULL)
return retval;
@@ -123,7 +122,7 @@ _nl_find_domain (dirname, locale, domainname, domainbinding)
for (cnt = 0; retval->successor[cnt] != NULL; ++cnt)
{
if (retval->successor[cnt]->decided == 0)
- _nl_load_domain (retval->successor[cnt]);
+ _nl_load_domain (retval->successor[cnt], domainbinding);
if (retval->successor[cnt]->data != NULL)
break;
@@ -164,21 +163,20 @@ _nl_find_domain (dirname, locale, domainname, domainbinding)
retval = _nl_make_l10nflist (&_nl_loaded_domains, dirname,
strlen (dirname) + 1, mask, language, territory,
codeset, normalized_codeset, modifier, special,
- sponsor, revision, domainname, domainbinding,
- 1);
+ sponsor, revision, domainname, 1);
if (retval == NULL)
/* This means we are out of core. */
return NULL;
if (retval->decided == 0)
- _nl_load_domain (retval);
+ _nl_load_domain (retval, domainbinding);
if (retval->data == NULL)
{
int cnt;
for (cnt = 0; retval->successor[cnt] != NULL; ++cnt)
{
if (retval->successor[cnt]->decided == 0)
- _nl_load_domain (retval->successor[cnt]);
+ _nl_load_domain (retval->successor[cnt], domainbinding);
if (retval->successor[cnt]->data != NULL)
break;
}
diff --git a/intl/gettextP.h b/intl/gettextP.h
index ef29e1e03b..1d6eac7e36 100644
--- a/intl/gettextP.h
+++ b/intl/gettextP.h
@@ -131,6 +131,7 @@ struct loaded_domain
struct string_desc *trans_tab;
nls_uint32 hash_size;
nls_uint32 *hash_tab;
+ int codeset_cntr;
#ifdef _LIBC
__gconv_t conv;
#else
@@ -158,6 +159,7 @@ struct binding
{
struct binding *next;
char *dirname;
+ int codeset_cntr; /* Incremented each time codeset changes. */
char *codeset;
char domainname[ZERO];
};
@@ -172,10 +174,22 @@ struct loaded_l10nfile *_nl_find_domain PARAMS ((const char *__dirname,
const char *__domainname,
struct binding *__domainbinding))
internal_function;
-void _nl_load_domain PARAMS ((struct loaded_l10nfile *__domain))
+void _nl_load_domain PARAMS ((struct loaded_l10nfile *__domain,
+ struct binding *__domainbinding))
internal_function;
void _nl_unload_domain PARAMS ((struct loaded_domain *__domain))
internal_function;
+const char *_nl_init_domain_conv PARAMS ((struct loaded_l10nfile *__domain_file,
+ struct loaded_domain *__domain,
+ struct binding *__domainbinding))
+ internal_function;
+void _nl_free_domain_conv PARAMS ((struct loaded_domain *__domain))
+ internal_function;
+
+char *_nl_find_msg PARAMS ((struct loaded_l10nfile *domain_file,
+ struct binding *domainbinding,
+ const char *msgid, size_t *lengthp))
+ internal_function;
#ifdef _LIBC
extern char *__gettext PARAMS ((const char *__msgid));
diff --git a/intl/l10nflist.c b/intl/l10nflist.c
index 9b81a8f2ca..fd3c23cd07 100644
--- a/intl/l10nflist.c
+++ b/intl/l10nflist.c
@@ -175,7 +175,7 @@ pop (x)
struct loaded_l10nfile *
_nl_make_l10nflist (l10nfile_list, dirlist, dirlist_len, mask, language,
territory, codeset, normalized_codeset, modifier, special,
- sponsor, revision, filename, domainbinding, do_allocate)
+ sponsor, revision, filename, do_allocate)
struct loaded_l10nfile **l10nfile_list;
const char *dirlist;
size_t dirlist_len;
@@ -189,7 +189,6 @@ _nl_make_l10nflist (l10nfile_list, dirlist, dirlist_len, mask, language,
const char *sponsor;
const char *revision;
const char *filename;
- struct binding *domainbinding;
int do_allocate;
{
char *abs_filename;
@@ -310,7 +309,6 @@ _nl_make_l10nflist (l10nfile_list, dirlist, dirlist_len, mask, language,
return NULL;
retval->filename = abs_filename;
- retval->domainbinding = domainbinding;
retval->decided = (__argz_count (dirlist, dirlist_len) != 1
|| ((mask & XPG_CODESET) != 0
&& (mask & XPG_NORM_CODESET) != 0));
@@ -346,8 +344,7 @@ _nl_make_l10nflist (l10nfile_list, dirlist, dirlist_len, mask, language,
= _nl_make_l10nflist (l10nfile_list, dir, strlen (dir) + 1, cnt,
language, territory, codeset,
normalized_codeset, modifier, special,
- sponsor, revision, filename, domainbinding,
- 1);
+ sponsor, revision, filename, 1);
}
retval->successor[entries] = NULL;
diff --git a/intl/loadinfo.h b/intl/loadinfo.h
index a48433e4e9..7e682c9493 100644
--- a/intl/loadinfo.h
+++ b/intl/loadinfo.h
@@ -55,7 +55,6 @@
struct loaded_l10nfile
{
const char *filename;
- struct binding *domainbinding;
int decided;
const void *data;
@@ -80,8 +79,7 @@ _nl_make_l10nflist PARAMS ((struct loaded_l10nfile **l10nfile_list,
const char *normalized_codeset,
const char *modifier, const char *special,
const char *sponsor, const char *revision,
- const char *filename,
- struct binding *domainbinding, int do_allocate));
+ const char *filename, int do_allocate));
extern const char *_nl_expand_alias PARAMS ((const char *name));
@@ -99,9 +97,4 @@ extern int _nl_explode_name PARAMS ((char *name, const char **language,
extern char *_nl_find_language PARAMS ((const char *name));
-
-extern char *_nl_find_msg PARAMS ((struct loaded_l10nfile *domain_file,
- const char *msgid, size_t *lengthp))
- internal_function;
-
#endif /* loadinfo.h */
diff --git a/intl/loadmsgcat.c b/intl/loadmsgcat.c
index 660dc7b6ed..b7b237bc70 100644
--- a/intl/loadmsgcat.c
+++ b/intl/loadmsgcat.c
@@ -190,12 +190,146 @@ init_germanic_plural ()
#endif
+/* Initialize the codeset dependent parts of an opened message catalog.
+ Return the header entry. */
+const char *
+internal_function
+_nl_init_domain_conv (domain_file, domain, domainbinding)
+ struct loaded_l10nfile *domain_file;
+ struct loaded_domain *domain;
+ struct binding *domainbinding;
+{
+ /* Find out about the character set the file is encoded with.
+ This can be found (in textual form) in the entry "". If this
+ entry does not exist or if this does not contain the `charset='
+ information, we will assume the charset matches the one the
+ current locale and we don't have to perform any conversion. */
+ char *nullentry;
+ size_t nullentrylen;
+
+ /* Preinitialize fields, to avoid recursion during _nl_find_msg. */
+ domain->codeset_cntr =
+ (domainbinding != NULL ? domainbinding->codeset_cntr : 0);
+#ifdef _LIBC
+ domain->conv = (__gconv_t) -1;
+#else
+# if HAVE_ICONV
+ domain->conv = (iconv_t) -1;
+# endif
+#endif
+ domain->conv_tab = NULL;
+
+ /* Get the header entry. */
+ nullentry = _nl_find_msg (domain_file, domainbinding, "", &nullentrylen);
+
+ if (nullentry != NULL)
+ {
+#if defined _LIBC || HAVE_ICONV
+ const char *charsetstr;
+
+ charsetstr = strstr (nullentry, "charset=");
+ if (charsetstr != NULL)
+ {
+ size_t len;
+ char *charset;
+ const char *outcharset;
+
+ charsetstr += strlen ("charset=");
+ len = strcspn (charsetstr, " \t\n");
+
+ charset = (char *) alloca (len + 1);
+# if defined _LIBC || HAVE_MEMPCPY
+ *((char *) mempcpy (charset, charsetstr, len)) = '\0';
+# else
+ memcpy (charset, charsetstr, len);
+ charset[len] = '\0';
+# endif
+
+ /* The output charset should normally be determined by the
+ locale. But sometimes the locale is not used or not correctly
+ set up, so we provide a possibility for the user to override
+ this. Moreover, the value specified through
+ bind_textdomain_codeset overrides both. */
+ if (domainbinding != NULL && domainbinding->codeset != NULL)
+ outcharset = domainbinding->codeset;
+ else
+ {
+ outcharset = getenv ("OUTPUT_CHARSET");
+ if (outcharset == NULL || outcharset[0] == '\0')
+ {
+# ifdef _LIBC
+ outcharset = (*_nl_current[LC_CTYPE])->values[_NL_ITEM_INDEX (CODESET)].string;
+# else
+# if HAVE_ICONV
+ extern const char *locale_charset (void);
+ outcharset = locale_charset ();
+# endif
+# endif
+ }
+ }
+
+# ifdef _LIBC
+ /* We always want to use transliteration. */
+ outcharset = norm_add_slashes (outcharset, "TRANSLIT");
+ charset = norm_add_slashes (charset, NULL);
+ if (__gconv_open (outcharset, charset, &domain->conv,
+ GCONV_AVOID_NOCONV)
+ != __GCONV_OK)
+ domain->conv = (__gconv_t) -1;
+# else
+# if HAVE_ICONV
+ /* When using GNU libiconv, we want to use transliteration. */
+# if _LIBICONV_VERSION
+ len = strlen (outcharset);
+ {
+ char *tmp = (char *) alloca (len + 10 + 1);
+ memcpy (tmp, outcharset, len);
+ memcpy (tmp + len, "//TRANSLIT", 10 + 1);
+ outcharset = tmp;
+ }
+# endif
+ domain->conv = iconv_open (outcharset, charset);
+# if _LIBICONV_VERSION
+ freea (outcharset);
+# endif
+# endif
+# endif
+
+ freea (charset);
+ }
+#endif /* _LIBC || HAVE_ICONV */
+ }
+
+ return nullentry;
+}
+
+/* Frees the codeset dependent parts of an opened message catalog. */
+void
+internal_function
+_nl_free_domain_conv (domain)
+ struct loaded_domain *domain;
+{
+ if (domain->conv_tab != NULL && domain->conv_tab != (char **) -1)
+ free (domain->conv_tab);
+
+#ifdef _LIBC
+ if (domain->conv != (__gconv_t) -1)
+ __gconv_close (domain->conv);
+#else
+# if HAVE_ICONV
+ if (domain->conv != (iconv_t) -1)
+ iconv_close (domain->conv);
+# endif
+#endif
+}
+
/* Load the message catalogs specified by FILENAME. If it is no valid
message catalog do nothing. */
void
internal_function
-_nl_load_domain (domain_file)
+_nl_load_domain (domain_file, domainbinding)
struct loaded_l10nfile *domain_file;
+ struct binding *domainbinding;
{
int fd;
size_t size;
@@ -207,12 +341,15 @@ _nl_load_domain (domain_file)
struct mo_file_header *data = (struct mo_file_header *) -1;
int use_mmap = 0;
struct loaded_domain *domain;
- char *nullentry;
- size_t nullentrylen;
+ const char *nullentry;
domain_file->decided = 1;
domain_file->data = NULL;
+ /* Note that it would be useless to store domainbinding in domain_file
+ because domainbinding might be == NULL now but != NULL later (after
+ a call to bind_textdomain_codeset). */
+
/* If the record does not represent a valid locale the FILENAME
might be NULL. This can happen when according to the given
specification the locale file name is different for XPG and CEN
@@ -338,85 +475,10 @@ _nl_load_domain (domain_file)
return;
}
- /* Now find out about the character set the file is encoded with.
- This can be found (in textual form) in the entry "". If this
- entry does not exist or if this does not contain the `charset='
- information, we will assume the charset matches the one the
- current locale and we don't have to perform any conversion. */
-#ifdef _LIBC
- domain->conv = (__gconv_t) -1;
-#else
-# if HAVE_ICONV
- domain->conv = (iconv_t) -1;
-# endif
-#endif
- domain->conv_tab = NULL;
- nullentry = _nl_find_msg (domain_file, "", &nullentrylen);
- if (nullentry != NULL)
- {
-#if defined _LIBC || HAVE_ICONV
- const char *charsetstr;
-
- charsetstr = strstr (nullentry, "charset=");
- if (charsetstr != NULL)
- {
- size_t len;
- char *charset;
- const char *outcharset;
-
- charsetstr += strlen ("charset=");
- len = strcspn (charsetstr, " \t\n");
-
- charset = (char *) alloca (len + 1);
-# if defined _LIBC || HAVE_MEMPCPY
- *((char *) mempcpy (charset, charsetstr, len)) = '\0';
-# else
- memcpy (charset, charsetstr, len);
- charset[len] = '\0';
-# endif
-
- /* The output charset should normally be determined by the
- locale. But sometimes the locale is not used or not correctly
- set up, so we provide a possibility for the user to override
- this. Moreover, the value specified through
- bind_textdomain_codeset overrides both. */
- if (domain_file->domainbinding != NULL
- && domain_file->domainbinding->codeset != NULL)
- outcharset = domain_file->domainbinding->codeset;
- else
- {
- outcharset = getenv ("OUTPUT_CHARSET");
- if (outcharset == NULL || outcharset[0] == '\0')
- {
-# ifdef _LIBC
- outcharset = (*_nl_current[LC_CTYPE])->values[_NL_ITEM_INDEX (CODESET)].string;
-# else
-# if HAVE_ICONV
- extern const char *locale_charset (void);
- outcharset = locale_charset ();
-# endif
-# endif
- }
- }
-
-# ifdef _LIBC
- /* We always want to use transliteration. */
- outcharset = norm_add_slashes (outcharset, "TRANSLIT");
- charset = norm_add_slashes (charset, NULL);
- if (__gconv_open (outcharset, charset, &domain->conv,
- GCONV_AVOID_NOCONV)
- != __GCONV_OK)
- domain->conv = (__gconv_t) -1;
-# else
-# if HAVE_ICONV
- domain->conv = iconv_open (outcharset, charset);
-# endif
-# endif
-
- freea (charset);
- }
-#endif /* _LIBC || HAVE_ICONV */
- }
+ /* Now initialize the character set converter from the character set
+ the file is encoded with (found in the header entry) to the domain's
+ specified character set or the locale's character set. */
+ nullentry = _nl_init_domain_conv (domain_file, domain, domainbinding);
/* Also look for a plural specification. */
if (nullentry != NULL)
@@ -481,11 +543,7 @@ _nl_unload_domain (domain)
if (domain->plural != &germanic_plural)
__gettext_free_exp (domain->plural);
- if (domain->conv_tab != NULL && domain->conv_tab != (char **) -1)
- free (domain->conv_tab);
-
- if (domain->conv != (__gconv_t) -1)
- __gconv_close (domain->conv);
+ _nl_free_domain_conv (domain);
# ifdef _POSIX_MAPPED_FILES
if (domain->use_mmap)
diff --git a/intl/tst-codeset.c b/intl/tst-codeset.c
new file mode 100644
index 0000000000..9bdcd39cc9
--- /dev/null
+++ b/intl/tst-codeset.c
@@ -0,0 +1,56 @@
+/* Test of bind_textdomain_codeset.
+ Copyright (C) 2001 Free Software Foundation, Inc.
+ Contributed by Bruno Haible <haible@clisp.cons.org>, 2001.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include <libintl.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int
+main (void)
+{
+ char *s;
+ int result = 0;
+
+ unsetenv ("LANGUAGE");
+ unsetenv ("OUTPUT_CHARSET");
+ setlocale (LC_ALL, "de_DE.ISO-8859-1");
+ textdomain ("codeset");
+ bindtextdomain ("codeset", OBJPFX "domaindir");
+
+ /* Here we expect output in ISO-8859-1. */
+ s = gettext ("cheese");
+ if (strcmp (s, "K\344se"))
+ {
+ printf ("call 1 returned: %s\n", s);
+ result = 1;
+ }
+
+ bind_textdomain_codeset ("codeset", "UTF-8");
+
+ /* Here we expect output in UTF-8. */
+ s = gettext ("cheese");
+ if (strcmp (s, "K\303\244se"))
+ {
+ printf ("call 2 returned: %s\n", s);
+ result = 1;
+ }
+
+ return result;
+}
diff --git a/intl/tst-codeset.sh b/intl/tst-codeset.sh
new file mode 100644
index 0000000000..f75d91e23e
--- /dev/null
+++ b/intl/tst-codeset.sh
@@ -0,0 +1,42 @@
+#! /bin/sh
+# Test of bind_textdomain_codeset.
+# Copyright (C) 2001 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 Library General Public License as
+# published by the Free Software Foundation; either version 2 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with the GNU C Library; see the file COPYING.LIB. If
+# not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+common_objpfx=$1
+objpfx=$2
+
+GCONV_PATH=${common_objpfx}iconvdata
+export GCONV_PATH
+LOCPATH=${common_objpfx}localedata
+export LOCPATH
+LC_ALL=C
+export LC_ALL
+
+# Generate the test data.
+test -d ${objpfx}domaindir || mkdir ${objpfx}domaindir
+# Create the domain directories.
+test -d ${objpfx}domaindir/de_DE || mkdir ${objpfx}domaindir/de_DE
+test -d ${objpfx}domaindir/de_DE/LC_MESSAGES || mkdir ${objpfx}domaindir/de_DE/LC_MESSAGES
+# Populate them.
+msgfmt -o ${objpfx}domaindir/de_DE/LC_MESSAGES/codeset.mo tstcodeset.po
+
+${common_objpfx}elf/ld.so --library-path $common_objpfx \
+${objpfx}tst-codeset > ${objpfx}tst-codeset.out
+
+exit $?
diff --git a/intl/tstcodeset.po b/intl/tstcodeset.po
new file mode 100644
index 0000000000..9a6231d600
--- /dev/null
+++ b/intl/tstcodeset.po
@@ -0,0 +1,8 @@
+msgid ""
+msgstr ""
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ISO-8859-1\n"
+"Content-Transfer-Encoding: 8-bit\n"
+
+msgid "cheese"
+msgstr "Käse"
diff --git a/libio/freopen.c b/libio/freopen.c
index 162e835956..4e92df17b4 100644
--- a/libio/freopen.c
+++ b/libio/freopen.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993,95,96,97,98,2000 Free Software Foundation, Inc.
+/* Copyright (C) 1993,95,96,97,98,2000,2001 Free Software Foundation, Inc.
This file is part of the GNU IO Library.
This library is free software; you can redistribute it and/or
@@ -27,6 +27,7 @@
#include "stdio.h"
#include <shlib-compat.h>
+#include <fd_to_filename.h>
FILE*
freopen (filename, mode, fp)
@@ -35,11 +36,18 @@ freopen (filename, mode, fp)
FILE* fp;
{
FILE *result;
+ int fd = -1;
CHECK_FILE (fp, NULL);
if (!(fp->_flags & _IO_IS_FILEBUF))
return NULL;
_IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp);
_IO_flockfile (fp);
+ if (filename == NULL && _IO_fileno (fp) >= 0)
+ {
+ fd = dup (_IO_fileno (fp));
+ if (fd != -1)
+ filename = fd_to_filename (fd);
+ }
#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
if (&_IO_stdin_used == NULL)
/* If the shared C library is used by the application binary which
@@ -54,6 +62,12 @@ freopen (filename, mode, fp)
if (result != NULL)
/* unbound stream orientation */
result->_mode = 0;
+ if (fd != -1)
+ {
+ close (fd);
+ if (filename != NULL)
+ free ((char *) filename);
+ }
_IO_funlockfile (fp);
_IO_cleanup_region_end (0);
return result;
diff --git a/libio/freopen64.c b/libio/freopen64.c
index 8a104c6080..fb19ed9029 100644
--- a/libio/freopen64.c
+++ b/libio/freopen64.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993,1995,1996,1997,1998,2000 Free Software Foundation, Inc.
+/* Copyright (C) 1993,1995,1996,1997,1998,2000,2001 Free Software Foundation, Inc.
This file is part of the GNU IO Library.
This library is free software; you can redistribute it and/or
@@ -26,6 +26,8 @@
#include "libioP.h"
#include "stdio.h"
+#include <fd_to_filename.h>
+
FILE *
freopen64 (filename, mode, fp)
const char* filename;
@@ -34,15 +36,28 @@ freopen64 (filename, mode, fp)
{
#ifdef _G_OPEN64
FILE *result;
+ int fd = -1;
CHECK_FILE (fp, NULL);
if (!(fp->_flags & _IO_IS_FILEBUF))
return NULL;
_IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp);
_IO_flockfile (fp);
+ if (filename == NULL && _IO_fileno (fp) >= 0)
+ {
+ fd = dup (_IO_fileno (fp));
+ if (fd != -1)
+ filename = fd_to_filename (fd);
+ }
result = _IO_freopen64 (filename, mode, fp);
if (result != NULL)
/* unbound stream orientation */
result->_mode = 0;
+ if (fd != -1)
+ {
+ close (fd);
+ if (filename != NULL)
+ free ((char *) filename);
+ }
_IO_funlockfile (fp);
_IO_cleanup_region_end (0);
return result;
diff --git a/locale/findlocale.c b/locale/findlocale.c
index de2dc2ea66..e2c5713188 100644
--- a/locale/findlocale.c
+++ b/locale/findlocale.c
@@ -123,7 +123,7 @@ _nl_find_locale (const char *locale_path, size_t locale_path_len,
language, territory, codeset,
normalized_codeset, modifier, special,
sponsor, revision,
- _nl_category_names[category], NULL, 0);
+ _nl_category_names[category], 0);
if (locale_file == NULL)
{
@@ -134,7 +134,7 @@ _nl_find_locale (const char *locale_path, size_t locale_path_len,
language, territory, codeset,
normalized_codeset, modifier, special,
sponsor, revision,
- _nl_category_names[category], NULL, 1);
+ _nl_category_names[category], 1);
if (locale_file == NULL)
/* This means we are out of core. */
return NULL;
diff --git a/manual/stdio.texi b/manual/stdio.texi
index 970f0fe499..c23269ee06 100644
--- a/manual/stdio.texi
+++ b/manual/stdio.texi
@@ -873,7 +873,7 @@ The @code{putchar} function is equivalent to @code{putc} with
@comment wchar.h
@comment ISO
-@deftypefun wint_t putchar (wchar_t @var{wc})
+@deftypefun wint_t putwchar (wchar_t @var{wc})
The @code{putwchar} function is equivalent to @code{putwc} with
@code{stdout} as the value of the @var{stream} argument.
@end deftypefun
diff --git a/misc/error.c b/misc/error.c
index 8758bd0ade..6a0b2788c0 100644
--- a/misc/error.c
+++ b/misc/error.c
@@ -1,5 +1,5 @@
/* Error handler for noninteractive utilities
- Copyright (C) 1990-1998, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1990-1998, 2000, 2001 Free Software Foundation, Inc.
This file is part of the GNU C Library. Its master source is NOT part of
the C library, however. The master source lives in /gd/gnu/lib.
@@ -139,13 +139,11 @@ error (status, errnum, message, va_alist)
va_list args;
#endif
+ fflush (stdout);
if (error_print_progname)
(*error_print_progname) ();
else
- {
- fflush (stdout);
- fprintf (stderr, "%s: ", program_name);
- }
+ fprintf (stderr, "%s: ", program_name);
#ifdef VA_START
VA_START (args, message);
@@ -211,13 +209,11 @@ error_at_line (status, errnum, file_name, line_number, message, va_alist)
old_line_number = line_number;
}
+ fflush (stdout);
if (error_print_progname)
(*error_print_progname) ();
else
- {
- fflush (stdout);
- fprintf (stderr, "%s:", program_name);
- }
+ fprintf (stderr, "%s:", program_name);
if (file_name != NULL)
fprintf (stderr, "%s:%d: ", file_name, line_number);
diff --git a/sysdeps/generic/fd_to_filename.h b/sysdeps/generic/fd_to_filename.h
new file mode 100644
index 0000000000..f055463d67
--- /dev/null
+++ b/sysdeps/generic/fd_to_filename.h
@@ -0,0 +1,26 @@
+/* Query filename corresponding to an open FD. Generic version.
+ Copyright (C) 2001 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 Library General Public License as
+ published by the Free Software Foundation; either version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+/* In general there is no generic way to query filename for an open
+ file descriptor. */
+static inline const char *
+fd_to_filename (int fd)
+{
+ return NULL;
+}
diff --git a/sysdeps/sparc/sparc32/sparcv9/Makefile b/sysdeps/sparc/sparc32/sparcv9/Makefile
index 2844d8b514..421f273dca 100644
--- a/sysdeps/sparc/sparc32/sparcv9/Makefile
+++ b/sysdeps/sparc/sparc32/sparcv9/Makefile
@@ -1,5 +1,9 @@
sysdep-CFLAGS += -mcpu=v8 -mtune=ultrasparc -Wa,-Av9a
+ifeq ($(subdir),csu)
+sysdep_routines += hp-timing
+endif
+
ifeq ($(subst gnulib,string,$(subdir)),string)
ASFLAGS-.o += -Wa,-Av9a
ASFLAGS-.os += -Wa,-Av9a
diff --git a/sysdeps/sparc/sparc32/sparcv9/hp-timing.c b/sysdeps/sparc/sparc32/sparcv9/hp-timing.c
new file mode 100644
index 0000000000..772893e08b
--- /dev/null
+++ b/sysdeps/sparc/sparc32/sparcv9/hp-timing.c
@@ -0,0 +1,24 @@
+/* Support for high precision, low overhead timing functions. sparcv9 version.
+ Copyright (C) 2001 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by David S. Miller <davem@redhat.com>, 2001.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include <hp-timing.h>
+
+/* We have to define the variable for the overhead. */
+hp_timing_t __libc_hp_timing_overhead;
diff --git a/sysdeps/sparc/sparc32/sparcv9/hp-timing.h b/sysdeps/sparc/sparc32/sparcv9/hp-timing.h
new file mode 100644
index 0000000000..98acae9139
--- /dev/null
+++ b/sysdeps/sparc/sparc32/sparcv9/hp-timing.h
@@ -0,0 +1,89 @@
+/* High precision, low overhead timing functions. sparcv9 version.
+ Copyright (C) 2001 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by David S. Miller <davem@redhat.com>, 2001.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#ifndef _HP_TIMING_H
+#define _HP_TIMING_H 1
+
+#include <string.h>
+#include <sys/param.h>
+#include <stdio-common/_itoa.h>
+
+#define HP_TIMING_AVAIL (1)
+#define HP_TIMING_INLINE (1)
+
+typedef unsigned long long int hp_timing_t;
+
+extern hp_timing_t __libc_hp_timing_overhead;
+
+#define HP_TIMING_ZERO(Var) (Var) = (0)
+
+#define HP_TIMING_NOW(Var) \
+ __asm__ __volatile__ ("rd %%tick, %L0\n\t" \
+ "srlx %L0, 32, %H0" \
+ : "=r" (Var))
+
+#define HP_TIMING_DIFF_INIT() \
+ do { \
+ int __cnt = 5; \
+ __libc_hp_timing_overhead = ~0ull; \
+ do \
+ { \
+ hp_timing_t __t1, __t2; \
+ HP_TIMING_NOW (__t1); \
+ HP_TIMING_NOW (__t2); \
+ if (__t2 - __t1 < __libc_hp_timing_overhead) \
+ __libc_hp_timing_overhead = __t2 - __t1; \
+ } \
+ while (--__cnt > 0); \
+ } while (0)
+
+#define HP_TIMING_DIFF(Diff, Start, End) (Diff) = ((End) - (Start))
+
+#define HP_TIMING_ACCUM(Sum, Diff) \
+do { \
+ hp_timing_t __diff = (Diff) - __libc_hp_timing_overhead; \
+ __asm__ __volatile__("srl %L0, 0, %%g1\n\t" \
+ "sllx %H0, 32, %%g7\n\t" \
+ "or %%g1, %%g7, %%g1\n\t" \
+ "1: ldx [%1], %%g5\n\t" \
+ "add %%g5, %%g1, %%g7\n\t" \
+ "casx [%1], %%g5, %%g7\n\t" \
+ "cmp %%g5, %%g7\n\t" \
+ "bne,pn %%xcc, 1b\n\t" \
+ " nop" \
+ : /* no outputs */ \
+ : "r" (__diff), "r" (&(Sum)) \
+ : "memory", "g1", "g5", "g7"); \
+} while(0)
+
+#define HP_TIMING_ACCUM_NT(Sum, Diff) (Sum) += (Diff)
+
+#define HP_TIMING_PRINT(Buf, Len, Val) \
+ do { \
+ char __buf[20]; \
+ char *__cp = _itoa (Val, __buf + sizeof (__buf), 10, 0); \
+ int __len = (Len); \
+ char *__dest = (Buf); \
+ while (__len-- > 0 && __cp < __buf + sizeof (__buf)) \
+ *__dest++ = *__cp++; \
+ memcpy (__dest, " clock cycles", MIN (__len, sizeof (" clock cycles"))); \
+ } while (0)
+
+#endif /* hp-timing.h */
diff --git a/sysdeps/sparc/sparc64/Makefile b/sysdeps/sparc/sparc64/Makefile
index 312e59ea21..d12f478f95 100644
--- a/sysdeps/sparc/sparc64/Makefile
+++ b/sysdeps/sparc/sparc64/Makefile
@@ -1,2 +1,6 @@
# The Sparc `long double' is a distinct type we support.
long-double-fcts = yes
+
+ifeq ($(subdir),csu)
+sysdep_routines += hp-timing
+endif
diff --git a/sysdeps/sparc/sparc64/hp-timing.c b/sysdeps/sparc/sparc64/hp-timing.c
new file mode 100644
index 0000000000..862429fd0d
--- /dev/null
+++ b/sysdeps/sparc/sparc64/hp-timing.c
@@ -0,0 +1,24 @@
+/* Support for high precision, low overhead timing functions. sparc64 version.
+ Copyright (C) 2001 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by David S. Miller <davem@redhat.com>, 2001.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include <hp-timing.h>
+
+/* We have to define the variable for the overhead. */
+hp_timing_t __libc_hp_timing_overhead;
diff --git a/sysdeps/sparc/sparc64/hp-timing.h b/sysdeps/sparc/sparc64/hp-timing.h
new file mode 100644
index 0000000000..761a416c0c
--- /dev/null
+++ b/sysdeps/sparc/sparc64/hp-timing.h
@@ -0,0 +1,84 @@
+/* High precision, low overhead timing functions. sparc64 version.
+ Copyright (C) 2001 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by David S. Miller <davem@redhat.com>, 2001.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#ifndef _HP_TIMING_H
+#define _HP_TIMING_H 1
+
+#include <string.h>
+#include <sys/param.h>
+#include <stdio-common/_itoa.h>
+
+#define HP_TIMING_AVAIL (1)
+#define HP_TIMING_INLINE (1)
+
+typedef unsigned long int hp_timing_t;
+
+extern hp_timing_t __libc_hp_timing_overhead;
+
+#define HP_TIMING_ZERO(Var) (Var) = (0)
+
+#define HP_TIMING_NOW(Var) __asm__ __volatile__ ("rd %%tick, %0" : "=r" (Var))
+
+#define HP_TIMING_DIFF_INIT() \
+ do { \
+ int __cnt = 5; \
+ __libc_hp_timing_overhead = ~0ull; \
+ do \
+ { \
+ hp_timing_t __t1, __t2; \
+ HP_TIMING_NOW (__t1); \
+ HP_TIMING_NOW (__t2); \
+ if (__t2 - __t1 < __libc_hp_timing_overhead) \
+ __libc_hp_timing_overhead = __t2 - __t1; \
+ } \
+ while (--__cnt > 0); \
+ } while (0)
+
+#define HP_TIMING_DIFF(Diff, Start, End) (Diff) = ((End) - (Start))
+
+#define HP_TIMING_ACCUM(Sum, Diff) \
+do { \
+ hp_timing_t __diff = (Diff) - __libc_hp_timing_overhead; \
+ hp_timing_t tmp1, tmp2; \
+ __asm__ __volatile__("1: ldx [%3], %0\n\t" \
+ "add %0, %2, %1\n\t" \
+ "casx [%3], %0, %1\n\t" \
+ "cmp %0, %1\n\t" \
+ "bne,pn %%xcc, 1b\n\t" \
+ " nop" \
+ : "=&r" (tmp1), "=&r" (tmp2) \
+ : "r" (__diff), "r" (&(Sum)) \
+ : "memory", "g1", "g5", "g7"); \
+} while(0)
+
+#define HP_TIMING_ACCUM_NT(Sum, Diff) (Sum) += (Diff)
+
+#define HP_TIMING_PRINT(Buf, Len, Val) \
+ do { \
+ char __buf[20]; \
+ char *__cp = _itoa (Val, __buf + sizeof (__buf), 10, 0); \
+ int __len = (Len); \
+ char *__dest = (Buf); \
+ while (__len-- > 0 && __cp < __buf + sizeof (__buf)) \
+ *__dest++ = *__cp++; \
+ memcpy (__dest, " clock cycles", MIN (__len, sizeof (" clock cycles"))); \
+ } while (0)
+
+#endif /* hp-timing.h */
diff --git a/sysdeps/unix/sysv/linux/fd_to_filename.h b/sysdeps/unix/sysv/linux/fd_to_filename.h
new file mode 100644
index 0000000000..94f55b6c46
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/fd_to_filename.h
@@ -0,0 +1,46 @@
+/* Query filename corresponding to an open FD. Linux version.
+ Copyright (C) 2001 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 Library General Public License as
+ published by the Free Software Foundation; either version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <stdio-common/_itoa.h>
+
+static inline const char *
+fd_to_filename (int fd)
+{
+ char *ret = malloc (30);
+
+ if (ret != NULL)
+ {
+ struct stat64 st;
+
+ *_fitoa_word (fd, __stpcpy (ret, "/proc/self/fd/"), 10, 0) = '\0';
+
+ /* We must make sure the file exists. */
+ if (__lxstat64 (_STAT_VER, ret, &st) < 0)
+ {
+ /* /proc is not mounted or something else happened. Don't
+ return the file name. */
+ free (ret);
+ ret = NULL;
+ }
+ }
+ return ret;
+}