* 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:
Ulrich Drepper 2000-05-04 02:46:54 +00:00
parent 160016c945
commit 17c389fc2b
22 changed files with 752 additions and 233 deletions

View File

@ -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.

View File

@ -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;

View File

@ -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)

View File

@ -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

View File

@ -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);
}

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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__

View File

@ -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));

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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."

View File

@ -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

View File

@ -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;
}

View File

@ -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)