add libc building to agbcc.

This commit is contained in:
ProjectRevoTPP
2017-12-20 16:34:35 -05:00
parent f49e7cbb33
commit 48ef7704c0
306 changed files with 32781 additions and 0 deletions

44
libc/stdlib/__adjust.c Normal file
View File

@@ -0,0 +1,44 @@
/*
* return (*acc) scaled by 10**dexp.
*/
#include <_ansi.h>
#include <reent.h>
#include "std.h"
#define abs(x) (((x) < 0) ? -(x) : (x))
double
_DEFUN (__adjust, (ptr, acc, dexp, sign),
struct _reent *ptr _AND
double *acc _AND
int dexp _AND
int sign)
/* *acc the 64 bit accumulator */
/* dexp decimal exponent */
/* sign sign flag */
{
double r;
if (dexp > MAXE)
{
ptr->_errno = ERANGE;
return (sign) ? -HUGE_VAL : HUGE_VAL;
}
else if (dexp < MINE)
{
ptr->_errno = ERANGE;
return 0.0;
}
r = *acc;
if (sign)
r = -r;
if (dexp == 0)
return r;
if (dexp < 0)
return r / __exp10 (abs (dexp));
else
return r * __exp10 (dexp);
}

29
libc/stdlib/__exp10.c Normal file
View File

@@ -0,0 +1,29 @@
/*
* compute 10**x by successive squaring.
*/
#include <_ansi.h>
double
_DEFUN (__exp10, (x),
unsigned x)
{
static _CONST double powtab[] =
{1.0,
10.0,
100.0,
1000.0,
10000.0};
if (x < (sizeof (powtab) / sizeof (double)))
return powtab[x];
else if (x & 1)
{
return 10.0 * __exp10 (x - 1);
}
else
{
double n = __exp10 (x / 2);
return n * n;
}
}

23
libc/stdlib/__ten_mu.c Normal file
View File

@@ -0,0 +1,23 @@
/*
* [atw] multiply 64 bit accumulator by 10 and add digit.
* The KA/CA way to do this should be to use
* a 64-bit integer internally and use "adjust" to
* convert it to float at the end of processing.
*/
#include <_ansi.h>
int
_DEFUN (__ten_mul, (acc, digit),
double *acc _AND
int digit)
{
/*
* [atw] Crude, but effective (at least on a KB)...
*/
*acc *= 10;
*acc += digit;
return 0; /* no overflow */
}

66
libc/stdlib/abort.c Normal file
View File

@@ -0,0 +1,66 @@
/* NetWare can not use this implementation of abort. It provides its
own version of abort in clib.nlm. If we can not use clib.nlm, then
we must write abort in sys/netware. */
#ifdef ABORT_PROVIDED
int _dummy_abort = 1;
#else
/*
FUNCTION
<<abort>>---abnormal termination of a program
INDEX
abort
ANSI_SYNOPSIS
#include <stdlib.h>
void abort(void);
TRAD_SYNOPSIS
#include <stdlib.h>
void abort();
DESCRIPTION
Use <<abort>> to signal that your program has detected a condition it
cannot deal with. Normally, <<abort>> ends your program's execution.
Before terminating your program, <<abort>> raises the exception <<SIGABRT>>
(using `<<raise(SIGABRT)>>'). If you have used <<signal>> to register
an exception handler for this condition, that handler has the
opportunity to retain control, thereby avoiding program termination.
In this implementation, <<abort>> does not perform any stream- or
file-related cleanup (the host environment may do so; if not, you can
arrange for your program to do its own cleanup with a <<SIGABRT>>
exception handler).
RETURNS
<<abort>> does not return to its caller.
PORTABILITY
ANSI C requires <<abort>>.
Supporting OS subroutines required: <<getpid>>, <<kill>>.
*/
#include <stdlib.h>
#include <signal.h>
_VOID
_DEFUN_VOID (abort)
{
#ifdef ABORT_MESSAGE
write (2, "Abort called\n", sizeof ("Abort called\n")-1);
#endif
while (1)
{
raise (SIGABRT);
_exit (1);
}
}
#endif

43
libc/stdlib/abs.c Normal file
View File

@@ -0,0 +1,43 @@
/*
FUNCTION
<<abs>>---integer absolute value (magnitude)
INDEX
abs
ANSI_SYNOPSIS
#include <stdlib.h>
int abs(int <[i]>);
TRAD_SYNOPSIS
#include <stdlib.h>
int abs(<[i]>)
int <[i]>;
DESCRIPTION
<<abs>> returns
@tex
$|x|$,
@end tex
the absolute value of <[i]> (also called the magnitude
of <[i]>). That is, if <[i]> is negative, the result is the opposite
of <[i]>, but if <[i]> is nonnegative the result is <[i]>.
The similar function <<labs>> uses and returns <<long>> rather than <<int>> values.
RETURNS
The result is a nonnegative integer.
PORTABILITY
<<abs>> is ANSI.
No supporting OS subroutines are required.
*/
#include <stdlib.h>
int
_DEFUN (abs, (i), int i)
{
return (i < 0) ? -i : i;
}

62
libc/stdlib/assert.c Normal file
View File

@@ -0,0 +1,62 @@
/*
FUNCTION
<<assert>>---Macro for Debugging Diagnostics
INDEX
assert
ANSI_SYNOPSIS
#include <assert.h>
void assert(int <[expression]>);
TRAD_SYNOPSIS
#include <assert.h>
assert(<[expression]>)
int <[expression]>;
DESCRIPTION
Use this macro to embed debuggging diagnostic statements in
your programs. The argument <[expression]> should be an
expression which evaluates to true (nonzero) when your program
is working as you intended.
When <[expression]> evaluates to false (zero), <<assert>>
calls <<abort>>, after first printing a message showing what
failed and where:
. Assertion failed: <[expression]>, file <[filename]>, line <[lineno]>
The macro is defined to permit you to turn off all uses of
<<assert>> at compile time by defining <<NDEBUG>> as a
preprocessor variable. If you do this, the <<assert>> macro
expands to
. (void(0))
RETURNS
<<assert>> does not return a value.
PORTABILITY
The <<assert>> macro is required by ANSI, as is the behavior
when <<NDEBUG>> is defined.
Supporting OS subroutines required (only if enabled): <<close>>, <<fstat>>,
<<getpid>>, <<isatty>>, <<kill>>, <<lseek>>, <<read>>, <<sbrk>>, <<write>>.
*/
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
void
_DEFUN (__assert, (file, line, failedexpr),
const char *file _AND
int line _AND
const char *failedexpr)
{
(void)fiprintf(stderr,
"assertion \"%s\" failed: file \"%s\", line %d\n",
failedexpr, file, line);
abort();
/* NOTREACHED */
}

80
libc/stdlib/atexit.c Normal file
View File

@@ -0,0 +1,80 @@
/*
* Copyright (c) 1990 Regents of the University of California.
* All rights reserved.
*
* %sccs.include.redist.c%
*/
/*
FUNCTION
<<atexit>>---request execution of functions at program exit
INDEX
atexit
ANSI_SYNOPSIS
#include <stdlib.h>
int atexit(void (*<[function]>)(void);
TRAD_SYNOPSIS
#include <stdlib.h>
int atexit((<[function]>)
void (*<[function]>)();
DESCRIPTION
You can use <<atexit>> to enroll functions in a list of functions that
will be called when your program terminates normally. The argument is
a pointer to a user-defined function (which must not require arguments and
must not return a result).
The functions are kept in a LIFO stack; that is, the last function
enrolled by <<atexit>> will be the first to execute when your program
exits.
There is no built-in limit to the number of functions you can enroll
in this list; however, after every group of 32 functions is enrolled,
<<atexit>> will call <<malloc>> to get space for the next part of the
list. The initial list of 32 functions is statically allocated, so
you can always count on at least that many slots available.
RETURNS
<<atexit>> returns <<0>> if it succeeds in enrolling your function,
<<-1>> if it fails (possible only if no space was available for
<<malloc>> to extend the list of functions).
PORTABILITY
<<atexit>> is required by the ANSI standard, which also specifies that
implementations must support enrolling at least 32 functions.
Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>,
<<lseek>>, <<read>>, <<sbrk>>, <<write>>.
*/
#include <stddef.h>
#include <stdlib.h>
#include <reent.h>
/*
* Register a function to be performed at exit.
*/
int
_DEFUN (atexit,
(fn),
_VOID _EXFUN ((*fn), (_VOID)))
{
register struct _atexit *p;
if ((p = _REENT->_atexit) == NULL)
_REENT->_atexit = p = &_REENT->_atexit0;
if (p->_ind >= _ATEXIT_SIZE)
{
if ((p = (struct _atexit *) malloc (sizeof *p)) == NULL)
return -1;
p->_ind = 0;
p->_next = _REENT->_atexit;
_REENT->_atexit = p;
}
p->_fns[p->_ind++] = fn;
return 0;
}

13
libc/stdlib/atexit.h Normal file
View File

@@ -0,0 +1,13 @@
/*
* %G% (UofMD) %D%
*/
#define ATEXIT_SIZE 32 /* must be at least 32 to guarantee ANSI conformance */
struct atexit {
struct atexit *next; /* next in list */
int ind; /* next index in this table */
void (*fns[ATEXIT_SIZE])(); /* the table itself */
};
struct atexit *__atexit; /* points to head of LIFO stack */

72
libc/stdlib/atof.c Normal file
View File

@@ -0,0 +1,72 @@
/*
FUNCTION
<<atof>>, <<atoff>>---string to double or float
INDEX
atof
INDEX
atoff
ANSI_SYNOPSIS
#include <stdlib.h>
double atof(const char *<[s]>);
float atoff(const char *<[s]>);
TRAD_SYNOPSIS
#include <stdlib.h>
double atof(<[s]>)
char *<[s]>;
float atoff(<[s]>)
char *<[s]>;
DESCRIPTION
<<atof>> converts the initial portion of a string to a <<double>>.
<<atoff>> converts the initial portion of a string to a <<float>>.
The functions parse the character string <[s]>,
locating a substring which can be converted to a floating point
value. The substring must match the format:
. [+|-]<[digits]>[.][<[digits]>][(e|E)[+|-]<[digits]>]
The substring converted is the longest initial
fragment of <[s]> that has the expected format, beginning with
the first non-whitespace character. The substring
is empty if <<str>> is empty, consists entirely
of whitespace, or if the first non-whitespace character is
something other than <<+>>, <<->>, <<.>>, or a digit.
<<atof(<[s]>)>> is implemented as <<strtod(<[s]>, NULL)>>.
<<atoff(<[s]>)>> is implemented as <<strtodf(<[s]>, NULL)>>.
RETURNS
<<atof>> returns the converted substring value, if any, as a
<<double>>; or <<0.0>>, if no conversion could be performed.
If the correct value is out of the range of representable values, plus
or minus <<HUGE_VAL>> is returned, and <<ERANGE>> is stored in
<<errno>>.
If the correct value would cause underflow, <<0.0>> is returned
and <<ERANGE>> is stored in <<errno>>.
<<atoff>> obeys the same rules as <<atof>>, except that it
returns a <<float>>.
PORTABILITY
<<atof>> is ANSI C. <<atof>>, <<atoi>>, and <<atol>> are subsumed by <<strod>>
and <<strol>>, but are used extensively in existing code. These functions are
less reliable, but may be faster if the argument is verified to be in a valid
range.
Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>,
<<lseek>>, <<read>>, <<sbrk>>, <<write>>.
*/
#include <stdlib.h>
#include <_ansi.h>
double
_DEFUN (atof, (s),
_CONST char *s)
{
return strtod (s, NULL);
}

9
libc/stdlib/atoff.c Normal file
View File

@@ -0,0 +1,9 @@
#include <stdlib.h>
#include <_ansi.h>
float
_DEFUN (atoff, (s),
_CONST char *s)
{
return strtodf (s, NULL);
}

54
libc/stdlib/atoi.c Normal file
View File

@@ -0,0 +1,54 @@
/*
FUNCTION
<<atoi>>, <<atol>>---string to integer
INDEX
atoi
INDEX
atol
ANSI_SYNOPSIS
#include <stdlib.h>
int atoi(const char *<[s]>);
long atol(const char *<[s]>);
TRAD_SYNOPSIS
#include <stdlib.h>
int atoi(<[s]>)
char *<[s]>;
long atol(<[s]>)
char *<[s]>;
DESCRIPTION
<<atoi>> converts the initial portion of a string to an <<int>>.
<<atol>> converts the initial portion of a string to a <<long>>.
<<atoi(s)>> is implemented as <<(int)strtol(s, NULL, 10).>>
<<atol(s)>> is implemented as <<strtol(s, NULL, 10).>>
RETURNS
The functions return the converted value, if any. If no conversion was
made, <<0>> is returned.
PORTABILITY
<<atoi>> is ANSI.
No supporting OS subroutines are required.
*/
/*
* Andy Wilson, 2-Oct-89.
*/
#include <stdlib.h>
#include <_ansi.h>
int
_DEFUN (atoi, (s),
_CONST char *s)
{
return (int) strtol (s, NULL, 10);
}

12
libc/stdlib/atol.c Normal file
View File

@@ -0,0 +1,12 @@
/*
* Andy Wilson, 2-Oct-89.
*/
#include <stdlib.h>
#include <_ansi.h>
long
_DEFUN (atol, (s), _CONST char *s)
{
return strtol (s, NULL, 10);
}

100
libc/stdlib/bsearch.c Normal file
View File

@@ -0,0 +1,100 @@
/*
* bsearch.c
* Original Author: G. Haley
* Rewritten by: G. Noer
*
* Searches an array of nmemb members, the initial member of which is pointed
* to by base, for a member that matches the object pointed to by key. The
* contents of the array shall be in ascending order according to a comparison
* function pointed to by compar. The function shall return an integer less
* than, equal to or greater than zero if the first argument is considered to be
* respectively less than, equal to or greater than the second. Returns a
* pointer to the matching member of the array, or a null pointer if no match
* is found.
*/
/*
FUNCTION
<<bsearch>>---binary search
INDEX
bsearch
ANSI_SYNOPSIS
#include <stdlib.h>
void *bsearch(const void *<[key]>, const void *<[base]>,
size_t <[nmemb]>, size_t <[size]>,
int (*<[compar]>)(const void *, const void *));
TRAD_SYNOPSIS
#include <stdlib.h>
char *bsearch(<[key]>, <[base]>, <[nmemb]>, <[size]>, <[compar]>)
char *<[key]>;
char *<[base]>;
size_t <[nmemb]>, <[size]>;
int (*<[compar]>)();
DESCRIPTION
<<bsearch>> searches an array beginning at <[base]> for any element
that matches <[key]>, using binary search. <[nmemb]> is the element
count of the array; <[size]> is the size of each element.
The array must be sorted in ascending order with respect to the
comparison function <[compar]> (which you supply as the last argument of
<<bsearch>>).
You must define the comparison function <<(*<[compar]>)>> to have two
arguments; its result must be negative if the first argument is
less than the second, zero if the two arguments match, and
positive if the first argument is greater than the second (where
``less than'' and ``greater than'' refer to whatever arbitrary
ordering is appropriate).
RETURNS
Returns a pointer to an element of <[array]> that matches <[key]>. If
more than one matching element is available, the result may point to
any of them.
PORTABILITY
<<bsearch>> is ANSI.
No supporting OS subroutines are required.
*/
#include <stdlib.h>
_PTR
_DEFUN (bsearch, (key, base, nmemb, size, compar),
_CONST _PTR key _AND
_CONST _PTR base _AND
size_t nmemb _AND
size_t size _AND
int _EXFUN ((*compar), (const _PTR, const _PTR)))
{
_PTR current;
size_t lower = 0;
size_t upper = nmemb;
size_t index;
int result;
if (nmemb == 0 || size == 0)
return NULL;
while (lower < upper)
{
index = (lower + upper) / 2;
current = (_PTR) (((char *) base) + (index * size));
result = compar (key, current);
if (result < 0)
upper = index;
else if (result > 0)
lower = index + 1;
else
return current;
}
return NULL;
}

65
libc/stdlib/calloc.c Normal file
View File

@@ -0,0 +1,65 @@
/*
FUNCTION
<<calloc>>---allocate space for arrays
INDEX
calloc
INDEX
_calloc_r
ANSI_SYNOPSIS
#include <stdlib.h>
void *calloc(size_t <[n]>, size_t <[s]>);
void *calloc_r(void *<[reent]>, size_t <n>, <size_t> <[s]>);
TRAD_SYNOPSIS
#include <stdlib.h>
char *calloc(<[n]>, <[s]>)
size_t <[n]>, <[s]>;
char *_calloc_r(<[reent]>, <[n]>, <[s]>)
char *<[reent]>;
size_t <[n]>;
size_t <[s]>;
DESCRIPTION
Use <<calloc>> to request a block of memory sufficient to hold an
array of <[n]> elements, each of which has size <[s]>.
The memory allocated by <<calloc>> comes out of the same memory pool
used by <<malloc>>, but the memory block is initialized to all zero
bytes. (To avoid the overhead of initializing the space, use
<<malloc>> instead.)
The alternate function <<_calloc_r>> is reentrant.
The extra argument <[reent]> is a pointer to a reentrancy structure.
RETURNS
If successful, a pointer to the newly allocated space.
If unsuccessful, <<NULL>>.
PORTABILITY
<<calloc>> is ANSI.
Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>,
<<lseek>>, <<read>>, <<sbrk>>, <<write>>.
*/
#include <string.h>
#include <stdlib.h>
#ifndef _REENT_ONLY
_PTR
_DEFUN (calloc, (n, size),
size_t n _AND
size_t size)
{
return _calloc_r (_REENT, n, size);
}
#endif

132
libc/stdlib/div.c Normal file
View File

@@ -0,0 +1,132 @@
/*
FUNCTION
<<div>>---divide two integers
INDEX
div
ANSI_SYNOPSIS
#include <stdlib.h>
div_t div(int <[n]>, int <[d]>);
TRAD_SYNOPSIS
#include <stdlib.h>
div_t div(<[n]>, <[d]>)
int <[n]>, <[d]>;
DESCRIPTION
Divide
@tex
$n/d$,
@end tex
@ifinfo
<[n]>/<[d]>,
@end ifinfo
returning quotient and remainder as two integers in a structure <<div_t>>.
RETURNS
The result is represented with the structure
. typedef struct
. {
. int quot;
. int rem;
. } div_t;
where the <<quot>> field represents the quotient, and <<rem>> the
remainder. For nonzero <[d]>, if `<<<[r]> = div(<[n]>,<[d]>);>>' then
<[n]> equals `<<<[r]>.rem + <[d]>*<[r]>.quot>>'.
To divide <<long>> rather than <<int>> values, use the similar
function <<ldiv>>.
PORTABILITY
<<div>> is ANSI.
No supporting OS subroutines are required.
*/
/*
* 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 <_ansi.h>
#include <stdlib.h> /* div_t */
div_t
_DEFUN (div, (num, denom),
int num _AND
int denom)
{
div_t r;
r.quot = num / denom;
r.rem = num % denom;
/*
* The ANSI standard says that |r.quot| <= |n/d|, where
* n/d is to be computed in infinite precision. In other
* words, we should always truncate the quotient towards
* 0, never -infinity or +infinity.
*
* Machine division and remainer may work either way when
* one or both of n or d is negative. If only one is
* negative and r.quot has been truncated towards -inf,
* r.rem will have the same sign as denom and the opposite
* sign of num; if both are negative and r.quot has been
* truncated towards -inf, r.rem will be positive (will
* have the opposite sign of num). These are considered
* `wrong'.
*
* If both are num and denom are positive, r will always
* be positive.
*
* This all boils down to:
* if num >= 0, but r.rem < 0, we got the wrong answer.
* In that case, to get the right answer, add 1 to r.quot and
* subtract denom from r.rem.
* if num < 0, but r.rem > 0, we also have the wrong answer.
* In this case, to get the right answer, subtract 1 from r.quot and
* add denom to r.rem.
*/
if (num >= 0 && r.rem < 0) {
++r.quot;
r.rem -= denom;
}
else if (num < 0 && r.rem > 0) {
--r.quot;
r.rem += denom;
}
return (r);
}

854
libc/stdlib/dtoa.c Normal file
View File

