mirror of
https://sourceware.org/git/glibc.git
synced 2024-12-16 08:00:05 +00:00
Update.
* libio/stdio.h: Make fseeko and ftello prototypes available is __USE_LARGEFILE. Patch by Paul Eggert <eggert@twinsun.com>. * sysdeps/generic/dl-environ.c (unsetenv): Follow change to the real unsetenv implementation from 1999-07-29 [PR libc/1714]. 2000-05-03 Bruno Haible <haible@clisp.cons.org> * intl/dcigettext.c (dcigettext): Do the defaulting of 'domainname' before calling tfind. 2000-03-05 Jakub Jelinek <jakub@redhat.com> * resolv/resolv.h (res_querydomain): Remove redefinition to __res_querydomain (reported by Owen Taylor <otaylor@redhat.com>). 2000-05-03 Ulrich Drepper <drepper@redhat.com> * po/gl.po: Update from translation team. * manual/intro.texi (Program Basics): Change section title. * manual/process.texi: Fix reference. (Executing a File): Add reference exec in other section. * manual/signal.texi: Fix reference. * manual/startup.texi: Document syscall function. Patches by Bryan Henderson <bryanh@giraffe-data.com>. 2000-04-29 Bruno Haible <haible@clisp.cons.org> * intl/libintl.h (bind_textdomain_codeset): New declaration. * intl/bindtextdom.c (set_binding_values): New function. (bindtextdomain): Call it. (bind_textdomain_codeset): New function. * intl/dcigettext.c (dcigettext): Pass binding to _nl_find_domain. (free_mem): Free each binding's codeset. * intl/gettextP.h (struct binding): Add codeset field. (_nl_find_domain): Add domainbinding argument. * intl/finddomain.c (_nl_find_domain): Add domainbinding argument. Pass it to _nl_make_l10nflist. * intl/loadinfo.h (struct loaded_l10nfile): Add domainbinding field. (_nl_make_l10nflist): Add domainbinding argument. * intl/l10nflist.c (_nl_make_l10nflist): Add domainbinding argument. * intl/loadmsgcat.c (_nl_load_domain): Look at the domainbinding's codeset when determining outcharset. If !_LIBC && HAVE_ICONV, call locale_charset(). * manual/message.texi: New node "Charset conversion in gettext". 2000-04-30 Bruno Haible <haible@clisp.cons.org> * catgets/open_catalog.c (__open_catalog): Use __builtin_expect where appropriate. Handle possible __read error. 2000-04-29 Bruno Haible <haible@clisp.cons.org> * intl/gettextP.h (__builtin_expect): Define as empty if not a compiler builtin. * intl/loadinfo.h (__builtin_expect): Likewise. * intl/dcigettext.c (dcigettext, _nl_find_msg): Use __builtin_expect where appropriate. * intl/loadmsgcat.c (_nl_load_domain): Likewise. * intl/localealias.c (extend_alias_table): Return an error indicator. (read_alias_file): Bail out if extend_alias_table fails. 2000-04-29 Bruno Haible <haible@clisp.cons.org> * intl/loadmsgcat.c: Define _GNU_SOURCE as early as possible. * intl/localealias.c: Likewise. 2000-05-01 Bruno Haible <haible@clisp.cons.org> * intl/loadmsgcat.c (_nl_load_domain): Initialize domain->conv_tab. Initialize domain->plural and domain->nplurals even if there is no nullentry. 2000-05-01 Bruno Haible <haible@clisp.cons.org> * intl/dcigettext.c (_nl_find_msg): Terminate __gconv loop if return value is == __GCONV_OK or == __GCONV_EMPTY_INPUT, not != __GCONV_OK. In case of failure, goto converted. 2000-05-01 Bruno Haible <haible@clisp.cons.org> * wcsmbs/wcsmbsload.c (norm_add_slashes): Move away. * iconv/gconv_int.h (norm_add_slashes): Move to here. * intl/loadmsgcat.c (_nl_load_domain): Normalize strings passed to __gconv_open. 2000-04-29 Bruno Haible <haible@clisp.cons.org> * intl/dcigettext.c (transcmp): Compare the domains as well. (dcigettext): Call strlen (msgid1) after testing msgid1 against NULL, not before. * intl/loadmsgcat.c (_nl_load_domain): Deal with EINTR. Include <errno.h>. 2000-05-03 Ulrich Drepper <drepper@redhat.com>
This commit is contained in:
parent
160016c945
commit
17c389fc2b
97
ChangeLog
97
ChangeLog
@ -1,3 +1,100 @@
|
||||
2000-05-03 Ulrich Drepper <drepper@redhat.com>
|
||||
|
||||
* libio/stdio.h: Make fseeko and ftello prototypes available is
|
||||
__USE_LARGEFILE. Patch by Paul Eggert <eggert@twinsun.com>.
|
||||
|
||||
* sysdeps/generic/dl-environ.c (unsetenv): Follow change to the
|
||||
real unsetenv implementation from 1999-07-29 [PR libc/1714].
|
||||
|
||||
2000-05-03 Bruno Haible <haible@clisp.cons.org>
|
||||
|
||||
* intl/dcigettext.c (dcigettext): Do the defaulting of 'domainname'
|
||||
before calling tfind.
|
||||
|
||||
2000-03-05 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* resolv/resolv.h (res_querydomain): Remove redefinition to
|
||||
__res_querydomain (reported by Owen Taylor <otaylor@redhat.com>).
|
||||
|
||||
2000-05-03 Ulrich Drepper <drepper@redhat.com>
|
||||
|
||||
* po/gl.po: Update from translation team.
|
||||
|
||||
* manual/intro.texi (Program Basics): Change section title.
|
||||
* manual/process.texi: Fix reference.
|
||||
(Executing a File): Add reference exec in other section.
|
||||
* manual/signal.texi: Fix reference.
|
||||
* manual/startup.texi: Document syscall function.
|
||||
Patches by Bryan Henderson <bryanh@giraffe-data.com>.
|
||||
|
||||
2000-04-29 Bruno Haible <haible@clisp.cons.org>
|
||||
|
||||
* intl/libintl.h (bind_textdomain_codeset): New declaration.
|
||||
* intl/bindtextdom.c (set_binding_values): New function.
|
||||
(bindtextdomain): Call it.
|
||||
(bind_textdomain_codeset): New function.
|
||||
* intl/dcigettext.c (dcigettext): Pass binding to _nl_find_domain.
|
||||
(free_mem): Free each binding's codeset.
|
||||
* intl/gettextP.h (struct binding): Add codeset field.
|
||||
(_nl_find_domain): Add domainbinding argument.
|
||||
* intl/finddomain.c (_nl_find_domain): Add domainbinding argument.
|
||||
Pass it to _nl_make_l10nflist.
|
||||
* intl/loadinfo.h (struct loaded_l10nfile): Add domainbinding field.
|
||||
(_nl_make_l10nflist): Add domainbinding argument.
|
||||
* intl/l10nflist.c (_nl_make_l10nflist): Add domainbinding argument.
|
||||
* intl/loadmsgcat.c (_nl_load_domain): Look at the domainbinding's
|
||||
codeset when determining outcharset. If !_LIBC && HAVE_ICONV, call
|
||||
locale_charset().
|
||||
* manual/message.texi: New node "Charset conversion in gettext".
|
||||
|
||||
2000-04-30 Bruno Haible <haible@clisp.cons.org>
|
||||
|
||||
* catgets/open_catalog.c (__open_catalog): Use __builtin_expect where
|
||||
appropriate. Handle possible __read error.
|
||||
|
||||
2000-04-29 Bruno Haible <haible@clisp.cons.org>
|
||||
|
||||
* intl/gettextP.h (__builtin_expect): Define as empty if not a
|
||||
compiler builtin.
|
||||
* intl/loadinfo.h (__builtin_expect): Likewise.
|
||||
* intl/dcigettext.c (dcigettext, _nl_find_msg): Use
|
||||
__builtin_expect where appropriate.
|
||||
* intl/loadmsgcat.c (_nl_load_domain): Likewise.
|
||||
* intl/localealias.c (extend_alias_table): Return an error indicator.
|
||||
(read_alias_file): Bail out if extend_alias_table fails.
|
||||
|
||||
2000-04-29 Bruno Haible <haible@clisp.cons.org>
|
||||
|
||||
* intl/loadmsgcat.c: Define _GNU_SOURCE as early as possible.
|
||||
* intl/localealias.c: Likewise.
|
||||
|
||||
2000-05-01 Bruno Haible <haible@clisp.cons.org>
|
||||
|
||||
* intl/loadmsgcat.c (_nl_load_domain): Initialize domain->conv_tab.
|
||||
Initialize domain->plural and domain->nplurals even if there is no
|
||||
nullentry.
|
||||
|
||||
2000-05-01 Bruno Haible <haible@clisp.cons.org>
|
||||
|
||||
* intl/dcigettext.c (_nl_find_msg): Terminate __gconv loop if return
|
||||
value is == __GCONV_OK or == __GCONV_EMPTY_INPUT, not != __GCONV_OK.
|
||||
In case of failure, goto converted.
|
||||
|
||||
2000-05-01 Bruno Haible <haible@clisp.cons.org>
|
||||
|
||||
* wcsmbs/wcsmbsload.c (norm_add_slashes): Move away.
|
||||
* iconv/gconv_int.h (norm_add_slashes): Move to here.
|
||||
* intl/loadmsgcat.c (_nl_load_domain): Normalize strings passed to
|
||||
__gconv_open.
|
||||
|
||||
2000-04-29 Bruno Haible <haible@clisp.cons.org>
|
||||
|
||||
* intl/dcigettext.c (transcmp): Compare the domains as well.
|
||||
(dcigettext): Call strlen (msgid1) after testing msgid1 against NULL,
|
||||
not before.
|
||||
* intl/loadmsgcat.c (_nl_load_domain): Deal with EINTR. Include
|
||||
<errno.h>.
|
||||
|
||||
2000-05-03 Ulrich Drepper <drepper@redhat.com>
|
||||
|
||||
* string/bits/string2.h: Declare __strdup and __strndup if necessary.
|
||||
|
@ -50,7 +50,7 @@ __open_catalog (__nl_catd catalog)
|
||||
__libc_lock_lock (catalog->lock);
|
||||
|
||||
/* Check whether there was no other thread faster. */
|
||||
if (catalog->status != closed)
|
||||
if (__builtin_expect (catalog->status != closed, 0))
|
||||
/* While we waited some other thread tried to open the catalog. */
|
||||
goto unlock_return;
|
||||
|
||||
@ -60,7 +60,7 @@ __open_catalog (__nl_catd catalog)
|
||||
{
|
||||
const char *run_nlspath = catalog->nlspath;
|
||||
#define ENOUGH(n) \
|
||||
if (bufact + (n) >=bufmax) \
|
||||
if (__builtin_expect (bufact + (n) >= bufmax, 0)) \
|
||||
{ \
|
||||
char *old_buf = buf; \
|
||||
bufmax += 256 + (n); \
|
||||
@ -251,8 +251,12 @@ __open_catalog (__nl_catd catalog)
|
||||
{
|
||||
size_t now = __read (fd, (((char *) &catalog->file_ptr)
|
||||
+ (st.st_size - todo)), todo);
|
||||
if (now == 0)
|
||||
if (now == 0 || now == (size_t) -1)
|
||||
{
|
||||
#ifdef EINTR
|
||||
if (now == (size_t) -1 && errno == EINTR)
|
||||
continue;
|
||||
#endif
|
||||
free ((void *) catalog->file_ptr);
|
||||
catalog->status = nonexisting;
|
||||
goto close_unlock_return;
|
||||
|
@ -100,6 +100,34 @@ extern size_t __gconv_nmodules;
|
||||
extern struct gconv_module *__gconv_modules_db;
|
||||
|
||||
|
||||
/* The gconv functions expects the name to be in upper case and complete,
|
||||
including the trailing slashes if necessary. */
|
||||
#define norm_add_slashes(str) \
|
||||
({ \
|
||||
const char *cp = (str); \
|
||||
char *result; \
|
||||
char *tmp; \
|
||||
size_t cnt = 0; \
|
||||
\
|
||||
while (*cp != '\0') \
|
||||
if (*cp++ == '/') \
|
||||
++cnt; \
|
||||
\
|
||||
tmp = result = alloca (cp - (str) + 3); \
|
||||
cp = (str); \
|
||||
while (*cp != '\0') \
|
||||
*tmp++ = _toupper (*cp++); \
|
||||
if (cnt < 2) \
|
||||
{ \
|
||||
*tmp++ = '/'; \
|
||||
if (cnt < 1) \
|
||||
*tmp++ = '/'; \
|
||||
} \
|
||||
*tmp = '\0'; \
|
||||
result; \
|
||||
})
|
||||
|
||||
|
||||
/* Return in *HANDLE decriptor for transformation from FROMSET to TOSET. */
|
||||
extern int __gconv_open (const char *__toset, const char *__fromset,
|
||||
__gconv_t *__handle, int flags)
|
||||
|
@ -75,29 +75,44 @@ __libc_rwlock_define (extern, _nl_state_lock)
|
||||
prefix. So we have to make a difference here. */
|
||||
#ifdef _LIBC
|
||||
# define BINDTEXTDOMAIN __bindtextdomain
|
||||
# define BIND_TEXTDOMAIN_CODESET __bind_textdomain_codeset
|
||||
# ifndef strdup
|
||||
# define strdup(str) __strdup (str)
|
||||
# endif
|
||||
#else
|
||||
# define BINDTEXTDOMAIN bindtextdomain__
|
||||
# define BIND_TEXTDOMAIN_CODESET bind_textdomain_codeset__
|
||||
#endif
|
||||
|
||||
/* Specify that the DOMAINNAME message catalog will be found
|
||||
in DIRNAME rather than in the system locale data base. */
|
||||
char *
|
||||
BINDTEXTDOMAIN (domainname, dirname)
|
||||
/* 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
|
||||
modified, only the current value is returned.
|
||||
If DIRNAMEP or CODESETP is NULL, the corresponding attribute is neither
|
||||
modified nor returned. */
|
||||
static void
|
||||
set_binding_values (domainname, dirnamep, codesetp)
|
||||
const char *domainname;
|
||||
const char *dirname;
|
||||
const char **dirnamep;
|
||||
const char **codesetp;
|
||||
{
|
||||
struct binding *binding;
|
||||
char *result;
|
||||
int modified;
|
||||
|
||||
/* Some sanity checks. */
|
||||
if (domainname == NULL || domainname[0] == '\0')
|
||||
return NULL;
|
||||
{
|
||||
if (dirnamep)
|
||||
*dirnamep = NULL;
|
||||
if (codesetp)
|
||||
*codesetp = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
__libc_rwlock_wrlock (_nl_state_lock);
|
||||
|
||||
modified = 0;
|
||||
|
||||
for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next)
|
||||
{
|
||||
int compare = strcmp (domainname, binding->domainname);
|
||||
@ -112,39 +127,95 @@ BINDTEXTDOMAIN (domainname, dirname)
|
||||
}
|
||||
}
|
||||
|
||||
if (dirname == NULL)
|
||||
/* The current binding has be to returned. */
|
||||
result = binding == NULL ? (char *) _nl_default_dirname : binding->dirname;
|
||||
else if (binding != NULL)
|
||||
if (binding != NULL)
|
||||
{
|
||||
/* The domain is already bound. If the new value and the old
|
||||
one are equal we simply do nothing. Otherwise replace the
|
||||
old binding. */
|
||||
result = binding->dirname;
|
||||
if (strcmp (dirname, result) != 0)
|
||||
if (dirnamep)
|
||||
{
|
||||
if (strcmp (dirname, _nl_default_dirname) == 0)
|
||||
result = (char *) _nl_default_dirname;
|
||||
const char *dirname = *dirnamep;
|
||||
|
||||
if (dirname == NULL)
|
||||
/* The current binding has be to returned. */
|
||||
*dirnamep = binding->dirname;
|
||||
else
|
||||
{
|
||||
/* The domain is already bound. If the new value and the old
|
||||
one are equal we simply do nothing. Otherwise replace the
|
||||
old binding. */
|
||||
char *result = binding->dirname;
|
||||
if (strcmp (dirname, result) != 0)
|
||||
{
|
||||
if (strcmp (dirname, _nl_default_dirname) == 0)
|
||||
result = (char *) _nl_default_dirname;
|
||||
else
|
||||
{
|
||||
#if defined _LIBC || defined HAVE_STRDUP
|
||||
result = strdup (dirname);
|
||||
result = strdup (dirname);
|
||||
#else
|
||||
size_t len = strlen (dirname) + 1;
|
||||
result = (char *) malloc (len);
|
||||
if (result != NULL)
|
||||
memcpy (result, dirname, len);
|
||||
size_t len = strlen (dirname) + 1;
|
||||
result = (char *) malloc (len);
|
||||
if (__builtin_expect (result != NULL, 1))
|
||||
memcpy (result, dirname, len);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (result != NULL)
|
||||
{
|
||||
if (binding->dirname != _nl_default_dirname)
|
||||
free (binding->dirname);
|
||||
if (__builtin_expect (result != NULL, 1))
|
||||
{
|
||||
if (binding->dirname != _nl_default_dirname)
|
||||
free (binding->dirname);
|
||||
|
||||
binding->dirname = result;
|
||||
binding->dirname = result;
|
||||
modified = 1;
|
||||
}
|
||||
}
|
||||
*dirnamep = result;
|
||||
}
|
||||
}
|
||||
|
||||
if (codesetp)
|
||||
{
|
||||
const char *codeset = *codesetp;
|
||||
|
||||
if (codeset == NULL)
|
||||
/* The current binding has be to returned. */
|
||||
*codesetp = binding->codeset;
|
||||
else
|
||||
{
|
||||
/* The domain is already bound. If the new value and the old
|
||||
one are equal we simply do nothing. Otherwise replace the
|
||||
old binding. */
|
||||
char *result = binding->codeset;
|
||||
if (result == NULL || strcmp (codeset, result) != 0)
|
||||
{
|
||||
#if defined _LIBC || defined HAVE_STRDUP
|
||||
result = strdup (codeset);
|
||||
#else
|
||||
size_t len = strlen (codeset) + 1;
|
||||
result = (char *) malloc (len);
|
||||
if (__builtin_expect (result != NULL, 1))
|
||||
memcpy (result, codeset, len);
|
||||
#endif
|
||||
|
||||
if (__builtin_expect (result != NULL, 1))
|
||||
{
|
||||
if (binding->codeset != NULL)
|
||||
free (binding->codeset);
|
||||
|
||||
binding->codeset = result;
|
||||
modified = 1;
|
||||
}
|
||||
}
|
||||
*codesetp = result;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ((dirnamep == NULL || *dirnamep == NULL)
|
||||
&& (codesetp == NULL || *codesetp == NULL))
|
||||
{
|
||||
/* Simply return the default values. */
|
||||
if (dirnamep)
|
||||
*dirnamep = _nl_default_dirname;
|
||||
if (codesetp)
|
||||
*codesetp = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -153,61 +224,140 @@ BINDTEXTDOMAIN (domainname, dirname)
|
||||
struct binding *new_binding =
|
||||
(struct binding *) malloc (sizeof (*new_binding) + len);
|
||||
|
||||
if (new_binding == NULL)
|
||||
result = NULL;
|
||||
if (__builtin_expect (new_binding == NULL, 0))
|
||||
goto failed;
|
||||
|
||||
memcpy (new_binding->domainname, domainname, len);
|
||||
|
||||
if (dirnamep)
|
||||
{
|
||||
const char *dirname = *dirnamep;
|
||||
|
||||
if (dirname == NULL)
|
||||
/* The default value. */
|
||||
dirname = _nl_default_dirname;
|
||||
else
|
||||
{
|
||||
if (strcmp (dirname, _nl_default_dirname) == 0)
|
||||
dirname = _nl_default_dirname;
|
||||
else
|
||||
{
|
||||
char *result;
|
||||
#if defined _LIBC || defined HAVE_STRDUP
|
||||
result = strdup (dirname);
|
||||
if (__builtin_expect (result == NULL, 0))
|
||||
goto failed_dirname;
|
||||
#else
|
||||
size_t len = strlen (dirname) + 1;
|
||||
result = (char *) malloc (len);
|
||||
if (__builtin_expect (result == NULL, 0))
|
||||
goto failed_dirname;
|
||||
memcpy (result, dirname, len);
|
||||
#endif
|
||||
dirname = result;
|
||||
}
|
||||
}
|
||||
*dirnamep = dirname;
|
||||
new_binding->dirname = (char *) dirname;
|
||||
}
|
||||
else
|
||||
/* The default value. */
|
||||
new_binding->dirname = (char *) _nl_default_dirname;
|
||||
|
||||
if (codesetp)
|
||||
{
|
||||
const char *codeset = *codesetp;
|
||||
|
||||
if (codeset != NULL)
|
||||
{
|
||||
char *result;
|
||||
|
||||
#if defined _LIBC || defined HAVE_STRDUP
|
||||
result = strdup (codeset);
|
||||
if (__builtin_expect (result == NULL, 0))
|
||||
goto failed_codeset;
|
||||
#else
|
||||
size_t len = strlen (codeset) + 1;
|
||||
result = (char *) malloc (len);
|
||||
if (__builtin_expect (result == NULL, 0))
|
||||
goto failed_codeset;
|
||||
memcpy (result, codeset, len);
|
||||
#endif
|
||||
codeset = result;
|
||||
}
|
||||
*codesetp = codeset;
|
||||
new_binding->codeset = (char *) codeset;
|
||||
}
|
||||
else
|
||||
new_binding->codeset = NULL;
|
||||
|
||||
/* Now enqueue it. */
|
||||
if (_nl_domain_bindings == NULL
|
||||
|| strcmp (domainname, _nl_domain_bindings->domainname) < 0)
|
||||
{
|
||||
new_binding->next = _nl_domain_bindings;
|
||||
_nl_domain_bindings = new_binding;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy (new_binding->domainname, domainname, len);
|
||||
binding = _nl_domain_bindings;
|
||||
while (binding->next != NULL
|
||||
&& strcmp (domainname, binding->next->domainname) > 0)
|
||||
binding = binding->next;
|
||||
|
||||
if (strcmp (dirname, _nl_default_dirname) == 0)
|
||||
result = new_binding->dirname = (char *) _nl_default_dirname;
|
||||
else
|
||||
{
|
||||
#if defined _LIBC || defined HAVE_STRDUP
|
||||
result = new_binding->dirname = strdup (dirname);
|
||||
#else
|
||||
len = strlen (dirname) + 1;
|
||||
result = new_binding->dirname = (char *) malloc (len);
|
||||
if (result != NULL)
|
||||
memcpy (new_binding->dirname, dirname, len);
|
||||
#endif
|
||||
}
|
||||
new_binding->next = binding->next;
|
||||
binding->next = new_binding;
|
||||
}
|
||||
|
||||
if (result != NULL)
|
||||
modified = 1;
|
||||
|
||||
/* Here we deal with memory allocation failures. */
|
||||
if (0)
|
||||
{
|
||||
/* Now enqueue it. */
|
||||
if (_nl_domain_bindings == NULL
|
||||
|| strcmp (domainname, _nl_domain_bindings->domainname) < 0)
|
||||
{
|
||||
new_binding->next = _nl_domain_bindings;
|
||||
_nl_domain_bindings = new_binding;
|
||||
}
|
||||
else
|
||||
{
|
||||
binding = _nl_domain_bindings;
|
||||
while (binding->next != NULL
|
||||
&& strcmp (domainname, binding->next->domainname) > 0)
|
||||
binding = binding->next;
|
||||
|
||||
new_binding->next = binding->next;
|
||||
binding->next = new_binding;
|
||||
}
|
||||
failed_codeset:
|
||||
if (new_binding->dirname != _nl_default_dirname)
|
||||
free (new_binding->dirname);
|
||||
failed_dirname:
|
||||
free (new_binding);
|
||||
failed:
|
||||
if (dirnamep)
|
||||
*dirnamep = NULL;
|
||||
if (codesetp)
|
||||
*codesetp = NULL;
|
||||
}
|
||||
else if (new_binding != NULL)
|
||||
free (new_binding);
|
||||
}
|
||||
|
||||
/* For a succesful call we flush the caches. */
|
||||
if (result != NULL)
|
||||
/* If we modified any binding, we flush the caches. */
|
||||
if (modified)
|
||||
++_nl_msg_cat_cntr;
|
||||
|
||||
__libc_rwlock_unlock (_nl_state_lock);
|
||||
}
|
||||
|
||||
return result;
|
||||
/* Specify that the DOMAINNAME message catalog will be found
|
||||
in DIRNAME rather than in the system locale data base. */
|
||||
char *
|
||||
BINDTEXTDOMAIN (domainname, dirname)
|
||||
const char *domainname;
|
||||
const char *dirname;
|
||||
{
|
||||
set_binding_values (domainname, &dirname, NULL);
|
||||
return (char *) dirname;
|
||||
}
|
||||
|
||||
/* Specify the character encoding in which the messages from the
|
||||
DOMAINNAME message catalog will be returned. */
|
||||
char *
|
||||
BIND_TEXTDOMAIN_CODESET (domainname, codeset)
|
||||
const char *domainname;
|
||||
const char *codeset;
|
||||
{
|
||||
set_binding_values (domainname, NULL, &codeset);
|
||||
return (char *) codeset;
|
||||
}
|
||||
|
||||
#ifdef _LIBC
|
||||
/* Alias for function name in GNU C Library. */
|
||||
/* Aliases for function names in GNU C Library. */
|
||||
weak_alias (__bindtextdomain, bindtextdomain);
|
||||
weak_alias (__bind_textdomain_codeset, bind_textdomain_codeset);
|
||||
#endif
|
||||
|
@ -230,7 +230,7 @@ transcmp (const void *p1, const void *p2)
|
||||
result = strcmp (s1->msgid, s2->msgid);
|
||||
if (result == 0)
|
||||
{
|
||||
result = strcmp (s1->msgid, s2->msgid);
|
||||
result = strcmp (s1->domain, s2->domain);
|
||||
if (result == 0)
|
||||
{
|
||||
result = s1->plindex - s2->plindex;
|
||||
@ -362,7 +362,7 @@ DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
|
||||
#if defined HAVE_TSEARCH || defined _LIBC
|
||||
struct known_translation_t *search;
|
||||
struct known_translation_t **foundp = NULL;
|
||||
size_t msgid_len = strlen (msgid1) + 1;
|
||||
size_t msgid_len;
|
||||
#endif
|
||||
size_t domainname_len;
|
||||
|
||||
@ -372,7 +372,15 @@ DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
|
||||
|
||||
__libc_rwlock_rdlock (_nl_state_lock);
|
||||
|
||||
/* If DOMAINNAME is NULL, we are interested in the default domain. If
|
||||
CATEGORY is not LC_MESSAGES this might not make much sense but the
|
||||
definition left this undefined. */
|
||||
if (domainname == NULL)
|
||||
domainname = _nl_current_default_domain;
|
||||
|
||||
#if defined HAVE_TSEARCH || defined _LIBC
|
||||
msgid_len = strlen (msgid1) + 1;
|
||||
|
||||
if (plural == 0)
|
||||
{
|
||||
/* Try to find the translation among those which we found at
|
||||
@ -399,12 +407,6 @@ DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
|
||||
/* See whether this is a SUID binary or not. */
|
||||
DETERMINE_SECURE;
|
||||
|
||||
/* If DOMAINNAME is NULL, we are interested in the default domain. If
|
||||
CATEGORY is not LC_MESSAGES this might not make much sense but the
|
||||
definition left this undefined. */
|
||||
if (domainname == NULL)
|
||||
domainname = _nl_current_default_domain;
|
||||
|
||||
/* First find matching binding. */
|
||||
for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next)
|
||||
{
|
||||
@ -529,7 +531,7 @@ DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
|
||||
|
||||
/* Find structure describing the message catalog matching the
|
||||
DOMAINNAME and CATEGORY. */
|
||||
domain = _nl_find_domain (dirname, single_locale, xdomainname);
|
||||
domain = _nl_find_domain (dirname, single_locale, xdomainname, binding);
|
||||
|
||||
if (domain != NULL)
|
||||
{
|
||||
@ -605,7 +607,7 @@ DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
|
||||
/* Insert the entry in the search tree. */
|
||||
foundp = (struct known_translation_t **)
|
||||
tsearch (newp, &root, transcmp);
|
||||
if (&newp != foundp)
|
||||
if (__builtin_expect (&newp != foundp, 0))
|
||||
/* The insert failed. */
|
||||
free (newp);
|
||||
}
|
||||
@ -751,7 +753,7 @@ _nl_find_msg (domain_file, msgid, index)
|
||||
/* Mark that we didn't succeed allocating a table. */
|
||||
domain->conv_tab = (char **) -1;
|
||||
|
||||
if (domain->conv_tab == (char **) -1)
|
||||
if (__builtin_expect (domain->conv_tab == (char **) -1, 0))
|
||||
/* Nothing we can do, no more memory. */
|
||||
goto converted;
|
||||
|
||||
@ -787,59 +789,61 @@ _nl_find_msg (domain_file, msgid, index)
|
||||
|
||||
__libc_lock_lock (lock);
|
||||
|
||||
while (1)
|
||||
{
|
||||
# ifdef _LIBC
|
||||
{
|
||||
size_t written;
|
||||
int res;
|
||||
size_t non_reversible;
|
||||
int res;
|
||||
|
||||
while ((res = __gconv (domain->conv,
|
||||
&inbuf, inbuf + resultlen,
|
||||
&outbuf, outbuf + freemem_size,
|
||||
&written)) == __GCONV_OK)
|
||||
{
|
||||
if (res != __GCONV_FULL_OUTPUT)
|
||||
goto out;
|
||||
res = __gconv (domain->conv,
|
||||
&inbuf, inbuf + resultlen,
|
||||
&outbuf, outbuf + freemem_size,
|
||||
&non_reversible);
|
||||
|
||||
/* We must resize the buffer. */
|
||||
freemem_size = MAX (2 * freemem_size, 4064);
|
||||
freemem = (char *) malloc (freemem_size);
|
||||
if (freemem == NULL)
|
||||
goto out;
|
||||
if (res == __GCONV_OK || res == __GCONV_EMPTY_INPUT)
|
||||
break;
|
||||
|
||||
inbuf = result;
|
||||
outbuf = freemem + 4;
|
||||
}
|
||||
}
|
||||
if (res != __GCONV_FULL_OUTPUT)
|
||||
{
|
||||
__libc_lock_unlock (lock);
|
||||
goto converted;
|
||||
}
|
||||
|
||||
inbuf = result;
|
||||
# else
|
||||
# if HAVE_ICONV
|
||||
for (;;)
|
||||
{
|
||||
const char *inptr = (const char *) inbuf;
|
||||
size_t inleft = resultlen;
|
||||
char *outptr = (char *) outbuf;
|
||||
size_t outleft = freemem_size;
|
||||
|
||||
if (iconv (domain->conv, &inptr, &inleft, &outptr, &outleft)
|
||||
!= (size_t)(-1))
|
||||
!= (size_t) (-1))
|
||||
{
|
||||
outbuf = (unsigned char *) outptr;
|
||||
break;
|
||||
}
|
||||
if (errno != E2BIG)
|
||||
goto out;
|
||||
{
|
||||
__libc_lock_unlock (lock);
|
||||
goto converted;
|
||||
}
|
||||
# endif
|
||||
# endif
|
||||
|
||||
/* We must resize the buffer. */
|
||||
freemem_size = 2 * freemem_size;
|
||||
if (freemem_size < 4064)
|
||||
freemem_size = 4064;
|
||||
freemem = (char *) malloc (freemem_size);
|
||||
if (freemem == NULL)
|
||||
goto out;
|
||||
if (__builtin_expect (freemem == NULL, 0))
|
||||
{
|
||||
__libc_lock_unlock (lock);
|
||||
goto converted;
|
||||
}
|
||||
|
||||
outbuf = freemem + 4;
|
||||
}
|
||||
# endif
|
||||
# endif
|
||||
|
||||
/* We have now in our buffer a converted string. Put this
|
||||
into the table of conversions. */
|
||||
@ -848,10 +852,9 @@ _nl_find_msg (domain_file, msgid, index)
|
||||
/* Shrink freemem, but keep it aligned. */
|
||||
freemem_size -= outbuf - freemem;
|
||||
freemem = outbuf;
|
||||
freemem += freemem_size & 3;
|
||||
freemem_size = freemem_size & ~3;
|
||||
freemem += freemem_size & (__alignof__ (nls_uint32) - 1);
|
||||
freemem_size = freemem_size & ~ (__alignof__ (nls_uint32) - 1);
|
||||
|
||||
out:
|
||||
__libc_lock_unlock (lock);
|
||||
}
|
||||
|
||||
@ -1070,15 +1073,19 @@ free_mem (void)
|
||||
struct binding *runp;
|
||||
|
||||
for (runp = _nl_domain_bindings; runp != NULL; runp = runp->next)
|
||||
if (runp->dirname != _nl_default_dirname)
|
||||
/* Yes, this is a pointer comparison. */
|
||||
free (runp->dirname);
|
||||
{
|
||||
if (runp->dirname != _nl_default_dirname)
|
||||
/* Yes, this is a pointer comparison. */
|
||||
free (runp->dirname);
|
||||
if (runp->codeset != NULL)
|
||||
free (runp->codeset);
|
||||
}
|
||||
|
||||
if (_nl_current_default_domain != _nl_default_default_domain)
|
||||
/* Yes, again a pointer comparison. */
|
||||
free ((char *) _nl_current_default_domain);
|
||||
|
||||
/* Remove the search tree with the know translations. */
|
||||
/* Remove the search tree with the known translations. */
|
||||
__tdestroy (root, free);
|
||||
}
|
||||
|
||||
|
@ -67,10 +67,11 @@ static struct loaded_l10nfile *_nl_loaded_domains;
|
||||
established bindings. */
|
||||
struct loaded_l10nfile *
|
||||
internal_function
|
||||
_nl_find_domain (dirname, locale, domainname)
|
||||
_nl_find_domain (dirname, locale, domainname, domainbinding)
|
||||
const char *dirname;
|
||||
char *locale;
|
||||
const char *domainname;
|
||||
struct binding *domainbinding;
|
||||
{
|
||||
struct loaded_l10nfile *retval;
|
||||
const char *language;
|
||||
@ -109,7 +110,8 @@ _nl_find_domain (dirname, locale, domainname)
|
||||
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, 0);
|
||||
NULL, NULL, NULL, NULL, NULL, domainname,
|
||||
domainbinding, 0);
|
||||
if (retval != NULL)
|
||||
{
|
||||
/* We know something about this locale. */
|
||||
@ -165,7 +167,8 @@ _nl_find_domain (dirname, locale, domainname)
|
||||
retval = _nl_make_l10nflist (&_nl_loaded_domains, dirname,
|
||||
strlen (dirname) + 1, mask, language, territory,
|
||||
codeset, normalized_codeset, modifier, special,
|
||||
sponsor, revision, domainname, 1);
|
||||
sponsor, revision, domainname, domainbinding,
|
||||
1);
|
||||
if (retval == NULL)
|
||||
/* This means we are out of core. */
|
||||
return NULL;
|
||||
|
@ -44,6 +44,12 @@
|
||||
# define internal_function
|
||||
#endif
|
||||
|
||||
/* Tell the compiler when a conditional or integer expression is
|
||||
almost always true or almost always false. */
|
||||
#ifndef HAVE_BUILTIN_EXPECT
|
||||
# define __builtin_expect(expr, val) (expr)
|
||||
#endif
|
||||
|
||||
#ifndef W
|
||||
# define W(flag, data) ((flag) ? SWAP (data) : (data))
|
||||
#endif
|
||||
@ -137,6 +143,7 @@ struct binding
|
||||
{
|
||||
struct binding *next;
|
||||
char *dirname;
|
||||
char *codeset;
|
||||
#ifdef __GNUC__
|
||||
char domainname[0];
|
||||
#else
|
||||
@ -148,7 +155,8 @@ extern int _nl_msg_cat_cntr;
|
||||
|
||||
struct loaded_l10nfile *_nl_find_domain PARAMS ((const char *__dirname,
|
||||
char *__locale,
|
||||
const char *__domainname))
|
||||
const char *__domainname,
|
||||
struct binding *__domainbinding))
|
||||
internal_function;
|
||||
void _nl_load_domain PARAMS ((struct loaded_l10nfile *__domain))
|
||||
internal_function;
|
||||
|
@ -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, do_allocate)
|
||||
sponsor, revision, filename, domainbinding, do_allocate)
|
||||
struct loaded_l10nfile **l10nfile_list;
|
||||
const char *dirlist;
|
||||
size_t dirlist_len;
|
||||
@ -189,6 +189,7 @@ _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;
|
||||
@ -309,6 +310,7 @@ _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));
|
||||
@ -344,7 +346,8 @@ _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, 1);
|
||||
sponsor, revision, filename, domainbinding,
|
||||
1);
|
||||
}
|
||||
retval->successor[entries] = NULL;
|
||||
|
||||
|
@ -78,6 +78,11 @@ extern char *textdomain (__const char *__domainname) __THROW;
|
||||
extern char *bindtextdomain (__const char *__domainname,
|
||||
__const char *__dirname) __THROW;
|
||||
|
||||
/* Specify the character encoding in which the messages from the
|
||||
DOMAINNAME message catalog will be returned. */
|
||||
extern char *bind_textdomain_codeset (__const char *__domainname,
|
||||
__const char *__codeset) __THROW;
|
||||
|
||||
|
||||
/* Optimized version of the function above. */
|
||||
#if defined __OPTIMIZE__
|
||||
|
@ -32,6 +32,12 @@
|
||||
# define internal_function
|
||||
#endif
|
||||
|
||||
/* Tell the compiler when a conditional or integer expression is
|
||||
almost always true or almost always false. */
|
||||
#ifndef HAVE_BUILTIN_EXPECT
|
||||
# define __builtin_expect(expr, val) (expr)
|
||||
#endif
|
||||
|
||||
/* Encoding of locale name parts. */
|
||||
#define CEN_REVISION 1
|
||||
#define CEN_SPONSOR 2
|
||||
@ -49,6 +55,7 @@
|
||||
struct loaded_l10nfile
|
||||
{
|
||||
const char *filename;
|
||||
struct binding *domainbinding;
|
||||
int decided;
|
||||
|
||||
const void *data;
|
||||
@ -73,7 +80,8 @@ _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, int do_allocate));
|
||||
const char *filename,
|
||||
struct binding *domainbinding, int do_allocate));
|
||||
|
||||
|
||||
extern const char *_nl_expand_alias PARAMS ((const char *name));
|
||||
|
@ -16,11 +16,19 @@
|
||||
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* Tell glibc's <string.h> to provide a prototype for mempcpy().
|
||||
This must come before <config.h> because <config.h> may include
|
||||
<features.h>, and once <features.h> has been included, it's too late. */
|
||||
#ifndef _GNU_SOURCE
|
||||
# define _GNU_SOURCE 1
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
@ -30,9 +38,6 @@
|
||||
#endif
|
||||
|
||||
#if defined HAVE_STRING_H || defined _LIBC
|
||||
# ifndef _GNU_SOURCE
|
||||
# define _GNU_SOURCE 1
|
||||
# endif
|
||||
# include <string.h>
|
||||
#else
|
||||
# include <strings.h>
|
||||
@ -138,9 +143,9 @@ _nl_load_domain (domain_file)
|
||||
return;
|
||||
|
||||
/* We must know about the size of the file. */
|
||||
if (fstat (fd, &st) != 0
|
||||
|| (size = (size_t) st.st_size) != st.st_size
|
||||
|| size < sizeof (struct mo_file_header))
|
||||
if (__builtin_expect (fstat (fd, &st) != 0, 0)
|
||||
|| __builtin_expect ((size = (size_t) st.st_size) != st.st_size, 0)
|
||||
|| __builtin_expect (size < sizeof (struct mo_file_header), 0))
|
||||
{
|
||||
/* Something went wrong. */
|
||||
close (fd);
|
||||
@ -153,7 +158,7 @@ _nl_load_domain (domain_file)
|
||||
data = (struct mo_file_header *) mmap (NULL, size, PROT_READ,
|
||||
MAP_PRIVATE, fd, 0);
|
||||
|
||||
if (data != (struct mo_file_header *) -1)
|
||||
if (__builtin_expect (data != (struct mo_file_header *) -1, 1))
|
||||
{
|
||||
/* mmap() call was successful. */
|
||||
close (fd);
|
||||
@ -177,12 +182,15 @@ _nl_load_domain (domain_file)
|
||||
do
|
||||
{
|
||||
long int nb = (long int) read (fd, read_ptr, to_read);
|
||||
if (nb == -1)
|
||||
if (nb <= 0)
|
||||
{
|
||||
#ifdef EINTR
|
||||
if (nb == -1 && errno == EINTR)
|
||||
continue;
|
||||
#endif
|
||||
close (fd);
|
||||
return;
|
||||
}
|
||||
|
||||
read_ptr += nb;
|
||||
to_read -= nb;
|
||||
}
|
||||
@ -193,7 +201,8 @@ _nl_load_domain (domain_file)
|
||||
|
||||
/* Using the magic number we can test whether it really is a message
|
||||
catalog file. */
|
||||
if (data->magic != _MAGIC && data->magic != _MAGIC_SWAPPED)
|
||||
if (__builtin_expect (data->magic != _MAGIC && data->magic != _MAGIC_SWAPPED,
|
||||
0))
|
||||
{
|
||||
/* The magic number is wrong: not a message catalog file. */
|
||||
#ifdef HAVE_MMAP
|
||||
@ -254,14 +263,13 @@ _nl_load_domain (domain_file)
|
||||
domain->conv = (iconv_t) -1;
|
||||
# endif
|
||||
#endif
|
||||
domain->conv_tab = NULL;
|
||||
nullentry = _nl_find_msg (domain_file, "", 0);
|
||||
if (nullentry != NULL)
|
||||
{
|
||||
const char *charsetstr;
|
||||
const char *plural;
|
||||
const char *nplurals;
|
||||
|
||||
#if defined _LIBC || HAVE_ICONV
|
||||
const char *charsetstr;
|
||||
|
||||
charsetstr = strstr (nullentry, "charset=");
|
||||
if (charsetstr != NULL)
|
||||
{
|
||||
@ -282,12 +290,33 @@ _nl_load_domain (domain_file)
|
||||
|
||||
/* 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 to override this. */
|
||||
outcharset = getenv ("OUTPUT_CHARSET");
|
||||
if (outcharset == NULL || outcharset[0] == '\0')
|
||||
outcharset = (*_nl_current[LC_CTYPE])->values[_NL_ITEM_INDEX (CODESET)].string;
|
||||
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 ();
|
||||
if (outcharset == NULL)
|
||||
outcharset = "";
|
||||
# endif
|
||||
# endif
|
||||
}
|
||||
}
|
||||
|
||||
# ifdef _LIBC
|
||||
outcharset = norm_add_slashes (outcharset);
|
||||
charset = norm_add_slashes (charset);
|
||||
if (__gconv_open (outcharset, charset, &domain->conv,
|
||||
GCONV_AVOID_NOCONV)
|
||||
!= __GCONV_OK)
|
||||
@ -299,19 +328,18 @@ _nl_load_domain (domain_file)
|
||||
# endif
|
||||
}
|
||||
#endif /* _LIBC || HAVE_ICONV */
|
||||
}
|
||||
|
||||
/* Also look for a plural specification. */
|
||||
if (nullentry != NULL)
|
||||
{
|
||||
const char *plural;
|
||||
const char *nplurals;
|
||||
|
||||
/* Also look for a plural specification. */
|
||||
plural = strstr (nullentry, "plural=");
|
||||
nplurals = strstr (nullentry, "nplurals=");
|
||||
if (plural == NULL || nplurals == NULL)
|
||||
{
|
||||
/* By default we are using the Germanic form: singular form only
|
||||
for `one', the plural form otherwise. Yes, this is also what
|
||||
English is using since English is a Germanic language. */
|
||||
no_plural:
|
||||
domain->plural = &germanic_plural;
|
||||
domain->nplurals = 2;
|
||||
}
|
||||
goto no_plural;
|
||||
else
|
||||
{
|
||||
/* First get the number. */
|
||||
@ -336,6 +364,15 @@ _nl_load_domain (domain_file)
|
||||
domain->plural = args.res;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* By default we are using the Germanic form: singular form only
|
||||
for `one', the plural form otherwise. Yes, this is also what
|
||||
English is using since English is a Germanic language. */
|
||||
no_plural:
|
||||
domain->plural = &germanic_plural;
|
||||
domain->nplurals = 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -16,6 +16,13 @@
|
||||
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* Tell glibc's <string.h> to provide a prototype for mempcpy().
|
||||
This must come before <config.h> because <config.h> may include
|
||||
<features.h>, and once <features.h> has been included, it's too late. */
|
||||
#ifndef _GNU_SOURCE
|
||||
# define _GNU_SOURCE 1
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
@ -53,9 +60,6 @@ void free ();
|
||||
#endif
|
||||
|
||||
#if defined HAVE_STRING_H || defined _LIBC
|
||||
# ifndef _GNU_SOURCE
|
||||
# define _GNU_SOURCE 1
|
||||
# endif
|
||||
# include <string.h>
|
||||
#else
|
||||
# include <strings.h>
|
||||
@ -158,7 +162,7 @@ static size_t maxmap;
|
||||
/* Prototypes for local functions. */
|
||||
static size_t read_alias_file PARAMS ((const char *fname, int fname_len))
|
||||
internal_function;
|
||||
static void extend_alias_table PARAMS ((void));
|
||||
static int extend_alias_table PARAMS ((void));
|
||||
static int alias_compare PARAMS ((const struct alias_map *map1,
|
||||
const struct alias_map *map2));
|
||||
|
||||
@ -326,7 +330,11 @@ read_alias_file (fname, fname_len)
|
||||
*cp++ = '\0';
|
||||
|
||||
if (nmap >= maxmap)
|
||||
extend_alias_table ();
|
||||
if (__builtin_expect (extend_alias_table (), 0))
|
||||
{
|
||||
FREE_BLOCKS (block_list);
|
||||
return added;
|
||||
}
|
||||
|
||||
alias_len = strlen (alias) + 1;
|
||||
value_len = strlen (value) + 1;
|
||||
@ -374,7 +382,7 @@ read_alias_file (fname, fname_len)
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
static int
|
||||
extend_alias_table ()
|
||||
{
|
||||
size_t new_size;
|
||||
@ -385,10 +393,11 @@ extend_alias_table ()
|
||||
* sizeof (struct alias_map)));
|
||||
if (new_map == NULL)
|
||||
/* Simply don't extend: we don't have any more core. */
|
||||
return;
|
||||
return -1;
|
||||
|
||||
map = new_map;
|
||||
maxmap = new_size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Define ISO C stdio on top of C++ iostreams.
|
||||
Copyright (C) 1991, 94, 95, 96, 97, 98, 99 Free Software Foundation, Inc.
|
||||
Copyright (C) 1991, 1994-1999, 2000 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 Library General Public License as
|
||||
@ -481,7 +481,7 @@ typedef __off64_t off64_t;
|
||||
|
||||
|
||||
#ifndef __USE_FILE_OFFSET64
|
||||
# ifdef __USE_UNIX98
|
||||
# ifdef __USE_LARGEFILE
|
||||
/* Seek to a certain position on STREAM. */
|
||||
extern int fseeko (FILE *__stream, __off_t __off, int __whence) __THROW;
|
||||
/* Return the current position of STREAM. */
|
||||
@ -495,7 +495,7 @@ extern int fgetpos (FILE *__restrict __stream, fpos_t *__restrict __pos)
|
||||
extern int fsetpos (FILE *__stream, __const fpos_t *__pos) __THROW;
|
||||
#else
|
||||
# ifdef __REDIRECT
|
||||
# ifdef __USE_UNIX98
|
||||
# ifdef __USE_LARGEFILE
|
||||
extern int __REDIRECT (fseeko,
|
||||
(FILE *__stream, __off64_t __off, int __whence) __THROW,
|
||||
fseeko64);
|
||||
@ -507,7 +507,7 @@ extern int __REDIRECT (fsetpos,
|
||||
(FILE *__stream, __const fpos_t *__pos) __THROW,
|
||||
fsetpos64);
|
||||
# else
|
||||
# ifdef __USE_UNIX98
|
||||
# ifdef __USE_LARGEFILE
|
||||
# define fseeko fseeko64
|
||||
# define ftello ftello64
|
||||
# endif
|
||||
@ -517,10 +517,8 @@ extern int __REDIRECT (fsetpos,
|
||||
#endif
|
||||
|
||||
#ifdef __USE_LARGEFILE64
|
||||
# ifdef __USE_UNIX98
|
||||
extern int fseeko64 (FILE *__stream, __off64_t __off, int __whence) __THROW;
|
||||
extern __off64_t ftello64 (FILE *__stream) __THROW;
|
||||
# endif
|
||||
extern int fgetpos64 (FILE *__restrict __stream, fpos64_t *__restrict __pos)
|
||||
__THROW;
|
||||
extern int fsetpos64 (FILE *__stream, __const fpos64_t *__pos) __THROW;
|
||||
|
@ -674,7 +674,7 @@ signal is delivered, and how to prevent signals from arriving during
|
||||
critical sections of your program.
|
||||
|
||||
@item
|
||||
@ref{Process Startup}, tells how your programs can access their
|
||||
@ref{Program Basics}, tells how your programs can access their
|
||||
command-line arguments and environment variables.
|
||||
|
||||
@item
|
||||
|
@ -764,13 +764,15 @@ basic functionally is equivalent. There are functions of the following
|
||||
categories:
|
||||
|
||||
@menu
|
||||
* Translation with gettext:: What has to be done to translate a message.
|
||||
* Locating gettext catalog:: How to determine which catalog to be used.
|
||||
* Advanced gettext functions:: Additional functions for more complicated
|
||||
situations.
|
||||
* GUI program problems:: How to use @code{gettext} in GUI programs.
|
||||
* Using gettextized software:: The possibilities of the user to influence
|
||||
the way @code{gettext} works.
|
||||
* Translation with gettext:: What has to be done to translate a message.
|
||||
* Locating gettext catalog:: How to determine which catalog to be used.
|
||||
* Advanced gettext functions:: Additional functions for more complicated
|
||||
situations.
|
||||
* Charset conversion in gettext:: How to specify the output character set
|
||||
@code{gettext} uses.
|
||||
* GUI program problems:: How to use @code{gettext} in GUI programs.
|
||||
* Using gettextized software:: The possibilities of the user to influence
|
||||
the way @code{gettext} works.
|
||||
@end menu
|
||||
|
||||
@node Translation with gettext
|
||||
@ -1045,7 +1047,7 @@ running program does not depend on the user setting an environment
|
||||
variable.
|
||||
|
||||
The @code{bindtextdomain} function can be used several times and if the
|
||||
@var{domainname} argument is different the previously bounded domains
|
||||
@var{domainname} argument is different the previously bound domains
|
||||
will not be overwritten.
|
||||
|
||||
If the program which wish to use @code{bindtextdomain} at some point of
|
||||
@ -1359,6 +1361,52 @@ Slovenian
|
||||
@end table
|
||||
|
||||
|
||||
@node Charset conversion in gettext
|
||||
@subsubsection How to specify the output character set @code{gettext} uses
|
||||
|
||||
@code{gettext} not only looks up a translation in a message catalog. It
|
||||
also converts the translation on the fly to the desired output character
|
||||
set. This is useful if the user is working in a different character set
|
||||
than the translator who created the message catalog, because it avoids
|
||||
distributing variants of message catalogs which differ only in the
|
||||
character set.
|
||||
|
||||
The output character set is, by default, the value of @code{nl_langinfo
|
||||
(CODESET)}, which depends on the @code{LC_CTYPE} part of the current
|
||||
locale. But programs which store strings in a locale independent way
|
||||
(e.g. UTF-8) can request that @code{gettext} and related functions
|
||||
return the translations in that encoding, by use of the
|
||||
@code{bind_textdomain_codeset} function.
|
||||
|
||||
Note that the @var{msgid} argument to @code{gettext} is not subject to
|
||||
character set conversion. Also, when @code{gettext} does not find a
|
||||
translation for @var{msgid}, it returns @var{msgid} unchanged --
|
||||
independently of the current output character set. It is therefore
|
||||
recommended that all @var{msgid}s be US-ASCII strings.
|
||||
|
||||
@comment libintl.h
|
||||
@comment GNU
|
||||
@deftypefun {char *} bind_textdomain_codeset (const char *@var{domainname}, const char *@var{codeset})
|
||||
The @code{bind_textdomain_codeset} function can be used to specify the
|
||||
output character set for message catalogs for domain @var{domainname}.
|
||||
|
||||
If the @var{codeset} parameter is the null pointer,
|
||||
@code{bind_textdomain_codeset} returns the currently selected codeset
|
||||
for the domain with the name @var{domainname}. It returns @code{NULL} if
|
||||
no codeset has yet been selected.
|
||||
|
||||
The @code{bind_textdomain_codeset} function can be used several times.
|
||||
If used multiple times with the same @var{domainname} argument, the
|
||||
later call overrides the settings made by the earlier one.
|
||||
|
||||
The @code{bind_textdomain_codeset} function returns a pointer to a
|
||||
string containing the name of the selected codeset. The string is
|
||||
allocated internally in the function and must not be changed by the
|
||||
user. If the system went out of core during the execution of
|
||||
@code{bind_textdomain_codeset}, the return value is @code{NULL} and the
|
||||
global variable @var{errno} is set accordingly. @end deftypefun
|
||||
|
||||
|
||||
@node GUI program problems
|
||||
@subsubsection How to use @code{gettext} in GUI programs
|
||||
|
||||
@ -1589,7 +1637,7 @@ to work:
|
||||
@{
|
||||
textdomain ("test-package");
|
||||
bindtextdomain ("test-package", "/usr/local/share/locale");
|
||||
puts (gettext ("Hello, world!");
|
||||
puts (gettext ("Hello, world!"));
|
||||
@}
|
||||
@end smallexample
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
@node Processes, Job Control, Process Startup, Top
|
||||
@node Processes, Job Control, Program Basics, Top
|
||||
@c %MENU% How to create processes and run other programs
|
||||
@chapter Processes
|
||||
|
||||
@ -276,6 +276,9 @@ This section describes the @code{exec} family of functions, for executing
|
||||
a file as a process image. You can use these functions to make a child
|
||||
process execute a new program after it has been forked.
|
||||
|
||||
To see the effects of @code{exec} from the point of view of the called
|
||||
program, @xref{Program Basics}.
|
||||
|
||||
@pindex unistd.h
|
||||
The functions in this family differ in how you specify the arguments,
|
||||
but otherwise they all do the same thing. They are declared in the
|
||||
|
@ -1,4 +1,4 @@
|
||||
@node Signal Handling, Process Startup, Non-Local Exits, Top
|
||||
@node Signal Handling, Program Basics, Non-Local Exits, Top
|
||||
@c %MENU% How to send, block, and handle signals
|
||||
@chapter Signal Handling
|
||||
|
||||
|
@ -1,25 +1,43 @@
|
||||
@node Process Startup, Processes, Signal Handling, Top
|
||||
@node Program Basics, Processes, Signal Handling, Top
|
||||
@c %MENU% Writing the beginning and end of your program
|
||||
@chapter Process Startup and Termination
|
||||
@chapter The Basic Program/System Interface
|
||||
|
||||
@cindex process
|
||||
@cindex program
|
||||
@cindex address space
|
||||
@cindex thread of control
|
||||
@dfn{Processes} are the primitive units for allocation of system
|
||||
resources. Each process has its own address space and (usually) one
|
||||
thread of control. A process executes a program; you can have multiple
|
||||
processes executing the same program, but each process has its own copy
|
||||
of the program within its own address space and executes it
|
||||
independently of the other copies.
|
||||
independently of the other copies. Though it may have multiple threads
|
||||
of control within the same program and a program may be composed of
|
||||
multiple logically separate modules, a process always executes exactly
|
||||
one program.
|
||||
|
||||
This chapter explains what your program should do to handle the startup
|
||||
of a process, to terminate its process, and to receive information
|
||||
(arguments and the environment) from the parent process.
|
||||
Note that we are using a specific definition of ``program'' for the
|
||||
purposes of this manual, which corresponds to a common definition in the
|
||||
context of Unix system. In popular usage, ``program'' enjoys a much
|
||||
broader definition; it can refer for example to a system's kernel, an
|
||||
editor macro, a complex package of software, or a discrete section of
|
||||
code executing within a process.
|
||||
|
||||
Writing the program is what this manual is all about. This chapter
|
||||
explains the most basic interface between your program and the system
|
||||
that runs, or calls, it. This includes passing of parameters (arguments
|
||||
and environment) from the system, requesting basic services from the
|
||||
system, and telling the system the program is done.
|
||||
|
||||
A program starts another program with the @code{exec} family of system calls.
|
||||
This chapter looks at program startup from the execee's point of view. To
|
||||
see the event from the execor's point of view, @xref{Executing a File}.
|
||||
|
||||
@menu
|
||||
* Program Arguments:: Parsing your program's command-line arguments.
|
||||
* Environment Variables:: How to access parameters inherited from
|
||||
a parent process.
|
||||
* Program Termination:: How to cause a process to terminate and
|
||||
return status information to its parent.
|
||||
* Environment Variables:: Less direct parameters affecting your program
|
||||
* System Calls:: Requesting service from the system
|
||||
* Program Termination:: Telling the system you're done; return status
|
||||
@end menu
|
||||
|
||||
@node Program Arguments
|
||||
@ -72,7 +90,7 @@ int main (int @var{argc}, char *@var{argv}[], char *@var{envp})
|
||||
@end smallexample
|
||||
|
||||
The first two arguments are just the same. The third argument
|
||||
@var{envp} gives the process's environment; it is the same as the value
|
||||
@var{envp} gives the program's environment; it is the same as the value
|
||||
of @code{environ}. @xref{Environment Variables}. POSIX.1 does not
|
||||
allow this three-argument form, so to be portable it is best to write
|
||||
@code{main} to take two arguments, and use the value of @code{environ}.
|
||||
@ -438,7 +456,7 @@ this lets the user specify the value.
|
||||
|
||||
This is the name that the user used to log in. Since the value in the
|
||||
environment can be tweaked arbitrarily, this is not a reliable way to
|
||||
identify the user who is running a process; a function like
|
||||
identify the user who is running a program; a function like
|
||||
@code{getlogin} (@pxref{Who Logged In}) is better for that purpose.
|
||||
|
||||
For most purposes, it is better to use @code{LOGNAME}, precisely because
|
||||
@ -562,6 +580,113 @@ reordering of command line arguments by @code{getopt} and
|
||||
@c !!! GNU also has COREFILE, CORESERVER, EXECSERVERS
|
||||
@end table
|
||||
|
||||
@node System Calls
|
||||
@section System Calls
|
||||
|
||||
@cindex system call
|
||||
A system call is a request for service that a program makes of the
|
||||
kernel. The service is generally something that only the kernel has
|
||||
the privilege to do, such as doing I/O. Programmers don't normally
|
||||
need to be concerned with system calls because there are functions in
|
||||
the GNU C library to do virtually everything that system calls do.
|
||||
These functions work by making system calls themselves. For example,
|
||||
there is a system call that changes the permissions of a file, but
|
||||
you don't need to know about it because you can just use the GNU C
|
||||
library's @code{chmod} function.
|
||||
|
||||
@cindex kernel call
|
||||
System calls are sometimes called kernel calls.
|
||||
|
||||
However, there are times when you want to make a system call explicitly,
|
||||
and for that, the GNU C library provides the @code{syscall} function.
|
||||
@code{syscall} is harder to use and less portable than functions like
|
||||
@code{chmod}, but easier and more portable than coding the system call
|
||||
in assembler instructions.
|
||||
|
||||
@code{syscall} is most useful when you are working with a system call
|
||||
which is special to your system or is newer than the GNU C library you
|
||||
are using. @code{syscall} is implemented in an entirely generic way;
|
||||
the function does not know anything about what a particular system
|
||||
call does or even if it is valid.
|
||||
|
||||
The description of @code{syscall} in this section assumes a certain
|
||||
protocol for system calls on the various platforms on which the GNU C
|
||||
library runs. That protocol is not defined by any strong authority, but
|
||||
we won't describe it here either because anyone who is coding
|
||||
@code{syscall} probably won't accept anything less than kernel and C
|
||||
library source code as a specification of the interface between them
|
||||
anyway.
|
||||
|
||||
|
||||
@code{syscall} is declared in @file{unistd.h}.
|
||||
|
||||
@comment unistd.h
|
||||
@comment ???
|
||||
@deftypefun long int syscall (long int @var{sysno}, ...)
|
||||
|
||||
@code{syscall} performs a generic system call.
|
||||
|
||||
@cindex system call number
|
||||
@var{sysno} is the system call number. Each kind of system call is
|
||||
identified by a number. Macros for all the possible system call numbers
|
||||
are defined in @file{sys/syscall.h}
|
||||
|
||||
The remaining arguments are the arguments for the system call, in
|
||||
order, and their meanings depend on the kind of system call. Each kind
|
||||
of system call has a definite number of arguments, from zero to five.
|
||||
If you code more arguments than the system call takes, the extra ones to
|
||||
the right are ignored.
|
||||
|
||||
The return value is the return value from the system call, unless the
|
||||
system call failed. In that case, @code{syscall} returns @code{-1} and
|
||||
sets @code{errno} to an error code that the system call returned. Note
|
||||
that system calls do not return @code{-1} when they succeed.
|
||||
@cindex errno
|
||||
|
||||
If you specify an invalid @var{sysno}, @code{syscall} returns @code{-1}
|
||||
with @code{errno} = @code{ENOSYS}.
|
||||
|
||||
Example:
|
||||
|
||||
@smallexample
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <errno.h>
|
||||
|
||||
...
|
||||
|
||||
int rc;
|
||||
|
||||
rc = syscall(SYS_chmod, "/etc/passwd", 0444);
|
||||
|
||||
if (rc == -1)
|
||||
fprintf(stderr, "chmod failed, errno = %d\n", errno);
|
||||
|
||||
@end smallexample
|
||||
|
||||
This, if all the compatibility stars are aligned, is equivalent to the
|
||||
following preferable code:
|
||||
|
||||
@smallexample
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
|
||||
...
|
||||
|
||||
int rc;
|
||||
|
||||
rc = chmod("/etc/passwd", 0444);
|
||||
if (rc == -1)
|
||||
fprintf(stderr, "chmod failed, errno = %d\n", errno);
|
||||
|
||||
@end smallexample
|
||||
|
||||
@end deftypefun
|
||||
|
||||
|
||||
@node Program Termination
|
||||
@section Program Termination
|
||||
@cindex program termination
|
||||
@ -595,15 +720,19 @@ a signal that kills the program.
|
||||
@node Normal Termination
|
||||
@subsection Normal Termination
|
||||
|
||||
A process terminates normally when the program calls @code{exit}.
|
||||
Returning from @code{main} is equivalent to calling @code{exit}, and
|
||||
the value that @code{main} returns is used as the argument to @code{exit}.
|
||||
A process terminates normally when its program signals it is done by
|
||||
calling @code{exit}. Returning from @code{main} is equivalent to
|
||||
calling @code{exit}, and the value that @code{main} returns is used as
|
||||
the argument to @code{exit}.
|
||||
|
||||
@comment stdlib.h
|
||||
@comment ISO
|
||||
@deftypefun void exit (int @var{status})
|
||||
The @code{exit} function terminates the process with status
|
||||
@var{status}. This function does not return.
|
||||
The @code{exit} function tells the system that the program is done, which
|
||||
causes it to terminate the process.
|
||||
|
||||
@var{status} is the program's exit status, which becomes part of the
|
||||
process' termination status. This function does not return.
|
||||
@end deftypefun
|
||||
|
||||
Normal termination causes the following actions:
|
||||
@ -695,6 +824,12 @@ kinds of "non-success". For example, @code{diff} uses status value
|
||||
mean that there was difficulty in opening the files.
|
||||
@end deftypevr
|
||||
|
||||
Don't confuse a program's exit status with a process' termination status.
|
||||
There are lots of ways a process can terminate besides having it's program
|
||||
finish. In the event that the process termination @emph{is} caused by program
|
||||
termination (i.e. @code{exit}), though, the program's exit status becomes
|
||||
part of the process' termination status.
|
||||
|
||||
@node Cleanups on Exit
|
||||
@subsection Cleanups on Exit
|
||||
|
||||
@ -796,8 +931,8 @@ This function was introduced in @w{ISO C99} and is declared in
|
||||
@file{stdlib.h}.
|
||||
@end deftypefun
|
||||
|
||||
When a process terminates for any reason---either by an explicit
|
||||
termination call, or termination as a result of a signal---the
|
||||
When a process terminates for any reason---either because the program
|
||||
terminates, or as a result of a signal---the
|
||||
following things happen:
|
||||
|
||||
@itemize @bullet
|
||||
@ -807,9 +942,11 @@ Note that streams are not flushed automatically when the process
|
||||
terminates; see @ref{I/O on Streams}.
|
||||
|
||||
@item
|
||||
The low-order 8 bits of the return status code are saved to be reported
|
||||
back to the parent process via @code{wait} or @code{waitpid}; see
|
||||
@ref{Process Completion}.
|
||||
A process exit status is saved to be reported back to the parent process
|
||||
via @code{wait} or @code{waitpid}; see @ref{Process Completion}. If the
|
||||
program exited, this status includes as its low-order 8 bits the program
|
||||
exit status.
|
||||
|
||||
|
||||
@item
|
||||
Any child processes of the process being terminated are assigned a new
|
||||
|
6
po/gl.po
6
po/gl.po
@ -3227,11 +3227,11 @@ msgstr "mcheck_status falso, a librer
|
||||
|
||||
#: sunrpc/pmap_rmt.c:185
|
||||
msgid "broadcast: ioctl (get interface configuration)"
|
||||
msgstr "multidifusión: ioctl (obte-la configuración do interfaz)"
|
||||
msgstr "multidifusión: ioctl (obte-la configuración da interface)"
|
||||
|
||||
#: sunrpc/pmap_rmt.c:194
|
||||
msgid "broadcast: ioctl (get interface flags)"
|
||||
msgstr "multidifusión: ioctl (obte-los parámetros do interfaz)"
|
||||
msgstr "multidifusión: ioctl (obte-los parámetros da interface)"
|
||||
|
||||
#: login/programs/request.c:167
|
||||
msgid "buffer overflow"
|
||||
@ -3739,7 +3739,7 @@ msgstr "xerar un perfil plano con contas e tempos"
|
||||
|
||||
#: sunrpc/get_myaddr.c:77
|
||||
msgid "get_myaddress: ioctl (get interface configuration)"
|
||||
msgstr "get_myaddress: ioctl (obte-la configuración do interfaz)"
|
||||
msgstr "get_myaddress: ioctl (obte-la configuración da interface)"
|
||||
|
||||
#: nss/getent.c:54
|
||||
msgid "getent - get entries from administrative database."
|
||||
|
@ -266,7 +266,6 @@ extern struct __res_state _res;
|
||||
#define p_query __p_query
|
||||
#define res_close __res_close
|
||||
#define res_isourserver __res_isourserver
|
||||
#define res_querydomain __res_querydomain
|
||||
#define res_send __res_send
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*Environment handling for dynamic loader.
|
||||
Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
|
||||
/* Environment handling for dynamic loader.
|
||||
Copyright (C) 1995, 1996, 1997, 1998, 2000 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,8 @@ unsetenv (const char *name)
|
||||
const size_t len = strlen (name);
|
||||
char **ep;
|
||||
|
||||
for (ep = _environ; *ep != NULL; ++ep)
|
||||
ep = _environ;
|
||||
while (*ep != NULL)
|
||||
if (!strncmp (*ep, name, len) && (*ep)[len] == '=')
|
||||
{
|
||||
/* Found it. Remove this pointer by moving later ones back. */
|
||||
@ -66,4 +67,6 @@ unsetenv (const char *name)
|
||||
while (*dp++);
|
||||
/* Continue the loop in case NAME appears again. */
|
||||
}
|
||||
else
|
||||
++ep;
|
||||
}
|
||||
|
@ -132,34 +132,6 @@ getfct (const char *to, const char *from)
|
||||
})
|
||||
|
||||
|
||||
/* The gconv functions expects the name to be complete, including the
|
||||
trailing shashes if necessary. */
|
||||
#define norm_add_slashes(str) \
|
||||
({ \
|
||||
const char *cp = str; \
|
||||
char *result; \
|
||||
char *tmp; \
|
||||
size_t cnt = 0; \
|
||||
\
|
||||
while (*cp != '\0') \
|
||||
if (*cp++ == '/') \
|
||||
++cnt; \
|
||||
\
|
||||
tmp = result = alloca (cp - str + 3); \
|
||||
cp = str; \
|
||||
while (*cp != '\0') \
|
||||
*tmp++ = _toupper (*cp++); \
|
||||
if (cnt < 2) \
|
||||
{ \
|
||||
*tmp++ = '/'; \
|
||||
if (cnt < 1) \
|
||||
*tmp++ = '/'; \
|
||||
} \
|
||||
*tmp = '\0'; \
|
||||
result; \
|
||||
})
|
||||
|
||||
|
||||
/* We must modify global data. */
|
||||
__libc_lock_define_initialized (static, lock)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user