diff --git a/ChangeLog b/ChangeLog index 6c1f55be36..525d1aa9d7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,62 @@ +2001-04-05 David S. Miller + + 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 + + * 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 + + * misc/error.c (error): fflush stdout also if + error_print_progname != NULL. + (error_at_line): Likewise. + +2001-04-07 Bruno Haible + + * 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 * 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 , 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 +#include +#include +#include + +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 +#include 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 + 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 , 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 + +/* 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 , 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 +#include +#include + +#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 , 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 + +/* 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 , 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 +#include +#include + +#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 +#include +#include +#include + +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; +}