From 0ecb606cb6cf65de1d9fc8a919bceb4be476c602 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Thu, 12 Jul 2007 18:26:36 +0000 Subject: 2.5-18.1 --- stdlib/Depend | 1 + stdlib/Makefile | 44 +++- stdlib/abort.c | 140 +++++++++++ stdlib/add_n.c | 62 +++++ stdlib/addmul_1.c | 65 +++++ stdlib/bits/monetary-ldbl.h | 28 +++ stdlib/bits/stdlib-ldbl.h | 44 ++++ stdlib/bits/stdlib.h | 115 +++++++++ stdlib/bug-strtod2.c | 46 ++++ stdlib/canonicalize.c | 9 +- stdlib/cmp.c | 56 +++++ stdlib/cxa_atexit.c | 73 ++++-- stdlib/cxa_finalize.c | 33 ++- stdlib/dbl2mpn.c | 32 +++ stdlib/div.c | 86 +++++++ stdlib/divmod_1.c | 208 ++++++++++++++++ stdlib/divrem.c | 245 +++++++++++++++++++ stdlib/exit.c | 34 ++- stdlib/exit.h | 5 +- stdlib/fmtmsg.c | 78 ++---- stdlib/fpioconst.c | 2 +- stdlib/gen-mpn-copy | 35 --- stdlib/getcontext.c | 32 +++ stdlib/getenv.c | 98 ++++++++ stdlib/inlines.c | 3 + stdlib/jrand48_r.c | 4 +- stdlib/labs.c | 29 +++ stdlib/ldbl2mpn.c | 1 + stdlib/ldiv.c | 54 +++++ stdlib/llabs.c | 31 +++ stdlib/lldiv.c | 57 +++++ stdlib/longlong.h | 153 ++++++------ stdlib/lshift.c | 87 +++++++ stdlib/makecontext.c | 30 +++ stdlib/mod_1.c | 197 ++++++++++++++++ stdlib/monetary.h | 7 +- stdlib/mp_clz_tab.c | 37 +++ stdlib/mpn2dbl.c | 30 +++ stdlib/mpn2flt.c | 30 +++ stdlib/mpn2ldbl.c | 1 + stdlib/mul.c | 152 ++++++++++++ stdlib/mul_1.c | 59 +++++ stdlib/mul_n.c | 401 +++++++++++++++++++++++++++++++ stdlib/on_exit.c | 10 +- stdlib/putenv.c | 72 ++++++ stdlib/random_r.c | 28 ++- stdlib/rshift.c | 88 +++++++ stdlib/setcontext.c | 32 +++ stdlib/setenv.c | 353 +++++++++++++++++++++++++++ stdlib/stdlib.h | 162 +++++++------ stdlib/strfmon.c | 8 +- stdlib/strfmon_l.c | 84 +++---- stdlib/strtod.c | 15 +- stdlib/strtod_l.c | 101 +++++--- stdlib/strtoimax.c | 1 + stdlib/strtol.c | 111 +++++++++ stdlib/strtol_l.c | 564 ++++++++++++++++++++++++++++++++++++++++++++ stdlib/strtold.c | 36 ++- stdlib/strtold_l.c | 58 +++++ stdlib/strtoll.c | 34 +++ stdlib/strtoll_l.c | 28 +++ stdlib/strtoul.c | 21 ++ stdlib/strtoul_l.c | 28 +++ stdlib/strtoull.c | 34 +++ stdlib/strtoull_l.c | 29 +++ stdlib/strtoumax.c | 1 + stdlib/sub_n.c | 62 +++++ stdlib/submul_1.c | 65 +++++ stdlib/swapcontext.c | 33 +++ stdlib/system.c | 38 +++ stdlib/test-canon.c | 22 +- stdlib/test-canon2.c | 2 +- stdlib/tst-atof1.c | 19 ++ stdlib/tst-atof2.c | 55 +++++ stdlib/tst-fmtmsg.c | 32 ++- stdlib/tst-makecontext.c | 67 ++++++ stdlib/tst-putenv.c | 18 ++ stdlib/tst-putenvmod.c | 17 ++ stdlib/tst-rand48-2.c | 113 +++++++++ stdlib/tst-rand48.c | 28 +-- stdlib/tst-random2.c | 59 +++++ stdlib/tst-setcontext.c | 6 +- stdlib/tst-strtod2.c | 44 ++++ stdlib/tst-strtod3.c | 55 +++++ stdlib/tst-strtod4.c | 56 +++++ stdlib/udiv_qrnnd.c | 10 + stdlib/wcstoimax.c | 1 + stdlib/wcstoumax.c | 1 + 88 files changed, 5211 insertions(+), 424 deletions(-) create mode 100644 stdlib/Depend create mode 100644 stdlib/abort.c create mode 100644 stdlib/add_n.c create mode 100644 stdlib/addmul_1.c create mode 100644 stdlib/bits/monetary-ldbl.h create mode 100644 stdlib/bits/stdlib-ldbl.h create mode 100644 stdlib/bits/stdlib.h create mode 100644 stdlib/bug-strtod2.c create mode 100644 stdlib/cmp.c create mode 100644 stdlib/dbl2mpn.c create mode 100644 stdlib/div.c create mode 100644 stdlib/divmod_1.c create mode 100644 stdlib/divrem.c delete mode 100644 stdlib/gen-mpn-copy create mode 100644 stdlib/getcontext.c create mode 100644 stdlib/getenv.c create mode 100644 stdlib/inlines.c create mode 100644 stdlib/labs.c create mode 100644 stdlib/ldbl2mpn.c create mode 100644 stdlib/ldiv.c create mode 100644 stdlib/llabs.c create mode 100644 stdlib/lldiv.c create mode 100644 stdlib/lshift.c create mode 100644 stdlib/makecontext.c create mode 100644 stdlib/mod_1.c create mode 100644 stdlib/mp_clz_tab.c create mode 100644 stdlib/mpn2dbl.c create mode 100644 stdlib/mpn2flt.c create mode 100644 stdlib/mpn2ldbl.c create mode 100644 stdlib/mul.c create mode 100644 stdlib/mul_1.c create mode 100644 stdlib/mul_n.c create mode 100644 stdlib/putenv.c create mode 100644 stdlib/rshift.c create mode 100644 stdlib/setcontext.c create mode 100644 stdlib/setenv.c create mode 100644 stdlib/strtoimax.c create mode 100644 stdlib/strtol.c create mode 100644 stdlib/strtol_l.c create mode 100644 stdlib/strtold_l.c create mode 100644 stdlib/strtoll.c create mode 100644 stdlib/strtoll_l.c create mode 100644 stdlib/strtoul.c create mode 100644 stdlib/strtoul_l.c create mode 100644 stdlib/strtoull.c create mode 100644 stdlib/strtoull_l.c create mode 100644 stdlib/strtoumax.c create mode 100644 stdlib/sub_n.c create mode 100644 stdlib/submul_1.c create mode 100644 stdlib/swapcontext.c create mode 100644 stdlib/system.c create mode 100644 stdlib/tst-atof1.c create mode 100644 stdlib/tst-atof2.c create mode 100644 stdlib/tst-makecontext.c create mode 100644 stdlib/tst-putenv.c create mode 100644 stdlib/tst-putenvmod.c create mode 100644 stdlib/tst-rand48-2.c create mode 100644 stdlib/tst-random2.c create mode 100644 stdlib/tst-strtod2.c create mode 100644 stdlib/tst-strtod3.c create mode 100644 stdlib/tst-strtod4.c create mode 100644 stdlib/udiv_qrnnd.c create mode 100644 stdlib/wcstoimax.c create mode 100644 stdlib/wcstoumax.c (limited to 'stdlib') diff --git a/stdlib/Depend b/stdlib/Depend new file mode 100644 index 0000000000..f3e1156a4e --- /dev/null +++ b/stdlib/Depend @@ -0,0 +1 @@ +localedata diff --git a/stdlib/Makefile b/stdlib/Makefile index 5f4675033e..ecda85b0dd 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -1,4 +1,4 @@ -# Copyright (C) 1991-2002, 2003, 2004 Free Software Foundation, Inc. +# Copyright (C) 1991-2006, 2007 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 @@ -21,9 +21,12 @@ # subdir := stdlib -headers := stdlib.h alloca.h monetary.h fmtmsg.h ucontext.h sys/ucontext.h \ - inttypes.h stdint.h bits/wordsize.h bits/wchar.h \ - errno.h sys/errno.h bits/errno.h +headers := stdlib.h bits/stdlib.h bits/stdlib-ldbl.h \ + monetary.h bits/monetary-ldbl.h \ + inttypes.h stdint.h bits/wordsize.h \ + errno.h sys/errno.h bits/errno.h \ + ucontext.h sys/ucontext.h \ + alloca.h fmtmsg.h routines := \ atof atoi atol atoll \ @@ -61,10 +64,17 @@ distribute := exit.h grouping.h abort-instr.h isomac.c tst-fmtmsg.sh \ test-srcs := tst-fmtmsg tests := tst-strtol tst-strtod testmb testrand testsort testdiv \ test-canon test-canon2 tst-strtoll tst-environ \ - tst-xpg-basename tst-random tst-bsearch tst-limits \ - tst-rand48 bug-strtod tst-setcontext test-a64l tst-qsort \ - tst-system testmb2 + tst-xpg-basename tst-random tst-random2 tst-bsearch \ + tst-limits tst-rand48 bug-strtod tst-setcontext \ + test-a64l tst-qsort tst-system testmb2 bug-strtod2 \ + tst-atof1 tst-atof2 tst-strtod2 tst-strtod3 tst-rand48-2 \ + tst-makecontext tst-strtod4 +include ../Makeconfig + +ifeq ($(build-shared),yes) +tests += tst-putenv +endif # Several mpn functions from GNU MP are used by the strtod function. mpn-routines := inlines add_n addmul_1 cmp divmod_1 divrem udiv_qrnnd \ @@ -75,18 +85,20 @@ routines := $(strip $(routines) $(mpn-routines)) \ dbl2mpn ldbl2mpn \ mpn2flt mpn2dbl mpn2ldbl aux += fpioconst mp_clz_tab -distribute := $(distribute) $(mpn-headers) gen-mpn-copy fpioconst.h +distribute := $(distribute) $(mpn-headers) fpioconst.h tst-putenvmod.c + +tests-extras += tst-putenvmod +extra-test-objs += tst-putenvmod.os -generated += isomac isomac.out +generated += isomac isomac.out tst-putenvmod.so CFLAGS-bsearch.c = $(uses-callbacks) CFLAGS-msort.c = $(uses-callbacks) CFLAGS-qsort.c = $(uses-callbacks) CFLAGS-system.c = -fexceptions +CFLAGS-system.os = -fomit-frame-pointer CFLAGS-fmtmsg.c = -fexceptions -include ../Makeconfig - ifneq (,$(filter %REENTRANT, $(defines))) CFLAGS-strfmon.c = -D_IO_MTSAFE_IO CFLAGS-strfmon_l.c = -D_IO_MTSAFE_IO @@ -105,6 +117,8 @@ include ../Rules test-canon-ARGS = --test-dir=${common-objpfx}stdlib tst-strtod-ENV = LOCPATH=$(common-objpfx)localedata +tst-strtod3-ENV = LOCPATH=$(common-objpfx)localedata +tst-strtod4-ENV = LOCPATH=$(common-objpfx)localedata testmb2-ENV = LOCPATH=$(common-objpfx)localedata # Run a test on the header files we use. @@ -116,7 +130,7 @@ endif $(objpfx)isomac.out: $(objpfx)isomac $(dir $<)$(notdir $<) '$(CC)' \ - '-I../include -I.. $(+sysdep-includes) $(sysincludes)' > $<.out + '-I../include $(+sysdep-includes) $(sysincludes) -I..' > $<.out isomac-CFLAGS = -O $(objpfx)isomac: isomac.c @@ -124,3 +138,9 @@ $(objpfx)isomac: isomac.c $(objpfx)tst-fmtmsg.out: tst-fmtmsg.sh $(objpfx)tst-fmtmsg $(SHELL) -e $< $(common-objpfx) '$(run-program-prefix)' $(common-objpfx)stdlib/ + +$(objpfx)tst-putenv: $(objpfx)tst-putenvmod.so + +$(objpfx)tst-putenvmod.so: $(objpfx)tst-putenvmod.os + $(build-module) +CFLAGS-tst-putenvmod.c = -DNOT_IN_libc=1 diff --git a/stdlib/abort.c b/stdlib/abort.c new file mode 100644 index 0000000000..00788f22c7 --- /dev/null +++ b/stdlib/abort.c @@ -0,0 +1,140 @@ +/* Copyright (C) 1991,93,95,96,97,98,2001,02 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include + +/* Try to get a machine dependent instruction which will make the + program crash. This is used in case everything else fails. */ +#include +#ifndef ABORT_INSTRUCTION +/* No such instruction is available. */ +# define ABORT_INSTRUCTION +#endif + +#ifdef USE_IN_LIBIO +# include +# define fflush(s) _IO_flush_all_lockp (0) +#endif + +/* We must avoid to run in circles. Therefore we remember how far we + already got. */ +static int stage; + +/* We should be prepared for multiple threads trying to run abort. */ +__libc_lock_define_initialized_recursive (static, lock); + + +/* Cause an abnormal program termination with core-dump. */ +void +abort (void) +{ + struct sigaction act; + sigset_t sigs; + + /* First acquire the lock. */ + __libc_lock_lock_recursive (lock); + + /* Now it's for sure we are alone. But recursive calls are possible. */ + + /* Unlock SIGABRT. */ + if (stage == 0) + { + ++stage; + if (__sigemptyset (&sigs) == 0 && + __sigaddset (&sigs, SIGABRT) == 0) + __sigprocmask (SIG_UNBLOCK, &sigs, (sigset_t *) NULL); + } + + /* Flush all streams. We cannot close them now because the user + might have registered a handler for SIGABRT. */ + if (stage == 1) + { + ++stage; + fflush (NULL); + } + + /* Send signal which possibly calls a user handler. */ + if (stage == 2) + { + /* This stage is special: we must allow repeated calls of + `abort' when a user defined handler for SIGABRT is installed. + This is risky since the `raise' implementation might also + fail but I don't see another possibility. */ + int save_stage = stage; + + stage = 0; + __libc_lock_unlock_recursive (lock); + + raise (SIGABRT); + + __libc_lock_lock_recursive (lock); + stage = save_stage + 1; + } + + /* There was a handler installed. Now remove it. */ + if (stage == 3) + { + ++stage; + memset (&act, '\0', sizeof (struct sigaction)); + act.sa_handler = SIG_DFL; + __sigfillset (&act.sa_mask); + act.sa_flags = 0; + __sigaction (SIGABRT, &act, NULL); + } + + /* Now close the streams which also flushes the output the user + defined handler might has produced. */ + if (stage == 4) + { + ++stage; + __fcloseall (); + } + + /* Try again. */ + if (stage == 5) + { + ++stage; + raise (SIGABRT); + } + + /* Now try to abort using the system specific command. */ + if (stage == 6) + { + ++stage; + ABORT_INSTRUCTION; + } + + /* If we can't signal ourselves and the abort instruction failed, exit. */ + if (stage == 7) + { + ++stage; + _exit (127); + } + + /* If even this fails try to use the provided instruction to crash + or otherwise make sure we never return. */ + while (1) + /* Try for ever and ever. */ + ABORT_INSTRUCTION; +} +libc_hidden_def (abort) diff --git a/stdlib/add_n.c b/stdlib/add_n.c new file mode 100644 index 0000000000..280e30545a --- /dev/null +++ b/stdlib/add_n.c @@ -0,0 +1,62 @@ +/* mpn_add_n -- Add two limb vectors of equal, non-zero length. + +Copyright (C) 1992, 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or (at your +option) any later version. + +The GNU MP 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 Lesser General Public +License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include +#include "gmp-impl.h" + +mp_limb_t +#if __STDC__ +mpn_add_n (mp_ptr res_ptr, mp_srcptr s1_ptr, mp_srcptr s2_ptr, mp_size_t size) +#else +mpn_add_n (res_ptr, s1_ptr, s2_ptr, size) + register mp_ptr res_ptr; + register mp_srcptr s1_ptr; + register mp_srcptr s2_ptr; + mp_size_t size; +#endif +{ + register mp_limb_t x, y, cy; + register mp_size_t j; + + /* The loop counter and index J goes from -SIZE to -1. This way + the loop becomes faster. */ + j = -size; + + /* Offset the base pointers to compensate for the negative indices. */ + s1_ptr -= j; + s2_ptr -= j; + res_ptr -= j; + + cy = 0; + do + { + y = s2_ptr[j]; + x = s1_ptr[j]; + y += cy; /* add previous carry to one addend */ + cy = (y < cy); /* get out carry from that addition */ + y = x + y; /* add other addend */ + cy = (y < x) + cy; /* get out carry from that add, combine */ + res_ptr[j] = y; + } + while (++j != 0); + + return cy; +} diff --git a/stdlib/addmul_1.c b/stdlib/addmul_1.c new file mode 100644 index 0000000000..6ae1e57ad9 --- /dev/null +++ b/stdlib/addmul_1.c @@ -0,0 +1,65 @@ +/* mpn_addmul_1 -- multiply the S1_SIZE long limb vector pointed to by S1_PTR + by S2_LIMB, add the S1_SIZE least significant limbs of the product to the + limb vector pointed to by RES_PTR. Return the most significant limb of + the product, adjusted for carry-out from the addition. + +Copyright (C) 1992, 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or (at your +option) any later version. + +The GNU MP 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 Lesser General Public +License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include +#include "gmp-impl.h" +#include "longlong.h" + +mp_limb_t +mpn_addmul_1 (res_ptr, s1_ptr, s1_size, s2_limb) + register mp_ptr res_ptr; + register mp_srcptr s1_ptr; + mp_size_t s1_size; + register mp_limb_t s2_limb; +{ + register mp_limb_t cy_limb; + register mp_size_t j; + register mp_limb_t prod_high, prod_low; + register mp_limb_t x; + + /* The loop counter and index J goes from -SIZE to -1. This way + the loop becomes faster. */ + j = -s1_size; + + /* Offset the base pointers to compensate for the negative indices. */ + res_ptr -= j; + s1_ptr -= j; + + cy_limb = 0; + do + { + umul_ppmm (prod_high, prod_low, s1_ptr[j], s2_limb); + + prod_low += cy_limb; + cy_limb = (prod_low < cy_limb) + prod_high; + + x = res_ptr[j]; + prod_low = x + prod_low; + cy_limb += (prod_low < x); + res_ptr[j] = prod_low; + } + while (++j != 0); + + return cy_limb; +} diff --git a/stdlib/bits/monetary-ldbl.h b/stdlib/bits/monetary-ldbl.h new file mode 100644 index 0000000000..3e080f93f0 --- /dev/null +++ b/stdlib/bits/monetary-ldbl.h @@ -0,0 +1,28 @@ +/* -mlong-double-64 compatibility mode for monetary functions. + Copyright (C) 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _MONETARY_H +# error "Never include directly; use instead." +#endif + +__LDBL_REDIR_DECL (strfmon) + +#ifdef __USE_GNU +__LDBL_REDIR_DECL (strfmon_l) +#endif diff --git a/stdlib/bits/stdlib-ldbl.h b/stdlib/bits/stdlib-ldbl.h new file mode 100644 index 0000000000..b197c5754d --- /dev/null +++ b/stdlib/bits/stdlib-ldbl.h @@ -0,0 +1,44 @@ +/* -mlong-double-64 compatibility mode for functions. + Copyright (C) 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _STDLIB_H +# error "Never include directly; use instead." +#endif + +#ifdef __USE_ISOC99 +__BEGIN_NAMESPACE_C99 +__LDBL_REDIR1_DECL (strtold, strtod) +__END_NAMESPACE_C99 +#endif + +#ifdef __USE_GNU +__LDBL_REDIR1_DECL (strtold_l, strtod_l) +#endif + +__LDBL_REDIR1_DECL (__strtold_internal, __strtod_internal) + +#if defined __USE_SVID || defined __USE_XOPEN_EXTENDED +# ifdef __USE_MISC +__LDBL_REDIR1_DECL (qecvt, ecvt) +__LDBL_REDIR1_DECL (qfcvt, fcvt) +__LDBL_REDIR1_DECL (qgcvt, gcvt) +__LDBL_REDIR1_DECL (qecvt_r, ecvt_r) +__LDBL_REDIR1_DECL (qfcvt_r, fcvt_r) +# endif +#endif diff --git a/stdlib/bits/stdlib.h b/stdlib/bits/stdlib.h new file mode 100644 index 0000000000..4bacb09a09 --- /dev/null +++ b/stdlib/bits/stdlib.h @@ -0,0 +1,115 @@ +/* Checking macros for stdlib functions. + Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _STDLIB_H +# error "Never include directly; use instead." +#endif + +extern char *__realpath_chk (__const char *__restrict __name, + char *__restrict __resolved, + size_t __resolvedlen) __THROW __wur; +extern char *__REDIRECT_NTH (__realpath_alias, + (__const char *__restrict __name, + char *__restrict __resolved), realpath) __wur; + +extern __always_inline __wur char * +__NTH (realpath (__const char *__restrict __name, char *__restrict __resolved)) +{ + if (__bos (__resolved) != (size_t) -1) + return __realpath_chk (__name, __resolved, __bos (__resolved)); + + return __realpath_alias (__name, __resolved); +} + + +extern int __ptsname_r_chk (int __fd, char *__buf, size_t __buflen, + size_t __nreal) __THROW __nonnull ((2)); +extern int __REDIRECT_NTH (__ptsname_r_alias, (int __fd, char *__buf, + size_t __buflen), ptsname_r) + __nonnull ((2)); + +extern __always_inline int +__NTH (ptsname_r (int __fd, char *__buf, size_t __buflen)) +{ + if (__bos (__buf) != (size_t) -1 + && (!__builtin_constant_p (__buflen) || __buflen > __bos (__buf))) + return __ptsname_r_chk (__fd, __buf, __buflen, __bos (__buf)); + return __ptsname_r_alias (__fd, __buf, __buflen); +} + + +extern int __wctomb_chk (char *__s, wchar_t __wchar, size_t __buflen) + __THROW __wur; +extern int __REDIRECT_NTH (__wctomb_alias, (char *__s, wchar_t __wchar), + wctomb) __wur; + +extern __always_inline __wur int +__NTH (wctomb (char *__s, wchar_t __wchar)) +{ + /* We would have to include to get a definition of MB_LEN_MAX. + But this would only disturb the namespace. So we define our own + version here. */ +#define __STDLIB_MB_LEN_MAX 16 +#if defined MB_LEN_MAX && MB_LEN_MAX != __STDLIB_MB_LEN_MAX +# error "Assumed value of MB_LEN_MAX wrong" +#endif + if (__bos (__s) != (size_t) -1 && __STDLIB_MB_LEN_MAX > __bos (__s)) + return __wctomb_chk (__s, __wchar, __bos (__s)); + return __wctomb_alias (__s, __wchar); +} + + +extern size_t __mbstowcs_chk (wchar_t *__restrict __dst, + __const char *__restrict __src, + size_t __len, size_t __dstlen) __THROW; +extern size_t __REDIRECT_NTH (__mbstowcs_alias, + (wchar_t *__restrict __dst, + __const char *__restrict __src, + size_t __len), mbstowcs); + +extern __always_inline size_t +__NTH (mbstowcs (wchar_t *__restrict __dst, __const char *__restrict __src, + size_t __len)) +{ + if (__bos (__dst) != (size_t) -1 + && (!__builtin_constant_p (__len) + || __len > __bos (__dst) / sizeof (wchar_t))) + return __mbstowcs_chk (__dst, __src, __len, + __bos (__dst) / sizeof (wchar_t)); + return __mbstowcs_alias (__dst, __src, __len); +} + + +extern size_t __wcstombs_chk (char *__restrict __dst, + __const wchar_t *__restrict __src, + size_t __len, size_t __dstlen) __THROW; +extern size_t __REDIRECT_NTH (__wcstombs_alias, + (char *__restrict __dst, + __const wchar_t *__restrict __src, + size_t __len), wcstombs); + +extern __always_inline size_t +__NTH (wcstombs (char *__restrict __dst, __const wchar_t *__restrict __src, + size_t __len)) +{ + if (__bos (__dst) != (size_t) -1 + && (!__builtin_constant_p (__len) || __len > __bos (__dst))) + return __wcstombs_chk (__dst, __src, __len, __bos (__dst)); + return __wcstombs_alias (__dst, __src, __len); +} diff --git a/stdlib/bug-strtod2.c b/stdlib/bug-strtod2.c new file mode 100644 index 0000000000..a1f037cdc8 --- /dev/null +++ b/stdlib/bug-strtod2.c @@ -0,0 +1,46 @@ +#include +#include +#include +#include + +static const char *tests[] = + { + "inf", "Inf", "iNf", "inF", "INf", "iNF", "INF", "InF", + "infinity", "Infinity", "InfInity", "INFINITY" + }; +#define ntests (sizeof (tests) / sizeof (tests[0])) + +static int +do_test (void) +{ + /* The Turkish locale is notorious because tolower() maps 'I' to the + dotless lowercase 'i' and toupper() maps 'i' to an 'I' with a dot + above. */ + if (setlocale (LC_ALL, "tr_TR.UTF-8") == NULL) + { + puts ("cannot set locale"); + return 0; + } + + int res = 0; + for (int i = 0; i < ntests; ++i) + { + char *endp; + double d = strtod (tests[i], &endp); + if (*endp != '\0') + { + printf ("did not consume all of '%s'\n", tests[i]); + res = 1; + } + if (!isinf (d)) + { + printf ("'%s' does not pass isinf\n", tests[i]); + res = 1; + } + } + + return res; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/stdlib/canonicalize.c b/stdlib/canonicalize.c index 2168bbd90e..19808b50d6 100644 --- a/stdlib/canonicalize.c +++ b/stdlib/canonicalize.c @@ -1,5 +1,5 @@ /* Return the canonical absolute name of a given file. - Copyright (C) 1996-2001, 2002, 2004 Free Software Foundation, Inc. + Copyright (C) 1996-2002, 2004, 2005, 2006 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 @@ -91,7 +91,7 @@ __realpath (const char *name, char *resolved) rpath[0] = '\0'; goto error; } - dest = strchr (rpath, '\0'); + dest = __rawmemchr (rpath, '\0'); } else { @@ -199,6 +199,11 @@ __realpath (const char *name, char *resolved) if (dest > rpath + 1) while ((--dest)[-1] != '/'); } + else if (!S_ISDIR (st.st_mode) && *end != '\0') + { + __set_errno (ENOTDIR); + goto error; + } } } if (dest > rpath + 1 && dest[-1] == '/') diff --git a/stdlib/cmp.c b/stdlib/cmp.c new file mode 100644 index 0000000000..e7661702b6 --- /dev/null +++ b/stdlib/cmp.c @@ -0,0 +1,56 @@ +/* mpn_cmp -- Compare two low-level natural-number integers. + +Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or (at your +option) any later version. + +The GNU MP 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 Lesser General Public +License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include +#include "gmp-impl.h" + +/* Compare OP1_PTR/OP1_SIZE with OP2_PTR/OP2_SIZE. + There are no restrictions on the relative sizes of + the two arguments. + Return 1 if OP1 > OP2, 0 if they are equal, and -1 if OP1 < OP2. */ + +int +#if __STDC__ +mpn_cmp (mp_srcptr op1_ptr, mp_srcptr op2_ptr, mp_size_t size) +#else +mpn_cmp (op1_ptr, op2_ptr, size) + mp_srcptr op1_ptr; + mp_srcptr op2_ptr; + mp_size_t size; +#endif +{ + mp_size_t i; + mp_limb_t op1_word, op2_word; + + for (i = size - 1; i >= 0; i--) + { + op1_word = op1_ptr[i]; + op2_word = op2_ptr[i]; + if (op1_word != op2_word) + goto diff; + } + return 0; + diff: + /* This can *not* be simplified to + op2_word - op2_word + since that expression might give signed overflow. */ + return (op1_word > op2_word) ? 1 : -1; +} diff --git a/stdlib/cxa_atexit.c b/stdlib/cxa_atexit.c index a3d4c5037d..3bdf871e53 100644 --- a/stdlib/cxa_atexit.c +++ b/stdlib/cxa_atexit.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. +/* Copyright (C) 1999, 2001, 2002, 2005, 2006 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 @@ -16,9 +16,13 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#include +#include #include + +#include #include "exit.h" +#include +#include #undef __cxa_atexit @@ -33,10 +37,14 @@ __cxa_atexit (void (*func) (void *), void *arg, void *d) if (new == NULL) return -1; - new->flavor = ef_cxa; +#ifdef PTR_MANGLE + PTR_MANGLE (func); +#endif new->func.cxa.fn = (void (*) (void *, int)) func; new->func.cxa.arg = arg; new->func.cxa.dso_handle = d; + atomic_write_barrier (); + new->flavor = ef_cxa; return 0; } INTDEF(__cxa_atexit) @@ -48,49 +56,68 @@ __libc_lock_define_initialized (static, lock) static struct exit_function_list initial; struct exit_function_list *__exit_funcs = &initial; +uint64_t __new_exitfn_called; struct exit_function * __new_exitfn (void) { + struct exit_function_list *p = NULL; struct exit_function_list *l; + struct exit_function *r = NULL; size_t i = 0; __libc_lock_lock (lock); - for (l = __exit_funcs; l != NULL; l = l->next) + for (l = __exit_funcs; l != NULL; p = l, l = l->next) { - for (i = 0; i < l->idx; ++i) - if (l->fns[i].flavor == ef_free) + for (i = l->idx; i > 0; --i) + if (l->fns[i - 1].flavor != ef_free) break; - if (i < l->idx) + + if (i > 0) break; - if (l->idx < sizeof (l->fns) / sizeof (l->fns[0])) - { - i = l->idx++; - break; - } + /* This block is completely unused. */ + l->idx = 0; } - if (l == NULL) + if (l == NULL || i == sizeof (l->fns) / sizeof (l->fns[0])) { - l = (struct exit_function_list *) - malloc (sizeof (struct exit_function_list)); - if (l != NULL) + /* The last entry in a block is used. Use the first entry in + the previous block if it exists. Otherwise create a new one. */ + if (p == NULL) { - l->next = __exit_funcs; - __exit_funcs = l; + assert (l != NULL); + p = (struct exit_function_list *) + calloc (1, sizeof (struct exit_function_list)); + if (p != NULL) + { + p->next = __exit_funcs; + __exit_funcs = p; + } + } - l->idx = 1; - i = 0; + if (p != NULL) + { + r = &p->fns[0]; + p->idx = 1; } } + else + { + /* There is more room in the block. */ + r = &l->fns[i]; + l->idx = i + 1; + } /* Mark entry as used, but we don't know the flavor now. */ - if (l != NULL) - l->fns[i].flavor = ef_us; + if (r != NULL) + { + r->flavor = ef_us; + ++__new_exitfn_called; + } __libc_lock_unlock (lock); - return l == NULL ? NULL : &l->fns[i]; + return r; } diff --git a/stdlib/cxa_finalize.c b/stdlib/cxa_finalize.c index 2339c7b5bd..bb49f36ddd 100644 --- a/stdlib/cxa_finalize.c +++ b/stdlib/cxa_finalize.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1999, 2001, 2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 1999,2001,2002,2003,2005,2006 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 @@ -21,6 +21,7 @@ #include #include "exit.h" #include +#include /* If D is non-NULL, call all functions registered with `__cxa_atexit' with the same dso handle. Otherwise, if D is NULL, call all of the @@ -30,16 +31,36 @@ __cxa_finalize (void *d) { struct exit_function_list *funcs; + restart: for (funcs = __exit_funcs; funcs; funcs = funcs->next) { struct exit_function *f; for (f = &funcs->fns[funcs->idx - 1]; f >= &funcs->fns[0]; --f) - if ((d == NULL || d == f->func.cxa.dso_handle) - /* We don't want to run this cleanup more than once. */ - && ! atomic_compare_and_exchange_bool_acq (&f->flavor, ef_free, - ef_cxa)) - (*f->func.cxa.fn) (f->func.cxa.arg, 0); + { + void (*cxafn) (void *arg, int status); + void *cxaarg; + + if ((d == NULL || d == f->func.cxa.dso_handle) + /* We don't want to run this cleanup more than once. */ + && (cxafn = f->func.cxa.fn, + cxaarg = f->func.cxa.arg, + ! atomic_compare_and_exchange_bool_acq (&f->flavor, ef_free, + ef_cxa))) + { + uint64_t check = __new_exitfn_called; + +#ifdef PTR_DEMANGLE + PTR_DEMANGLE (cxafn); +#endif + cxafn (cxaarg, 0); + + /* It is possible that that last exit function registered + more exit functions. Start the loop over. */ + if (__builtin_expect (check != __new_exitfn_called, 0)) + goto restart; + } + } } /* Remove the registered fork handlers. We do not have to diff --git a/stdlib/dbl2mpn.c b/stdlib/dbl2mpn.c new file mode 100644 index 0000000000..4444467946 --- /dev/null +++ b/stdlib/dbl2mpn.c @@ -0,0 +1,32 @@ +/* Copyright (C) 1993, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "gmp-impl.h" + +/* Convert a `double' to a multi-precision integer representing the + significand scaled up by the highest possible number of significant bits + of fraction (DBL_MANT_DIG), and an integral power of two (MPN frexp). */ + +mp_size_t +__mpn_extract_double (mp_ptr res_ptr, mp_size_t size, + int *expt, int *is_neg, + double value) +{ +#error "__mpn_extract_double is not implemented for this floating point format" +} diff --git a/stdlib/div.c b/stdlib/div.c new file mode 100644 index 0000000000..5268f4c494 --- /dev/null +++ b/stdlib/div.c @@ -0,0 +1,86 @@ +/* Copyright (C) 1992, 1997, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * Copyright (c) 1990 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +/* Return the `div_t' representation of NUMER over DENOM. */ +div_t +div (numer, denom) + int numer, denom; +{ + div_t result; + + result.quot = numer / denom; + result.rem = numer % denom; + + /* The ANSI standard says that |QUOT| <= |NUMER / DENOM|, where + NUMER / DENOM is to be computed in infinite precision. In + other words, we should always truncate the quotient towards + zero, never -infinity. Machine division and remainer may + work either way when one or both of NUMER or DENOM is + negative. If only one is negative and QUOT has been + truncated towards -infinity, REM will have the same sign as + DENOM and the opposite sign of NUMER; if both are negative + and QUOT has been truncated towards -infinity, REM will be + positive (will have the opposite sign of NUMER). These are + considered `wrong'. If both are NUM and DENOM are positive, + RESULT will always be positive. This all boils down to: if + NUMER >= 0, but REM < 0, we got the wrong answer. In that + case, to get the right answer, add 1 to QUOT and subtract + DENOM from REM. */ + + if (numer >= 0 && result.rem < 0) + { + ++result.quot; + result.rem -= denom; + } + + return result; +} diff --git a/stdlib/divmod_1.c b/stdlib/divmod_1.c new file mode 100644 index 0000000000..51a47d85d3 --- /dev/null +++ b/stdlib/divmod_1.c @@ -0,0 +1,208 @@ +/* mpn_divmod_1(quot_ptr, dividend_ptr, dividend_size, divisor_limb) -- + Divide (DIVIDEND_PTR,,DIVIDEND_SIZE) by DIVISOR_LIMB. + Write DIVIDEND_SIZE limbs of quotient at QUOT_PTR. + Return the single-limb remainder. + There are no constraints on the value of the divisor. + + QUOT_PTR and DIVIDEND_PTR might point to the same limb. + +Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or (at your +option) any later version. + +The GNU MP 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 Lesser General Public +License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include +#include "gmp-impl.h" +#include "longlong.h" + +#ifndef UMUL_TIME +#define UMUL_TIME 1 +#endif + +#ifndef UDIV_TIME +#define UDIV_TIME UMUL_TIME +#endif + +/* FIXME: We should be using invert_limb (or invert_normalized_limb) + here (not udiv_qrnnd). */ + +mp_limb_t +#if __STDC__ +mpn_divmod_1 (mp_ptr quot_ptr, + mp_srcptr dividend_ptr, mp_size_t dividend_size, + mp_limb_t divisor_limb) +#else +mpn_divmod_1 (quot_ptr, dividend_ptr, dividend_size, divisor_limb) + mp_ptr quot_ptr; + mp_srcptr dividend_ptr; + mp_size_t dividend_size; + mp_limb_t divisor_limb; +#endif +{ + mp_size_t i; + mp_limb_t n1, n0, r; + int dummy; + + /* ??? Should this be handled at all? Rely on callers? */ + if (dividend_size == 0) + return 0; + + /* If multiplication is much faster than division, and the + dividend is large, pre-invert the divisor, and use + only multiplications in the inner loop. */ + + /* This test should be read: + Does it ever help to use udiv_qrnnd_preinv? + && Does what we save compensate for the inversion overhead? */ + if (UDIV_TIME > (2 * UMUL_TIME + 6) + && (UDIV_TIME - (2 * UMUL_TIME + 6)) * dividend_size > UDIV_TIME) + { + int normalization_steps; + + count_leading_zeros (normalization_steps, divisor_limb); + if (normalization_steps != 0) + { + mp_limb_t divisor_limb_inverted; + + divisor_limb <<= normalization_steps; + + /* Compute (2**2N - 2**N * DIVISOR_LIMB) / DIVISOR_LIMB. The + result is a (N+1)-bit approximation to 1/DIVISOR_LIMB, with the + most significant bit (with weight 2**N) implicit. */ + + /* Special case for DIVISOR_LIMB == 100...000. */ + if (divisor_limb << 1 == 0) + divisor_limb_inverted = ~(mp_limb_t) 0; + else + udiv_qrnnd (divisor_limb_inverted, dummy, + -divisor_limb, 0, divisor_limb); + + n1 = dividend_ptr[dividend_size - 1]; + r = n1 >> (BITS_PER_MP_LIMB - normalization_steps); + + /* Possible optimization: + if (r == 0 + && divisor_limb > ((n1 << normalization_steps) + | (dividend_ptr[dividend_size - 2] >> ...))) + ...one division less... */ + + for (i = dividend_size - 2; i >= 0; i--) + { + n0 = dividend_ptr[i]; + udiv_qrnnd_preinv (quot_ptr[i + 1], r, r, + ((n1 << normalization_steps) + | (n0 >> (BITS_PER_MP_LIMB - normalization_steps))), + divisor_limb, divisor_limb_inverted); + n1 = n0; + } + udiv_qrnnd_preinv (quot_ptr[0], r, r, + n1 << normalization_steps, + divisor_limb, divisor_limb_inverted); + return r >> normalization_steps; + } + else + { + mp_limb_t divisor_limb_inverted; + + /* Compute (2**2N - 2**N * DIVISOR_LIMB) / DIVISOR_LIMB. The + result is a (N+1)-bit approximation to 1/DIVISOR_LIMB, with the + most significant bit (with weight 2**N) implicit. */ + + /* Special case for DIVISOR_LIMB == 100...000. */ + if (divisor_limb << 1 == 0) + divisor_limb_inverted = ~(mp_limb_t) 0; + else + udiv_qrnnd (divisor_limb_inverted, dummy, + -divisor_limb, 0, divisor_limb); + + i = dividend_size - 1; + r = dividend_ptr[i]; + + if (r >= divisor_limb) + r = 0; + else + { + quot_ptr[i] = 0; + i--; + } + + for (; i >= 0; i--) + { + n0 = dividend_ptr[i]; + udiv_qrnnd_preinv (quot_ptr[i], r, r, + n0, divisor_limb, divisor_limb_inverted); + } + return r; + } + } + else + { + if (UDIV_NEEDS_NORMALIZATION) + { + int normalization_steps; + + count_leading_zeros (normalization_steps, divisor_limb); + if (normalization_steps != 0) + { + divisor_limb <<= normalization_steps; + + n1 = dividend_ptr[dividend_size - 1]; + r = n1 >> (BITS_PER_MP_LIMB - normalization_steps); + + /* Possible optimization: + if (r == 0 + && divisor_limb > ((n1 << normalization_steps) + | (dividend_ptr[dividend_size - 2] >> ...))) + ...one division less... */ + + for (i = dividend_size - 2; i >= 0; i--) + { + n0 = dividend_ptr[i]; + udiv_qrnnd (quot_ptr[i + 1], r, r, + ((n1 << normalization_steps) + | (n0 >> (BITS_PER_MP_LIMB - normalization_steps))), + divisor_limb); + n1 = n0; + } + udiv_qrnnd (quot_ptr[0], r, r, + n1 << normalization_steps, + divisor_limb); + return r >> normalization_steps; + } + } + /* No normalization needed, either because udiv_qrnnd doesn't require + it, or because DIVISOR_LIMB is already normalized. */ + + i = dividend_size - 1; + r = dividend_ptr[i]; + + if (r >= divisor_limb) + r = 0; + else + { + quot_ptr[i] = 0; + i--; + } + + for (; i >= 0; i--) + { + n0 = dividend_ptr[i]; + udiv_qrnnd (quot_ptr[i], r, r, n0, divisor_limb); + } + return r; + } +} diff --git a/stdlib/divrem.c b/stdlib/divrem.c new file mode 100644 index 0000000000..c97d01ec17 --- /dev/null +++ b/stdlib/divrem.c @@ -0,0 +1,245 @@ +/* mpn_divrem -- Divide natural numbers, producing both remainder and + quotient. + +Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or (at your +option) any later version. + +The GNU MP 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 Lesser General Public +License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include +#include "gmp-impl.h" +#include "longlong.h" + +/* Divide num (NP/NSIZE) by den (DP/DSIZE) and write + the NSIZE-DSIZE least significant quotient limbs at QP + and the DSIZE long remainder at NP. If QEXTRA_LIMBS is + non-zero, generate that many fraction bits and append them after the + other quotient limbs. + Return the most significant limb of the quotient, this is always 0 or 1. + + Preconditions: + 0. NSIZE >= DSIZE. + 1. The most significant bit of the divisor must be set. + 2. QP must either not overlap with the input operands at all, or + QP + DSIZE >= NP must hold true. (This means that it's + possible to put the quotient in the high part of NUM, right after the + remainder in NUM. + 3. NSIZE >= DSIZE, even if QEXTRA_LIMBS is non-zero. */ + +mp_limb_t +#if __STDC__ +mpn_divrem (mp_ptr qp, mp_size_t qextra_limbs, + mp_ptr np, mp_size_t nsize, + mp_srcptr dp, mp_size_t dsize) +#else +mpn_divrem (qp, qextra_limbs, np, nsize, dp, dsize) + mp_ptr qp; + mp_size_t qextra_limbs; + mp_ptr np; + mp_size_t nsize; + mp_srcptr dp; + mp_size_t dsize; +#endif +{ + mp_limb_t most_significant_q_limb = 0; + + switch (dsize) + { + case 0: + /* We are asked to divide by zero, so go ahead and do it! (To make + the compiler not remove this statement, return the value.) */ + return 1 / dsize; + + case 1: + { + mp_size_t i; + mp_limb_t n1; + mp_limb_t d; + + d = dp[0]; + n1 = np[nsize - 1]; + + if (n1 >= d) + { + n1 -= d; + most_significant_q_limb = 1; + } + + qp += qextra_limbs; + for (i = nsize - 2; i >= 0; i--) + udiv_qrnnd (qp[i], n1, n1, np[i], d); + qp -= qextra_limbs; + + for (i = qextra_limbs - 1; i >= 0; i--) + udiv_qrnnd (qp[i], n1, n1, 0, d); + + np[0] = n1; + } + break; + + case 2: + { + mp_size_t i; + mp_limb_t n1, n0, n2; + mp_limb_t d1, d0; + + np += nsize - 2; + d1 = dp[1]; + d0 = dp[0]; + n1 = np[1]; + n0 = np[0]; + + if (n1 >= d1 && (n1 > d1 || n0 >= d0)) + { + sub_ddmmss (n1, n0, n1, n0, d1, d0); + most_significant_q_limb = 1; + } + + for (i = qextra_limbs + nsize - 2 - 1; i >= 0; i--) + { + mp_limb_t q; + mp_limb_t r; + + if (i >= qextra_limbs) + np--; + else + np[0] = 0; + + if (n1 == d1) + { + /* Q should be either 111..111 or 111..110. Need special + treatment of this rare case as normal division would + give overflow. */ + q = ~(mp_limb_t) 0; + + r = n0 + d1; + if (r < d1) /* Carry in the addition? */ + { + add_ssaaaa (n1, n0, r - d0, np[0], 0, d0); + qp[i] = q; + continue; + } + n1 = d0 - (d0 != 0); + n0 = -d0; + } + else + { + udiv_qrnnd (q, r, n1, n0, d1); + umul_ppmm (n1, n0, d0, q); + } + + n2 = np[0]; + q_test: + if (n1 > r || (n1 == r && n0 > n2)) + { + /* The estimated Q was too large. */ + q--; + + sub_ddmmss (n1, n0, n1, n0, 0, d0); + r += d1; + if (r >= d1) /* If not carry, test Q again. */ + goto q_test; + } + + qp[i] = q; + sub_ddmmss (n1, n0, r, n2, n1, n0); + } + np[1] = n1; + np[0] = n0; + } + break; + + default: + { + mp_size_t i; + mp_limb_t dX, d1, n0; + + np += nsize - dsize; + dX = dp[dsize - 1]; + d1 = dp[dsize - 2]; + n0 = np[dsize - 1]; + + if (n0 >= dX) + { + if (n0 > dX || mpn_cmp (np, dp, dsize - 1) >= 0) + { + mpn_sub_n (np, np, dp, dsize); + n0 = np[dsize - 1]; + most_significant_q_limb = 1; + } + } + + for (i = qextra_limbs + nsize - dsize - 1; i >= 0; i--) + { + mp_limb_t q; + mp_limb_t n1, n2; + mp_limb_t cy_limb; + + if (i >= qextra_limbs) + { + np--; + n2 = np[dsize]; + } + else + { + n2 = np[dsize - 1]; + MPN_COPY_DECR (np + 1, np, dsize); + np[0] = 0; + } + + if (n0 == dX) + /* This might over-estimate q, but it's probably not worth + the extra code here to find out. */ + q = ~(mp_limb_t) 0; + else + { + mp_limb_t r; + + udiv_qrnnd (q, r, n0, np[dsize - 1], dX); + umul_ppmm (n1, n0, d1, q); + + while (n1 > r || (n1 == r && n0 > np[dsize - 2])) + { + q--; + r += dX; + if (r < dX) /* I.e. "carry in previous addition?" */ + break; + n1 -= n0 < d1; + n0 -= d1; + } + } + + /* Possible optimization: We already have (q * n0) and (1 * n1) + after the calculation of q. Taking advantage of that, we + could make this loop make two iterations less. */ + + cy_limb = mpn_submul_1 (np, dp, dsize, q); + + if (n2 != cy_limb) + { + mpn_add_n (np, np, dp, dsize); + q--; + } + + qp[i] = q; + n0 = np[dsize - 1]; + } + } + } + + return most_significant_q_limb; +} diff --git a/stdlib/exit.c b/stdlib/exit.c index ac247a1233..bc4cb0fd08 100644 --- a/stdlib/exit.c +++ b/stdlib/exit.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991,95,96,97,99,2001,02 Free Software Foundation, Inc. +/* Copyright (C) 1991,95,96,97,99,2001,2002,2005 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 @@ -19,12 +19,11 @@ #include #include #include +#include #include "exit.h" -#ifdef HAVE_GNU_LD #include "set-hooks.h" DEFINE_HOOK (__libc_atexit, (void)) -#endif /* Call all functions registered with `atexit' and `on_exit', @@ -47,17 +46,33 @@ exit (int status) &__exit_funcs->fns[--__exit_funcs->idx]; switch (f->flavor) { + void (*atfct) (void); + void (*onfct) (int status, void *arg); + void (*cxafct) (void *arg, int status); + case ef_free: case ef_us: break; case ef_on: - (*f->func.on.fn) (status, f->func.on.arg); + onfct = f->func.on.fn; +#ifdef PTR_DEMANGLE + PTR_DEMANGLE (onfct); +#endif + onfct (status, f->func.on.arg); break; case ef_at: - (*f->func.at) (); + atfct = f->func.at; +#ifdef PTR_DEMANGLE + PTR_DEMANGLE (atfct); +#endif + atfct (); break; case ef_cxa: - (*f->func.cxa.fn) (f->func.cxa.arg, status); + cxafct = f->func.cxa.fn; +#ifdef PTR_DEMANGLE + PTR_DEMANGLE (cxafct); +#endif + cxafct (f->func.cxa.arg, status); break; } } @@ -70,14 +85,7 @@ exit (int status) free (old); } -#ifdef HAVE_GNU_LD RUN_HOOK (__libc_atexit, ()); -#else - { - extern void _cleanup (void); - _cleanup (); - } -#endif _exit (status); } diff --git a/stdlib/exit.h b/stdlib/exit.h index 055506f04e..779675d134 100644 --- a/stdlib/exit.h +++ b/stdlib/exit.h @@ -1,4 +1,5 @@ -/* Copyright (C) 1991,1996,1997,1999,2001,2002 Free Software Foundation, Inc. +/* Copyright (C) 1991,1996,1997,1999,2001,2002,2006 + 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 @@ -19,6 +20,7 @@ #ifndef _EXIT_H #define _EXIT_H 1 +#include enum { @@ -59,5 +61,6 @@ struct exit_function_list extern struct exit_function_list *__exit_funcs attribute_hidden; extern struct exit_function *__new_exitfn (void); +extern uint64_t __new_exitfn_called attribute_hidden; #endif /* exit.h */ diff --git a/stdlib/fmtmsg.c b/stdlib/fmtmsg.c index 2ab97b7d90..2a4d16a461 100644 --- a/stdlib/fmtmsg.c +++ b/stdlib/fmtmsg.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1997,1999,2000,2001,2002,2003 Free Software Foundation, Inc. +/* Copyright (C) 1997,1999,2000-2003,2005, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 1997. @@ -44,7 +44,7 @@ enum static const struct { - size_t len; + uint32_t len; /* Adjust the size if new elements are added. */ const char name[12]; } keywords[] = @@ -154,42 +154,21 @@ fmtmsg (long int classification, const char *label, int severity, int do_action = (print & action_mask) && action != MM_NULLACT; int do_tag = (print & tag_mask) && tag != MM_NULLTAG; -#ifdef USE_IN_LIBIO - if (_IO_fwide (stderr, 0) > 0) - { - if (__fwprintf (stderr, L"%s%s%s%s%s%s%s%s%s%s\n", - do_label ? label : "", - do_label - && (do_severity | do_text | do_action | do_tag) - ? ": " : "", - do_severity ? severity_rec->string : "", - do_severity && (do_text | do_action | do_tag) - ? ": " : "", - do_text ? text : "", - do_text && (do_action | do_tag) ? "\n" : "", - do_action ? "TO FIX: " : "", - do_action ? action : "", - do_action && do_tag ? " " : "", - do_tag ? tag : "") < 0) - /* Oh, oh. An error occurred during the output. */ - result = MM_NOMSG; - } - else -#endif - if (fprintf (stderr, "%s%s%s%s%s%s%s%s%s%s\n", - do_label ? label : "", - do_label && (do_severity | do_text | do_action | do_tag) - ? ": " : "", - do_severity ? severity_rec->string : "", - do_severity && (do_text | do_action | do_tag) ? ": " : "", - do_text ? text : "", - do_text && (do_action | do_tag) ? "\n" : "", - do_action ? "TO FIX: " : "", - do_action ? action : "", - do_action && do_tag ? " " : "", - do_tag ? tag : "") < 0) - /* Oh, oh. An error occurred during the output. */ - result = MM_NOMSG; + if (__fxprintf (stderr, "%s%s%s%s%s%s%s%s%s%s\n", + do_label ? label : "", + do_label && (do_severity | do_text | do_action | do_tag) + ? ": " : "", + do_severity ? severity_rec->string : "", + do_severity && (do_text | do_action | do_tag) + ? ": " : "", + do_text ? text : "", + do_text && (do_action | do_tag) ? "\n" : "", + do_action ? "TO FIX: " : "", + do_action ? action : "", + do_action && do_tag ? " " : "", + do_tag ? tag : "") < 0) + /* Oh, oh. An error occurred during the output. */ + result = MM_NOMSG; } if (classification & MM_CONSOLE) @@ -316,7 +295,7 @@ internal_addseverity (int severity, const char *string) int result = MM_OK; /* First see if there is already a record for the severity level. */ - for (runp = severity_list, lastp = NULL; runp != NULL; runp = runp-> next) + for (runp = severity_list, lastp = NULL; runp != NULL; runp = runp->next) if (runp->severity == severity) break; else @@ -324,9 +303,6 @@ internal_addseverity (int severity, const char *string) if (runp != NULL) { - /* Release old string. */ - free ((char *) runp->string); - if (string != NULL) /* Change the string. */ runp->string = string; @@ -367,34 +343,17 @@ int addseverity (int severity, const char *string) { int result; - const char *new_string; /* Prevent illegal SEVERITY values. */ if (severity <= MM_INFO) return MM_NOTOK; - if (string == NULL) - /* We want to remove the severity class. */ - new_string = NULL; - else - { - new_string = __strdup (string); - - if (new_string == NULL) - /* Allocation failed or illegal value. */ - return MM_NOTOK; - } - /* Protect the global data. */ __libc_lock_lock (lock); /* Do the real work. */ result = internal_addseverity (severity, string); - if (result != MM_OK) - /* Free the allocated string. */ - free ((char *) new_string); - /* Release the lock. */ __libc_lock_unlock (lock); @@ -411,7 +370,6 @@ libc_freeres_fn (free_mem) { /* This is data we have to release. */ struct severity_info *here = runp; - free ((char *) runp->string); runp = runp->next; free (here); } diff --git a/stdlib/fpioconst.c b/stdlib/fpioconst.c index 59a5e43a82..0e36da65b2 100644 --- a/stdlib/fpioconst.c +++ b/stdlib/fpioconst.c @@ -278,7 +278,7 @@ const mp_limb_t __tens[] = 0x26b2716ed595d80full, 0x1d153624adc666b0ull, 0x63ff540e3c42d35aull, 0x65f9ef17cc5573c0ull, 0x80dcc7f755bc28f2ull, 0x5fdcefcef46eeddcull, 0x00000000000553f7ull, -#if!defined __NO_LONG_DOUBLE_MATH && __LDBL_MAX_EXP__ > 1024 +#if !defined __NO_LONG_DOUBLE_MATH && __LDBL_MAX_EXP__ > 1024 # define TENS_P9_IDX (TENS_P8_IDX + TENS_P8_SIZE) # define TENS_P9_SIZE 28 [TENS_P9_IDX] = 0x0000000000000000ull, 0x0000000000000000ull, diff --git a/stdlib/gen-mpn-copy b/stdlib/gen-mpn-copy deleted file mode 100644 index 01656ae54d..0000000000 --- a/stdlib/gen-mpn-copy +++ /dev/null @@ -1,35 +0,0 @@ -#!/bin/sh - -translations=' -sparc64 sparc/sparc64 -sparc32/v8 sparc/sparc8 -sparc32 sparc -x86/pentium i386/i586 -x86 i386 -m68k/mc68000 m68k/m68000 -m68k/mc68020 m68k/m68020 -m88k/mc88100 m88k/m88100 -m88k/mc88110 m88k/m88110 -mips3 mips/mips3 -mips2 mips -hppa/hppa1_1 hppa/hppa1.1 -alpha/ev5 alpha/alphaev5 -power rs6000 -am29000 a29k -' - -set $translations -while [ $# -ge 2 ]; do - gmp=$1 glibc=$2 - shift; shift - echo 'mpn-found-1 := $(filter $(gmp-srcdir)/mpn/'$gmp'/%,$(mpn-found)) -mpn-copy-1 := $(patsubst $(gmp-srcdir)/mpn/'$gmp'/%,$(sysdep_dir)/'$glibc\ -'/%,$(mpn-found-1)) -mpn-found := $(filter-out $(mpn-found-1),$(mpn-found)) -mpn-copy-sysdep := $(mpn-copy-sysdep) $(mpn-copy-1) -$(mpn-copy-1): $(sysdep_dir)/'$glibc'/%: \ - $(ignore gmp2glibc.sed) $(gmp-srcdir)/mpn/'$gmp'/% - $(gmp2glibc)' -done - -exit 0 diff --git a/stdlib/getcontext.c b/stdlib/getcontext.c new file mode 100644 index 0000000000..e417575a58 --- /dev/null +++ b/stdlib/getcontext.c @@ -0,0 +1,32 @@ +/* Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +int +getcontext (ucp) + ucontext_t *ucp; +{ + __set_errno (ENOSYS); + return -1; +} + + +stub_warning (getcontext) +#include diff --git a/stdlib/getenv.c b/stdlib/getenv.c new file mode 100644 index 0000000000..6cdfe2b266 --- /dev/null +++ b/stdlib/getenv.c @@ -0,0 +1,98 @@ +/* Copyright (C) 1991,92,94,96,98,99,2002,2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include + + +/* Return the value of the environment variable NAME. This implementation + is tuned a bit in that it assumes no environment variable has an empty + name which of course should always be true. We have a special case for + one character names so that for the general case we can assume at least + two characters which we can access. By doing this we can avoid using the + `strncmp' most of the time. */ +char * +getenv (name) + const char *name; +{ + size_t len = strlen (name); + char **ep; + uint16_t name_start; + + if (__environ == NULL || name[0] == '\0') + return NULL; + + if (name[1] == '\0') + { + /* The name of the variable consists of only one character. Therefore + the first two characters of the environment entry are this character + and a '=' character. */ +#if __BYTE_ORDER == __LITTLE_ENDIAN || !_STRING_ARCH_unaligned + name_start = ('=' << 8) | *(const unsigned char *) name; +#else +# if __BYTE_ORDER == __BIG_ENDIAN + name_start = '=' | ((*(const unsigned char *) name) << 8); +# else + #error "Funny byte order." +# endif +#endif + for (ep = __environ; *ep != NULL; ++ep) + { +#if _STRI