@@ -0,0 +1,854 @@
/****************************************************************
*
* The author of this software is David M. Gay.
*
* Copyright (c) 1991 by AT&T.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software and in all copies of the supporting
* documentation for such software.
*
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR AT&T MAKES ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*
***************************************************************/
/* Please send bug reports to
David M. Gay
AT&T Bell Laboratories, Room 2C-463
600 Mountain Avenue
Murray Hill, NJ 07974-2070
U.S.A.
dmg@research.att.com or research!dmg
*/
#include <_ansi.h>
#include <stdlib.h>
#include <reent.h>
#include <string.h>
#include "mprec.h"
static int
_DEFUN (quorem,
(b, S),
_Bigint * b _AND _Bigint * S)
{
int n;
Long borrow, y;
ULong carry, q, ys;
ULong *bx, *bxe, *sx, *sxe;
#ifdef Pack_32
Long z;
ULong si, zs;
#endif
n = S->_wds;
#ifdef DEBUG
/*debug*/ if (b->_wds > n)
/*debug*/ Bug ("oversize b in quorem");
#endif
if (b->_wds < n)
return 0;
sx = S->_x;
sxe = sx + --n;
bx = b->_x;
bxe = bx + n;
q = *bxe / (*sxe + 1); /* ensure q <= true quotient */
#ifdef DEBUG
/*debug*/ if (q > 9)
/*debug*/ Bug ("oversized quotient in quorem");
#endif
if (q)
{
borrow = 0;
carry = 0;
do
{
#ifdef Pack_32
si = *sx++;
ys = (si & 0xffff) * q + carry;
zs = (si >> 16) * q + (ys >> 16);
carry = zs >> 16;
y = (*bx & 0xffff) - (ys & 0xffff) + borrow;
borrow = y >> 16;
Sign_Extend (borrow, y);
z = (*bx >> 16) - (zs & 0xffff) + borrow;
borrow = z >> 16;
Sign_Extend (borrow, z);
Storeinc (bx, z, y);
#else
ys = *sx++ * q + carry;
carry = ys >> 16;
y = *bx - (ys & 0xffff) + borrow;
borrow = y >> 16;
Sign_Extend (borrow, y);
*bx++ = y & 0xffff;
#endif
}
while (sx <= sxe);
if (!*bxe)
{
bx = b->_x;
while (--bxe > bx && !*bxe)
--n;
b->_wds = n;
}
}
if (cmp (b, S) >= 0)
{
q++;
borrow = 0;
carry = 0;
bx = b->_x;
sx = S->_x;
do
{
#ifdef Pack_32
si = *sx++;
ys = (si & 0xffff) + carry;
zs = (si >> 16) + (ys >> 16);
carry = zs >> 16;
y = (*bx & 0xffff) - (ys & 0xffff) + borrow;
borrow = y >> 16;
Sign_Extend (borrow, y);
z = (*bx >> 16) - (zs & 0xffff) + borrow;
borrow = z >> 16;
Sign_Extend (borrow, z);
Storeinc (bx, z, y);
#else
ys = *sx++ + carry;
carry = ys >> 16;
y = *bx - (ys & 0xffff) + borrow;
borrow = y >> 16;
Sign_Extend (borrow, y);
*bx++ = y & 0xffff;
#endif
}
while (sx <= sxe);
bx = b->_x;
bxe = bx + n;
if (!*bxe)
{
while (--bxe > bx && !*bxe)
--n;
b->_wds = n;
}
}
return q;
}
/* dtoa for IEEE arithmetic (dmg): convert double to ASCII string.
*
* Inspired by "How to Print Floating-Point Numbers Accurately" by
* Guy L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90, pp. 92-101].
*
* Modifications:
* 1. Rather than iterating, we use a simple numeric overestimate
* to determine k = floor(log10(d)). We scale relevant
* quantities using O(log2(k)) rather than O(k) multiplications.
* 2. For some modes > 2 (corresponding to ecvt and fcvt), we don't
* try to generate digits strictly left to right. Instead, we
* compute with fewer bits and propagate the carry if necessary
* when rounding the final digit up. This is often faster.
* 3. Under the assumption that input will be rounded nearest,
* mode 0 renders 1e23 as 1e23 rather than 9.999999999999999e22.
* That is, we allow equality in stopping tests when the
* round-nearest rule will give the same floating-point value
* as would satisfaction of the stopping test with strict
* inequality.
* 4. We remove common factors of powers of 2 from relevant
* quantities.
* 5. When converting floating-point integers less than 1e16,
* we use floating-point arithmetic rather than resorting
* to multiple-precision integers.
* 6. When asked to produce fewer than 15 digits, we first try
* to get by with floating-point arithmetic; we resort to
* multiple-precision integer arithmetic only if we cannot
* guarantee that the floating-point calculation has given
* the correctly rounded result. For k requested digits and
* "uniformly" distributed input, the probability is
* something like 10^(k-15) that we must resort to the long
* calculation.
*/
char *
_DEFUN (_dtoa_r,
(ptr, _d, mode, ndigits, decpt, sign, rve),
struct _reent *ptr _AND
double _d _AND
int mode _AND
int ndigits _AND
int *decpt _AND
int *sign _AND
char **rve)
{
/* Arguments ndigits, decpt, sign are similar to those
of ecvt and fcvt; trailing zeros are suppressed from
the returned string. If not null, *rve is set to point
to the end of the return value. If d is +-Infinity or NaN,
then *decpt is set to 9999.
mode:
0 ==> shortest string that yields d when read in
and rounded to nearest.
1 ==> like 0, but with Steele & White stopping rule;
e.g. with IEEE P754 arithmetic , mode 0 gives
1e23 whereas mode 1 gives 9.999999999999999e22.
2 ==> max(1,ndigits) significant digits. This gives a
return value similar to that of ecvt, except
that trailing zeros are suppressed.
3 ==> through ndigits past the decimal point. This
gives a return value similar to that from fcvt,
except that trailing zeros are suppressed, and
ndigits can be negative.
4-9 should give the same return values as 2-3, i.e.,
4 <= mode <= 9 ==> same return as mode
2 + (mode & 1). These modes are mainly for
debugging; often they run slower but sometimes
faster than modes 2-3.
4,5,8,9 ==> left-to-right digit generation.
6-9 ==> don't try fast floating-point estimate
(if applicable).
Values of mode other than 0-9 are treated as mode 0.
Sufficient space is allocated to the return value
to hold the suppressed trailing zeros.
*/
int bbits, b2, b5, be, dig, i, ieps, ilim, ilim0, ilim1, j, j1, k, k0,
k_check, leftright, m2, m5, s2, s5, spec_case, try_quick;
union double_union d, d2, eps;
Long L;
#ifndef Sudden_Underflow
int denorm;
ULong x;
#endif
_Bigint *b, *b1, *delta, *mlo, *mhi, *S;
double ds;
char *s, *s0;
d.d = _d;
if (ptr->_result)
{
ptr->_result->_k = ptr->_result_k;
ptr->_result->_maxwds = 1 << ptr->_result_k;
Bfree (ptr, ptr->_result);
ptr->_result = 0;
}
if (word0 (d) & Sign_bit)
{
/* set sign for everything, including 0's and NaNs */
*sign = 1;
word0 (d) &= ~Sign_bit; /* clear sign bit */
}
else
*sign = 0;
#if defined(IEEE_Arith) + defined(VAX)
#ifdef IEEE_Arith
if ((word0 (d) & Exp_mask) == Exp_mask)
#else
if (word0 (d) == 0x8000)
#endif
{
/* Infinity or NaN */
*decpt = 9999;
s =
#ifdef IEEE_Arith
!word1 (d) && !(word0 (d) & 0xfffff) ? "Infinity" :
#endif
"NaN";
if (rve)
*rve =
#ifdef IEEE_Arith
s[3] ? s + 8 :
#endif
s + 3;
return s;
}
#endif
#ifdef IBM
d.d += 0; /* normalize */
#endif
if (!d.d)
{
*decpt = 1;
s = "0";
if (rve)
*rve = s + 1;
return s;
}
b = d2b (ptr, d.d, &be, &bbits);
#ifdef Sudden_Underflow
i = (int) (word0 (d) >> Exp_shift1 & (Exp_mask >> Exp_shift1));
#else
if (i = (int) (word0 (d) >> Exp_shift1 & (Exp_mask >> Exp_shift1)))
{
#endif
d2.d = d.d;
word0 (d2) &= Frac_mask1;
word0 (d2) |= Exp_11;
#ifdef IBM
if (j = 11 - hi0bits (word0 (d2) & Frac_mask))
d2.d /= 1 << j;
#endif
/* log(x) ~=~ log(1.5) + (x-1.5)/1.5
* log10(x) = log(x) / log(10)
* ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10))
* log10(d) = (i-Bias)*log(2)/log(10) + log10(d2)
*
* This suggests computing an approximation k to log10(d) by
*
* k = (i - Bias)*0.301029995663981
* + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 );
*
* We want k to be too large rather than too small.
* The error in the first-order Taylor series approximation
* is in our favor, so we just round up the constant enough
* to compensate for any error in the multiplication of
* (i - Bias) by 0.301029995663981; since |i - Bias| <= 1077,
* and 1077 * 0.30103 * 2^-52 ~=~ 7.2e-14,
* adding 1e-13 to the constant term more than suffices.
* Hence we adjust the constant term to 0.1760912590558.
* (We could get a more accurate k by invoking log10,
* but this is probably not worthwhile.)
*/
i -= Bias;
#ifdef IBM
i <<= 2;
i += j;
#endif
#ifndef Sudden_Underflow
denorm = 0;
}
else
{
/* d is denormalized */
i = bbits + be + (Bias + (P - 1) - 1);
x = i > 32 ? word0 (d) << 64 - i | word1 (d) >> i - 32
: word1 (d) << 32 - i;
d2.d = x;
word0 (d2) -= 31 * Exp_msk1; /* adjust exponent */
i -= (Bias + (P - 1) - 1) + 1;
denorm = 1;
}
#endif
ds = (d2.d - 1.5) * 0.289529654602168 + 0.1760912590558 + i * 0.301029995663981;
k = (int) ds;
if (ds < 0. && ds != k)
k--; /* want k = floor(ds) */
k_check = 1;
if (k >= 0 && k <= Ten_pmax)
{
if (d.d < tens[k])
k--;
k_check = 0;
}
j = bbits - i - 1;
if (j >= 0)
{
b2 = 0;
s2 = j;
}
else
{
b2 = -j;
s2 = 0;
}
if (k >= 0)
{
b5 = 0;
s5 = k;
s2 += k;
}
else
{
b2 -= k;
b5 = -k;
s5 = 0;
}
if (mode < 0 || mode > 9)
mode = 0;
try_quick = 1;
if (mode > 5)
{
mode -= 4;
try_quick = 0;
}
leftright = 1;
switch (mode)
{
case 0:
case 1:
ilim = ilim1 = -1;
i = 18;
ndigits = 0;
break;
case 2:
leftright = 0;
/* no break */
case 4:
if (ndigits <= 0)
ndigits = 1;
ilim = ilim1 = i = ndigits;
break;
case 3:
leftright = 0;
/* no break */
case 5:
i = ndigits + k + 1;
ilim = i;
ilim1 = i - 1;
if (i <= 0)
i = 1;
}
j = sizeof (ULong);
for (ptr->_result_k = 0; sizeof (_Bigint) - sizeof (ULong) + j <= i;
j <<= 1)
ptr->_result_k++;
ptr->_result = Balloc (ptr, ptr->_result_k);
s = s0 = (char *) ptr->_result;
if (ilim >= 0 && ilim <= Quick_max && try_quick)
{
/* Try to get by with floating-point arithmetic. */
i = 0;
d2.d = d.d;
k0 = k;
ilim0 = ilim;
ieps = 2; /* conservative */
if (k > 0)
{
ds = tens[k & 0xf];
j = k >> 4;
if (j & Bletch)
{
/* prevent overflows */
j &= Bletch - 1;
d.d /= bigtens[n_bigtens - 1];
ieps++;
}
for (; j; j >>= 1, i++)
if (j & 1)
{
ieps++;
ds *= bigtens[i];
}
d.d /= ds;
}
else if (j1 = -k)
{
d.d *= tens[j1 & 0xf];
for (j = j1 >> 4; j; j >>= 1, i++)
if (j & 1)
{
ieps++;
d.d *= bigtens[i];
}
}
if (k_check && d.d < 1. && ilim > 0)
{
if (ilim1 <= 0)
goto fast_failed;
ilim = ilim1;
k--;
d.d *= 10.;
ieps++;
}
eps.d = ieps * d.d + 7.;
word0 (eps) -= (P - 1) * Exp_msk1;
if (ilim == 0)
{
S = mhi = 0;
d.d -= 5.;
if (d.d > eps.d)
goto one_digit;
if (d.d < -eps.d)
goto no_digits;
goto fast_failed;
}
#ifndef No_leftright
if (leftright)
{
/* Use Steele & White method of only
* generating digits needed.
*/
eps.d = 0.5 / tens[ilim - 1] - eps.d;
for (i = 0;;)
{
L = d.d;
d.d -= L;
*s++ = '0' + (int) L;
if (d.d < eps.d)
goto ret1;
if (1. - d.d < eps.d)
goto bump_up;
if (++i >= ilim)
break;
eps.d *= 10.;
d.d *= 10.;
}
}
else
{
#endif
/* Generate ilim digits, then fix them up. */
eps.d *= tens[ilim - 1];
for (i = 1;; i++, d.d *= 10.)
{
L = d.d;
d.d -= L;
*s++ = '0' + (int) L;
if (i == ilim)
{
if (d.d > 0.5 + eps.d)
goto bump_up;
else if (d.d < 0.5 - eps.d)
{
while (*--s == '0');
s++;
goto ret1;
}
break;
}
}
#ifndef No_leftright
}
#endif
fast_failed:
s = s0;
d.d = d2.d;
k = k0;
ilim = ilim0;
}
/* Do we have a "small" integer? */
if (be >= 0 && k <= Int_max)
{
/* Yes. */
ds = tens[k];
if (ndigits < 0 && ilim <= 0)
{
S = mhi = 0;
if (ilim < 0 || d.d <= 5 * ds)
goto no_digits;
goto one_digit;
}
for (i = 1;; i++)
{
L = d.d / ds;
d.d -= L * ds;
#ifdef Check_FLT_ROUNDS
/* If FLT_ROUNDS == 2, L will usually be high by 1 */
if (d.d < 0)
{
L--;
d.d += ds;
}
#endif
*s++ = '0' + (int) L;
if (i == ilim)
{
d.d += d.d;
if (d.d > ds || d.d == ds && L & 1)
{
bump_up:
while (*--s == '9')
if (s == s0)
{
k++;
*s = '0';
break;
}
++*s++;
}
break;
}
if (!(d.d *= 10.))
break;
}
goto ret1;
}
m2 = b2;
m5 = b5;
mhi = mlo = 0;
if (leftright)
{
if (mode < 2)
{
i =
#ifndef Sudden_Underflow
denorm ? be + (Bias + (P - 1) - 1 + 1) :
#endif
#ifdef IBM
1 + 4 * P - 3 - bbits + ((bbits + be - 1) & 3);
#else
1 + P - bbits;
#endif
}
else
{
j = ilim - 1;
if (m5 >= j)
m5 -= j;
else
{
s5 += j -= m5;
b5 += j;
m5 = 0;
}
if ((i = ilim) < 0)
{
m2 -= i;
i = 0;
}
}
b2 += i;
s2 += i;
mhi = i2b (ptr, 1);
}
if (m2 > 0 && s2 > 0)
{
i = m2 < s2 ? m2 : s2;
b2 -= i;
m2 -= i;
s2 -= i;
}
if (b5 > 0)
{
if (leftright)
{
if (m5 > 0)
{
mhi = pow5mult (ptr, mhi, m5);
b1 = mult (ptr, mhi, b);
Bfree (ptr, b);
b = b1;
}
if (j = b5 - m5)
b = pow5mult (ptr, b, j);
}
else
b = pow5mult (ptr, b, b5);
}
S = i2b (ptr, 1);
if (s5 > 0)
S = pow5mult (ptr, S, s5);
/* Check for special case that d is a normalized power of 2. */
if (mode < 2)
{
if (!word1 (d) && !(word0 (d) & Bndry_mask)
#ifndef Sudden_Underflow
&& word0 (d) & Exp_mask
#endif
)
{
/* The special case */
b2 += Log2P;
s2 += Log2P;
spec_case = 1;
}
else
spec_case = 0;
}
/* Arrange for convenient computation of quotients:
* shift left if necessary so divisor has 4 leading 0 bits.
*
* Perhaps we should just compute leading 28 bits of S once
* and for all and pass them and a shift to quorem, so it
* can do shifts and ors to compute the numerator for q.
*/
#ifdef Pack_32
if (i = ((s5 ? 32 - hi0bits (S->_x[S->_wds - 1]) : 1) + s2) & 0x1f)
i = 32 - i;
#else
if (i = ((s5 ? 32 - hi0bits (S->_x[S->_wds - 1]) : 1) + s2) & 0xf)
i = 16 - i;
#endif
if (i > 4)
{
i -= 4;
b2 += i;
m2 += i;
s2 += i;
}
else if (i < 4)
{
i += 28;
b2 += i;
m2 += i;
s2 += i;
}
if (b2 > 0)
b = lshift (ptr, b, b2);
if (s2 > 0)
S = lshift (ptr, S, s2);
if (k_check)
{
if (cmp (b, S) < 0)
{
k--;
b = multadd (ptr, b, 10, 0); /* we botched the k estimate */
if (leftright)
mhi = multadd (ptr, mhi, 10, 0);
ilim = ilim1;
}
}
if (ilim <= 0 && mode > 2)
{
if (ilim < 0 || cmp (b, S = multadd (ptr, S, 5, 0)) <= 0)
{
/* no digits, fcvt style */
no_digits:
k = -1 - ndigits;
goto ret;
}
one_digit:
*s++ = '1';
k++;
goto ret;
}
if (leftright)
{
if (m2 > 0)
mhi = lshift (ptr, mhi, m2);
/* Compute mlo -- check for special case
* that d is a normalized power of 2.
*/
mlo = mhi;
if (spec_case)
{
mhi = Balloc (ptr, mhi->_k);
Bcopy (mhi, mlo);
mhi = lshift (ptr, mhi, Log2P);
}
for (i = 1;; i++)
{
dig = quorem (b, S) + '0';
/* Do we yet have the shortest decimal string
* that will round to d?
*/
j = cmp (b, mlo);
delta = diff (ptr, S, mhi);
j1 = delta->_sign ? 1 : cmp (b, delta);
Bfree (ptr, delta);
#ifndef ROUND_BIASED
if (j1 == 0 && !mode && !(word1 (d) & 1))
{
if (dig == '9')
goto round_9_up;
if (j > 0)
dig++;
*s++ = dig;
goto ret;
}
#endif
if (j < 0 || j == 0 && !mode
#ifndef ROUND_BIASED
&& !(word1 (d) & 1)
#endif
)
{
if (j1 > 0)
{
b = lshift (ptr, b, 1);
j1 = cmp (b, S);
if ((j1 > 0 || j1 == 0 && dig & 1)
&& dig++ == '9')
goto round_9_up;
}
*s++ = dig;
goto ret;
}
if (j1 > 0)
{
if (dig == '9')
{ /* possible if i == 1 */
round_9_up:
*s++ = '9';
goto roundoff;
}
*s++ = dig + 1;
goto ret;
}
*s++ = dig;
if (i == ilim)
break;
b = multadd (ptr, b, 10, 0);
if (mlo == mhi)
mlo = mhi = multadd (ptr, mhi, 10, 0);
else
{
mlo = multadd (ptr, mlo, 10, 0);
mhi = multadd (ptr, mhi, 10, 0);
}
}
}
else
for (i = 1;; i++)
{
*s++ = dig = quorem (b, S) + '0';
if (i >= ilim)
break;
b = multadd (ptr, b, 10, 0);
}
/* Round off last digit */
b = lshift (ptr, b, 1);
j = cmp (b, S);
if (j > 0 || j == 0 && dig & 1)
{
roundoff:
while (*--s == '9')
if (s == s0)
{
k++;
*s++ = '1';
goto ret;
}
++*s++;
}
else
{
while (*--s == '0');
s++;
}
ret:
Bfree (ptr, S);
if (mhi)
{
if (mlo && mlo != mhi)
Bfree (ptr, mlo);
Bfree (ptr, mhi);
}
ret1:
Bfree (ptr, b);
*s = 0;
*decpt = k + 1;
if (rve)
*rve = s;
return s0;
}

23
libc/stdlib/dtoastub.c Normal file
View File

@@ -0,0 +1,23 @@
#include <_ansi.h>
#include <stdlib.h>
#include <reent.h>
#include <string.h>
/* Nothing in newlib actually *calls* dtoa, they all call _dtoa_r, so this
is a safe way of providing it to the user. */
#ifndef NO_REENT
char *
_DEFUN (__dtoa,
(d, mode, ndigits, decpt, sign, rve),
double d _AND
int mode _AND
int ndigits _AND
int *decpt _AND
int *sign _AND
char **rve)
{
return _dtoa_r (_REENT, d, mode, ndigits, decpt, sign, rve);
}
#endif

469
libc/stdlib/ecvtbuf.c Normal file
View File

