aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>1999-06-28 15:52:36 +0000
committerUlrich Drepper <drepper@redhat.com>1999-06-28 15:52:36 +0000
commitb3fc5f84d13573b9494fb1f0db9b5e80679e5098 (patch)
treedc0a71f8e940437cbc744a1b2fb9e8a01913a5a8
parent738d1a5a43e97ee81d7b62a3c7a5f754f5b51b82 (diff)
downloadglibc-b3fc5f84d13573b9494fb1f0db9b5e80679e5098.tar
glibc-b3fc5f84d13573b9494fb1f0db9b5e80679e5098.tar.gz
glibc-b3fc5f84d13573b9494fb1f0db9b5e80679e5098.tar.bz2
glibc-b3fc5f84d13573b9494fb1f0db9b5e80679e5098.zip
Update.
* sysdeps/libm-ieee754/e_gamma_r.c: Initialize *signgamp for NaN returns. * sysdeps/libm-ieee754/e_gammaf_r.c: Likewise. * sysdeps/libm-ieee754/e_gammal_r.c: Likewise. Reported by John Reiser <jreiser@BitWagon.com> [PR libc/1185]. * elf/dl-dst.h: Fix typo. * elf/dl-open.c: Likewise. 1999-06-26 Zack Weinberg <zack@rabi.columbia.edu> * elf/dl-libc.c: New file, provides three functions: __libc_dlopen, __libc_dlclose, __libc_dlsym. * include/dlfcn.h: Prototype them. Prototype _dl_addr. * elf/Makefile (routines): Add dl-libc.c. * elf/dl-profstub.c (_dl_mcount_wrapper): Change type of argument to void *. * elf/ldsodefs.h: Change proto and use of _dl_mcount_wrapper to match. * iconv/gconv.c: Include dlfcn.h. * iconv/gconv_db.c: Likewise. * malloc/mtrace.c: Likewise. Don't include ldsodefs.h. * iconv/gconv_int.h (struct __gconv_loaded_object): Change `handle' to a void *. (__gconv_find_func): Delete prototype. * iconv/gconv_dl.c: Don't include ldsodefs.h. Remove dlerror_run and related functions and structs. Use __libc_dlopen, __libc_dlsym, __libc_dlclose. * nss/nsswitch.c: Likewise. 1999-06-28 Ulrich Drepper <drepper@cygnus.com>
-rw-r--r--ChangeLog34
-rw-r--r--elf/Makefile2
-rw-r--r--elf/dl-dst.h2
-rw-r--r--elf/dl-libc.c122
-rw-r--r--elf/dl-open.c2
-rw-r--r--elf/dl-profstub.c5
-rw-r--r--elf/ldsodefs.h4
-rw-r--r--iconv/gconv.c2
-rw-r--r--iconv/gconv_db.c1
-rw-r--r--iconv/gconv_dl.c93
-rw-r--r--iconv/gconv_int.h6
-rw-r--r--include/dlfcn.h7
-rw-r--r--malloc/mtrace.c2
-rw-r--r--nss/nsswitch.c77
-rw-r--r--sysdeps/libm-ieee754/e_gamma_r.c10
-rw-r--r--sysdeps/libm-ieee754/e_gammaf_r.c10
-rw-r--r--sysdeps/libm-ieee754/e_gammal_r.c10
17 files changed, 214 insertions, 175 deletions
diff --git a/ChangeLog b/ChangeLog
index 2c8874b0c8..48bc56bdd8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,39 @@
1999-06-28 Ulrich Drepper <drepper@cygnus.com>
+ * sysdeps/libm-ieee754/e_gamma_r.c: Initialize *signgamp for NaN
+ returns.
+ * sysdeps/libm-ieee754/e_gammaf_r.c: Likewise.
+ * sysdeps/libm-ieee754/e_gammal_r.c: Likewise.
+ Reported by John Reiser <jreiser@BitWagon.com> [PR libc/1185].
+
+ * elf/dl-dst.h: Fix typo.
+ * elf/dl-open.c: Likewise.
+
+1999-06-26 Zack Weinberg <zack@rabi.columbia.edu>
+
+ * elf/dl-libc.c: New file, provides three functions:
+ __libc_dlopen, __libc_dlclose, __libc_dlsym.
+ * include/dlfcn.h: Prototype them. Prototype _dl_addr.
+ * elf/Makefile (routines): Add dl-libc.c.
+ * elf/dl-profstub.c (_dl_mcount_wrapper): Change type of
+ argument to void *.
+ * elf/ldsodefs.h: Change proto and use of _dl_mcount_wrapper to match.
+
+ * iconv/gconv.c: Include dlfcn.h.
+ * iconv/gconv_db.c: Likewise.
+ * malloc/mtrace.c: Likewise. Don't include ldsodefs.h.
+
+ * iconv/gconv_int.h (struct __gconv_loaded_object): Change
+ `handle' to a void *.
+ (__gconv_find_func): Delete prototype.
+
+ * iconv/gconv_dl.c: Don't include ldsodefs.h. Remove
+ dlerror_run and related functions and structs. Use
+ __libc_dlopen, __libc_dlsym, __libc_dlclose.
+ * nss/nsswitch.c: Likewise.
+
+1999-06-28 Ulrich Drepper <drepper@cygnus.com>
+
* sysdeps/unix/sysv/linux/gethostid.c: Test for gethostbyname_r
function correctly.
diff --git a/elf/Makefile b/elf/Makefile
index 6c526437e2..b5145ea025 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -22,7 +22,7 @@ subdir := elf
headers = elf.h bits/elfclass.h bits/dlfcn.h link.h dlfcn.h
routines = $(dl-routines) dl-open dl-close dl-symbol dl-support \
- dl-addr enbl-secure dl-profstub dl-origin
+ dl-addr enbl-secure dl-profstub dl-origin dl-libc
# The core dynamic linking functions are in libc for the static and
# profiled libraries.
diff --git a/elf/dl-dst.h b/elf/dl-dst.h
index 4b014d6ed5..ca32e25104 100644
--- a/elf/dl-dst.h
+++ b/elf/dl-dst.h
@@ -33,7 +33,7 @@
extern size_t _dl_dst_count (const char *name, int is_path);
-/* Guess from the number of DSTs the length of the restul string. */
+/* Guess from the number of DSTs the length of the result string. */
#define DL_DST_REQUIRED(l, name, len, cnt) \
({ \
size_t origin_len; \
diff --git a/elf/dl-libc.c b/elf/dl-libc.c
new file mode 100644
index 0000000000..afb3f2d14e
--- /dev/null
+++ b/elf/dl-libc.c
@@ -0,0 +1,122 @@
+/* Handle loading and unloading shared objects for internal libc purposes.
+ Copyright (C) 1999 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Zack Weinberg <zack@rabi.columbia.edu>, 1999.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include <dlfcn.h>
+#include <stdlib.h>
+#include <ldsodefs.h>
+
+/* The purpose of this file is to provide wrappers around the dynamic
+ linker error mechanism (similar to dlopen() et al in libdl) which
+ are usable from within libc. Generally we want to throw away the
+ string that dlerror() would return and just pass back a null pointer
+ for errors. This also lets the rest of libc not know about the error
+ handling mechanism.
+
+ Much of this code came from gconv_dl.c with slight modifications. */
+
+static int
+internal_function
+dlerror_run (void (*operate) (void *), void *args)
+{
+ char *last_errstring = NULL;
+ int result;
+
+ (void) _dl_catch_error (&last_errstring, operate, args);
+
+ result = last_errstring != NULL;
+ if (result)
+ free (last_errstring);
+
+ return result;
+}
+
+/* These functions are called by dlerror_run... */
+
+struct do_dlopen_args
+{
+ /* Argument to do_dlopen. */
+ const char *name;
+
+ /* Return from do_dlopen. */
+ struct link_map *map;
+};
+
+struct do_dlsym_args
+{
+ /* Arguments to do_dlsym. */
+ struct link_map *map;
+ const char *name;
+
+ /* Return values of do_dlsym. */
+ ElfW(Addr) loadbase;
+ const ElfW(Sym) *ref;
+};
+
+static void
+do_dlopen (void *ptr)
+{
+ struct do_dlopen_args *args = (struct do_dlopen_args *) ptr;
+ /* Open and relocate the shared object. */
+ args->map = _dl_open (args->name, RTLD_LAZY, NULL);
+}
+
+static void
+do_dlsym (void *ptr)
+{
+ struct do_dlsym_args *args = (struct do_dlsym_args *) ptr;
+ args->ref = NULL;
+ args->loadbase = _dl_lookup_symbol (args->name, &args->ref,
+ args->map->l_local_scope,
+ args->map->l_name, 0);
+}
+
+static void
+do_dlclose (void *ptr)
+{
+ _dl_close ((struct link_map *) ptr);
+}
+
+/* ... and these functions call dlerror_run. */
+
+void *
+__libc_dlopen (const char *__name)
+{
+ struct do_dlopen_args args;
+ args.name = __name;
+
+ return (dlerror_run (do_dlopen, &args) ? NULL : (void *) args.map);
+}
+
+void *
+__libc_dlsym (void *__map, const char *__name)
+{
+ struct do_dlsym_args args;
+ args.map = __map;
+ args.name = __name;
+
+ return (dlerror_run (do_dlsym, &args) ? NULL
+ : (void *) (args.loadbase + args.ref->st_value));
+}
+
+int
+__libc_dlclose (void *__map)
+{
+ return dlerror_run (do_dlclose, __map);
+}
diff --git a/elf/dl-open.c b/elf/dl-open.c
index 149badd618..a9d81c75a8 100644
--- a/elf/dl-open.c
+++ b/elf/dl-open.c
@@ -127,7 +127,7 @@ dl_open_worker (void *a)
/* If the substitution failed don't try to load. */
if (*new_file == '\0')
_dl_signal_error (0, "dlopen",
- "empty dynamics string token substitution");
+ "empty dynamic string token substitution");
/* Now we have a new file name. */
file = new_file;
diff --git a/elf/dl-profstub.c b/elf/dl-profstub.c
index 10db640769..55304a73df 100644
--- a/elf/dl-profstub.c
+++ b/elf/dl-profstub.c
@@ -28,9 +28,10 @@ extern struct link_map *_dl_profile_map;
void
-_dl_mcount_wrapper (ElfW(Addr) selfpc)
+_dl_mcount_wrapper (void *selfpc)
{
- _dl_mcount ((ElfW(Addr)) __builtin_return_address (0), selfpc);
+ _dl_mcount ((ElfW(Addr)) __builtin_return_address (0),
+ (ElfW(Addr)) selfpc);
}
diff --git a/elf/ldsodefs.h b/elf/ldsodefs.h
index f8db76c32c..bd33ba15ee 100644
--- a/elf/ldsodefs.h
+++ b/elf/ldsodefs.h
@@ -407,7 +407,7 @@ extern void _dl_mcount (ElfW(Addr) frompc, ElfW(Addr) selfpc);
/* This function is simply a wrapper around the _dl_mcount function
which does not require a FROMPC parameter since this is the
calling function. */
-extern void _dl_mcount_wrapper (ElfW(Addr) selfpc);
+extern void _dl_mcount_wrapper (void *selfpc);
/* Show the members of the auxiliary array passed up from the kernel. */
@@ -432,7 +432,7 @@ extern const struct r_strlenpair *_dl_important_hwcaps (const char *platform,
helps do it. */
#define _CALL_DL_FCT(fctp, args) \
({ if (_dl_profile_map != NULL) \
- _dl_mcount_wrapper ((ElfW(Addr)) fctp); \
+ _dl_mcount_wrapper (fctp); \
(*fctp) args; \
})
diff --git a/iconv/gconv.c b/iconv/gconv.c
index 828db9d6f8..3120f00b3f 100644
--- a/iconv/gconv.c
+++ b/iconv/gconv.c
@@ -22,7 +22,7 @@
#include <assert.h>
#include <gconv.h>
#include <sys/param.h>
-
+#include <dlfcn.h>
#include <ldsodefs.h>
int
diff --git a/iconv/gconv_db.c b/iconv/gconv_db.c
index 727be41c25..39292994d8 100644
--- a/iconv/gconv_db.c
+++ b/iconv/gconv_db.c
@@ -25,6 +25,7 @@
#include <sys/param.h>
#include <bits/libc-lock.h>
+#include <dlfcn.h>
#include <ldsodefs.h>
#include <gconv_int.h>
diff --git a/iconv/gconv_dl.c b/iconv/gconv_dl.c
index dc90986077..7d327edc68 100644
--- a/iconv/gconv_dl.c
+++ b/iconv/gconv_dl.c
@@ -26,10 +26,8 @@
#include <bits/libc-lock.h>
#include <sys/param.h>
-#include <ldsodefs.h>
#include <gconv_int.h>
-
/* This is a tuning parameter. If a transformation module is not used
anymore it gets not immediately unloaded. Instead we wait a certain
number of load attempts for further modules. If none of the
@@ -39,13 +37,10 @@
before unloading. */
#define TRIES_BEFORE_UNLOAD 2
-
/* Array of loaded objects. This is shared by all threads so we have
to use semaphores to access it. */
static void *loaded;
-
-
/* Comparison function for searching `loaded_object' tree. */
static int
known_compare (const void *p1, const void *p2)
@@ -58,70 +53,6 @@ known_compare (const void *p1, const void *p2)
return (intptr_t) s1->handle - (intptr_t) s2->handle;
}
-
-static void
-do_open (void *a)
-{
- struct __gconv_loaded_object *args = (struct __gconv_loaded_object *) a;
- /* Open and relocate the shared object. */
- args->handle = _dl_open (args->name, RTLD_LAZY, NULL);
-}
-
-
-static int
-internal_function
-dlerror_run (void (*operate) (void *), void *args)
-{
- char *last_errstring = NULL;
- int result;
-
- (void) _dl_catch_error (&last_errstring, operate, args);
-
- result = last_errstring != NULL;
- if (result)
- free (last_errstring);
-
- return result;
-}
-
-
-struct get_sym_args
-{
- /* Arguments to get_sym. */
- struct link_map *map;
- const char *name;
-
- /* Return values of get_sym. */
- ElfW(Addr) loadbase;
- const ElfW(Sym) *ref;
-};
-
-static void
-get_sym (void *a)
-{
- struct get_sym_args *args = (struct get_sym_args *) a;
- args->ref = NULL;
- args->loadbase = _dl_lookup_symbol (args->name, &args->ref,
- args->map->l_local_scope,
- args->map->l_name, 0);
-}
-
-
-void *
-internal_function
-__gconv_find_func (void *handle, const char *name)
-{
- struct get_sym_args args;
-
- args.map = handle;
- args.name = name;
-
- return (dlerror_run (get_sym, &args) ? NULL
- : (void *) (args.loadbase + args.ref->st_value));
-}
-
-
-
/* Open the gconv database if necessary. A non-negative return value
means success. */
struct __gconv_loaded_object *
@@ -170,9 +101,10 @@ __gconv_find_shlib (const char *name)
{
if (found->counter < -TRIES_BEFORE_UNLOAD)
{
- if (dlerror_run (do_open, found) == 0)
+ found->handle = __libc_dlopen (found->name);
+ if (found->handle != NULL)
{
- found->fct = __gconv_find_func (found->handle, "gconv");
+ found->fct = __libc_dlsym (found->handle, "gconv");
if (found->fct == NULL)
{
/* Argh, no conversion function. There is something
@@ -182,10 +114,8 @@ __gconv_find_shlib (const char *name)
}
else
{
- found->init_fct = __gconv_find_func (found->handle,
- "gconv_init");
- found->end_fct = __gconv_find_func (found->handle,
- "gconv_end");
+ found->init_fct = __libc_dlsym (found->handle, "gconv_init");
+ found->end_fct = __libc_dlsym (found->handle, "gconv_end");
/* We have succeeded in loading the shared object. */
found->counter = 1;
@@ -224,11 +154,8 @@ do_release_shlib (const void *nodep, VISIT value, int level)
{
if (--obj->counter < -TRIES_BEFORE_UNLOAD && obj->handle != NULL)
{
- /* Unload the shared object. We don't use the trick to
- catch errors since in the case an error is signalled
- something is really wrong. */
- _dl_close (obj->handle);
-
+ /* Unload the shared object. */
+ __libc_dlclose (obj->handle);
obj->handle = NULL;
}
}
@@ -258,11 +185,9 @@ do_release_all (void *nodep)
{
struct __gconv_loaded_object *obj = (struct __gconv_loaded_object *) nodep;
- /* Unload the shared object. We don't use the trick to
- catch errors since in the case an error is signalled
- something is really wrong. */
+ /* Unload the shared object. */
if (obj->handle != NULL)
- _dl_close (obj->handle);
+ __libc_dlclose (obj->handle);
free (obj);
}
diff --git a/iconv/gconv_int.h b/iconv/gconv_int.h
index 29f495c30f..6048319372 100644
--- a/iconv/gconv_int.h
+++ b/iconv/gconv_int.h
@@ -51,7 +51,7 @@ struct __gconv_loaded_object
int counter;
/* The handle for the shared object. */
- struct link_map *handle;
+ void *handle;
/* Pointer to the functions the module defines. */
__gconv_fct fct;
@@ -135,10 +135,6 @@ extern int __gconv_close_transform (struct __gconv_step *__steps,
extern struct __gconv_loaded_object *__gconv_find_shlib (const char *__name)
internal_function;
-/* Find function named NAME in shared object referenced by HANDLE. */
-void *__gconv_find_func (void *handle, const char *name)
- internal_function;
-
/* Release shared object. If no further reference is available unload
the object. */
extern int __gconv_release_shlib (struct __gconv_loaded_object *__handle)
diff --git a/include/dlfcn.h b/include/dlfcn.h
index 955819739a..f875a636ae 100644
--- a/include/dlfcn.h
+++ b/include/dlfcn.h
@@ -4,4 +4,11 @@
/* Now define the internal interfaces. */
extern void *__dlvsym __P ((void *__handle, __const char *__name,
__const char *__version));
+
+extern void *__libc_dlopen __P ((__const char *__name));
+extern void *__libc_dlsym __P ((void *__map, __const char *__name));
+extern int __libc_dlclose __P ((void *__map));
+extern int _dl_addr __P ((const void *address, Dl_info *info))
+ internal_function;
+
#endif
diff --git a/malloc/mtrace.c b/malloc/mtrace.c
index c539cb47ea..4e6e1e5efb 100644
--- a/malloc/mtrace.c
+++ b/malloc/mtrace.c
@@ -28,7 +28,7 @@
#include <bits/libc-lock.h>
#endif
-#include <ldsodefs.h>
+#include <dlfcn.h>
#include <stdio.h>
#include <string.h>
diff --git a/nss/nsswitch.c b/nss/nsswitch.c
index 0fac09ef65..f1250262ff 100644
--- a/nss/nsswitch.c
+++ b/nss/nsswitch.c
@@ -26,7 +26,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <ldsodefs.h> /* We need some help from ld.so. */
#if !defined DO_STATIC_NSS || defined PIC
# include <gnu/lib-names.h>
@@ -245,60 +244,6 @@ __nss_configure_lookup (const char *dbname, const char *service_line)
}
-#if !defined DO_STATIC_NSS || defined PIC
-static int
-nss_dlerror_run (void (*operate) (void *), void *args)
-{
- char *last_errstring = NULL;
- int result;
-
- (void) _dl_catch_error (&last_errstring, operate, args);
-
- result = last_errstring != NULL;
- if (result)
- free (last_errstring);
-
- return result;
-}
-
-
-struct do_open_args
-{
- /* Argument to do_open. */
- char *shlib_name;
- service_user *ni;
-};
-
-struct get_sym_args
-{
- /* Arguments to get_sym. */
- struct link_map *map;
- char *name;
-
- /* Return values of get_sym. */
- ElfW(Addr) loadbase;
- const ElfW(Sym) *ref;
-};
-
-static void
-do_open (void *a)
-{
- struct do_open_args *args = (struct do_open_args *) a;
- /* Open and relocate the shared object. */
- args->ni->library->lib_handle = _dl_open (args->shlib_name, RTLD_LAZY, NULL);
-}
-
-static void
-get_sym (void *a)
-{
- struct get_sym_args *args = (struct get_sym_args *) a;
- args->ref = NULL;
- args->loadbase = _dl_lookup_symbol (args->name, &args->ref,
- args->map->l_local_scope,
- args->map->l_name, 0);
-}
-#endif
-
/* Comparison function for searching NI->known tree. */
static int
known_compare (const void *p1, const void *p2)
@@ -376,18 +321,17 @@ __nss_lookup_function (service_user *ni, const char *fct_name)
size_t shlen = (7 + strlen (ni->library->name) + 3
+ strlen (__nss_shlib_revision) + 1);
int saved_errno = errno;
- struct do_open_args args;
- args.shlib_name = __alloca (shlen);
- args.ni = ni;
+ char shlib_name[shlen];
/* Construct shared object name. */
- __stpcpy (__stpcpy (__stpcpy (__stpcpy (args.shlib_name,
+ __stpcpy (__stpcpy (__stpcpy (__stpcpy (shlib_name,
"libnss_"),
ni->library->name),
".so"),
__nss_shlib_revision);
- if (nss_dlerror_run (do_open, &args) != 0)
+ ni->library->lib_handle = __libc_dlopen (shlib_name);
+ if (ni->library->lib_handle == NULL)
{
/* Failed to load the library. */
ni->library->lib_handle = (void *) -1l;
@@ -400,22 +344,19 @@ __nss_lookup_function (service_user *ni, const char *fct_name)
result = NULL;
else
{
- /* Get the desired function. Again, GNU ld.so magic ahead. */
+ /* Get the desired function. */
size_t namlen = (5 + strlen (ni->library->name) + 1
+ strlen (fct_name) + 1);
- struct get_sym_args args;
- args.name = __alloca (namlen);
- args.map = ni->library->lib_handle;
+ char name[namlen];
/* Construct the function name. */
- __stpcpy (__stpcpy (__stpcpy (__stpcpy (args.name, "_nss_"),
+ __stpcpy (__stpcpy (__stpcpy (__stpcpy (name, "_nss_"),
ni->library->name),
"_"),
fct_name);
/* Look up the symbol. */
- result = (nss_dlerror_run (get_sym, &args) ? NULL
- : (void *) (args.loadbase + args.ref->st_value));
+ result = __libc_dlsym (ni->library->lib_handle, name);
}
#else
/* We can't get function address dynamically in static linking. */
@@ -796,7 +737,7 @@ free_mem (void)
{
service_library *oldl = library;
- _dl_close (library->lib_handle);
+ __libc_dlclose (library->lib_handle);
library = library->next;
free (oldl);
diff --git a/sysdeps/libm-ieee754/e_gamma_r.c b/sysdeps/libm-ieee754/e_gamma_r.c
index 901f1451d2..bd802c24f1 100644
--- a/sysdeps/libm-ieee754/e_gamma_r.c
+++ b/sysdeps/libm-ieee754/e_gamma_r.c
@@ -1,5 +1,5 @@
/* Implementation of gamma function according to ISO C.
- Copyright (C) 1997 Free Software Foundation, Inc.
+ Copyright (C) 1997, 1999 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
@@ -34,11 +34,15 @@ __ieee754_gamma_r (double x, int *signgamp)
EXTRACT_WORDS (hx, lx, x);
if (((hx & 0x7fffffff) | lx) == 0)
- /* Return value for x == 0 is NaN with invalid exception. */
- return x / x;
+ {
+ /* Return value for x == 0 is NaN with invalid exception. */
+ *signgamp = 0;
+ return x / x;
+ }
if (hx < 0 && (u_int32_t) hx < 0xfff00000 && __rint (x) == x)
{
/* Return value for integer x < 0 is NaN with invalid exception. */
+ *signgamp = 0;
return (x - x) / (x - x);
}
diff --git a/sysdeps/libm-ieee754/e_gammaf_r.c b/sysdeps/libm-ieee754/e_gammaf_r.c
index bf79ffeb57..926905e7cd 100644
--- a/sysdeps/libm-ieee754/e_gammaf_r.c
+++ b/sysdeps/libm-ieee754/e_gammaf_r.c
@@ -1,5 +1,5 @@
/* Implementation of gamma function according to ISO C.
- Copyright (C) 1997 Free Software Foundation, Inc.
+ Copyright (C) 1997, 1999 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
@@ -33,11 +33,15 @@ __ieee754_gammaf_r (float x, int *signgamp)
GET_FLOAT_WORD (hx, x);
if ((hx & 0x7fffffff) == 0)
- /* Return value for x == 0 is NaN with invalid exception. */
- return x / x;
+ {
+ /* Return value for x == 0 is NaN with invalid exception. */
+ *signgamp = 0;
+ return x / x;
+ }
if (hx < 0 && (u_int32_t) hx < 0xff800000 && __rintf (x) == x)
{
/* Return value for integer x < 0 is NaN with invalid exception. */
+ *signgamp = 0;
return (x - x) / (x - x);
}
diff --git a/sysdeps/libm-ieee754/e_gammal_r.c b/sysdeps/libm-ieee754/e_gammal_r.c
index 4fd49886d1..104992450b 100644
--- a/sysdeps/libm-ieee754/e_gammal_r.c
+++ b/sysdeps/libm-ieee754/e_gammal_r.c
@@ -1,5 +1,5 @@
/* Implementation of gamma function according to ISO C.
- Copyright (C) 1997 Free Software Foundation, Inc.
+ Copyright (C) 1997, 1999 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
@@ -33,11 +33,15 @@ __ieee754_gammal_r (long double x, int *signgamp)
GET_LDOUBLE_WORDS (es, hx, lx, x);
if (((es & 0x7fff) | hx | lx) == 0)
- /* Return value for x == 0 is NaN with invalid exception. */
- return x / x;
+ {
+ /* Return value for x == 0 is NaN with invalid exception. */
+ *signgamp = 0;
+ return x / x;
+ }
if ((hx & 0x8000) != 0 && (hx & 0x7fff) != 0x7fff && __rintl (x) == x)
{
/* Return value for integer x < 0 is NaN with invalid exception. */
+ *signgamp = 0;
return (x - x) / (x - x);
}