about summary refs log tree commit diff
path: root/stdlib
diff options
context:
space:
mode:
Diffstat (limited to 'stdlib')
-rw-r--r--stdlib/abort.c140
-rw-r--r--stdlib/add_n.c62
-rw-r--r--stdlib/addmul_1.c65
-rw-r--r--stdlib/cmp.c56
-rw-r--r--stdlib/cxa_atexit.c8
-rw-r--r--stdlib/cxa_finalize.c11
-rw-r--r--stdlib/dbl2mpn.c32
-rw-r--r--stdlib/div.c86
-rw-r--r--stdlib/divmod_1.c208
-rw-r--r--stdlib/divrem.c245
-rw-r--r--stdlib/exit.c23
-rw-r--r--stdlib/getcontext.c32
-rw-r--r--stdlib/getenv.c98
-rw-r--r--stdlib/inlines.c3
-rw-r--r--stdlib/labs.c29
-rw-r--r--stdlib/ldbl2mpn.c1
-rw-r--r--stdlib/ldiv.c54
-rw-r--r--stdlib/llabs.c31
-rw-r--r--stdlib/lldiv.c57
-rw-r--r--stdlib/longlong.h152
-rw-r--r--stdlib/lshift.c87
-rw-r--r--stdlib/makecontext.c30
-rw-r--r--stdlib/mod_1.c197
-rw-r--r--stdlib/mp_clz_tab.c37
-rw-r--r--stdlib/mpn2dbl.c30
-rw-r--r--stdlib/mpn2flt.c30
-rw-r--r--stdlib/mpn2ldbl.c1
-rw-r--r--stdlib/mul.c152
-rw-r--r--stdlib/mul_1.c59
-rw-r--r--stdlib/mul_n.c401
-rw-r--r--stdlib/on_exit.c10
-rw-r--r--stdlib/putenv.c72
-rw-r--r--stdlib/rshift.c88
-rw-r--r--stdlib/setcontext.c32
-rw-r--r--stdlib/setenv.c353
-rw-r--r--stdlib/strtod_l.c4
-rw-r--r--stdlib/strtoimax.c1
-rw-r--r--stdlib/strtol.c111
-rw-r--r--stdlib/strtol_l.c557
-rw-r--r--stdlib/strtold_l.c58
-rw-r--r--stdlib/strtoll.c34
-rw-r--r--stdlib/strtoll_l.c28
-rw-r--r--stdlib/strtoul.c21
-rw-r--r--stdlib/strtoul_l.c28
-rw-r--r--stdlib/strtoull.c34
-rw-r--r--stdlib/strtoull_l.c29
-rw-r--r--stdlib/strtoumax.c1
-rw-r--r--stdlib/sub_n.c62
-rw-r--r--stdlib/submul_1.c65
-rw-r--r--stdlib/swapcontext.c33
-rw-r--r--stdlib/system.c38
-rw-r--r--stdlib/udiv_qrnnd.c10
-rw-r--r--stdlib/wcstoimax.c1
-rw-r--r--stdlib/wcstoumax.c1
54 files changed, 4013 insertions, 75 deletions
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 <bits/libc-lock.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+/* Try to get a machine dependent instruction which will make the
+   program crash.  This is used in case everything else fails.  */
+#include <abort-instr.h>
+#ifndef ABORT_INSTRUCTION
+/* No such instruction is available.  */
+# define ABORT_INSTRUCTION
+#endif
+
+#ifdef USE_IN_LIBIO
+# include <libio/libioP.h>
+# 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 <gmp.h>
+#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 <gmp.h>
+#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/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 <gmp.h>
+#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 490776105f..9b7a932b85 100644
--- a/stdlib/cxa_atexit.c
+++ b/stdlib/cxa_atexit.c
@@ -21,6 +21,8 @@
 
 #include <bits/libc-lock.h>
 #include "exit.h"
+#include <atomic.h>
+#include <sysdep.h>
 
 #undef __cxa_atexit
 
@@ -35,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)
diff --git a/stdlib/cxa_finalize.c b/stdlib/cxa_finalize.c
index 2339c7b5bd..43fcbc484f 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 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 <atomic.h>
 #include "exit.h"
 #include <fork.h>
+#include <sysdep.h>
 
 /* 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
@@ -39,7 +40,13 @@ __cxa_finalize (void *d)
 	    /* 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) = f->func.cxa.fn;
+#ifdef PTR_DEMANGLE
+	    PTR_DEMANGLE (cxafn);
+#endif
+	    cxafn (f->func.cxa.arg, 0);
+	  }
     }
 
   /* 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 <gmp.h>
+#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 <stdlib.h>
+
+/* 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 <gmp.h>
+#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 <gmp.h>
+#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 e5e25960b1..bc4cb0fd08 100644
--- a/stdlib/exit.c
+++ b/stdlib/exit.c
@@ -19,6 +19,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
+#include <sysdep.h>
 #include "exit.h"
 
 #include "set-hooks.h"
@@ -45,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;
 	    }
 	}
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 <errno.h>
+#include <ucontext.h>
+
+int
+getcontext (ucp)
+     ucontext_t *ucp;
+{
+  __set_errno (ENOSYS);
+  return -1;
+}
+
+
+stub_warning (getcontext)
+#include <stub-tag.h>
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 <endian.h>
+#include <errno.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+
+/* 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 _STRING_ARCH_unaligned
+	  uint16_t ep_start = *(uint16_t *) *ep;
+#else
+	  uint16_t ep_start = (((unsigned char *) *ep)[0]
+			       | (((unsigned char *) *ep)[1] << 8));
+#endif
+	  if (name_start == ep_start)
+	    return &(*ep)[2];
+	}
+    }
+  else
+    {
+#if _STRING_ARCH_unaligned
+      name_start = *(const uint16_t *) name;
+#else
+      name_start = (((const unsigned char *) name)[0]
+		    | (((const unsigned char *) name)[1] << 8));
+#endif
+      len -= 2;
+      name += 2;
+
+      for (ep = __environ; *ep != NULL; ++ep)
+	{
+#if _STRING_ARCH_unaligned
+	  uint16_t ep_start = *(uint16_t *) *ep;
+#else
+	  uint16_t ep_start = (((unsigned char *) *ep)[0]
+			       | (((unsigned char *) *ep)[1] << 8));
+#endif
+
+	  if (name_start == ep_start && !strncmp (*ep + 2, name, len)
+	      && (*ep)[len + 2] == '=')
+	    return &(*ep)[len + 3];
+	}
+    }
+
+  return NULL;
+}
+libc_hidden_def (getenv)
diff --git a/stdlib/inlines.c b/stdlib/inlines.c
new file mode 100644
index 0000000000..5f1065ea13
--- /dev/null
+++ b/stdlib/inlines.c
@@ -0,0 +1,3 @@
+#define _FORCE_INLINES
+#define _EXTERN_INLINE /* empty */
+#include <gmp.h>
diff --git a/stdlib/labs.c b/stdlib/labs.c
new file mode 100644
index 0000000000..c568e44454
--- /dev/null
+++ b/stdlib/labs.c
@@ -0,0 +1,29 @@
+/* Copyright (C) 1991, 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 <stdlib.h>
+
+#undef	labs
+
+
+/* Return the absolute value of I.  */
+long int
+labs (long int i)
+{
+  return i < 0 ? -i : i;
+}
diff --git a/stdlib/ldbl2mpn.c b/stdlib/ldbl2mpn.c
new file mode 100644
index 0000000000..450f9381cc
--- /dev/null
+++ b/stdlib/ldbl2mpn.c
@@ -0,0 +1 @@
+/* Empty.  Not needed unless ldbl support is in. */
diff --git a/stdlib/ldiv.c b/stdlib/ldiv.c
new file mode 100644
index 0000000000..a7796d8e95
--- /dev/null
+++ b/stdlib/ldiv.c
@@ -0,0 +1,54 @@
+/* Copyright (C) 1992, 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 <stdlib.h>
+
+
+/* Return the `ldiv_t' representation of NUMER over DENOM.  */
+ldiv_t
+ldiv (long int numer, long int denom)
+{
+  ldiv_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/llabs.c b/stdlib/llabs.c
new file mode 100644
index 0000000000..b15c347d32
--- /dev/null
+++ b/stdlib/llabs.c
@@ -0,0 +1,31 @@
+/* `long long int' absolute value.
+   Copyright (C) 1991, 1996, 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 <stdlib.h>
+
+#undef	llabs
+
+
+/* Return the absolute value of I.  */
+long long int
+llabs (i)
+     long long int i;
+{
+  return i < 0 ? -i : i;
+}
diff --git a/stdlib/lldiv.c b/stdlib/lldiv.c
new file mode 100644
index 0000000000..28a016b744
--- /dev/null
+++ b/stdlib/lldiv.c
@@ -0,0 +1,57 @@
+/* `long long int' divison with remainder.
+   Copyright (C) 1992, 1996, 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 <stdlib.h>
+
+
+/* Return the `lldiv_t' representation of NUMER over DENOM.  */
+lldiv_t
+lldiv (numer, denom)
+     long long int numer;
+     long long int denom;
+{
+  lldiv_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/longlong.h b/stdlib/longlong.h
index f89ae27a67..4e1931d823 100644
--- a/stdlib/longlong.h
+++ b/stdlib/longlong.h
@@ -1,5 +1,6 @@
 /* longlong.h -- definitions for mixed size 32/64 bit arithmetic.
-   Copyright (C) 1991, 1992, 1994, 1995, 1996, 1997, 1998, 1999, 2000
+   Copyright (C) 1991, 1992, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
+   2002, 2003, 2004, 2005
    Free Software Foundation, Inc.
 
    This file is part of the GNU C Library.
@@ -31,8 +32,7 @@
    DItype, UDItype -- Signed and unsigned 64 bit types.
 
    On a 32 bit machine UWtype should typically be USItype;
-   on a 64 bit machine, UWtype should typically be UDItype.
-*/
+   on a 64 bit machine, UWtype should typically be UDItype.  */
 
 #define __BITS4 (W_TYPE_SIZE / 4)
 #define __ll_B ((UWtype) 1 << (W_TYPE_SIZE / 2))
@@ -46,10 +46,12 @@
 #define UDWtype		UDItype
 #endif
 
+extern const UQItype __clz_tab[256];
+
 /* Define auxiliary asm macros.
 
-   1) umul_ppmm(high_prod, low_prod, multipler, multiplicand) multiplies two
-   UWtype integers MULTIPLER and MULTIPLICAND, and generates a two UWtype
+   1) umul_ppmm(high_prod, low_prod, multiplier, multiplicand) multiplies two
+   UWtype integers MULTIPLIER and MULTIPLICAND, and generates a two UWtype
    word product in HIGH_PROD and LOW_PROD.
 
    2) __umulsidi3(a,b) multiplies two UWtype integers A and B, and returns a
@@ -113,10 +115,7 @@
 #define umul_ppmm(ph, pl, m0, m1) \
   do {									\
     UDItype __m0 = (m0), __m1 = (m1);					\
-    __asm__ ("umulh %r1,%2,%0"						\
-	     : "=r" ((UDItype) ph)					\
-	     : "%rJ" (__m0),						\
-	       "rI" (__m1));						\
+    (ph) = __builtin_alpha_umulh (__m0, __m1);				\
     (pl) = __m0 * __m1;							\
   } while (0)
 #define UMUL_TIME 46
@@ -130,30 +129,27 @@ extern UDItype __udiv_qrnnd (UDItype *, UDItype, UDItype, UDItype);
 #define UDIV_TIME 220
 #endif /* LONGLONG_STANDALONE */
 #ifdef __alpha_cix__
-#define count_leading_zeros(COUNT,X) \
-  __asm__("ctlz %1,%0" : "=r"(COUNT) : "r"(X))
-#define count_trailing_zeros(COUNT,X) \
-  __asm__("cttz %1,%0" : "=r"(COUNT) : "r"(X))
+#define count_leading_zeros(COUNT,X)	((COUNT) = __builtin_clzl (X))
+#define count_trailing_zeros(COUNT,X)	((COUNT) = __builtin_ctzl (X))
 #define COUNT_LEADING_ZEROS_0 64
 #else
-extern const UQItype __clz_tab[];
 #define count_leading_zeros(COUNT,X) \
   do {									\
     UDItype __xr = (X), __t, __a;					\
-    __asm__("cmpbge $31,%1,%0" : "=r"(__t) : "r"(__xr));		\
+    __t = __builtin_alpha_cmpbge (0, __xr);				\
     __a = __clz_tab[__t ^ 0xff] - 1;					\
-    __asm__("extbl %1,%2,%0" : "=r"(__t) : "r"(__xr), "r"(__a));	\
+    __t = __builtin_alpha_extbl (__xr, __a);				\
     (COUNT) = 64 - (__clz_tab[__t] + __a*8);				\
   } while (0)
 #define count_trailing_zeros(COUNT,X) \
   do {									\
     UDItype __xr = (X), __t, __a;					\
-    __asm__("cmpbge $31,%1,%0" : "=r"(__t) : "r"(__xr));		\
+    __t = __builtin_alpha_cmpbge (0, __xr);				\
     __t = ~__t & -~__t;							\
     __a = ((__t & 0xCC) != 0) * 2;					\
     __a += ((__t & 0xF0) != 0) * 4;					\
     __a += ((__t & 0xAA) != 0);						\
-    __asm__("extbl %1,%2,%0" : "=r"(__t) : "r"(__xr), "r"(__a));	\
+    __t = __builtin_alpha_extbl (__xr, __a);				\
     __a <<= 3;								\
     __t &= -__t;							\
     __a += ((__t & 0xCC) != 0) * 2;					\
@@ -193,7 +189,7 @@ do {									\
 UDItype __umulsidi3 (USItype, USItype);
 #endif
 
-#if defined (__arm__) && W_TYPE_SIZE == 32
+#if defined (__arm__) && !defined (__thumb__) && W_TYPE_SIZE == 32
 #define add_ssaaaa(sh, sl, ah, al, bh, bl) \
   __asm__ ("adds	%1, %4, %5\n\tadc	%0, %2, %3"		\
 	   : "=r" ((USItype) (sh)),					\
@@ -201,7 +197,7 @@ UDItype __umulsidi3 (USItype, USItype);
 	   : "%r" ((USItype) (ah)),					\
 	     "rI" ((USItype) (bh)),					\
 	     "%r" ((USItype) (al)),					\
-	     "rI" ((USItype) (bl)))
+	     "rI" ((USItype) (bl)) __CLOBBER_CC)
 #define sub_ddmmss(sh, sl, ah, al, bh, bl) \
   __asm__ ("subs	%1, %4, %5\n\tsbc	%0, %2, %3"		\
 	   : "=r" ((USItype) (sh)),					\
@@ -209,7 +205,7 @@ UDItype __umulsidi3 (USItype, USItype);
 	   : "r" ((USItype) (ah)),					\
 	     "rI" ((USItype) (bh)),					\
 	     "r" ((USItype) (al)),					\
-	     "rI" ((USItype) (bl)))
+	     "rI" ((USItype) (bl)) __CLOBBER_CC)
 #define umul_ppmm(xh, xl, a, b) \
 {register USItype __t0, __t1, __t2;					\
   __asm__ ("%@ Inlined umul_ppmm\n"					\
@@ -229,7 +225,7 @@ UDItype __umulsidi3 (USItype, USItype);
 	     "=r" ((USItype) (xl)),					\
 	     "=&r" (__t0), "=&r" (__t1), "=r" (__t2)			\
 	   : "r" ((USItype) (a)),					\
-	     "r" ((USItype) (b)));}
+	     "r" ((USItype) (b)) __CLOBBER_CC );}
 #define UMUL_TIME 20
 #define UDIV_TIME 100
 #endif /* __arm__ */