@@ -0,0 +1,469 @@
/*
FUNCTION
<<ecvtbuf>>, <<fcvtbuf>>---double or float to string
INDEX
ecvtbuf
INDEX
fcvtbuf
ANSI_SYNOPSIS
#include <stdio.h>
char *ecvtbuf(double <[val]>, int <[chars]>, int *<[decpt]>,
int *<[sgn]>, char *<[buf]>);
char *fcvtbuf(double <[val]>, int <[decimals]>, int *<[decpt]>,
int *<[sgn]>, char *<[buf]>);
TRAD_SYNOPSIS
#include <stdio.h>
char *ecvtbuf(<[val]>, <[chars]>, <[decpt]>, <[sgn]>, <[buf]>);
double <[val]>;
int <[chars]>;
int *<[decpt]>;
int *<[sgn]>;
char *<[buf]>;
char *fcvtbuf(<[val]>, <[decimals]>, <[decpt]>, <[sgn]>, <[buf]>);
double <[val]>;
int <[decimals]>;
int *<[decpt]>;
int *<[sgn]>;
char *<[buf]>;
DESCRIPTION
<<ecvtbuf>> and <<fcvtbuf>> produce (null-terminated) strings
of digits representating the <<double>> number <[val]>.
The only difference between <<ecvtbuf>> and <<fcvtbuf>> is the
interpretation of the second argument (<[chars]> or
<[decimals]>). For <<ecvtbuf>>, the second argument <[chars]>
specifies the total number of characters to write (which is
also the number of significant digits in the formatted string,
since these two functions write only digits). For <<fcvtbuf>>,
the second argument <[decimals]> specifies the number of
characters to write after the decimal point; all digits for
the integer part of <[val]> are always included.
Since <<ecvtbuf>> and <<fcvtbuf>> write only digits in the
output string, they record the location of the decimal point
in <<*<[decpt]>>>, and the sign of the number in <<*<[sgn]>>>.
After formatting a number, <<*<[decpt]>>> contains the number
of digits to the left of the decimal point. <<*<[sgn]>>>
contains <<0>> if the number is positive, and <<1>> if it is
negative. For both functions, you supply a pointer <[buf]> to
an area of memory to hold the converted string.
RETURNS
Both functions return a pointer to <[buf]>, the string
containing a character representation of <[val]>.
PORTABILITY
Neither function is ANSI C.
Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>,
<<lseek>>, <<read>>, <<sbrk>>, <<write>>.
*/
#include <_ansi.h>
#include <stdlib.h>
#include <string.h>
#include <reent.h>
#include "mprec.h"
#include "local.h"
static void
_DEFUN (print_f, (ptr, buf, invalue, ndigit, type, dot, mode),
struct _reent *ptr _AND
char *buf _AND
double invalue _AND
int ndigit _AND
char type _AND
int dot _AND
int mode)
{
int decpt;
int sign;
char *p, *start, *end;
start = p = _dtoa_r (ptr, invalue, mode, ndigit, &decpt, &sign, &end);
if (decpt == 9999)
{
strcpy (buf, p);
return;
}
while (*p && decpt > 0)
{
*buf++ = *p++;
decpt--;
}
/* Even if not in buffer */
while (decpt > 0)
{
*buf++ = '0';
decpt--;
}
if (dot || *p)
{
if (p == start)
*buf++ = '0';
*buf++ = '.';
while (decpt < 0 && ndigit > 0)
{
*buf++ = '0';
decpt++;
ndigit--;
}
/* Print rest of stuff */
while (*p && ndigit > 0)
{
*buf++ = *p++;
ndigit--;
}
/* And trailing zeros */
while (ndigit > 0)
{
*buf++ = '0';
ndigit--;
}
}
*buf++ = 0;
}
/* Print number in e format with width chars after.
TYPE is one of 'e' or 'E'. It may also be one of 'g' or 'G' indicating
that _gcvt is calling us and we should remove trailing zeroes.
WIDTH is the number of digits of precision after the decimal point. */
static void
_DEFUN (print_e, (ptr, buf, invalue, width, type, dot),
struct _reent *ptr _AND
char *buf _AND
double invalue _AND
int width _AND
char type _AND
int dot)
{
int dp;
int sign;
char *end;
char *p;
int decpt;
int top;
int ndigit = width;
p = _dtoa_r (ptr, invalue, 2, width + 1, &decpt, &sign, &end);
if (decpt == 9999)
{
strcpy (buf, p);
return;
}
*buf++ = *p++;
if (dot || ndigit != 0)
*buf++ = '.';
while (*p && ndigit > 0)
{
*buf++ = *p++;
ndigit--;
}
/* Add trailing zeroes to fill out to ndigits unless this is 'g' format.
Also, convert g/G to e/E. */
if (type == 'g')
type = 'e';
else if (type == 'G')
type = 'E';
else
{
while (ndigit > 0)
{
*buf++ = '0';
ndigit--;
}
}
/* Add the exponent. */
*buf++ = type;
decpt--;
if (decpt < 0)
{
*buf++ = '-';
decpt = -decpt;
}
else
{
*buf++ = '+';
}
if (decpt > 99)
{
int top = decpt / 100;
*buf++ = top + '0';
decpt -= top * 100;
}
top = decpt / 10;
*buf++ = top + '0';
decpt -= top * 10;
*buf++ = decpt + '0';
*buf++ = 0;
}
#ifndef _REENT_ONLY
/* Undocumented behaviour: when given NULL as a buffer, return a
pointer to static space in the rent structure. This is only to
support ecvt and fcvt, which aren't ANSI anyway. */
char *
_DEFUN (fcvtbuf, (invalue, ndigit, decpt, sign, fcvt_buf),
double invalue _AND
int ndigit _AND
int *decpt _AND
int *sign _AND
char *fcvt_buf)
{
char *save;
char *p;
char *end;
int done = 0;
if (fcvt_buf == NULL)
{
if (_REENT->_cvtlen <= ndigit)
{
if ((fcvt_buf = (char *) _realloc_r (_REENT, _REENT->_cvtbuf,
ndigit + 1)) == NULL)
return NULL;
_REENT->_cvtlen = ndigit + 1;
_REENT->_cvtbuf = fcvt_buf;
}
fcvt_buf = _REENT->_cvtbuf ;
}
save = fcvt_buf;
if (invalue < 1.0 && invalue > -1.0)
{
p = _dtoa_r (_REENT, invalue, 2, ndigit, decpt, sign, &end);
}
else
{
p = _dtoa_r (_REENT, invalue, 3, ndigit, decpt, sign, &end);
}
/* Now copy */
while (p < end)
{
*fcvt_buf++ = *p++;
done++;
}
/* And unsuppress the trailing zeroes */
while (done < ndigit)
{
*fcvt_buf++ = '0';
done++;
}
*fcvt_buf++ = 0;
return save;
}
char *
_DEFUN (ecvtbuf, (invalue, ndigit, decpt, sign, fcvt_buf),
double invalue _AND
int ndigit _AND
int *decpt _AND
int *sign _AND
char *fcvt_buf)
{
char *save;
char *p;
char *end;
int done = 0;
if (fcvt_buf == NULL)
{
if (_REENT->_cvtlen <= ndigit)
{
if ((fcvt_buf = (char *) _realloc_r (_REENT, _REENT->_cvtbuf,
ndigit + 1)) == NULL)
return NULL;
_REENT->_cvtlen = ndigit + 1;
_REENT->_cvtbuf = fcvt_buf;
}
fcvt_buf = _REENT->_cvtbuf ;
}
save = fcvt_buf;
p = _dtoa_r (_REENT, invalue, 2, ndigit, decpt, sign, &end);
/* Now copy */
while (p < end)
{
*fcvt_buf++ = *p++;
done++;
}
/* And unsuppress the trailing zeroes */
while (done < ndigit)
{
*fcvt_buf++ = '0';
done++;
}
*fcvt_buf++ = 0;
return save;
}
#endif
char *
_DEFUN (_gcvt, (ptr, invalue, ndigit, buf, type, dot),
struct _reent *ptr _AND
double invalue _AND
int ndigit _AND
char *buf _AND
char type _AND
int dot)
{
char *save = buf;
if (invalue < 0)
{
invalue = -invalue;
}
if (invalue == 0)
{
*buf++ = '0';
*buf = '\0';
}
else
/* Which one to print ?
ANSI says that anything with more that 4 zeros after the . or more
than precision digits before is printed in e with the qualification
that trailing zeroes are removed from the fraction portion. */
if (0.0001 >= invalue || invalue >= _mprec_log10 (ndigit))
{
/* We subtract 1 from ndigit because in the 'e' format the precision is
the number of digits after the . but in 'g' format it is the number
of significant digits.
We defer changing type to e/E so that print_e() can know it's us
calling and thus should remove trailing zeroes. */
print_e (ptr, buf, invalue, ndigit - 1, type, dot);
}
else
{
int decpt;
int sign;
char *end;
char *p;
if (invalue < 1.0)
{
/* what we want is ndigits after the point */
p = _dtoa_r (ptr, invalue, 3, ndigit, &decpt, &sign, &end);
}
else
{
p = _dtoa_r (ptr, invalue, 2, ndigit, &decpt, &sign, &end);
}
if (decpt == 9999)
{
strcpy (buf, p);
return save;
}
while (*p && decpt > 0)
{
*buf++ = *p++;
decpt--;
ndigit--;
}
/* Even if not in buffer */
while (decpt > 0 && ndigit > 0)
{
*buf++ = '0';
decpt--;
ndigit--;
}
if (dot || *p)
{
if (buf == save)
*buf++ = '0';
*buf++ = '.';
while (decpt < 0 && ndigit > 0)
{
*buf++ = '0';
decpt++;
ndigit--;
}
/* Print rest of stuff */
while (*p && ndigit > 0)
{
*buf++ = *p++;
ndigit--;
}
/* And trailing zeros */
if (dot)
{
while (ndigit > 0)
{
*buf++ = '0';
ndigit--;
}
}
}
*buf++ = 0;
}
return save;
}
char *
_DEFUN (_dcvt, (ptr, buffer, invalue, precision, width, type, dot),
struct _reent *ptr _AND
char *buffer _AND
double invalue _AND
int precision _AND
int width _AND
char type _AND
int dot)
{
switch (type)
{
case 'f':
case 'F':
print_f (ptr, buffer, invalue, precision, type, precision == 0 ? dot : 1, 3);
break;
case 'g':
case 'G':
if (precision == 0)
precision = 1;
_gcvt (ptr, invalue, precision, buffer, type, dot);
break;
case 'e':
case 'E':
print_e (ptr, buffer, invalue, precision, type, dot);
}
return buffer;
}

202
libc/stdlib/efgcvt.c Normal file
View File

@@ -0,0 +1,202 @@
/*
FUNCTION
<<ecvt>>,<<ecvtf>>,<<fcvt>>,<<fcvtf>>---double or float to string
INDEX
ecvt
INDEX
fcvt
ANSI_SYNOPSIS
#include <stdlib.h>
char *ecvt(double <[val]>, int <[chars]>, int *<[decpt]>, int *<[sgn]>);
char *ecvtf(float <[val]>, int <[chars]>, int *<[decpt]>, int *<[sgn]>);
char *fcvt(double <[val]>, int <[decimals]>,
int *<[decpt]>, int *<[sgn]>);
char *fcvtf(float <[val]>, int <[decimals]>,
int *<[decpt]>, int *<[sgn]>);
TRAD_SYNOPSIS
#include <stdlib.h>
char *ecvt(<[val]>, <[chars]>, <[decpt]>, <[sgn]>);
double <[val]>;
int <[chars]>;
int *<[decpt]>;
int *<[sgn]>;
char *ecvtf(<[val]>, <[chars]>, <[decpt]>, <[sgn]>);
float <[val]>;
int <[chars]>;
int *<[decpt]>;
int *<[sgn]>;
char *fcvt(<[val]>, <[decimals]>, <[decpt]>, <[sgn]>);
double <[val]>;
int <[decimals]>;
int *<[decpt]>;
int *<[sgn]>;
char *fcvtf(<[val]>, <[decimals]>, <[decpt]>, <[sgn]>);
float <[val]>;
int <[decimals]>;
int *<[decpt]>;
int *<[sgn]>;
DESCRIPTION
<<ecvt>> and <<fcvt>> produce (null-terminated) strings of digits
representating the <<double>> number <[val]>.
<<ecvtf>> and <<fcvtf>> produce the corresponding character
representations of <<float>> numbers.
(The <<stdlib>> functions <<ecvtbuf>> and <<fcvtbuf>> are reentrant
versions of <<ecvt>> and <<fcvt>>.)
The only difference between <<ecvt>> and <<fcvt>> is the
interpretation of the second argument (<[chars]> or <[decimals]>).
For <<ecvt>>, the second argument <[chars]> specifies the total number
of characters to write (which is also the number of significant digits
in the formatted string, since these two functions write only digits).
For <<fcvt>>, the second argument <[decimals]> specifies the number of
characters to write after the decimal point; all digits for the integer
part of <[val]> are always included.
Since <<ecvt>> and <<fcvt>> write only digits in the output string,
they record the location of the decimal point in <<*<[decpt]>>>, and
the sign of the number in <<*<[sgn]>>>. After formatting a number,
<<*<[decpt]>>> contains the number of digits to the left of the
decimal point. <<*<[sgn]>>> contains <<0>> if the number is positive,
and <<1>> if it is negative.
RETURNS
All four functions return a pointer to the new string containing a
character representation of <[val]>.
PORTABILITY
None of these functions are ANSI C.
Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>,
<<lseek>>, <<read>>, <<sbrk>>, <<write>>.
NEWPAGE
FUNCTION
<<gvcvt>>, <<gcvtf>>---format double or float as string
INDEX
gcvt
INDEX
gcvtf
ANSI_SYNOPSIS
#include <stdlib.h>
char *gcvt(double <[val]>, int <[precision]>, char *<[buf]>);
char *gcvtf(float <[val]>, int <[precision]>, char *<[buf]>);
TRAD_SYNOPSIS
#include <stdlib.h>
char *gcvt(<[val]>, <[precision]>, <[buf]>);
double <[val]>;
int <[precision]>;
char *<[buf]>;
char *gcvtf(<[val]>, <[precision]>, <[buf]>);
float <[val]>;
int <[precision]>;
char *<[buf]>;
DESCRIPTION
<<gcvt>> writes a fully formatted number as a null-terminated
string in the buffer <<*<[buf]>>>. <<gdvtf>> produces corresponding
character representations of <<float>> numbers.
<<gcvt>> uses the same rules as the <<printf>> format
`<<%.<[precision]>g>>'---only negative values are signed (with
`<<->>'), and either exponential or ordinary decimal-fraction format
is chosen depending on the number of significant digits (specified by
<[precision]>).
RETURNS
The result is a pointer to the formatted representation of <[val]>
(the same as the argument <[buf]>).
PORTABILITY
Neither function is ANSI C.
Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>,
<<lseek>>, <<read>>, <<sbrk>>, <<write>>.
*/
#include <_ansi.h>
#include <reent.h>
#include <stdio.h>
#include <stdlib.h>
#include "local.h"
char *
_DEFUN (fcvt, (d, ndigit, decpt, sign),
double d _AND
int ndigit _AND
int *decpt _AND
int *sign)
{
return fcvtbuf (d, ndigit, decpt, sign, NULL);
}
char *
_DEFUN (fcvtf, (d, ndigit, decpt, sign),
float d _AND
int ndigit _AND
int *decpt _AND
int *sign)
{
return fcvt ((float) d, ndigit, decpt, sign);
}
char *
_DEFUN (gcvtf, (d, ndigit, buf),
float d _AND
int ndigit _AND
char *buf)
{
double asd = d;
return gcvt (asd, ndigit, buf);
}
char *
_DEFUN (ecvt, (d, ndigit, decpt, sign),
double d _AND
int ndigit _AND
int *decpt _AND
int *sign)
{
return ecvtbuf (d, ndigit, decpt, sign, NULL);
}
char *
_DEFUN (ecvtf, (d, ndigit, decpt, sign),
float d _AND
int ndigit _AND
int *decpt _AND
int *sign)
{
return ecvt ((double) d, ndigit, decpt, sign);
}
char *
_DEFUN (gcvt, (d, ndigit, buf),
double d _AND
int ndigit _AND
char *buf)
{
char *tbuf = buf;
if (d < 0) {
*buf = '-';
buf++;
ndigit--;
}
return (_gcvt (_REENT, d, ndigit, buf, 'g', 0) ? tbuf : 0);
}

23
libc/stdlib/environ.c Normal file
View File

@@ -0,0 +1,23 @@
/* Copyright (c) 1995, 1996 Cygnus Support.
* 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
* at Cygnus Support, Inc. Cygnus Support, Inc. 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 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
/* Provide a definition of `environ' if crt0.o doesn't. */
static char *initial_env[] = { 0 };
/* Posix says `environ' is a pointer to a null terminated list of pointers.
Hence `environ' itself is never NULL. */
char **environ = &initial_env[0];

26
libc/stdlib/eprintf.c Normal file
View File

@@ -0,0 +1,26 @@
/* This is an implementation of the __eprintf function which is
compatible with the assert.h which is distributed with gcc.
This function is provided because in some cases libgcc.a will not
provide __eprintf. This will happen if inhibit_libc is defined,
which is done because at the time that libgcc2.c is compiled, the
correct <stdio.h> may not be available. newlib provides its own
copy of assert.h, which calls __assert, not __eprintf. However, in
some cases you may accidentally wind up compiling with the gcc
assert.h. In such a case, this __eprintf will be used if there
does not happen to be one in libgcc2.c. */
#include <stdlib.h>
#include <stdio.h>
void
__eprintf (format, file, line, expression)
const char *format;
const char *file;
unsigned int line;
const char *expression;
{
(void) fiprintf (stderr, format, file, line, expression);
abort ();
/*NOTREACHED*/
}

73
libc/stdlib/exit.c Normal file
View File

@@ -0,0 +1,73 @@
/*
* Copyright (c) 1990 Regents of the University of California.
* All rights reserved.
*
* %sccs.include.redist.c%
*/
/*
FUNCTION
<<exit>>---end program execution
INDEX
exit
ANSI_SYNOPSIS
#include <stdlib.h>
void exit(int <[code]>);
TRAD_SYNOPSIS
#include <stdlib.h>
void exit(<[code]>)
int <[code]>;
DESCRIPTION
Use <<exit>> to return control from a program to the host operating
environment. Use the argument <[code]> to pass an exit status to the
operating environment: two particular values, <<EXIT_SUCCESS>> and
<<EXIT_FAILURE>>, are defined in `<<stdlib.h>>' to indicate success or
failure in a portable fashion.
<<exit>> does two kinds of cleanup before ending execution of your
program. First, it calls all application-defined cleanup functions
you have enrolled with <<atexit>>. Second, files and streams are
cleaned up: any pending output is delivered to the host system, each
open file or stream is closed, and files created by <<tmpfile>> are
deleted.
RETURNS
<<exit>> does not return to its caller.
PORTABILITY
ANSI C requires <<exit>>, and specifies that <<EXIT_SUCCESS>> and
<<EXIT_FAILURE>> must be defined.
Supporting OS subroutines required: <<_exit>>.
*/
#include <stdlib.h>
#include <unistd.h> /* for _exit() declaration */
#include <reent.h>
#ifndef _REENT_ONLY
/*
* Exit, flushing stdio buffers if necessary.
*/
void
_DEFUN (exit, (code),
int code)
{
register struct _atexit *p;
register int n;
for (p = _REENT->_atexit; p; p = p->_next)
for (n = p->_ind; --n >= 0;)
(*p->_fns[n]) ();
if (_REENT->__cleanup)
(*_REENT->__cleanup) (_REENT);
_exit (code);
}
#endif

121
libc/stdlib/getenv.c Normal file
View File

@@ -0,0 +1,121 @@
/*
FUNCTION
<<getenv>>---look up environment variable
INDEX
getenv
INDEX
environ
ANSI_SYNOPSIS
#include <stdlib.h>
char *getenv(const char *<[name]>);
TRAD_SYNOPSIS
#include <stdlib.h>
char *getenv(<[name]>)
char *<[name]>;
DESCRIPTION
<<getenv>> searches the list of environment variable names and values
(using the global pointer `<<char **environ>>') for a variable whose
name matches the string at <[name]>. If a variable name matches,
<<getenv>> returns a pointer to the associated value.
RETURNS
A pointer to the (string) value of the environment variable, or
<<NULL>> if there is no such environment variable.
PORTABILITY
<<getenv>> is ANSI, but the rules for properly forming names of environment
variables vary from one system to another.
<<getenv>> requires a global pointer <<environ>>.
*/
/* This file may have been modified by DJ Delorie (Jan 1991). If so,
** these modifications are Coyright (C) 1991 DJ Delorie, 24 Kirsten Ave,
** Rochester NH, 03867-2954, USA.
*/
/*
* Copyright (c) 1987 Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that: (1) source distributions retain this entire copyright
* notice and comment, and (2) distributions including binaries display
* the following acknowledgement: ``This product includes software
* developed by the University of California, Berkeley and its contributors''
* in the documentation or other materials provided with the distribution
* and in all advertising materials mentioning features or use of this
* software. 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
extern char **environ;
/*
* _findenv --
* Returns pointer to value associated with name, if any, else NULL.
* Sets offset to be the offset of the name/value combination in the
* environmental array, for use by setenv(3) and unsetenv(3).
* Explicitly removes '=' in argument name.
*
* This routine *should* be a static; don't use it.
*/
char *
_DEFUN (_findenv, (name, offset),
register _CONST char *name _AND
int *offset)
{
register int len;
register char **p;
_CONST char *c;
/* In some embedded systems, this does not get set. This protects
newlib from dereferencing a bad pointer. */
if (!environ)
return NULL;
c = name;
len = 0;
while (*c && *c != '=')
{
c++;
len++;
}
for (p = environ; *p; ++p)
if (!strncmp (*p, name, len))
if (*(c = *p + len) == '=')
{
*offset = p - environ;
return (char *) (++c);
}
return NULL;
}
/*
* getenv --
* Returns ptr to value associated with name, if any, else NULL.
*/
char *
_DEFUN (getenv, (name),
_CONST char *name)
{
int offset;
char *_findenv ();
return _findenv (name, &offset);
}

117
libc/stdlib/getopt.c Normal file
View File

@@ -0,0 +1,117 @@
/*
* Copyright (c) 1987, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* 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.
*/
#if defined(LIBC_SCCS) && !defined(lint)
/* static char sccsid[] = "from: @(#)getopt.c 8.2 (Berkeley) 4/2/94"; */
static char *rcsid = "$Id: getopt.c,v 1.2 1998/01/21 22:27:05 billm Exp $";
#endif /* LIBC_SCCS and not lint */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int opterr = 1, /* if error message should be printed */
optind = 1, /* index into parent argv vector */
optopt, /* character checked for validity */
optreset; /* reset getopt */
char *optarg; /* argument associated with option */
#define BADCH (int)'?'
#define BADARG (int)':'
#define EMSG ""
/*
* getopt --
* Parse argc/argv argument vector.
*/
int
getopt(nargc, nargv, ostr)
int nargc;
char * const *nargv;
const char *ostr;
{
static char *place = EMSG; /* option letter processing */
char *oli; /* option letter list index */
if (optreset || !*place) { /* update scanning pointer */
optreset = 0;
if (optind >= nargc || *(place = nargv[optind]) != '-') {
place = EMSG;
return (-1);
}
if (place[1] && *++place == '-') { /* found "--" */
++optind;
place = EMSG;
return (-1);
}
} /* option letter okay? */
if ((optopt = (int)*place++) == (int)':' ||
!(oli = strchr(ostr, optopt))) {
/*
* if the user didn't specify '-' as an option,
* assume it means -1.
*/
if (optopt == (int)'-')
return (-1);
if (!*place)
++optind;
if (opterr && *ostr != ':')
(void)fprintf(stderr,
"%s: illegal option -- %c\n", nargv[0], optopt);
return (BADCH);
}
if (*++oli != ':') { /* don't need argument */
optarg = NULL;
if (!*place)
++optind;
}
else { /* need an argument */
if (*place) /* no white space */
optarg = place;
else if (nargc <= ++optind) { /* no arg */
place = EMSG;
if (*ostr == ':')
return (BADARG);
if (opterr)
(void)fprintf(stderr,
"%s: option requires an argument -- %c\n",
nargv[0], optopt);
return (BADCH);
}
else /* white space */
optarg = nargv[optind];
place = EMSG;
++optind;
}
return (optopt); /* dump back option letter */
}

49
libc/stdlib/labs.c Normal file
View File

@@ -0,0 +1,49 @@
/*
FUNCTION
<<labs>>---long integer absolute value
INDEX
labs
ANSI_SYNOPSIS
#include <stdlib.h>
long labs(long <[i]>);
TRAD_SYNOPSIS
#include <stdlib.h>
long labs(<[i]>)
long <[i]>;
DESCRIPTION
<<labs>> returns
@tex
$|x|$,
@end tex
the absolute value of <[i]> (also called the magnitude
of <[i]>). That is, if <[i]> is negative, the result is the opposite
of <[i]>, but if <[i]> is nonnegative the result is <[i]>.
The similar function <<abs>> uses and returns <<int>> rather than
<<long>> values.
RETURNS
The result is a nonnegative long integer.
PORTABILITY
<<labs>> is ANSI.
No supporting OS subroutine calls are required.
*/
#include <stdlib.h>
long
_DEFUN (labs, (x),
long x)
{
if (x < 0)
{
x = -x;
}
return x;
}

109
libc/stdlib/ldiv.c Normal file
View File

@@ -0,0 +1,109 @@
/*
FUNCTION
<<ldiv>>---divide two long integers
INDEX
ldiv
ANSI_SYNOPSIS
#include <stdlib.h>
ldiv_t ldiv(long <[n]>, long <[d]>);
TRAD_SYNOPSIS
#include <stdlib.h>
ldiv_t ldiv(<[n]>, <[d]>)
long <[n]>, <[d]>;
DESCRIPTION
Divide
@tex
$n/d$,
@end tex
@ifinfo
<[n]>/<[d]>,
@end ifinfo
returning quotient and remainder as two long integers in a structure <<ldiv_t>>.
RETURNS
The result is represented with the structure
. typedef struct
. {
. long quot;
. long rem;
. } ldiv_t;
where the <<quot>> field represents the quotient, and <<rem>> the
remainder. For nonzero <[d]>, if `<<<[r]> = ldiv(<[n]>,<[d]>);>>' then
<[n]> equals `<<<[r]>.rem + <[d]>*<[r]>.quot>>'.
To divide <<int>> rather than <<long>> values, use the similar
function <<div>>.
PORTABILITY
<<ldiv>> is ANSI.
No supporting OS subroutines are required.
*/
/*
* 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 <_ansi.h>
#include <stdlib.h> /* ldiv_t */
ldiv_t
_DEFUN (ldiv, (num, denom),
long num _AND
long denom)
{
ldiv_t r;
/* see div.c for comments */
r.quot = num / denom;
r.rem = num % denom;
if (num >= 0 && r.rem < 0) {
++r.quot;
r.rem -= denom;
}
else if (num < 0 && r.rem > 0) {
--r.quot;
r.rem += denom;
}
return (r);
}

8
libc/stdlib/local.h Normal file
View File

@@ -0,0 +1,8 @@
/* Misc. local definitions for libc/stdlib */
#ifndef _LOCAL_H_
#define _LOCAL_H_
char * _EXFUN(_gcvt,(struct _reent *, double , int , char *, char, int));
#endif

18
libc/stdlib/malign.c Normal file
View File

@@ -0,0 +1,18 @@
/* malign.c -- a wrapper for memalign_r. */
#include <_ansi.h>
#include <reent.h>
#include <stdlib.h>
#include <malloc.h>
#ifndef _REENT_ONLY
_PTR
_DEFUN (memalign, (align, nbytes),
size_t align _AND
size_t nbytes)
{
return _memalign_r (_REENT, align, nbytes);
}
#endif

206
libc/stdlib/malloc.c Normal file
View File

