aboutsummaryrefslogtreecommitdiff
path: root/stdlib
diff options
context:
space:
mode:
Diffstat (limited to 'stdlib')
-rw-r--r--stdlib/Makefile43
-rw-r--r--stdlib/abs.c30
-rw-r--r--stdlib/alloca.h44
-rw-r--r--stdlib/atexit.c65
-rw-r--r--stdlib/atof.c30
-rw-r--r--stdlib/atoi.c30
-rw-r--r--stdlib/atol.c30
-rw-r--r--stdlib/bsearch.c51
-rw-r--r--stdlib/div.c92
-rw-r--r--stdlib/exit.c70
-rw-r--r--stdlib/exit.h44
-rw-r--r--stdlib/labs.c31
-rw-r--r--stdlib/ldiv.c92
-rw-r--r--stdlib/mblen.c31
-rw-r--r--stdlib/mbstowcs.c78
-rw-r--r--stdlib/mbtowc.c84
-rw-r--r--stdlib/msort.c103
-rw-r--r--stdlib/on_exit.c37
-rw-r--r--stdlib/qsort.c243
-rw-r--r--stdlib/rand.c30
-rw-r--r--stdlib/random.c357
-rw-r--r--stdlib/stdlib.h289
-rw-r--r--stdlib/strtod.c1027
-rw-r--r--stdlib/strtof.c12
-rw-r--r--stdlib/strtol.c189
-rw-r--r--stdlib/strtold.c12
-rw-r--r--stdlib/strtoq.c22
-rw-r--r--stdlib/strtoul.c21
-rw-r--r--stdlib/strtouq.c22
-rw-r--r--stdlib/testdiv.c33
-rw-r--r--stdlib/testdiv.input2
-rw-r--r--stdlib/testmb.c69
-rw-r--r--stdlib/testrand.c51
-rw-r--r--stdlib/testsort.c38
-rw-r--r--stdlib/tst-strtod.c94
-rw-r--r--stdlib/tst-strtol.c127
-rw-r--r--stdlib/wcstombs.c77
-rw-r--r--stdlib/wctomb.c72
38 files changed, 3772 insertions, 0 deletions
diff --git a/stdlib/Makefile b/stdlib/Makefile
new file mode 100644
index 0000000..1a1498c
--- /dev/null
+++ b/stdlib/Makefile
@@ -0,0 +1,43 @@
+# Copyright (C) 1991, 1992, 1993, 1994, 1995 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 Library General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+
+# The GNU C Library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Library General Public License for more details.
+
+# You should have received a copy of the GNU Library General Public
+# License along with the GNU C Library; see the file COPYING.LIB. If
+# not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+# Cambridge, MA 02139, USA.
+
+#
+# Makefile for stdlib routines
+#
+subdir := stdlib
+
+headers := stdlib.h alloca.h
+
+routines := \
+ atof atoi atol \
+ abort \
+ bsearch qsort msort \
+ getenv putenv setenv \
+ exit on_exit atexit \
+ abs labs \
+ div ldiv \
+ mblen mbstowcs mbtowc wcstombs wctomb \
+ random rand \
+ strtol strtoul strtoq strtouq \
+ strtof strtod strtold \
+ system
+
+distribute := exit.h
+tests := tst-strtol tst-strtod testmb testrand testsort testdiv
+
+include ../Rules
diff --git a/stdlib/abs.c b/stdlib/abs.c
new file mode 100644
index 0000000..b8db100
--- /dev/null
+++ b/stdlib/abs.c
@@ -0,0 +1,30 @@
+/* Copyright (C) 1991 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 Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <stdlib.h>
+
+#undef abs
+
+/* Return the absolute value of I. */
+__CONSTVALUE
+int
+DEFUN(abs, (i), int i)
+{
+ return(i < 0 ? -i : i);
+}
diff --git a/stdlib/alloca.h b/stdlib/alloca.h
new file mode 100644
index 0000000..4e9de46
--- /dev/null
+++ b/stdlib/alloca.h
@@ -0,0 +1,44 @@
+/* Copyright (C) 1992 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 Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the, 1992 Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#ifndef _ALLOCA_H
+#define _ALLOCA_H 1
+#include <features.h>
+
+#define __need_size_t
+#include <stddef.h>
+
+__BEGIN_DECLS
+
+/* Remove any previous definitions. */
+#undef __alloca
+#undef alloca
+
+/* Allocate a block that will be freed when the calling function exits. */
+extern __ptr_t __alloca __P ((size_t __size));
+extern __ptr_t alloca __P ((size_t __size));
+
+#ifdef __GNUC__
+#define __alloca(size) __builtin_alloca(size)
+#endif /* GCC. */
+
+#define alloca(size) __alloca(size)
+
+__END_DECLS
+
+#endif /* alloca.h */
diff --git a/stdlib/atexit.c b/stdlib/atexit.c
new file mode 100644
index 0000000..a2ab453
--- /dev/null
+++ b/stdlib/atexit.c
@@ -0,0 +1,65 @@
+/* Copyright (C) 1991 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 Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <stdlib.h>
+#include "exit.h"
+
+
+/* Register FUNC to be executed by `exit'. */
+int
+DEFUN(atexit, (func), void EXFUN((*func), (NOARGS)))
+{
+ struct exit_function *new = __new_exitfn();
+
+ if (new == NULL)
+ return -1;
+
+ new->flavor = ef_at;
+ new->func.at = func;
+ return 0;
+}
+
+
+static struct exit_function_list fnlist = { NULL, 0, };
+struct exit_function_list *__exit_funcs = &fnlist;
+
+struct exit_function *
+DEFUN_VOID(__new_exitfn)
+{
+ register struct exit_function_list *l;
+
+ for (l = __exit_funcs; l != NULL; l = l->next)
+ {
+ register size_t i;
+ for (i = 0; i < l->idx; ++i)
+ if (l->fns[i].flavor == ef_free)
+ return &l->fns[i];
+ if (l->idx < sizeof(l->fns) / sizeof(l->fns[0]))
+ return &l->fns[l->idx++];
+ }
+
+ l = (struct exit_function_list *) malloc(sizeof(struct exit_function_list));
+ if (l == NULL)
+ return NULL;
+ l->next = __exit_funcs;
+ __exit_funcs = l;
+
+ l->idx = 1;
+ return &l->fns[0];
+}
diff --git a/stdlib/atof.c b/stdlib/atof.c
new file mode 100644
index 0000000..7958546
--- /dev/null
+++ b/stdlib/atof.c
@@ -0,0 +1,30 @@
+/* Copyright (C) 1991 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 Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <stdlib.h>
+
+#undef atof
+
+
+/* Convert a string to a double. */
+double
+DEFUN(atof, (nptr), CONST char *nptr)
+{
+ return(strtod(nptr, (char **) NULL));
+}
diff --git a/stdlib/atoi.c b/stdlib/atoi.c
new file mode 100644
index 0000000..9fe280c
--- /dev/null
+++ b/stdlib/atoi.c
@@ -0,0 +1,30 @@
+/* Copyright (C) 1991 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 Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <stdlib.h>
+
+#undef atoi
+
+
+/* Convert a string to an int. */
+int
+DEFUN(atoi, (nptr), CONST char *nptr)
+{
+ return((int) strtol(nptr, (char **) NULL, 10));
+}
diff --git a/stdlib/atol.c b/stdlib/atol.c
new file mode 100644
index 0000000..75f599c
--- /dev/null
+++ b/stdlib/atol.c
@@ -0,0 +1,30 @@
+/* Copyright (C) 1991 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 Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <stdlib.h>
+
+#undef atol
+
+
+/* Convert a string to a long int. */
+long int
+DEFUN(atol, (nptr), CONST char *nptr)
+{
+ return(strtol(nptr, (char **) NULL, 10));
+}
diff --git a/stdlib/bsearch.c b/stdlib/bsearch.c
new file mode 100644
index 0000000..d798eab
--- /dev/null
+++ b/stdlib/bsearch.c
@@ -0,0 +1,51 @@
+/* Copyright (C) 1991, 1992 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 Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <stdlib.h>
+
+
+/* Perform a binary search for KEY in BASE which has NMEMB elements
+ of SIZE bytes each. The comparisons are done by (*COMPAR)(). */
+PTR
+DEFUN(bsearch, (key, base, nmemb, size, compar),
+ register CONST PTR key AND register CONST PTR base AND
+ size_t nmemb AND register size_t size AND
+ register int EXFUN((*compar), (CONST PTR, CONST PTR)))
+{
+ register size_t l, u, idx;
+ register CONST PTR p;
+ register int comparison;
+
+ l = 0;
+ u = nmemb;
+ while (l < u)
+ {
+ idx = (l + u) / 2;
+ p = (PTR) (((CONST char *) base) + (idx * size));
+ comparison = (*compar)(key, p);
+ if (comparison < 0)
+ u = idx;
+ else if (comparison > 0)
+ l = idx + 1;
+ else
+ return (PTR) p;
+ }
+
+ return NULL;
+}
diff --git a/stdlib/div.c b/stdlib/div.c
new file mode 100644
index 0000000..5a0ee7d
--- /dev/null
+++ b/stdlib/div.c
@@ -0,0 +1,92 @@
+/* Copyright (C) 1992 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 Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 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 <ansidecl.h>
+#include <stdlib.h>
+
+
+/* Return the `div_t' representation of NUMER over DENOM. */
+__CONSTVALUE
+div_t
+DEFUN(div, (numer, denom), int numer AND int 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/exit.c b/stdlib/exit.c
new file mode 100644
index 0000000..4f33a25
--- /dev/null
+++ b/stdlib/exit.c
@@ -0,0 +1,70 @@
+/* Copyright (C) 1991, 1995 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 Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "exit.h"
+
+#ifdef HAVE_GNU_LD
+#include "set-hooks.h"
+DEFINE_HOOK (__libc_atexit, (void))
+#endif
+
+
+/* Call all functions registered with `atexit' and `on_exit',
+ in the reverse of the order in which they were registered
+ perform stdio cleanup, and terminate program execution with STATUS. */
+void
+DEFUN(exit, (status), int status)
+{
+ register CONST struct exit_function_list *l;
+
+ for (l = __exit_funcs; l != NULL; l = l->next)
+ {
+ register size_t i = l->idx;
+ while (i-- > 0)
+ {
+ CONST struct exit_function *CONST f = &l->fns[i];
+ switch (f->flavor)
+ {
+ case ef_free:
+ break;
+ case ef_on:
+ (*f->func.on.fn)(status, f->func.on.arg);
+ break;
+ case ef_at:
+ (*f->func.at)();
+ break;
+ }
+ }
+ }
+
+#ifdef HAVE_GNU_LD
+ RUN_HOOK (__libc_atexit, ());
+#else
+ {
+ extern void EXFUN(_cleanup, (NOARGS));
+ _cleanup();
+ }
+#endif
+
+ _exit(status);
+}
+
diff --git a/stdlib/exit.h b/stdlib/exit.h
new file mode 100644
index 0000000..2142178
--- /dev/null
+++ b/stdlib/exit.h
@@ -0,0 +1,44 @@
+/* Copyright (C) 1991 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 Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#ifndef _EXIT_H
+
+struct exit_function
+ {
+ enum { ef_free, ef_on, ef_at } flavor; /* `ef_free' MUST be zero! */
+ union
+ {
+ void EXFUN((*at), (NOARGS));
+ struct
+ {
+ void EXFUN((*fn), (int status, PTR arg));
+ PTR arg;
+ } on;
+ } func;
+ };
+struct exit_function_list
+ {
+ struct exit_function_list *next;
+ size_t idx;
+ struct exit_function fns[32];
+ };
+extern struct exit_function_list *__exit_funcs;
+
+extern struct exit_function *EXFUN(__new_exitfn, (NOARGS));
+
+#endif /* exit.h */
diff --git a/stdlib/labs.c b/stdlib/labs.c
new file mode 100644
index 0000000..c54339f
--- /dev/null
+++ b/stdlib/labs.c
@@ -0,0 +1,31 @@
+/* Copyright (C) 1991 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 Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <stdlib.h>
+
+#undef labs
+
+
+/* Return the absolute value of I. */
+__CONSTVALUE
+long int
+DEFUN(labs, (i), long int i)
+{
+ return(i < 0 ? -i : i);
+}
diff --git a/stdlib/ldiv.c b/stdlib/ldiv.c
new file mode 100644
index 0000000..661f1bd
--- /dev/null
+++ b/stdlib/ldiv.c
@@ -0,0 +1,92 @@
+/* Copyright (C) 1992 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 Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 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 <ansidecl.h>
+#include <stdlib.h>
+
+
+/* Return the `ldiv_t' representation of NUMER over DENOM. */
+__CONSTVALUE
+ldiv_t
+DEFUN(ldiv, (numer, denom), long int numer AND 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/mblen.c b/stdlib/mblen.c
new file mode 100644
index 0000000..5393ce4
--- /dev/null
+++ b/stdlib/mblen.c
@@ -0,0 +1,31 @@
+/* Copyright (C) 1991 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 Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <stdlib.h>
+
+#undef mblen
+
+
+/* Return the length of the multibyte character (if there is one)
+ at S which is no longer than N characters. */
+int
+DEFUN(mblen, (s, n), CONST char *s AND size_t n)
+{
+ return(mbtowc((wchar_t *) NULL, s, n));
+}
diff --git a/stdlib/mbstowcs.c b/stdlib/mbstowcs.c
new file mode 100644
index 0000000..38c7102
--- /dev/null
+++ b/stdlib/mbstowcs.c
@@ -0,0 +1,78 @@
+/* Copyright (C) 1991, 1992 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 Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <ctype.h>
+#include <stddef.h>
+#include <stdlib.h>
+
+
+extern int _mb_shift; /* Defined in mbtowc.c. */
+
+/* Convert the string of multibyte characters in S to `wchar_t's in
+ PWCS, writing no more than N. Return the number written,
+ or (size_t) -1 if an invalid multibyte character is encountered. */
+size_t
+DEFUN(mbstowcs, (pwcs, s, n),
+ register wchar_t *pwcs AND register CONST char *s AND register size_t n)
+{
+ int save_shift;
+ register size_t written = 0;
+
+ /* Save the shift state. */
+ save_shift = _mb_shift;
+ /* Reset the shift state. */
+ _mb_shift = 0;
+
+ while (*s != '\0')
+ {
+ int len;
+ if (isascii (*s))
+ {
+ *pwcs = (wchar_t) *s;
+ len = 1;
+ }
+ else
+ len = mbtowc (pwcs, s, n);
+
+ if (len < 1)
+ {
+ /* Return an error. */
+ written = (size_t) -1;
+ break;
+ }
+ else
+ {
+ /* Multibyte character converted. */
+ ++pwcs;
+ ++written;
+ s += len;
+ n -= len;
+ }
+ }
+
+ /* Terminate the string if it has space. */
+ if (n > 0)
+ *pwcs = (wchar_t) 0;
+
+ /* Restore the old shift state. */
+ _mb_shift = save_shift;
+
+ /* Return how many we wrote (or maybe an error). */
+ return written;
+}
diff --git a/stdlib/mbtowc.c b/stdlib/mbtowc.c
new file mode 100644
index 0000000..6210340
--- /dev/null
+++ b/stdlib/mbtowc.c
@@ -0,0 +1,84 @@
+/* Copyright (C) 1991, 1992, 1995 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 Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <localeinfo.h>
+#include <ctype.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+long int _mb_shift = 0;
+
+/* Convert the multibyte character at S, which is no longer
+ than N characters, to its `wchar_t' representation, placing
+ this n *PWC and returning its length. */
+int
+DEFUN(mbtowc, (pwc, s, n), wchar_t *pwc AND CONST char *s AND size_t n)
+{
+ register CONST mb_char *mb;
+ register wchar_t i;
+
+ if (s == NULL)
+ return _mb_shift != 0;
+
+ if (*s == '\0')
+ /* ANSI 4.10.7.2, line 19. */
+ return 0;
+
+ if (isascii (*s))
+ {
+ /* A normal ASCII character translates to itself. */
+ if (pwc != NULL)
+ *pwc = (wchar_t) *s;
+ return 1;
+ }
+
+ if (_ctype_info->mbchar == NULL ||
+ _ctype_info->mbchar->mb_chars == NULL)
+ return -1;
+
+ if (n > MB_CUR_MAX)
+ n = MB_CUR_MAX;
+
+ for (i = 0; i < WCHAR_MAX; ++i)
+ {
+ mb = &_ctype_info->mbchar->mb_chars[i];
+ /* EOF and NUL aren't MB chars. */
+ if (i == (wchar_t) EOF || i == (wchar_t) '\0')
+ continue;
+ /* Normal ASCII values can't start MB chars. */
+ else if (isascii(i))
+ continue;
+ else if (mb->string == NULL || mb->len == 0)
+ continue;
+ else if (mb->len > n)
+ continue;
+ else if (!strncmp(mb->string, s, mb->len))
+ {
+ _mb_shift += mb->shift;
+ if (pwc != NULL)
+ *pwc = i;
+ return mb->len;
+ }
+ }
+
+ return -1;
+}
diff --git a/stdlib/msort.c b/stdlib/msort.c
new file mode 100644
index 0000000..92ba518
--- /dev/null
+++ b/stdlib/msort.c
@@ -0,0 +1,103 @@
+/* msort -- an alternative to qsort, with an identical interface.
+ Copyright (C) 1992 Free Software Foundation, Inc.
+ Written by Mike Haertel, September 1988.
+
+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 Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define MEMCPY(dst, src, s) \
+ ((s) == sizeof (int) \
+ ? (*(int *) (dst) = *(int *) (src), (dst)) \
+ : memcpy (dst, src, s))
+
+static void
+DEFUN(msort_with_tmp, (b, n, s, cmp, t),
+ PTR b AND size_t n AND size_t s AND __compar_fn_t cmp AND char *t)
+{
+ char *tmp;
+ char *b1, *b2;
+ size_t n1, n2;
+
+ if (n <= 1)
+ return;
+
+ n1 = n / 2;
+ n2 = n - n1;
+ b1 = b;
+ b2 = (char *) b + (n1 * s);
+
+ msort_with_tmp (b1, n1, s, cmp, t);
+ msort_with_tmp (b2, n2, s, cmp, t);
+
+ tmp = t;
+
+ while (n1 > 0 && n2 > 0)
+ {
+ if ((*cmp) (b1, b2) <= 0)
+ {
+ MEMCPY (tmp, b1, s);
+ b1 += s;
+ --n1;
+ }
+ else
+ {
+ MEMCPY (tmp, b2, s);
+ b2 += s;
+ --n2;
+ }
+ tmp += s;
+ }
+ if (n1 > 0)
+ memcpy (tmp, b1, n1 * s);
+ memcpy (b, t, (n - n2) * s);
+}
+
+void
+DEFUN(qsort, (b, n, s, cmp),
+ PTR b AND size_t n AND size_t s AND __compar_fn_t cmp)
+{
+ CONST size_t size = n * s;
+
+ if (size < 1024)
+ /* The temporary array is small, so put it on the stack. */
+ msort_with_tmp (b, n, s, cmp, __alloca (size));
+ else
+ {
+ /* It's somewhat large, so malloc it. */
+ int save = errno;
+ char *tmp = malloc (size);
+ if (tmp == NULL)
+ {
+ /* Couldn't get space, so use the slower algorithm
+ that doesn't need a temporary array. */
+ extern void EXFUN(_quicksort, (PTR __base,
+ size_t __nmemb, size_t __size,
+ __compar_fn_t __compar));
+ _quicksort (b, n, s, cmp);
+ }
+ else
+ {
+ msort_with_tmp (b, n, s, cmp, tmp);
+ free (tmp);
+ }
+ errno = save;
+ }
+}
diff --git a/stdlib/on_exit.c b/stdlib/on_exit.c
new file mode 100644
index 0000000..bd100be
--- /dev/null
+++ b/stdlib/on_exit.c
@@ -0,0 +1,37 @@
+/* Copyright (C) 1991 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 Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <stdlib.h>
+#include "exit.h"
+
+/* Register a function to be called by exit. */
+int
+DEFUN(on_exit, (func, arg),
+ void EXFUN((*func), (int status, PTR arg)) AND PTR arg)
+{
+ struct exit_function *new = __new_exitfn();
+
+ if (new == NULL)
+ return -1;
+
+ new->flavor = ef_on;
+ new->func.on.fn = func;
+ new->func.on.arg = arg;
+ return 0;
+}
diff --git a/stdlib/qsort.c b/stdlib/qsort.c
new file mode 100644
index 0000000..bc8d171
--- /dev/null
+++ b/stdlib/qsort.c
@@ -0,0 +1,243 @@
+/* Copyright (C) 1991, 1992 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+Written by Douglas C. Schmidt (schmidt@ics.uci.edu).
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* Byte-wise swap two items of size SIZE. */
+#define SWAP(a, b, size) \
+ do \
+ { \
+ register size_t __size = (size); \
+ register char *__a = (a), *__b = (b); \
+ do \
+ { \
+ char __tmp = *__a; \
+ *__a++ = *__b; \
+ *__b++ = __tmp; \
+ } while (--__size > 0); \
+ } while (0)
+
+/* Discontinue quicksort algorithm when partition gets below this size.
+ This particular magic number was chosen to work best on a Sun 4/260. */
+#define MAX_THRESH 4
+
+/* Stack node declarations used to store unfulfilled partition obligations. */
+typedef struct
+ {
+ char *lo;
+ char *hi;
+ } stack_node;
+
+/* The next 4 #defines implement a very fast in-line stack abstraction. */
+#define STACK_SIZE (8 * sizeof(unsigned long int))
+#define PUSH(low, high) ((void) ((top->lo = (low)), (top->hi = (high)), ++top))
+#define POP(low, high) ((void) (--top, (low = top->lo), (high = top->hi)))
+#define STACK_NOT_EMPTY (stack < top)
+
+
+/* Order size using quicksort. This implementation incorporates
+ four optimizations discussed in Sedgewick:
+
+ 1. Non-recursive, using an explicit stack of pointer that store the
+ next array partition to sort. To save time, this maximum amount
+ of space required to store an array of MAX_INT is allocated on the
+ stack. Assuming a 32-bit integer, this needs only 32 *
+ sizeof(stack_node) == 136 bits. Pretty cheap, actually.
+
+ 2. Chose the pivot element using a median-of-three decision tree.
+ This reduces the probability of selecting a bad pivot value and
+ eliminates certain extraneous comparisons.
+
+ 3. Only quicksorts TOTAL_ELEMS / MAX_THRESH partitions, leaving
+ insertion sort to order the MAX_THRESH items within each partition.
+ This is a big win, since insertion sort is faster for small, mostly
+ sorted array segements.
+
+ 4. The larger of the two sub-partitions is always pushed onto the
+ stack first, with the algorithm then concentrating on the
+ smaller partition. This *guarantees* no more than log (n)
+ stack size is needed (actually O(1) in this case)! */
+
+void
+DEFUN(_quicksort, (pbase, total_elems, size, cmp),
+ PTR CONST pbase AND size_t total_elems AND size_t size AND
+ int EXFUN((*cmp), (CONST PTR, CONST PTR)))
+{
+ register char *base_ptr = (char *) pbase;
+
+ /* Allocating SIZE bytes for a pivot buffer facilitates a better
+ algorithm below since we can do comparisons directly on the pivot. */
+ char *pivot_buffer = (char *) __alloca (size);
+ CONST size_t max_thresh = MAX_THRESH * size;
+
+ if (total_elems == 0)
+ /* Avoid lossage with unsigned arithmetic below. */
+ return;
+
+ if (total_elems > MAX_THRESH)
+ {
+ char *lo = base_ptr;
+ char *hi = &lo[size * (total_elems - 1)];
+ /* Largest size needed for 32-bit int!!! */
+ stack_node stack[STACK_SIZE];
+ stack_node *top = stack + 1;
+
+ while (STACK_NOT_EMPTY)
+ {
+ char *left_ptr;
+ char *right_ptr;
+
+ char *pivot = pivot_buffer;
+
+ /* Select median value from among LO, MID, and HI. Rearrange
+ LO and HI so the three values are sorted. This lowers the
+ probability of picking a pathological pivot value and
+ skips a comparison for both the LEFT_PTR and RIGHT_PTR. */
+
+ char *mid = lo + size * ((hi - lo) / size >> 1);
+
+ if ((*cmp)((PTR) mid, (PTR) lo) < 0)
+ SWAP(mid, lo, size);
+ if ((*cmp)((PTR) hi, (PTR) mid) < 0)
+ SWAP(mid, hi, size);
+ else
+ goto jump_over;
+ if ((*cmp)((PTR) mid, (PTR) lo) < 0)
+ SWAP(mid, lo, size);
+ jump_over:;
+ memcpy(pivot, mid, size);
+ pivot = pivot_buffer;
+
+ left_ptr = lo + size;
+ right_ptr = hi - size;
+
+ /* Here's the famous ``collapse the walls'' section of quicksort.
+ Gotta like those tight inner loops! They are the main reason
+ that this algorithm runs much faster than others. */
+ do
+ {
+ while ((*cmp)((PTR) left_ptr, (PTR) pivot) < 0)
+ left_ptr += size;
+
+ while ((*cmp)((PTR) pivot, (PTR) right_ptr) < 0)
+ right_ptr -= size;
+
+ if (left_ptr < right_ptr)
+ {
+ SWAP(left_ptr, right_ptr, size);
+ left_ptr += size;
+ right_ptr -= size;
+ }
+ else if (left_ptr == right_ptr)
+ {
+ left_ptr += size;
+ right_ptr -= size;
+ break;
+ }
+ }
+ while (left_ptr <= right_ptr);
+
+ /* Set up pointers for next iteration. First determine whether
+ left and right partitions are below the threshold size. If so,
+ ignore one or both. Otherwise, push the larger partition's
+ bounds on the stack and continue sorting the smaller one. */
+
+ if ((size_t) (right_ptr - lo) <= max_thresh)
+ {
+ if ((size_t) (hi - left_ptr) <= max_thresh)
+ /* Ignore both small partitions. */
+ POP(lo, hi);
+ else
+ /* Ignore small left partition. */
+ lo = left_ptr;
+ }
+ else if ((size_t) (hi - left_ptr) <= max_thresh)
+ /* Ignore small right partition. */
+ hi = right_ptr;
+ else if ((right_ptr - lo) > (hi - left_ptr))
+ {
+ /* Push larger left partition indices. */
+ PUSH(lo, right_ptr);
+ lo = left_ptr;
+ }
+ else
+ {
+ /* Push larger right partition indices. */
+ PUSH(left_ptr, hi);
+ hi = right_ptr;
+ }
+ }
+ }
+
+ /* Once the BASE_PTR array is partially sorted by quicksort the rest
+ is completely sorted using insertion sort, since this is efficient
+ for partitions below MAX_THRESH size. BASE_PTR points to the beginning
+ of the array to sort, and END_PTR points at the very last element in
+ the array (*not* one beyond it!). */
+
+#define min(x, y) ((x) < (y) ? (x) : (y))
+
+ {
+ char *CONST end_ptr = &base_ptr[size * (total_elems - 1)];
+ char *tmp_ptr = base_ptr;
+ char *thresh = min(end_ptr, base_ptr + max_thresh);
+ register char *run_ptr;
+
+ /* Find smallest element in first threshold and place it at the
+ array's beginning. This is the smallest array element,
+ and the operation speeds up insertion sort's inner loop. */
+
+ for (run_ptr = tmp_ptr + size; run_ptr <= thresh; run_ptr += size)
+ if ((*cmp)((PTR) run_ptr, (PTR) tmp_ptr) < 0)
+ tmp_ptr = run_ptr;
+
+ if (tmp_ptr != base_ptr)
+ SWAP(tmp_ptr, base_ptr, size);
+
+ /* Insertion sort, running from left-hand-side up to right-hand-side. */
+
+ run_ptr = base_ptr + size;
+ while ((run_ptr += size) <= end_ptr)
+ {
+ tmp_ptr = run_ptr - size;
+ while ((*cmp)((PTR) run_ptr, (PTR) tmp_ptr) < 0)
+ tmp_ptr -= size;
+
+ tmp_ptr += size;
+ if (tmp_ptr != run_ptr)
+ {
+ char *trav;
+
+ trav = run_ptr + size;
+ while (--trav >= run_ptr)
+ {
+ char c = *trav;
+ char *hi, *lo;
+
+ for (hi = lo = trav; (lo -= size) >= tmp_ptr; hi = lo)
+ *hi = *lo;
+ *hi = c;
+ }
+ }
+ }
+ }
+}
+
diff --git a/stdlib/rand.c b/stdlib/rand.c
new file mode 100644
index 0000000..1353432
--- /dev/null
+++ b/stdlib/rand.c
@@ -0,0 +1,30 @@
+/* Copyright (C) 1991 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 Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <stdlib.h>
+
+#undef rand
+
+
+/* Return a random integer between 0 and RAND_MAX. */
+int
+DEFUN_VOID(rand)
+{
+ return (int) __random();
+}
diff --git a/stdlib/random.c b/stdlib/random.c
new file mode 100644
index 0000000..fb32b36
--- /dev/null
+++ b/stdlib/random.c
@@ -0,0 +1,357 @@
+/*
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/*
+ * This is derived from the Berkeley source:
+ * @(#)random.c 5.5 (Berkeley) 7/6/88
+ * It was reworked for the GNU C Library by Roland McGrath.
+ */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <limits.h>
+#include <stddef.h>
+#include <stdlib.h>
+
+
+/* An improved random number generation package. In addition to the standard
+ rand()/srand() like interface, this package also has a special state info
+ interface. The initstate() routine is called with a seed, an array of
+ bytes, and a count of how many bytes are being passed in; this array is
+ then initialized to contain information for random number generation with
+ that much state information. Good sizes for the amount of state
+ information are 32, 64, 128, and 256 bytes. The state can be switched by
+ calling the setstate() function with the same array as was initiallized
+ with initstate(). By default, the package runs with 128 bytes of state
+ information and generates far better random numbers than a linear
+ congruential generator. If the amount of state information is less than
+ 32 bytes, a simple linear congruential R.N.G. is used. Internally, the
+ state information is treated as an array of longs; the zeroeth element of
+ the array is the type of R.N.G. being used (small integer); the remainder
+ of the array is the state information for the R.N.G. Thus, 32 bytes of
+ state information will give 7 longs worth of state information, which will
+ allow a degree seven polynomial. (Note: The zeroeth word of state
+ information also has some other information stored in it; see setstate
+ for details). The random number generation technique is a linear feedback
+ shift register approach, employing trinomials (since there are fewer terms
+ to sum up that way). In this approach, the least significant bit of all
+ the numbers in the state table will act as a linear feedback shift register,
+ and will have period 2^deg - 1 (where deg is the degree of the polynomial
+ being used, assuming that the polynomial is irreducible and primitive).
+ The higher order bits will have longer periods, since their values are
+ also influenced by pseudo-random carries out of the lower bits. The
+ total period of the generator is approximately deg*(2**deg - 1); thus
+ doubling the amount of state information has a vast influence on the
+ period of the generator. Note: The deg*(2**deg - 1) is an approximation
+ only good for large deg, when the period of the shift register is the
+ dominant factor. With deg equal to seven, the period is actually much
+ longer than the 7*(2**7 - 1) predicted by this formula. */
+
+
+
+/* For each of the currently supported random number generators, we have a
+ break value on the amount of state information (you need at least thi
+ bytes of state info to support this random number generator), a degree for
+ the polynomial (actually a trinomial) that the R.N.G. is based on, and
+ separation between the two lower order coefficients of the trinomial. */
+
+/* Linear congruential. */
+#define TYPE_0 0
+#define BREAK_0 8
+#define DEG_0 0
+#define SEP_0 0
+
+/* x**7 + x**3 + 1. */
+#define TYPE_1 1
+#define BREAK_1 32
+#define DEG_1 7
+#define SEP_1 3
+
+/* x**15 + x + 1. */
+#define TYPE_2 2
+#define BREAK_2 64
+#define DEG_2 15
+#define SEP_2 1
+
+/* x**31 + x**3 + 1. */
+#define TYPE_3 3
+#define BREAK_3 128
+#define DEG_3 31
+#define SEP_3 3
+
+/* x**63 + x + 1. */
+#define TYPE_4 4
+#define BREAK_4 256
+#define DEG_4 63
+#define SEP_4 1
+
+
+/* Array versions of the above information to make code run faster.
+ Relies on fact that TYPE_i == i. */
+
+#define MAX_TYPES 5 /* Max number of types above. */
+
+static int degrees[MAX_TYPES] = { DEG_0, DEG_1, DEG_2, DEG_3, DEG_4 };
+static int seps[MAX_TYPES] = { SEP_0, SEP_1, SEP_2, SEP_3, SEP_4 };
+
+
+
+/* Initially, everything is set up as if from:
+ initstate(1, randtbl, 128);
+ Note that this initialization takes advantage of the fact that srandom
+ advances the front and rear pointers 10*rand_deg times, and hence the
+ rear pointer which starts at 0 will also end up at zero; thus the zeroeth
+ element of the state information, which contains info about the current
+ position of the rear pointer is just
+ (MAX_TYPES * (rptr - state)) + TYPE_3 == TYPE_3. */
+
+static long int randtbl[DEG_3 + 1] =
+ {
+ TYPE_3,
+ -851904987, -43806228, -2029755270, 1390239686, -1912102820,
+ -485608943, 1969813258, -1590463333, -1944053249, 455935928, 508023712,
+ -1714531963, 1800685987, -2015299881, 654595283, -1149023258,
+ -1470005550, -1143256056, -1325577603, -1568001885, 1275120390,
+ -607508183, -205999574, -1696891592, 1492211999, -1528267240,
+ -952028296, -189082757, 362343714, 1424981831, 2039449641,
+ };
+
+/* FPTR and RPTR are two pointers into the state info, a front and a rear
+ pointer. These two pointers are always rand_sep places aparts, as they
+ cycle through the state information. (Yes, this does mean we could get
+ away with just one pointer, but the code for random is more efficient
+ this way). The pointers are left positioned as they would be from the call:
+ initstate(1, randtbl, 128);
+ (The position of the rear pointer, rptr, is really 0 (as explained above
+ in the initialization of randtbl) because the state table pointer is set
+ to point to randtbl[1] (as explained below).) */
+
+static long int *fptr = &randtbl[SEP_3 + 1];
+static long int *rptr = &randtbl[1];
+
+
+
+/* The following things are the pointer to the state information table,
+ the type of the current generator, the degree of the current polynomial
+ being used, and the separation between the two pointers.
+ Note that for efficiency of random, we remember the first location of
+ the state information, not the zeroeth. Hence it is valid to access
+ state[-1], which is used to store the type of the R.N.G.
+ Also, we remember the last location, since this is more efficient than
+ indexing every time to find the address of the last element to see if
+ the front and rear pointers have wrapped. */
+
+static long int *state = &randtbl[1];
+
+static int rand_type = TYPE_3;
+static int rand_deg = DEG_3;
+static int rand_sep = SEP_3;
+
+static long int *end_ptr = &randtbl[sizeof(randtbl) / sizeof(randtbl[0])];
+
+/* Initialize the random number generator based on the given seed. If the
+ type is the trivial no-state-information type, just remember the seed.
+ Otherwise, initializes state[] based on the given "seed" via a linear
+ congruential generator. Then, the pointers are set to known locations
+ that are exactly rand_sep places apart. Lastly, it cycles the state
+ information a given number of times to get rid of any initial dependencies
+ introduced by the L.C.R.N.G. Note that the initialization of randtbl[]
+ for default usage relies on values produced by this routine. */
+void
+DEFUN(__srandom, (x), unsigned int x)
+{
+ state[0] = x;
+ if (rand_type != TYPE_0)
+ {
+ register long int i;
+ for (i = 1; i < rand_deg; ++i)
+ state[i] = (1103515145 * state[i - 1]) + 12345;
+ fptr = &state[rand_sep];
+ rptr = &state[0];
+ for (i = 0; i < 10 * rand_deg; ++i)
+ (void) __random();
+ }
+}
+
+weak_alias (__srandom, srandom)
+weak_alias (__srandom, srand)
+
+/* Initialize the state information in the given array of N bytes for
+ future random number generation. Based on the number of bytes we
+ are given, and the break values for the different R.N.G.'s, we choose
+ the best (largest) one we can and set things up for it. srandom is
+ then called to initialize the state information. Note that on return
+ from srandom, we set state[-1] to be the type multiplexed with the current
+ value of the rear pointer; this is so successive calls to initstate won't
+ lose this information and will be able to restart with setstate.
+ Note: The first thing we do is save the current state, if any, just like
+ setstate so that it doesn't matter when initstate is called.
+ Returns a pointer to the old state. */
+PTR
+DEFUN(__initstate, (seed, arg_state, n),
+ unsigned int seed AND PTR arg_state AND size_t n)
+{
+ PTR ostate = (PTR) &state[-1];
+
+ if (rand_type == TYPE_0)
+ state[-1] = rand_type;
+ else
+ state[-1] = (MAX_TYPES * (rptr - state)) + rand_type;
+ if (n < BREAK_1)
+ {
+ if (n < BREAK_0)
+ {
+ errno = EINVAL;
+ return NULL;
+ }
+ rand_type = TYPE_0;
+ rand_deg = DEG_0;
+ rand_sep = SEP_0;
+ }
+ else if (n < BREAK_2)
+ {
+ rand_type = TYPE_1;
+ rand_deg = DEG_1;
+ rand_sep = SEP_1;
+ }
+ else if (n < BREAK_3)
+ {
+ rand_type = TYPE_2;
+ rand_deg = DEG_2;
+ rand_sep = SEP_2;
+ }
+ else if (n < BREAK_4)
+ {
+ rand_type = TYPE_3;
+ rand_deg = DEG_3;
+ rand_sep = SEP_3;
+ }
+ else
+ {
+ rand_type = TYPE_4;
+ rand_deg = DEG_4;
+ rand_sep = SEP_4;
+ }
+
+ state = &((long int *) arg_state)[1]; /* First location. */
+ /* Must set END_PTR before srandom. */
+ end_ptr = &state[rand_deg];
+ __srandom(seed);
+ if (rand_type == TYPE_0)
+ state[-1] = rand_type;
+ else
+ state[-1] = (MAX_TYPES * (rptr - state)) + rand_type;
+
+ return ostate;
+}
+
+weak_alias (__initstate, initstate)
+
+/* Restore the state from the given state array.
+ Note: It is important that we also remember the locations of the pointers
+ in the current state information, and restore the locations of the pointers
+ from the old state information. This is done by multiplexing the pointer
+ location into the zeroeth word of the state information. Note that due
+ to the order in which things are done, it is OK to call setstate with the
+ same state as the current state
+ Returns a pointer to the old state information. */
+PTR
+DEFUN(__setstate, (arg_state), PTR arg_state)
+{
+ register long int *new_state = (long int *) arg_state;
+ register int type = new_state[0] % MAX_TYPES;
+ register int rear = new_state[0] / MAX_TYPES;
+ PTR ostate = (PTR) &state[-1];
+
+ if (rand_type == TYPE_0)
+ state[-1] = rand_type;
+ else
+ state[-1] = (MAX_TYPES * (rptr - state)) + rand_type;
+
+ switch (type)
+ {
+ case TYPE_0:
+ case TYPE_1:
+ case TYPE_2:
+ case TYPE_3:
+ case TYPE_4:
+ rand_type = type;
+ rand_deg = degrees[type];
+ rand_sep = seps[type];
+ break;
+ default:
+ /* State info munged. */
+ errno = EINVAL;
+ return NULL;
+ }
+
+ state = &new_state[1];
+ if (rand_type != TYPE_0)
+ {
+ rptr = &state[rear];
+ fptr = &state[(rear + rand_sep) % rand_deg];
+ }
+ /* Set end_ptr too. */
+ end_ptr = &state[rand_deg];
+
+ return ostate;
+}
+
+weak_alias (__setstate, setstate)
+
+/* If we are using the trivial TYPE_0 R.N.G., just do the old linear
+ congruential bit. Otherwise, we do our fancy trinomial stuff, which is the
+ same in all ther other cases due to all the global variables that have been
+ set up. The basic operation is to add the number at the rear pointer into
+ the one at the front pointer. Then both pointers are advanced to the next
+ location cyclically in the table. The value returned is the sum generated,
+ reduced to 31 bits by throwing away the "least random" low bit.
+ Note: The code takes advantage of the fact that both the front and
+ rear pointers can't wrap on the same call by not testing the rear
+ pointer if the front one has wrapped. Returns a 31-bit random number. */
+
+long int
+DEFUN_VOID(__random)
+{
+ if (rand_type == TYPE_0)
+ {
+ state[0] = ((state[0] * 1103515245) + 12345) & LONG_MAX;
+ return state[0];
+ }
+ else
+ {
+ long int i;
+ *fptr += *rptr;
+ /* Chucking least random bit. */
+ i = (*fptr >> 1) & LONG_MAX;
+ ++fptr;
+ if (fptr >= end_ptr)
+ {
+ fptr = state;
+ ++rptr;
+ }
+ else
+ {
+ ++rptr;
+ if (rptr >= end_ptr)
+ rptr = state;
+ }
+ return i;
+ }
+}
+
+weak_alias (__random, random)
diff --git a/stdlib/stdlib.h b/stdlib/stdlib.h
new file mode 100644
index 0000000..d64a2ff
--- /dev/null
+++ b/stdlib/stdlib.h
@@ -0,0 +1,289 @@
+/* Copyright (C) 1991, 1992, 1993, 1994, 1995 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 Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the, 1992 Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+/*
+ * ANSI Standard: 4.10 GENERAL UTILITIES <stdlib.h>
+ */
+
+#ifndef _STDLIB_H
+
+#define _STDLIB_H 1
+#include <features.h>
+
+/* Get size_t, wchar_t and NULL from <stddef.h>. */
+#define __need_size_t
+#define __need_wchar_t
+#define __need_NULL
+#include <stddef.h>
+
+#define __need_Emath
+#include <errno.h>
+
+__BEGIN_DECLS
+
+/* Returned by `div'. */
+typedef struct
+ {
+ int quot; /* Quotient. */
+ int rem; /* Remainder. */
+ } div_t;
+
+/* Returned by `ldiv'. */
+typedef struct
+ {
+ long int quot; /* Quotient. */
+ long int rem; /* Remainder. */
+ } ldiv_t;
+
+
+/* The largest number rand will return (same as INT_MAX). */
+#define RAND_MAX 2147483647
+
+
+/* We define these the same for all machines.
+ Changes from this to the outside world should be done in `_exit'. */
+#define EXIT_FAILURE 1 /* Failing exit status. */
+#define EXIT_SUCCESS 0 /* Successful exit status. */
+
+
+/* Maximum length of a multibyte character in the current locale.
+ This is just one until the fancy locale support is finished. */
+#define MB_CUR_MAX 1
+
+
+/* Convert a string to a floating-point number. */
+extern double atof __P ((__const char *__nptr));
+/* Convert a string to an integer. */
+extern int atoi __P ((__const char *__nptr));
+/* Convert a string to a long integer. */
+extern long int atol __P ((__const char *__nptr));
+
+/* Convert a string to a floating-point number. */
+extern double strtod __P ((__const char *__nptr, char **__endptr));
+
+#ifdef __USE_GNU
+/* Likewise for `float' and `long double' sizes of floating-point numbers. */
+extern float __strtof __P ((__const char *__nptr, char **__endptr));
+extern float strtof __P ((__const char *__nptr, char **__endptr));
+extern __long_double_t __strtold __P ((__const char *__nptr, char **__endptr));
+extern __long_double_t strtold __P ((__const char *__nptr, char **__endptr));
+#endif
+
+/* Convert a string to a long integer. */
+extern long int strtol __P ((__const char *__nptr, char **__endptr,
+ int __base));
+/* Convert a string to an unsigned long integer. */
+extern unsigned long int strtoul __P ((__const char *__nptr,
+ char **__endptr, int __base));
+
+#if defined (__GNUC__) && defined (__USE_BSD)
+/* Convert a string to a quadword integer. */
+extern long long int strtoq __P ((__const char *__nptr, char **__endptr,
+ int __base));
+/* Convert a string to an unsigned quadword integer. */
+extern unsigned long long int strtouq __P ((__const char *__nptr,
+ char **__endptr, int __base));
+#endif /* GCC and use BSD. */
+
+#if defined (__OPTIMIZE__) && __GNUC__ >= 2
+extern __inline double atof (__const char *__nptr)
+{ return strtod(__nptr, (char **) NULL); }
+extern __inline int atoi (__const char *__nptr)
+{ return (int) strtol (__nptr, (char **) NULL, 10); }
+extern __inline long int atol (__const char *__nptr)
+{ return strtol (__nptr, (char **) NULL, 10); }
+#endif /* Optimizing GCC >=2. */
+
+
+/* Return a random integer between 0 and RAND_MAX inclusive. */
+extern int rand __P ((void));
+/* Seed the random number generator with the given number. */
+extern void srand __P ((unsigned int __seed));
+
+/* These are the functions that actually do things. The `random', `srandom',
+ `initstate' and `setstate' functions are those from BSD Unices.
+ The `rand' and `srand' functions are required by the ANSI standard.
+ We provide both interfaces to the same random number generator. */
+/* Return a random long integer between 0 and RAND_MAX inclusive. */
+extern long int __random __P ((void));
+/* Seed the random number generator with the given number. */
+extern void __srandom __P ((unsigned int __seed));
+
+/* Initialize the random number generator to use state buffer STATEBUF,
+ of length STATELEN, and seed it with SEED. Optimal lengths are 8, 16,
+ 32, 64, 128 and 256, the bigger the better; values less than 8 will
+ cause an error and values greater than 256 will be rounded down. */
+extern __ptr_t __initstate __P ((unsigned int __seed, __ptr_t __statebuf,
+ size_t __statelen));
+/* Switch the random number generator to state buffer STATEBUF,
+ which should have been previously initialized by `initstate'. */
+extern __ptr_t __setstate __P ((__ptr_t __statebuf));
+
+#ifdef __USE_BSD
+extern long int random __P ((void));
+extern void srandom __P ((unsigned int __seed));
+extern __ptr_t initstate __P ((unsigned int __seed, __ptr_t __statebuf,
+ size_t __statelen));
+extern __ptr_t setstate __P ((__ptr_t __statebuf));
+
+#if defined (__OPTIMIZE__) && __GNUC__ >= 2
+extern __inline long int random (void)
+{ return __random(); }
+extern __inline void srandom (unsigned int __seed)
+{ __srandom(__seed); }
+extern __inline __ptr_t initstate (unsigned int __seed,
+ __ptr_t __statebuf, size_t __statelen)
+{ return __initstate (__seed, __statebuf, __statelen); }
+extern __inline __ptr_t setstate (__ptr_t __statebuf)
+{ return __setstate (__statebuf); }
+#endif /* Optimizing GCC >=2. */
+#endif /* Use BSD. */
+
+
+/* Allocate SIZE bytes of memory. */
+extern __ptr_t malloc __P ((size_t __size));
+/* Re-allocate the previously allocated block
+ in __ptr_t, making the new block SIZE bytes long. */
+extern __ptr_t realloc __P ((__ptr_t __ptr, size_t __size));
+/* Allocate NMEMB elements of SIZE bytes each, all initialized to 0. */
+extern __ptr_t calloc __P ((size_t __nmemb, size_t __size));
+/* Free a block allocated by `malloc', `realloc' or `calloc'. */
+extern void free __P ((__ptr_t __ptr));
+
+#ifdef __USE_MISC
+/* Free a block. An alias for `free'. (Sun Unices). */
+extern void cfree __P ((__ptr_t __ptr));
+#endif /* Use misc. */
+
+#if defined(__USE_GNU) || defined(__USE_BSD) || defined(__USE_MISC)
+#include <alloca.h>
+#endif /* Use GNU, BSD, or misc. */
+
+#ifdef __USE_BSD
+/* Allocate SIZE bytes on a page boundary. The storage cannot be freed. */
+extern __ptr_t valloc __P ((size_t __size));
+#endif
+
+
+/* Abort execution and generate a core-dump. */
+extern void abort __P ((void)) __attribute__ ((__noreturn__));
+
+
+/* Register a function to be called when `exit' is called. */
+extern int atexit __P ((void (*__func) (void)));
+
+#ifdef __USE_MISC
+/* Register a function to be called with the status
+ given to `exit' and the given argument. */
+extern int on_exit __P ((void (*__func) (int __status, __ptr_t __arg),
+ __ptr_t __arg));
+#endif
+
+/* Call all functions registered with `atexit' and `on_exit',
+ in the reverse of the order in which they were registered
+ perform stdio cleanup, and terminate program execution with STATUS. */
+extern void exit __P ((int __status)) __attribute__ ((__noreturn__));
+
+
+/* Return the value of envariable NAME, or NULL if it doesn't exist. */
+extern char *getenv __P ((__const char *__name));
+
+#ifdef __USE_SVID
+/* The SVID says this is in <stdio.h>, but this seems a better place. */
+/* Put STRING, which is of the form "NAME=VALUE", in the environment.
+ If there is no `=', remove NAME from the environment. */
+extern int putenv __P ((__const char *__string));
+#endif
+
+#ifdef __USE_BSD
+/* Set NAME to VALUE in the environment.
+ If REPLACE is nonzero, overwrite an existing value. */
+extern int setenv __P ((__const char *__name, __const char *__value,
+ int __replace));
+#endif
+
+/* Execute the given line as a shell command. */
+extern int system __P ((__const char *__command));
+
+
+/* Shorthand for type of comparison functions. */
+typedef int (*__compar_fn_t) __P ((__const __ptr_t, __const __ptr_t));
+
+#ifdef __USE_GNU
+typedef __compar_fn_t comparison_fn_t;
+#endif
+
+/* Do a binary search for KEY in BASE, which consists of NMEMB elements
+ of SIZE bytes each, using COMPAR to perform the comparisons. */
+extern __ptr_t bsearch __P ((__const __ptr_t __key, __const __ptr_t __base,
+ size_t __nmemb, size_t __size,
+ __compar_fn_t __compar));
+
+/* Sort NMEMB elements of BASE, of SIZE bytes each,
+ using COMPAR to perform the comparisons. */
+extern void qsort __P ((__ptr_t __base, size_t __nmemb, size_t __size,
+ __compar_fn_t __compar));
+
+
+#ifndef __CONSTVALUE
+#ifdef __GNUC__
+/* The `const' keyword tells GCC that a function's return value is
+ based solely on its arguments, and there are no side-effects. */
+#define __CONSTVALUE __const
+#else
+#define __CONSTVALUE
+#endif /* GCC. */
+#endif /* __CONSTVALUE not defined. */
+
+/* Return the absolute value of X. */
+extern __CONSTVALUE int abs __P ((int __x));
+extern __CONSTVALUE long int labs __P ((long int __x));
+
+
+/* Return the `div_t' or `ldiv_t' representation
+ of the value of NUMER over DENOM. */
+/* GCC may have built-ins for these someday. */
+extern __CONSTVALUE div_t div __P ((int __numer, int __denom));
+extern __CONSTVALUE ldiv_t ldiv __P ((long int __numer, long int __denom));
+
+
+/* Return the length of the multibyte character
+ in S, which is no longer than N. */
+extern int mblen __P ((__const char *__s, size_t __n));
+/* Return the length of the given multibyte character,
+ putting its `wchar_t' representation in *PWC. */
+extern int mbtowc __P ((wchar_t * __pwc, __const char *__s, size_t __n));
+/* Put the multibyte character represented
+ by WCHAR in S, returning its length. */
+extern int wctomb __P ((char *__s, wchar_t __wchar));
+
+#if defined (__OPTIMIZE__) && __GNUC__ >= 2
+extern __inline int mblen (__const char *__s, size_t __n)
+{ return mbtowc ((wchar_t *) NULL, __s, __n); }
+#endif /* Optimizing GCC >=2. */
+
+
+/* Convert a multibyte string to a wide char string. */
+extern size_t mbstowcs __P ((wchar_t * __pwcs, __const char *__s, size_t __n));
+/* Convert a wide char string to multibyte string. */
+extern size_t wcstombs __P ((char *__s, __const wchar_t * __pwcs, size_t __n));
+
+
+__END_DECLS
+
+#endif /* stdlib.h */
diff --git a/stdlib/strtod.c b/stdlib/strtod.c
new file mode 100644
index 0000000..d647753
--- /dev/null
+++ b/stdlib/strtod.c
@@ -0,0 +1,1027 @@
+/* Read decimal floating point numbers.
+Copyright (C) 1995 Free Software Foundation, Inc.
+Contributed by Ulrich Drepper.
+
+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 Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+/* Configuration part. These macros are defined by `strtold.c' and `strtof.c'
+ to produce the `long double' and `float' versions of the reader. */
+#ifndef FLOAT
+#define FLOAT double
+#define FLT DBL
+#define STRTOF strtod
+#define MPN2FLOAT __mpn_construct_double
+#define FLOAT_HUGE_VAL HUGE_VAL
+#endif
+/* End of configuration part. */
+
+#include <ctype.h>
+#include <errno.h>
+#include <float.h>
+#include <localeinfo.h>
+#include <math.h>
+#include <stdlib.h>
+#include "../stdio/gmp.h"
+#include "../stdio/gmp-impl.h"
+#include <gmp-mparam.h>
+#include "../stdio/longlong.h"
+#include "../stdio/fpioconst.h"
+
+/* #define NDEBUG 1 */
+#include <assert.h>
+
+
+/* Constants we need from float.h; select the set for the FLOAT precision. */
+#define MANT_DIG FLT##_MANT_DIG
+#define MAX_EXP FLT##_MAX_EXP
+#define MIN_EXP FLT##_MIN_EXP
+#define MAX_10_EXP FLT##_MAX_10_EXP
+#define MIN_10_EXP FLT##_MIN_10_EXP
+#define MAX_10_EXP_LOG FLT##_MAX_10_EXP_LOG
+
+
+/* Function to construct a floating point number from an MP integer
+ containing the fraction bits, a base 2 exponent, and a sign flag. */
+extern FLOAT MPN2FLOAT (mp_srcptr mpn, int exponent, int negative);
+
+/* Definitions according to limb size used. */
+#if BITS_PER_MP_LIMB == 32
+# define MAX_DIG_PER_LIMB 9
+# define MAX_FAC_PER_LIMB 1000000000L
+#elif BITS_PER_MP_LIMB == 64
+# define MAX_DIG_PER_LIMB 19
+# define MAX_FAC_PER_LIMB 10000000000000000000L
+#else
+# error "mp_limb size " BITS_PER_MP_LIMB "not accounted for"
+#endif
+
+
+/* Local data structure. */
+static const mp_limb _tens_in_limb[MAX_DIG_PER_LIMB] =
+{ 0, 10, 100,
+ 1000, 10000, 100000,
+ 1000000, 10000000, 100000000
+#if BITS_PER_MP_LIMB > 32
+ , 1000000000, 10000000000, 100000000000,
+ 1000000000000, 10000000000000, 100000000000000,
+ 1000000000000000, 10000000000000000, 100000000000000000,
+ 1000000000000000000
+#endif
+#if BITS_PER_MP_LIMB > 64
+ #error "Need to expand tens_in_limb table to" MAX_DIG_PER_LIMB
+#endif
+};
+
+#ifndef howmany
+#define howmany(x,y) (((x)+((y)-1))/(y))
+#endif
+#define SWAP(x, y) ({ typeof(x) _tmp = x; x = y; y = _tmp; })
+
+#define NDIG (MAX_10_EXP - MIN_10_EXP + 2 * MANT_DIG)
+#define RETURN_LIMB_SIZE howmany (MANT_DIG, BITS_PER_MP_LIMB)
+
+#define RETURN(val,end) \
+ do { if (endptr != 0) *endptr = (char *) end; return val; } while (0)
+
+/* Maximum size necessary for mpn integers to hold floating point numbers. */
+#define MPNSIZE (howmany (MAX_EXP + MANT_DIG, BITS_PER_MP_LIMB) + 1)
+/* Declare an mpn integer variable that big. */
+#define MPN_VAR(name) mp_limb name[MPNSIZE]; mp_size_t name##size
+/* Copy an mpn integer value. */
+#define MPN_ASSIGN(dst, src) \
+ memcpy (dst, src, (dst##size = src##size) * sizeof (mp_limb))
+
+
+/* Return a floating point number of the needed type according to the given
+ multi-precision number after possible rounding. */
+static inline FLOAT
+round_and_return (mp_limb *retval, int exponent, int negative,
+ mp_limb round_limb, mp_size_t round_bit, int more_bits)
+{
+ if (exponent < MIN_EXP)
+ {
+ mp_size_t shift = MIN_EXP - 1 - exponent;
+
+ if (shift >= MANT_DIG)
+ {
+ errno = EDOM;
+ return 0.0;
+ }
+
+ more_bits |= (round_limb & ((1 << round_bit) - 1)) != 0;
+ if (shift >= BITS_PER_MP_LIMB)
+ {
+ round_limb = retval[(shift - 1) / BITS_PER_MP_LIMB];
+ round_bit = (shift - 1) % BITS_PER_MP_LIMB;
+#if RETURN_LIMB_SIZE <= 2
+ assert (RETURN_LIMB_SIZE == 2);
+ more_bits |= retval[0] != 0;
+ retval[0] = retval[1];
+ retval[1] = 0;
+#else
+ int disp = shift / BITS_PER_MP_LIMB;
+ int i = 0;
+ while (retval[i] == 0 && i < disp)
+ ++i;
+ more_bits |= i < disp;
+ for (i = disp; i < RETURN_LIMB_SIZE; ++i)
+ retval[i - disp] = retval[i];
+ MPN_ZERO (&retval[RETURN_LIMB_SIZE - disp], disp);
+#endif
+ shift %= BITS_PER_MP_LIMB;
+ }
+ else
+ {
+ round_limb = retval[0];
+ round_bit = shift - 1;
+ }
+ (void) __mpn_rshift (retval, retval, RETURN_LIMB_SIZE, shift);
+ exponent = MIN_EXP - 2;
+ }
+
+ if ((round_limb & (1 << round_bit)) != 0 &&
+ (more_bits || (retval[0] & 1) != 0 ||
+ (round_limb & ((1 << round_bit) - 1)) != 0))
+ {
+ mp_limb cy = __mpn_add_1 (retval, retval, RETURN_LIMB_SIZE, 1);
+ if (cy || (retval[RETURN_LIMB_SIZE - 1]
+ & (1 << (MANT_DIG % BITS_PER_MP_LIMB))) != 0)
+ {
+ ++exponent;
+ (void) __mpn_rshift (retval, retval, RETURN_LIMB_SIZE, 1);
+ retval[RETURN_LIMB_SIZE - 1] |= 1 << (MANT_DIG % BITS_PER_MP_LIMB);
+ }
+ }
+
+ if (exponent > MAX_EXP)
+ return negative ? -FLOAT_HUGE_VAL : FLOAT_HUGE_VAL;
+
+ return MPN2FLOAT (retval, exponent, negative);
+}
+
+
+/* Read a multi-precision integer starting at STR with exactly DIGCNT digits
+ into N. Return the size of the number limbs in NSIZE at the first
+ character od the string that is not part of the integer as the function
+ value. If the EXPONENT is small enough to be taken as an additional
+ factor for the resulting number (see code) multiply by it. */
+static inline const char *
+str_to_mpn (const char *str, int digcnt, mp_limb *n, mp_size_t *nsize,
+ int *exponent)
+{
+ /* Number of digits for actual limb. */
+ int cnt = 0;
+ mp_limb low = 0;
+ mp_limb base;
+
+ *nsize = 0;
+ assert (digcnt > 0);
+ do
+ {
+ if (cnt == MAX_DIG_PER_LIMB)
+ {
+ if (*nsize == 0)
+ n[0] = low;
+ else
+ {
+ mp_limb cy;
+ cy = __mpn_mul_1 (n, n, *nsize, MAX_FAC_PER_LIMB);
+ cy += __mpn_add_1 (n, n, *nsize, low);
+ if (cy != 0)
+ n[*nsize] = cy;
+ }
+ ++(*nsize);
+ cnt = 0;
+ low = 0;
+ }
+
+ /* There might be thousands separators or radix characters in the string.
+ But these all can be ignored because we know the format of the number
+ is correct and we have an exact number of characters to read. */
+ while (!isdigit (*str))
+ ++str;
+ low = low * 10 + *str++ - '0';
+ ++cnt;
+ }
+ while (--digcnt > 0);
+
+ if (*exponent > 0 && cnt + *exponent <= MAX_DIG_PER_LIMB)
+ {
+ low *= _tens_in_limb[*exponent];
+ base = _tens_in_limb[cnt + *exponent];
+ *exponent = 0;
+ }
+ else
+ base = _tens_in_limb[cnt];
+
+ if (*nsize == 0)
+ {
+ n[0] = low;
+ *nsize = 1;
+ }
+ else
+ {
+ mp_limb cy;
+ cy = __mpn_mul_1 (n, n, *nsize, base);
+ cy += __mpn_add_1 (n, n, *nsize, low);
+ if (cy != 0)
+ n[(*nsize)++] = cy;
+ }
+ return str;
+}
+
+
+/* Shift {PTR, SIZE} COUNT bits to the left, and fill the vacated bits
+ with the COUNT most significant bits of LIMB.
+
+ Tege doesn't like this function so I have to write it here myself. :)
+ --drepper */
+static inline void
+__mpn_lshift_1 (mp_limb *ptr, mp_size_t size, unsigned int count, mp_limb limb)
+{
+ if (count == BITS_PER_MP_LIMB)
+ {
+ /* Optimize the case of shifting by exactly a word:
+ just copy words, with no actual bit-shifting. */
+ mp_size_t i;
+ for (i = size - 1; i > 0; --i)
+ ptr[i] = ptr[i - 1];
+ ptr[0] = limb;
+ }
+ else
+ {
+ (void) __mpn_lshift (ptr, ptr, size, count);
+ ptr[0] |= limb >> (BITS_PER_MP_LIMB - count);
+ }
+}
+
+
+/* Return a floating point number with the value of the given string NPTR.
+ Set *ENDPTR to the character after the last used one. If the number is
+ smaller than the smallest representable number, set `errno' to ERANGE and
+ return 0.0. If the number is too big to be represented, set `errno' to
+ ERANGE and return HUGE_VAL with the approriate sign. */
+FLOAT
+STRTOF (nptr, endptr)
+ const char *nptr;
+ char **endptr;
+{
+ int negative; /* The sign of the number. */
+ MPN_VAR (num); /* MP representation of the number. */
+ int exponent; /* Exponent of the number. */
+
+ /* When we have to compute fractional digits we form a fraction with a
+ second multi-precision number (and we sometimes need a second for
+ temporary results). */
+ MPN_VAR (den);
+
+ /* Representation for the return value. */
+ mp_limb retval[RETURN_LIMB_SIZE];
+ /* Number of bits currently in result value. */
+ int bits;
+
+ /* Running pointer after the last character processed in the string. */
+ const char *cp;
+ /* Start of significant part of the number. */
+ const char *startp;
+ /* Points at the character following the integer and fractional digits. */
+ const char *expp;
+ /* Total number of digit and number of digits in integer part. */
+ int dig_no, int_no;
+ /* Contains the last character read. */
+ char c;
+
+ /* The radix character of the current locale. */
+ wchar_t decimal;
+#ifdef USE_GROUPING
+ /* The thousands character of the current locale. */
+ wchar_t thousands;
+ /* The numeric grouping specification of the current locale,
+ in the format described in <locale.h>. */
+ const char *grouping;
+
+ /* Check the grouping of the integer part at [BEGIN,END).
+ Return zero iff a separator is found out of place. */
+ int grouping_ok (const char *begin, const char *end)
+ {
+ if (grouping)
+ while (end > begin)
+ {
+ const char *p = end;
+ do
+ --p;
+ while (*p != thousands && p > begin);
+ if (end - 1 - p != *grouping++)
+ return 0; /* Wrong number of digits in this group. */
+ end = p; /* Correct group; trim it off the end. */
+
+ if (*grouping == 0)
+ --grouping; /* Same grouping repeats in next iteration. */
+ else if (*grouping == CHAR_MAX || *grouping < 0)
+ {
+ /* No further grouping allowed. */
+ while (end > begin)
+ if (*--end == thousands)
+ return 0;
+ }
+ }
+ return 1;
+ }
+ /* Return with no conversion if the grouping of [STARTP,CP) is bad. */
+#define CHECK_GROUPING if (! grouping_ok (startp, cp)) RETURN (0.0, nptr); else
+
+ grouping = _numeric_info->grouping; /* Cache the grouping info array. */
+ if (*grouping <= 0 || *grouping == CHAR_MAX)
+ grouping = NULL;
+ else
+ {
+ /* Figure out the thousands seperator character. */
+ if (mbtowc (&thousands_sep, _numeric_info->thousands_sep,
+ strlen (_numeric_info->thousands_sep)) <= 0)
+ thousands = (wchar_t) *_numeric_info->thousands_sep;
+ if (thousands == L'\0')
+ grouping = NULL;
+ }
+#else
+#define grouping NULL
+#define thousands L'\0'
+#define CHECK_GROUPING ((void) 0)
+#endif
+
+ /* Find the locale's decimal point character. */
+ if (mbtowc (&decimal, _numeric_info->decimal_point,
+ strlen (_numeric_info->decimal_point)) <= 0)
+ decimal = (wchar_t) *_numeric_info->decimal_point;
+
+
+ /* Prepare number representation. */
+ exponent = 0;
+ negative = 0;
+ bits = 0;
+
+ /* Parse string to get maximal legal prefix. We need the number of
+ characters of the interger part, the fractional part and the exponent. */
+ cp = nptr - 1;
+ /* Ignore leading white space. */
+ do
+ c = *++cp;
+ while (isspace (c));
+
+ /* Get sign of the result. */
+ if (c == '-')
+ {
+ negative = 1;
+ c = *++cp;
+ }
+ else if (c == '+')
+ c = *++cp;
+
+ /* Return 0.0 if no legal string is found.
+ No character is used even if a sign was found. */
+ if (!isdigit (c))
+ RETURN (0.0, nptr);
+
+ /* Record the start of the digits, in case we will check their grouping. */
+ startp = cp;
+
+ /* Ignore leading zeroes. This helps us to avoid useless computations. */
+ while (c == '0' || (thousands != L'\0' && c == thousands))
+ c = *++cp;
+
+ CHECK_GROUPING;
+
+ /* If no other digit but a '0' is found the result is 0.0.
+ Return current read pointer. */
+ if (!isdigit (c) && c != decimal)
+ RETURN (0.0, cp);
+
+ /* Remember first significant digit and read following characters until the
+ decimal point, exponent character or any non-FP number character. */
+ startp = cp;
+ dig_no = 0;
+ while (dig_no < NDIG ||
+ /* If parsing grouping info, keep going past useful digits
+ so we can check all the grouping separators. */
+ grouping)
+ {
+ if (isdigit (c))
+ ++dig_no;
+ else if (thousands == L'\0' || c != thousands)
+ /* Not a digit or separator: end of the integer part. */
+ break;
+ c = *++cp;
+ }
+
+ CHECK_GROUPING;
+
+ if (dig_no >= NDIG)
+ /* Too many digits to be representable. Assigning this to EXPONENT
+ allows us to read the full number but return HUGE_VAL after parsing. */
+ exponent = MAX_10_EXP;
+
+ /* We have the number digits in the integer part. Whether these are all or
+ any is really a fractional digit will be decided later. */
+ int_no = dig_no;
+
+ /* Read the fractional digits. */
+ if (c == decimal)
+ {
+ if (isdigit (cp[1]))
+ {
+ ++cp;
+ do
+ {
+ ++dig_no;
+ c = *++cp;
+ }
+ while (isdigit (c));
+ }
+ }
+
+ /* Remember start of exponent (if any). */
+ expp = cp;
+
+ /* Read exponent. */
+ if (tolower (c) == 'e')
+ {
+ int exp_negative = 0;
+
+ c = *++cp;
+ if (c == '-')
+ {
+ exp_negative = 1;
+ c = *++cp;
+ }
+ else if (c == '+')
+ c = *++cp;
+
+ if (isdigit (c))
+ {
+ do
+ {
+ if ((!exp_negative && exponent * 10 + int_no > MAX_10_EXP)
+ || (exp_negative
+ && exponent * 10 + int_no > -MIN_10_EXP + MANT_DIG))
+ /* The exponent is too large/small to represent a valid
+ number. */
+ {
+ FLOAT retval;
+
+ /* Overflow or underflow. */
+ errno = ERANGE;
+ retval = (exp_negative ? 0.0 :
+ negative ? -FLOAT_HUGE_VAL : FLOAT_HUGE_VAL);
+
+ /* Accept all following digits as part of the exponent. */
+ do
+ ++cp;
+ while (isdigit (*cp));
+
+ RETURN (retval, cp);
+ /* NOTREACHED */
+ }
+
+ exponent *= 10;
+ exponent += c - '0';
+ c = *++cp;
+ }
+ while (isdigit (c));
+ }
+ else
+ cp = expp;
+
+ if (exp_negative)
+ exponent = -exponent;
+ }
+
+ /* We don't want to have to work with trailing zeroes after the radix. */
+ if (dig_no > int_no)
+ {
+ while (expp[-1] == '0')
+ {
+ --expp;
+ --dig_no;
+ }
+ assert (dig_no >= int_no);
+ }
+
+ /* The whole string is parsed. Store the address of the next character. */
+ if (endptr)
+ *endptr = (char *) cp;
+
+ if (dig_no == 0)
+ return 0.0;
+
+ /* Now we have the number of digits in total and the integer digits as well
+ as the exponent and its sign. We can decide whether the read digits are
+ really integer digits or belong to the fractional part; i.e. we normalize
+ 123e-2 to 1.23. */
+ {
+ register int incr = exponent < 0 ? MAX (-int_no, exponent)
+ : MIN (dig_no - int_no, exponent);
+ int_no += incr;
+ exponent -= incr;
+ }
+
+ if (int_no + exponent > MAX_10_EXP)
+ {
+ errno = ERANGE;
+ return negative ? -FLOAT_HUGE_VAL : FLOAT_HUGE_VAL;
+ }
+
+ if (int_no - dig_no + exponent < MIN_10_EXP - MANT_DIG)
+ {
+ errno = ERANGE;
+ return 0.0;
+ }
+
+ if (int_no > 0)
+ {
+ /* Read the integer part as a multi-precision number to NUM. */
+ startp = str_to_mpn (startp, int_no, num, &numsize, &exponent);
+
+ if (exponent > 0)
+ {
+ /* We now multiply the gained number by the given power of ten. */
+ mp_limb *psrc = num;
+ mp_limb *pdest = den;
+ int expbit = 1;
+ const struct mp_power *ttab = &_fpioconst_pow10[0];
+
+ assert (exponent < (1 << (MAX_10_EXP_LOG + 1)));
+ do
+ {
+ if ((exponent & expbit) != 0)
+ {
+ mp_limb cy;
+ exponent ^= expbit;
+
+ /* FIXME: not the whole multiplication has to be done.
+ If we have the needed number of bits we only need the
+ information whether more non-zero bits follow. */
+ if (numsize >= ttab->arraysize - 2)
+ cy = __mpn_mul (pdest, psrc, numsize,
+ &ttab->array[2], ttab->arraysize - 2);
+ else
+ cy = __mpn_mul (pdest, &ttab->array[2],
+ ttab->arraysize - 2,
+ psrc, numsize);
+ numsize += ttab->arraysize - 2;
+ if (cy == 0)
+ --numsize;
+ SWAP (psrc, pdest);
+ }
+ expbit <<= 1;
+ ++ttab;
+ }
+ while (exponent != 0);
+
+ if (psrc == den)
+ memcpy (num, den, numsize * sizeof (mp_limb));
+ }
+
+ /* Determine how many bits of the result we already have. */
+ count_leading_zeros (bits, num[numsize - 1]);
+ bits = numsize * BITS_PER_MP_LIMB - bits;
+
+ /* We have already the first BITS bits of the result. Together with
+ the information whether more non-zero bits follow this is enough
+ to determine the result. */
+ if (bits > MANT_DIG)
+ {
+ const mp_size_t least_idx = (bits - MANT_DIG) / BITS_PER_MP_LIMB;
+ const mp_size_t least_bit = (bits - MANT_DIG) % BITS_PER_MP_LIMB;
+ const mp_size_t round_idx = least_bit == 0 ? least_idx - 1
+ : least_idx;
+ const mp_size_t round_bit = least_bit == 0 ? BITS_PER_MP_LIMB - 1
+ : least_idx - 1;
+ int i;
+
+ if (least_bit == 0)
+ memcpy (retval, &num[least_idx],
+ RETURN_LIMB_SIZE * sizeof (mp_limb));
+ else
+ (void) __mpn_rshift (retval, &num[least_idx],
+ numsize - least_idx + 1, least_bit);
+
+ /* Check whether any limb beside the ones in RETVAL are non-zero. */
+ for (i = 0; num[i] == 0; ++i)
+ ;
+
+ return round_and_return (retval, bits - 1, negative,
+ num[round_idx], round_bit,
+ int_no < dig_no || i < round_idx);
+ /* NOTREACHED */
+ }
+ else if (dig_no == int_no)
+ {
+ const mp_size_t target_bit = (MANT_DIG - 1) % BITS_PER_MP_LIMB;
+ const mp_size_t is_bit = (bits - 1) % BITS_PER_MP_LIMB;
+
+ if (target_bit == is_bit)
+ {
+ memcpy (&retval[RETURN_LIMB_SIZE - numsize], num,
+ numsize * sizeof (mp_limb));
+ /* FIXME: the following loop can be avoided if we assume a
+ maximal MANT_DIG value. */
+ MPN_ZERO (retval, RETURN_LIMB_SIZE - numsize);
+ }
+ else if (target_bit > is_bit)
+ {
+ (void) __mpn_lshift (&retval[RETURN_LIMB_SIZE - numsize],
+ num, numsize, target_bit - is_bit);
+ /* FIXME: the following loop can be avoided if we assume a
+ maximal MANT_DIG value. */
+ MPN_ZERO (retval, RETURN_LIMB_SIZE - numsize);
+ }
+ else
+ {
+ mp_limb cy;
+ assert (numsize < RETURN_LIMB_SIZE);
+
+ cy = __mpn_rshift (&retval[RETURN_LIMB_SIZE - numsize],
+ num, numsize, is_bit - target_bit);
+ retval[RETURN_LIMB_SIZE - numsize - 1] = cy;
+ /* FIXME: the following loop can be avoided if we assume a
+ maximal MANT_DIG value. */
+ MPN_ZERO (retval, RETURN_LIMB_SIZE - numsize - 1);
+ }
+
+ return round_and_return (retval, bits - 1, negative, 0, 0, 0);
+ /* NOTREACHED */
+ }
+
+ /* Store the bits we already have. */
+ memcpy (retval, num, numsize * sizeof (mp_limb));
+#if RETURN_LIMB_SIZE > 1
+ if (numsize < RETURN_LIMB_SIZE)
+ retval[numsize] = 0;
+#endif
+ }
+
+ /* We have to compute at least some of the fractional digits. */
+ {
+ /* We construct a fraction and the result of the division gives us
+ the needed digits. The denominator is 1.0 multiplied by the
+ exponent of the lowest digit; i.e. 0.123 gives 123 / 1000 and
+ 123e6 gives 123 / 1000000. */
+
+ int expbit;
+ int cnt;
+ mp_limb cy;
+ mp_limb *psrc = den;
+ mp_limb *pdest = num;
+ int neg_exp = dig_no - int_no - exponent;
+ const struct mp_power *ttab = &_fpioconst_pow10[0];
+
+ assert (dig_no > int_no && exponent <= 0);
+
+ /* Construct the denominator. */
+ densize = 0;
+ expbit = 1;
+ do
+ {
+ if ((neg_exp & expbit) != 0)
+ {
+ mp_limb cy;
+ neg_exp ^= expbit;
+
+ if (densize == 0)
+ memcpy (psrc, &ttab->array[2],
+ (densize = ttab->arraysize - 2) * sizeof (mp_limb));
+ else
+ {
+ cy = __mpn_mul (pdest, &ttab->array[2], ttab->arraysize - 2,
+ psrc, densize);
+ densize += ttab->arraysize - 2;
+ if (cy == 0)
+ --densize;
+ SWAP (psrc, pdest);
+ }
+ }
+ expbit <<= 1;
+ ++ttab;
+ }
+ while (neg_exp != 0);
+
+ if (psrc == num)
+ memcpy (den, num, densize * sizeof (mp_limb));
+
+ /* Read the fractional digits from the string. */
+ (void) str_to_mpn (startp, dig_no - int_no, num, &numsize, &exponent);
+
+
+ /* We now have to shift both numbers so that the highest bit in the
+ denominator is set. In the same process we copy the numerator to
+ a high place in the array so that the division constructs the wanted
+ digits. This is done by a "quasi fix point" number representation.
+
+ num: ddddddddddd . 0000000000000000000000
+ |--- m ---|
+ den: ddddddddddd n >= m
+ |--- n ---|
+ */
+
+ count_leading_zeros (cnt, den[densize - 1]);
+
+ (void) __mpn_lshift (den, den, densize, cnt);
+ cy = __mpn_lshift (num, num, numsize, cnt);
+ if (cy != 0)
+ num[numsize++] = cy;
+
+ /* Now we are ready for the division. But it is not necessary to
+ do a full multi-precision division because we only need a small
+ number of bits for the result. So we do not use __mpn_divmod
+ here but instead do the division here by hand and stop whenever
+ the needed number of bits is reached. The code itself comes
+ from the GNU MP Library by Torbj\"orn Granlund. */
+
+ exponent = bits;
+
+ switch (densize)
+ {
+ case 1:
+ {
+ mp_limb d, n, quot;
+ int used = 0;
+
+ n = num[0];
+ d = den[0];
+ assert (numsize == 1 && n < d);
+
+ do
+ {
+ udiv_qrnnd (quot, n, n, 0, d);
+
+#define got_limb \
+ if (bits == 0) \
+ { \
+ register int cnt; \
+ if (quot == 0) \
+ cnt = BITS_PER_MP_LIMB; \
+ else \
+ count_leading_zeros (cnt, quot); \
+ exponent -= cnt; \
+ if (BITS_PER_MP_LIMB - cnt > MANT_DIG) \
+ { \
+ used = cnt + MANT_DIG; \
+ retval[0] = quot >> (BITS_PER_MP_LIMB - used); \
+ bits -= BITS_PER_MP_LIMB - used; \
+ } \
+ else \
+ { \
+ /* Note that we only clear the second element. */ \
+ retval[1] = 0; \
+ retval[0] = quot; \
+ bits -= cnt; \
+ } \
+ } \
+ else if (bits + BITS_PER_MP_LIMB <= MANT_DIG) \
+ __mpn_lshift_1 (retval, RETURN_LIMB_SIZE, BITS_PER_MP_LIMB, \
+ quot); \
+ else \
+ { \
+ used = MANT_DIG - bits; \
+ if (used > 0) \
+ __mpn_lshift_1 (retval, RETURN_LIMB_SIZE, used, quot); \
+ } \
+ bits += BITS_PER_MP_LIMB
+
+ got_limb;
+ }
+ while (bits <= MANT_DIG);
+
+ return round_and_return (retval, exponent - 1, negative,
+ quot, BITS_PER_MP_LIMB - 1 - used,
+ n != 0);
+ }
+ case 2:
+ {
+ mp_limb d0, d1, n0, n1;
+ mp_limb quot = 0;
+ int used = 0;
+
+ d0 = den[0];
+ d1 = den[1];
+
+ if (numsize < densize)
+ {
+ if (bits <= 0)
+ exponent -= BITS_PER_MP_LIMB;
+ else
+ {
+ if (bits + BITS_PER_MP_LIMB <= MANT_DIG)
+ __mpn_lshift_1 (retval, RETURN_LIMB_SIZE,
+ BITS_PER_MP_LIMB, 0);
+ else
+ {
+ used = MANT_DIG - bits;
+ if (used > 0)
+ __mpn_lshift_1 (retval, RETURN_LIMB_SIZE, used, 0);
+ }
+ bits += BITS_PER_MP_LIMB;
+ }
+ n1 = num[0];
+ n0 = 0;
+ }
+ else
+ {
+ n1 = num[1];
+ n0 = num[0];
+ }
+
+ while (bits <= MANT_DIG)
+ {
+ mp_limb r;
+
+ if (n1 == d1)
+ {
+ /* QUOT should be either 111..111 or 111..110. We need
+ special treatment of this rare case as normal division
+ would give overflow. */
+ quot = ~(mp_limb) 0;
+
+ r = n0 + d1;
+ if (r < d1) /* Carry in the addition? */
+ {
+ add_ssaaaa (n1, n0, r - d0, 0, 0, d0);
+ goto have_quot;
+ }
+ n1 = d0 - (d0 != 0);
+ n0 = -d0;
+ }
+ else
+ {
+ udiv_qrnnd (quot, r, n1, n0, d1);
+ umul_ppmm (n1, n0, d0, quot);
+ }
+
+ q_test:
+ if (n1 > r || (n1 == r && n0 > 0))
+ {
+ /* The estimated QUOT was too large. */
+ --quot;
+
+ sub_ddmmss (n1, n0, n1, n0, 0, d0);
+ r += d1;
+ if (r >= d1) /* If not carry, test QUOT again. */
+ goto q_test;
+ }
+ sub_ddmmss (n1, n0, r, 0, n1, n0);
+
+ have_quot:
+ got_limb;
+ }
+
+ return round_and_return (retval, exponent - 1, negative,
+ quot, BITS_PER_MP_LIMB - 1 - used,
+ n1 != 0 || n0 != 0);
+ }
+ default:
+ {
+ int i;
+ mp_limb cy, dX, d1, n0, n1;
+ mp_limb quot = 0;
+ int used = 0;
+
+ dX = den[densize - 1];
+ d1 = den[densize - 2];
+
+ /* The division does not work if the upper limb of the two-limb
+ numerator is greater than the denominator. */
+ if (num[numsize - 1] > dX)
+ num[numsize++] = 0;
+
+ if (numsize < densize)
+ {
+ mp_size_t empty = densize - numsize;
+
+ if (bits <= 0)
+ {
+ register int i;
+ for (i = numsize; i > 0; --i)
+ num[i + empty] = num[i - 1];
+ MPN_ZERO (num, empty + 1);
+ exponent -= empty * BITS_PER_MP_LIMB;
+ }
+ else
+ {
+ if (bits + empty * BITS_PER_MP_LIMB <= MANT_DIG)
+ {
+ /* We make a difference here because the compiler
+ cannot optimize the `else' case that good and
+ this reflects all currently used FLOAT types
+ and GMP implementations. */
+ register int i;
+#if RETURN_LIMB_SIZE <= 2
+ assert (empty == 1);
+ __mpn_lshift_1 (retval, RETURN_LIMB_SIZE,
+ BITS_PER_MP_LIMB, 0);
+#else
+ for (i = RETURN_LIMB_SIZE; i > empty; --i)
+ retval[i] = retval[i - empty];
+#endif
+ retval[1] = 0;
+ for (i = numsize; i > 0; --i)
+ num[i + empty] = num[i - 1];
+ MPN_ZERO (num, empty + 1);
+ }
+ else
+ {
+ used = MANT_DIG - bits;
+ if (used >= BITS_PER_MP_LIMB)
+ {
+ register int i;
+ (void) __mpn_lshift (&retval[used
+ / BITS_PER_MP_LIMB],
+ retval, RETURN_LIMB_SIZE,
+ used % BITS_PER_MP_LIMB);
+ for (i = used / BITS_PER_MP_LIMB; i >= 0; --i)
+ retval[i] = 0;
+ }
+ else if (used > 0)
+ __mpn_lshift_1 (retval, RETURN_LIMB_SIZE, used, 0);
+ }
+ bits += empty * BITS_PER_MP_LIMB;
+ }
+ }
+ else
+ {
+ int i;
+ assert (numsize == densize);
+ for (i = numsize; i > 0; --i)
+ num[i] = num[i - 1];
+ }
+
+ den[densize] = 0;
+ n0 = num[densize];
+
+ while (bits <= MANT_DIG)
+ {
+ if (n0 == dX)
+ /* This might over-estimate QUOT, but it's probably not
+ worth the extra code here to find out. */
+ quot = ~(mp_limb) 0;
+ else
+ {
+ mp_limb r;
+
+ udiv_qrnnd (quot, r, n0, num[densize - 1], dX);
+ umul_ppmm (n1, n0, d1, quot);
+
+ while (n1 > r || (n1 == r && n0 > num[densize - 2]))
+ {
+ --quot;
+ 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 QUOT. Taking advantage of this, we
+ could make this loop make two iterations less. */
+
+ cy = __mpn_submul_1 (num, den, densize + 1, quot);
+
+ if (num[densize] != cy)
+ {
+ cy = __mpn_add_n (num, num, den, densize);
+ assert (cy != 0);
+ --quot;
+ }
+ n0 = num[densize] = num[densize - 1];
+ for (i = densize - 1; i > 0; --i)
+ num[i] = num[i - 1];
+
+ got_limb;
+ }
+
+ for (i = densize - 1; num[i] != 0 && i >= 0; --i)
+ ;
+ return round_and_return (retval, exponent - 1, negative,
+ quot, BITS_PER_MP_LIMB - 1 - used,
+ i >= 0);
+ }
+ }
+ }
+
+ /* NOTREACHED */
+}
diff --git a/stdlib/strtof.c b/stdlib/strtof.c
new file mode 100644
index 0000000..bf1349b
--- /dev/null
+++ b/stdlib/strtof.c
@@ -0,0 +1,12 @@
+/* The actual implementation for all floating point sizes is in strtod.c.
+ These macros tell it to produce the `float' version, `strtof'. */
+
+#define FLOAT float
+#define FLT FLT
+#define STRTOF __strtof
+#define MPN2FLOAT __mpn_construct_float
+#define FLOAT_HUGE_VAL HUGE_VALf
+
+#include "strtod.c"
+
+weak_alias (__strtof, strtof)
diff --git a/stdlib/strtol.c b/stdlib/strtol.c
new file mode 100644
index 0000000..888a94e
--- /dev/null
+++ b/stdlib/strtol.c
@@ -0,0 +1,189 @@
+/* Copyright (C) 1991, 1992, 1994, 1995 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 Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ctype.h>
+#include <limits.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <errno.h>
+
+/* Nonzero if we are defining `strtoul' or `strtouq', operating on unsigned
+ integers. */
+#ifndef UNSIGNED
+#define UNSIGNED 0
+#endif
+
+/* If QUAD is defined, we are defining `strtoq' or `strtouq',
+ operating on `long long int's. */
+#ifdef QUAD
+#if UNSIGNED
+#define strtoul strtouq
+#else
+#define strtol strtoq
+#endif
+#define LONG long long
+#undef LONG_MIN
+#define LONG_MIN LONG_LONG_MIN
+#undef LONG_MAX
+#define LONG_MAX LONG_LONG_MAX
+#undef ULONG_MAX
+#define ULONG_MAX ULONG_LONG_MAX
+#if __GNUC__ == 2 && __GNUC_MINOR__ < 7
+/* Work around gcc bug with using this constant. */
+static const unsigned long long int maxquad = ULONG_LONG_MAX;
+#undef ULONG_MAX
+#define ULONG_MAX maxquad
+#endif
+#else
+#define LONG long
+#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. */
+#if UNSIGNED
+unsigned LONG int
+#define strtol strtoul
+#else
+LONG int
+#endif
+strtol (nptr, endptr, base)
+ const char *nptr;
+ char **endptr;
+ int base;
+{
+ int negative;
+ register unsigned LONG int cutoff;
+ register unsigned int cutlim;
+ register unsigned LONG int i;
+ register const char *s;
+ register unsigned char c;
+ const char *save;
+ int overflow;
+
+ if (base < 0 || base == 1 || base > 36)
+ base = 10;
+
+ s = nptr;
+
+ /* Skip white space. */
+ while (isspace (*s))
+ ++s;
+ if (*s == '\0')
+ goto noconv;
+
+ /* Check for a sign. */
+ if (*s == '-')
+ {
+ negative = 1;
+ ++s;
+ }
+ else if (*s == '+')
+ {
+ negative = 0;
+ ++s;
+ }
+ else
+ negative = 0;
+
+ if (base == 16 && s[0] == '0' && toupper (s[1]) == 'X')
+ s += 2;
+
+ /* If BASE is zero, figure it out ourselves. */
+ if (base == 0)
+ if (*s == '0')
+ {
+ if (toupper (s[1]) == 'X')
+ {
+ s += 2;
+ base = 16;
+ }
+ else
+ base = 8;
+ }
+ else
+ base = 10;
+
+ /* Save the pointer so we can check later if anything happened. */
+ save = s;
+
+ cutoff = ULONG_MAX / (unsigned LONG int) base;
+ cutlim = ULONG_MAX % (unsigned LONG int) base;
+
+ overflow = 0;
+ i = 0;
+ for (c = *s; c != '\0'; c = *++s)
+ {
+ if (isdigit (c))
+ c -= '0';
+ else if (isalpha (c))
+ c = toupper (c) - 'A' + 10;
+ else
+ break;
+ if (c >= base)
+ break;
+ /* Check for overflow. */
+ if (i > cutoff || (i == cutoff && c > cutlim))
+ overflow = 1;
+ else
+ {
+ 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 = (char *) s;
+
+#if !UNSIGNED
+ /* Check for a value that is within the range of
+ `unsigned LONG int', but outside the range of `LONG int'. */
+ if (i > (negative ?
+ -(unsigned LONG int) LONG_MIN : (unsigned LONG int) LONG_MAX))
+ overflow = 1;
+#endif
+
+ if (overflow)
+ {
+ errno = ERANGE;
+#if UNSIGNED
+ return ULONG_MAX;
+#else
+ return negative ? LONG_MIN : LONG_MAX;
+#endif
+ }
+
+ /* Return the result of the appropriate sign. */
+ return (negative ? -i : i);
+
+noconv:
+ /* There was no number to convert. */
+ if (endptr != NULL)
+ *endptr = (char *) nptr;
+ return 0L;
+}
diff --git a/stdlib/strtold.c b/stdlib/strtold.c
new file mode 100644
index 0000000..2595725
--- /dev/null
+++ b/stdlib/strtold.c
@@ -0,0 +1,12 @@
+/* The actual implementation for all floating point sizes is in strtod.c.
+ These macros tell it to produce the `long double' version, `strtold'. */
+
+#define FLOAT long double
+#define FLT LDBL
+#define STRTOF __strtold
+#define MPN2FLOAT __mpn_construct_long_double
+#define FLOAT_HUGE_VAL HUGE_VALl
+
+#include "strtod.c"
+
+weak_alias (__strtold, strtold)
diff --git a/stdlib/strtoq.c b/stdlib/strtoq.c
new file mode 100644
index 0000000..be1f723
--- /dev/null
+++ b/stdlib/strtoq.c
@@ -0,0 +1,22 @@
+/* strtoq -- Function to parse a `long long int' from text.
+Copyright (C) 1995 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 Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#define QUAD 1
+
+#include <strtol.c>
diff --git a/stdlib/strtoul.c b/stdlib/strtoul.c
new file mode 100644
index 0000000..386cc7a
--- /dev/null
+++ b/stdlib/strtoul.c
@@ -0,0 +1,21 @@
+/* Copyright (C) 1991 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 Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#define UNSIGNED 1
+
+#include <strtol.c>
diff --git a/stdlib/strtouq.c b/stdlib/strtouq.c
new file mode 100644
index 0000000..4eea0b2
--- /dev/null
+++ b/stdlib/strtouq.c
@@ -0,0 +1,22 @@
+/* strtouq -- Function to parse an `unsigned long long int' from text.
+Copyright (C) 1995 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 Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#define QUAD 1
+
+#include <strtoul.c>
diff --git a/stdlib/testdiv.c b/stdlib/testdiv.c
new file mode 100644
index 0000000..b86a58d
--- /dev/null
+++ b/stdlib/testdiv.c
@@ -0,0 +1,33 @@
+/* Copyright (C) 1992 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 Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+int
+DEFUN_VOID(main)
+{
+ int i, j;
+ while (scanf ("%d %d\n", &i, &j) == 2)
+ {
+ div_t d = div (i, j);
+ printf ("%d / %d = %d + %d/%d\n", i, j, d.quot, d.rem, j);
+ }
+ return 0;
+}
diff --git a/stdlib/testdiv.input b/stdlib/testdiv.input
new file mode 100644
index 0000000..415b7b4
--- /dev/null
+++ b/stdlib/testdiv.input
@@ -0,0 +1,2 @@
+10 3
+-10 3
diff --git a/stdlib/testmb.c b/stdlib/testmb.c
new file mode 100644
index 0000000..c840ce1
--- /dev/null
+++ b/stdlib/testmb.c
@@ -0,0 +1,69 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+int
+main ()
+{
+ wchar_t w[10];
+ char c[10];
+ int i;
+ int lose = 0;
+
+ i = mbstowcs (w, "bar", 4);
+ if (!(i == 3 && w[1] == 'a'))
+ {
+ puts ("mbstowcs FAILED!");
+ lose = 1;
+ }
+
+ mbstowcs (w, "blah", 5);
+ i = wcstombs (c, w, 10);
+ if (i != 4)
+ {
+ puts ("wcstombs FAILED!");
+ lose = 1;
+ }
+
+ if (mblen ("foobar", 7) != 1)
+ {
+ puts ("mblen 1 FAILED!");
+ lose = 1;
+ }
+
+ if (mblen ("", 1) != 0)
+ {
+ puts ("mblen 2 FAILED!");
+ lose = 1;
+ }
+
+ {
+ int r;
+ char c = 'x';
+ wchar_t wc;
+ char *mbc;
+
+ mbc = (char *) malloc (MB_CUR_MAX);
+ mbc[0] = c;
+ mbc[1] = '\0';
+
+ if ((r = mbtowc (&wc, &c, MB_CUR_MAX)) <= 0)
+ {
+ printf ("conversion to wide failed, result: %d\n", r);
+ lose = 1;
+ }
+ else
+ {
+ printf ("wide value: 0x%04x\n", (unsigned long) wc);
+ mbc[0] = '\0';
+ if ((r = wctomb (mbc, wc)) <= 0)
+ {
+ printf ("conversion to multibyte failed, result: %d\n", r);
+ lose = 1;
+ }
+ }
+
+ }
+
+ puts (lose ? "Test FAILED!" : "Test succeeded.");
+ return lose;
+}
diff --git a/stdlib/testrand.c b/stdlib/testrand.c
new file mode 100644
index 0000000..b66dca9
--- /dev/null
+++ b/stdlib/testrand.c
@@ -0,0 +1,51 @@
+/* Copyright (C) 1992 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 Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+int
+DEFUN_VOID(main)
+{
+ int i1, i2;
+ int j1, j2;
+
+ /* The C standard says that "If rand is called before any calls to
+ srand have been made, the same sequence shall be generated as
+ when srand is first called with a seed value of 1." */
+ i1 = rand();
+ i2 = rand();
+ srand (1);
+ j1 = rand();
+ j2 = rand();
+ if (j1 == i1 && j2 == i2)
+ {
+ puts ("Test succeeded.");
+ return 0;
+ }
+ else
+ {
+ if (j1 != i1)
+ printf ("%d != %d\n", j1, i1);
+ if (j2 != i2)
+ printf ("%d != %d\n", j2, i2);
+ puts ("Test FAILED!");
+ return 1;
+ }
+}
diff --git a/stdlib/testsort.c b/stdlib/testsort.c
new file mode 100644
index 0000000..a171a62
--- /dev/null
+++ b/stdlib/testsort.c
@@ -0,0 +1,38 @@
+#include <ansidecl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+int
+DEFUN(compare, (a, b), CONST PTR a AND CONST PTR b)
+{
+ return strcmp (*(char **) a, *(char **) b);
+}
+
+
+int
+DEFUN_VOID(main)
+{
+ char bufs[500][20];
+ char *lines[500];
+ size_t lens[500];
+ size_t i, j;
+
+ srandom (1);
+
+ for (i = 0; i < 500; ++i)
+ {
+ lens[i] = random() % 19;
+ lines[i] = bufs[i];
+ for (j = 0; j < lens[i]; ++j)
+ lines[i][j] = random() % 26 + 'a';
+ lines[i][j] = '\0';
+ }
+
+ qsort (lines, 500, sizeof (char *), compare);
+
+ for (i = 0; i < 500 && lines[i] != NULL; ++i)
+ puts (lines[i]);
+
+ return 0;
+}
diff --git a/stdlib/tst-strtod.c b/stdlib/tst-strtod.c
new file mode 100644
index 0000000..a38ff4a
--- /dev/null
+++ b/stdlib/tst-strtod.c
@@ -0,0 +1,94 @@
+/* Copyright (C) 1991 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 Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+
+struct ltest
+ {
+ CONST char *str; /* Convert this. */
+ double expect; /* To get this. */
+ char left; /* With this left over. */
+ int err; /* And this in errno. */
+ };
+static CONST struct ltest tests[] =
+ {
+ { "12.345", 12.345, '\0', 0 },
+ { "12.345e19", 12.345e19, '\0', 0 },
+ { "-.1e+9", -.1e+9, '\0', 0 },
+ { ".125", .125, '\0', 0 },
+ { "1e20", 1e20, '\0', 0 },
+ { NULL, 0, '\0', 0 }
+ };
+
+static void EXFUN(expand, (char *dst, int c));
+
+int
+DEFUN_VOID(main)
+{
+ register CONST struct ltest *lt;
+ char *ep;
+ int status = 0;
+
+ for (lt = tests; lt->str != NULL; ++lt)
+ {
+ double d;
+
+ errno = 0;
+ d = strtod(lt->str, &ep);
+ printf("strtod(\"%s\") test %u",
+ lt->str, (unsigned int) (lt - tests));
+ if (d == lt->expect && *ep == lt->left && errno == lt->err)
+ puts("\tOK");
+ else
+ {
+ puts("\tBAD");
+ if (d != lt->expect)
+ printf(" returns %.60g, expected %.60g\n", d, lt->expect);
+ if (lt->left != *ep)
+ {
+ char exp1[5], exp2[5];
+ expand(exp1, *ep);
+ expand(exp2, lt->left);
+ printf(" leaves '%s', expected '%s'\n", exp1, exp2);
+ }
+ if (errno != lt->err)
+ printf(" errno %d (%s) instead of %d (%s)\n",
+ errno, strerror(errno), lt->err, strerror(lt->err));
+ status = 1;
+ }
+ }
+
+ exit(status ? EXIT_FAILURE : EXIT_SUCCESS);
+}
+
+static void
+DEFUN(expand, (dst, c), register char *dst AND register int c)
+{
+ if (isprint(c))
+ {
+ dst[0] = c;
+ dst[1] = '\0';
+ }
+ else
+ (void) sprintf(dst, "%#.3o", (unsigned int) c);
+}
diff --git a/stdlib/tst-strtol.c b/stdlib/tst-strtol.c
new file mode 100644
index 0000000..0682da3
--- /dev/null
+++ b/stdlib/tst-strtol.c
@@ -0,0 +1,127 @@
+/* My bet is this was written by Chris Torek.
+ I reformatted and ansidecl-ized it, and tweaked it a little. */
+
+#include <ansidecl.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <strings.h>
+
+struct ltest
+ {
+ CONST char *str; /* Convert this. */
+ unsigned long int expect; /* To get this. */
+ int base; /* Use this base. */
+ char left; /* With this left over. */
+ int err; /* And this in errno. */
+ };
+static CONST struct ltest tests[] =
+ {
+ /* First, signed numbers. */
+ { " -17", -17, 0, 0, 0 },
+ { " +0x123fg", 0x123f, 0, 'g', 0 },
+ { "2147483647", 2147483647, 0, 0, 0 },
+ { "2147483648", 2147483647, 0, 0, ERANGE },
+ { "214748364888", 2147483647, 0, 0, ERANGE },
+ { "2147483650", 2147483647, 0, 0, ERANGE },
+ { "-2147483649", -2147483648, 0, 0, ERANGE },
+ { "-2147483648", -2147483648, 0, 0, 0 },
+ { "0123", 0123, 0, 0, 0 },
+ { "0x1122334455z", 2147483647, 16, 'z', ERANGE },
+ { "0x0xc", 0, 0, 'x', 0 },
+ { "yz!", 34*36+35, 36, '!', 0 },
+ { NULL, 0, 0, 0, 0 },
+
+ /* Then unsigned. */
+ { " 0", 0, 0, 0, 0 },
+ { "0xffffffffg", 0xffffffff, 0, 'g', 0 },
+ { "0xf1f2f3f4f5", 0xffffffff, 0, 0, ERANGE },
+ { "-0x123456789", 0xffffffff, 0, 0, ERANGE },
+ { "-0xfedcba98", -0xfedcba98, 0, 0, 0 },
+ { NULL, 0, 0, 0, 0 },
+ };
+
+static void EXFUN(expand, (char *dst, int c));
+
+int
+DEFUN_VOID(main)
+{
+ register CONST struct ltest *lt;
+ char *ep;
+ int status = 0;
+
+ for (lt = tests; lt->str != NULL; ++lt)
+ {
+ register long int l;
+
+ errno = 0;
+ l = strtol(lt->str, &ep, lt->base);
+ printf("strtol(\"%s\", , %d) test %u",
+ lt->str, lt->base, (unsigned int) (lt - tests));
+ if (l == (long int) lt->expect && *ep == lt->left && errno == lt->err)
+ puts("\tOK");
+ else
+ {
+ puts("\tBAD");
+ if (l != (long int) lt->expect)
+ printf(" returns %ld, expected %ld\n",
+ l, (long int) lt->expect);
+ if (lt->left != *ep)
+ {
+ char exp1[5], exp2[5];
+ expand(exp1, *ep);
+ expand(exp2, lt->left);
+ printf(" leaves '%s', expected '%s'\n", exp1, exp2);
+ }
+ if (errno != lt->err)
+ printf(" errno %d (%s) instead of %d (%s)\n",
+ errno, strerror(errno), lt->err, strerror(lt->err));
+ status = 1;
+ }
+ }
+
+ for (++lt; lt->str != NULL; lt++)
+ {
+ register unsigned long int ul;
+
+ errno = 0;
+ ul = strtoul(lt->str, &ep, lt->base);
+ printf("strtoul(\"%s\", , %d) test %u",
+ lt->str, lt->base, (unsigned int) (lt - tests));
+ if (ul == lt->expect && *ep == lt->left && errno == lt->err)
+ puts("\tOK");
+ else
+ {
+ puts("\tBAD");
+ if (ul != lt->expect)
+ printf(" returns %lu, expected %lu\n",
+ ul, lt->expect);
+ if (lt->left != *ep)
+ {
+ char exp1[5], exp2[5];
+ expand(exp1, *ep);
+ expand(exp2, lt->left);
+ printf(" leaves '%s', expected '%s'\n", exp1, exp2);
+ }
+ if (errno != lt->err)
+ printf(" errno %d (%s) instead of %d (%s)\n",
+ errno, strerror(errno), lt->err, strerror(lt->err));
+ status = 1;
+ }
+ }
+
+ exit(status ? EXIT_FAILURE : EXIT_SUCCESS);
+}
+
+static void
+DEFUN(expand, (dst, c), register char *dst AND register int c)
+{
+ if (isprint(c))
+ {
+ dst[0] = c;
+ dst[1] = '\0';
+ }
+ else
+ (void) sprintf(dst, "%#.3o", (unsigned int) c);
+}
diff --git a/stdlib/wcstombs.c b/stdlib/wcstombs.c
new file mode 100644
index 0000000..acaf15a
--- /dev/null
+++ b/stdlib/wcstombs.c
@@ -0,0 +1,77 @@
+/* Copyright (C) 1991, 1992 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 Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <localeinfo.h>
+#include <ctype.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+/* Convert the `wchar_t' string in PWCS to a multibyte character string
+ in S, writing no more than N characters. Return the number of bytes
+ written, or (size_t) -1 if an invalid `wchar_t' was found. */
+size_t
+DEFUN(wcstombs, (s, pwcs, n),
+ register char *s AND register CONST wchar_t *pwcs AND register size_t n)
+{
+ register CONST mb_char *mb;
+ register int shift = 0;
+
+ register size_t written = 0;
+ register wchar_t w;
+
+ while ((w = *pwcs++) != (wchar_t) '\0')
+ {
+ if (isascii (w))
+ {
+ /* A normal character. */
+ *s++ = (unsigned char) w;
+ --n;
+ ++written;
+ }
+ else
+ {
+ mb = &_ctype_info->mbchar->mb_chars[w + shift];
+ if (mb->string == NULL || mb->len == 0)
+ {
+ written = (size_t) -1;
+ break;
+ }
+ else if (mb->len > n)
+ break;
+ else
+ {
+ memcpy ((PTR) s, (CONST PTR) mb->string, mb->len);
+ s += mb->len;
+ n -= mb->len;
+ written += mb->len;
+ shift += mb->shift;
+ }
+ }
+ }
+
+ /* Terminate the string if it has space. */
+ if (n > 0)
+ *s = '\0';
+
+ /* Return the number of characters written (or maybe an error). */
+ return written;
+}
diff --git a/stdlib/wctomb.c b/stdlib/wctomb.c
new file mode 100644
index 0000000..53f1cef
--- /dev/null
+++ b/stdlib/wctomb.c
@@ -0,0 +1,72 @@
+/* Copyright (C) 1991, 1992, 1995 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 Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <localeinfo.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+
+extern long int _mb_shift; /* Defined in mbtowc.c. */
+
+/* Convert WCHAR into its multibyte character representation,
+ putting this in S and returning its length. */
+int
+DEFUN(wctomb, (s, wchar), register char *s AND wchar_t wchar)
+{
+ register CONST mb_char *mb;
+
+ if (_ctype_info->mbchar == NULL)
+ mb = NULL;
+ else
+ mb = _ctype_info->mbchar->mb_chars;
+
+ /* If S is NULL, just say if we're shifted or not. */
+ if (s == NULL)
+ return _mb_shift != 0;
+
+ if (wchar == (wchar_t) '\0')
+ {
+ _mb_shift = 0;
+ /* See ANSI 4.4.1.1, line 21. */
+ if (s != NULL)
+ *s = '\0';
+ return 1;
+ }
+ else if (mb == NULL)
+ {
+ if ((wchar_t) (char) wchar == wchar && isascii ((char) wchar))
+ {
+ /* A normal ASCII character translates to itself. */
+ if (s != NULL)
+ *s = (char) wchar;
+ return 1;
+ }
+ return -1;
+ }
+
+ mb += wchar + _mb_shift;
+ if (mb->string == NULL || mb->len == 0)
+ return -1;
+ memcpy((PTR) s, (CONST PTR) mb->string, mb->len + 1);
+ _mb_shift += mb->shift;
+ return mb->len;
+}