@@ -294,44 +290,27 @@ UDItype __umulsidi3 (USItype, USItype);
   } while (0)
 #endif
 
-#if (defined (__i370__) || defined (__mvs__)) && W_TYPE_SIZE == 32
-#define umul_ppmm(xh, xl, m0, m1) \
-  do {									\
-    union {UDItype __ll;						\
-	   struct {USItype __h, __l;} __i;				\
-	  } __xx;							\
-    USItype __m0 = (m0), __m1 = (m1);					\
-    __asm__ ("mr %0,%3"							\
-	     : "=r" (__xx.__i.__h),					\
-	       "=r" (__xx.__i.__l)					\
-	     : "%1" (__m0),						\
-	       "r" (__m1));						\
-    (xh) = __xx.__i.__h; (xl) = __xx.__i.__l;				\
-    (xh) += ((((SItype) __m0 >> 31) & __m1)				\
-	     + (((SItype) __m1 >> 31) & __m0));				\
-  } while (0)
+#if (defined (__i370__) || defined (__s390__) || defined (__mvs__)) && W_TYPE_SIZE == 32
 #define smul_ppmm(xh, xl, m0, m1) \
   do {									\
     union {DItype __ll;							\
 	   struct {USItype __h, __l;} __i;				\
-	  } __xx;							\
-    __asm__ ("mr %0,%3"							\
-	     : "=r" (__xx.__i.__h),					\
-	       "=r" (__xx.__i.__l)					\
-	     : "%1" (m0),						\
-	       "r" (m1));						\
-    (xh) = __xx.__i.__h; (xl) = __xx.__i.__l;				\
+	  } __x;							\
+    __asm__ ("lr %N0,%1\n\tmr %0,%2"					\
+	     : "=&r" (__x.__ll)						\
+	     : "r" (m0), "r" (m1));					\
+    (xh) = __x.__i.__h; (xl) = __x.__i.__l;				\
   } while (0)
 #define sdiv_qrnnd(q, r, n1, n0, d) \
   do {									\
     union {DItype __ll;							\
 	   struct {USItype __h, __l;} __i;				\
-	  } __xx;							\
-    __xx.__i.__h = n1; __xx.__i.__l = n0;				\
+	  } __x;							\
+    __x.__i.__h = n1; __x.__i.__l = n0;					\
     __asm__ ("dr %0,%2"							\
-	     : "=r" (__xx.__ll)						\
-	     : "0" (__xx.__ll), "r" (d));				\
-    (q) = __xx.__i.__l; (r) = __xx.__i.__h;				\
+	     : "=r" (__x.__ll)						\
+	     : "0" (__x.__ll), "r" (d));				\
+    (q) = __x.__i.__l; (r) = __x.__i.__h;				\
   } while (0)
 #endif
 
@@ -438,11 +417,8 @@ UDItype __umulsidi3 (USItype, USItype);
 	     "1" ((USItype) (al)),					\
 	     "g" ((USItype) (bl)))
 
-/* The '020, '030, '040 and CPU32 have 32x32->64 and 64/32->32q-32r.  */
-#if defined (__mc68020__) || defined(mc68020) \
-	|| defined(__mc68030__) || defined(mc68030) \
-	|| defined(__mc68040__) || defined(mc68040) \
-	|| defined(__mcpu32__) || defined(mcpu32)
+/* The '020, '030, '040, '060 and CPU32 have 32x32->64 and 64/32->32q-32r.  */
+#if (defined (__mc68020__) && !defined (__mc68060__))
 #define umul_ppmm(w1, w0, u, v) \
   __asm__ ("mulu%.l %3,%1:%0"						\
 	   : "=d" ((USItype) (w0)),					\
@@ -466,8 +442,43 @@ UDItype __umulsidi3 (USItype, USItype);
 	     "1" ((USItype) (n1)),					\
 	     "dmi" ((USItype) (d)))
 
-#else /* not mc68020 */
-#if !defined(__mcf5200__)
+#elif defined (__mcoldfire__) /* not mc68020 */
+
+#define umul_ppmm(xh, xl, a, b) \
+  __asm__ ("| Inlined umul_ppmm\n"					\
+	   "	move%.l	%2,%/d0\n"					\
+	   "	move%.l	%3,%/d1\n"					\
+	   "	move%.l	%/d0,%/d2\n"					\
+	   "	swap	%/d0\n"						\
+	   "	move%.l	%/d1,%/d3\n"					\
+	   "	swap	%/d1\n"						\
+	   "	move%.w	%/d2,%/d4\n"					\
+	   "	mulu	%/d3,%/d4\n"					\
+	   "	mulu	%/d1,%/d2\n"					\
+	   "	mulu	%/d0,%/d3\n"					\
+	   "	mulu	%/d0,%/d1\n"					\
+	   "	move%.l	%/d4,%/d0\n"					\
+	   "	clr%.w	%/d0\n"						\
+	   "	swap	%/d0\n"						\
+	   "	add%.l	%/d0,%/d2\n"					\
+	   "	add%.l	%/d3,%/d2\n"					\
+	   "	jcc	1f\n"						\
+	   "	add%.l	%#65536,%/d1\n"					\
+	   "1:	swap	%/d2\n"						\
+	   "	moveq	%#0,%/d0\n"					\
+	   "	move%.w	%/d2,%/d0\n"					\
+	   "	move%.w	%/d4,%/d2\n"					\
+	   "	move%.l	%/d2,%1\n"					\
+	   "	add%.l	%/d1,%/d0\n"					\
+	   "	move%.l	%/d0,%0"					\
+	   : "=g" ((USItype) (xh)),					\
+	     "=g" ((USItype) (xl))					\
+	   : "g" ((USItype) (a)),					\
+	     "g" ((USItype) (b))					\
+	   : "d0", "d1", "d2", "d3", "d4")
+#define UMUL_TIME 100
+#define UDIV_TIME 400
+#else /* not ColdFire */
 /* %/ inserts REGISTER_PREFIX, %# inserts IMMEDIATE_PREFIX.  */
 #define umul_ppmm(xh, xl, a, b) \
   __asm__ ("| Inlined umul_ppmm\n"					\
@@ -503,14 +514,12 @@ UDItype __umulsidi3 (USItype, USItype);
 	   : "d0", "d1", "d2", "d3", "d4")
 #define UMUL_TIME 100
 #define UDIV_TIME 400
-#endif /* not mcf5200 */
+
 #endif /* not mc68020 */
 