@@ -0,0 +1,206 @@
/* VxWorks provides its own version of malloc, and we can't use this
one because VxWorks does not provide sbrk. So we have a hook to
not compile this code. */
/* The routines here are simple cover fns to the routines that do the real
work (the reentrant versions). */
/* FIXME: Does the warning below (see WARNINGS) about non-reentrancy still
apply? A first guess would be "no", but how about reentrancy in the *same*
thread? */
#ifdef MALLOC_PROVIDED
int _dummy_malloc = 1;
#else
/*
FUNCTION
<<malloc>>, <<realloc>>, <<free>>---manage memory
INDEX
malloc
INDEX
realloc
INDEX
free
INDEX
memalign
INDEX
malloc_usable_size
INDEX
_malloc_r
INDEX
_realloc_r
INDEX
_free_r
INDEX
_memalign_r
INDEX
_malloc_usable_size_r
ANSI_SYNOPSIS
#include <stdlib.h>
void *malloc(size_t <[nbytes]>);
void *realloc(void *<[aptr]>, size_t <[nbytes]>);
void free(void *<[aptr]>);
void *memalign(size_t <[align]>, size_t <[nbytes]>);
size_t malloc_usable_size(void *<[aptr]>);
void *_malloc_r(void *<[reent]>, size_t <[nbytes]>);
void *_realloc_r(void *<[reent]>,
void *<[aptr]>, size_t <[nbytes]>);
void _free_r(void *<[reent]>, void *<[aptr]>);
void *_memalign_r(void *<[reent]>,
size_t <[align]>, size_t <[nbytes]>);
size_t _malloc_usable_size_r(void *<[reent]>, void *<[aptr]>);
TRAD_SYNOPSIS
#include <stdlib.h>
char *malloc(<[nbytes]>)
size_t <[nbytes]>;
char *realloc(<[aptr]>, <[nbytes]>)
char *<[aptr]>;
size_t <[nbytes]>;
void free(<[aptr]>)
char *<[aptr]>;
char *memalign(<[align]>, <[nbytes]>)
size_t <[align]>;
size_t <[nbytes]>;
size_t malloc_usable_size(<[aptr]>)
char *<[aptr]>;
char *_malloc_r(<[reent]>,<[nbytes]>)
char *<[reent]>;
size_t <[nbytes]>;
char *_realloc_r(<[reent]>, <[aptr]>, <[nbytes]>)
char *<[reent]>;
char *<[aptr]>;
size_t <[nbytes]>;
void _free_r(<[reent]>, <[aptr]>)
char *<[reent]>;
char *<[aptr]>;
char *_memalign_r(<[reent]>, <[align]>, <[nbytes]>)
char *<[reent]>;
size_t <[align]>;
size_t <[nbytes]>;
size_t malloc_usable_size(<[reent]>, <[aptr]>)
char *<[reent]>;
char *<[aptr]>;
DESCRIPTION
These functions manage a pool of system memory.
Use <<malloc>> to request allocation of an object with at least
<[nbytes]> bytes of storage available. If the space is available,
<<malloc>> returns a pointer to a newly allocated block as its result.
If you already have a block of storage allocated by <<malloc>>, but
you no longer need all the space allocated to it, you can make it
smaller by calling <<realloc>> with both the object pointer and the
new desired size as arguments. <<realloc>> guarantees that the
contents of the smaller object match the beginning of the original object.
Similarly, if you need more space for an object, use <<realloc>> to
request the larger size; again, <<realloc>> guarantees that the
beginning of the new, larger object matches the contents of the
original object.
When you no longer need an object originally allocated by <<malloc>>
or <<realloc>> (or the related function <<calloc>>), return it to the
memory storage pool by calling <<free>> with the address of the object
as the argument. You can also use <<realloc>> for this purpose by
calling it with <<0>> as the <[nbytes]> argument.
The <<memalign>> function returns a block of size <[nbytes]> aligned
to a <[align]> boundary. The <[align]> argument must be a power of
two.
The <<malloc_usable_size>> function takes a pointer to a block
allocated by <<malloc>>. It returns the amount of space that is
available in the block. This may or may not be more than the size
requested from <<malloc>>, due to alignment or minimum size
constraints.
The alternate functions <<_malloc_r>>, <<_realloc_r>>, <<_free_r>>,
<<_memalign_r>>, and <<_malloc_usable_size_r>> are reentrant versions.
The extra argument <[reent]> is a pointer to a reentrancy structure.
If you have multiple threads of execution which may call any of these
routines, or if any of these routines may be called reentrantly, then
you must provide implementations of the <<__malloc_lock>> and
<<__malloc_unlock>> functions for your system. See the documentation
for those functions.
These functions operate by calling the function <<_sbrk_r>> or
<<sbrk>>, which allocates space. You may need to provide one of these
functions for your system. <<_sbrk_r>> is called with a positive
value to allocate more space, and with a negative value to release
previously allocated space if it is no longer required.
@xref{Stubs}.
RETURNS
<<malloc>> returns a pointer to the newly allocated space, if
successful; otherwise it returns <<NULL>>. If your application needs
to generate empty objects, you may use <<malloc(0)>> for this purpose.
<<realloc>> returns a pointer to the new block of memory, or <<NULL>>
if a new block could not be allocated. <<NULL>> is also the result
when you use `<<realloc(<[aptr]>,0)>>' (which has the same effect as
`<<free(<[aptr]>)>>'). You should always check the result of
<<realloc>>; successful reallocation is not guaranteed even when
you request a smaller object.
<<free>> does not return a result.
<<memalign>> returns a pointer to the newly allocated space.
<<malloc_usable_size>> returns the usable size.
PORTABILITY
<<malloc>>, <<realloc>>, and <<free>> are specified by the ANSI C
standard, but other conforming implementations of <<malloc>> may
behave differently when <[nbytes]> is zero.
<<memalign>> is part of SVR4.
<<malloc_usable_size>> is not portable.
Supporting OS subroutines required: <<sbrk>>. */
#include <_ansi.h>
#include <reent.h>
#include <stdlib.h>
#include <malloc.h>
#ifndef _REENT_ONLY
_PTR
_DEFUN (malloc, (nbytes),
size_t nbytes) /* get a block */
{
return _malloc_r (_REENT, nbytes);
}
void
_DEFUN (free, (aptr),
_PTR aptr)
{
_free_r (_REENT, aptr);
}
#endif
#endif /* ! defined (MALLOC_PROVIDED) */

3620
libc/stdlib/mallocr.c Normal file

File diff suppressed because it is too large Load Diff

20
libc/stdlib/mbctype.h Normal file
View File

@@ -0,0 +1,20 @@
#ifndef _MBCTYPE_H_
#define _MBCTYPE_H_
/* escape character used for JIS encoding */
#define ESC_CHAR 0x1b
/* functions used to support SHIFT_JIS, EUC-JP, and JIS multibyte encodings */
int _EXFUN(_issjis1, (int c));
int _EXFUN(_issjis2, (int c));
int _EXFUN(_iseucjp, (int c));
int _EXFUN(_isjis, (int c));
#define _issjis1(c) ((c) >= 0x81 && (c) <= 0x9f || (c) >= 0xe0 && (c) <= 0xef)
#define _issjis2(c) ((c) >= 0x40 && (c) <= 0x7e || (c) >= 0x80 && (c) <= 0xfc)
#define _iseucjp(c) ((c) >= 0xa1 && (c) <= 0xfe)
#define _isjis(c) ((c) >= 0x21 && (c) <= 0x7e)
#endif /* _MBCTYPE_H_ */

63
libc/stdlib/mblen.c Normal file
View File

@@ -0,0 +1,63 @@
/*
FUNCTION
<<mblen>>---minimal multibyte length function
INDEX
mblen
ANSI_SYNOPSIS
#include <stdlib.h>
int mblen(const char *<[s]>, size_t <[n]>);
TRAD_SYNOPSIS
#include <stdlib.h>
int mblen(<[s]>, <[n]>)
const char *<[s]>;
size_t <[n]>;
DESCRIPTION
When MB_CAPABLE is not defined, this is a minimal ANSI-conforming
implementation of <<mblen>>. In this case, the
only ``multi-byte character sequences'' recognized are single bytes,
and thus <<1>> is returned unless <[s]> is the null pointer or
has a length of 0 or is the empty string.
When MB_CAPABLE is defined, this routine calls <<_mbtowc_r>> to perform
the conversion, passing a state variable to allow state dependent
decoding. The result is based on the locale setting which may
be restricted to a defined set of locales.
RETURNS
This implementation of <<mblen>> returns <<0>> if
<[s]> is <<NULL>> or the empty string; it returns <<1>> if not MB_CAPABLE or
the character is a single-byte character; it returns <<-1>>
if the multi-byte character is invalid; otherwise it returns
the number of bytes in the multibyte character.
PORTABILITY
<<mblen>> is required in the ANSI C standard. However, the precise
effects vary with the locale.
<<mblen>> requires no supporting OS subroutines.
*/
#include <stdlib.h>
int
_DEFUN (mblen, (s, n),
const char *s _AND
size_t n)
{
#ifdef MB_CAPABLE
static int state;
return _mbtowc_r (_REENT, NULL, s, n, &state);
#else /* not MB_CAPABLE */
if (s == NULL || *s == '\0')
return 0;
if (n == 0)
return -1;
return 1;
#endif /* not MB_CAPABLE */
}

76
libc/stdlib/mbstowcs.c Normal file
View File

@@ -0,0 +1,76 @@
/*
FUNCTION
<<mbstowcs>>---minimal multibyte string to wide char converter
INDEX
mbstowcs
ANSI_SYNOPSIS
#include <stdlib.h>
int mbstowcs(wchar_t *<[pwc]>, const char *<[s]>, size_t <[n]>);
TRAD_SYNOPSIS
#include <stdlib.h>
int mbstowcs(<[pwc]>, <[s]>, <[n]>)
wchar_t *<[pwc]>;
const char *<[s]>;
size_t <[n]>;
DESCRIPTION
When MB_CAPABLE is not defined, this is a minimal ANSI-conforming
implementation of <<mbstowcs>>. In this case, the
only ``multi-byte character sequences'' recognized are single bytes,
and they are ``converted'' to wide-char versions simply by byte
extension.
When MB_CAPABLE is defined, this routine calls <<_mbstowcs_r>> to perform
the conversion, passing a state variable to allow state dependent
decoding. The result is based on the locale setting which may
be restricted to a defined set of locales.
RETURNS
This implementation of <<mbstowcs>> returns <<0>> if
<[s]> is <<NULL>> or is the empty string;
it returns <<-1>> if MB_CAPABLE and one of the
multi-byte characters is invalid or incomplete;
otherwise it returns the minimum of: <<n>> or the
number of multi-byte characters in <<s>> plus 1 (to
compensate for the nul character).
If the return value is -1, the state of the <<pwc>> string is
indeterminate. If the input has a length of 0, the output
string will be modified to contain a wchar_t nul terminator.
PORTABILITY
<<mbstowcs>> is required in the ANSI C standard. However, the precise
effects vary with the locale.
<<mbstowcs>> requires no supporting OS subroutines.
*/
#include <stdlib.h>
size_t
_DEFUN (mbstowcs, (pwcs, s, n),
wchar_t *pwcs _AND
const char *s _AND
size_t n)
{
#ifdef MB_CAPABLE
int state = 0;
return _mbstowcs_r (_REENT, pwcs, s, n, &state);
#else /* not MB_CAPABLE */
int count = 0;
if (n != 0) {
do {
if ((*pwcs++ = (wchar_t) *s++) == 0)
break;
count++;
} while (--n != 0);
}
return count;
#endif /* not MB_CAPABLE */
}

29
libc/stdlib/mbstowcs_r.c Normal file
View File

@@ -0,0 +1,29 @@
#include <stdlib.h>
size_t
_DEFUN (_mbstowcs_r, (reent, pwcs, s, n, state),
struct _reent *r _AND
wchar_t *pwcs _AND
const char *s _AND
size_t n _AND
int *state)
{
wchar_t *ptr = pwcs;
size_t max = n;
char *t = (char *)s;
int bytes;
while (n > 0)
{
bytes = _mbtowc_r (r, ptr, t, MB_CUR_MAX, state);
if (bytes == -1)
return -1;
else if (bytes == 0)
return ptr - pwcs;
t += bytes;
++ptr;
--n;
}
return max;
}

77
libc/stdlib/mbtowc.c Normal file
View File

@@ -0,0 +1,77 @@
/*
FUNCTION
<<mbtowc>>---minimal multibyte to wide char converter
INDEX
mbtowc
ANSI_SYNOPSIS
#include <stdlib.h>
int mbtowc(wchar_t *<[pwc]>, const char *<[s]>, size_t <[n]>);
TRAD_SYNOPSIS
#include <stdlib.h>
int mbtowc(<[pwc]>, <[s]>, <[n]>)
wchar_t *<[pwc]>;
const char *<[s]>;
size_t <[n]>;
DESCRIPTION
When MB_CAPABLE is not defined, this is a minimal ANSI-conforming
implementation of <<mbtowc>>. In this case,
only ``multi-byte character sequences'' recognized are single bytes,
and they are ``converted'' to themselves.
Each call to <<mbtowc>> copies one character from <<*<[s]>>> to
<<*<[pwc]>>>, unless <[s]> is a null pointer. The argument n
is ignored.
When MB_CAPABLE is defined, this routine calls <<_mbtowc_r>> to perform
the conversion, passing a state variable to allow state dependent
decoding. The result is based on the locale setting which may
be restricted to a defined set of locales.
RETURNS
This implementation of <<mbtowc>> returns <<0>> if
<[s]> is <<NULL>> or is the empty string;
it returns <<1>> if not MB_CAPABLE or
the character is a single-byte character; it returns <<-1>>
if n is <<0>> or the multi-byte character is invalid;
otherwise it returns the number of bytes in the multibyte character.
If the return value is -1, no changes are made to the <<pwc>>
output string. If the input is the empty string, a wchar_t nul
is placed in the output string and 0 is returned. If the input
has a length of 0, no changes are made to the <<pwc>> output string.
PORTABILITY
<<mbtowc>> is required in the ANSI C standard. However, the precise
effects vary with the locale.
<<mbtowc>> requires no supporting OS subroutines.
*/
#include <stdlib.h>
int
_DEFUN (mbtowc, (pwc, s, n),
wchar_t *pwc _AND
const char *s _AND
size_t n)
{
#ifdef MB_CAPABLE
static int state;
return _mbtowc_r (_REENT, pwc, s, n, &state);
#else /* not MB_CAPABLE */
if (s == NULL)
return 0;
if (n == 0)
return -1;
if (pwc)
*pwc = (wchar_t) *s;
return (*s != '\0');
#endif /* not MB_CAPABLE */
}

206
libc/stdlib/mbtowc_r.c Normal file
View File

@@ -0,0 +1,206 @@
#include <stdlib.h>
#include <locale.h>
#include "mbctype.h"
#ifdef MB_CAPABLE
typedef enum { ESCAPE, DOLLAR, BRACKET, AT, B, J,
NUL, JIS_CHAR, OTHER, JIS_C_NUM } JIS_CHAR_TYPE;
typedef enum { ASCII, A_ESC, A_ESC_DL, JIS, JIS_1, JIS_2, J_ESC, J_ESC_BR,
J2_ESC, J2_ESC_BR, DONE, INV, JIS_S_NUM } JIS_STATE;
typedef enum { COPY_A, COPY_J, COPY_J2, MAKE_A, MAKE_J, NOOP, EMPTY, ERROR } JIS_ACTION;
/**************************************************************************************
* state/action tables for processing JIS encoding
* Where possible, switches to JIS are grouped with proceding JIS characters and switches
* to ASCII are grouped with preceding JIS characters. Thus, maximum returned length
* is 2 (switch to JIS) + 2 (JIS characters) + 2 (switch back to ASCII) = 6.
*************************************************************************************/
static JIS_STATE JIS_state_table[JIS_S_NUM][JIS_C_NUM] = {
/* ESCAPE DOLLAR BRACKET AT B J NUL JIS_CHAR OTHER */
/* ASCII */ { A_ESC, DONE, DONE, DONE, DONE, DONE, DONE, DONE, DONE },
/* A_ESC */ { DONE, A_ESC_DL, DONE, DONE, DONE, DONE, DONE, DONE, DONE },
/* A_ESC_DL */{ DONE, DONE, DONE, JIS, JIS, DONE, DONE, DONE, DONE },
/* JIS */ { J_ESC, JIS_1, JIS_1, JIS_1, JIS_1, JIS_1, INV, JIS_1, INV },
/* JIS_1 */ { INV, JIS_2, JIS_2, JIS_2, JIS_2, JIS_2, INV, JIS_2, INV },
/* JIS_2 */ { J2_ESC, DONE, DONE, DONE, DONE, DONE, INV, DONE, DONE },
/* J_ESC */ { INV, INV, J_ESC_BR, INV, INV, INV, INV, INV, INV },
/* J_ESC_BR */{ INV, INV, INV, INV, ASCII, ASCII, INV, INV, INV },
/* J2_ESC */ { INV, INV, J2_ESC_BR,INV, INV, INV, INV, INV, INV },
/* J2_ESC_BR*/{ INV, INV, INV, INV, DONE, DONE, INV, INV, INV },
};
static JIS_ACTION JIS_action_table[JIS_S_NUM][JIS_C_NUM] = {
/* ESCAPE DOLLAR BRACKET AT B J NUL JIS_CHAR OTHER */
/* ASCII */ { NOOP, COPY_A, COPY_A, COPY_A, COPY_A, COPY_A, EMPTY, COPY_A, COPY_A},
/* A_ESC */ { COPY_A, NOOP, COPY_A, COPY_A, COPY_A, COPY_A, COPY_A, COPY_A, COPY_A},
/* A_ESC_DL */{ COPY_A, COPY_A, COPY_A, MAKE_J, MAKE_J, COPY_A, COPY_A, COPY_A, COPY_A},
/* JIS */ { NOOP, NOOP, NOOP, NOOP, NOOP, NOOP, ERROR, NOOP, ERROR },
/* JIS_1 */ { ERROR, NOOP, NOOP, NOOP, NOOP, NOOP, ERROR, NOOP, ERROR },
/* JIS_2 */ { NOOP, COPY_J2, COPY_J2, COPY_J2, COPY_J2, COPY_J2, ERROR, COPY_J2, COPY_J2},
/* J_ESC */ { ERROR, ERROR, NOOP, ERROR, ERROR, ERROR, ERROR, ERROR, ERROR },
/* J_ESC_BR */{ ERROR, ERROR, ERROR, ERROR, NOOP, NOOP, ERROR, ERROR, ERROR },
/* J2_ESC */ { ERROR, ERROR, NOOP, ERROR, ERROR, ERROR, ERROR, ERROR, ERROR },
/* J2_ESC_BR*/{ ERROR, ERROR, ERROR, ERROR, COPY_J, COPY_J, ERROR, ERROR, ERROR },
};
#endif /* MB_CAPABLE */
int
_DEFUN (_mbtowc_r, (r, pwc, s, n, state),
struct _reent *r _AND
wchar_t *pwc _AND
const char *s _AND
size_t n _AND
int *state)
{
wchar_t dummy;
unsigned char *t = (unsigned char *)s;
if (pwc == NULL)
pwc = &dummy;
if (s != NULL && n == 0)
return -1;
#ifdef MB_CAPABLE
if (r->_current_locale == NULL ||
(strlen (r->_current_locale) <= 1))
{ /* fall-through */ }
else if (!strcmp (r->_current_locale, "C-SJIS"))
{
int char1 = *t;
if (s == NULL)
return 0; /* not state-dependent */
if (_issjis1 (char1))
{
int char2 = t[1];
if (n <= 1)
return -1;
if (_issjis2 (char2))
{
*pwc = (((wchar_t)*t) << 8) + (wchar_t)(*(t+1));
return 2;
}
else
return -1;
}
}
else if (!strcmp (r->_current_locale, "C-EUCJP"))
{
int char1 = *t;
if (s == NULL)
return 0; /* not state-dependent */
if (_iseucjp (char1))
{
int char2 = t[1];
if (n <= 1)
return -1;
if (_iseucjp (char2))
{
*pwc = (((wchar_t)*t) << 8) + (wchar_t)(*(t+1));
return 2;
}
else
return -1;
}
}
else if (!strcmp (r->_current_locale, "C-JIS"))
{
JIS_STATE curr_state;
JIS_ACTION action;
JIS_CHAR_TYPE ch;
unsigned char *ptr;
int i, curr_ch;
if (s == NULL)
{
*state = 0;
return 1; /* state-dependent */
}
curr_state = (*state == 0 ? ASCII : JIS);
ptr = t;
for (i = 0; i < n; ++i)
{
curr_ch = t[i];
switch (curr_ch)
{
case ESC_CHAR:
ch = ESCAPE;
break;
case '$':
ch = DOLLAR;
break;
case '@':
ch = AT;
break;
case '(':
ch = BRACKET;
break;
case 'B':
ch = B;
break;
case 'J':
ch = J;
break;
case '\0':
ch = NUL;
break;
default:
if (_isjis (curr_ch))
ch = JIS_CHAR;
else
ch = OTHER;
}
action = JIS_action_table[curr_state][ch];
curr_state = JIS_state_table[curr_state][ch];
switch (action)
{
case NOOP:
break;
case EMPTY:
*state = 0;
*pwc = (wchar_t)0;
return i;
case COPY_A:
*state = 0;
*pwc = (wchar_t)*ptr;
return (i + 1);
case COPY_J:
*state = 0;
*pwc = (((wchar_t)*ptr) << 8) + (wchar_t)(*(ptr+1));
return (i + 1);
case COPY_J2:
*state = 1;
*pwc = (((wchar_t)*ptr) << 8) + (wchar_t)(*(ptr+1));
return (ptr - t) + 2;
case MAKE_A:
case MAKE_J:
ptr = (char *)(t + i + 1);
break;
case ERROR:
default:
return -1;
}
}
return -1; /* n < bytes needed */
}
#endif /* MB_CAPABLE */
/* otherwise this must be the "C" locale or unknown locale */
if (s == NULL)
return 0; /* not state-dependent */
*pwc = (wchar_t)*t;
if (*t == '\0')
return 0;
return 1;
}

50
libc/stdlib/mlock.c Normal file
View File

@@ -0,0 +1,50 @@
/*
FUNCTION
<<__malloc_lock>>, <<__malloc_unlock>>--lock malloc pool
INDEX
__malloc_lock
INDEX
__malloc_unlock
ANSI_SYNOPSIS
#include <malloc.h>
void __malloc_lock (void *<[reent]>);
void __malloc_unlock (void *<[reent]>);
TRAD_SYNOPSIS
void __malloc_lock(<[reent]>)
char *<[reent]>;
void __malloc_unlock(<[reent]>)
char *<[reent]>;
DESCRIPTION
The <<malloc>> family of routines call these functions when they need
to lock the memory pool. The version of these routines supplied in
the library does not do anything. If multiple threads of execution
can call <<malloc>>, or if <<malloc>> can be called reentrantly, then
you need to define your own versions of these functions in order to
safely lock the memory pool during a call. If you do not, the memory
pool may become corrupted.
A call to <<malloc>> may call <<__malloc_lock>> recursively; that is,
the sequence of calls may go <<__malloc_lock>>, <<__malloc_lock>>,
<<__malloc_unlock>>, <<__malloc_unlock>>. Any implementation of these
routines must be careful to avoid causing a thread to wait for a lock
that it already holds.
*/
#include <malloc.h>
void
__malloc_lock (ptr)
struct _reent *ptr;
{
}
void
__malloc_unlock (ptr)
struct _reent *ptr;
{
}

978
libc/stdlib/mprec.c Normal file
View File

@@ -0,0 +1,978 @@
/****************************************************************
*
* The author of this software is David M. Gay.
*
* Copyright (c) 1991 by AT&T.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software and in all copies of the supporting
* documentation for such software.
*
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR AT&T MAKES ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*
***************************************************************/
/* Please send bug reports to
David M. Gay
AT&T Bell Laboratories, Room 2C-463
600 Mountain Avenue
Murray Hill, NJ 07974-2070
U.S.A.
dmg@research.att.com or research!dmg
*/
/* strtod for IEEE-, VAX-, and IBM-arithmetic machines.
*
* This strtod returns a nearest machine number to the input decimal
* string (or sets errno to ERANGE). With IEEE arithmetic, ties are
* broken by the IEEE round-even rule. Otherwise ties are broken by
* biased rounding (add half and chop).
*
* Inspired loosely by William D. Clinger's paper "How to Read Floating
* Point Numbers Accurately" [Proc. ACM SIGPLAN '90, pp. 92-101].
*
* Modifications:
*
* 1. We only require IEEE, IBM, or VAX double-precision
* arithmetic (not IEEE double-extended).
* 2. We get by with floating-point arithmetic in a case that
* Clinger missed -- when we're computing d * 10^n
* for a small integer d and the integer n is not too
* much larger than 22 (the maximum integer k for which
* we can represent 10^k exactly), we may be able to
* compute (d*10^k) * 10^(e-k) with just one roundoff.
* 3. Rather than a bit-at-a-time adjustment of the binary
* result in the hard case, we use floating-point
* arithmetic to determine the adjustment to within
* one bit; only in really hard cases do we need to
* compute a second residual.
* 4. Because of 3., we don't need a large table of powers of 10
* for ten-to-e (just some small tables, e.g. of 10^k
* for 0 <= k <= 22).
*/
/*
* #define IEEE_8087 for IEEE-arithmetic machines where the least
* significant byte has the lowest address.
* #define IEEE_MC68k for IEEE-arithmetic machines where the most
* significant byte has the lowest address.
* #define Sudden_Underflow for IEEE-format machines without gradual
* underflow (i.e., that flush to zero on underflow).
* #define IBM for IBM mainframe-style floating-point arithmetic.
* #define VAX for VAX-style floating-point arithmetic.
* #define Unsigned_Shifts if >> does treats its left operand as unsigned.
* #define No_leftright to omit left-right logic in fast floating-point
* computation of dtoa.
* #define Check_FLT_ROUNDS if FLT_ROUNDS can assume the values 2 or 3.
* #define RND_PRODQUOT to use rnd_prod and rnd_quot (assembly routines
* that use extended-precision instructions to compute rounded
* products and quotients) with IBM.
* #define ROUND_BIASED for IEEE-format with biased rounding.
* #define Inaccurate_Divide for IEEE-format with correctly rounded
* products but inaccurate quotients, e.g., for Intel i860.
* #define Just_16 to store 16 bits per 32-bit long when doing high-precision
* integer arithmetic. Whether this speeds things up or slows things
* down depends on the machine and the number being converted.
*/
#include <_ansi.h>
#include <stdlib.h>
#include <string.h>
#include <reent.h>
#include "mprec.h"
/* reent.c knows this value */
#define _Kmax 15
_Bigint *
_DEFUN (Balloc, (ptr, k), struct _reent *ptr _AND int k)
{
int x;
_Bigint *rv ;
if (ptr->_freelist == NULL)
{
/* Allocate a list of pointers to the mprec objects */
ptr->_freelist = (struct _Bigint **) _calloc_r (ptr,
sizeof (struct _Bigint *),
_Kmax + 1);
if (ptr->_freelist == NULL)
{
return NULL;
}
}
if (rv = ptr->_freelist[k])
{
ptr->_freelist[k] = rv->_next;
}
else
{
x = 1 << k;
/* Allocate an mprec Bigint and stick in in the freelist */
rv = (_Bigint *) _calloc_r (ptr,
1,
sizeof (_Bigint) +
(x-1) * sizeof(rv->_x));
if (rv == NULL) return NULL;
rv->_k = k;
rv->_maxwds = x;
}
rv->_sign = rv->_wds = 0;
return rv;
}
void
_DEFUN (Bfree, (ptr, v), struct _reent *ptr _AND _Bigint * v)
{
if (v)
{
v->_next = ptr->_freelist[v->_k];
ptr->_freelist[v->_k] = v;
}
}
_Bigint *
_DEFUN (multadd, (ptr, b, m, a),
struct _reent *ptr _AND
_Bigint * b _AND
int m _AND
int a)
{
int i, wds;
ULong *x, y;
#ifdef Pack_32
ULong xi, z;
#endif
_Bigint *b1;
wds = b->_wds;
x = b->_x;
i = 0;
do
{
#ifdef Pack_32
xi = *x;
y = (xi & 0xffff) * m + a;
z = (xi >> 16) * m + (y >> 16);
a = (int) (z >> 16);
*x++ = (z << 16) + (y & 0xffff);
#else
y = *x * m + a;
a = (int) (y >> 16);
*x++ = y & 0xffff;
#endif
}
while (++i < wds);
if (a)
{
if (wds >= b->_maxwds)
{
b1 = Balloc (ptr, b->_k + 1);
Bcopy (b1, b);
Bfree (ptr, b);
b = b1;
}
b->_x[wds++] = a;
b->_wds = wds;
}
return b;
}
_Bigint *
_DEFUN (s2b, (ptr, s, nd0, nd, y9),
struct _reent * ptr _AND
_CONST char *s _AND
int nd0 _AND
int nd _AND
ULong y9)
{
_Bigint *b;
int i, k;
Long x, y;
x = (nd + 8) / 9;
for (k = 0, y = 1; x > y; y <<= 1, k++);
#ifdef Pack_32
b = Balloc (ptr, k);
b->_x[0] = y9;
b->_wds = 1;
#else
b = Balloc (ptr, k + 1);
b->_x[0] = y9 & 0xffff;
b->_wds = (b->_x[1] = y9 >> 16) ? 2 : 1;
#endif
i = 9;
if (9 < nd0)
{
s += 9;
do
b = multadd (ptr, b, 10, *s++ - '0');
while (++i < nd0);
s++;
}
else
s += 10;
for (; i < nd; i++)
b = multadd (ptr, b, 10, *s++ - '0');
return b;
}
int
_DEFUN (hi0bits,
(x), register ULong x)
{
register int k = 0;
if (!(x & 0xffff0000))
{
k = 16;
x <<= 16;
}
if (!(x & 0xff000000))
{
k += 8;
x <<= 8;
}
if (!(x & 0xf0000000))
{
k += 4;
x <<= 4;
}
if (!(x & 0xc0000000))
{
k += 2;
x <<= 2;
}
if (!(x & 0x80000000))
{
k++;
if (!(x & 0x40000000))
return 32;
}
return k;
}
int
_DEFUN (lo0bits, (y), ULong *y)
{
register int k;
register ULong x = *y;
if (x & 7)
{
if (x & 1)
return 0;
if (x & 2)
{
*y = x >> 1;
return 1;
}
*y = x >> 2;
return 2;
}
k = 0;
if (!(x & 0xffff))
{
k = 16;
x >>= 16;
}
if (!(x & 0xff))
{
k += 8;
x >>= 8;
}
if (!(x & 0xf))
{
k += 4;
x >>= 4;
}
if (!(x & 0x3))
{
k += 2;
x >>= 2;
}
if (!(x & 1))
{
k++;
x >>= 1;
if (!x & 1)
return 32;
}
*y = x;
return k;
}
_Bigint *
_DEFUN (i2b, (ptr, i), struct _reent * ptr _AND int i)
{
_Bigint *b;
b = Balloc (ptr, 1);
b->_x[0] = i;
b->_wds = 1;
return b;
}
_Bigint *
_DEFUN (mult, (ptr, a, b), struct _reent * ptr _AND _Bigint * a _AND _Bigint * b)
{
_Bigint *c;
int k, wa, wb, wc;
ULong carry, y, z;
ULong *x, *xa, *xae, *xb, *xbe, *xc, *xc0;
#ifdef Pack_32
ULong z2;
#endif
if (a->_wds < b->_wds)
{
c = a;
a = b;
b = c;
}
k = a->_k;
wa = a->_wds;
wb = b->_wds;
wc = wa + wb;
if (wc > a->_maxwds)
k++;
c = Balloc (ptr, k);
for (x = c->_x, xa = x + wc; x < xa; x++)
*x = 0;
xa = a->_x;
xae = xa + wa;
xb = b->_x;
xbe = xb + wb;
xc0 = c->_x;
#ifdef Pack_32
for (; xb < xbe; xb++, xc0++)
{
if (y = *xb & 0xffff)
{
x = xa;
xc = xc0;
carry = 0;
do
{
z = (*x & 0xffff) * y + (*xc & 0xffff) + carry;
carry = z >> 16;
z2 = (*x++ >> 16) * y + (*xc >> 16) + carry;
carry = z2 >> 16;
Storeinc (xc, z2, z);
}
while (x < xae);
*xc = carry;
}
if (y = *xb >> 16)
{
x = xa;
xc = xc0;
carry = 0;
z2 = *xc;
do
{
z = (*x & 0xffff) * y + (*xc >> 16) + carry;
carry = z >> 16;
Storeinc (xc, z, z2);
z2 = (*x++ >> 16) * y + (*xc & 0xffff) + carry;
carry = z2 >> 16;
}
while (x < xae);
*xc = z2;
}
}
#else
for (; xb < xbe; xc0++)
{
if (y = *xb++)
{
x = xa;
xc = xc0;
carry = 0;
do
{
z = *x++ * y + *xc + carry;
carry = z >> 16;
*xc++ = z & 0xffff;
}
while (x < xae);
*xc = carry;
}
}
#endif
for (xc0 = c->_x, xc = xc0 + wc; wc > 0 && !*--xc; --wc);
c->_wds = wc;
return c;
}
_Bigint *
_DEFUN (pow5mult,
(ptr, b, k), struct _reent * ptr _AND _Bigint * b _AND int k)
{
_Bigint *b1, *p5, *p51;
int i;
static _CONST int p05[3] = {5, 25, 125};
if (i = k & 3)
b = multadd (ptr, b, p05[i - 1], 0);
if (!(k >>= 2))
return b;
if (!(p5 = ptr->_p5s))
{
/* first time */
p5 = ptr->_p5s = i2b (ptr, 625);
p5->_next = 0;
}
for (;;)
{
if (k & 1)
{
b1 = mult (ptr, b, p5);
Bfree (ptr, b);
b = b1;
}
if (!(k >>= 1))
break;
if (!(p51 = p5->_next))
{
p51 = p5->_next = mult (ptr, p5, p5);
p51->_next = 0;
}
p5 = p51;
}
return b;
}
_Bigint *
_DEFUN (lshift, (ptr, b, k), struct _reent * ptr _AND _Bigint * b _AND int k)
{
int i, k1, n, n1;
_Bigint *b1;
ULong *x, *x1, *xe, z;
#ifdef Pack_32
n = k >> 5;
#else
n = k >> 4;
#endif
k1 = b->_k;
n1 = n + b->_wds + 1;
for (i = b->_maxwds; n1 > i; i <<= 1)
k1++;
b1 = Balloc (ptr, k1);
x1 = b1->_x;
for (i = 0; i < n; i++)
*x1++ = 0;
x = b->_x;
xe = x + b->_wds;
#ifdef Pack_32
if (k &= 0x1f)
{
k1 = 32 - k;
z = 0;
do
{
*x1++ = *x << k | z;
z = *x++ >> k1;
}
while (x < xe);
if (*x1 = z)
++n1;
}
#else
if (k &= 0xf)
{
k1 = 16 - k;
z = 0;
do
{
*x1++ = *x << k & 0xffff | z;
z = *x++ >> k1;
}
while (x < xe);
if (*x1 = z)
++n1;
}
#endif
else
do
*x1++ = *x++;
while (x < xe);
b1->_wds = n1 - 1;
Bfree (ptr, b);
return b1;
}
int
_DEFUN (cmp, (a, b), _Bigint * a _AND _Bigint * b)
{
ULong *xa, *xa0, *xb, *xb0;
int i, j;
i = a->_wds;
j = b->_wds;
#ifdef DEBUG
if (i > 1 && !a->_x[i - 1])
Bug ("cmp called with a->_x[a->_wds-1] == 0");
if (j > 1 && !b->_x[j - 1])
Bug ("cmp called with b->_x[b->_wds-1] == 0");
#endif
if (i -= j)
return i;
xa0 = a->_x;
xa = xa0 + j;
xb0 = b->_x;
xb = xb0 + j;
for (;;)
{
if (*--xa != *--xb)
return *xa < *xb ? -1 : 1;
if (xa <= xa0)
break;
}
return 0;
}
_Bigint *
_DEFUN (diff, (ptr, a, b), struct _reent * ptr _AND
_Bigint * a _AND _Bigint * b)
{
_Bigint *c;
int i, wa, wb;
Long borrow, y; /* We need signed shifts here. */
ULong *xa, *xae, *xb, *xbe, *xc;
#ifdef Pack_32
Long z;
#endif
i = cmp (a, b);
if (!i)
{
c = Balloc (ptr, 0);
c->_wds = 1;
c->_x[0] = 0;
return c;
}
if (i < 0)
{
c = a;
a = b;
b = c;
i = 1;
}
else
i = 0;
c = Balloc (ptr, a->_k);
c->_sign = i;
wa = a->_wds;
xa = a->_x;
xae = xa + wa;
wb = b->_wds;
xb = b->_x;
xbe = xb + wb;
xc = c->_x;
borrow = 0;
#ifdef Pack_32
do
{
y = (*xa & 0xffff) - (*xb & 0xffff) + borrow;
borrow = y >> 16;
Sign_Extend (borrow, y);
z = (*xa++ >> 16) - (*xb++ >> 16) + borrow;
borrow = z >> 16;
Sign_Extend (borrow, z);
Storeinc (xc, z, y);
}
while (xb < xbe);
while (xa < xae)
{
y = (*xa & 0xffff) + borrow;
borrow = y >> 16;
Sign_Extend (borrow, y);
z = (*xa++ >> 16) + borrow;
borrow = z >> 16;
Sign_Extend (borrow, z);
Storeinc (xc, z, y);
}
#else
do
{
y = *xa++ - *xb++ + borrow;
borrow = y >> 16;
Sign_Extend (borrow, y);
*xc++ = y & 0xffff;
}
while (xb < xbe);
while (xa < xae)
{
y = *xa++ + borrow;
borrow = y >> 16;
Sign_Extend (borrow, y);
*xc++ = y & 0xffff;
}
#endif
while (!*--xc)
wa--;
c->_wds = wa;
return c;
}
double
_DEFUN (ulp, (_x), double _x)
{
union double_union x, a;
register Long L;
x.d = _x;
L = (word0 (x) & Exp_mask) - (P - 1) * Exp_msk1;
#ifndef Sudden_Underflow
if (L > 0)
{
#endif
#ifdef IBM
L |= Exp_msk1 >> 4;
#endif
word0 (a) = L;
#ifndef _DOUBLE_IS_32BITS
word1 (a) = 0;
#endif
#ifndef Sudden_Underflow
}
else
{
L = -L >> Exp_shift;
if (L < Exp_shift)
{
word0 (a) = 0x80000 >> L;
#ifndef _DOUBLE_IS_32BITS
word1 (a) = 0;
#endif
}
else
{
word0 (a) = 0;
L -= Exp_shift;
#ifndef _DOUBLE_IS_32BITS
word1 (a) = L >= 31 ? 1 : 1 << 31 - L;
#endif
}
}
#endif
return a.d;
}
double
_DEFUN (b2d, (a, e),
_Bigint * a _AND int *e)
{
ULong *xa, *xa0, w, y, z;
int k;
union double_union d;
#ifdef VAX
ULong d0, d1;
#else
#define d0 word0(d)
#define d1 word1(d)
#endif
xa0 = a->_x;
xa = xa0 + a->_wds;
y = *--xa;
#ifdef DEBUG
if (!y)
Bug ("zero y in b2d");
#endif
k = hi0bits (y);
*e = 32 - k;
#ifdef Pack_32
if (k < Ebits)
{
d0 = Exp_1 | y >> Ebits - k;
w = xa > xa0 ? *--xa : 0;
#ifndef _DOUBLE_IS_32BITS
d1 = y << (32 - Ebits) + k | w >> Ebits - k;
#endif
goto ret_d;
}
z = xa > xa0 ? *--xa : 0;
if (k -= Ebits)
{
d0 = Exp_1 | y << k | z >> 32 - k;
y = xa > xa0 ? *--xa : 0;
#ifndef _DOUBLE_IS_32BITS
d1 = z << k | y >> 32 - k;
#endif
}
else
{
d0 = Exp_1 | y;
#ifndef _DOUBLE_IS_32BITS
d1 = z;
#endif
}
#else
if (k < Ebits + 16)
{
z = xa > xa0 ? *--xa : 0;
d0 = Exp_1 | y << k - Ebits | z >> Ebits + 16 - k;
w = xa > xa0 ? *--xa : 0;
y = xa > xa0 ? *--xa : 0;
d1 = z << k + 16 - Ebits | w << k - Ebits | y >> 16 + Ebits - k;
goto ret_d;
}
z = xa > xa0 ? *--xa : 0;
w = xa > xa0 ? *--xa : 0;
k -= Ebits + 16;
d0 = Exp_1 | y << k + 16 | z << k | w >> 16 - k;
y = xa > xa0 ? *--xa : 0;
d1 = w << k + 16 | y << k;
#endif
ret_d:
#ifdef VAX
word0 (d) = d0 >> 16 | d0 << 16;
word1 (d) = d1 >> 16 | d1 << 16;
#else
#undef d0
#undef d1
#endif
return d.d;
}
_Bigint *
_DEFUN (d2b,
(ptr, _d, e, bits),
struct _reent * ptr _AND
double _d _AND
int *e _AND
int *bits)
{
union double_union d;
_Bigint *b;
int de, i, k;
ULong *x, y, z;
#ifdef VAX
ULong d0, d1;
d.d = _d;
d0 = word0 (d) >> 16 | word0 (d) << 16;
d1 = word1 (d) >> 16 | word1 (d) << 16;
#else
#define d0 word0(d)
#define d1 word1(d)
d.d = _d;
#endif
#ifdef Pack_32
b = Balloc (ptr, 1);
#else
b = Balloc (ptr, 2);
#endif
x = b->_x;
z = d0 & Frac_mask;
d0 &= 0x7fffffff; /* clear sign bit, which we ignore */
#ifdef Sudden_Underflow
de = (int) (d0 >> Exp_shift);
#ifndef IBM
z |= Exp_msk11;
#endif
#else
if (de = (int) (d0 >> Exp_shift))
z |= Exp_msk1;
#endif
#ifdef Pack_32
#ifndef _DOUBLE_IS_32BITS
if (y = d1)
{
if (k = lo0bits (&y))
{
x[0] = y | z << 32 - k;
z >>= k;
}
else
x[0] = y;
i = b->_wds = (x[1] = z) ? 2 : 1;
}
else
#endif
{
#ifdef DEBUG
if (!z)
Bug ("Zero passed to d2b");
#endif
k = lo0bits (&z);
x[0] = z;
i = b->_wds = 1;
#ifndef _DOUBLE_IS_32BITS
k += 32;
#endif
}
#else
if (y = d1)
{
if (k = lo0bits (&y))
if (k >= 16)
{
x[0] = y | z << 32 - k & 0xffff;
x[1] = z >> k - 16 & 0xffff;
x[2] = z >> k;
i = 2;
}
else
{
x[0] = y & 0xffff;
x[1] = y >> 16 | z << 16 - k & 0xffff;
x[2] = z >> k & 0xffff;
x[3] = z >> k + 16;
i = 3;
}
else
{
x[0] = y & 0xffff;
x[1] = y >> 16;
x[2] = z & 0xffff;
x[3] = z >> 16;
i = 3;
}
}
else
{
#ifdef DEBUG
if (!z)
Bug ("Zero passed to d2b");
#endif
k = lo0bits (&z);
if (k >= 16)
{
x[0] = z;
i = 0;
}
else
{
x[0] = z & 0xffff;
x[1] = z >> 16;
i = 1;
}
k += 32;
}
while (!x[i])
--i;
b->_wds = i + 1;
#endif
#ifndef Sudden_Underflow
if (de)
{
#endif
#ifdef IBM
*e = (de - Bias - (P - 1) << 2) + k;
*bits = 4 * P + 8 - k - hi0bits (word0 (d) & Frac_mask);
#else
*e = de - Bias - (P - 1) + k;
*bits = P - k;
#endif
#ifndef Sudden_Underflow
}
else
{
*e = de - Bias - (P - 1) + 1 + k;
#ifdef Pack_32
*bits = 32 * i - hi0bits (x[i - 1]);
#else
*bits = (i + 2) * 16 - hi0bits (x[i]);
#endif
}
#endif
return b;
}
#undef d0
#undef d1
double
_DEFUN (ratio, (a, b), _Bigint * a _AND _Bigint * b)
{
union double_union da, db;
int k, ka, kb;
da.d = b2d (a, &ka);
db.d = b2d (b, &kb);
#ifdef Pack_32
k = ka - kb + 32 * (a->_wds - b->_wds);
#else
k = ka - kb + 16 * (a->_wds - b->_wds);
#endif
#ifdef IBM
if (k > 0)
{
word0 (da) += (k >> 2) * Exp_msk1;
if (k &= 3)
da.d *= 1 << k;
}
else
{
k = -k;
word0 (db) += (k >> 2) * Exp_msk1;
if (k &= 3)
db.d *= 1 << k;
}
#else
if (k > 0)
word0 (da) += k * Exp_msk1;
else
{
k = -k;
word0 (db) += k * Exp_msk1;
}
#endif
return da.d / db.d;
}
_CONST double
tens[] =
{
1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
1e20, 1e21, 1e22, 1e23, 1e24
};
#if !defined(_DOUBLE_IS_32BITS) && !defined(__v800)
_CONST double bigtens[] =
{1e16, 1e32, 1e64, 1e128, 1e256};
_CONST double tinytens[] =
{1e-16, 1e-32, 1e-64, 1e-128, 1e-256};
#else
_CONST double bigtens[] =
{1e16, 1e32};
_CONST double tinytens[] =
{1e-16, 1e-32};
#endif
double
_DEFUN (_mprec_log10, (dig),
int dig)
{
double v = 1.0;
if (dig < 24)
return tens[dig];
while (dig > 0)
{
v *= 10;
dig--;
}
return v;
}

313
libc/stdlib/mprec.h Normal file
View File