-/* The '020, '030, '040 and '060 have bitfield insns.  */
-#if defined (__mc68020__) || defined(mc68020) \
-	|| defined(__mc68030__) || defined(mc68030) \
-	|| defined(__mc68040__) || defined(mc68040) \
-	|| defined(__mc68060__) || defined(mc68060)
+/* The '020, '030, '040 and '060 have bitfield insns.
+   cpu32 disguises as a 68020, but lacks them.  */
+#if defined (__mc68020__) && !defined (__mcpu32__)
 #define count_leading_zeros(count, x) \
   __asm__ ("bfffo %1{%b2:%b2},%0"					\
 	   : "=d" ((USItype) (count))					\
@@ -671,7 +680,7 @@ UDItype __umulsidi3 (USItype, USItype);
   __asm__ ("{cntlz|cntlzw} %0,%1" : "=r" (count) : "r" (x))
 #define COUNT_LEADING_ZEROS_0 32
 #if defined (_ARCH_PPC) || defined (__powerpc__) || defined (__POWERPC__) \
-  || defined (__ppc__) || defined (PPC) || defined (__vxworks__)
+  || defined (__ppc__) || defined (PPC)
 #define umul_ppmm(ph, pl, m0, m1) \
   do {									\
     USItype __m0 = (m0), __m1 = (m1);					\
@@ -1203,6 +1212,20 @@ UDItype __umulsidi3 (USItype, USItype);
   } while (0)
 #endif
 
+/* If we lack umul_ppmm but have smul_ppmm, define umul_ppmm in terms of
+   smul_ppmm.  */
+#if !defined (umul_ppmm) && defined (smul_ppmm)
+#define umul_ppmm(w1, w0, u, v)						\
+  do {									\
+    UWtype __w1;							\
+    UWtype __xm0 = (u), __xm1 = (v);					\
+    smul_ppmm (__w1, w0, __xm0, __xm1);					\
+    (w1) = __w1 + (-(__xm0 >> (W_TYPE_SIZE - 1)) & __xm1)		\
+		+ (-(__xm1 >> (W_TYPE_SIZE - 1)) & __xm0);		\
+  } while (0)
+#endif
+
+/* If we still don't have umul_ppmm, define it using plain C.  */
 #if !defined (umul_ppmm)
 #define umul_ppmm(w1, w0, u, v)						\
   do {									\
@@ -1292,7 +1315,6 @@ UDItype __umulsidi3 (USItype, USItype);
 #endif
 
 #if !defined (count_leading_zeros)
-extern const UQItype __clz_tab[];
 #define count_leading_zeros(count, x) \
   do {									\
     UWtype __xr = (x);							\
diff --git a/stdlib/lshift.c b/stdlib/lshift.c
new file mode 100644
index 0000000000..bedf44229f
--- /dev/null
+++ b/stdlib/lshift.c
@@ -0,0 +1,87 @@
+/* mpn_lshift -- Shift left low level.
+
+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 <gmp.h>
+#include "gmp-impl.h"
+
+/* Shift U (pointed to by UP and USIZE digits long) CNT bits to the left
+   and store the USIZE least significant digits of the result at WP.
+   Return the bits shifted out from the most significant digit.
+
+   Argument constraints:
+   1. 0 < CNT < BITS_PER_MP_LIMB
+   2. If the result is to be written over the input, WP must be >= UP.
+*/
+
+mp_limb_t
+#if __STDC__
+mpn_lshift (register mp_ptr wp,
+	    register mp_srcptr up, mp_size_t usize,
+	    register unsigned int cnt)
+#else
+mpn_lshift (wp, up, usize, cnt)
+     register mp_ptr wp;
+     register mp_srcptr up;
+     mp_size_t usize;
+     register unsigned int cnt;
+#endif
+{
+  register mp_limb_t high_limb, low_limb;
+  register unsigned sh_1, sh_2;
+  register mp_size_t i;
+  mp_limb_t retval;
+
+#ifdef DEBUG
+  if (usize == 0 || cnt == 0)
+    abort ();
+#endif
+
+  sh_1 = cnt;
+#if 0
+  if (sh_1 == 0)
+    {
+      if (wp != up)
+	{
+	  /* Copy from high end to low end, to allow specified input/output
+	     overlapping.  */
+	  for (i = usize - 1; i >= 0; i--)
+	    wp[i] = up[i];
+	}
+      return 0;
+    }
+#endif
+
+  wp += 1;
+  sh_2 = BITS_PER_MP_LIMB - sh_1;
+  i = usize - 1;
+  low_limb = up[i];
+  retval = low_limb >> sh_2;
+  high_limb = low_limb;
+  while (--i >= 0)
+    {
+      low_limb = up[i];
+      wp[i] = (high_limb << sh_1) | (low_limb >> sh_2);
+      high_limb = low_limb;
+    }
+  wp[i] = high_limb << sh_1;
+
+  return retval;
+}
diff --git a/stdlib/makecontext.c b/stdlib/makecontext.c
new file mode 100644
index 0000000000..a65868827f
--- /dev/null
+++ b/stdlib/makecontext.c
@@ -0,0 +1,30 @@
+/* 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 <errno.h>
+#include <ucontext.h>
+
+void
+makecontext (ucontext_t *ucp, void (*func) (void), int argc, ...)
+{
+  __set_errno (ENOSYS);
+}
+
+
+stub_warning (makecontext)
+#include <stub-tag.h>
diff --git a/stdlib/mod_1.c b/stdlib/mod_1.c
new file mode 100644
index 0000000000..3273c9222d
--- /dev/null
+++ b/stdlib/mod_1.c
@@ -0,0 +1,197 @@
+/* mpn_mod_1(dividend_ptr, dividend_size, divisor_limb) --
+   Divide (DIVIDEND_PTR,,DIVIDEND_SIZE) by DIVISOR_LIMB.
+   Return the single-limb remainder.
+   There are no constraints on the value of the divisor.
+
+Copyright (C) 1991, 1993, 1994, 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 <gmp.h>
+#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_mod_1 (mp_srcptr dividend_ptr, mp_size_t dividend_size,
+	   mp_limb_t divisor_limb)
+#else
+mpn_mod_1 (dividend_ptr, dividend_size, divisor_limb)
+     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;
+
+  /* Botch: 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 (dummy, r, r,
+				 ((n1 << normalization_steps)
+				  | (n0 >> (BITS_PER_MP_LIMB - normalization_steps))),
+				 divisor_limb, divisor_limb_inverted);
+	      n1 = n0;
+	    }
+	  udiv_qrnnd_preinv (dummy, 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
+	    i--;
+
+	  for (; i >= 0; i--)
+	    {
+	      n0 = dividend_ptr[i];
+	      udiv_qrnnd_preinv (dummy, 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 (dummy, r, r,
+			      ((n1 << normalization_steps)
+			       | (n0 >> (BITS_PER_MP_LIMB - normalization_steps))),
+			      divisor_limb);
+		  n1 = n0;
+		}
+	      udiv_qrnnd (dummy, 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
+	i--;
+
+      for (; i >= 0; i--)
+	{
+	  n0 = dividend_ptr[i];
+	  udiv_qrnnd (dummy, r, r, n0, divisor_limb);
+	}
+      return r;
+    }
+}
diff --git a/stdlib/mp_clz_tab.c b/stdlib/mp_clz_tab.c
new file mode 100644
index 0000000000..2220299e7c
--- /dev/null
+++ b/stdlib/mp_clz_tab.c
@@ -0,0 +1,37 @@
+/* __clz_tab -- support for longlong.h
+   Copyright (C) 1991, 1993, 1994, 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.  Its master source is NOT part of
+   the C library, however.  The master source lives in the GNU MP 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.  */
+
+#if 0
+#include <gmp.h>
+#include "gmp-impl.h"
+#endif
+
+const
+unsigned char __clz_tab[] =
+{
+  0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
+  6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+  7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+  7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+  8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+  8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+  8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+  8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+};
diff --git a/stdlib/mpn2dbl.c b/stdlib/mpn2dbl.c
new file mode 100644
index 0000000000..178edbf816
--- /dev/null
+++ b/stdlib/mpn2dbl.c
@@ -0,0 +1,30 @@
+/* Copyright (C) 1995, 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 <gmp.h>
+#include "gmp-impl.h"
+#include <float.h>
+
+/* Convert a multi-precision integer of the needed number of bits and an
+   integral power of two to a `double'.  */
+
+double
+__mpn_construct_double (mp_srcptr frac_ptr, int expt, int negative)
+{
+#error "__mpn_construct_double not implemented for this floating point format"
+}
diff --git a/stdlib/mpn2flt.c b/stdlib/mpn2flt.c
new file mode 100644
index 0000000000..16ec73c174
--- /dev/null
+++ b/stdlib/mpn2flt.c
@@ -0,0 +1,30 @@
+/* Copyright (C) 1995, 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 "gmp.h"
+#include "gmp-impl.h"
+#include <float.h>
+
+/* Convert a multi-precision integer of the needed number of bits and an
+   integral power of two to a `float'.  */
+
+float
+__mpn_construct_float (mp_srcptr frac_ptr, int expt, int negative)
+{
+#error "__mpn_construct_float not implemented for this floating point format"
+}
diff --git a/stdlib/mpn2ldbl.c b/stdlib/mpn2ldbl.c
new file mode 100644
index 0000000000..450f9381cc
--- /dev/null
+++ b/stdlib/mpn2ldbl.c
@@ -0,0 +1 @@
+/* Empty.  Not needed unless ldbl support is in. */
diff --git a/stdlib/mul.c b/stdlib/mul.c
new file mode 100644
index 0000000000..fe0cbf3d7f
--- /dev/null
+++ b/stdlib/mul.c
@@ -0,0 +1,152 @@
+/* mpn_mul -- Multiply two natural numbers.
+
+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 <gmp.h>
+#include "gmp-impl.h"
+
+/* Multiply the natural numbers u (pointed to by UP, with USIZE limbs)
+   and v (pointed to by VP, with VSIZE limbs), and store the result at
+   PRODP.  USIZE + VSIZE limbs are always stored, but if the input
+   operands are normalized.  Return the most significant limb of the
+   result.
+
+   NOTE: The space pointed to by PRODP is overwritten before finished
+   with U and V, so overlap is an error.
+
+   Argument constraints:
+   1. USIZE >= VSIZE.
+   2. PRODP != UP and PRODP != VP, i.e. the destination
+      must be distinct from the multiplier and the multiplicand.  */
+
+/* If KARATSUBA_THRESHOLD is not already defined, define it to a
+   value which is good on most machines.  */
+#ifndef KARATSUBA_THRESHOLD
+#define KARATSUBA_THRESHOLD 32
+#endif
+
+mp_limb_t
+#if __STDC__
+mpn_mul (mp_ptr prodp,
+	 mp_srcptr up, mp_size_t usize,
+	 mp_srcptr vp, mp_size_t vsize)
+#else
+mpn_mul (prodp, up, usize, vp, vsize)
+     mp_ptr prodp;
+     mp_srcptr up;
+     mp_size_t usize;
+     mp_srcptr vp;
+     mp_size_t vsize;
+#endif
+{
+  mp_ptr prod_endp = prodp + usize + vsize - 1;
+  mp_limb_t cy;
+  mp_ptr tspace;
+  TMP_DECL (marker);
+
+  if (vsize < KARATSUBA_THRESHOLD)
+    {
+      /* Handle simple cases with traditional multiplication.
+
+	 This is the most critical code of the entire function.  All
+	 multiplies rely on this, both small and huge.  Small ones arrive
+	 here immediately.  Huge ones arrive here as this is the base case
+	 for Karatsuba's recursive algorithm below.  */
+      mp_size_t i;
+      mp_limb_t cy_limb;
+      mp_limb_t v_limb;
+
+      if (vsize == 0)
+	return 0;
+
+      /* Multiply by the first limb in V separately, as the result can be
+	 stored (not added) to PROD.  We also avoid a loop for zeroing.  */
+      v_limb = vp[0];
+      if (v_limb <= 1)
+	{
+	  if (v_limb == 1)
+	    MPN_COPY (prodp, up, usize);
+	  else
+	    MPN_ZERO (prodp, usize);
+	  cy_limb = 0;
+	}
+      else
+	cy_limb = mpn_mul_1 (prodp, up, usize, v_limb);
+
+      prodp[usize] = cy_limb;
+      prodp++;
+
+      /* For each iteration in the outer loop, multiply one limb from
+	 U with one limb from V, and add it to PROD.  */
+      for (i = 1; i < vsize; i++)
+	{
+	  v_limb = vp[i];
+	  if (v_limb <= 1)
+	    {
+	      cy_limb = 0;
+	      if (v_limb == 1)
+		cy_limb = mpn_add_n (prodp, prodp, up, usize);
+	    }
+	  else
+	    cy_limb = mpn_addmul_1 (prodp, up, usize, v_limb);
+
+	  prodp[usize] = cy_limb;
+	  prodp++;
+	}
+      return cy_limb;
+    }
+
+  TMP_MARK (marker);
+
+  tspace = (mp_ptr) TMP_ALLOC (2 * vsize * BYTES_PER_MP_LIMB);
+  MPN_MUL_N_RECURSE (prodp, up, vp, vsize, tspace);
+
+  prodp += vsize;
+  up += vsize;
+  usize -= vsize;
+  if (usize >= vsize)
+    {
+      mp_ptr tp = (mp_ptr) TMP_ALLOC (2 * vsize * BYTES_PER_MP_LIMB);
+      do
+	{
+	  MPN_MUL_N_RECURSE (tp, up, vp, vsize, tspace);
+	  cy = mpn_add_n (prodp, prodp, tp, vsize);
+	  mpn_add_1 (prodp + vsize, tp + vsize, vsize, cy);
+	  prodp += vsize;
+	  up += vsize;
+	  usize -= vsize;
+	}
+      while (usize >= vsize);
+    }
+
+  /* True: usize < vsize.  */
+
+  /* Make life simple: Recurse.  */
+
+  if (usize != 0)
+    {
+      mpn_mul (tspace, vp, vsize, up, usize);
+      cy = mpn_add_n (prodp, prodp, tspace, vsize);
+      mpn_add_1 (prodp + vsize, tspace + vsize, usize, cy);
+    }
+
+  TMP_FREE (marker);
+  return *prod_endp;
+}
diff --git a/stdlib/mul_1.c b/stdlib/mul_1.c
new file mode 100644
index 0000000000..686e6c5efe
--- /dev/null
+++ b/stdlib/mul_1.c
@@ -0,0 +1,59 @@
+/* mpn_mul_1 -- Multiply a limb vector with a single limb and
+   store the product in a second limb vector.
+
+Copyright (C) 1991, 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 <gmp.h>
+#include "gmp-impl.h"
+#include "longlong.h"
+
+mp_limb_t
+mpn_mul_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;
+
+  /* The loop counter and index J goes from -S1_SIZE to -1.  This way
+     the loop becomes faster.  */
+  j = -s1_size;
+
+  /* Offset the base pointers to compensate for the negative indices.  */
+  s1_ptr -= j;
+  res_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;
+
+      res_ptr[j] = prod_low;
+    }
+  while (++j != 0);
+
+  return cy_limb;
+}
diff --git a/stdlib/mul_n.c b/stdlib/mul_n.c
new file mode 100644
index 0000000000..b478c76aba
--- /dev/null
+++ b/stdlib/mul_n.c
@@ -0,0 +1,401 @@
+/* mpn_mul_n -- Multiply two natural numbers of length n.
+
+Copyright (C) 1991, 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 <gmp.h>
+#include "gmp-impl.h"
+
+/* Multiply the natural numbers u (pointed to by UP) and v (pointed to by VP),
+   both with SIZE limbs, and store the result at PRODP.  2 * SIZE limbs are
+   always stored.  Return the most significant limb.
+
+   Argument constraints:
+   1. PRODP != UP and PRODP != VP, i.e. the destination
+      must be distinct from the multiplier and the multiplicand.  */
+
+/* If KARATSUBA_THRESHOLD is not already defined, define it to a
+   value which is good on most machines.  */
+#ifndef KARATSUBA_THRESHOLD
+#define KARATSUBA_THRESHOLD 32
+#endif
+
+/* The code can't handle KARATSUBA_THRESHOLD smaller than 2.  */
+#if KARATSUBA_THRESHOLD < 2
+#undef KARATSUBA_THRESHOLD
+#define KARATSUBA_THRESHOLD 2
+#endif
+
+/* Handle simple cases with traditional multiplication.
+
+   This is the most critical code of multiplication.  All multiplies rely
+   on this, both small and huge.  Small ones arrive here immediately.  Huge
+   ones arrive here as this is the base case for Karatsuba's recursive
+   algorithm below.  */
+
+void
+#if __STDC__
+impn_mul_n_basecase (mp_ptr prodp, mp_srcptr up, mp_srcptr vp, mp_size_t size)
+#else
+impn_mul_n_basecase (prodp, up, vp, size)
+     mp_ptr prodp;
+     mp_srcptr up;
+     mp_srcptr vp;
+     mp_size_t size;
+#endif
+{
+  mp_size_t i;
+  mp_limb_t cy_limb;
+  mp_limb_t v_limb;
+
+  /* Multiply by the first limb in V separately, as the result can be
+     stored (not added) to PROD.  We also avoid a loop for zeroing.  */
+  v_limb = vp[0];
+  if (v_limb <= 1)
+    {
+      if (v_limb == 1)
+	MPN_COPY (prodp, up, size);
+      else
+	MPN_ZERO (prodp, size);
+      cy_limb = 0;
+    }
+  else
+    cy_limb = mpn_mul_1 (prodp, up, size, v_limb);
+
+  prodp[size] = cy_limb;
+  prodp++;
+
+  /* For each iteration in the outer loop, multiply one limb from
+     U with one limb from V, and add it to PROD.  */
+  for (i = 1; i < size; i++)
+    {
+      v_limb = vp[i];
+      if (v_limb <= 1)
+	{
+	  cy_limb = 0;
+	  if (v_limb == 1)
+	    cy_limb = mpn_add_n (prodp, prodp, up, size);
+	}
+      else
+	cy_limb = mpn_addmul_1 (prodp, up, size, v_limb);
+
+      prodp[size] = cy_limb;
+      prodp++;
+    }
+}
+
+void
+#if __STDC__
+impn_mul_n (mp_ptr prodp,
+	     mp_srcptr up, mp_srcptr vp, mp_size_t size, mp_ptr tspace)
+#else
+impn_mul_n (prodp, up, vp, size, tspace)
+     mp_ptr prodp;
+     mp_srcptr up;
+     mp_srcptr vp;
+     mp_size_t size;
+     mp_ptr tspace;
+#endif
+{
+  if ((size & 1) != 0)
+    {
+      /* The size is odd, the code code below doesn't handle that.
+	 Multiply the least significant (size - 1) limbs with a recursive
+	 call, and handle the most significant limb of S1 and S2
+	 separately.  */
+      /* A slightly faster way to do this would be to make the Karatsuba
+	 code below behave as if the size were even, and let it check for
+	 odd size in the end.  I.e., in essence move this code to the end.
+	 Doing so would save us a recursive call, and potentially make the
+	 stack grow a lot less.  */
+
+      mp_size_t esize = size - 1;	/* even size */
+      mp_limb_t cy_limb;
+
+      MPN_MUL_N_RECURSE (prodp, up, vp, esize, tspace);
+      cy_limb = mpn_addmul_1 (prodp + esize, up, esize, vp[esize]);
+      prodp[esize + esize] = cy_limb;
+      cy_limb = mpn_addmul_1 (prodp + esize, vp, size, up[esize]);
+
+      prodp[esize + size] = cy_limb;
+    }
+  else
+    {
+      /* Anatolij Alekseevich Karatsuba's divide-and-conquer algorithm.
+
+	 Split U in two pieces, U1 and U0, such that
+	 U = U0 + U1*(B**n),
+	 and V in V1 and V0, such that
+	 V = V0 + V1*(B**n).
+
+	 UV is then computed recursively using the identity
+
+		2n   n          n                     n
+	 UV = (B  + B )U V  +  B (U -U )(V -V )  +  (B + 1)U V
+			1 1        1  0   0  1              0 0
+
+	 Where B = 2**BITS_PER_MP_LIMB.  */
+
+      mp_size_t hsize = size >> 1;
+      mp_limb_t cy;
+      int negflg;
+
+      /*** Product H.	 ________________  ________________
+			|_____U1 x V1____||____U0 x V0_____|  */
+      /* Put result in upper part of PROD and pass low part of TSPACE
+	 as new TSPACE.  */
+      MPN_MUL_N_RECURSE (prodp + size, up + hsize, vp + hsize, hsize, tspace);
+
+      /*** Product M.	 ________________
+			|_(U1-U0)(V0-V1)_|  */
+      if (mpn_cmp (up + hsize, up, hsize) >= 0)
+	{
+	  mpn_sub_n (prodp, up + hsize, up, hsize);
+	  negflg = 0;
+	}
+      else
+	{
+	  mpn_sub_n (prodp, up, up + hsize, hsize);
+	  negflg = 1;
+	}
+      if (mpn_cmp (vp + hsize, vp, hsize) >= 0)
+	{
+	  mpn_sub_n (prodp + hsize, vp + hsize, vp, hsize);
+	  negflg ^= 1;
+	}
+      else
+	{
+	  mpn_sub_n (prodp + hsize, vp, vp + hsize, hsize);
+	  /* No change of NEGFLG.  */
+	}
+      /* Read temporary operands from low part of PROD.
+	 Put result in low part of TSPACE using upper part of TSPACE
+	 as new TSPACE.  */
+      MPN_MUL_N_RECURSE (tspace, prodp, prodp + hsize, hsize, tspace + size);
+
+      /*** Add/copy product H.  */
+      MPN_COPY (prodp + hsize, prodp + size, hsize);
+      cy = mpn_add_n (prodp + size, prodp + size, prodp + size + hsize, hsize);
+
+      /*** Add product M (if NEGFLG M is a negative number).  */
+      if (negflg)
+	cy -= mpn_sub_n (prodp + hsize, prodp + hsize, tspace, size);
+      else
+	cy += mpn_add_n (prodp + hsize, prodp + hsize, tspace, size);
+
+      /*** Product L.	 ________________  ________________
+			|________________||____U0 x V0_____|  */
+      /* Read temporary operands from low part of PROD.
+	 Put result in low part of TSPACE using upper part of TSPACE
+	 as new TSPACE.  */
+      MPN_MUL_N_RECURSE (tspace, up, vp, hsize, tspace + size);
+
+      /*** Add/copy Product L (twice).  */
+
+      cy += mpn_add_n (prodp + hsize, prodp + hsize, tspace, size);
+      if (cy)
+	mpn_add_1 (prodp + hsize + size, prodp + hsize + size, hsize, cy);
+
+      MPN_COPY (prodp, tspace, hsize);
+      cy = mpn_add_n (prodp + hsize, prodp + hsize, tspace + hsize, hsize);
+      if (cy)
+	mpn_add_1 (prodp + size, prodp + size, size, 1);
+    }
+}
+
+void
+#if __STDC__
+impn_sqr_n_basecase (mp_ptr prodp, mp_srcptr up, mp_size_t size)
+#else
+impn_sqr_n_basecase (prodp, up, size)
+     mp_ptr prodp;
+     mp_srcptr up;
+     mp_size_t size;
+#endif
+{
+  mp_size_t i;
+  mp_limb_t cy_limb;
+  mp_limb_t v_limb;
+
+  /* Multiply by the first limb in V separately, as the result can be
+     stored (not added) to PROD.  We also avoid a loop for zeroing.  */
+  v_limb = up[0];
+  if (v_limb <= 1)
+    {
+      if (v_limb == 1)
+	MPN_COPY (prodp, up, size);
+      else
+	MPN_ZERO (prodp, size);
+      cy_limb = 0;
+    }
+  else
+    cy_limb = mpn_mul_1 (prodp, up, size, v_limb);
+
+  prodp[size] = cy_limb;
+  prodp++;
+
+  /* For each iteration in the outer loop, multiply one limb from
+     U with one limb from V, and add it to PROD.  */
+  for (i = 1; i < size; i++)
+    {
+      v_limb = up[i];
+      if (v_limb <= 1)
+	{
+	  cy_limb = 0;
+	  if (v_limb == 1)
+	    cy_limb = mpn_add_n (prodp, prodp, up, size);
+	}
+      else
+	cy_limb = mpn_addmul_1 (prodp, up, size, v_limb);
+
+      prodp[size] = cy_limb;
+      prodp++;
+    }
+}
+
+void
+#if __STDC__
+impn_sqr_n (mp_ptr prodp,
+	     mp_srcptr up, mp_size_t size, mp_ptr tspace)
+#else
+impn_sqr_n (prodp, up, size, tspace)
+     mp_ptr prodp;
+     mp_srcptr up;
+     mp_size_t size;
+     mp_ptr tspace;
+#endif
+{
+  if ((size & 1) != 0)
+    {
+      /* The size is odd, the code code below doesn't handle that.
+	 Multiply the least significant (size - 1) limbs with a recursive
+	 call, and handle the most significant limb of S1 and S2
+	 separately.  */
+      /* A slightly faster way to do this would be to make the Karatsuba
+	 code below behave as if the size were even, and let it check for
+	 odd size in the end.  I.e., in essence move this code to the end.
+	 Doing so would save us a recursive call, and potentially make the
+	 stack grow a lot less.  */
+
+      mp_size_t esize = size - 1;	/* even size */
+      mp_limb_t cy_limb;
+
+      MPN_SQR_N_RECURSE (prodp, up, esize, tspace);
+      cy_limb = mpn_addmul_1 (prodp + esize, up, esize, up[esize]);
+      prodp[esize + esize] = cy_limb;
+      cy_limb = mpn_addmul_1 (prodp + esize, up, size, up[esize]);
+
+      prodp[esize + size] = cy_limb;
+    }
+  else
+    {
+      mp_size_t hsize = size >> 1;
+      mp_limb_t cy;
+
+      /*** Product H.	 ________________  ________________
+			|_____U1 x U1____||____U0 x U0_____|  */
+      /* Put result in upper part of PROD and pass low part of TSPACE
+	 as new TSPACE.  */
+      MPN_SQR_N_RECURSE (prodp + size, up + hsize, hsize, tspace);
+
+      /*** Product M.	 ________________
+			|_(U1-U0)(U0-U1)_|  */
+      if (mpn_cmp (up + hsize, up, hsize) >= 0)
+	{
+	  mpn_sub_n (prodp, up + hsize, up, hsize);
+	}
+      else
+	{
+	  mpn_sub_n (prodp, up, up + hsize, hsize);
+	}
+
+      /* Read temporary operands from low part of PROD.
+	 Put result in low part of TSPACE using upper part of TSPACE
+	 as new TSPACE.  */
+      MPN_SQR_N_RECURSE (tspace, prodp, hsize, tspace + size);
+
+      /*** Add/copy product H.  */
+      MPN_COPY (prodp + hsize, prodp + size, hsize);
+      cy = mpn_add_n (prodp + size, prodp + size, prodp + size + hsize, hsize);
+
+      /*** Add product M (if NEGFLG M is a negative number).  */
+      cy -= mpn_sub_n (prodp + hsize, prodp + hsize, tspace, size);
+
+      /*** Product L.	 ________________  ________________
+			|________________||____U0 x U0_____|  */
+      /* Read temporary operands from low part of PROD.
+	 Put result in low part of TSPACE using upper part of TSPACE
+	 as new TSPACE.  */
+      MPN_SQR_N_RECURSE (tspace, up, hsize, tspace + size);
+
+      /*** Add/copy Product L (twice).  */
+
+      cy += mpn_add_n (prodp + hsize, prodp + hsize, tspace, size);
+      if (cy)
+	mpn_add_1 (prodp + hsize + size, prodp + hsize + size, hsize, cy);
+
+      MPN_COPY (prodp, tspace, hsize);
+      cy = mpn_add_n (prodp + hsize, prodp + hsize, tspace + hsize, hsize);
+      if (cy)
+	mpn_add_1 (prodp + size, prodp + size, size, 1);
+    }
+}
+
+/* This should be made into an inline function in gmp.h.  */
+void
+#if __STDC__
+mpn_mul_n (mp_ptr prodp, mp_srcptr up, mp_srcptr vp, mp_size_t size)
+#else
+mpn_mul_n (prodp, up, vp, size)
+     mp_ptr prodp;
+     mp_srcptr up;
+     mp_srcptr vp;
+     mp_size_t size;
+#endif
+{
+  TMP_DECL (marker);
+  TMP_MARK (marker);
+  if (up == vp)
+    {
+      if (size < KARATSUBA_THRESHOLD)
+	{
+	  impn_sqr_n_basecase (prodp, up, size);
+	}
+      else
+	{
+	  mp_ptr tspace;
+	  tspace = (mp_ptr) TMP_ALLOC (2 * size * BYTES_PER_MP_LIMB);
+	  impn_sqr_n (prodp, up, size, tspace);
+	}
+    }
+  else
+    {
+      if (size < KARATSUBA_THRESHOLD)
+	{
+	  impn_mul_n_basecase (prodp, up, vp, size);
+	}
+      else
+	{
+	  mp_ptr tspace;
+	  tspace = (mp_ptr) TMP_ALLOC (2 * size * BYTES_PER_MP_LIMB);
+	  impn_mul_n (prodp, up, vp, size, tspace);
+	}
+    }
+  TMP_FREE (marker);
+}
diff --git a/stdlib/on_exit.c b/stdlib/on_exit.c
index d98fbb3a86..e777604084 100644
--- a/stdlib/on_exit.c
+++ b/stdlib/on_exit.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991, 1996 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 1996, 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
@@ -18,6 +18,8 @@
 
 #include <stdlib.h>
 #include "exit.h"
+#include <atomic.h>
+#include <sysdep.h>
 
 /* Register a function to be called by exit.  */
 int
@@ -28,9 +30,13 @@ __on_exit (void (*func) (int status, void *arg), void *arg)
   if (new == NULL)
     return -1;
 
-  new->flavor = ef_on;
+#ifdef PTR_MANGLE
+  PTR_MANGLE (func);
+#endif
   new->func.on.fn = func;
   new->func.on.arg = arg;
+  atomic_write_barrier ();
+  new->flavor = ef_on;
   return 0;
 }
 weak_alias (__on_exit, on_exit)
diff --git a/stdlib/putenv.c b/stdlib/putenv.c
new file mode 100644
index 0000000000..4e8693403a
--- /dev/null
+++ b/stdlib/putenv.c
@@ -0,0 +1,72 @@
+/* Copyright (C) 1991, 94, 95, 96, 97, 98, 99 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.  */
+
+#if defined _AIX && !defined __GNUC__
+ #pragma alloca
+#endif
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#if _LIBC || HAVE_STDLIB_H
+# include <stdlib.h>
+#endif
+#if _LIBC || HAVE_STRING_H
+# include <string.h>
+#endif
+
+#if !__GNU_LIBRARY__ && !HAVE_STRCHR
+# define strchr index
+#endif
+
+#ifndef _LIBC
+# ifdef HAVE_ALLOCA_H
+#  include <alloca.h>
+# else
+#  ifdef __GNUC__
+#   define alloca __builtin_alloca
+#  else
+extern char *alloca ();
+#  endif /* __GNUC__ */
+# endif /* HAVE_ALLOCA_H */
+#endif /* _LIBC */
+
+
+/* Put STRING, which is of the form "NAME=VALUE", in the environment.  */
+int
+putenv (string)
+     char *string;
+{
+  const char *const name_end = strchr (string, '=');
+
+  if (name_end != NULL)
+    {
+#ifdef _LIBC
+      char *name = strndupa (string, name_end - string);
+#else
+      char *name = alloca (name_end - string + 1);
+      memcpy (name, string, name_end - string);
+      name[name_end - string] = '\0';
+#endif
+      return __add_to_environ (name, NULL, string, 1);
+    }
+
+  __unsetenv (string);
+  return 0;
+}
diff --git a/stdlib/rshift.c b/stdlib/rshift.c
new file mode 100644
index 0000000000..9d0a9c4c0e
--- /dev/null
+++ b/stdlib/rshift.c
@@ -0,0 +1,88 @@
+/* mpn_rshift -- Shift right a low-level natural-number integer.
+
+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 <gmp.h>
+#include "gmp-impl.h"
+
+/* Shift U (pointed to by UP and USIZE limbs long) CNT bits to the right
+   and store the USIZE least significant limbs of the result at WP.
+   The bits shifted out to the right are returned.
+
+   Argument constraints:
+   1. 0 < CNT < BITS_PER_MP_LIMB
+   2. If the result is to be written over the input, WP must be <= UP.
+*/
+
+mp_limb_t
+#if __STDC__
+mpn_rshift (register mp_ptr wp,
+	    register mp_srcptr up, mp_size_t usize,
+	    register unsigned int cnt)
+#else
+mpn_rshift (wp, up, usize, cnt)
+     register mp_ptr wp;
+     register mp_srcptr up;
+     mp_size_t usize;
+     register unsigned int cnt;
+#endif
+{
+  register mp_limb_t high_limb, low_limb;
+  register unsigned sh_1, sh_2;
+  register mp_size_t i;
+  mp_limb_t retval;
+
+#ifdef DEBUG
+  if (usize == 0 || cnt == 0)
+    abort ();
+#endif
+
+  sh_1 = cnt;
+
+#if 0
+  if (sh_1 == 0)
+    {
+      if (wp != up)
+	{
+	  /* Copy from low end to high end, to allow specified input/output
+	     overlapping.  */
+	  for (i = 0; i < usize; i++)
+	    wp[i] = up[i];
+	}
+      return usize;
+    }
+#endif
+
+  wp -= 1;
+  sh_2 = BITS_PER_MP_LIMB - sh_1;
+  high_limb = up[0];
+  retval = high_limb << sh_2;
+  low_limb = high_limb;
+
+  for (i = 1; i < usize; i++)
+    {
+      high_limb = up[i];
+      wp[i] = (low_limb >> sh_1) | (high_limb << sh_2);
+      low_limb = high_limb;
+    }
+  wp[i] = low_limb >> sh_1;
+
+  return retval;
+}
diff --git a/stdlib/setcontext.c b/stdlib/setcontext.c
new file mode 100644
index 0000000000..5841e20317
--- /dev/null
+++ b/stdlib/setcontext.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 <errno.h>
+#include <ucontext.h>
+
+int
+setcontext (ucp)
+     const ucontext_t *ucp;
+{
+  __set_errno (ENOSYS);
+  return -1;
+}
+
+
+stub_warning (setcontext)
+#include <stub-tag.h>
diff --git a/stdlib/setenv.c b/stdlib/setenv.c
new file mode 100644
index 0000000000..48aaecffe0
--- /dev/null
+++ b/stdlib/setenv.c
@@ -0,0 +1,353 @@
+/* Copyright (C) 1992,1995-2001,2004 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.  */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <errno.h>
+#if !_LIBC
+# if !defined errno && !defined HAVE_ERRNO_DECL
+extern int errno;
+# endif
+# define __set_errno(ev) ((errno) = (ev))
+#endif
+
+#if _LIBC || HAVE_STDLIB_H
+# include <stdlib.h>
+#endif
+#if _LIBC || HAVE_STRING_H
+# include <string.h>
+#endif
+#if _LIBC || HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#if !_LIBC
+# define __environ	environ
+# ifndef HAVE_ENVIRON_DECL
+extern char **environ;
+# endif
+#endif
+
+#if _LIBC
+/* This lock protects against simultaneous modifications of `environ'.  */
+# include <bits/libc-lock.h>
+__libc_lock_define_initialized (static, envlock)
+# define LOCK	__libc_lock_lock (envlock)
+# define UNLOCK	__libc_lock_unlock (envlock)
+#else
+# define LOCK
+# define UNLOCK
+#endif
+
+/* In the GNU C library we must keep the namespace clean.  */
+#ifdef _LIBC
+# define setenv __setenv
+# define unsetenv __unsetenv
+# define clearenv __clearenv
+# define tfind __tfind
+# define tsearch __tsearch
+#endif
+
+/* In the GNU C library implementation we try to be more clever and
+   allow arbitrarily many changes of the environment given that the used
+   values are from a small set.  Outside glibc this will eat up all
+   memory after a while.  */
+#if defined _LIBC || (defined HAVE_SEARCH_H && defined HAVE_TSEARCH \
+		      && defined __GNUC__)
+# define USE_TSEARCH	1
+# include <search.h>
+
+/* This is a pointer to the root of the search tree with the known
+   values.  */
+static void *known_values;
+
+# define KNOWN_VALUE(Str) \
+  ({									      \
+    void *value = tfind (Str, &known_values, (__compar_fn_t) strcmp);	      \
+    value != NULL ? *(char **) value : NULL;				      \
+  })
+# define STORE_VALUE(Str) \
+  tsearch (Str, &known_values, (__compar_fn_t) strcmp)
+
+#else
+# undef USE_TSEARCH
+
+# define KNOWN_VALUE(Str) NULL
+# define STORE_VALUE(Str) do { } while (0)
+
+#endif
+
+
+/* If this variable is not a null pointer we allocated the current
+   environment.  */
+static char **last_environ;
+
+
+/* This function is used by `setenv' and `putenv'.  The difference between
+   the two functions is that for the former must create a new string which
+   is then placed in the environment, while the argument of `putenv'
+   must be used directly.  This is all complicated by the fact that we try
+   to reuse values once generated for a `setenv' call since we can never
+   free the strings.  */
+int
+__add_to_environ (name, value, combined, replace)
+     const char *name;
+     const char *value;
+     const char *combined;
+     int replace;
+{
+  register char **ep;
+  register size_t size;
+  const size_t namelen = strlen (name);
+  const size_t vallen = value != NULL ? strlen (value) + 1 : 0;
+
+  LOCK;
+
+  /* We have to get the pointer now that we have the lock and not earlier
+     since another thread might have created a new environment.  */
+  ep = __environ;
+
+  size = 0;
+  if (ep != NULL)
+    {
+      for (; *ep != NULL; ++ep)
+	if (!strncmp (*ep, name, namelen) && (*ep)[namelen] == '=')
+	  break;
+	else
+	  ++size;
+    }
+
+  if (ep == NULL || __builtin_expect (*ep == NULL, 1))
+    {
+      char **new_environ;
+
+      /* We allocated this space; we can extend it.  */
+      new_environ = (char **) realloc (last_environ,
+				       (size + 2) * sizeof (char *));
+      if (new_environ == NULL)
+	{
+	  UNLOCK;
+	  return -1;
+	}
+
+      /* If the whole entry is given add it.  */
+      if (combined != NULL)
+	/* We must not add the string to the search tree since it belongs
+	   to the user.  */
+	new_environ[size] = (char *) combined;
+      else
+	{
+	  /* See whether the value is already known.  */
+#ifdef USE_TSEARCH
+# ifdef __GNUC__
+	  char new_value[namelen + 1 + vallen];
+# else
+	  char *new_value = (char *) alloca (namelen + 1 + vallen);
+# endif
+# ifdef _LIBC
+	  __mempcpy (__mempcpy (__mempcpy (new_value, name, namelen), "=", 1),
+		     value, vallen);
+# else
+	  memcpy (new_value, name, namelen);
+	  new_value[namelen] = '=';
+	  memcpy (&new_value[namelen + 1], value, vallen);
+# endif
+
+	  new_environ[size] = KNOWN_VALUE (new_value);
+	  if (__builtin_expect (new_environ[size] == NULL, 1))
+#endif
+	    {
+	      new_environ[size] = (char *) malloc (namelen + 1 + vallen);
+	      if (__builtin_expect (new_environ[size] == NULL, 0))
+		{
+		  __set_errno (ENOMEM);
+		  UNLOCK;
+		  return -1;
+		}
+
+#ifdef USE_TSEARCH
+	      memcpy (new_environ[size], new_value, namelen + 1 + vallen);
+#else
+	      memcpy (new_environ[size], name, namelen);
+	      new_environ[size][namelen] = '=';
+	      memcpy (&new_environ[size][namelen + 1], value, vallen);
+#endif
+	      /* And save the value now.  We cannot do this when we remove
+		 the string since then we cannot decide whether it is a
+		 user string or not.  */
+	      STORE_VALUE (new_environ[size]);
+	    }
+	}
+
+      if (__environ != last_environ)
+	memcpy ((char *) new_environ, (char *) __environ,
+		size * sizeof (char *));
+
+      new_environ[size + 1] = NULL;
+
+      last_environ = __environ = new_environ;
+    }
+  else if (replace)
+    {
+      char *np;
+
+      /* Use the user string if given.  */
+      if (combined != NULL)
+	np = (char *) combined;
+      else
+	{
+#ifdef USE_TSEARCH
+# ifdef __GNUC__
+	  char new_value[namelen + 1 + vallen];
+# else
+	  char *new_value = (char *) alloca (namelen + 1 + vallen);
+# endif
+# ifdef _LIBC
+	  __mempcpy (__mempcpy (__mempcpy (new_value, name, namelen), "=", 1),
+		     value, vallen);
+# else
+	  memcpy (new_value, name, namelen);
+	  new_value[namelen] = '=';
+	  memcpy (&new_value[namelen + 1], value, vallen);
+# endif
+
+	  np = KNOWN_VALUE (new_value);
+	  if (__builtin_expect (np == NULL, 1))
+#endif
+	    {
+	      np = malloc (namelen + 1 + vallen);
+	      if (__builtin_expect (np == NULL, 0))
+		{
+		  UNLOCK;
+		  return -1;
+		}
+
+#ifdef USE_TSEARCH
+	      memcpy (np, new_value, namelen + 1 + vallen);
+#else
+	      memcpy (np, name, namelen);
+	      np[namelen] = '=';
+	      memcpy (&np[namelen + 1], value, vallen);
+#endif
+	      /* And remember the value.  */
+	      STORE_VALUE (np);
+	    }
+	}
+
+      *ep = np;
+    }
+
+  UNLOCK;
+
+  return 0;
+}
+
+int
+setenv (name, value, replace)
+     const char *name;
+     const char *value;
+     int replace;
+{
+  if (name == NULL || *name == '\0' || strchr (name, '=') != NULL)
+    {
+      __set_errno (EINVAL);
+      return -1;
+    }
+
+  return __add_to_environ (name, value, NULL, replace);
+}
+
+int
+unsetenv (name)
+     const char *name;
+{
+  size_t len;
+  char **ep;
+
+  if (name == NULL || *name == '\0' || strchr (name, '=') != NULL)
+    {
+      __set_errno (EINVAL);
+      return -1;
+    }
+
+  len = strlen (name);
+
+  LOCK;
+
+  ep = __environ;
+  while (*ep != NULL)
+    if (!strncmp (*ep, name, len) && (*ep)[len] == '=')
+      {
+	/* Found it.  Remove this pointer by moving later ones back.  */
+	char **dp = ep;
+
+	do
+	  dp[0] = dp[1];
+	while (*dp++);
+	/* Continue the loop in case NAME appears again.  */
+      }
+    else
+      ++ep;
+
+  UNLOCK;
+
+  return 0;
+}
+
+/* The `clearenv' was planned to be added to POSIX.1 but probably
+   never made it.  Nevertheless the POSIX.9 standard (POSIX bindings
+   for Fortran 77) requires this function.  */
+int
+clearenv ()
+{
+  LOCK;
+
+  if (__environ == last_environ && __environ != NULL)
+    {
+      /* We allocated this environment so we can free it.  */
+      free (__environ);
+      last_environ = NULL;
+    }
+
+  /* Clear the environment pointer removes the whole environment.  */
+  __environ = NULL;
+
+  UNLOCK;
+
+  return 0;
+}
+#ifdef _LIBC
+libc_freeres_fn (free_mem)
+{
+  /* Remove all traces.  */
+  clearenv ();
+
+  /* Now remove the search tree.  */
+  __tdestroy (known_values, free);
+  known_values = NULL;
+}
+
+# undef setenv
+# undef unsetenv
+# undef clearenv
+weak_alias (__setenv, setenv)
+weak_alias (__unsetenv, unsetenv)
+weak_alias (__clearenv, clearenv)
+#endif
diff --git a/stdlib/strtod_l.c b/stdlib/strtod_l.c
index 3a1c1ebd4b..c7901c29fe 100644
--- a/stdlib/strtod_l.c
+++ b/stdlib/strtod_l.c
@@ -68,8 +68,8 @@ extern unsigned long long int ____strtoull_l_internal (const char *, char **,
    and _LONG_LONG_LIMB in it can take effect into gmp.h.  */
 #include <gmp-mparam.h>
 #include <gmp.h>
-#include <gmp-impl.h>
-#include <longlong.h>
+#include "gmp-impl.h"
+#include "longlong.h"
 #include "fpioconst.h"
 
 #define NDEBUG 1
diff --git a/stdlib/strtoimax.c b/stdlib/strtoimax.c
new file mode 100644
index 0000000000..f1de70f320
--- /dev/null
+++ b/stdlib/strtoimax.c
@@ -0,0 +1 @@
+#error "The correct implementation must be chosen based on the `intmax_t' type"
diff --git a/stdlib/strtol.c b/stdlib/strtol.c
new file mode 100644
index 0000000000..02ec19aabe
--- /dev/null
+++ b/stdlib/strtol.c
@@ -0,0 +1,111 @@
+/* Convert string representation of a number into an integer value.
+   Copyright (C) 1991,92,94,95,96,97,98,99,2000,2001,2002,2003,2004
+   	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 <stdlib.h>
+#include <wchar.h>
+#include <locale/localeinfo.h>
+
+#ifndef UNSIGNED
+# define UNSIGNED 0
+# define INT LONG int
+#else
+# define INT unsigned LONG int
+#endif
+
+#if UNSIGNED
+# ifdef USE_WIDE_CHAR
+#  ifdef QUAD
+#   define strtol wcstoull
+#   define __strtol_l __wcstoull_l
+#  else
+#   define strtol wcstoul
+#   define __strtol_l __wcstoul_l
+#  endif
+# else
+#  ifdef QUAD
+#   define strtol strtoull
+#   define __strtol_l __strtoull_l
+#  else
+#   define strtol strtoul
+#   define __strtol_l __strtoul_l
+#  endif
+# endif
+#else
+# ifdef USE_WIDE_CHAR
+#  ifdef QUAD
+#   define strtol wcstoll
+#   define __strtol_l __wcstoll_l
+#  else
+#   define strtol wcstol
+#   define __strtol_l __wcstol_l
+#  endif
+# else
+#  ifdef QUAD
+#   define strtol strtoll
+#   define __strtol_l __strtoll_l
+#  endif
+# endif
+#endif
+
+
+/* If QUAD is defined, we are defining `strtoll' or `strtoull',
+   operating on `long long int's.  */
+#ifdef QUAD
+# define LONG long long
+#else
+# define LONG long
+#endif
+
+
+#ifdef USE_WIDE_CHAR
+# define STRING_TYPE wchar_t
+#else
+# define STRING_TYPE char
+#endif
+
+
+#define INTERNAL(X) INTERNAL1(X)
+#define INTERNAL1(X) __##X##_internal
+
+
+extern INT INTERNAL (__strtol_l) (const STRING_TYPE *, STRING_TYPE **, int,
+				  int, __locale_t);
+
+
+INT
+INTERNAL (strtol) (nptr, endptr, base, group)
+     const STRING_TYPE *nptr;
+     STRING_TYPE **endptr;
+     int base;
+     int group;
+{
+  return INTERNAL (__strtol_l) (nptr, endptr, base, group, _NL_CURRENT_LOCALE);
+}
+libc_hidden_def (INTERNAL (strtol))
+
+
+INT
+strtol (nptr, endptr, base)
+     const STRING_TYPE *nptr;
+     STRING_TYPE **endptr;
+     int base;
+{
+  return INTERNAL (__strtol_l) (nptr, endptr, base, 0, _NL_CURRENT_LOCALE);
+}
diff --git a/stdlib/strtol_l.c b/stdlib/strtol_l.c
new file mode 100644
index 0000000000..156083c748
--- /dev/null
+++ b/stdlib/strtol_l.c
@@ -0,0 +1,557 @@
+/* Convert string representing a number to integer value, using given locale.
+   Copyright (C) 1997, 2002, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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.  */
+
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifdef _LIBC
+# define USE_NUMBER_GROUPING
+# define STDC_HEADERS
+# define HAVE_LIMITS_H
+#endif
+
+#include <ctype.h>
+#include <errno.h>
+#ifndef __set_errno
+# define __set_errno(Val) errno = (Val)
+#endif
+
+#ifdef HAVE_LIMITS_H
+# include <limits.h>
+#endif
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <locale.h>
+#include <xlocale.h>
+#include <bits/wordsize.h>
+
+#ifdef USE_NUMBER_GROUPING
+# include "../locale/localeinfo.h"
+#endif
+
+/* Nonzero if we are defining `strtoul' or `strtoull', operating on
+   unsigned integers.  */
+#ifndef UNSIGNED
+# define UNSIGNED 0
+# define INT LONG int
+#else
+# define INT unsigned LONG int
+#endif
+
+/* Determine the name.  */
+#if UNSIGNED
+# ifdef USE_WIDE_CHAR
+#  ifdef QUAD
+#   define strtol_l wcstoull_l
+#  else
+#   define strtol_l wcstoul_l
+#  endif
+# else
+#  ifdef QUAD
+#   define strtol_l strtoull_l
+#  else
+#   define strtol_l strtoul_l
+#  endif
+# endif
+#else
+# ifdef USE_WIDE_CHAR
+#  ifdef QUAD
+#   define strtol_l wcstoll_l
+#  else
+#   define strtol_l wcstol_l
+#  endif
+# else
+#  ifdef QUAD
+#   define strtol_l strtoll_l
+#  else
+#   define strtol_l strtol_l
+#  endif
+# endif
+#endif
+
+#define __strtol_l __strtol_l2(strtol_l)
+#define __strtol_l2(name) __strtol_l3(name)
+#define __strtol_l3(name) __##name
+
+
+/* If QUAD is defined, we are defining `strtoll' or `strtoull',
+   operating on `long long int's.  */
+#ifdef QUAD
+# define LONG long long
+# define STRTOL_LONG_MIN LONG_LONG_MIN
+# define STRTOL_LONG_MAX LONG_LONG_MAX
+# define STRTOL_ULONG_MAX ULONG_LONG_MAX
+#else
+# define LONG long
+
+# ifndef ULONG_MAX
+#  define ULONG_MAX ((unsigned long int) ~(unsigned long int) 0)
+# endif
+# ifndef LONG_MAX
+#  define LONG_MAX ((long int) (ULONG_MAX >> 1))
+# endif
+# define STRTOL_LONG_MIN LONG_MIN
+# define STRTOL_LONG_MAX LONG_MAX
+# define STRTOL_ULONG_MAX ULONG_MAX
+#endif
+
+
+/* We use this code for the extended locale handling where the
+   function gets as an additional argument the locale which has to be
+   used.  To access the values we have to redefine the _NL_CURRENT and
+   _NL_CURRENT_WORD macros.  */
+#undef _NL_CURRENT
+#define _NL_CURRENT(category, item) \
+  (current->values[_NL_ITEM_INDEX (item)].string)
+#undef _NL_CURRENT_WORD
+#define _NL_CURRENT_WORD(category, item) \
+  ((uint32_t) current->values[_NL_ITEM_INDEX (item)].word)
+
+#if defined _LIBC || defined HAVE_WCHAR_H
+# include <wchar.h>
+#endif
+
+#ifdef USE_WIDE_CHAR
+# include <wctype.h>
+# define L_(Ch) L##Ch
+# define UCHAR_TYPE wint_t
+# define STRING_TYPE wchar_t
+# define ISSPACE(Ch) __iswspace_l ((Ch), loc)
+# define ISALPHA(Ch) __iswalpha_l ((Ch), loc)
+# define TOUPPER(Ch) __towupper_l ((Ch), loc)
+#else
+# if defined _LIBC \
+   || defined STDC_HEADERS || (!defined isascii && !defined HAVE_ISASCII)
+#  define IN_CTYPE_DOMAIN(c) 1
+# else
+#  define IN_CTYPE_DOMAIN(c) isascii(c)
+# endif
+# define L_(Ch) Ch
+# define UCHAR_TYPE unsigned char
+# define STRING_TYPE char
+# define ISSPACE(Ch) __isspace_l ((Ch), loc)
+# define ISALPHA(Ch) __isalpha_l ((Ch), loc)
+# define TOUPPER(Ch) __toupper_l ((Ch), loc)
+#endif
+
+#define INTERNAL(X) INTERNAL1(X)
+#define INTERNAL1(X) __##X##_internal
+#define WEAKNAME(X) WEAKNAME1(X)
+
+#ifdef USE_NUMBER_GROUPING
+/* This file defines a function to check for correct grouping.  */
+# include "grouping.h"
+#endif
+
+
+/* Define tables of maximum values and remainders in order to detect
+   overflow.  Do this at compile-time in order to avoid the runtime
+   overhead of the division.  */
+
+#define DEF(TYPE, NAME)							   \
+  const TYPE NAME[] attribute_hidden					   \
+	__attribute__((section(".gnu.linkonce.r." #NAME))) =		   \
+  {									   \
+    F(2), F(3), F(4), F(5), F(6), F(7), F(8), F(9), F(10), 		   \
+    F(11), F(12), F(13), F(14), F(15), F(16), F(17), F(18), F(19), F(20),  \
+    F(21), F(22), F(23), F(24), F(25), F(26), F(27), F(28), F(29), F(30),  \
+    F(31), F(32), F(33), F(34), F(35), F(36)				   \
+  }
+
+#define F(X)	ULONG_MAX / X
+  DEF (unsigned long, __strtol_ul_max_tab);
+#undef F
+#if defined(QUAD) && __WORDSIZE == 32
+# define F(X)	ULONG_LONG_MAX / X
+  DEF (unsigned long long, __strtol_ull_max_tab);
+# undef F
+# define F(X)	ULONG_LONG_MAX % X
+  DEF (unsigned char, __strtol_ull_rem_tab);
+# undef F
+#else
+# define F(X)	ULONG_MAX % X
+  DEF (unsigned char, __strtol_ul_rem_tab);
+# undef F
+#endif
+#undef DEF
+
+/* Define some more readable aliases for these arrays which correspond
+   to how they'll be used in the function below.  */
+#define jmax_tab	__strtol_ul_max_tab
+#if defined(QUAD) && __WORDSIZE == 32
+# define cutoff_tab	__strtol_ull_max_tab
+# define cutlim_tab	__strtol_ull_rem_tab
+#else
+# define cutoff_tab	__strtol_ul_max_tab
+# define cutlim_tab	__strtol_ul_rem_tab
+#endif
+
+
+/* Convert NPTR to an `unsigned long int' or `long int' in base BASE.
+   If BASE is 0 the base is determined by the presence of a leading
+   zero, indicating octal or a leading "0x" or "0X", indicating hexadecimal.
+   If BASE is < 2 or > 36, it is reset to 10.
+   If ENDPTR is not NULL, a pointer to the character after the last
+   one converted is stored in *ENDPTR.  */
+
+INT
+INTERNAL (__strtol_l) (nptr, endptr, base, group, loc)
+     const STRING_TYPE *nptr;
+     STRING_TYPE **endptr;
+     int base;
+     int group;
+     __locale_t loc;
+{
+  int negative;
+  register unsigned LONG int cutoff;
+  register unsigned int cutlim;
+  register unsigned LONG int i;
+  register const STRING_TYPE *s;
+  register UCHAR_TYPE c;
+  const STRING_TYPE *save, *end;
+  int overflow;
+#ifndef USE_WIDE_CHAR
+  size_t cnt;
+#endif
+
+#ifdef USE_NUMBER_GROUPING
+  struct locale_data *current = loc->__locales[LC_NUMERIC];
+  /* The thousands character of the current locale.  */
+# ifdef USE_WIDE_CHAR
+  wchar_t thousands = L'\0';
+# else
+  const char *thousands = NULL;
+  size_t thousands_len = 0;
+# endif
+  /* The numeric grouping specification of the current locale,
+     in the format described in <locale.h>.  */
+  const char *grouping;
+
+  if (__builtin_expect (group, 0))
+    {
+      grouping = _NL_CURRENT (LC_NUMERIC, GROUPING);
+      if (*grouping <= 0 || *grouping == CHAR_MAX)
+	grouping = NULL;
+      else
+	{
+	  /* Figure out the thousands separator character.  */
+# ifdef USE_WIDE_CHAR
+#  ifdef _LIBC
+	  thousands = _NL_CURRENT_WORD (LC_NUMERIC,
+					_NL_NUMERIC_THOUSANDS_SEP_WC);
+#  endif
+	  if (thousands == L'\0')
+	    grouping = NULL;
+# else
+#  ifdef _LIBC
+	  thousands = _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP);
+#  endif
+	  if (*thousands == '\0')
+	    {
+	      thousands = NULL;
+	      grouping = NULL;
+	    }
+# endif
+	}
+    }
+  else
+    grouping = NULL;
+#endif
+
+  if (base < 0 || base == 1 || base > 36)
+    {
+      __set_errno (EINVAL);
+      return 0;
+    }
+
+  save = s = nptr;
+
+  /* Skip white space.  */
+  while (ISSPACE (*s))
+    ++s;
+  if (__builtin_expect (*s == L_('\0'), 0))
+    goto noconv;
+
+  /* Check for a sign.  */
+  negative = 0;
+  if (*s == L_('-'))
+    {
+      negative = 1;
+      ++s;
+    }
+  else if (*s == L_('+'))
+    ++s;
+
+  /* Recognize number prefix and if BASE is zero, figure it out ourselves.  */
+  if (*s == L_('0'))
+    {
+      if ((base == 0 || base == 16) && TOUPPER (s[1]) == L_('X'))
+	{
+	  s += 2;
+	  base = 16;
+	}
+      else if (base == 0)
+	base = 8;
+    }
+  else if (base == 0)
+    base = 10;
+
+  /* Save the pointer so we can check later if anything happened.  */
+  save = s;
+
+#ifdef USE_NUMBER_GROUPING
+  if (base != 10)
+    grouping = NULL;
+
+  if (__builtin_expect (grouping != NULL, 0))
+    {
+# ifndef USE_WIDE_CHAR
+      thousands_len = strlen (thousands);
+# endif
+
+      /* Find the end of the digit string and check its grouping.  */
+      end = s;
+      if (
+# ifdef USE_WIDE_CHAR
+	  *s != thousands
+# else
+	  ({ for (cnt = 0; cnt < thousands_len; ++cnt)
+	       if (thousands[cnt] != end[cnt])
+		 break;
+	     cnt < thousands_len; })
+# endif
+	  )
+	{
+	  for (c = *end; c != L_('\0'); c = *++end)
+	    if (((STRING_TYPE) c < L_('0') || (STRING_TYPE) c > L_('9'))
+# ifdef USE_WIDE_CHAR
+		&& (wchar_t) c != thousands
+# else
+		&& ({ for (cnt = 0; cnt < thousands_len; ++cnt)
+		      if (thousands[cnt] != end[cnt])
+			break;
+		      cnt < thousands_len; })
+# endif
+		&& (!ISALPHA (c)
+		    || (int) (TOUPPER (c) - L_('A') + 10) >= base))
+	      break;
+
+# ifdef USE_WIDE_CHAR
+	  end = __correctly_grouped_prefixwc (s, end, thousands, grouping);
+# else
+	  end = __correctly_grouped_prefixmb (s, end, thousands, grouping);
+# endif
+	}
+    }
+  else
+#endif
+    end = NULL;
+
+  /* Avoid runtime division; lookup cutoff and limit.  */
+  cutoff = cutoff_tab[base - 2];
+  cutlim = cutlim_tab[base - 2];
+
+  overflow = 0;
+  i = 0;
+  c = *s;
+  if (sizeof (long int) != sizeof (LONG int))
+    {
+      unsigned long int j = 0;
+      unsigned long int jmax = jmax_tab[base - 2];
+
+      for (;c != L_('\0'); c = *++s)
+	{
+	  if (s == end)
+	    break;
+	  if (c >= L_('0') && c <= L_('9'))
+	    c -= L_('0');
+#ifdef USE_NUMBER_GROUPING
+# ifdef USE_WIDE_CHAR
+	  else if (grouping && (wchar_t) c == thousands)
+	    continue;
+# else
+	  else if (thousands_len)
+	    {
+	      for (cnt = 0; cnt < thousands_len; ++cnt)
+		if (thousands[cnt] != s[cnt])
+		  break;
+	      if (cnt == thousands_len)
+		{
+		  s += thousands_len - 1;
+		  continue;
+		}
+	      if (ISALPHA (c))
+		c = TOUPPER (c) - L_('A') + 10;
+	      else
+		break;
+	    }
+# endif
+#endif
+	  else if (ISALPHA (c))
+	    c = TOUPPER (c) - L_('A') + 10;
+	  else
+	    break;
+	  if ((int) c >= base)
+	    break;
+	  /* Note that we never can have an overflow.  */
+	  else if (j >= jmax)
+	    {
+	      /* We have an overflow.  Now use the long representation.  */
+	      i = (unsigned LONG int) j;
+	      goto use_long;
+	    }
+	  else
+	    j = j * (unsigned long int) base + c;
+	}
+
+      i = (unsigned LONG int) j;
+    }
+  else
+    for (;c != L_('\0'); c = *++s)
+      {
+	if (s == end)
+	  break;
+	if (c >= L_('0') && c <= L_('9'))
+	  c -= L_('0');
+#ifdef USE_NUMBER_GROUPING
+# ifdef USE_WIDE_CHAR
+	else if (grouping && (wchar_t) c == thousands)
+	  continue;
+# else
+	else if (thousands_len)
+	  {
+	    for (cnt = 0; cnt < thousands_len; ++cnt)
+	      if (thousands[cnt] != s[cnt])
+		break;
+	    if (cnt == thousands_len)
+	      {
+		s += thousands_len - 1;
+		continue;
+	      }
+	    if (ISALPHA (c))
+	      c = TOUPPER (c) - L_('A') + 10;
+	    else
+	      break;
+	  }
+# endif
+#endif
+	else if (ISALPHA (c))
+	  c = TOUPPER (c) - L_('A') + 10;
+	else
+	  break;
+	if ((int) c >= base)
+	  break;
+	/* Check for overflow.  */
+	if (i > cutoff || (i == cutoff && c > cutlim))
+	  overflow = 1;
+	else
+	  {
+	  use_long:
+	    i *= (unsigned LONG int) base;
+	    i += c;
+	  }
+      }
+
+  /* Check if anything actually happened.  */
+  if (s == save)
+    goto noconv;
+
+  /* Store in ENDPTR the address of one character
+     past the last character we converted.  */
+  if (endptr != NULL)
+    *endptr = (STRING_TYPE *) s;
+
+#if !UNSIGNED
+  /* Check for a value that is within the range of
+     `unsigned LONG int', but outside the range of `LONG int'.  */
+  if (overflow == 0
+      && i > (negative
+	      ? -((unsigned LONG int) (STRTOL_LONG_MIN + 1)) + 1
+	      : (unsigned LONG int) STRTOL_LONG_MAX))
+    overflow = 1;
+#endif
+
+  if (__builtin_expect (overflow, 0))
+    {
+      __set_errno (ERANGE);
+#if UNSIGNED
+      return STRTOL_ULONG_MAX;
+#else
+      return negative ? STRTOL_LONG_MIN : STRTOL_LONG_MAX;
+#endif
+    }
+
+  /* Return the result of the appropriate sign.  */
+  return negative ? -i : i;
+
+noconv:
+  /* We must handle a special case here: the base is 0 or 16 and the
+     first two characters are '0' and 'x', but the rest are no
+     hexadecimal digits.  This is no error case.  We return 0 and
+     ENDPTR points to the `x`.  */
+  if (endptr != NULL)
+    {
+      if (save - nptr >= 2 && TOUPPER (save[-1]) == L_('X')
+	  && save[-2] == L_('0'))
+	*endptr = (STRING_TYPE *) &save[-1];
+      else
+	/*  There was no number to convert.  */
+	*endptr = (STRING_TYPE *) nptr;
+    }
+
+  return 0L;
+}
+#if defined _LIBC && !defined USE_WIDE_CHAR
+libc_hidden_def (INTERNAL (__strtol_l))
+#endif
+
+/* External user entry point.  */
+
+#if _LIBC - 0 == 0
+# undef PARAMS
+# if defined (__STDC__) && __STDC__
+#  define PARAMS(Args) Args
+# else
+#  define PARAMS(Args) ()
+# endif
+
+/* Prototype.  */
+extern INT __strtol_l PARAMS ((const STRING_TYPE *nptr, STRING_TYPE **endptr,
+			       int base));
+#endif
+
+
+INT
+#ifdef weak_function
+weak_function
+#endif
+__strtol_l (nptr, endptr, base, loc)
+     const STRING_TYPE *nptr;
+     STRING_TYPE **endptr;
+     int base;
+     __locale_t loc;
+{
+  return INTERNAL (__strtol_l) (nptr, endptr, base, 0, loc);
+}
+weak_alias (__strtol_l, strtol_l)
diff --git a/stdlib/strtold_l.c b/stdlib/strtold_l.c
new file mode 100644
index 0000000000..690a8a92eb
--- /dev/null
+++ b/stdlib/strtold_l.c
@@ -0,0 +1,58 @@
+/* Copyright (C) 1999, 2002, 2004 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 <math.h>
+#include <stdlib.h>
+#include <xlocale.h>
+
+#ifdef USE_WIDE_CHAR
+# define STRING_TYPE	wchar_t
+# define STRTOLD	wcstold_l
+# define __STRTOLD	__wcstold_l
+# define __STRTOD	__wcstod_l
+#else
+# define STRING_TYPE	char
+# define STRTOLD	strtold_l
+# define __STRTOLD	__strtold_l
+# define __STRTOD	__strtod_l
+#endif
+
+#define INTERNAL(x) INTERNAL1(x)
+#define INTERNAL1(x) __##x##_internal
+
+extern double INTERNAL (__STRTOD) (const STRING_TYPE *, STRING_TYPE **,
+				   int, __locale_t);
+
+/* There is no `long double' type, use the `double' implementations.  */
+long double
+INTERNAL (__STRTOLD) (const STRING_TYPE *nptr, STRING_TYPE **endptr,
+		      int group, __locale_t loc)
+{
+  return INTERNAL (__STRTOD) (nptr, endptr, group, loc);
+}
+#ifndef USE_WIDE_CHAR
+libc_hidden_def (INTERNAL (__STRTOLD))
+#endif
+
+long double
+weak_function
+__STRTOLD (const STRING_TYPE *nptr, STRING_TYPE **endptr, __locale_t loc)
+{
+  return INTERNAL (__STRTOD) (nptr, endptr, 0, loc);
+}
+weak_alias (__STRTOLD, STRTOLD)
diff --git a/stdlib/strtoll.c b/stdlib/strtoll.c
new file mode 100644
index 0000000000..60128df781
--- /dev/null
+++ b/stdlib/strtoll.c
@@ -0,0 +1,34 @@
+/* Function to parse a `long long int' from text.
+   Copyright (C) 1995, 1996, 1997, 1999, 2001 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU 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.  */
+
+#define	QUAD	1
+
+#include <strtol.c>
+
+#ifdef _LIBC
+# ifdef SHARED
+#  include <shlib-compat.h>
+
+#  if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_2)
+compat_symbol (libc, __strtoll_internal, __strtoq_internal, GLIBC_2_0);
+#  endif
+
+# endif
+weak_alias (strtoll, strtoq)
+#endif
diff --git a/stdlib/strtoll_l.c b/stdlib/strtoll_l.c
new file mode 100644
index 0000000000..7725035bd1
--- /dev/null
+++ b/stdlib/strtoll_l.c
@@ -0,0 +1,28 @@
+/* Convert string representing a number to integer value, using given locale.
+   Copyright (C) 1997, 2002, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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.  */
+
+#define QUAD	1
+
+#include <xlocale.h>
+
+extern long long int ____strtoll_l_internal (const char *, char **, int, int,
+					     __locale_t);
+
+#include <strtol_l.c>
diff --git a/stdlib/strtoul.c b/stdlib/strtoul.c
new file mode 100644
index 0000000000..0862950231
--- /dev/null
+++ b/stdlib/strtoul.c
@@ -0,0 +1,21 @@
+/* Copyright (C) 1991, 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.  */
+
+#define	UNSIGNED	1
+
+#include "strtol.c"
diff --git a/stdlib/strtoul_l.c b/stdlib/strtoul_l.c
new file mode 100644
index 0000000000..a8b980f48d
--- /dev/null
+++ b/stdlib/strtoul_l.c
@@ -0,0 +1,28 @@
+/* Convert string representing a number to integer value, using given locale.
+   Copyright (C) 1997, 2002, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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.  */
+
+#define UNSIGNED	1
+
+#include <xlocale.h>
+
+extern unsigned long int ____strtoul_l_internal (const char *, char **, int,
+						 int, __locale_t);
+
+#include "strtol_l.c"
diff --git a/stdlib/strtoull.c b/stdlib/strtoull.c
new file mode 100644
index 0000000000..accf5874a0
--- /dev/null
+++ b/stdlib/strtoull.c
@@ -0,0 +1,34 @@
+/* Function to parse an `unsigned long long int' from text.
+   Copyright (C) 1995, 1996, 1997, 1999, 2001 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU 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.  */
+
+#define	QUAD	1
+
+#include <strtoul.c>
+
+#ifdef _LIBC
+# ifdef SHARED
+#  include <shlib-compat.h>
+
+#  if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_2)
+compat_symbol (libc, __strtoull_internal, __strtouq_internal, GLIBC_2_0);
+#  endif
+
+# endif
+weak_alias (strtoull, strtouq)
+#endif
diff --git a/stdlib/strtoull_l.c b/stdlib/strtoull_l.c
new file mode 100644
index 0000000000..68ad0d826e
--- /dev/null
+++ b/stdlib/strtoull_l.c
@@ -0,0 +1,29 @@
+/* Convert string representing a number to integer value, using given locale.
+   Copyright (C) 1997, 2002, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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.  */
+
+#define QUAD		1
+#define UNSIGNED	1
+
+#include <xlocale.h>
+
+extern unsigned long long int ____strtoull_l_internal (const char *, char **,
+						       int, int, __locale_t);
+
+#include <strtol_l.c>
diff --git a/stdlib/strtoumax.c b/stdlib/strtoumax.c
new file mode 100644
index 0000000000..508cb19f8c
--- /dev/null
+++ b/stdlib/strtoumax.c
@@ -0,0 +1 @@
+#error "The correct implementation must be chosen based on the `uintmax_t' type"
diff --git a/stdlib/sub_n.c b/stdlib/sub_n.c
new file mode 100644
index 0000000000..987ad91eb1
--- /dev/null
+++ b/stdlib/sub_n.c
@@ -0,0 +1,62 @@
+/* mpn_sub_n -- Subtract 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 <gmp.h>
+#include "gmp-impl.h"
+
+mp_limb_t
+#if __STDC__
+mpn_sub_n (mp_ptr res_ptr, mp_srcptr s1_ptr, mp_srcptr s2_ptr, mp_size_t size)
+#else
+mpn_sub_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 subtrahend */
+      cy = (y < cy);		/* get out carry from that addition */
+      y = x - y;		/* main subtract */
+      cy = (y > x) + cy;	/* get out carry from the subtract, combine */
+      res_ptr[j] = y;
+    }
+  while (++j != 0);
+
+  return cy;
+}
diff --git a/stdlib/submul_1.c b/stdlib/submul_1.c
new file mode 100644
index 0000000000..3e7163a2a3
--- /dev/null
+++ b/stdlib/submul_1.c
@@ -0,0 +1,65 @@
+/* mpn_submul_1 -- multiply the S1_SIZE long limb vector pointed to by S1_PTR
+   by S2_LIMB, subtract the S1_SIZE least significant limbs of the product
+   from the limb vector pointed to by RES_PTR.  Return the most significant
+   limb of the product, adjusted for carry-out from the subtraction.
+
+Copyright (C) 1992, 1993, 1994, 1996, 2005 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 <gmp.h>
+#include "gmp-impl.h"
+#include "longlong.h"
+
+mp_limb_t
+mpn_submul_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/swapcontext.c b/stdlib/swapcontext.c
new file mode 100644
index 0000000000..56b73f0d6c
--- /dev/null
+++ b/stdlib/swapcontext.c
@@ -0,0 +1,33 @@
+/* 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 <errno.h>
+#include <ucontext.h>
+
+int
+swapcontext (oucp, ucp)
+     ucontext_t *oucp;
+     const ucontext_t *ucp;
+{
+  __set_errno (ENOSYS);
+  return -1;
+}
+
+
+stub_warning (swapcontext)
+#include <stub-tag.h>
diff --git a/stdlib/system.c b/stdlib/system.c
new file mode 100644
index 0000000000..cd12128cd8
--- /dev/null
+++ b/stdlib/system.c
@@ -0,0 +1,38 @@
+/* Copyright (C) 1991, 1993, 1995, 1996, 1997, 2003 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 <errno.h>
+#include <stdlib.h>
+
+
+/* Execute LINE as a shell command.  */
+int
+__libc_system (line)
+     const char *line;
+{
+  if (line == NULL)
+    return 0;			/* This indicates no command processor.  */
+
+  __set_errno (ENOSYS);
+  return -1;
+}
+weak_alias (__libc_system, system)
+
+
+stub_warning (system)
+#include <stub-tag.h>
diff --git a/stdlib/udiv_qrnnd.c b/stdlib/udiv_qrnnd.c
new file mode 100644
index 0000000000..d32796c04d
--- /dev/null
+++ b/stdlib/udiv_qrnnd.c
@@ -0,0 +1,10 @@
+/* For some machines GNU MP needs to define an auxiliary function:
+
+   udiv_qrnnd (quotient, remainder, high_numerator, low_numerator, denominator)
+
+   Divides a two-word unsigned integer, composed by the integers
+   HIGH_NUMERATOR and LOW_NUMERATOR, by DENOMINATOR and places the quotient
+   in QUOTIENT and the remainder in REMAINDER.  HIGH_NUMERATOR must be less
+   than DENOMINATOR for correct operation.  If, in addition, the most
+   significant bit of DENOMINATOR must be 1, then the pre-processor symbol
+   UDIV_NEEDS_NORMALIZATION is defined to 1.  */
diff --git a/stdlib/wcstoimax.c b/stdlib/wcstoimax.c
new file mode 100644
index 0000000000..f1de70f320
--- /dev/null
+++ b/stdlib/wcstoimax.c
@@ -0,0 +1 @@
+#error "The correct implementation must be chosen based on the `intmax_t' type"
diff --git a/stdlib/wcstoumax.c b/stdlib/wcstoumax.c
new file mode 100644
index 0000000000..508cb19f8c
--- /dev/null
+++ b/stdlib/wcstoumax.c
@@ -0,0 +1 @@
+#error "The correct implementation must be chosen based on the `uintmax_t' type"