@@ -0,0 +1,313 @@
/****************************************************************
*
* The author of this software is David M. Gay.
*
* Copyright (c) 1991 by AT&T.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software and in all copies of the supporting
* documentation for such software.
*
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR AT&T MAKES ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*
***************************************************************/
/* Please send bug reports to
David M. Gay
AT&T Bell Laboratories, Room 2C-463
600 Mountain Avenue
Murray Hill, NJ 07974-2070
U.S.A.
dmg@research.att.com or research!dmg
*/
#include <ieeefp.h>
#include <math.h>
#include <float.h>
#include <errno.h>
#include <sys/config.h>
#ifdef __IEEE_LITTLE_ENDIAN
#define IEEE_8087
#endif
#ifdef __IEEE_BIG_ENDIAN
#define IEEE_MC68k
#endif
#ifdef __Z8000__
#define Just_16
#endif
#ifdef DEBUG
#include "stdio.h"
#define Bug(x) {fprintf(stderr, "%s\n", x); exit(1);}
#endif
#ifdef Unsigned_Shifts
#define Sign_Extend(a,b) if (b < 0) a |= (__uint32_t)0xffff0000;
#else
#define Sign_Extend(a,b) /*no-op*/
#endif
#if defined(IEEE_8087) + defined(IEEE_MC68k) + defined(VAX) + defined(IBM) != 1
Exactly one of IEEE_8087, IEEE_MC68k, VAX, or IBM should be defined.
#endif
/* If we are going to examine or modify specific bits in a double using
the word0 and/or word1 macros, then we must wrap the double inside
a union. This is necessary to avoid undefined behavior according to
the ANSI C spec. */
union double_union
{
double d;
__uint32_t i[2];
};
#ifdef IEEE_8087
#define word0(x) (x.i[1])
#define word1(x) (x.i[0])
#else
#define word0(x) (x.i[0])
#define word1(x) (x.i[1])
#endif
/* The following definition of Storeinc is appropriate for MIPS processors.
* An alternative that might be better on some machines is
* #define Storeinc(a,b,c) (*a++ = b << 16 | c & 0xffff)
*/
#if defined(IEEE_8087) + defined(VAX)
#define Storeinc(a,b,c) (((unsigned short *)a)[1] = (unsigned short)b, \
((unsigned short *)a)[0] = (unsigned short)c, a++)
#else
#define Storeinc(a,b,c) (((unsigned short *)a)[0] = (unsigned short)b, \
((unsigned short *)a)[1] = (unsigned short)c, a++)
#endif
/* #define P DBL_MANT_DIG */
/* Ten_pmax = floor(P*log(2)/log(5)) */
/* Bletch = (highest power of 2 < DBL_MAX_10_EXP) / 16 */
/* Quick_max = floor((P-1)*log(FLT_RADIX)/log(10) - 1) */
/* Int_max = floor(P*log(FLT_RADIX)/log(10) - 1) */
#if defined(IEEE_8087) + defined(IEEE_MC68k)
#if defined (_DOUBLE_IS_32BITS)
#define Exp_shift 23
#define Exp_shift1 23
#define Exp_msk1 ((__uint32_t)0x00800000L)
#define Exp_msk11 ((__uint32_t)0x00800000L)
#define Exp_mask ((__uint32_t)0x7f800000L)
#define P 24
#define Bias 127
#if 0
#define IEEE_Arith /* it is, but the code doesn't handle IEEE singles yet */
#endif
#define Emin (-126)
#define Exp_1 ((__uint32_t)0x3f800000L)
#define Exp_11 ((__uint32_t)0x3f800000L)
#define Ebits 8
#define Frac_mask ((__uint32_t)0x007fffffL)
#define Frac_mask1 ((__uint32_t)0x007fffffL)
#define Ten_pmax 10
#define Sign_bit ((__uint32_t)0x80000000L)
#define Ten_pmax 10
#define Bletch 2
#define Bndry_mask ((__uint32_t)0x007fffffL)
#define Bndry_mask1 ((__uint32_t)0x007fffffL)
#define LSB 1
#define Sign_bit ((__uint32_t)0x80000000L)
#define Log2P 1
#define Tiny0 0
#define Tiny1 1
#define Quick_max 5
#define Int_max 6
#define Infinite(x) (word0(x) == ((__uint32_t)0x7f800000L))
#undef word0
#undef word1
#define word0(x) (x.i[0])
#define word1(x) 0
#else
#define Exp_shift 20
#define Exp_shift1 20
#define Exp_msk1 ((__uint32_t)0x100000L)
#define Exp_msk11 ((__uint32_t)0x100000L)
#define Exp_mask ((__uint32_t)0x7ff00000L)
#define P 53
#define Bias 1023
#define IEEE_Arith
#define Emin (-1022)
#define Exp_1 ((__uint32_t)0x3ff00000L)
#define Exp_11 ((__uint32_t)0x3ff00000L)
#define Ebits 11
#define Frac_mask ((__uint32_t)0xfffffL)
#define Frac_mask1 ((__uint32_t)0xfffffL)
#define Ten_pmax 22
#define Bletch 0x10
#define Bndry_mask ((__uint32_t)0xfffffL)
#define Bndry_mask1 ((__uint32_t)0xfffffL)
#define LSB 1
#define Sign_bit ((__uint32_t)0x80000000L)
#define Log2P 1
#define Tiny0 0
#define Tiny1 1
#define Quick_max 14
#define Int_max 14
#define Infinite(x) (word0(x) == ((__uint32_t)0x7ff00000L)) /* sufficient test for here */
#endif
#else
#undef Sudden_Underflow
#define Sudden_Underflow
#ifdef IBM
#define Exp_shift 24
#define Exp_shift1 24
#define Exp_msk1 ((__uint32_t)0x1000000L)
#define Exp_msk11 ((__uint32_t)0x1000000L)
#define Exp_mask ((__uint32_t)0x7f000000L)
#define P 14
#define Bias 65
#define Exp_1 ((__uint32_t)0x41000000L)
#define Exp_11 ((__uint32_t)0x41000000L)
#define Ebits 8 /* exponent has 7 bits, but 8 is the right value in b2d */
#define Frac_mask ((__uint32_t)0xffffffL)
#define Frac_mask1 ((__uint32_t)0xffffffL)
#define Bletch 4
#define Ten_pmax 22
#define Bndry_mask ((__uint32_t)0xefffffL)
#define Bndry_mask1 ((__uint32_t)0xffffffL)
#define LSB 1
#define Sign_bit ((__uint32_t)0x80000000L)
#define Log2P 4
#define Tiny0 ((__uint32_t)0x100000L)
#define Tiny1 0
#define Quick_max 14
#define Int_max 15
#else /* VAX */
#define Exp_shift 23
#define Exp_shift1 7
#define Exp_msk1 0x80
#define Exp_msk11 ((__uint32_t)0x800000L)
#define Exp_mask ((__uint32_t)0x7f80L)
#define P 56
#define Bias 129
#define Exp_1 ((__uint32_t)0x40800000L)
#define Exp_11 ((__uint32_t)0x4080L)
#define Ebits 8
#define Frac_mask ((__uint32_t)0x7fffffL)
#define Frac_mask1 ((__uint32_t)0xffff007fL)
#define Ten_pmax 24
#define Bletch 2
#define Bndry_mask ((__uint32_t)0xffff007fL)
#define Bndry_mask1 ((__uint32_t)0xffff007fL)
#define LSB ((__uint32_t)0x10000L)
#define Sign_bit ((__uint32_t)0x8000L)
#define Log2P 1
#define Tiny0 0x80
#define Tiny1 0
#define Quick_max 15
#define Int_max 15
#endif
#endif
#ifndef IEEE_Arith
#define ROUND_BIASED
#endif
#ifdef RND_PRODQUOT
#define rounded_product(a,b) a = rnd_prod(a, b)
#define rounded_quotient(a,b) a = rnd_quot(a, b)
#ifdef KR_headers
extern double rnd_prod(), rnd_quot();
#else
extern double rnd_prod(double, double), rnd_quot(double, double);
#endif
#else
#define rounded_product(a,b) a *= b
#define rounded_quotient(a,b) a /= b
#endif
#define Big0 (Frac_mask1 | Exp_msk1*(DBL_MAX_EXP+Bias-1))
#define Big1 ((__uint32_t)0xffffffffL)
#ifndef Just_16
/* When Pack_32 is not defined, we store 16 bits per 32-bit long.
* This makes some inner loops simpler and sometimes saves work
* during multiplications, but it often seems to make things slightly
* slower. Hence the default is now to store 32 bits per long.
*/
#ifndef Pack_32
#define Pack_32
#endif
#endif
#ifdef __cplusplus
extern "C" double strtod(const char *s00, char **se);
extern "C" char *dtoa(double d, int mode, int ndigits,
int *decpt, int *sign, char **rve);
#endif
typedef struct _Bigint _Bigint;
#define Balloc _Balloc
#define Bfree _Bfree
#define multadd _multadd
#define s2b _s2b
#define lo0bits _lo0bits
#define hi0bits _hi0bits
#define i2b _i2b
#define mult _multiply
#define pow5mult _pow5mult
#define lshift _lshift
#define cmp __mcmp
#define diff __mdiff
#define ulp _ulp
#define b2d _b2d
#define d2b _d2b
#define ratio _ratio
#define tens __mprec_tens
#define bigtens __mprec_bigtens
#define tinytens __mprec_tinytens
struct _reent ;
double _EXFUN(ulp,(double x));
double _EXFUN(b2d,(_Bigint *a , int *e));
_Bigint * _EXFUN(Balloc,(struct _reent *p, int k));
void _EXFUN(Bfree,(struct _reent *p, _Bigint *v));
_Bigint * _EXFUN(multadd,(struct _reent *p, _Bigint *, int, int));
_Bigint * _EXFUN(s2b,(struct _reent *, const char*, int, int, ULong));
_Bigint * _EXFUN(i2b,(struct _reent *,int));
_Bigint * _EXFUN(mult, (struct _reent *, _Bigint *, _Bigint *));
_Bigint * _EXFUN(pow5mult, (struct _reent *, _Bigint *, int k));
int _EXFUN(hi0bits,(ULong));
int _EXFUN(lo0bits,(ULong *));
_Bigint * _EXFUN(d2b,(struct _reent *p, double d, int *e, int *bits));
_Bigint * _EXFUN(lshift,(struct _reent *p, _Bigint *b, int k));
_Bigint * _EXFUN(diff,(struct _reent *p, _Bigint *a, _Bigint *b));
int _EXFUN(cmp,(_Bigint *a, _Bigint *b));
double _EXFUN(ratio,(_Bigint *a, _Bigint *b));
#define Bcopy(x,y) memcpy((char *)&x->_sign, (char *)&y->_sign, y->_wds*sizeof(Long) + 2*sizeof(int))
#if defined(_DOUBLE_IS_32BITS) && defined(__v800)
#define n_bigtens 2
#else
#define n_bigtens 5
#endif
extern _CONST double tinytens[];
extern _CONST double bigtens[];
extern _CONST double tens[];
double _EXFUN(_mprec_log10,(int));

17
libc/stdlib/msize.c Normal file
View File

@@ -0,0 +1,17 @@
/* msize.c -- a wrapper for malloc_usable_size. */
#include <_ansi.h>
#include <reent.h>
#include <stdlib.h>
#include <malloc.h>
#ifndef _REENT_ONLY
size_t
_DEFUN (malloc_usable_size, (ptr),
_PTR ptr)
{
return _malloc_usable_size_r (_REENT, ptr);
}
#endif

151
libc/stdlib/mstats.c Normal file
View File

@@ -0,0 +1,151 @@
/* VxWorks provides its own version of malloc, and we can't use this
one because VxWorks does not provide sbrk. So we have a hook to
not compile this code. */
#ifdef MALLOC_PROVIDED
int _dummy_mstats = 1;
#else
/*
FUNCTION
<<mallinfo>>, <<malloc_stats>>, <<mallopt>>--malloc support
INDEX
mallinfo
INDEX
malloc_stats
INDEX
mallopt
INDEX
_mallinfo_r
INDEX
_malloc_stats_r
INDEX
_mallopt_r
ANSI_SYNOPSIS
#include <malloc.h>
struct mallinfo mallinfo(void);
void malloc_stats(void);
int mallopt(int <[parameter]>, <[value]>);
struct mallinfo _mallinfo_r(void *<[reent]>);
void _malloc_stats_r(void *<[reent]>);
int _mallopt_r(void *<[reent]>, int <[parameter]>, <[value]>);
TRAD_SYNOPSIS
#include <malloc.h>
struct mallinfo mallinfo();
void malloc_stats();
int mallopt(<[parameter]>, <[value]>)
int <[parameter]>;
int <[value]>;
struct mallinfo _mallinfo_r(<[reent]>);
char *<[reent]>;
void _malloc_stats_r(<[reent]>);
char *<[reent]>;
int _mallopt_r(<[reent]>, <[parameter]>, <[value]>)
char *<[reent]>;
int <[parameter]>;
int <[value]>;
DESCRIPTION
<<mallinfo>> returns a structure describing the current state of
memory allocation. The structure is defined in malloc.h. The
following fields are defined: <<arena>> is the total amount of space
in the heap; <<ordblks>> is the number of chunks which are not in use;
<<uordblks>> is the total amount of space allocated by <<malloc>>;
<<fordblks>> is the total amount of space not in use; <<keepcost>> is
the size of the top most memory block.
<<malloc_stats>> print some statistics about memory allocation on
standard error.
<<mallopt>> takes a parameter and a value. The parameters are defined
in malloc.h, and may be one of the following: <<M_TRIM_THRESHOLD>>
sets the maximum amount of unused space in the top most block before
releasing it back to the system in <<free>> (the space is released by
calling <<_sbrk_r>> with a negative argument); <<M_TOP_PAD>> is the
amount of padding to allocate whenever <<_sbrk_r>> is called to
allocate more space.
The alternate functions <<_mallinfo_r>>, <<_malloc_stats_r>>, and
<<_mallopt_r>> are reentrant versions. The extra argument <[reent]>
is a pointer to a reentrancy structure.
RETURNS
<<mallinfo>> returns a mallinfo structure. The structure is defined
in malloc.h.
<<malloc_stats>> does not return a result.
<<mallopt>> returns zero if the parameter could not be set, or
non-zero if it could be set.
PORTABILITY
<<mallinfo>> and <<mallopt>> are provided by SVR4, but <<mallopt>>
takes different parameters on different systems. <<malloc_stats>> is
not portable.
*/
#include <_ansi.h>
#include <reent.h>
#include <stdlib.h>
#include <malloc.h>
#include <stdio.h>
#ifndef _REENT_ONLY
struct mallinfo
_DEFUN_VOID (mallinfo)
{
return _mallinfo_r (_REENT);
}
void
_DEFUN_VOID (malloc_stats)
{
_malloc_stats_r (_REENT);
}
int
_DEFUN (mallopt, (p, v),
int p _AND
int v)
{
return _mallopt_r (_REENT, p, v);
}
#endif
/* mstats is now compatibility code. It used to be real, for a
previous version of the malloc routines. It now just calls
malloc_stats. */
void
_DEFUN (_mstats_r, (ptr, s),
struct _reent *ptr _AND
char *s)
{
fiprintf (_stderr_r (ptr), "Memory allocation statistics %s\n", s);
_malloc_stats_r (ptr);
}
#ifndef _REENT_ONLY
void
_DEFUN (mstats, (s),
char *s)
{
_mstats_r (_REENT, s);
}
#endif
#endif /* ! defined (MALLOC_PROVIDED) */

17
libc/stdlib/mtrim.c Normal file
View File

@@ -0,0 +1,17 @@
/* mtrim.c -- a wrapper for malloc_trim. */
#include <_ansi.h>
#include <reent.h>
#include <stdlib.h>
#include <malloc.h>
#ifndef _REENT_ONLY
int
_DEFUN (malloc_trim, (pad),
size_t pad)
{
return _malloc_trim_r (_REENT, pad);
}
#endif

46
libc/stdlib/putenv.c Normal file
View File

@@ -0,0 +1,46 @@
/* This file may have been modified by DJ Delorie (Jan 1991). If so,
** these modifications are Coyright (C) 1991 DJ Delorie, 24 Kirsten Ave,
** Rochester NH, 03867-2954, USA.
*/
/*-
* Copyright (c) 1988 The Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that: (1) source distributions retain this entire copyright
* notice and comment, and (2) distributions including binaries display
* the following acknowledgement: ``This product includes software
* developed by the University of California, Berkeley and its contributors''
* in the documentation or other materials provided with the distribution
* and in all advertising materials mentioning features or use of this
* software. 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#include <stdlib.h>
#include <string.h>
int
_DEFUN (putenv, (str),
_CONST char *str)
{
register char *p, *equal;
int rval;
if (!(p = strdup (str)))
return 1;
if (!(equal = index (p, '=')))
{
(void) free (p);
return 1;
}
*equal = '\0';
rval = setenv (p, equal + 1, 1);
(void) free (p);
return rval;
}

222
libc/stdlib/qsort.c Normal file
View File

@@ -0,0 +1,222 @@
/*
FUNCTION
<<qsort>>---sort an array
INDEX
qsort
ANSI_SYNOPSIS
#include <stdlib.h>
void qsort(void *<[base]>, size_t <[nmemb]>, size_t <[size]>,
int (*<[compar]>)(const void *, const void *) );
TRAD_SYNOPSIS
#include <stdlib.h>
qsort(<[base]>, <[nmemb]>, <[size]>, <[compar]> )
char *<[base]>;
size_t <[nmemb]>;
size_t <[size]>;
int (*<[compar]>)();
DESCRIPTION
<<qsort>> sorts an array (beginning at <[base]>) of <[nmemb]> objects.
<[size]> describes the size of each element of the array.
You must supply a pointer to a comparison function, using the argument
shown as <[compar]>. (This permits sorting objects of unknown
properties.) Define the comparison function to accept two arguments,
each a pointer to an element of the array starting at <[base]>. The
result of <<(*<[compar]>)>> must be negative if the first argument is
less than the second, zero if the two arguments match, and positive if
the first argument is greater than the second (where ``less than'' and
``greater than'' refer to whatever arbitrary ordering is appropriate).
The array is sorted in place; that is, when <<qsort>> returns, the
array elements beginning at <[base]> have been reordered.
RETURNS
<<qsort>> does not return a result.
PORTABILITY
<<qsort>> is required by ANSI (without specifying the sorting algorithm).
*/
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* 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 <_ansi.h>
#include <stdlib.h>
#ifndef __GNUC__
#define inline
#endif
static inline char *med3 _PARAMS((char *, char *, char *, int (*)()));
static inline void swapfunc _PARAMS((char *, char *, int, int));
#define min(a, b) (a) < (b) ? a : b
/*
* Qsort routine from Bentley & McIlroy's "Engineering a Sort Function".
*/
#define swapcode(TYPE, parmi, parmj, n) { \
long i = (n) / sizeof (TYPE); \
register TYPE *pi = (TYPE *) (parmi); \
register TYPE *pj = (TYPE *) (parmj); \
do { \
register TYPE t = *pi; \
*pi++ = *pj; \
*pj++ = t; \
} while (--i > 0); \
}
#define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \
es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1;
static inline void
_DEFUN(swapfunc, (a, b, n, swaptype),
char *a _AND
char *b _AND
int n _AND
int swaptype)
{
if(swaptype <= 1)
swapcode(long, a, b, n)
else
swapcode(char, a, b, n)
}
#define swap(a, b) \
if (swaptype == 0) { \
long t = *(long *)(a); \
*(long *)(a) = *(long *)(b); \
*(long *)(b) = t; \
} else \
swapfunc(a, b, es, swaptype)
#define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype)
static inline char *
_DEFUN(med3, (a, b, c, cmp),
char *a _AND
char *b _AND
char *c _AND
int (*cmp)())
{
return cmp(a, b) < 0 ?
(cmp(b, c) < 0 ? b : (cmp(a, c) < 0 ? c : a ))
:(cmp(b, c) > 0 ? b : (cmp(a, c) < 0 ? a : c ));
}
void
_DEFUN(qsort, (a, n, es, cmp),
void *a _AND
size_t n _AND
size_t es _AND
int (*cmp)())
{
char *pa, *pb, *pc, *pd, *pl, *pm, *pn;
int d, r, swaptype, swap_cnt;
loop: SWAPINIT(a, es);
swap_cnt = 0;
if (n < 7) {
for (pm = (char *) a + es; pm < (char *) a + n * es; pm += es)
for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0;
pl -= es)
swap(pl, pl - es);
return;
}
pm = (char *) a + (n / 2) * es;
if (n > 7) {
pl = a;
pn = (char *) a + (n - 1) * es;
if (n > 40) {
d = (n / 8) * es;
pl = med3(pl, pl + d, pl + 2 * d, cmp);
pm = med3(pm - d, pm, pm + d, cmp);
pn = med3(pn - 2 * d, pn - d, pn, cmp);
}
pm = med3(pl, pm, pn, cmp);
}
swap(a, pm);
pa = pb = (char *) a + es;
pc = pd = (char *) a + (n - 1) * es;
for (;;) {
while (pb <= pc && (r = cmp(pb, a)) <= 0) {
if (r == 0) {
swap_cnt = 1;
swap(pa, pb);
pa += es;
}
pb += es;
}
while (pb <= pc && (r = cmp(pc, a)) >= 0) {
if (r == 0) {
swap_cnt = 1;
swap(pc, pd);
pd -= es;
}
pc -= es;
}
if (pb > pc)
break;
swap(pb, pc);
swap_cnt = 1;
pb += es;
pc -= es;
}
if (swap_cnt == 0) { /* Switch to insertion sort */
for (pm = (char *) a + es; pm < (char *) a + n * es; pm += es)
for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0;
pl -= es)
swap(pl, pl - es);
return;
}
pn = (char *) a + n * es;
r = min(pa - (char *)a, pb - pa);
vecswap(a, pb - r, r);
r = min(pd - pc, pn - pd - es);
vecswap(pb, pn - r, r);
if ((r = pb - pa) > es)
qsort(a, r / es, es, cmp);
if ((r = pd - pc) > es) {
/* Iterate rather than recurse to save stack space */
a = pn - r;
n = r / es;
goto loop;
}
/* qsort(pn - r, r / es, es, cmp);*/
}

86
libc/stdlib/rand.c Normal file
View File

@@ -0,0 +1,86 @@
/*
FUNCTION
<<rand>>, <<srand>>---pseudo-random numbers
INDEX
rand
INDEX
srand
INDEX
rand_r
ANSI_SYNOPSIS
#include <stdlib.h>
int rand(void);
void srand(unsigned int <[seed]>);
int rand_r(unsigned int *<[seed]>);
TRAD_SYNOPSIS
#include <stdlib.h>
int rand();
void srand(<[seed]>)
unsigned int <[seed]>;
void rand_r(<[seed]>)
unsigned int *<[seed]>;
DESCRIPTION
<<rand>> returns a different integer each time it is called; each
integer is chosen by an algorithm designed to be unpredictable, so
that you can use <<rand>> when you require a random number.
The algorithm depends on a static variable called the ``random seed'';
starting with a given value of the random seed always produces the
same sequence of numbers in successive calls to <<rand>>.
You can set the random seed using <<srand>>; it does nothing beyond
storing its argument in the static variable used by <<rand>>. You can
exploit this to make the pseudo-random sequence less predictable, if
you wish, by using some other unpredictable value (often the least
significant parts of a time-varying value) as the random seed before
beginning a sequence of calls to <<rand>>; or, if you wish to ensure
(for example, while debugging) that successive runs of your program
use the same ``random'' numbers, you can use <<srand>> to set the same
random seed at the outset.
RETURNS
<<rand>> returns the next pseudo-random integer in sequence; it is a
number between <<0>> and <<RAND_MAX>> (inclusive).
<<srand>> does not return a result.
NOTES
<<rand>> and <<srand>> are unsafe for multi-thread applications.
<<rand_r>> is MT-Safe and should be used instead.
PORTABILITY
<<rand>> is required by ANSI, but the algorithm for pseudo-random
number generation is not specified; therefore, even if you use
the same random seed, you cannot expect the same sequence of results
on two different systems.
<<rand>> requires no supporting OS subroutines.
*/
#ifndef _REENT_ONLY
#include <stdlib.h>
#include <reent.h>
void
_DEFUN (srand, (seed), unsigned int seed)
{
_REENT->_new._reent._rand_next = seed;
}
int
_DEFUN_VOID (rand)
{
return ((_REENT->_new._reent._rand_next =
_REENT->_new._reent._rand_next * 1103515245 + 12345 )
& RAND_MAX );
}
#endif /* _REENT_ONLY */

7
libc/stdlib/rand_r.c Normal file
View File

@@ -0,0 +1,7 @@
#include <stdlib.h>
int
_DEFUN (rand_r, (seed), unsigned int *seed)
{
return (((*seed) = (*seed) * 1103515245 + 12345) & RAND_MAX);
}

18
libc/stdlib/realloc.c Normal file
View File

@@ -0,0 +1,18 @@
/* realloc.c -- a wrapper for realloc_r. */
#include <_ansi.h>
#include <reent.h>
#include <stdlib.h>
#include <malloc.h>
#ifndef _REENT_ONLY
_PTR
_DEFUN (realloc, (ap, nbytes),
_PTR ap _AND
size_t nbytes)
{
return _realloc_r (_REENT, ap, nbytes);
}
#endif

113
libc/stdlib/setenv.c Normal file
View File

@@ -0,0 +1,113 @@
/* This file may have been modified by DJ Delorie (Jan 1991). If so,
** these modifications are Coyright (C) 1991 DJ Delorie, 24 Kirsten Ave,
** Rochester NH, 03867-2954, USA.
*/
/*
* Copyright (c) 1987 Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that: (1) source distributions retain this entire copyright
* notice and comment, and (2) distributions including binaries display
* the following acknowledgement: ``This product includes software
* developed by the University of California, Berkeley and its contributors''
* in the documentation or other materials provided with the distribution
* and in all advertising materials mentioning features or use of this
* software. 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
/* _findenv is defined in getenv.c. */
extern char *_findenv _PARAMS ((const char *, int *));
/*
* setenv --
* Set the value of the environmental variable "name" to be
* "value". If rewrite is set, replace any current value.
*/
int
_DEFUN (setenv, (name, value, rewrite),
_CONST char *name _AND
_CONST char *value _AND
int rewrite)
{
extern char **environ;
static int alloced; /* if allocated space before */
register char *C;
int l_value, offset;
if (*value == '=') /* no `=' in value */
++value;
l_value = strlen (value);
if ((C = _findenv (name, &offset)))
{ /* find if already exists */
if (!rewrite)
return 0;
if (strlen (C) >= l_value)
{ /* old larger; copy over */
while (*C++ = *value++);
return 0;
}
}
else
{ /* create new slot */
register int cnt;
register char **P;
for (P = environ, cnt = 0; *P; ++P, ++cnt);
if (alloced)
{ /* just increase size */
environ = (char **) realloc ((char *) environ,
(size_t) (sizeof (char *) * (cnt + 2)));
if (!environ)
return -1;
}
else
{ /* get new space */
alloced = 1; /* copy old entries into it */
P = (char **) malloc ((size_t) (sizeof (char *) * (cnt + 2)));
if (!P)
return (-1);
bcopy ((char *) environ, (char *) P, cnt * sizeof (char *));
environ = P;
}
environ[cnt + 1] = NULL;
offset = cnt;
}
for (C = (char *) name; *C && *C != '='; ++C); /* no `=' in name */
if (!(environ[offset] = /* name + `=' + value */
malloc ((size_t) ((int) (C - name) + l_value + 2))))
return -1;
for (C = environ[offset]; (*C = *name++) && *C != '='; ++C);
for (*C++ = '='; *C++ = *value++;);
return 0;
}
/*
* unsetenv(name) --
* Delete environmental variable "name".
*/
void
_DEFUN (unsetenv, (name),
_CONST char *name)
{
extern char **environ;
register char **P;
int offset;
while (_findenv (name, &offset)) /* if set multiple times */
for (P = &environ[offset];; ++P)
if (!(*P = *(P + 1)))
break;
}

33
libc/stdlib/std.h Normal file
View File

@@ -0,0 +1,33 @@
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <limits.h>
#include <math.h>
#ifndef CYGNUS_NEC
#include <ctype.h>
#endif
#define Ise(c) ((c == 'e') || (c == 'E') || (c == 'd') || (c == 'D'))
#define Isdigit(c) ((c <= '9') && (c >= '0'))
#define Isspace(c) ((c == ' ') || (c == '\t') || (c=='\n') || (c=='\v') \
|| (c == '\r') || (c == '\f'))
#define Issign(c) ((c == '-') || (c == '+'))
#define Val(c) ((c - '0'))
#define MAXE 308
#define MINE (-308)
/* flags */
#define SIGN 0x01
#define ESIGN 0x02
#define DECP 0x04
#ifdef _HAVE_STDC
int __ten_mul(double *acc, int digit);
double __adjust(struct _reent *ptr, double *acc, int dexp, int sign);
const double __exp10(unsigned x);
#else
int __ten_mul();
double __adjust();
double __exp10();
#endif

14
libc/stdlib/strdup.c Normal file
View File

@@ -0,0 +1,14 @@
#include <stdlib.h>
#include <string.h>
char *
_DEFUN (strdup, (str), _CONST char *str)
{
size_t len = strlen (str) + 1;
char *copy = malloc (len);
if (copy)
{
memcpy (copy, str, len);
}
return copy;
}

731
libc/stdlib/strtod.c Normal file
View File

@@ -0,0 +1,731 @@
/*
FUNCTION
<<strtod>>, <<strtodf>>---string to double or float
INDEX
strtod
INDEX
_strtod_r
INDEX
strtodf
ANSI_SYNOPSIS
#include <stdlib.h>
double strtod(const char *<[str]>, char **<[tail]>);
float strtodf(const char *<[str]>, char **<[tail]>);
double _strtod_r(void *<[reent]>,
const char *<[str]>, char **<[tail]>);
TRAD_SYNOPSIS
#include <stdlib.h>
double strtod(<[str]>,<[tail]>)
char *<[str]>;
char **<[tail]>;
float strtodf(<[str]>,<[tail]>)
char *<[str]>;
char **<[tail]>;
double _strtod_r(<[reent]>,<[str]>,<[tail]>)
char *<[reent]>;
char *<[str]>;
char **<[tail]>;
DESCRIPTION
The function <<strtod>> parses the character string <[str]>,
producing a substring which can be converted to a double
value. The substring converted is the longest initial
subsequence of <[str]>, beginning with the first
non-whitespace character, that has the format:
.[+|-]<[digits]>[.][<[digits]>][(e|E)[+|-]<[digits]>]
The substring contains no characters if <[str]> is empty, consists
entirely of whitespace, or if the first non-whitespace
character is something other than <<+>>, <<->>, <<.>>, or a
digit. If the substring is empty, no conversion is done, and
the value of <[str]> is stored in <<*<[tail]>>>. Otherwise,
the substring is converted, and a pointer to the final string
(which will contain at least the terminating null character of
<[str]>) is stored in <<*<[tail]>>>. If you want no
assignment to <<*<[tail]>>>, pass a null pointer as <[tail]>.
<<strtodf>> is identical to <<strtod>> except for its return type.
This implementation returns the nearest machine number to the
input decimal string. Ties are broken by using the IEEE
round-even rule.
The alternate function <<_strtod_r>> is a reentrant version.
The extra argument <[reent]> is a pointer to a reentrancy structure.
RETURNS
<<strtod>> returns the converted substring value, if any. If
no conversion could be performed, 0 is returned. If the
correct value is out of the range of representable values,
plus or minus <<HUGE_VAL>> is returned, and <<ERANGE>> is
stored in errno. If the correct value would cause underflow, 0
is returned and <<ERANGE>> is stored in errno.
Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>,
<<lseek>>, <<read>>, <<sbrk>>, <<write>>.
*/
/****************************************************************
*
* The author of this software is David M. Gay.
*
* Copyright (c) 1991 by AT&T.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software and in all copies of the supporting
* documentation for such software.
*
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR AT&T MAKES ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*
***************************************************************/
/* Please send bug reports to
David M. Gay
AT&T Bell Laboratories, Room 2C-463
600 Mountain Avenue
Murray Hill, NJ 07974-2070
U.S.A.
dmg@research.att.com or research!dmg
*/
#include <_ansi.h>
#include <reent.h>
#include <string.h>
#include "mprec.h"
double
_DEFUN (_strtod_r, (ptr, s00, se),
struct _reent *ptr _AND
_CONST char *s00 _AND
char **se)
{
int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, dsign, e1, esign, i, j,
k, nd, nd0, nf, nz, nz0, sign;
long e;
_CONST char *s, *s0, *s1;
double aadj, aadj1, adj;
long L;
unsigned long z;
ULong y;
union double_union rv, rv0;
_Bigint *bb, *bb1, *bd, *bd0, *bs, *delta;
sign = nz0 = nz = 0;
rv.d = 0.;
for (s = s00;; s++)
switch (*s)
{
case '-':
sign = 1;
/* no break */
case '+':
if (*++s)
goto break2;
/* no break */
case 0:
s = s00;
goto ret;
case '\t':
case '\n':
case '\v':
case '\f':
case '\r':
case ' ':
continue;
default:
goto break2;
}
break2:
if (*s == '0')
{
nz0 = 1;
while (*++s == '0');
if (!*s)
goto ret;
}
s0 = s;
y = z = 0;
for (nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++)
if (nd < 9)
y = 10 * y + c - '0';
else if (nd < 16)
z = 10 * z + c - '0';
nd0 = nd;
if (c == '.')
{
c = *++s;
if (!nd)
{
for (; c == '0'; c = *++s)
nz++;
if (c > '0' && c <= '9')
{
s0 = s;
nf += nz;
nz = 0;
goto have_dig;
}
goto dig_done;
}
for (; c >= '0' && c <= '9'; c = *++s)
{
have_dig:
nz++;
if (c -= '0')
{
nf += nz;
for (i = 1; i < nz; i++)
if (nd++ < 9)
y *= 10;
else if (nd <= DBL_DIG + 1)
z *= 10;
if (nd++ < 9)
y = 10 * y + c;
else if (nd <= DBL_DIG + 1)
z = 10 * z + c;
nz = 0;
}
}
}
dig_done:
e = 0;
if (c == 'e' || c == 'E')
{
if (!nd && !nz && !nz0)
{
s = s00;
goto ret;
}
s00 = s;
esign = 0;
switch (c = *++s)
{
case '-':
esign = 1;
case '+':
c = *++s;
}
if (c >= '0' && c <= '9')
{
while (c == '0')
c = *++s;
if (c > '0' && c <= '9')
{
e = c - '0';
s1 = s;
while ((c = *++s) >= '0' && c <= '9')
e = 10 * e + c - '0';
if (s - s1 > 8)
/* Avoid confusion from exponents
* so large that e might overflow.
*/
e = 9999999L;
if (esign)
e = -e;
}
else
e = 0;
}
else
s = s00;
}
if (!nd)
{
if (!nz && !nz0)
s = s00;
goto ret;
}
e1 = e -= nf;
/* Now we have nd0 digits, starting at s0, followed by a
* decimal point, followed by nd-nd0 digits. The number we're
* after is the integer represented by those digits times
* 10**e */
if (!nd0)
nd0 = nd;
k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1;
rv.d = y;
if (k > 9)
rv.d = tens[k - 9] * rv.d + z;
bd0 = 0;
if (nd <= DBL_DIG
#ifndef RND_PRODQUOT
&& FLT_ROUNDS == 1
#endif
)
{
if (!e)
goto ret;
if (e > 0)
{
if (e <= Ten_pmax)
{
#ifdef VAX
goto vax_ovfl_check;
#else
/* rv.d = */ rounded_product (rv.d, tens[e]);
goto ret;
#endif
}
i = DBL_DIG - nd;
if (e <= Ten_pmax + i)
{
/* A fancier test would sometimes let us do
* this for larger i values.
*/
e -= i;
rv.d *= tens[i];
#ifdef VAX
/* VAX exponent range is so narrow we must
* worry about overflow here...
*/
vax_ovfl_check:
word0 (rv) -= P * Exp_msk1;
/* rv.d = */ rounded_product (rv.d, tens[e]);
if ((word0 (rv) & Exp_mask)
> Exp_msk1 * (DBL_MAX_EXP + Bias - 1 - P))
goto ovfl;
word0 (rv) += P * Exp_msk1;
#else
/* rv.d = */ rounded_product (rv.d, tens[e]);
#endif
goto ret;
}
}
#ifndef Inaccurate_Divide
else if (e >= -Ten_pmax)
{
/* rv.d = */ rounded_quotient (rv.d, tens[-e]);
goto ret;
}
#endif
}
e1 += nd - k;
/* Get starting approximation = rv.d * 10**e1 */
if (e1 > 0)
{
if (i = e1 & 15)
rv.d *= tens[i];
if (e1 &= ~15)
{
if (e1 > DBL_MAX_10_EXP)
{
ovfl:
ptr->_errno = ERANGE;
#ifdef _HAVE_STDC
rv.d = HUGE_VAL;
#else
/* Can't trust HUGE_VAL */
#ifdef IEEE_Arith
word0 (rv) = Exp_mask;
#ifndef _DOUBLE_IS_32BITS
word1 (rv) = 0;
#endif
#else
word0 (rv) = Big0;
#ifndef _DOUBLE_IS_32BITS
word1 (rv) = Big1;
#endif
#endif
#endif
if (bd0)
goto retfree;
goto ret;
}
if (e1 >>= 4)
{
for (j = 0; e1 > 1; j++, e1 >>= 1)
if (e1 & 1)
rv.d *= bigtens[j];
/* The last multiplication could overflow. */
word0 (rv) -= P * Exp_msk1;
rv.d *= bigtens[j];
if ((z = word0 (rv) & Exp_mask)
> Exp_msk1 * (DBL_MAX_EXP + Bias - P))
goto ovfl;
if (z > Exp_msk1 * (DBL_MAX_EXP + Bias - 1 - P))
{
/* set to largest number */
/* (Can't trust DBL_MAX) */
word0 (rv) = Big0;
#ifndef _DOUBLE_IS_32BITS
word1 (rv) = Big1;
#endif
}
else
word0 (rv) += P * Exp_msk1;
}
}
}
else if (e1 < 0)
{
e1 = -e1;
if (i = e1 & 15)
rv.d /= tens[i];
if (e1 &= ~15)
{
e1 >>= 4;
if (e1 >= 1 << n_bigtens)
goto undfl;
for (j = 0; e1 > 1; j++, e1 >>= 1)
if (e1 & 1)
rv.d *= tinytens[j];
/* The last multiplication could underflow. */
rv0.d = rv.d;
rv.d *= tinytens[j];
if (!rv.d)
{
rv.d = 2. * rv0.d;
rv.d *= tinytens[j];
if (!rv.d)
{
undfl:
rv.d = 0.;
ptr->_errno = ERANGE;
if (bd0)
goto retfree;
goto ret;
}
#ifndef _DOUBLE_IS_32BITS
word0 (rv) = Tiny0;
word1 (rv) = Tiny1;
#else
word0 (rv) = Tiny1;
#endif
/* The refinement below will clean
* this approximation up.
*/
}
}
}
/* Now the hard part -- adjusting rv to the correct value.*/
/* Put digits into bd: true value = bd * 10^e */
bd0 = s2b (ptr, s0, nd0, nd, y);
for (;;)
{
bd = Balloc (ptr, bd0->_k);
Bcopy (bd, bd0);
bb = d2b (ptr, rv.d, &bbe, &bbbits); /* rv.d = bb * 2^bbe */
bs = i2b (ptr, 1);
if (e >= 0)
{
bb2 = bb5 = 0;
bd2 = bd5 = e;
}
else
{
bb2 = bb5 = -e;
bd2 = bd5 = 0;
}
if (bbe >= 0)
bb2 += bbe;
else
bd2 -= bbe;
bs2 = bb2;
#ifdef Sudden_Underflow
#ifdef IBM
j = 1 + 4 * P - 3 - bbbits + ((bbe + bbbits - 1) & 3);
#else
j = P + 1 - bbbits;
#endif
#else
i = bbe + bbbits - 1; /* logb(rv.d) */
if (i < Emin) /* denormal */
j = bbe + (P - Emin);
else
j = P + 1 - bbbits;
#endif
bb2 += j;
bd2 += j;
i = bb2 < bd2 ? bb2 : bd2;
if (i > bs2)
i = bs2;
if (i > 0)
{
bb2 -= i;
bd2 -= i;
bs2 -= i;
}
if (bb5 > 0)
{
bs = pow5mult (ptr, bs, bb5);
bb1 = mult (ptr, bs, bb);
Bfree (ptr, bb);
bb = bb1;
}
if (bb2 > 0)
bb = lshift (ptr, bb, bb2);
if (bd5 > 0)
bd = pow5mult (ptr, bd, bd5);
if (bd2 > 0)
bd = lshift (ptr, bd, bd2);
if (bs2 > 0)
bs = lshift (ptr, bs, bs2);
delta = diff (ptr, bb, bd);
dsign = delta->_sign;
delta->_sign = 0;
i = cmp (delta, bs);
if (i < 0)
{
/* Error is less than half an ulp -- check for
* special case of mantissa a power of two.
*/
if (dsign || word1 (rv) || word0 (rv) & Bndry_mask)
break;
delta = lshift (ptr, delta, Log2P);
if (cmp (delta, bs) > 0)
goto drop_down;
break;
}
if (i == 0)
{
/* exactly half-way between */
if (dsign)
{
if ((word0 (rv) & Bndry_mask1) == Bndry_mask1
&& word1 (rv) == 0xffffffff)
{
/*boundary case -- increment exponent*/
word0 (rv) = (word0 (rv) & Exp_mask)
+ Exp_msk1
#ifdef IBM
| Exp_msk1 >> 4
#endif
;
#ifndef _DOUBLE_IS_32BITS
word1 (rv) = 0;
#endif
break;
}
}
else if (!(word0 (rv) & Bndry_mask) && !word1 (rv))
{
drop_down:
/* boundary case -- decrement exponent */
#ifdef Sudden_Underflow
L = word0 (rv) & Exp_mask;
#ifdef IBM
if (L < Exp_msk1)
#else
if (L <= Exp_msk1)
#endif
goto undfl;
L -= Exp_msk1;
#else
L = (word0 (rv) & Exp_mask) - Exp_msk1;
#endif
word0 (rv) = L | Bndry_mask1;
#ifndef _DOUBLE_IS_32BITS
word1 (rv) = 0xffffffff;
#endif
#ifdef IBM
goto cont;
#else
break;
#endif
}
#ifndef ROUND_BIASED
if (!(word1 (rv) & LSB))
break;
#endif
if (dsign)
rv.d += ulp (rv.d);
#ifndef ROUND_BIASED
else
{
rv.d -= ulp (rv.d);
#ifndef Sudden_Underflow
if (!rv.d)
goto undfl;
#endif
}
#endif
break;
}
if ((aadj = ratio (delta, bs)) <= 2.)
{
if (dsign)
aadj = aadj1 = 1.;
else if (word1 (rv) || word0 (rv) & Bndry_mask)
{
#ifndef Sudden_Underflow
if (word1 (rv) == Tiny1 && !word0 (rv))
goto undfl;
#endif
aadj = 1.;
aadj1 = -1.;
}
else
{
/* special case -- power of FLT_RADIX to be */
/* rounded down... */
if (aadj < 2. / FLT_RADIX)
aadj = 1. / FLT_RADIX;
else
aadj *= 0.5;
aadj1 = -aadj;
}
}
else
{
aadj *= 0.5;
aadj1 = dsign ? aadj : -aadj;
#ifdef Check_FLT_ROUNDS
switch (FLT_ROUNDS)
{
case 2: /* towards +infinity */
aadj1 -= 0.5;
break;
case 0: /* towards 0 */
case 3: /* towards -infinity */
aadj1 += 0.5;
}
#else
if (FLT_ROUNDS == 0)
aadj1 += 0.5;
#endif
}
y = word0 (rv) & Exp_mask;
/* Check for overflow */
if (y == Exp_msk1 * (DBL_MAX_EXP + Bias - 1))
{
rv0.d = rv.d;
word0 (rv) -= P * Exp_msk1;
adj = aadj1 * ulp (rv.d);
rv.d += adj;
if ((word0 (rv) & Exp_mask) >=
Exp_msk1 * (DBL_MAX_EXP + Bias - P))
{
if (word0 (rv0) == Big0 && word1 (rv0) == Big1)
goto ovfl;
#ifdef _DOUBLE_IS_32BITS
word0 (rv) = Big1;
#else
word0 (rv) = Big0;
word1 (rv) = Big1;
#endif
goto cont;
}
else
word0 (rv) += P * Exp_msk1;
}
else
{
#ifdef Sudden_Underflow
if ((word0 (rv) & Exp_mask) <= P * Exp_msk1)
{
rv0.d = rv.d;
word0 (rv) += P * Exp_msk1;
adj = aadj1 * ulp (rv.d);
rv.d += adj;
#ifdef IBM
if ((word0 (rv) & Exp_mask) < P * Exp_msk1)
#else
if ((word0 (rv) & Exp_mask) <= P * Exp_msk1)
#endif
{
if (word0 (rv0) == Tiny0
&& word1 (rv0) == Tiny1)
goto undfl;
word0 (rv) = Tiny0;
word1 (rv) = Tiny1;
goto cont;
}
else
word0 (rv) -= P * Exp_msk1;
}
else
{
adj = aadj1 * ulp (rv.d);
rv.d += adj;
}
#else
/* Compute adj so that the IEEE rounding rules will
* correctly round rv.d + adj in some half-way cases.
* If rv.d * ulp(rv.d) is denormalized (i.e.,
* y <= (P-1)*Exp_msk1), we must adjust aadj to avoid
* trouble from bits lost to denormalization;
* example: 1.2e-307 .
*/
if (y <= (P - 1) * Exp_msk1 && aadj >= 1.)
{
aadj1 = (double) (int) (aadj + 0.5);
if (!dsign)
aadj1 = -aadj1;
}
adj = aadj1 * ulp (rv.d);
rv.d += adj;
#endif
}
z = word0 (rv) & Exp_mask;
if (y == z)
{
/* Can we stop now? */
L = aadj;
aadj -= L;
/* The tolerances below are conservative. */
if (dsign || word1 (rv) || word0 (rv) & Bndry_mask)
{
if (aadj < .4999999 || aadj > .5000001)
break;
}
else if (aadj < .4999999 / FLT_RADIX)
break;
}
cont:
Bfree (ptr, bb);
Bfree (ptr, bd);
Bfree (ptr, bs);
Bfree (ptr, delta);
}
retfree:
Bfree (ptr, bb);
Bfree (ptr, bd);
Bfree (ptr, bs);
Bfree (ptr, bd0);
Bfree (ptr, delta);
ret:
if (se)
*se = (char *) s;
return sign ? -rv.d : rv.d;
}
#ifndef NO_REENT
double
_DEFUN (strtod, (s00, se),
_CONST char *s00 _AND char **se)
{
return _strtod_r (_REENT, s00, se);
}
float
_DEFUN (strtodf, (s00, se),
_CONST char *s00 _AND
char **se)
{
return strtod (s00, se);
}
#endif

226
libc/stdlib/strtol.c Normal file
View File

@@ -0,0 +1,226 @@
/*
FUNCTION
<<strtol>>---string to long
INDEX
strtol
INDEX
_strtol_r
ANSI_SYNOPSIS
#include <stdlib.h>
long strtol(const char *<[s]>, char **<[ptr]>,int <[base]>);
long _strtol_r(void *<[reent]>,
const char *<[s]>, char **<[ptr]>,int <[base]>);
TRAD_SYNOPSIS
#include <stdlib.h>
long strtol (<[s]>, <[ptr]>, <[base]>)
char *<[s]>;
char **<[ptr]>;
int <[base]>;
long _strtol_r (<[reent]>, <[s]>, <[ptr]>, <[base]>)
char *<[reent]>;
char *<[s]>;
char **<[ptr]>;
int <[base]>;
DESCRIPTION
The function <<strtol>> converts the string <<*<[s]>>> to
a <<long>>. First, it breaks down the string into three parts:
leading whitespace, which is ignored; a subject string consisting
of characters resembling an integer in the radix specified by <[base]>;
and a trailing portion consisting of zero or more unparseable characters,
and always including the terminating null character. Then, it attempts
to convert the subject string into a <<long>> and returns the
result.
If the value of <[base]> is 0, the subject string is expected to look
like a normal C integer constant: an optional sign, a possible `<<0x>>'
indicating a hexadecimal base, and a number. If <[base]> is between
2 and 36, the expected form of the subject is a sequence of letters
and digits representing an integer in the radix specified by <[base]>,
with an optional plus or minus sign. The letters <<a>>--<<z>> (or,
equivalently, <<A>>--<<Z>>) are used to signify values from 10 to 35;
only letters whose ascribed values are less than <[base]> are
permitted. If <[base]> is 16, a leading <<0x>> is permitted.
The subject sequence is the longest initial sequence of the input
string that has the expected form, starting with the first
non-whitespace character. If the string is empty or consists entirely
of whitespace, or if the first non-whitespace character is not a
permissible letter or digit, the subject string is empty.
If the subject string is acceptable, and the value of <[base]> is zero,
<<strtol>> attempts to determine the radix from the input string. A
string with a leading <<0x>> is treated as a hexadecimal value; a string with
a leading 0 and no <<x>> is treated as octal; all other strings are
treated as decimal. If <[base]> is between 2 and 36, it is used as the
conversion radix, as described above. If the subject string begins with
a minus sign, the value is negated. Finally, a pointer to the first
character past the converted subject string is stored in <[ptr]>, if
<[ptr]> is not <<NULL>>.
If the subject string is empty (or not in acceptable form), no conversion
is performed and the value of <[s]> is stored in <[ptr]> (if <[ptr]> is
not <<NULL>>).
The alternate function <<_strtol_r>> is a reentrant version. The
extra argument <[reent]> is a pointer to a reentrancy structure.
RETURNS
<<strtol>> returns the converted value, if any. If no conversion was
made, 0 is returned.
<<strtol>> returns <<LONG_MAX>> or <<LONG_MIN>> if the magnitude of
the converted value is too large, and sets <<errno>> to <<ERANGE>>.
PORTABILITY
<<strtol>> is ANSI.
No supporting OS subroutines are required.
*/
/*-
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* 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 <_ansi.h>
#include <limits.h>
#include <ctype.h>
#include <errno.h>
#include <stdlib.h>
#include <reent.h>
/*
* Convert a string to a long integer.
*
* Ignores `locale' stuff. Assumes that the upper and lower case
* alphabets and digits are each contiguous.
*/
long
_DEFUN (_strtol_r, (rptr, nptr, endptr, base),
struct _reent *rptr _AND
_CONST char *nptr _AND
char **endptr _AND
int base)
{
register const char *s = nptr;
register unsigned long acc;
register int c;
register unsigned long cutoff;
register int neg = 0, any, cutlim;
/*
* Skip white space and pick up leading +/- sign if any.
* If base is 0, allow 0x for hex and 0 for octal, else
* assume decimal; if base is already 16, allow 0x.
*/
do {
c = *s++;
} while (isspace(c));
if (c == '-') {
neg = 1;
c = *s++;
} else if (c == '+')
c = *s++;
if ((base == 0 || base == 16) &&
c == '0' && (*s == 'x' || *s == 'X')) {
c = s[1];
s += 2;
base = 16;
}
if (base == 0)
base = c == '0' ? 8 : 10;
/*
* Compute the cutoff value between legal numbers and illegal
* numbers. That is the largest legal value, divided by the
* base. An input number that is greater than this value, if
* followed by a legal input character, is too big. One that
* is equal to this value may be valid or not; the limit
* between valid and invalid numbers is then based on the last
* digit. For instance, if the range for longs is
* [-2147483648..2147483647] and the input base is 10,
* cutoff will be set to 214748364 and cutlim to either
* 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
* a value > 214748364, or equal but the next digit is > 7 (or 8),
* the number is too big, and we will return a range error.
*
* Set any if any `digits' consumed; make it negative to indicate
* overflow.
*/
cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX;
cutlim = cutoff % (unsigned long)base;
cutoff /= (unsigned long)base;
for (acc = 0, any = 0;; c = *s++) {
if (isdigit(c))
c -= '0';
else if (isalpha(c))
c -= isupper(c) ? 'A' - 10 : 'a' - 10;
else
break;
if (c >= base)
break;
if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
any = -1;
else {
any = 1;
acc *= base;
acc += c;
}
}
if (any < 0) {
acc = neg ? LONG_MIN : LONG_MAX;
rptr->_errno = ERANGE;
} else if (neg)
acc = -acc;
if (endptr != 0)
*endptr = (char *) (any ? s - 1 : nptr);
return (acc);
}
#ifndef _REENT_ONLY
long
_DEFUN (strtol, (s, ptr, base),
_CONST char *s _AND
char **ptr _AND
int base)
{
return _strtol_r (_REENT, s, ptr, base);
}
#endif

206
libc/stdlib/strtoul.c Normal file
View File

@@ -0,0 +1,206 @@
/*
FUNCTION
<<strtoul>>---string to unsigned long
INDEX
strtoul
INDEX
_strtoul_r
ANSI_SYNOPSIS
#include <stdlib.h>
unsigned long strtoul(const char *<[s]>, char **<[ptr]>,
int <[base]>);
unsigned long _strtoul_r(void *<[reent]>, const char *<[s]>,
char **<[ptr]>, int <[base]>);
TRAD_SYNOPSIS
#include <stdlib.h>
unsigned long strtoul(<[s]>, <[ptr]>, <[base]>)
char *<[s]>;
char **<[ptr]>;
int <[base]>;
unsigned long _strtoul_r(<[reent]>, <[s]>, <[ptr]>, <[base]>)
char *<[reent]>;
char *<[s]>;
char **<[ptr]>;
int <[base]>;
DESCRIPTION
The function <<strtoul>> converts the string <<*<[s]>>> to
an <<unsigned long>>. First, it breaks down the string into three parts:
leading whitespace, which is ignored; a subject string consisting
of the digits meaningful in the radix specified by <[base]>
(for example, <<0>> through <<7>> if the value of <[base]> is 8);
and a trailing portion consisting of one or more unparseable characters,
which always includes the terminating null character. Then, it attempts
to convert the subject string into an unsigned long integer, and returns the
result.
If the value of <[base]> is zero, the subject string is expected to look
like a normal C integer constant (save that no optional sign is permitted):
a possible <<0x>> indicating hexadecimal radix, and a number.
If <[base]> is between 2 and 36, the expected form of the subject is a
sequence of digits (which may include letters, depending on the
base) representing an integer in the radix specified by <[base]>.
The letters <<a>>--<<z>> (or <<A>>--<<Z>>) are used as digits valued from
10 to 35. If <[base]> is 16, a leading <<0x>> is permitted.
The subject sequence is the longest initial sequence of the input
string that has the expected form, starting with the first
non-whitespace character. If the string is empty or consists entirely
of whitespace, or if the first non-whitespace character is not a
permissible digit, the subject string is empty.
If the subject string is acceptable, and the value of <[base]> is zero,
<<strtoul>> attempts to determine the radix from the input string. A
string with a leading <<0x>> is treated as a hexadecimal value; a string with
a leading <<0>> and no <<x>> is treated as octal; all other strings are
treated as decimal. If <[base]> is between 2 and 36, it is used as the
conversion radix, as described above. Finally, a pointer to the first
character past the converted subject string is stored in <[ptr]>, if
<[ptr]> is not <<NULL>>.
If the subject string is empty (that is, if <<*>><[s]> does not start
with a substring in acceptable form), no conversion
is performed and the value of <[s]> is stored in <[ptr]> (if <[ptr]> is
not <<NULL>>).
The alternate function <<_strtoul_r>> is a reentrant version. The
extra argument <[reent]> is a pointer to a reentrancy structure.
RETURNS
<<strtoul>> returns the converted value, if any. If no conversion was
made, <<0>> is returned.
<<strtoul>> returns <<ULONG_MAX>> if the magnitude of the converted
value is too large, and sets <<errno>> to <<ERANGE>>.
PORTABILITY
<<strtoul>> is ANSI.
<<strtoul>> requires no supporting OS subroutines.
*/
/*
* Copyright (c) 1990 Regents of the University of California.
* All rights reserved.
*
* 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 <_ansi.h>
#include <limits.h>
#include <ctype.h>
#include <errno.h>
#include <stdlib.h>
#include <reent.h>
/*
* Convert a string to an unsigned long integer.
*
* Ignores `locale' stuff. Assumes that the upper and lower case
* alphabets and digits are each contiguous.
*/
unsigned long
_DEFUN (_strtoul_r, (rptr, nptr, endptr, base),
struct _reent *rptr _AND
_CONST char *nptr _AND
char **endptr _AND
int base)
{
register const char *s = nptr;
register unsigned long acc;
register int c;
register unsigned long cutoff;
register int neg = 0, any, cutlim;
/*
* See strtol for comments as to the logic used.
*/
do {
c = *s++;
} while (isspace(c));
if (c == '-') {
neg = 1;
c = *s++;
} else if (c == '+')
c = *s++;
if ((base == 0 || base == 16) &&
c == '0' && (*s == 'x' || *s == 'X')) {
c = s[1];
s += 2;
base = 16;
}
if (base == 0)
base = c == '0' ? 8 : 10;
cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
cutlim = (unsigned long)ULONG_MAX % (unsigned long)base;
for (acc = 0, any = 0;; c = *s++) {
if (isdigit(c))
c -= '0';
else if (isalpha(c))
c -= isupper(c) ? 'A' - 10 : 'a' - 10;
else
break;
if (c >= base)
break;
if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
any = -1;
else {
any = 1;
acc *= base;
acc += c;
}
}
if (any < 0) {
acc = ULONG_MAX;
rptr->_errno = ERANGE;
} else if (neg)
acc = -acc;
if (endptr != 0)
*endptr = (char *) (any ? s - 1 : nptr);
return (acc);
}
#ifndef _REENT_ONLY
unsigned long
_DEFUN (strtoul, (s, ptr, base),
_CONST char *s _AND
char **ptr _AND
int base)
{
return _strtoul_r (_REENT, s, ptr, base);
}
#endif

179
libc/stdlib/system.c Normal file
View File

@@ -0,0 +1,179 @@
/*
FUNCTION
<<system>>---execute command string
INDEX
system
INDEX
_system_r
ANSI_SYNOPSIS
#include <stdlib.h>
int system(char *<[s]>);
int _system_r(void *<[reent]>, char *<[s]>);
TRAD_SYNOPSIS
#include <stdlib.h>
int system(<[s]>)
char *<[s]>;
int _system_r(<[reent]>, <[s]>)
char *<[reent]>;
char *<[s]>;
DESCRIPTION
Use <<system>> to pass a command string <<*<[s]>>> to <</bin/sh>> on
your system, and wait for it to finish executing.
Use `<<system(NULL)>>' to test whether your system has <</bin/sh>>
available.
The alternate function <<_system_r>> is a reentrant version. The
extra argument <[reent]> is a pointer to a reentrancy structure.
RETURNS
<<system(NULL)>> returns a non-zero value if <</bin/sh>> is available, and
<<0>> if it is not.
With a command argument, the result of <<system>> is the exit status
returned by <</bin/sh>>.
PORTABILITY
ANSI C requires <<system>>, but leaves the nature and effects of a
command processor undefined. ANSI C does, however, specify that
<<system(NULL)>> return zero or nonzero to report on the existence of
a command processor.
POSIX.2 requires <<system>>, and requires that it invoke a <<sh>>.
Where <<sh>> is found is left unspecified.
Supporting OS subroutines required: <<_exit>>, <<_execve>>, <<_fork_r>>,
<<_wait_r>>.
*/
#include <errno.h>
#include <stddef.h>
#include <stdlib.h>
#include <_syslist.h>
#if defined (unix) || defined (__CYGWIN32__)
static int do_system ();
#endif
int
_system_r (ptr, s)
struct _reent *ptr;
_CONST char *s;
{
#ifdef NO_EXEC
if (s == NULL)
return 0;
errno = ENOSYS;
return -1;
#else
/* ??? How to handle (s == NULL) here is not exactly clear.
If _fork_r fails, that's not really a justification for returning 0.
For now we always return 0 and leave it to each target to explicitly
handle otherwise (this can always be relaxed in the future). */
#if defined (unix) || defined (__CYGWIN32__)
if (s == NULL)
return 1;
return do_system (ptr, s);
#else
if (s == NULL)
return 0;
errno = ENOSYS;
return -1;
#endif
#endif
}
#ifndef _REENT_ONLY
int
system (s)
_CONST char *s;
{
return _system_r (_REENT, s);
}
#endif
#if defined (unix) && !defined (__CYGWIN32__)
static int
do_system (ptr, s)
struct _reent *ptr;
_CONST char *s;
{
char *argv[4];
int pid, status;
extern char *environ[];
argv[0] = "sh";
argv[1] = "-c";
argv[2] = (char *) s;
argv[3] = NULL;
if ((pid = _fork_r (ptr)) == 0)
{
_execve ("/bin/sh", argv, environ);
exit (100);
}
else if (pid == -1)
return -1;
else
{
int rc = _wait_r (ptr, &status);
if (rc == -1)
return -1;
status = (status >> 8) & 0xff;
return status;
}
}
#endif
#if defined (__CYGWIN32__)
static int
do_system (ptr, s)
struct _reent *ptr;
_CONST char *s;
{
char *argv[4];
int pid, status;
extern char *environ[];
argv[0] = "sh";
argv[1] = "-c";
argv[2] = (char *) s;
argv[3] = NULL;
if ((pid = vfork ()) == 0)
{
/* ??? It's not clear what's the right path to take (pun intended :-).
There won't be an "sh" in any fixed location so we need each user
to be able to say where to find "sh". That suggests using an
environment variable, but after a few more such situations we may
have too many of them. */
char *sh = getenv ("SH_PATH");
if (sh == NULL)
sh = "/bin/sh";
_execve (sh, argv, environ);
exit (100);
}
else if (pid == -1)
return -1;
else
{
int rc = _wait (&status);
if (rc == -1)
return -1;
status = (status >> 8) & 0xff;
return status;
}
}
#endif

24
libc/stdlib/valloc.c Normal file
View File

@@ -0,0 +1,24 @@
/* valloc.c -- a wrapper for valloc_r and pvalloc_r. */
#include <_ansi.h>
#include <reent.h>
#include <stdlib.h>
#include <malloc.h>
#ifndef _REENT_ONLY
_PTR
_DEFUN (valloc, (nbytes),
size_t nbytes)
{
return _valloc_r (_REENT, nbytes);
}
_PTR
_DEFUN (pvalloc, (nbytes),
size_t nbytes)
{
return _pvalloc_r (_REENT, nbytes);
}
#endif

79
libc/stdlib/wcstombs.c Normal file
View File

@@ -0,0 +1,79 @@
/*
FUNCTION
<<wcstombs>>---minimal wide char string to multibyte string converter
INDEX
wcstombs
ANSI_SYNOPSIS
#include <stdlib.h>
int wcstombs(const char *<[s]>, wchar_t *<[pwc]>, size_t <[n]>);
TRAD_SYNOPSIS
#include <stdlib.h>
int wcstombs(<[s]>, <[pwc]>, <[n]>)
const char *<[s]>;
wchar_t *<[pwc]>;
size_t <[n]>;
DESCRIPTION
When MB_CAPABLE is not defined, this is a minimal ANSI-conforming
implementation of <<wcstombs>>. In this case,
all wide-characters are expected to represent single bytes and so
are converted simply by casting to char.
When MB_CAPABLE is defined, this routine calls <<_wcstombs_r>> to perform
the conversion, passing a state variable to allow state dependent
decoding. The result is based on the locale setting which may
be restricted to a defined set of locales.
RETURNS
This implementation of <<wcstombs>> returns <<0>> if
<[s]> is <<NULL>> or is the empty string;
it returns <<-1>> if MB_CAPABLE and one of the
wide-char characters does not represent a valid multi-byte character;
otherwise it returns the minimum of: <<n>> or the
number of bytes that are transferred to <<s>>, not including the
nul terminator.
If the return value is -1, the state of the <<pwc>> string is
indeterminate. If the input has a length of 0, the output
string will be modified to contain a wchar_t nul terminator if
<<n>> > 0.
PORTABILITY
<<wcstombs>> is required in the ANSI C standard. However, the precise
effects vary with the locale.
<<wcstombs>> requires no supporting OS subroutines.
*/
#include <stdlib.h>
size_t
_DEFUN (wcstombs, (s, pwcs, n),
char *s _AND
const wchar_t *pwcs _AND
size_t n)
{
#ifdef MB_CAPABLE
int state = 0;
return _wcstombs_r (_REENT, s, pwcs, n, &state);
#else /* not MB_CAPABLE */
int count = 0;
if (n != 0) {
do {
if ((*s++ = (char) *pwcs++) == 0)
break;
count++;
} while (--n != 0);
}
return count;
#endif /* not MB_CAPABLE */
}

32
libc/stdlib/wcstombs_r.c Normal file
View File

@@ -0,0 +1,32 @@
#include <stdlib.h>
size_t
_DEFUN (_wcstombs_r, (reent, s, pwcs, n, state),
struct _reent *r _AND
char *s _AND
const wchar_t *pwcs _AND
size_t n _AND
int *state)
{
char *ptr = s;
size_t max = n;
char buff[8];
int i, num_to_copy;
while (n > 0)
{
int bytes = _wctomb_r (r, buff, *pwcs, state);
if (bytes == -1)
return -1;
num_to_copy = (n > bytes ? bytes : (int)n);
for (i = 0; i < num_to_copy; ++i)
*ptr++ = buff[i];
if (*pwcs == 0x00)
return ptr - s - (n >= bytes);
++pwcs;
n -= num_to_copy;
}
return max;
}

64
libc/stdlib/wctomb.c Normal file
View File

@@ -0,0 +1,64 @@
/*
FUNCTION
<<wctomb>>---minimal wide char to multibyte converter
INDEX
wctomb
ANSI_SYNOPSIS
#include <stdlib.h>
int wctomb(char *<[s]>, wchar_t <[wchar]>);
TRAD_SYNOPSIS
#include <stdlib.h>
int wctomb(<[s]>, <[wchar]>)
char *<[s]>;
wchar_t <[wchar]>;
DESCRIPTION
When MB_CAPABLE is not defined, this is a minimal ANSI-conforming
implementation of <<wctomb>>. The
only ``wide characters'' recognized are single bytes,
and they are ``converted'' to themselves.
When MB_CAPABLE is defined, this routine calls <<_wctomb_r>> to perform
the conversion, passing a state variable to allow state dependent
decoding. The result is based on the locale setting which may
be restricted to a defined set of locales.
Each call to <<wctomb>> modifies <<*<[s]>>> unless <[s]> is a null
pointer or MB_CAPABLE is defined and <[wchar]> is invalid.
RETURNS
This implementation of <<wctomb>> returns <<0>> if
<[s]> is <<NULL>>; it returns <<-1>> if MB_CAPABLE is enabled
and the wchar is not a valid multi-byte character, it returns <<1>>
if MB_CAPABLE is not defined or the wchar is in reality a single
byte character, otherwise it returns the number of bytes in the
multi-byte character.
PORTABILITY
<<wctomb>> is required in the ANSI C standard. However, the precise
effects vary with the locale.
<<wctomb>> requires no supporting OS subroutines.
*/
#include <stdlib.h>
int
_DEFUN (wctomb, (s, wchar),
char *s _AND
wchar_t wchar)
{
#ifdef MB_CAPABLE
static int state;
return _wctomb_r (_REENT, s, wchar, &state);
#else /* not MB_CAPABLE */
if (s == NULL)
return 0;
*s = (char) wchar;
return 1;
#endif /* not MB_CAPABLE */
}

110
libc/stdlib/wctomb_r.c Normal file
View File

@@ -0,0 +1,110 @@
#include <stdlib.h>
#include <locale.h>
#include "mbctype.h"
int
_DEFUN (_wctomb_r, (r, s, wchar, state),
struct _reent *r _AND
char *s _AND
wchar_t wchar _AND
int *state)
{
if (strlen (r->_current_locale) <= 1)
{ /* fall-through */ }
else if (!strcmp (r->_current_locale, "C-SJIS"))
{
unsigned char char2 = (unsigned char)wchar;
unsigned char char1 = (unsigned char)(wchar >> 8);
if (s == NULL)
return 0; /* not state-dependent */
if (char1 != 0x00)
{
/* first byte is non-zero..validate multi-byte char */
if (_issjis1(char1) && _issjis2(char2))
{
*s++ = (char)char1;
*s = (char)char2;
return 2;
}
else
return -1;
}
}
else if (!strcmp (r->_current_locale, "C-EUCJP"))
{
unsigned char char2 = (unsigned char)wchar;
unsigned char char1 = (unsigned char)(wchar >> 8);
if (s == NULL)
return 0; /* not state-dependent */
if (char1 != 0x00)
{
/* first byte is non-zero..validate multi-byte char */
if (_iseucjp (char1) && _iseucjp (char2))
{
*s++ = (char)char1;
*s = (char)char2;
return 2;
}
else
return -1;
}
}
else if (!strcmp (r->_current_locale, "C-JIS"))
{
int cnt = 0;
unsigned char char2 = (unsigned char)wchar;
unsigned char char1 = (unsigned char)(wchar >> 8);
if (s == NULL)
return 1; /* state-dependent */
if (char1 != 0x00)
{
/* first byte is non-zero..validate multi-byte char */
if (_isjis (char1) && _isjis (char2))
{
if (*state == 0)
{
/* must switch from ASCII to JIS state */
*state = 1;
*s++ = ESC_CHAR;
*s++ = '$';
*s++ = 'B';
cnt = 3;
}
*s++ = (char)char1;
*s = (char)char2;
return cnt + 2;
}
else
return -1;
}
else
{
if (*state != 0)
{
/* must switch from JIS to ASCII state */
*state = 0;
*s++ = ESC_CHAR;
*s++ = '(';
*s++ = 'B';
cnt = 3;
}
*s = (char)char2;
return cnt + 1;
}
}
if (s == NULL)
return 0;
/* otherwise we are dealing with a single byte character */
*s = (char) wchar;
return 1;
}