Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 4873 → Rev 4874

/contrib/sdk/sources/newlib/libc/stdlib/assert.c
0,0 → 1,76
/*
FUNCTION
<<assert>>---macro for debugging diagnostics
 
INDEX
assert
 
ANSI_SYNOPSIS
#include <assert.h>
void assert(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]>, function: <[func]>
 
If the name of the current function is not known (for example,
when using a C89 compiler that does not understand __func__),
the function location is omitted.
 
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>
 
#ifndef HAVE_ASSERT_FUNC
/* func can be NULL, in which case no function information is given. */
void
_DEFUN (__assert_func, (file, line, func, failedexpr),
const char *file _AND
int line _AND
const char *func _AND
const char *failedexpr)
{
fiprintf(stderr,
"assertion \"%s\" failed: file \"%s\", line %d%s%s\n",
failedexpr, file, line,
func ? ", function: " : "", func ? func : "");
abort();
/* NOTREACHED */
}
#endif /* HAVE_ASSERT_FUNC */
 
void
_DEFUN (__assert, (file, line, failedexpr),
const char *file _AND
int line _AND
const char *failedexpr)
{
__assert_func (file, line, NULL, failedexpr);
/* NOTREACHED */
}
/contrib/sdk/sources/newlib/libc/stdlib/atexit.c
0,0 → 1,66
/*
* 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 <stdlib.h>
#include "atexit.h"
 
/*
* Register a function to be performed at exit.
*/
 
int
_DEFUN (atexit,
(fn),
_VOID _EXFNPTR(fn, (_VOID)))
{
return __register_exitproc (__et_atexit, fn, NULL, NULL);
}
/contrib/sdk/sources/newlib/libc/stdlib/__atexit.c
0,0 → 1,99
/*
* Common routine to implement atexit-like functionality.
*/
 
#include <stddef.h>
#include <stdlib.h>
#include <reent.h>
#include <sys/lock.h>
#include "atexit.h"
 
/* Make this a weak reference to avoid pulling in malloc. */
void * malloc(size_t) _ATTRIBUTE((__weak__));
__LOCK_INIT_RECURSIVE(, __atexit_lock);
 
/*
* Register a function to be performed at exit or on shared library unload.
*/
 
int
_DEFUN (__register_exitproc,
(type, fn, arg, d),
int type _AND
void (*fn) (void) _AND
void *arg _AND
void *d)
{
struct _on_exit_args * args;
register struct _atexit *p;
 
#ifndef __SINGLE_THREAD__
__lock_acquire_recursive(__atexit_lock);
#endif
 
p = _GLOBAL_REENT->_atexit;
if (p == NULL)
_GLOBAL_REENT->_atexit = p = &_GLOBAL_REENT->_atexit0;
if (p->_ind >= _ATEXIT_SIZE)
{
#ifndef _ATEXIT_DYNAMIC_ALLOC
return -1;
#else
/* Don't dynamically allocate the atexit array if malloc is not
available. */
if (!malloc)
return -1;
 
p = (struct _atexit *) malloc (sizeof *p);
if (p == NULL)
{
#ifndef __SINGLE_THREAD__
__lock_release_recursive(__atexit_lock);
#endif
return -1;
}
p->_ind = 0;
p->_next = _GLOBAL_REENT->_atexit;
_GLOBAL_REENT->_atexit = p;
#ifndef _REENT_SMALL
p->_on_exit_args._fntypes = 0;
p->_on_exit_args._is_cxa = 0;
#endif
#endif
}
 
if (type != __et_atexit)
{
#ifdef _REENT_SMALL
args = p->_on_exit_args_ptr;
if (args == NULL)
{
if (malloc)
args = malloc (sizeof * p->_on_exit_args_ptr);
 
if (args == NULL)
{
#ifndef __SINGLE_THREAD__
__lock_release(lock);
#endif
return -1;
}
args->_fntypes = 0;
args->_is_cxa = 0;
p->_on_exit_args_ptr = args;
}
#else
args = &p->_on_exit_args;
#endif
args->_fnargs[p->_ind] = arg;
args->_fntypes |= (1 << p->_ind);
args->_dso_handle[p->_ind] = d;
if (type == __et_cxa)
args->_is_cxa |= (1 << p->_ind);
}
p->_fns[p->_ind++] = fn;
#ifndef __SINGLE_THREAD__
__lock_release_recursive(__atexit_lock);
#endif
return 0;
}
/contrib/sdk/sources/newlib/libc/stdlib/__call_atexit.c
0,0 → 1,161
/*
* COmmon routine to call call registered atexit-like routines.
*/
 
 
#include <stdlib.h>
#include <reent.h>
#include <sys/lock.h>
#include "atexit.h"
 
/* Make this a weak reference to avoid pulling in free. */
void free(void *) _ATTRIBUTE((__weak__));
 
#ifndef __SINGLE_THREAD__
extern _LOCK_RECURSIVE_T __atexit_lock;
#endif
 
#ifdef _WANT_REGISTER_FINI
 
/* If "__libc_fini" is defined, finalizers (either
"__libc_fini_array", or "_fini", as appropriate) will be run after
all user-specified atexit handlers. For example, you can define
"__libc_fini" to "_fini" in your linker script if you want the C
library, rather than startup code, to register finalizers. If you
do that, then your startup code need not contain references to
"atexit" or "exit". As a result, only applications that reference
"exit" explicitly will pull in finalization code.
 
The choice of whether to register finalizers from libc or from
startup code is deferred to link-time, rather than being a
configure-time option, so that the same C library binary can be
used with multiple BSPs, some of which register finalizers from
startup code, while others defer to the C library. */
extern char __libc_fini __attribute__((weak));
 
/* Register the application finalization function with atexit. These
finalizers should run last. Therefore, we want to call atexit as
soon as possible. */
static void
register_fini(void) __attribute__((constructor (0)));
 
static void
register_fini(void)
{
if (&__libc_fini) {
#ifdef HAVE_INITFINI_ARRAY
extern void __libc_fini_array (void);
atexit (__libc_fini_array);
#else
extern void _fini (void);
atexit (_fini);
#endif
}
}
 
#endif /* _WANT_REGISTER_FINI */
 
/*
* Call registered exit handlers. If D is null then all handlers are called,
* otherwise only the handlers from that DSO are called.
*/
 
void
_DEFUN (__call_exitprocs, (code, d),
int code _AND _PTR d)
{
register struct _atexit *p;
struct _atexit **lastp;
register struct _on_exit_args * args;
register int n;
int i;
void (*fn) (void);
 
 
#ifndef __SINGLE_THREAD__
__lock_acquire_recursive(__atexit_lock);
#endif
 
restart:
 
p = _GLOBAL_REENT->_atexit;
lastp = &_GLOBAL_REENT->_atexit;
while (p)
{
#ifdef _REENT_SMALL
args = p->_on_exit_args_ptr;
#else
args = &p->_on_exit_args;
#endif
for (n = p->_ind - 1; n >= 0; n--)
{
int ind;
 
i = 1 << n;
 
/* Skip functions not from this dso. */
if (d && (!args || args->_dso_handle[n] != d))
continue;
 
/* Remove the function now to protect against the
function calling exit recursively. */
fn = p->_fns[n];
if (n == p->_ind - 1)
p->_ind--;
else
p->_fns[n] = NULL;
 
/* Skip functions that have already been called. */
if (!fn)
continue;
 
ind = p->_ind;
 
/* Call the function. */
if (!args || (args->_fntypes & i) == 0)
fn ();
else if ((args->_is_cxa & i) == 0)
(*((void (*)(int, _PTR)) fn))(code, args->_fnargs[n]);
else
(*((void (*)(_PTR)) fn))(args->_fnargs[n]);
 
/* The function we called call atexit and registered another
function (or functions). Call these new functions before
continuing with the already registered functions. */
if (ind != p->_ind || *lastp != p)
goto restart;
}
 
#ifndef _ATEXIT_DYNAMIC_ALLOC
break;
#else
/* Don't dynamically free the atexit array if free is not
available. */
if (!free)
break;
 
/* Move to the next block. Free empty blocks except the last one,
which is part of _GLOBAL_REENT. */
if (p->_ind == 0 && p->_next)
{
/* Remove empty block from the list. */
*lastp = p->_next;
#ifdef _REENT_SMALL
if (args)
free (args);
#endif
free (p);
p = *lastp;
}
else
{
lastp = &p->_next;
p = p->_next;
}
#endif
}
#ifndef __SINGLE_THREAD__
__lock_release_recursive(__atexit_lock);
#endif
 
}
/contrib/sdk/sources/newlib/libc/stdlib/abort.c
0,0 → 1,67
/* 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: <<_exit>> and optionally, <<write>>.
*/
 
#include <stdlib.h>
#include <unistd.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
/contrib/sdk/sources/newlib/libc/stdlib/abs.c
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;
}
/contrib/sdk/sources/newlib/libc/stdlib/atexit.h
0,0 → 1,14
/*
* Common definitions for atexit-like routines
*/
 
enum __atexit_types
{
__et_atexit,
__et_onexit,
__et_cxa
};
 
void __call_exitprocs _PARAMS ((int, _PTR));
int __register_exitproc _PARAMS ((int, void (*fn) (void), _PTR, _PTR));
 
/contrib/sdk/sources/newlib/libc/stdlib/atof.c
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 <<strtof(<[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);
}
/contrib/sdk/sources/newlib/libc/stdlib/atoi.c
0,0 → 1,81
/*
FUNCTION
<<atoi>>, <<atol>>---string to integer
 
INDEX
atoi
INDEX
atol
INDEX
_atoi_r
INDEX
_atol_r
 
ANSI_SYNOPSIS
#include <stdlib.h>
int atoi(const char *<[s]>);
long atol(const char *<[s]>);
int _atoi_r(struct _reent *<[ptr]>, const char *<[s]>);
long _atol_r(struct _reent *<[ptr]>, const char *<[s]>);
 
TRAD_SYNOPSIS
#include <stdlib.h>
int atoi(<[s]>)
char *<[s]>;
 
long atol(<[s]>)
char *<[s]>;
 
int _atoi_r(<[ptr]>, <[s]>)
struct _reent *<[ptr]>;
char *<[s]>;
 
long _atol_r(<[ptr]>, <[s]>)
struct _reent *<[ptr]>;
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).>>
 
<<_atoi_r>> and <<_atol_r>> are reentrant versions of <<atoi>> and
<<atol>> respectively, passing the reentrancy struct pointer.
 
RETURNS
The functions return the converted value, if any. If no conversion was
made, <<0>> is returned.
 
PORTABILITY
<<atoi>>, <<atol>> are ANSI.
 
No supporting OS subroutines are required.
*/
 
/*
* Andy Wilson, 2-Oct-89.
*/
 
#include <stdlib.h>
#include <_ansi.h>
 
#ifndef _REENT_ONLY
int
_DEFUN (atoi, (s),
_CONST char *s)
{
return (int) strtol (s, NULL, 10);
}
#endif /* !_REENT_ONLY */
 
int
_DEFUN (_atoi_r, (s),
struct _reent *ptr _AND
_CONST char *s)
{
return (int) _strtol_r (ptr, s, NULL, 10);
}
 
/contrib/sdk/sources/newlib/libc/stdlib/atol.c
0,0 → 1,21
/*
* Andy Wilson, 2-Oct-89.
*/
 
#include <stdlib.h>
#include <_ansi.h>
 
#ifndef _REENT_ONLY
long
_DEFUN (atol, (s), _CONST char *s)
{
return strtol (s, NULL, 10);
}
#endif /* !_REENT_ONLY */
 
long
_DEFUN (_atol_r, (ptr, s), struct _reent *ptr _AND _CONST char *s)
{
return _strtol_r (ptr, s, NULL, 10);
}
 
/contrib/sdk/sources/newlib/libc/stdlib/calloc.c
0,0 → 1,69
#ifdef MALLOC_PROVIDED
int _dummy_calloc = 1;
#else
/*
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
#endif /* MALLOC_PROVIDED */
/contrib/sdk/sources/newlib/libc/stdlib/div.c
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
@ifnottex
<[n]>/<[d]>,
@end ifnottex
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);
}
/contrib/sdk/sources/newlib/libc/stdlib/dtoa.c
0,0 → 1,862
/****************************************************************
*
* 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 = NULL, *mhi, *S;
double ds;
char *s, *s0;
 
d.d = _d;
 
_REENT_CHECK_MP(ptr);
if (_REENT_MP_RESULT(ptr))
{
_REENT_MP_RESULT(ptr)->_k = _REENT_MP_RESULT_K(ptr);
_REENT_MP_RESULT(ptr)->_maxwds = 1 << _REENT_MP_RESULT_K(ptr);
Bfree (ptr, _REENT_MP_RESULT(ptr));
_REENT_MP_RESULT(ptr) = 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))) != 0)
{
#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);
#if defined (_DOUBLE_IS_32BITS)
x = word0 (d) << (32 - i);
#else
x = (i > 32) ? (word0 (d) << (64 - i)) | (word1 (d) >> (i - 32))
: (word1 (d) << (32 - i));
#endif
d2.d = x;
word0 (d2) -= 31 * Exp_msk1; /* adjust exponent */
i -= (Bias + (P - 1) - 1) + 1;
denorm = 1;
}
#endif
#if defined (_DOUBLE_IS_32BITS)
ds = (d2.d - 1.5) * 0.289529651 + 0.176091269 + i * 0.30103001;
#else
ds = (d2.d - 1.5) * 0.289529654602168 + 0.1760912590558 + i * 0.301029995663981;
#endif
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;
ilim = ilim1 = -1;
switch (mode)
{
case 0:
case 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 (_REENT_MP_RESULT_K(ptr) = 0; sizeof (_Bigint) - sizeof (__ULong) + j <= i;
j <<= 1)
_REENT_MP_RESULT_K(ptr)++;
_REENT_MP_RESULT(ptr) = Balloc (ptr, _REENT_MP_RESULT_K(ptr));
s = s0 = (char *) _REENT_MP_RESULT(ptr);
 
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) != 0)
{
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) != 0)
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. */
 
spec_case = 0;
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;
}
}
 
/* 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) != 0)
i = 32 - i;
#else
if ((i = ((s5 ? 32 - hi0bits (S->_x[S->_wds - 1]) : 1) + s2) & 0xf) != 0)
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;
}
/contrib/sdk/sources/newlib/libc/stdlib/dtoastub.c
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 _REENT_ONLY
 
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
/contrib/sdk/sources/newlib/libc/stdlib/exit.c
0,0 → 1,66
/*
* 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>
#include "atexit.h"
 
/*
* Exit, flushing stdio buffers if necessary.
*/
 
void
_DEFUN (exit, (code),
int code)
{
__call_exitprocs (code, NULL);
 
if (_GLOBAL_REENT->__cleanup)
(*_GLOBAL_REENT->__cleanup) (_GLOBAL_REENT);
_exit (code);
}
/contrib/sdk/sources/newlib/libc/stdlib/gd_qnan.h
0,0 → 1,33
#ifdef __IEEE_BIG_ENDIAN
 
#define f_QNAN 0x7fc00000
#define d_QNAN0 0x7ff80000
#define d_QNAN1 0x0
#define ld_QNAN0 0x7ff80000
#define ld_QNAN1 0x0
#define ld_QNAN2 0x0
#define ld_QNAN3 0x0
#define ldus_QNAN0 0x7ff8
#define ldus_QNAN1 0x0
#define ldus_QNAN2 0x0
#define ldus_QNAN3 0x0
#define ldus_QNAN4 0x0
 
#elif defined(__IEEE_LITTLE_ENDIAN)
 
#define f_QNAN 0xffc00000
#define d_QNAN0 0x0
#define d_QNAN1 0xfff80000
#define ld_QNAN0 0x0
#define ld_QNAN1 0xc0000000
#define ld_QNAN2 0xffff
#define ld_QNAN3 0x0
#define ldus_QNAN0 0x0
#define ldus_QNAN1 0x0
#define ldus_QNAN2 0x0
#define ldus_QNAN3 0xc000
#define ldus_QNAN4 0xffff
 
#else
#error IEEE endian not defined
#endif
/contrib/sdk/sources/newlib/libc/stdlib/gdtoa-gethex.c
0,0 → 1,354
/****************************************************************
 
The author of this software is David M. Gay.
 
Copyright (C) 1998 by Lucent Technologies
All Rights Reserved
 
Permission to use, copy, modify, and distribute this software and
its documentation for any purpose and without fee is hereby
granted, provided that the above copyright notice appear in all
copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of Lucent or any of its entities
not be used in advertising or publicity pertaining to
distribution of the software without specific, written prior
permission.
 
LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
THIS SOFTWARE.
 
****************************************************************/
 
/* Please send bug reports to David M. Gay (dmg at acm dot org,
* with " at " changed at "@" and " dot " changed to "."). */
 
#include <_ansi.h>
#include <reent.h>
#include <string.h>
#include "mprec.h"
#include "gdtoa.h"
#include "gd_qnan.h"
#include "locale.h"
 
unsigned char hexdig[256];
 
static void
_DEFUN (htinit, (h, s, inc),
unsigned char *h _AND
unsigned char *s _AND
int inc)
{
int i, j;
for(i = 0; (j = s[i]) !=0; i++)
h[j] = i + inc;
}
 
void
_DEFUN_VOID (hexdig_init)
{
#define USC (unsigned char *)
htinit(hexdig, USC "0123456789", 0x10);
htinit(hexdig, USC "abcdef", 0x10 + 10);
htinit(hexdig, USC "ABCDEF", 0x10 + 10);
}
 
static void
_DEFUN(rshift, (b, k),
_Bigint *b _AND
int k)
{
__ULong *x, *x1, *xe, y;
int n;
 
x = x1 = b->_x;
n = k >> kshift;
if (n < b->_wds) {
xe = x + b->_wds;
x += n;
if (k &= kmask) {
n = ULbits - k;
y = *x++ >> k;
while(x < xe) {
*x1++ = (y | (*x << n)) & ALL_ON;
y = *x++ >> k;
}
if ((*x1 = y) !=0)
x1++;
}
else
while(x < xe)
*x1++ = *x++;
}
if ((b->_wds = x1 - b->_x) == 0)
b->_x[0] = 0;
}
 
static _Bigint *
_DEFUN (increment, (ptr, b),
struct _reent *ptr _AND
_Bigint *b)
{
__ULong *x, *xe;
_Bigint *b1;
#ifdef Pack_16
__ULong carry = 1, y;
#endif
 
x = b->_x;
xe = x + b->_wds;
#ifdef Pack_32
do {
if (*x < (__ULong)0xffffffffL) {
++*x;
return b;
}
*x++ = 0;
} while(x < xe);
#else
do {
y = *x + carry;
carry = y >> 16;
*x++ = y & 0xffff;
if (!carry)
return b;
} while(x < xe);
if (carry)
#endif
{
if (b->_wds >= b->_maxwds) {
b1 = Balloc(ptr, b->_k+1);
Bcopy(b1, b);
Bfree(ptr, b);
b = b1;
}
b->_x[b->_wds++] = 1;
}
return b;
}
 
 
int
_DEFUN(gethex, (ptr, sp, fpi, exp, bp, sign),
struct _reent *ptr _AND
_CONST char **sp _AND
FPI *fpi _AND
Long *exp _AND
_Bigint **bp _AND
int sign)
{
_Bigint *b;
_CONST unsigned char *decpt, *s0, *s, *s1;
int esign, havedig, irv, k, n, nbits, up, zret;
__ULong L, lostbits, *x;
Long e, e1;
unsigned char *decimalpoint = (unsigned char *)
_localeconv_r (ptr)->decimal_point;
size_t decp_len = strlen ((const char *) decimalpoint);
unsigned char decp_end = decimalpoint[decp_len - 1];
 
if (!hexdig['0'])
hexdig_init();
havedig = 0;
s0 = *(_CONST unsigned char **)sp + 2;
while(s0[havedig] == '0')
havedig++;
s0 += havedig;
s = s0;
decpt = 0;
zret = 0;
e = 0;
if (!hexdig[*s]) {
zret = 1;
if (strncmp ((const char *) s, (const char *) decimalpoint,
decp_len) != 0)
goto pcheck;
decpt = (s += decp_len);
if (!hexdig[*s])
goto pcheck;
while(*s == '0')
s++;
if (hexdig[*s])
zret = 0;
havedig = 1;
s0 = s;
}
while(hexdig[*s])
s++;
if (strncmp ((const char *) s, (const char *) decimalpoint,
decp_len) == 0
&& !decpt) {
decpt = (s += decp_len);
while(hexdig[*s])
s++;
}
if (decpt)
e = -(((Long)(s-decpt)) << 2);
pcheck:
s1 = s;
switch(*s) {
case 'p':
case 'P':
esign = 0;
switch(*++s) {
case '-':
esign = 1;
/* no break */
case '+':
s++;
}
if ((n = hexdig[*s]) == 0 || n > 0x19) {
s = s1;
break;
}
e1 = n - 0x10;
while((n = hexdig[*++s]) !=0 && n <= 0x19)
e1 = 10*e1 + n - 0x10;
if (esign)
e1 = -e1;
e += e1;
}
*sp = (char*)s;
if (zret)
return havedig ? STRTOG_Zero : STRTOG_NoNumber;
n = s1 - s0 - 1;
for(k = 0; n > 7; n >>= 1)
k++;
b = Balloc(ptr, k);
x = b->_x;
n = 0;
L = 0;
while(s1 > s0) {
if (*--s1 == decp_end && s1 - decp_len + 1 >= s0
&& strncmp ((const char *) s1 - decp_len + 1,
(const char *) decimalpoint, decp_len) == 0) {
s1 -= decp_len - 1; /* Note the --s1 above! */
continue;
}
if (n == 32) {
*x++ = L;
L = 0;
n = 0;
}
L |= (hexdig[*s1] & 0x0f) << n;
n += 4;
}
*x++ = L;
b->_wds = n = x - b->_x;
n = 32*n - hi0bits(L);
nbits = fpi->nbits;
lostbits = 0;
x = b->_x;
if (n > nbits) {
n -= nbits;
if (any_on(b,n)) {
lostbits = 1;
k = n - 1;
if (x[k>>kshift] & 1 << (k & kmask)) {
lostbits = 2;
if (k > 1 && any_on(b,k-1))
lostbits = 3;
}
}
rshift(b, n);
e += n;
}
else if (n < nbits) {
n = nbits - n;
b = lshift(ptr, b, n);
e -= n;
x = b->_x;
}
if (e > fpi->emax) {
ovfl:
Bfree(ptr, b);
*bp = 0;
return STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi;
}
irv = STRTOG_Normal;
if (e < fpi->emin) {
irv = STRTOG_Denormal;
n = fpi->emin - e;
if (n >= nbits) {
switch (fpi->rounding) {
case FPI_Round_near:
if (n == nbits && (n < 2 || any_on(b,n-1)))
goto one_bit;
break;
case FPI_Round_up:
if (!sign)
goto one_bit;
break;
case FPI_Round_down:
if (sign) {
one_bit:
*exp = fpi->emin;
x[0] = b->_wds = 1;
*bp = b;
return STRTOG_Denormal | STRTOG_Inexhi
| STRTOG_Underflow;
}
}
Bfree(ptr, b);
*bp = 0;
return STRTOG_Zero | STRTOG_Inexlo | STRTOG_Underflow;
}
k = n - 1;
if (lostbits)
lostbits = 1;
else if (k > 0)
lostbits = any_on(b,k);
if (x[k>>kshift] & 1 << (k & kmask))
lostbits |= 2;
nbits -= n;
rshift(b,n);
e = fpi->emin;
}
if (lostbits) {
up = 0;
switch(fpi->rounding) {
case FPI_Round_zero:
break;
case FPI_Round_near:
if ((lostbits & 2)
&& ((lostbits & 1) | (x[0] & 1)))
up = 1;
break;
case FPI_Round_up:
up = 1 - sign;
break;
case FPI_Round_down:
up = sign;
}
if (up) {
k = b->_wds;
b = increment(ptr, b);
x = b->_x;
if (irv == STRTOG_Denormal) {
if (nbits == fpi->nbits - 1
&& x[nbits >> kshift] & 1 << (nbits & kmask))
irv = STRTOG_Normal;
}
else if ((b->_wds > k)
|| ((n = nbits & kmask) !=0
&& (hi0bits(x[k-1]) < 32-n))) {
rshift(b,1);
if (++e > fpi->emax)
goto ovfl;
}
irv |= STRTOG_Inexhi;
}
else
irv |= STRTOG_Inexlo;
}
*bp = b;
*exp = e;
return irv;
}
 
/contrib/sdk/sources/newlib/libc/stdlib/gdtoa-hexnan.c
0,0 → 1,142
/****************************************************************
 
The author of this software is David M. Gay.
 
Copyright (C) 2000 by Lucent Technologies
All Rights Reserved
 
Permission to use, copy, modify, and distribute this software and
its documentation for any purpose and without fee is hereby
granted, provided that the above copyright notice appear in all
copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of Lucent or any of its entities
not be used in advertising or publicity pertaining to
distribution of the software without specific, written prior
permission.
 
LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
THIS SOFTWARE.
 
****************************************************************/
 
/* Please send bug reports to
David M. Gay
Bell Laboratories, Room 2C-463
600 Mountain Avenue
Murray Hill, NJ 07974-0636
U.S.A.
dmg@bell-labs.com
*/
 
/* Modified 06-21-2006 by Jeff Johnston to work with newlib. */
 
#include <_ansi.h>
#include <reent.h>
#include <string.h>
#include "mprec.h"
#include "gdtoa.h"
 
#ifdef INFNAN_CHECK
static void
_DEFUN (L_shift, (x, x1, i),
__ULong *x _AND
__ULong *x1 _AND
int i)
{
int j;
 
i = 8 - i;
i <<= 2;
j = ULbits - i;
do {
*x |= x[1] << j;
x[1] >>= i;
} while(++x < x1);
}
 
int
_DEFUN (hexnan, (sp, fpi, x0),
_CONST char **sp _AND
FPI *fpi _AND
__ULong *x0)
{
__ULong c, h, *x, *x1, *xe;
_CONST char *s;
int havedig, hd0, i, nbits;
 
if (!hexdig['0'])
hexdig_init();
nbits = fpi->nbits;
x = x0 + (nbits >> kshift);
if (nbits & kmask)
x++;
*--x = 0;
x1 = xe = x;
havedig = hd0 = i = 0;
s = *sp;
while((c = *(_CONST unsigned char*)++s)) {
if (!(h = hexdig[c])) {
if (c <= ' ') {
if (hd0 < havedig) {
if (x < x1 && i < 8)
L_shift(x, x1, i);
if (x <= x0) {
i = 8;
continue;
}
hd0 = havedig;
*--x = 0;
x1 = x;
i = 0;
}
continue;
}
if (/*(*/ c == ')') {
*sp = s + 1;
break;
}
return STRTOG_NaN;
}
havedig++;
if (++i > 8) {
if (x <= x0)
continue;
i = 1;
*--x = 0;
}
*x = ((*x << 4) | (h & 0xf));
}
if (!havedig)
return STRTOG_NaN;
if (x < x1 && i < 8)
L_shift(x, x1, i);
if (x > x0) {
x1 = x0;
do *x1++ = *x++;
while(x <= xe);
do *x1++ = 0;
while(x1 <= xe);
}
else {
/* truncate high-order word if necessary */
if ( (i = nbits & (ULbits-1)) !=0)
*xe &= ((__ULong)0xffffffff) >> (ULbits - i);
}
for(x1 = xe;; --x1) {
if (*x1 != 0)
break;
if (x1 == x0) {
*x1 = 1;
break;
}
}
return STRTOG_NaNbits;
}
#endif /* INFNAN_CHECK */
/contrib/sdk/sources/newlib/libc/stdlib/gdtoa.h
0,0 → 1,72
/****************************************************************
 
The author of this software is David M. Gay.
 
Copyright (C) 1998 by Lucent Technologies
All Rights Reserved
 
Permission to use, copy, modify, and distribute this software and
its documentation for any purpose and without fee is hereby
granted, provided that the above copyright notice appear in all
copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of Lucent or any of its entities
not be used in advertising or publicity pertaining to
distribution of the software without specific, written prior
permission.
 
LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
THIS SOFTWARE.
 
****************************************************************/
 
/* Please send bug reports to David M. Gay (dmg at acm dot org,
* with " at " changed at "@" and " dot " changed to "."). */
 
#ifndef GDTOA_H_INCLUDED
#define GDTOA_H_INCLUDED
 
 
enum { /* return values from strtodg */
STRTOG_Zero = 0,
STRTOG_Normal = 1,
STRTOG_Denormal = 2,
STRTOG_Infinite = 3,
STRTOG_NaN = 4,
STRTOG_NaNbits = 5,
STRTOG_NoNumber = 6,
STRTOG_Retmask = 7,
 
/* The following may be or-ed into one of the above values. */
 
STRTOG_Neg = 0x08,
STRTOG_Inexlo = 0x10,
STRTOG_Inexhi = 0x20,
STRTOG_Inexact = 0x30,
STRTOG_Underflow= 0x40,
STRTOG_Overflow = 0x80
};
 
typedef struct
FPI {
int nbits;
int emin;
int emax;
int rounding;
int sudden_underflow;
} FPI;
 
enum { /* FPI.rounding values: same as FLT_ROUNDS */
FPI_Round_zero = 0,
FPI_Round_near = 1,
FPI_Round_up = 2,
FPI_Round_down = 3
};
 
#endif /* GDTOA_H_INCLUDED */
/contrib/sdk/sources/newlib/libc/stdlib/getenv.c
0,0 → 1,93
/*
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>>.
*/
 
/*
* Copyright (c) 1987, 2000 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.
*/
 
#ifndef _REENT_ONLY
 
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
 
/*
* _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)
{
return NULL; //_findenv_r (_REENT, name, offset);
}
 
/*
* getenv --
* Returns ptr to value associated with name, if any, else NULL.
*/
 
char *
_DEFUN (getenv, (name),
_CONST char *name)
{
int offset;
 
return NULL; //_findenv_r (_REENT, name, &offset);
}
 
#endif /* !_REENT_ONLY */
/contrib/sdk/sources/newlib/libc/stdlib/local.h
0,0 → 1,66
/* Misc. local definitions for libc/stdlib */
 
#ifndef _LOCAL_H_
#define _LOCAL_H_
 
char * _EXFUN(_gcvt,(struct _reent *, double , int , char *, char, int));
 
char *__locale_charset(_NOARGS);
 
#ifndef __mbstate_t_defined
#include <wchar.h>
#endif
 
extern int (*__wctomb) (struct _reent *, char *, wchar_t, const char *,
mbstate_t *);
int __ascii_wctomb (struct _reent *, char *, wchar_t, const char *,
mbstate_t *);
#ifdef _MB_CAPABLE
int __utf8_wctomb (struct _reent *, char *, wchar_t, const char *, mbstate_t *);
int __sjis_wctomb (struct _reent *, char *, wchar_t, const char *, mbstate_t *);
int __eucjp_wctomb (struct _reent *, char *, wchar_t, const char *,
mbstate_t *);
int __jis_wctomb (struct _reent *, char *, wchar_t, const char *, mbstate_t *);
int __iso_wctomb (struct _reent *, char *, wchar_t, const char *, mbstate_t *);
int __cp_wctomb (struct _reent *, char *, wchar_t, const char *, mbstate_t *);
#ifdef __CYGWIN__
int __gbk_wctomb (struct _reent *, char *, wchar_t, const char *, mbstate_t *);
int __kr_wctomb (struct _reent *, char *, wchar_t, const char *, mbstate_t *);
int __big5_wctomb (struct _reent *, char *, wchar_t, const char *, mbstate_t *);
#endif
#endif
 
extern int (*__mbtowc) (struct _reent *, wchar_t *, const char *, size_t,
const char *, mbstate_t *);
int __ascii_mbtowc (struct _reent *, wchar_t *, const char *, size_t,
const char *, mbstate_t *);
#ifdef _MB_CAPABLE
int __utf8_mbtowc (struct _reent *, wchar_t *, const char *, size_t,
const char *, mbstate_t *);
int __sjis_mbtowc (struct _reent *, wchar_t *, const char *, size_t,
const char *, mbstate_t *);
int __eucjp_mbtowc (struct _reent *, wchar_t *, const char *, size_t,
const char *, mbstate_t *);
int __jis_mbtowc (struct _reent *, wchar_t *, const char *, size_t,
const char *, mbstate_t *);
int __iso_mbtowc (struct _reent *, wchar_t *, const char *, size_t,
const char *, mbstate_t *);
int __cp_mbtowc (struct _reent *, wchar_t *, const char *, size_t,
const char *, mbstate_t *);
#ifdef __CYGWIN__
int __gbk_mbtowc (struct _reent *, wchar_t *, const char *, size_t,
const char *, mbstate_t *);
int __kr_mbtowc (struct _reent *, wchar_t *, const char *, size_t,
const char *, mbstate_t *);
int __big5_mbtowc (struct _reent *, wchar_t *, const char *, size_t,
const char *, mbstate_t *);
#endif
#endif
 
extern wchar_t __iso_8859_conv[14][0x60];
int __iso_8859_index (const char *);
 
extern wchar_t __cp_conv[][0x80];
int __cp_index (const char *);
 
#endif
/contrib/sdk/sources/newlib/libc/stdlib/malloc.c
0,0 → 1,227
/* 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
reallocf
INDEX
free
INDEX
memalign
INDEX
malloc_usable_size
INDEX
_malloc_r
INDEX
_realloc_r
INDEX
_reallocf_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 *reallocf(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 *_reallocf_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]>;
 
char *reallocf(<[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]>;
 
char *_reallocf_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 <<reallocf>> function behaves just like <<realloc>> except if the
function is required to allocate new storage and this fails. In this
case <<reallocf>> will free the original object passed in whereas
<<realloc>> will not.
 
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>>, <<_reallocf_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) */
/contrib/sdk/sources/newlib/libc/stdlib/mallocr.c
0,0 → 1,2171
/*
This is a version (aka dlmalloc) of malloc/free/realloc written by
Doug Lea and released to the public domain, as explained at
http://creativecommons.org/licenses/publicdomain. Send questions,
comments, complaints, performance data, etc to dl@cs.oswego.edu
 
* Version 2.8.4 Wed May 27 09:56:23 2009 Doug Lea (dl at gee)
 
Note: There may be an updated version of this malloc obtainable at
ftp://gee.cs.oswego.edu/pub/misc/malloc.c
Check before installing!
 
* Quickstart
 
This library is all in one file to simplify the most common usage:
ftp it, compile it (-O3), and link it into another program. All of
the compile-time options default to reasonable values for use on
most platforms. You might later want to step through various
compile-time and dynamic tuning options.
 
For convenience, an include file for code using this malloc is at:
ftp://gee.cs.oswego.edu/pub/misc/malloc-2.8.4.h
You don't really need this .h file unless you call functions not
defined in your system include files. The .h file contains only the
excerpts from this file needed for using this malloc on ANSI C/C++
systems, so long as you haven't changed compile-time options about
naming and tuning parameters. If you do, then you can create your
own malloc.h that does include all settings by cutting at the point
indicated below. Note that you may already by default be using a C
library containing a malloc that is based on some version of this
malloc (for example in linux). You might still want to use the one
in this file to customize settings or to avoid overheads associated
with library versions.
 
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
 
 
struct malloc_chunk {
size_t prev_foot; /* Size of previous chunk (if free). */
size_t head; /* Size and inuse bits. */
struct malloc_chunk* fd; /* double links -- used only if free. */
struct malloc_chunk* bk;
};
 
typedef struct malloc_chunk mchunk;
typedef struct malloc_chunk* mchunkptr;
typedef struct malloc_chunk* sbinptr; /* The type of bins of chunks */
typedef unsigned int bindex_t; /* Described below */
typedef unsigned int binmap_t; /* Described below */
typedef unsigned int flag_t; /* The type of various bit flag sets */
 
 
 
/* ------------------- size_t and alignment properties -------------------- */
 
/* The maximum possible size_t value has all bits set */
#define MAX_SIZE_T (~(size_t)0)
 
void *user_alloc(size_t size)
{
void *val;
 
// __asm__("int3");
 
__asm__ __volatile__(
"int $0x40"
:"=a"(val)
:"a"(68),"b"(12),"c"(size));
return val;
}
 
static inline
int user_free(void *mem)
{
int val;
 
// __asm__("int3");
 
__asm__ __volatile__(
"int $0x40"
:"=a"(val)
:"a"(68),"b"(13),"c"(mem));
return val;
}
 
 
/* ------------------- size_t and alignment properties -------------------- */
 
/* The byte and bit size of a size_t */
#define SIZE_T_SIZE (sizeof(size_t))
#define SIZE_T_BITSIZE (sizeof(size_t) << 3)
 
/* Some constants coerced to size_t */
/* Annoying but necessary to avoid errors on some platforms */
#define SIZE_T_ZERO ((size_t)0)
#define SIZE_T_ONE ((size_t)1)
#define SIZE_T_TWO ((size_t)2)
#define SIZE_T_FOUR ((size_t)4)
#define TWO_SIZE_T_SIZES (SIZE_T_SIZE<<1)
#define FOUR_SIZE_T_SIZES (SIZE_T_SIZE<<2)
#define SIX_SIZE_T_SIZES (FOUR_SIZE_T_SIZES+TWO_SIZE_T_SIZES)
#define HALF_MAX_SIZE_T (MAX_SIZE_T / 2U)
 
#define USE_LOCK_BIT (2U)
#define USE_MMAP_BIT (SIZE_T_ONE)
#define USE_NONCONTIGUOUS_BIT (4U)
 
/* segment bit set in create_mspace_with_base */
#define EXTERN_BIT (8U)
 
#define HAVE_MMAP 1
#define CALL_MMAP(s) MMAP_DEFAULT(s)
#define CALL_MUNMAP(a, s) MUNMAP_DEFAULT((a), (s))
#define CALL_MREMAP(addr, osz, nsz, mv) MFAIL
 
#define calloc_must_clear(p) (!is_mmapped(p))
 
#define MALLOC_FAILURE_ACTION
 
#define MAX_RELEASE_CHECK_RATE 4095
#define NO_SEGMENT_TRAVERSAL 1
#define MALLOC_ALIGNMENT ((size_t)8U)
#define CHUNK_OVERHEAD (SIZE_T_SIZE)
#define DEFAULT_GRANULARITY ((size_t)512U * (size_t)1024U)
#define DEFAULT_MMAP_THRESHOLD ((size_t)1024U * (size_t)1024U)
#define DEFAULT_TRIM_THRESHOLD ((size_t)2048U * (size_t)1024U)
 
/* The bit mask value corresponding to MALLOC_ALIGNMENT */
#define CHUNK_ALIGN_MASK (MALLOC_ALIGNMENT - SIZE_T_ONE)
 
/* True if address a has acceptable alignment */
#define is_aligned(A) (((size_t)((A)) & (CHUNK_ALIGN_MASK)) == 0)
 
/* the number of bytes to offset an address to align it */
#define align_offset(A)\
((((size_t)(A) & CHUNK_ALIGN_MASK) == 0)? 0 :\
((MALLOC_ALIGNMENT - ((size_t)(A) & CHUNK_ALIGN_MASK)) & CHUNK_ALIGN_MASK))
 
 
#define MFAIL ((void*)(MAX_SIZE_T))
#define CMFAIL ((char*)(MFAIL)) /* defined for convenience */
 
/* For sys_alloc, enough padding to ensure can malloc request on success */
#define SYS_ALLOC_PADDING (TOP_FOOT_SIZE + MALLOC_ALIGNMENT)
 
/*
TOP_FOOT_SIZE is padding at the end of a segment, including space
that may be needed to place segment records and fenceposts when new
noncontiguous segments are added.
*/
#define TOP_FOOT_SIZE\
(align_offset(chunk2mem(0))+pad_request(sizeof(struct malloc_segment))+MIN_CHUNK_SIZE)
 
/* ------------------- Chunks sizes and alignments ----------------------- */
 
#define MCHUNK_SIZE (sizeof(mchunk))
 
/* MMapped chunks need a second word of overhead ... */
#define MMAP_CHUNK_OVERHEAD (TWO_SIZE_T_SIZES)
/* ... and additional padding for fake next-chunk at foot */
#define MMAP_FOOT_PAD (FOUR_SIZE_T_SIZES)
 
/* The smallest size we can malloc is an aligned minimal chunk */
#define MIN_CHUNK_SIZE\
((MCHUNK_SIZE + CHUNK_ALIGN_MASK) & ~CHUNK_ALIGN_MASK)
 
/* conversion from malloc headers to user pointers, and back */
#define chunk2mem(p) ((void*)((char*)(p) + TWO_SIZE_T_SIZES))
#define mem2chunk(mem) ((mchunkptr)((char*)(mem) - TWO_SIZE_T_SIZES))
/* chunk associated with aligned address A */
#define align_as_chunk(A) (mchunkptr)((A) + align_offset(chunk2mem(A)))
 
/* Bounds on request (not chunk) sizes. */
#define MAX_REQUEST ((-MIN_CHUNK_SIZE) << 2)
#define MIN_REQUEST (MIN_CHUNK_SIZE - CHUNK_OVERHEAD - SIZE_T_ONE)
 
/* pad request bytes into a usable size */
#define pad_request(req) \
(((req) + CHUNK_OVERHEAD + CHUNK_ALIGN_MASK) & ~CHUNK_ALIGN_MASK)
 
/* pad request, checking for minimum (but not maximum) */
#define request2size(req) \
(((req) < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(req))
 
/* ------------------ Operations on head and foot fields ----------------- */
 
/*
The head field of a chunk is or'ed with PINUSE_BIT when previous
adjacent chunk in use, and or'ed with CINUSE_BIT if this chunk is in
use, unless mmapped, in which case both bits are cleared.
 
FLAG4_BIT is not used by this malloc, but might be useful in extensions.
*/
 
#define PINUSE_BIT (SIZE_T_ONE)
#define CINUSE_BIT (SIZE_T_TWO)
#define FLAG4_BIT (SIZE_T_FOUR)
#define INUSE_BITS (PINUSE_BIT|CINUSE_BIT)
#define FLAG_BITS (PINUSE_BIT|CINUSE_BIT|FLAG4_BIT)
 
/* Head value for fenceposts */
#define FENCEPOST_HEAD (INUSE_BITS|SIZE_T_SIZE)
 
/* extraction of fields from head words */
#define cinuse(p) ((p)->head & CINUSE_BIT)
#define pinuse(p) ((p)->head & PINUSE_BIT)
#define is_inuse(p) (((p)->head & INUSE_BITS) != PINUSE_BIT)
#define is_mmapped(p) (((p)->head & INUSE_BITS) == 0)
 
#define chunksize(p) ((p)->head & ~(FLAG_BITS))
 
#define clear_pinuse(p) ((p)->head &= ~PINUSE_BIT)
 
/* Treat space at ptr +/- offset as a chunk */
#define chunk_plus_offset(p, s) ((mchunkptr)(((char*)(p)) + (s)))
#define chunk_minus_offset(p, s) ((mchunkptr)(((char*)(p)) - (s)))
 
/* Ptr to next or previous physical malloc_chunk. */
#define next_chunk(p) ((mchunkptr)( ((char*)(p)) + ((p)->head & ~FLAG_BITS)))
#define prev_chunk(p) ((mchunkptr)( ((char*)(p)) - ((p)->prev_foot) ))
 
/* extract next chunk's pinuse bit */
#define next_pinuse(p) ((next_chunk(p)->head) & PINUSE_BIT)
 
/* Set size, pinuse bit, and foot */
#define set_size_and_pinuse_of_free_chunk(p, s)\
((p)->head = (s|PINUSE_BIT), set_foot(p, s))
 
/* Set size, pinuse bit, foot, and clear next pinuse */
#define set_free_with_pinuse(p, s, n)\
(clear_pinuse(n), set_size_and_pinuse_of_free_chunk(p, s))
 
/* Get the internal overhead associated with chunk p */
#define overhead_for(p)\
(is_mmapped(p)? MMAP_CHUNK_OVERHEAD : CHUNK_OVERHEAD)
 
 
struct malloc_tree_chunk {
/* The first four fields must be compatible with malloc_chunk */
size_t prev_foot;
size_t head;
struct malloc_tree_chunk* fd;
struct malloc_tree_chunk* bk;
 
struct malloc_tree_chunk* child[2];
struct malloc_tree_chunk* parent;
bindex_t index;
};
 
typedef struct malloc_tree_chunk tchunk;
typedef struct malloc_tree_chunk* tchunkptr;
typedef struct malloc_tree_chunk* tbinptr; /* The type of bins of trees */
 
/* A little helper macro for trees */
#define leftmost_child(t) ((t)->child[0] != 0? (t)->child[0] : (t)->child[1])
 
 
struct malloc_segment {
char* base; /* base address */
size_t size; /* allocated size */
struct malloc_segment* next; /* ptr to next segment */
flag_t sflags; /* mmap and extern flag */
};
 
#define is_mmapped_segment(S) ((S)->sflags & USE_MMAP_BIT)
#define is_extern_segment(S) ((S)->sflags & EXTERN_BIT)
 
typedef struct malloc_segment msegment;
typedef struct malloc_segment* msegmentptr;
 
/* ---------------------------- malloc_state ----------------------------- */
 
/*
A malloc_state holds all of the bookkeeping for a space.
The main fields are:
 
Top
The topmost chunk of the currently active segment. Its size is
cached in topsize. The actual size of topmost space is
topsize+TOP_FOOT_SIZE, which includes space reserved for adding
fenceposts and segment records if necessary when getting more
space from the system. The size at which to autotrim top is
cached from mparams in trim_check, except that it is disabled if
an autotrim fails.
 
Designated victim (dv)
This is the preferred chunk for servicing small requests that
don't have exact fits. It is normally the chunk split off most
recently to service another small request. Its size is cached in
dvsize. The link fields of this chunk are not maintained since it
is not kept in a bin.
 
SmallBins
An array of bin headers for free chunks. These bins hold chunks
with sizes less than MIN_LARGE_SIZE bytes. Each bin contains
chunks of all the same size, spaced 8 bytes apart. To simplify
use in double-linked lists, each bin header acts as a malloc_chunk
pointing to the real first node, if it exists (else pointing to
itself). This avoids special-casing for headers. But to avoid
waste, we allocate only the fd/bk pointers of bins, and then use
repositioning tricks to treat these as the fields of a chunk.
 
TreeBins
Treebins are pointers to the roots of trees holding a range of
sizes. There are 2 equally spaced treebins for each power of two
from TREE_SHIFT to TREE_SHIFT+16. The last bin holds anything
larger.
 
Bin maps
There is one bit map for small bins ("smallmap") and one for
treebins ("treemap). Each bin sets its bit when non-empty, and
clears the bit when empty. Bit operations are then used to avoid
bin-by-bin searching -- nearly all "search" is done without ever
looking at bins that won't be selected. The bit maps
conservatively use 32 bits per map word, even if on 64bit system.
For a good description of some of the bit-based techniques used
here, see Henry S. Warren Jr's book "Hacker's Delight" (and
supplement at http://hackersdelight.org/). Many of these are
intended to reduce the branchiness of paths through malloc etc, as
well as to reduce the number of memory locations read or written.
 
Segments
A list of segments headed by an embedded malloc_segment record
representing the initial space.
 
Address check support
The least_addr field is the least address ever obtained from
MORECORE or MMAP. Attempted frees and reallocs of any address less
than this are trapped (unless INSECURE is defined).
 
Magic tag
A cross-check field that should always hold same value as mparams.magic.
 
Flags
Bits recording whether to use MMAP, locks, or contiguous MORECORE
 
Statistics
Each space keeps track of current and maximum system memory
obtained via MORECORE or MMAP.
 
Trim support
Fields holding the amount of unused topmost memory that should trigger
timming, and a counter to force periodic scanning to release unused
non-topmost segments.
 
Locking
If USE_LOCKS is defined, the "mutex" lock is acquired and released
around every public call using this mspace.
 
Extension support
A void* pointer and a size_t field that can be used to help implement
extensions to this malloc.
*/
 
/* Bin types, widths and sizes */
#define NSMALLBINS (32U)
#define NTREEBINS (32U)
#define SMALLBIN_SHIFT (3U)
#define SMALLBIN_WIDTH (SIZE_T_ONE << SMALLBIN_SHIFT)
#define TREEBIN_SHIFT (8U)
#define MIN_LARGE_SIZE (SIZE_T_ONE << TREEBIN_SHIFT)
#define MAX_SMALL_SIZE (MIN_LARGE_SIZE - SIZE_T_ONE)
#define MAX_SMALL_REQUEST (MAX_SMALL_SIZE - CHUNK_ALIGN_MASK - CHUNK_OVERHEAD)
 
struct malloc_state {
binmap_t smallmap;
binmap_t treemap;
size_t dvsize;
size_t topsize;
char* least_addr;
mchunkptr dv;
mchunkptr top;
size_t trim_check;
size_t release_checks;
size_t magic;
mchunkptr smallbins[(NSMALLBINS+1)*2];
tbinptr treebins[NTREEBINS];
size_t footprint;
size_t max_footprint;
flag_t mflags;
__libc_lock_recursive_t lock; /* locate lock among fields that rarely change */
msegment seg;
void* extp; /* Unused but available for extensions */
size_t exts;
};
 
typedef struct malloc_state* mstate;
 
/* ------------- Global malloc_state and malloc_params ------------------- */
 
/*
malloc_params holds global properties, including those that can be
dynamically set using mallopt. There is a single instance, mparams,
initialized in init_mparams. Note that the non-zeroness of "magic"
also serves as an initialization flag.
*/
 
struct malloc_params
{
volatile size_t magic;
size_t page_size;
size_t granularity;
size_t mmap_threshold;
size_t trim_threshold;
flag_t default_mflags;
};
 
static struct malloc_params mparams;
 
/* Ensure mparams initialized */
#define ensure_initialization() (void)(mparams.magic != 0 || init_mparams())
 
static struct malloc_state _gm_;
#define gm (&_gm_)
#define is_global(M) ((M) == &_gm_)
 
#define is_initialized(M) ((M)->top != 0)
 
 
 
 
__LOCK_INIT_RECURSIVE(static, malloc_global_mutex);
 
#define ACQUIRE_MALLOC_GLOBAL_LOCK() __libc_lock_lock_recursive(malloc_global_mutex);
#define RELEASE_MALLOC_GLOBAL_LOCK() __libc_lock_unlock_recursive(malloc_global_mutex);
 
#define PREACTION(M) ( __libc_lock_lock_recursive((M)->lock))
#define POSTACTION(M) { __libc_lock_unlock_recursive((M)->lock); }
 
/* ---------------------------- Indexing Bins ---------------------------- */
 
#define is_small(s) (((s) >> SMALLBIN_SHIFT) < NSMALLBINS)
#define small_index(s) ((s) >> SMALLBIN_SHIFT)
#define small_index2size(i) ((i) << SMALLBIN_SHIFT)
#define MIN_SMALL_INDEX (small_index(MIN_CHUNK_SIZE))
 
/* addressing by index. See above about smallbin repositioning */
#define smallbin_at(M, i) ((sbinptr)((char*)&((M)->smallbins[(i)<<1])))
#define treebin_at(M,i) (&((M)->treebins[i]))
 
 
#define compute_tree_index(S, I)\
{\
unsigned int X = S >> TREEBIN_SHIFT;\
if (X == 0)\
I = 0;\
else if (X > 0xFFFF)\
I = NTREEBINS-1;\
else {\
unsigned int K;\
__asm__("bsrl\t%1, %0\n\t" : "=r" (K) : "g" (X));\
I = (bindex_t)((K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1)));\
}\
}
 
/* Bit representing maximum resolved size in a treebin at i */
#define bit_for_tree_index(i) \
(i == NTREEBINS-1)? (SIZE_T_BITSIZE-1) : (((i) >> 1) + TREEBIN_SHIFT - 2)
 
/* Shift placing maximum resolved bit in a treebin at i as sign bit */
#define leftshift_for_tree_index(i) \
((i == NTREEBINS-1)? 0 : \
((SIZE_T_BITSIZE-SIZE_T_ONE) - (((i) >> 1) + TREEBIN_SHIFT - 2)))
 
/* The size of the smallest chunk held in bin with index i */
#define minsize_for_tree_index(i) \
((SIZE_T_ONE << (((i) >> 1) + TREEBIN_SHIFT)) | \
(((size_t)((i) & SIZE_T_ONE)) << (((i) >> 1) + TREEBIN_SHIFT - 1)))
 
 
/* ------------------------ Operations on bin maps ----------------------- */
 
/* bit corresponding to given index */
#define idx2bit(i) ((binmap_t)(1) << (i))
 
/* Mark/Clear bits with given index */
#define mark_smallmap(M,i) ((M)->smallmap |= idx2bit(i))
#define clear_smallmap(M,i) ((M)->smallmap &= ~idx2bit(i))
#define smallmap_is_marked(M,i) ((M)->smallmap & idx2bit(i))
 
#define mark_treemap(M,i) ((M)->treemap |= idx2bit(i))
#define clear_treemap(M,i) ((M)->treemap &= ~idx2bit(i))
#define treemap_is_marked(M,i) ((M)->treemap & idx2bit(i))
 
/* isolate the least set bit of a bitmap */
#define least_bit(x) ((x) & -(x))
 
/* mask with all bits to left of least bit of x on */
#define left_bits(x) ((x<<1) | -(x<<1))
 
/* mask with all bits to left of or equal to least bit of x on */
#define same_or_left_bits(x) ((x) | -(x))
 
 
/* index corresponding to given bit. Use x86 asm if possible */
 
#define compute_bit2idx(X, I)\
{\
unsigned int J;\
__asm__("bsfl\t%1, %0\n\t" : "=r" (J) : "g" (X));\
I = (bindex_t)J;\
}
 
 
#define mark_inuse_foot(M,p,s)
 
/* Get/set size at footer */
#define get_foot(p, s) (((mchunkptr)((char*)(p) + (s)))->prev_foot)
#define set_foot(p, s) (((mchunkptr)((char*)(p) + (s)))->prev_foot = (s))
 
/* Macros for setting head/foot of non-mmapped chunks */
 
/* Set cinuse bit and pinuse bit of next chunk */
#define set_inuse(M,p,s)\
((p)->head = (((p)->head & PINUSE_BIT)|s|CINUSE_BIT),\
((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT)
 
/* Set cinuse and pinuse of this chunk and pinuse of next chunk */
#define set_inuse_and_pinuse(M,p,s)\
((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\
((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT)
 
/* Set size, cinuse and pinuse bit of this chunk */
#define set_size_and_pinuse_of_inuse_chunk(M, p, s)\
((p)->head = (s|PINUSE_BIT|CINUSE_BIT))
 
 
#define assert(x)
#define RTCHECK(e) __builtin_expect(e, 1)
 
#define check_free_chunk(M,P)
#define check_inuse_chunk(M,P)
#define check_malloced_chunk(M,P,N)
#define check_mmapped_chunk(M,P)
#define check_malloc_state(M)
#define check_top_chunk(M,P)
 
/* Check if address a is at least as high as any from MORECORE or MMAP */
#define ok_address(M, a) ((char*)(a) >= (M)->least_addr)
/* Check if address of next chunk n is higher than base chunk p */
#define ok_next(p, n) ((char*)(p) < (char*)(n))
/* Check if p has inuse status */
#define ok_inuse(p) is_inuse(p)
/* Check if p has its pinuse bit on */
#define ok_pinuse(p) pinuse(p)
 
#define CORRUPTION_ERROR_ACTION(m) \
do { \
printf("%s malloc heap corrupted\n",__FUNCTION__); \
__asm__("int3"); \
}while(0) \
 
 
#define USAGE_ERROR_ACTION(m, p) \
do { \
printf("%s malloc heap corrupted\n",__FUNCTION__); \
__asm__("int3"); \
}while(0) \
 
/* ----------------------- Operations on smallbins ----------------------- */
 
/*
Various forms of linking and unlinking are defined as macros. Even
the ones for trees, which are very long but have very short typical
paths. This is ugly but reduces reliance on inlining support of
compilers.
*/
 
/* Link a free chunk into a smallbin */
#define insert_small_chunk(M, P, S) {\
bindex_t I = small_index(S);\
mchunkptr B = smallbin_at(M, I);\
mchunkptr F = B;\
assert(S >= MIN_CHUNK_SIZE);\
if (!smallmap_is_marked(M, I))\
mark_smallmap(M, I);\
else if (RTCHECK(ok_address(M, B->fd)))\
F = B->fd;\
else {\
CORRUPTION_ERROR_ACTION(M);\
}\
B->fd = P;\
F->bk = P;\
P->fd = F;\
P->bk = B;\
}
 
/* Unlink a chunk from a smallbin */
#define unlink_small_chunk(M, P, S) {\
mchunkptr F = P->fd;\
mchunkptr B = P->bk;\
bindex_t I = small_index(S);\
assert(P != B);\
assert(P != F);\
assert(chunksize(P) == small_index2size(I));\
if (F == B)\
clear_smallmap(M, I);\
else if (RTCHECK((F == smallbin_at(M,I) || ok_address(M, F)) &&\
(B == smallbin_at(M,I) || ok_address(M, B)))) {\
F->bk = B;\
B->fd = F;\
}\
else {\
CORRUPTION_ERROR_ACTION(M);\
}\
}
 
/* Unlink the first chunk from a smallbin */
#define unlink_first_small_chunk(M, B, P, I) {\
mchunkptr F = P->fd;\
assert(P != B);\
assert(P != F);\
assert(chunksize(P) == small_index2size(I));\
if (B == F)\
clear_smallmap(M, I);\
else if (RTCHECK(ok_address(M, F))) {\
B->fd = F;\
F->bk = B;\
}\
else {\
CORRUPTION_ERROR_ACTION(M);\
}\
}
 
/* Replace dv node, binning the old one */
/* Used only when dvsize known to be small */
#define replace_dv(M, P, S) {\
size_t DVS = M->dvsize;\
if (DVS != 0) {\
mchunkptr DV = M->dv;\
assert(is_small(DVS));\
insert_small_chunk(M, DV, DVS);\
}\
M->dvsize = S;\
M->dv = P;\
}
 
 
/* ------------------------- Operations on trees ------------------------- */
 
/* Insert chunk into tree */
#define insert_large_chunk(M, X, S) {\
tbinptr* H;\
bindex_t I;\
compute_tree_index(S, I);\
H = treebin_at(M, I);\
X->index = I;\
X->child[0] = X->child[1] = 0;\
if (!treemap_is_marked(M, I)) {\
mark_treemap(M, I);\
*H = X;\
X->parent = (tchunkptr)H;\
X->fd = X->bk = X;\
}\
else {\
tchunkptr T = *H;\
size_t K = S << leftshift_for_tree_index(I);\
for (;;) {\
if (chunksize(T) != S) {\
tchunkptr* C = &(T->child[(K >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1]);\
K <<= 1;\
if (*C != 0)\
T = *C;\
else if (RTCHECK(ok_address(M, C))) {\
*C = X;\
X->parent = T;\
X->fd = X->bk = X;\
break;\
}\
else {\
CORRUPTION_ERROR_ACTION(M);\
break;\
}\
}\
else {\
tchunkptr F = T->fd;\
if (RTCHECK(ok_address(M, T) && ok_address(M, F))) {\
T->fd = F->bk = X;\
X->fd = F;\
X->bk = T;\
X->parent = 0;\
break;\
}\
else {\
CORRUPTION_ERROR_ACTION(M);\
break;\
}\
}\
}\
}\
}
 
/*
Unlink steps:
 
1. If x is a chained node, unlink it from its same-sized fd/bk links
and choose its bk node as its replacement.
2. If x was the last node of its size, but not a leaf node, it must
be replaced with a leaf node (not merely one with an open left or
right), to make sure that lefts and rights of descendents
correspond properly to bit masks. We use the rightmost descendent
of x. We could use any other leaf, but this is easy to locate and
tends to counteract removal of leftmosts elsewhere, and so keeps
paths shorter than minimally guaranteed. This doesn't loop much
because on average a node in a tree is near the bottom.
3. If x is the base of a chain (i.e., has parent links) relink
x's parent and children to x's replacement (or null if none).
*/
 
#define unlink_large_chunk(M, X) {\
tchunkptr XP = X->parent;\
tchunkptr R;\
if (X->bk != X) {\
tchunkptr F = X->fd;\
R = X->bk;\
if (RTCHECK(ok_address(M, F))) {\
F->bk = R;\
R->fd = F;\
}\
else {\
CORRUPTION_ERROR_ACTION(M);\
}\
}\
else {\
tchunkptr* RP;\
if (((R = *(RP = &(X->child[1]))) != 0) ||\
((R = *(RP = &(X->child[0]))) != 0)) {\
tchunkptr* CP;\
while ((*(CP = &(R->child[1])) != 0) ||\
(*(CP = &(R->child[0])) != 0)) {\
R = *(RP = CP);\
}\
if (RTCHECK(ok_address(M, RP)))\
*RP = 0;\
else {\
CORRUPTION_ERROR_ACTION(M);\
}\
}\
}\
if (XP != 0) {\
tbinptr* H = treebin_at(M, X->index);\
if (X == *H) {\
if ((*H = R) == 0) \
clear_treemap(M, X->index);\
}\
else if (RTCHECK(ok_address(M, XP))) {\
if (XP->child[0] == X) \
XP->child[0] = R;\
else \
XP->child[1] = R;\
}\
else\
CORRUPTION_ERROR_ACTION(M);\
if (R != 0) {\
if (RTCHECK(ok_address(M, R))) {\
tchunkptr C0, C1;\
R->parent = XP;\
if ((C0 = X->child[0]) != 0) {\
if (RTCHECK(ok_address(M, C0))) {\
R->child[0] = C0;\
C0->parent = R;\
}\
else\
CORRUPTION_ERROR_ACTION(M);\
}\
if ((C1 = X->child[1]) != 0) {\
if (RTCHECK(ok_address(M, C1))) {\
R->child[1] = C1;\
C1->parent = R;\
}\
else\
CORRUPTION_ERROR_ACTION(M);\
}\
}\
else\
CORRUPTION_ERROR_ACTION(M);\
}\
}\
}
 
/* Relays to large vs small bin operations */
 
#define insert_chunk(M, P, S)\
if (is_small(S)) insert_small_chunk(M, P, S)\
else { tchunkptr TP = (tchunkptr)(P); insert_large_chunk(M, TP, S); }
 
#define unlink_chunk(M, P, S)\
if (is_small(S)) unlink_small_chunk(M, P, S)\
else { tchunkptr TP = (tchunkptr)(P); unlink_large_chunk(M, TP); }
 
 
/* -------------------------- system alloc setup ------------------------- */
 
/* Operations on mflags */
 
#define use_lock(M) ((M)->mflags & USE_LOCK_BIT)
#define enable_lock(M) ((M)->mflags |= USE_LOCK_BIT)
#define disable_lock(M) ((M)->mflags &= ~USE_LOCK_BIT)
 
#define use_mmap(M) ((M)->mflags & USE_MMAP_BIT)
#define enable_mmap(M) ((M)->mflags |= USE_MMAP_BIT)
#define disable_mmap(M) ((M)->mflags &= ~USE_MMAP_BIT)
 
#define use_noncontiguous(M) ((M)->mflags & USE_NONCONTIGUOUS_BIT)
#define disable_contiguous(M) ((M)->mflags |= USE_NONCONTIGUOUS_BIT)
 
#define set_lock(M,L)\
((M)->mflags = (L)?\
((M)->mflags | USE_LOCK_BIT) :\
((M)->mflags & ~USE_LOCK_BIT))
 
/* page-align a size */
#define page_align(S)\
(((S) + (mparams.page_size - SIZE_T_ONE)) & ~(mparams.page_size - SIZE_T_ONE))
 
/* granularity-align a size */
#define granularity_align(S)\
(((S) + (mparams.granularity - SIZE_T_ONE))\
& ~(mparams.granularity - SIZE_T_ONE))
 
 
/* For mmap, use granularity alignment */
#define mmap_align(S) granularity_align(S)
 
/* For sys_alloc, enough padding to ensure can malloc request on success */
#define SYS_ALLOC_PADDING (TOP_FOOT_SIZE + MALLOC_ALIGNMENT)
 
#define is_page_aligned(S)\
(((size_t)(S) & (mparams.page_size - SIZE_T_ONE)) == 0)
#define is_granularity_aligned(S)\
(((size_t)(S) & (mparams.granularity - SIZE_T_ONE)) == 0)
 
/* True if segment S holds address A */
#define segment_holds(S, A)\
((char*)(A) >= S->base && (char*)(A) < S->base + S->size)
 
/* Return segment holding given address */
static msegmentptr segment_holding(mstate m, char* addr)
{
msegmentptr sp = &m->seg;
for (;;) {
if (addr >= sp->base && addr < sp->base + sp->size)
return sp;
if ((sp = sp->next) == 0)
return 0;
}
}
 
/* Return true if segment contains a segment link */
static int has_segment_link(mstate m, msegmentptr ss)
{
msegmentptr sp = &m->seg;
for (;;) {
if ((char*)sp >= ss->base && (char*)sp < ss->base + ss->size)
return 1;
if ((sp = sp->next) == 0)
return 0;
}
}
 
static inline void* os_mmap(size_t size)
{
void* ptr = user_alloc(size);
return (ptr != 0)? ptr: MFAIL;
}
 
static inline int os_munmap(void* ptr, size_t size)
{
return (user_free(ptr) != 0) ? 0 : -1;
}
 
#define should_trim(M,s) ((s) > (M)->trim_check)
 
 
#define MMAP_DEFAULT(s) os_mmap(s)
#define MUNMAP_DEFAULT(a, s) os_munmap((a), (s))
#define DIRECT_MMAP_DEFAULT(s) os_mmap(s)
 
#define internal_malloc(m, b) malloc(b)
#define internal_free(m, mem) free(mem)
 
/* ----------------------- Direct-mmapping chunks ----------------------- */
 
/*
Directly mmapped chunks are set up with an offset to the start of
the mmapped region stored in the prev_foot field of the chunk. This
allows reconstruction of the required argument to MUNMAP when freed,
and also allows adjustment of the returned chunk to meet alignment
requirements (especially in memalign).
*/
 
/* Malloc using mmap */
static void* mmap_alloc(mstate m, size_t nb)
{
size_t mmsize = mmap_align(nb + SIX_SIZE_T_SIZES + CHUNK_ALIGN_MASK);
if (mmsize > nb) /* Check for wrap around 0 */
{
char* mm = (char*)(os_mmap(mmsize));
if (mm != CMFAIL)
{
size_t offset = align_offset(chunk2mem(mm));
size_t psize = mmsize - offset - MMAP_FOOT_PAD;
mchunkptr p = (mchunkptr)(mm + offset);
p->prev_foot = offset;
p->head = psize;
mark_inuse_foot(m, p, psize);
chunk_plus_offset(p, psize)->head = FENCEPOST_HEAD;
chunk_plus_offset(p, psize+SIZE_T_SIZE)->head = 0;
 
if (m->least_addr == 0 || mm < m->least_addr)
m->least_addr = mm;
if ((m->footprint += mmsize) > m->max_footprint)
m->max_footprint = m->footprint;
assert(is_aligned(chunk2mem(p)));
check_mmapped_chunk(m, p);
return chunk2mem(p);
}
}
return 0;
}
 
/* Realloc using mmap */
static mchunkptr mmap_resize(mstate m, mchunkptr oldp, size_t nb)
{
size_t oldsize = chunksize(oldp);
if (is_small(nb)) /* Can't shrink mmap regions below small size */
return 0;
/* Keep old chunk if big enough but not too big */
if (oldsize >= nb + SIZE_T_SIZE &&
(oldsize - nb) <= (mparams.granularity << 1))
return oldp;
else
{
size_t offset = oldp->prev_foot;
size_t oldmmsize = oldsize + offset + MMAP_FOOT_PAD;
size_t newmmsize = mmap_align(nb + SIX_SIZE_T_SIZES + CHUNK_ALIGN_MASK);
char* cp = (char*)CALL_MREMAP((char*)oldp - offset,
oldmmsize, newmmsize, 1);
if (cp != CMFAIL)
{
mchunkptr newp = (mchunkptr)(cp + offset);
size_t psize = newmmsize - offset - MMAP_FOOT_PAD;
newp->head = psize;
mark_inuse_foot(m, newp, psize);
chunk_plus_offset(newp, psize)->head = FENCEPOST_HEAD;
chunk_plus_offset(newp, psize+SIZE_T_SIZE)->head = 0;
 
if (cp < m->least_addr)
m->least_addr = cp;
if ((m->footprint += newmmsize - oldmmsize) > m->max_footprint)
m->max_footprint = m->footprint;
check_mmapped_chunk(m, newp);
return newp;
}
}
return 0;
}
 
/* ---------------------------- setting mparams -------------------------- */
 
/* Initialize mparams */
static int init_mparams(void) {
 
ACQUIRE_MALLOC_GLOBAL_LOCK();
 
if (mparams.magic == 0)
{
size_t magic;
size_t psize;
size_t gsize;
 
psize = 4096;
gsize = DEFAULT_GRANULARITY;
 
/* Sanity-check configuration:
size_t must be unsigned and as wide as pointer type.
ints must be at least 4 bytes.
alignment must be at least 8.
Alignment, min chunk size, and page size must all be powers of 2.
*/
 
mparams.granularity = gsize;
mparams.page_size = psize;
mparams.mmap_threshold = DEFAULT_MMAP_THRESHOLD;
mparams.trim_threshold = DEFAULT_TRIM_THRESHOLD;
mparams.default_mflags = USE_LOCK_BIT|USE_MMAP_BIT|USE_NONCONTIGUOUS_BIT;
 
/* Set up lock for main malloc area */
gm->mflags = mparams.default_mflags;
__libc_lock_init_recursive(gm->lock);
 
magic = (size_t)(0x12345678 ^ (size_t)0x55555555U);
magic |= (size_t)8U; /* ensure nonzero */
magic &= ~(size_t)7U; /* improve chances of fault for bad values */
mparams.magic = magic;
}
 
RELEASE_MALLOC_GLOBAL_LOCK();
return 1;
}
 
/* -------------------------- mspace management -------------------------- */
 
/* Initialize top chunk and its size */
static void init_top(mstate m, mchunkptr p, size_t psize)
{
/* Ensure alignment */
size_t offset = align_offset(chunk2mem(p));
p = (mchunkptr)((char*)p + offset);
psize -= offset;
 
m->top = p;
m->topsize = psize;
p->head = psize | PINUSE_BIT;
/* set size of fake trailing chunk holding overhead space only once */
chunk_plus_offset(p, psize)->head = TOP_FOOT_SIZE;
m->trim_check = mparams.trim_threshold; /* reset on each update */
}
 
/* Initialize bins for a new mstate that is otherwise zeroed out */
static void init_bins(mstate m)
{
/* Establish circular links for smallbins */
bindex_t i;
for (i = 0; i < NSMALLBINS; ++i) {
sbinptr bin = smallbin_at(m,i);
bin->fd = bin->bk = bin;
}
}
 
/* Allocate chunk and prepend remainder with chunk in successor base. */
static void* prepend_alloc(mstate m, char* newbase, char* oldbase,
size_t nb)
{
mchunkptr p = align_as_chunk(newbase);
mchunkptr oldfirst = align_as_chunk(oldbase);
size_t psize = (char*)oldfirst - (char*)p;
mchunkptr q = chunk_plus_offset(p, nb);
size_t qsize = psize - nb;
set_size_and_pinuse_of_inuse_chunk(m, p, nb);
 
assert((char*)oldfirst > (char*)q);
assert(pinuse(oldfirst));
assert(qsize >= MIN_CHUNK_SIZE);
 
/* consolidate remainder with first chunk of old base */
if (oldfirst == m->top) {
size_t tsize = m->topsize += qsize;
m->top = q;
q->head = tsize | PINUSE_BIT;
check_top_chunk(m, q);
}
else if (oldfirst == m->dv) {
size_t dsize = m->dvsize += qsize;
m->dv = q;
set_size_and_pinuse_of_free_chunk(q, dsize);
}
else {
if (!is_inuse(oldfirst)) {
size_t nsize = chunksize(oldfirst);
unlink_chunk(m, oldfirst, nsize);
oldfirst = chunk_plus_offset(oldfirst, nsize);
qsize += nsize;
}
set_free_with_pinuse(q, qsize, oldfirst);
insert_chunk(m, q, qsize);
check_free_chunk(m, q);
}
 
check_malloced_chunk(m, chunk2mem(p), nb);
return chunk2mem(p);
}
 
/* Add a segment to hold a new noncontiguous region */
static void add_segment(mstate m, char* tbase, size_t tsize, flag_t mmapped)
{
/* Determine locations and sizes of segment, fenceposts, old top */
char* old_top = (char*)m->top;
msegmentptr oldsp = segment_holding(m, old_top);
char* old_end = oldsp->base + oldsp->size;
size_t ssize = pad_request(sizeof(struct malloc_segment));
char* rawsp = old_end - (ssize + FOUR_SIZE_T_SIZES + CHUNK_ALIGN_MASK);
size_t offset = align_offset(chunk2mem(rawsp));
char* asp = rawsp + offset;
char* csp = (asp < (old_top + MIN_CHUNK_SIZE))? old_top : asp;
mchunkptr sp = (mchunkptr)csp;
msegmentptr ss = (msegmentptr)(chunk2mem(sp));
mchunkptr tnext = chunk_plus_offset(sp, ssize);
mchunkptr p = tnext;
int nfences = 0;
 
/* reset top to new space */
init_top(m, (mchunkptr)tbase, tsize - TOP_FOOT_SIZE);
 
/* Set up segment record */
assert(is_aligned(ss));
set_size_and_pinuse_of_inuse_chunk(m, sp, ssize);
*ss = m->seg; /* Push current record */
m->seg.base = tbase;
m->seg.size = tsize;
m->seg.sflags = mmapped;
m->seg.next = ss;
 
/* Insert trailing fenceposts */
for (;;) {
mchunkptr nextp = chunk_plus_offset(p, SIZE_T_SIZE);
p->head = FENCEPOST_HEAD;
++nfences;
if ((char*)(&(nextp->head)) < old_end)
p = nextp;
else
break;
}
assert(nfences >= 2);
 
/* Insert the rest of old top into a bin as an ordinary free chunk */
if (csp != old_top) {
mchunkptr q = (mchunkptr)old_top;
size_t psize = csp - old_top;
mchunkptr tn = chunk_plus_offset(q, psize);
set_free_with_pinuse(q, psize, tn);
insert_chunk(m, q, psize);
}
 
check_top_chunk(m, m->top);
}
 
/* -------------------------- System allocation -------------------------- */
 
/* Get memory from system using MORECORE or MMAP */
static void* sys_alloc(mstate m, size_t nb)
{
char* tbase = CMFAIL;
size_t tsize = 0;
flag_t mmap_flag = 0;
 
ensure_initialization();
 
/* Directly map large chunks, but only if already initialized */
if (use_mmap(m) && nb >= mparams.mmap_threshold && m->topsize != 0)
{
void* mem = mmap_alloc(m, nb);
if (mem != 0)
return mem;
}
 
/*
Try getting memory in any of three ways (in most-preferred to
least-preferred order):
1. A call to MORECORE that can normally contiguously extend memory.
(disabled if not MORECORE_CONTIGUOUS or not HAVE_MORECORE or
or main space is mmapped or a previous contiguous call failed)
2. A call to MMAP new space (disabled if not HAVE_MMAP).
Note that under the default settings, if MORECORE is unable to
fulfill a request, and HAVE_MMAP is true, then mmap is
used as a noncontiguous system allocator. This is a useful backup
strategy for systems with holes in address spaces -- in this case
sbrk cannot contiguously expand the heap, but mmap may be able to
find space.
3. A call to MORECORE that cannot usually contiguously extend memory.
(disabled if not HAVE_MORECORE)
 
In all cases, we need to request enough bytes from system to ensure
we can malloc nb bytes upon success, so pad with enough space for
top_foot, plus alignment-pad to make sure we don't lose bytes if
not on boundary, and round this up to a granularity unit.
*/
 
if (HAVE_MMAP && tbase == CMFAIL) /* Try MMAP */
{
size_t rsize = granularity_align(nb + SYS_ALLOC_PADDING);
if (rsize > nb) /* Fail if wraps around zero */
{
char* mp = (char*)(CALL_MMAP(rsize));
if (mp != CMFAIL)
{
tbase = mp;
tsize = rsize;
mmap_flag = USE_MMAP_BIT;
}
}
}
 
if (tbase != CMFAIL)
{
 
if ((m->footprint += tsize) > m->max_footprint)
m->max_footprint = m->footprint;
 
if (!is_initialized(m)) /* first-time initialization */
{
if (m->least_addr == 0 || tbase < m->least_addr)
m->least_addr = tbase;
m->seg.base = tbase;
m->seg.size = tsize;
m->seg.sflags = mmap_flag;
m->magic = mparams.magic;
m->release_checks = MAX_RELEASE_CHECK_RATE;
init_bins(m);
 
if (is_global(m))
init_top(m, (mchunkptr)tbase, tsize - TOP_FOOT_SIZE);
else
{
/* Offset top by embedded malloc_state */
mchunkptr mn = next_chunk(mem2chunk(m));
init_top(m, mn, (size_t)((tbase + tsize) - (char*)mn) -TOP_FOOT_SIZE);
}
}
else
{
/* Try to merge with an existing segment */
msegmentptr sp = &m->seg;
/* Only consider most recent segment if traversal suppressed */
while (sp != 0 && tbase != sp->base + sp->size)
sp = (NO_SEGMENT_TRAVERSAL) ? 0 : sp->next;
if (sp != 0 && !is_extern_segment(sp) &&
(sp->sflags & USE_MMAP_BIT) == mmap_flag &&
segment_holds(sp, m->top)) /* append */
{
sp->size += tsize;
init_top(m, m->top, m->topsize + tsize);
}
else
{
if (tbase < m->least_addr)
m->least_addr = tbase;
sp = &m->seg;
while (sp != 0 && sp->base != tbase + tsize)
sp = (NO_SEGMENT_TRAVERSAL) ? 0 : sp->next;
if (sp != 0 && !is_extern_segment(sp) &&
(sp->sflags & USE_MMAP_BIT) == mmap_flag)
{
char* oldbase = sp->base;
sp->base = tbase;
sp->size += tsize;
return prepend_alloc(m, tbase, oldbase, nb);
}
else
add_segment(m, tbase, tsize, mmap_flag);
}
}
 
if (nb < m->topsize) /* Allocate from new or extended top space */
{
size_t rsize = m->topsize -= nb;
mchunkptr p = m->top;
mchunkptr r = m->top = chunk_plus_offset(p, nb);
r->head = rsize | PINUSE_BIT;
set_size_and_pinuse_of_inuse_chunk(m, p, nb);
check_top_chunk(m, m->top);
check_malloced_chunk(m, chunk2mem(p), nb);
return chunk2mem(p);
}
}
 
MALLOC_FAILURE_ACTION;
return 0;
}
 
 
/* ----------------------- system deallocation -------------------------- */
 
/* Unmap and unlink any mmapped segments that don't contain used chunks */
static size_t release_unused_segments(mstate m)
{
size_t released = 0;
int nsegs = 0;
msegmentptr pred = &m->seg;
msegmentptr sp = pred->next;
while (sp != 0)
{
char* base = sp->base;
size_t size = sp->size;
msegmentptr next = sp->next;
++nsegs;
if (is_mmapped_segment(sp) && !is_extern_segment(sp))
{
mchunkptr p = align_as_chunk(base);
size_t psize = chunksize(p);
/* Can unmap if first chunk holds entire segment and not pinned */
if (!is_inuse(p) && (char*)p + psize >= base + size - TOP_FOOT_SIZE)
{
tchunkptr tp = (tchunkptr)p;
assert(segment_holds(sp, (char*)sp));
if (p == m->dv) {
m->dv = 0;
m->dvsize = 0;
}
else {
unlink_large_chunk(m, tp);
}
if (CALL_MUNMAP(base, size) == 0)
{
released += size;
m->footprint -= size;
/* unlink obsoleted record */
sp = pred;
sp->next = next;
}
else { /* back out if cannot unmap */
insert_large_chunk(m, tp, psize);
}
}
}
if (NO_SEGMENT_TRAVERSAL) /* scan only first segment */
break;
pred = sp;
sp = next;
}
/* Reset check counter */
m->release_checks = ((nsegs > MAX_RELEASE_CHECK_RATE)?
nsegs : MAX_RELEASE_CHECK_RATE);
return released;
}
 
static int sys_trim(mstate m, size_t pad)
{
size_t released = 0;
ensure_initialization();
if (pad < MAX_REQUEST && is_initialized(m))
{
pad += TOP_FOOT_SIZE; /* ensure enough room for segment overhead */
 
if (m->topsize > pad)
{
/* Shrink top space in granularity-size units, keeping at least one */
size_t unit = mparams.granularity;
size_t extra = ((m->topsize - pad + (unit - SIZE_T_ONE)) / unit -
SIZE_T_ONE) * unit;
msegmentptr sp = segment_holding(m, (char*)m->top);
 
if (!is_extern_segment(sp))
{
if (is_mmapped_segment(sp))
{
if (HAVE_MMAP &&
sp->size >= extra &&
!has_segment_link(m, sp)) /* can't shrink if pinned */
{
size_t newsize = sp->size - extra;
/* Prefer mremap, fall back to munmap */
if ((CALL_MREMAP(sp->base, sp->size, newsize, 0) != MFAIL) ||
(CALL_MUNMAP(sp->base + newsize, extra) == 0))
{
released = extra;
}
}
}
}
 
if (released != 0)
{
sp->size -= released;
m->footprint -= released;
init_top(m, m->top, m->topsize - released);
check_top_chunk(m, m->top);
}
}
 
/* Unmap any unused mmapped segments */
if (HAVE_MMAP)
released += release_unused_segments(m);
 
/* On failure, disable autotrim to avoid repeated failed future calls */
if (released == 0 && m->topsize > m->trim_check)
m->trim_check = MAX_SIZE_T;
}
 
return (released != 0)? 1 : 0;
}
 
 
 
/* ---------------------------- malloc support --------------------------- */
 
/* allocate a large request from the best fitting chunk in a treebin */
static void* tmalloc_large(mstate m, size_t nb) {
tchunkptr v = 0;
size_t rsize = -nb; /* Unsigned negation */
tchunkptr t;
bindex_t idx;
compute_tree_index(nb, idx);
if ((t = *treebin_at(m, idx)) != 0) {
/* Traverse tree for this bin looking for node with size == nb */
size_t sizebits = nb << leftshift_for_tree_index(idx);
tchunkptr rst = 0; /* The deepest untaken right subtree */
for (;;) {
tchunkptr rt;
size_t trem = chunksize(t) - nb;
if (trem < rsize) {
v = t;
if ((rsize = trem) == 0)
break;
}
rt = t->child[1];
t = t->child[(sizebits >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1];
if (rt != 0 && rt != t)
rst = rt;
if (t == 0) {
t = rst; /* set t to least subtree holding sizes > nb */
break;
}
sizebits <<= 1;
}
}
if (t == 0 && v == 0) { /* set t to root of next non-empty treebin */
binmap_t leftbits = left_bits(idx2bit(idx)) & m->treemap;
if (leftbits != 0) {
bindex_t i;
binmap_t leastbit = least_bit(leftbits);
compute_bit2idx(leastbit, i);
t = *treebin_at(m, i);
}
}
 
while (t != 0) { /* find smallest of tree or subtree */
size_t trem = chunksize(t) - nb;
if (trem < rsize) {
rsize = trem;
v = t;
}
t = leftmost_child(t);
}
 
/* If dv is a better fit, return 0 so malloc will use it */
if (v != 0 && rsize < (size_t)(m->dvsize - nb)) {
if (RTCHECK(ok_address(m, v))) { /* split */
mchunkptr r = chunk_plus_offset(v, nb);
assert(chunksize(v) == rsize + nb);
if (RTCHECK(ok_next(v, r))) {
unlink_large_chunk(m, v);
if (rsize < MIN_CHUNK_SIZE)
set_inuse_and_pinuse(m, v, (rsize + nb));
else {
set_size_and_pinuse_of_inuse_chunk(m, v, nb);
set_size_and_pinuse_of_free_chunk(r, rsize);
insert_chunk(m, r, rsize);
}
return chunk2mem(v);
}
}
CORRUPTION_ERROR_ACTION(m);
}
return 0;
}
 
/* allocate a small request from the best fitting chunk in a treebin */
static void* tmalloc_small(mstate m, size_t nb)
{
tchunkptr t, v;
size_t rsize;
bindex_t i;
binmap_t leastbit = least_bit(m->treemap);
compute_bit2idx(leastbit, i);
v = t = *treebin_at(m, i);
rsize = chunksize(t) - nb;
 
while ((t = leftmost_child(t)) != 0) {
size_t trem = chunksize(t) - nb;
if (trem < rsize) {
rsize = trem;
v = t;
}
}
 
if (RTCHECK(ok_address(m, v))) {
mchunkptr r = chunk_plus_offset(v, nb);
assert(chunksize(v) == rsize + nb);
if (RTCHECK(ok_next(v, r))) {
unlink_large_chunk(m, v);
if (rsize < MIN_CHUNK_SIZE)
set_inuse_and_pinuse(m, v, (rsize + nb));
else {
set_size_and_pinuse_of_inuse_chunk(m, v, nb);
set_size_and_pinuse_of_free_chunk(r, rsize);
replace_dv(m, r, rsize);
}
return chunk2mem(v);
}
}
 
CORRUPTION_ERROR_ACTION(m);
return 0;
}
 
/* --------------------------- realloc support --------------------------- */
 
static void* internal_realloc(struct _reent *reent_ptr, mstate m, void* oldmem, size_t bytes)
{
if (bytes >= MAX_REQUEST)
{
MALLOC_FAILURE_ACTION;
return 0;
}
 
PREACTION(m);
{
mchunkptr oldp = mem2chunk(oldmem);
size_t oldsize = chunksize(oldp);
mchunkptr next = chunk_plus_offset(oldp, oldsize);
mchunkptr newp = 0;
void* extra = 0;
 
/* Try to either shrink or extend into top. Else malloc-copy-free */
 
if (RTCHECK(ok_address(m, oldp) && ok_inuse(oldp) &&
ok_next(oldp, next) && ok_pinuse(next)))
{
size_t nb = request2size(bytes);
if (is_mmapped(oldp))
newp = mmap_resize(m, oldp, nb);
else if (oldsize >= nb) { /* already big enough */
size_t rsize = oldsize - nb;
newp = oldp;
if (rsize >= MIN_CHUNK_SIZE)
{
mchunkptr remainder = chunk_plus_offset(newp, nb);
set_inuse(m, newp, nb);
set_inuse_and_pinuse(m, remainder, rsize);
extra = chunk2mem(remainder);
}
}
else if (next == m->top && oldsize + m->topsize > nb)
{
/* Expand into top */
size_t newsize = oldsize + m->topsize;
size_t newtopsize = newsize - nb;
mchunkptr newtop = chunk_plus_offset(oldp, nb);
set_inuse(m, oldp, nb);
newtop->head = newtopsize |PINUSE_BIT;
m->top = newtop;
m->topsize = newtopsize;
newp = oldp;
}
}
else {
USAGE_ERROR_ACTION(m, oldmem);
POSTACTION(m);
return 0;
}
#if DEBUG
if (newp != 0) {
check_inuse_chunk(m, newp); /* Check requires lock */
}
#endif
 
POSTACTION(m);
 
if (newp != 0)
{
if (extra != 0) {
_free_r(reent_ptr, extra);
}
return chunk2mem(newp);
}
else
{
void* newmem = _malloc_r(reent_ptr, bytes);
if (newmem != 0) {
size_t oc = oldsize - overhead_for(oldp);
memcpy(newmem, oldmem, (oc < bytes)? oc : bytes);
_free_r(reent_ptr, oldmem);
}
return newmem;
}
}
return 0;
}
 
/* --------------------------- memalign support -------------------------- */
 
static void* internal_memalign(mstate m, size_t alignment, size_t bytes)
{
if (alignment <= MALLOC_ALIGNMENT) /* Can just use malloc */
return internal_malloc(m, bytes);
if (alignment < MIN_CHUNK_SIZE) /* must be at least a minimum chunk size */
alignment = MIN_CHUNK_SIZE;
if ((alignment & (alignment-SIZE_T_ONE)) != 0) {/* Ensure a power of 2 */
size_t a = MALLOC_ALIGNMENT << 1;
while (a < alignment) a <<= 1;
alignment = a;
}
 
if (bytes >= MAX_REQUEST - alignment) {
if (m != 0) { /* Test isn't needed but avoids compiler warning */
MALLOC_FAILURE_ACTION;
}
}
else
{
size_t nb = request2size(bytes);
size_t req = nb + alignment + MIN_CHUNK_SIZE - CHUNK_OVERHEAD;
char* mem = (char*)internal_malloc(m, req);
if (mem != 0)
{
void* leader = 0;
void* trailer = 0;
mchunkptr p = mem2chunk(mem);
 
PREACTION(m);
 
if ((((size_t)(mem)) % alignment) != 0) /* misaligned */
{
/*
Find an aligned spot inside chunk. Since we need to give
back leading space in a chunk of at least MIN_CHUNK_SIZE, if
the first calculation places us at a spot with less than
MIN_CHUNK_SIZE leader, we can move to the next aligned spot.
We've allocated enough total room so that this is always
possible.
*/
char* br = (char*)mem2chunk((size_t)(((size_t)(mem +
alignment -
SIZE_T_ONE)) &
-alignment));
char* pos = ((size_t)(br - (char*)(p)) >= MIN_CHUNK_SIZE)?
br : br+alignment;
mchunkptr newp = (mchunkptr)pos;
size_t leadsize = pos - (char*)(p);
size_t newsize = chunksize(p) - leadsize;
 
if (is_mmapped(p)) { /* For mmapped chunks, just adjust offset */
newp->prev_foot = p->prev_foot + leadsize;
newp->head = newsize;
}
else { /* Otherwise, give back leader, use the rest */
set_inuse(m, newp, newsize);
set_inuse(m, p, leadsize);
leader = chunk2mem(p);
}
p = newp;
}
 
/* Give back spare room at the end */
if (!is_mmapped(p))
{
size_t size = chunksize(p);
if (size > nb + MIN_CHUNK_SIZE)
{
size_t remainder_size = size - nb;
mchunkptr remainder = chunk_plus_offset(p, nb);
set_inuse(m, p, nb);
set_inuse(m, remainder, remainder_size);
trailer = chunk2mem(remainder);
}
}
 
assert (chunksize(p) >= nb);
assert((((size_t)(chunk2mem(p))) % alignment) == 0);
check_inuse_chunk(m, p);
POSTACTION(m);
if (leader != 0) {
internal_free(m, leader);
}
if (trailer != 0) {
internal_free(m, trailer);
}
return chunk2mem(p);
}
}
return 0;
}
 
void* memalign(size_t alignment, size_t bytes)
{
return internal_memalign(gm, alignment, bytes);
}
 
 
 
void* _malloc_r(struct _reent *reent_ptr, size_t bytes) {
/*
Basic algorithm:
If a small request (< 256 bytes minus per-chunk overhead):
1. If one exists, use a remainderless chunk in associated smallbin.
(Remainderless means that there are too few excess bytes to
represent as a chunk.)
2. If it is big enough, use the dv chunk, which is normally the
chunk adjacent to the one used for the most recent small request.
3. If one exists, split the smallest available chunk in a bin,
saving remainder in dv.
4. If it is big enough, use the top chunk.
5. If available, get memory from system and use it
Otherwise, for a large request:
1. Find the smallest available binned chunk that fits, and use it
if it is better fitting than dv chunk, splitting if necessary.
2. If better fitting than any binned chunk, use the dv chunk.
3. If it is big enough, use the top chunk.
4. If request size >= mmap threshold, try to directly mmap this chunk.
5. If available, get memory from system and use it
 
The ugly goto's here ensure that postaction occurs along all paths.
*/
 
ensure_initialization(); /* initialize in sys_alloc if not using locks */
 
PREACTION(gm);
{
void* mem;
size_t nb;
 
if (bytes <= MAX_SMALL_REQUEST)
{
bindex_t idx;
binmap_t smallbits;
nb = (bytes < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(bytes);
idx = small_index(nb);
smallbits = gm->smallmap >> idx;
 
if ((smallbits & 0x3U) != 0) /* Remainderless fit to a smallbin. */
{
mchunkptr b, p;
idx += ~smallbits & 1; /* Uses next bin if idx empty */
b = smallbin_at(gm, idx);
p = b->fd;
assert(chunksize(p) == small_index2size(idx));
unlink_first_small_chunk(gm, b, p, idx);
set_inuse_and_pinuse(gm, p, small_index2size(idx));
mem = chunk2mem(p);
check_malloced_chunk(gm, mem, nb);
goto postaction;
}
else if (nb > gm->dvsize)
{
if (smallbits != 0) /* Use chunk in next nonempty smallbin */
{
mchunkptr b, p, r;
size_t rsize;
bindex_t i;
binmap_t leftbits = (smallbits << idx) & left_bits(idx2bit(idx));
binmap_t leastbit = least_bit(leftbits);
compute_bit2idx(leastbit, i);
b = smallbin_at(gm, i);
p = b->fd;
assert(chunksize(p) == small_index2size(i));
unlink_first_small_chunk(gm, b, p, i);
rsize = small_index2size(i) - nb;
/* Fit here cannot be remainderless if 4byte sizes */
if (SIZE_T_SIZE != 4 && rsize < MIN_CHUNK_SIZE)
set_inuse_and_pinuse(gm, p, small_index2size(i));
else
{
set_size_and_pinuse_of_inuse_chunk(gm, p, nb);
r = chunk_plus_offset(p, nb);
set_size_and_pinuse_of_free_chunk(r, rsize);
replace_dv(gm, r, rsize);
}
mem = chunk2mem(p);
check_malloced_chunk(gm, mem, nb);
goto postaction;
}
else if (gm->treemap != 0 && (mem = tmalloc_small(gm, nb)) != 0)
{
check_malloced_chunk(gm, mem, nb);
goto postaction;
}
}
}
else if (bytes >= MAX_REQUEST)
nb = MAX_SIZE_T; /* Too big to allocate. Force failure (in sys alloc) */
else
{
nb = pad_request(bytes);
if (gm->treemap != 0 && (mem = tmalloc_large(gm, nb)) != 0)
{
check_malloced_chunk(gm, mem, nb);
goto postaction;
}
}
 
if (nb <= gm->dvsize) {
size_t rsize = gm->dvsize - nb;
mchunkptr p = gm->dv;
if (rsize >= MIN_CHUNK_SIZE) { /* split dv */
mchunkptr r = gm->dv = chunk_plus_offset(p, nb);
gm->dvsize = rsize;
set_size_and_pinuse_of_free_chunk(r, rsize);
set_size_and_pinuse_of_inuse_chunk(gm, p, nb);
}
else { /* exhaust dv */
size_t dvs = gm->dvsize;
gm->dvsize = 0;
gm->dv = 0;
set_inuse_and_pinuse(gm, p, dvs);
}
mem = chunk2mem(p);
check_malloced_chunk(gm, mem, nb);
goto postaction;
}
else if (nb < gm->topsize) { /* Split top */
size_t rsize = gm->topsize -= nb;
mchunkptr p = gm->top;
mchunkptr r = gm->top = chunk_plus_offset(p, nb);
r->head = rsize | PINUSE_BIT;
set_size_and_pinuse_of_inuse_chunk(gm, p, nb);
mem = chunk2mem(p);
check_top_chunk(gm, gm->top);
check_malloced_chunk(gm, mem, nb);
goto postaction;
}
 
mem = sys_alloc(gm, nb);
 
postaction:
POSTACTION(gm);
return mem;
}
 
return 0;
}
 
void _free_r(struct _reent *reent_ptr, void* mem) {
/*
Consolidate freed chunks with preceeding or succeeding bordering
free chunks, if they exist, and then place in a bin. Intermixed
with special cases for top, dv, mmapped chunks, and usage errors.
*/
 
if (mem != 0)
{
mchunkptr p = mem2chunk(mem);
 
#define fm gm
 
PREACTION(fm);
{
check_inuse_chunk(fm, p);
if (RTCHECK(ok_address(fm, p) && ok_inuse(p)))
{
size_t psize = chunksize(p);
mchunkptr next = chunk_plus_offset(p, psize);
if (!pinuse(p))
{
size_t prevsize = p->prev_foot;
if (is_mmapped(p))
{
psize += prevsize + MMAP_FOOT_PAD;
if (CALL_MUNMAP((char*)p - prevsize, psize) == 0)
fm->footprint -= psize;
goto postaction;
}
else
{
mchunkptr prev = chunk_minus_offset(p, prevsize);
psize += prevsize;
p = prev;
if (RTCHECK(ok_address(fm, prev))) /* consolidate backward */
{
if (p != fm->dv)
{
unlink_chunk(fm, p, prevsize);
}
else if ((next->head & INUSE_BITS) == INUSE_BITS)
{
fm->dvsize = psize;
set_free_with_pinuse(p, psize, next);
goto postaction;
}
}
else
goto erroraction;
}
}
 
if (RTCHECK(ok_next(p, next) && ok_pinuse(next)))
{
if (!cinuse(next)) /* consolidate forward */
{
if (next == fm->top)
{
size_t tsize = fm->topsize += psize;
fm->top = p;
p->head = tsize | PINUSE_BIT;
if (p == fm->dv)
{
fm->dv = 0;
fm->dvsize = 0;
}
if (should_trim(fm, tsize))
sys_trim(fm, 0);
goto postaction;
}
else if (next == fm->dv)
{
size_t dsize = fm->dvsize += psize;
fm->dv = p;
set_size_and_pinuse_of_free_chunk(p, dsize);
goto postaction;
}
else
{
size_t nsize = chunksize(next);
psize += nsize;
unlink_chunk(fm, next, nsize);
set_size_and_pinuse_of_free_chunk(p, psize);
if (p == fm->dv)
{
fm->dvsize = psize;
goto postaction;
}
}
}
else
set_free_with_pinuse(p, psize, next);
 
if (is_small(psize))
{
insert_small_chunk(fm, p, psize);
check_free_chunk(fm, p);
}
else
{
tchunkptr tp = (tchunkptr)p;
insert_large_chunk(fm, tp, psize);
check_free_chunk(fm, p);
if (--fm->release_checks == 0)
release_unused_segments(fm);
}
goto postaction;
}
}
erroraction:
USAGE_ERROR_ACTION(fm, p);
postaction:
POSTACTION(fm);
}
}
#undef fm
}
 
void* _calloc_r(struct _reent *reent_ptr, size_t n_elements, size_t elem_size) {
void* mem;
size_t req = 0;
if (n_elements != 0) {
req = n_elements * elem_size;
if (((n_elements | elem_size) & ~(size_t)0xffff) &&
(req / n_elements != elem_size))
req = MAX_SIZE_T; /* force downstream failure on overflow */
}
mem = _malloc_r(reent_ptr, req);
if (mem != 0 && calloc_must_clear(mem2chunk(mem)))
memset(mem, 0, req);
return mem;
}
 
void* _realloc_r (struct _reent *reent_ptr, void* oldmem, size_t bytes){
if (oldmem == 0)
return _malloc_r(reent_ptr, bytes);
#ifdef REALLOC_ZERO_BYTES_FREES
if (bytes == 0) {
_free_r(ptr, oldmem);
return 0;
}
#endif /* REALLOC_ZERO_BYTES_FREES */
else {
#if ! FOOTERS
mstate m = gm;
#else /* FOOTERS */
mstate m = get_mstate_for(mem2chunk(oldmem));
if (!ok_magic(m)) {
USAGE_ERROR_ACTION(m, oldmem);
return 0;
}
#endif /* FOOTERS */
return internal_realloc(reent_ptr, m, oldmem, bytes);
}
}
 
 
 
/* -----------------------------------------------------------------------
History:
V2.8.4 Wed May 27 09:56:23 2009 Doug Lea (dl at gee)
* Use zeros instead of prev foot for is_mmapped
* Add mspace_track_large_chunks; thanks to Jean Brouwers
* Fix set_inuse in internal_realloc; thanks to Jean Brouwers
* Fix insufficient sys_alloc padding when using 16byte alignment
* Fix bad error check in mspace_footprint
* Adaptations for ptmalloc; thanks to Wolfram Gloger.
* Reentrant spin locks; thanks to Earl Chew and others
* Win32 improvements; thanks to Niall Douglas and Earl Chew
* Add NO_SEGMENT_TRAVERSAL and MAX_RELEASE_CHECK_RATE options
* Extension hook in malloc_state
* Various small adjustments to reduce warnings on some compilers
* Various configuration extensions/changes for more platforms. Thanks
to all who contributed these.
 
V2.8.3 Thu Sep 22 11:16:32 2005 Doug Lea (dl at gee)
* Add max_footprint functions
* Ensure all appropriate literals are size_t
* Fix conditional compilation problem for some #define settings
* Avoid concatenating segments with the one provided
in create_mspace_with_base
* Rename some variables to avoid compiler shadowing warnings
* Use explicit lock initialization.
* Better handling of sbrk interference.
* Simplify and fix segment insertion, trimming and mspace_destroy
* Reinstate REALLOC_ZERO_BYTES_FREES option from 2.7.x
* Thanks especially to Dennis Flanagan for help on these.
 
V2.8.2 Sun Jun 12 16:01:10 2005 Doug Lea (dl at gee)
* Fix memalign brace error.
 
V2.8.1 Wed Jun 8 16:11:46 2005 Doug Lea (dl at gee)
* Fix improper #endif nesting in C++
* Add explicit casts needed for C++
 
V2.8.0 Mon May 30 14:09:02 2005 Doug Lea (dl at gee)
* Use trees for large bins
* Support mspaces
* Use segments to unify sbrk-based and mmap-based system allocation,
removing need for emulation on most platforms without sbrk.
* Default safety checks
* Optional footer checks. Thanks to William Robertson for the idea.
* Internal code refactoring
* Incorporate suggestions and platform-specific changes.
Thanks to Dennis Flanagan, Colin Plumb, Niall Douglas,
Aaron Bachmann, Emery Berger, and others.
* Speed up non-fastbin processing enough to remove fastbins.
* Remove useless cfree() to avoid conflicts with other apps.
* Remove internal memcpy, memset. Compilers handle builtins better.
* Remove some options that no one ever used and rename others.
 
V2.7.2 Sat Aug 17 09:07:30 2002 Doug Lea (dl at gee)
* Fix malloc_state bitmap array misdeclaration
 
V2.7.1 Thu Jul 25 10:58:03 2002 Doug Lea (dl at gee)
* Allow tuning of FIRST_SORTED_BIN_SIZE
* Use PTR_UINT as type for all ptr->int casts. Thanks to John Belmonte.
* Better detection and support for non-contiguousness of MORECORE.
Thanks to Andreas Mueller, Conal Walsh, and Wolfram Gloger
* Bypass most of malloc if no frees. Thanks To Emery Berger.
* Fix freeing of old top non-contiguous chunk im sysmalloc.
* Raised default trim and map thresholds to 256K.
* Fix mmap-related #defines. Thanks to Lubos Lunak.
* Fix copy macros; added LACKS_FCNTL_H. Thanks to Neal Walfield.
* Branch-free bin calculation
* Default trim and mmap thresholds now 256K.
 
V2.7.0 Sun Mar 11 14:14:06 2001 Doug Lea (dl at gee)
* Introduce independent_comalloc and independent_calloc.
Thanks to Michael Pachos for motivation and help.
* Make optional .h file available
* Allow > 2GB requests on 32bit systems.
* new WIN32 sbrk, mmap, munmap, lock code from <Walter@GeNeSys-e.de>.
Thanks also to Andreas Mueller <a.mueller at paradatec.de>,
and Anonymous.
* Allow override of MALLOC_ALIGNMENT (Thanks to Ruud Waij for
helping test this.)
* memalign: check alignment arg
* realloc: don't try to shift chunks backwards, since this
leads to more fragmentation in some programs and doesn't
seem to help in any others.
* Collect all cases in malloc requiring system memory into sysmalloc
* Use mmap as backup to sbrk
* Place all internal state in malloc_state
* Introduce fastbins (although similar to 2.5.1)
* Many minor tunings and cosmetic improvements
* Introduce USE_PUBLIC_MALLOC_WRAPPERS, USE_MALLOC_LOCK
* Introduce MALLOC_FAILURE_ACTION, MORECORE_CONTIGUOUS
Thanks to Tony E. Bennett <tbennett@nvidia.com> and others.
* Include errno.h to support default failure action.
 
V2.6.6 Sun Dec 5 07:42:19 1999 Doug Lea (dl at gee)
* return null for negative arguments
* Added Several WIN32 cleanups from Martin C. Fong <mcfong at yahoo.com>
* Add 'LACKS_SYS_PARAM_H' for those systems without 'sys/param.h'
(e.g. WIN32 platforms)
* Cleanup header file inclusion for WIN32 platforms
* Cleanup code to avoid Microsoft Visual C++ compiler complaints
* Add 'USE_DL_PREFIX' to quickly allow co-existence with existing
memory allocation routines
* Set 'malloc_getpagesize' for WIN32 platforms (needs more work)
* Use 'assert' rather than 'ASSERT' in WIN32 code to conform to
usage of 'assert' in non-WIN32 code
* Improve WIN32 'sbrk()' emulation's 'findRegion()' routine to
avoid infinite loop
* Always call 'fREe()' rather than 'free()'
 
V2.6.5 Wed Jun 17 15:57:31 1998 Doug Lea (dl at gee)
* Fixed ordering problem with boundary-stamping
 
V2.6.3 Sun May 19 08:17:58 1996 Doug Lea (dl at gee)
* Added pvalloc, as recommended by H.J. Liu
* Added 64bit pointer support mainly from Wolfram Gloger
* Added anonymously donated WIN32 sbrk emulation
* Malloc, calloc, getpagesize: add optimizations from Raymond Nijssen
* malloc_extend_top: fix mask error that caused wastage after
foreign sbrks
* Add linux mremap support code from HJ Liu
 
V2.6.2 Tue Dec 5 06:52:55 1995 Doug Lea (dl at gee)
* Integrated most documentation with the code.
* Add support for mmap, with help from
Wolfram Gloger (Gloger@lrz.uni-muenchen.de).
* Use last_remainder in more cases.
* Pack bins using idea from colin@nyx10.cs.du.edu
* Use ordered bins instead of best-fit threshhold
* Eliminate block-local decls to simplify tracing and debugging.
* Support another case of realloc via move into top
* Fix error occuring when initial sbrk_base not word-aligned.
* Rely on page size for units instead of SBRK_UNIT to
avoid surprises about sbrk alignment conventions.
* Add mallinfo, mallopt. Thanks to Raymond Nijssen
(raymond@es.ele.tue.nl) for the suggestion.
* Add `pad' argument to malloc_trim and top_pad mallopt parameter.
* More precautions for cases where other routines call sbrk,
courtesy of Wolfram Gloger (Gloger@lrz.uni-muenchen.de).
* Added macros etc., allowing use in linux libc from
H.J. Lu (hjl@gnu.ai.mit.edu)
* Inverted this history list
 
V2.6.1 Sat Dec 2 14:10:57 1995 Doug Lea (dl at gee)
* Re-tuned and fixed to behave more nicely with V2.6.0 changes.
* Removed all preallocation code since under current scheme
the work required to undo bad preallocations exceeds
the work saved in good cases for most test programs.
* No longer use return list or unconsolidated bins since
no scheme using them consistently outperforms those that don't
given above changes.
* Use best fit for very large chunks to prevent some worst-cases.
* Added some support for debugging
 
V2.6.0 Sat Nov 4 07:05:23 1995 Doug Lea (dl at gee)
* Removed footers when chunks are in use. Thanks to
Paul Wilson (wilson@cs.texas.edu) for the suggestion.
 
V2.5.4 Wed Nov 1 07:54:51 1995 Doug Lea (dl at gee)
* Added malloc_trim, with help from Wolfram Gloger
(wmglo@Dent.MED.Uni-Muenchen.DE).
 
V2.5.3 Tue Apr 26 10:16:01 1994 Doug Lea (dl at g)
 
V2.5.2 Tue Apr 5 16:20:40 1994 Doug Lea (dl at g)
* realloc: try to expand in both directions
* malloc: swap order of clean-bin strategy;
* realloc: only conditionally expand backwards
* Try not to scavenge used bins
* Use bin counts as a guide to preallocation
* Occasionally bin return list chunks in first scan
* Add a few optimizations from colin@nyx10.cs.du.edu
 
V2.5.1 Sat Aug 14 15:40:43 1993 Doug Lea (dl at g)
* faster bin computation & slightly different binning
* merged all consolidations to one part of malloc proper
(eliminating old malloc_find_space & malloc_clean_bin)
* Scan 2 returns chunks (not just 1)
* Propagate failure in realloc if malloc returns 0
* Add stuff to allow compilation on non-ANSI compilers
from kpv@research.att.com
 
V2.5 Sat Aug 7 07:41:59 1993 Doug Lea (dl at g.oswego.edu)
* removed potential for odd address access in prev_chunk
* removed dependency on getpagesize.h
* misc cosmetics and a bit more internal documentation
* anticosmetics: mangled names in macros to evade debugger strangeness
* tested on sparc, hp-700, dec-mips, rs6000
with gcc & native cc (hp, dec only) allowing
Detlefs & Zorn comparison study (in SIGPLAN Notices.)
 
Trial version Fri Aug 28 13:14:29 1992 Doug Lea (dl at g.oswego.edu)
* Based loosely on libg++-1.2X malloc. (It retains some of the overall
structure of old version, but most details differ.)
 
*/
 
/contrib/sdk/sources/newlib/libc/stdlib/mbctype.h
0,0 → 1,21
#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 _iseucjp1(c) ((c) == 0x8e || (c) == 0x8f || ((c) >= 0xa1 && (c) <= 0xfe))
#define _iseucjp2(c) ((c) >= 0xa1 && (c) <= 0xfe)
#define _isjis(c) ((c) >= 0x21 && (c) <= 0x7e)
 
#endif /* _MBCTYPE_H_ */
/contrib/sdk/sources/newlib/libc/stdlib/mbrtowc.c
0,0 → 1,79
#include <reent.h>
#include <newlib.h>
#include <wchar.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include "local.h"
 
size_t
_DEFUN (_mbrtowc_r, (ptr, pwc, s, n, ps),
struct _reent *ptr _AND
wchar_t *pwc _AND
const char *s _AND
size_t n _AND
mbstate_t *ps)
{
int retval = 0;
 
#ifdef _MB_CAPABLE
if (ps == NULL)
{
_REENT_CHECK_MISC(ptr);
ps = &(_REENT_MBRTOWC_STATE(ptr));
}
#endif
 
if (s == NULL)
retval = __mbtowc (ptr, NULL, "", 1, __locale_charset (), ps);
else
retval = __mbtowc (ptr, pwc, s, n, __locale_charset (), ps);
 
if (retval == -1)
{
ps->__count = 0;
ptr->_errno = EILSEQ;
return (size_t)(-1);
}
else
return (size_t)retval;
}
 
#ifndef _REENT_ONLY
size_t
_DEFUN (mbrtowc, (pwc, s, n, ps),
wchar_t *pwc _AND
const char *s _AND
size_t n _AND
mbstate_t *ps)
{
#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__)
return _mbrtowc_r (_REENT, pwc, s, n, ps);
#else
int retval = 0;
 
#ifdef _MB_CAPABLE
if (ps == NULL)
{
_REENT_CHECK_MISC(_REENT);
ps = &(_REENT_MBRTOWC_STATE(_REENT));
}
#endif
 
if (s == NULL)
retval = __mbtowc (_REENT, NULL, "", 1, __locale_charset (), ps);
else
retval = __mbtowc (_REENT, pwc, s, n, __locale_charset (), ps);
 
if (retval == -1)
{
ps->__count = 0;
_REENT->_errno = EILSEQ;
return (size_t)(-1);
}
else
return (size_t)retval;
#endif /* not PREFER_SIZE_OVER_SPEED */
}
#endif /* !_REENT_ONLY */
/contrib/sdk/sources/newlib/libc/stdlib/mbtowc.c
0,0 → 1,95
/*
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.
*/
 
#ifndef _REENT_ONLY
 
#include <newlib.h>
#include <stdlib.h>
#include <wchar.h>
#include "local.h"
 
int
_DEFUN (mbtowc, (pwc, s, n),
wchar_t *pwc _AND
const char *s _AND
size_t n)
{
#ifdef _MB_CAPABLE
int retval = 0;
mbstate_t *ps;
 
_REENT_CHECK_MISC(_REENT);
ps = &(_REENT_MBTOWC_STATE(_REENT));
retval = __mbtowc (_REENT, pwc, s, n, __locale_charset (), ps);
if (retval < 0)
{
ps->__count = 0;
return -1;
}
return retval;
#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 */
}
 
#endif /* !_REENT_ONLY */
 
 
 
 
/contrib/sdk/sources/newlib/libc/stdlib/mbtowc_r.c
0,0 → 1,646
#include <newlib.h>
#include <stdlib.h>
#include <locale.h>
#include "mbctype.h"
#include <wchar.h>
#include <string.h>
#include <errno.h>
#include "local.h"
 
int (*__mbtowc) (struct _reent *, wchar_t *, const char *, size_t,
const char *, mbstate_t *)
#ifdef __CYGWIN__
/* Cygwin starts up in UTF-8 mode. */
= __utf8_mbtowc;
#else
= __ascii_mbtowc;
#endif
 
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
mbstate_t *state)
{
return __mbtowc (r, pwc, s, n, __locale_charset (), state);
}
 
int
_DEFUN (__ascii_mbtowc, (r, pwc, s, n, charset, state),
struct _reent *r _AND
wchar_t *pwc _AND
const char *s _AND
size_t n _AND
const char *charset _AND
mbstate_t *state)
{
wchar_t dummy;
unsigned char *t = (unsigned char *)s;
 
if (pwc == NULL)
pwc = &dummy;
 
if (s == NULL)
return 0;
 
if (n == 0)
return -2;
 
#ifdef __CYGWIN__
if ((wchar_t)*t >= 0x80)
{
r->_errno = EILSEQ;
return -1;
}
#endif
 
*pwc = (wchar_t)*t;
if (*t == '\0')
return 0;
 
return 1;
}
 
#ifdef _MB_CAPABLE
typedef enum { ESCAPE, DOLLAR, BRACKET, AT, B, J,
NUL, JIS_CHAR, OTHER, JIS_C_NUM } JIS_CHAR_TYPE;
typedef enum { ASCII, JIS, A_ESC, A_ESC_DL, JIS_1, J_ESC, J_ESC_BR,
INV, JIS_S_NUM } JIS_STATE;
typedef enum { COPY_A, COPY_J1, COPY_J2, MAKE_A, 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, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII },
/* JIS */ { J_ESC, JIS_1, JIS_1, JIS_1, JIS_1, JIS_1, INV, JIS_1, INV },
/* A_ESC */ { ASCII, A_ESC_DL, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII },
/* A_ESC_DL */{ ASCII, ASCII, ASCII, JIS, JIS, ASCII, ASCII, ASCII, ASCII },
/* JIS_1 */ { INV, JIS, JIS, JIS, JIS, JIS, INV, JIS, INV },
/* 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 },
};
 
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},
/* JIS */ { NOOP, COPY_J1, COPY_J1, COPY_J1, COPY_J1, COPY_J1, ERROR, COPY_J1, ERROR },
/* 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, NOOP, NOOP, COPY_A, COPY_A, COPY_A, COPY_A},
/* JIS_1 */ { ERROR, COPY_J2, COPY_J2, COPY_J2, COPY_J2, COPY_J2, ERROR, COPY_J2, ERROR },
/* J_ESC */ { ERROR, ERROR, NOOP, ERROR, ERROR, ERROR, ERROR, ERROR, ERROR },
/* J_ESC_BR */{ ERROR, ERROR, ERROR, ERROR, MAKE_A, MAKE_A, ERROR, ERROR, ERROR },
};
 
/* we override the mbstate_t __count field for more complex encodings and use it store a state value */
#define __state __count
 
#ifdef _MB_EXTENDED_CHARSETS_ISO
int
_DEFUN (__iso_mbtowc, (r, pwc, s, n, charset, state),
struct _reent *r _AND
wchar_t *pwc _AND
const char *s _AND
size_t n _AND
const char *charset _AND
mbstate_t *state)
{
wchar_t dummy;
unsigned char *t = (unsigned char *)s;
 
if (pwc == NULL)
pwc = &dummy;
 
if (s == NULL)
return 0;
 
if (n == 0)
return -2;
 
if (*t >= 0xa0)
{
int iso_idx = __iso_8859_index (charset + 9);
if (iso_idx >= 0)
{
*pwc = __iso_8859_conv[iso_idx][*t - 0xa0];
if (*pwc == 0) /* Invalid character */
{
r->_errno = EILSEQ;
return -1;
}
return 1;
}
}
 
*pwc = (wchar_t) *t;
if (*t == '\0')
return 0;
 
return 1;
}
#endif /* _MB_EXTENDED_CHARSETS_ISO */
 
#ifdef _MB_EXTENDED_CHARSETS_WINDOWS
int
_DEFUN (__cp_mbtowc, (r, pwc, s, n, charset, state),
struct _reent *r _AND
wchar_t *pwc _AND
const char *s _AND
size_t n _AND
const char *charset _AND
mbstate_t *state)
{
wchar_t dummy;
unsigned char *t = (unsigned char *)s;
 
if (pwc == NULL)
pwc = &dummy;
 
if (s == NULL)
return 0;
 
if (n == 0)
return -2;
 
if (*t >= 0x80)
{
int cp_idx = __cp_index (charset + 2);
if (cp_idx >= 0)
{
*pwc = __cp_conv[cp_idx][*t - 0x80];
if (*pwc == 0) /* Invalid character */
{
r->_errno = EILSEQ;
return -1;
}
return 1;
}
}
 
*pwc = (wchar_t)*t;
if (*t == '\0')
return 0;
 
return 1;
}
#endif /* _MB_EXTENDED_CHARSETS_WINDOWS */
 
int
_DEFUN (__utf8_mbtowc, (r, pwc, s, n, charset, state),
struct _reent *r _AND
wchar_t *pwc _AND
const char *s _AND
size_t n _AND
const char *charset _AND
mbstate_t *state)
{
wchar_t dummy;
unsigned char *t = (unsigned char *)s;
int ch;
int i = 0;
 
if (pwc == NULL)
pwc = &dummy;
 
if (s == NULL)
return 0;
 
if (n == 0)
return -2;
 
if (state->__count == 0)
ch = t[i++];
else
ch = state->__value.__wchb[0];
 
if (ch == '\0')
{
*pwc = 0;
state->__count = 0;
return 0; /* s points to the null character */
}
 
if (ch <= 0x7f)
{
/* single-byte sequence */
state->__count = 0;
*pwc = ch;
return 1;
}
if (ch >= 0xc0 && ch <= 0xdf)
{
/* two-byte sequence */
state->__value.__wchb[0] = ch;
if (state->__count == 0)
state->__count = 1;
else if (n < (size_t)-1)
++n;
if (n < 2)
return -2;
ch = t[i++];
if (ch < 0x80 || ch > 0xbf)
{
r->_errno = EILSEQ;
return -1;
}
if (state->__value.__wchb[0] < 0xc2)
{
/* overlong UTF-8 sequence */
r->_errno = EILSEQ;
return -1;
}
state->__count = 0;
*pwc = (wchar_t)((state->__value.__wchb[0] & 0x1f) << 6)
| (wchar_t)(ch & 0x3f);
return i;
}
if (ch >= 0xe0 && ch <= 0xef)
{
/* three-byte sequence */
wchar_t tmp;
state->__value.__wchb[0] = ch;
if (state->__count == 0)
state->__count = 1;
else if (n < (size_t)-1)
++n;
if (n < 2)
return -2;
ch = (state->__count == 1) ? t[i++] : state->__value.__wchb[1];
if (state->__value.__wchb[0] == 0xe0 && ch < 0xa0)
{
/* overlong UTF-8 sequence */
r->_errno = EILSEQ;
return -1;
}
if (ch < 0x80 || ch > 0xbf)
{
r->_errno = EILSEQ;
return -1;
}
state->__value.__wchb[1] = ch;
if (state->__count == 1)
state->__count = 2;
else if (n < (size_t)-1)
++n;
if (n < 3)
return -2;
ch = t[i++];
if (ch < 0x80 || ch > 0xbf)
{
r->_errno = EILSEQ;
return -1;
}
state->__count = 0;
tmp = (wchar_t)((state->__value.__wchb[0] & 0x0f) << 12)
| (wchar_t)((state->__value.__wchb[1] & 0x3f) << 6)
| (wchar_t)(ch & 0x3f);
*pwc = tmp;
return i;
}
if (ch >= 0xf0 && ch <= 0xf4)
{
/* four-byte sequence */
wint_t tmp;
state->__value.__wchb[0] = ch;
if (state->__count == 0)
state->__count = 1;
else if (n < (size_t)-1)
++n;
if (n < 2)
return -2;
ch = (state->__count == 1) ? t[i++] : state->__value.__wchb[1];
if ((state->__value.__wchb[0] == 0xf0 && ch < 0x90)
|| (state->__value.__wchb[0] == 0xf4 && ch >= 0x90))
{
/* overlong UTF-8 sequence or result is > 0x10ffff */
r->_errno = EILSEQ;
return -1;
}
if (ch < 0x80 || ch > 0xbf)
{
r->_errno = EILSEQ;
return -1;
}
state->__value.__wchb[1] = ch;
if (state->__count == 1)
state->__count = 2;
else if (n < (size_t)-1)
++n;
if (n < 3)
return -2;
ch = (state->__count == 2) ? t[i++] : state->__value.__wchb[2];
if (ch < 0x80 || ch > 0xbf)
{
r->_errno = EILSEQ;
return -1;
}
state->__value.__wchb[2] = ch;
if (state->__count == 2)
state->__count = 3;
else if (n < (size_t)-1)
++n;
if (state->__count == 3 && sizeof(wchar_t) == 2)
{
/* On systems which have wchar_t being UTF-16 values, the value
doesn't fit into a single wchar_t in this case. So what we
do here is to store the state with a special value of __count
and return the first half of a surrogate pair. The first
three bytes of a UTF-8 sequence are enough to generate the
first half of a UTF-16 surrogate pair. As return value we
choose to return the number of bytes actually read up to
here.
The second half of the surrogate pair is returned in case we
recognize the special __count value of four, and the next
byte is actually a valid value. See below. */
tmp = (wint_t)((state->__value.__wchb[0] & 0x07) << 18)
| (wint_t)((state->__value.__wchb[1] & 0x3f) << 12)
| (wint_t)((state->__value.__wchb[2] & 0x3f) << 6);
state->__count = 4;
*pwc = 0xd800 | ((tmp - 0x10000) >> 10);
return i;
}
if (n < 4)
return -2;
ch = t[i++];
if (ch < 0x80 || ch > 0xbf)
{
r->_errno = EILSEQ;
return -1;
}
tmp = (wint_t)((state->__value.__wchb[0] & 0x07) << 18)
| (wint_t)((state->__value.__wchb[1] & 0x3f) << 12)
| (wint_t)((state->__value.__wchb[2] & 0x3f) << 6)
| (wint_t)(ch & 0x3f);
if (state->__count == 4 && sizeof(wchar_t) == 2)
/* Create the second half of the surrogate pair for systems with
wchar_t == UTF-16 . */
*pwc = 0xdc00 | (tmp & 0x3ff);
else
*pwc = tmp;
state->__count = 0;
return i;
}
 
r->_errno = EILSEQ;
return -1;
}
 
/* Cygwin defines its own doublebyte charset conversion functions
because the underlying OS requires wchar_t == UTF-16. */
#ifndef __CYGWIN__
int
_DEFUN (__sjis_mbtowc, (r, pwc, s, n, charset, state),
struct _reent *r _AND
wchar_t *pwc _AND
const char *s _AND
size_t n _AND
const char *charset _AND
mbstate_t *state)
{
wchar_t dummy;
unsigned char *t = (unsigned char *)s;
int ch;
int i = 0;
 
if (pwc == NULL)
pwc = &dummy;
 
if (s == NULL)
return 0; /* not state-dependent */
 
if (n == 0)
return -2;
 
ch = t[i++];
if (state->__count == 0)
{
if (_issjis1 (ch))
{
state->__value.__wchb[0] = ch;
state->__count = 1;
if (n <= 1)
return -2;
ch = t[i++];
}
}
if (state->__count == 1)
{
if (_issjis2 (ch))
{
*pwc = (((wchar_t)state->__value.__wchb[0]) << 8) + (wchar_t)ch;
state->__count = 0;
return i;
}
else
{
r->_errno = EILSEQ;
return -1;
}
}
 
*pwc = (wchar_t)*t;
if (*t == '\0')
return 0;
 
return 1;
}
 
int
_DEFUN (__eucjp_mbtowc, (r, pwc, s, n, charset, state),
struct _reent *r _AND
wchar_t *pwc _AND
const char *s _AND
size_t n _AND
const char *charset _AND
mbstate_t *state)
{
wchar_t dummy;
unsigned char *t = (unsigned char *)s;
int ch;
int i = 0;
 
if (pwc == NULL)
pwc = &dummy;
 
if (s == NULL)
return 0;
 
if (n == 0)
return -2;
 
ch = t[i++];
if (state->__count == 0)
{
if (_iseucjp1 (ch))
{
state->__value.__wchb[0] = ch;
state->__count = 1;
if (n <= 1)
return -2;
ch = t[i++];
}
}
if (state->__count == 1)
{
if (_iseucjp2 (ch))
{
if (state->__value.__wchb[0] == 0x8f)
{
state->__value.__wchb[1] = ch;
state->__count = 2;
if (n <= i)
return -2;
ch = t[i++];
}
else
{
*pwc = (((wchar_t)state->__value.__wchb[0]) << 8) + (wchar_t)ch;
state->__count = 0;
return i;
}
}
else
{
r->_errno = EILSEQ;
return -1;
}
}
if (state->__count == 2)
{
if (_iseucjp2 (ch))
{
*pwc = (((wchar_t)state->__value.__wchb[1]) << 8)
+ (wchar_t)(ch & 0x7f);
state->__count = 0;
return i;
}
else
{
r->_errno = EILSEQ;
return -1;
}
}
 
*pwc = (wchar_t)*t;
if (*t == '\0')
return 0;
 
return 1;
}
 
int
_DEFUN (__jis_mbtowc, (r, pwc, s, n, charset, state),
struct _reent *r _AND
wchar_t *pwc _AND
const char *s _AND
size_t n _AND
const char *charset _AND
mbstate_t *state)
{
wchar_t dummy;
unsigned char *t = (unsigned char *)s;
JIS_STATE curr_state;
JIS_ACTION action;
JIS_CHAR_TYPE ch;
unsigned char *ptr;
unsigned int i;
int curr_ch;
 
if (pwc == NULL)
pwc = &dummy;
 
if (s == NULL)
{
state->__state = ASCII;
return 1; /* state-dependent */
}
 
if (n == 0)
return -2;
 
curr_state = state->__state;
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->__state = ASCII;
*pwc = (wchar_t)0;
return 0;
case COPY_A:
state->__state = ASCII;
*pwc = (wchar_t)*ptr;
return (i + 1);
case COPY_J1:
state->__value.__wchb[0] = t[i];
break;
case COPY_J2:
state->__state = JIS;
*pwc = (((wchar_t)state->__value.__wchb[0]) << 8) + (wchar_t)(t[i]);
return (i + 1);
case MAKE_A:
ptr = (unsigned char *)(t + i + 1);
break;
case ERROR:
default:
r->_errno = EILSEQ;
return -1;
}
 
}
 
state->__state = curr_state;
return -2; /* n < bytes needed */
}
#endif /* !__CYGWIN__*/
#endif /* _MB_CAPABLE */
/contrib/sdk/sources/newlib/libc/stdlib/mlock.c
0,0 → 1,56
/*
FUNCTION
<<__malloc_lock>>, <<__malloc_unlock>>---lock malloc pool
 
INDEX
__malloc_lock
INDEX
__malloc_unlock
 
ANSI_SYNOPSIS
#include <malloc.h>
void __malloc_lock (struct _reent *<[reent]>);
void __malloc_unlock (struct _reent *<[reent]>);
 
TRAD_SYNOPSIS
void __malloc_lock(<[reent]>)
struct _reent *<[reent]>;
 
void __malloc_unlock(<[reent]>)
struct _reent *<[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 use
the lock API defined in sys/lock.h. 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>
#include <sys/lock.h>
 
__LOCK_INIT_RECURSIVE(static, __malloc_lock_object);
 
void
__malloc_lock (ptr)
struct _reent *ptr;
{
__lock_acquire_recursive (__malloc_lock_object);
}
 
void
__malloc_unlock (ptr)
struct _reent *ptr;
{
__lock_release_recursive (__malloc_lock_object);
}
 
/contrib/sdk/sources/newlib/libc/stdlib/mprec.c
0,0 → 1,1049
/****************************************************************
*
* 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"
 
/* This is defined in sys/reent.h as (sizeof (size_t) << 3) now, as in NetBSD.
The old value of 15 was wrong and made newlib vulnerable against buffer
overrun attacks (CVE-2009-0689), same as other implementations of gdtoa
based on BSD code.
#define _Kmax 15
*/
 
_Bigint *
_DEFUN (Balloc, (ptr, k), struct _reent *ptr _AND int k)
{
int x;
_Bigint *rv ;
 
_REENT_CHECK_MP(ptr);
if (_REENT_MP_FREELIST(ptr) == NULL)
{
/* Allocate a list of pointers to the mprec objects */
_REENT_MP_FREELIST(ptr) = (struct _Bigint **) _calloc_r (ptr,
sizeof (struct _Bigint *),
_Kmax + 1);
if (_REENT_MP_FREELIST(ptr) == NULL)
{
return NULL;
}
}
 
if ((rv = _REENT_MP_FREELIST(ptr)[k]) != 0)
{
_REENT_MP_FREELIST(ptr)[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)
{
_REENT_CHECK_MP(ptr);
if (v)
{
v->_next = _REENT_MP_FREELIST(ptr)[v->_k];
_REENT_MP_FREELIST(ptr)[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) != 0)
{
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) != 0)
{
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) != 0)
b = multadd (ptr, b, p05[i - 1], 0);
 
if (!(k >>= 2))
return b;
_REENT_CHECK_MP(ptr);
if (!(p5 = _REENT_MP_P5S(ptr)))
{
/* first time */
p5 = _REENT_MP_P5S(ptr) = 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) != 0)
++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;
#endif
d.d = _d;
#ifdef VAX
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)) != 0)
z |= Exp_msk1;
#endif
#ifdef Pack_32
#ifndef _DOUBLE_IS_32BITS
if (d1)
{
y = d1;
k = lo0bits (&y);
if (k)
{
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 (d1)
{
y = d1;
k = lo0bits (&y);
if (k)
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;
}
 
void
_DEFUN (copybits, (c, n, b),
__ULong *c _AND
int n _AND
_Bigint *b)
{
__ULong *ce, *x, *xe;
#ifdef Pack_16
int nw, nw1;
#endif
 
ce = c + ((n-1) >> kshift) + 1;
x = b->_x;
#ifdef Pack_32
xe = x + b->_wds;
while(x < xe)
*c++ = *x++;
#else
nw = b->_wds;
nw1 = nw & 1;
for(xe = x + (nw - nw1); x < xe; x += 2)
Storeinc(c, x[1], x[0]);
if (nw1)
*c++ = *x;
#endif
while(c < ce)
*c++ = 0;
}
 
__ULong
_DEFUN (any_on, (b, k),
_Bigint *b _AND
int k)
{
int n, nwds;
__ULong *x, *x0, x1, x2;
 
x = b->_x;
nwds = b->_wds;
n = k >> kshift;
if (n > nwds)
n = nwds;
else if (n < nwds && (k &= kmask)) {
x1 = x2 = x[n];
x1 >>= k;
x1 <<= k;
if (x1 != x2)
return 1;
}
x0 = x;
x += n;
while(x > x0)
if (*--x)
return 1;
return 0;
}
 
/contrib/sdk/sources/newlib/libc/stdlib/mprec.h
0,0 → 1,415
/****************************************************************
*
* 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>
#include <sys/types.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 is taken from gdtoaimp.h for use with new strtod, but
adjusted to avoid invalid type-punning. */
typedef __int32_t Long;
 
/* Unfortunately, because __ULong might be a different type than
__uint32_t, we can't re-use union double_union as-is without
further edits in strtod.c. */
typedef union { double d; __ULong i[2]; } U;
 
#define dword0(x) word0(x)
#define dword1(x) word1(x)
#define dval(x) (x.d)
 
#undef SI
#ifdef Sudden_Underflow
#define SI 1
#else
#define SI 0
#endif
 
#define Storeinc(a,b,c) (*(a)++ = (b) << 16 | (c) & 0xffff)
 
/* #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
#define NO_HEX_FP /* not supported in this case */
#define IEEE_Arith
#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
#undef dword0
#undef dword1
 
#define word0(x) (x.i[0])
#define word1(x) 0
#define dword0(x) word0(x)
#define dword1(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 /* !_DOUBLE_IS_32BITS */
 
#ifndef Flt_Rounds
#ifdef FLT_ROUNDS
#define Flt_Rounds FLT_ROUNDS
#else
#define Flt_Rounds 1
#endif
#endif /*Flt_Rounds*/
 
#else /* !IEEE_8087 && !IEEE_MC68k */
#undef Sudden_Underflow
#define Sudden_Underflow
#ifdef IBM
#define Flt_Rounds 0
#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 Flt_Rounds 1
#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
#else
#define Scale_Bit 0x10
#if defined(_DOUBLE_IS_32BITS) && defined(__v800)
#define n_bigtens 2
#else
#define n_bigtens 5
#endif
#endif
 
#ifdef IBM
#define n_bigtens 3
#endif
 
#ifdef VAX
#define n_bigtens 2
#endif
 
#ifndef __NO_INFNAN_CHECK
#define INFNAN_CHECK
#endif
 
/*
* NAN_WORD0 and NAN_WORD1 are only referenced in strtod.c. Prior to
* 20050115, they used to be hard-wired here (to 0x7ff80000 and 0,
* respectively), but now are determined by compiling and running
* qnan.c to generate gd_qnan.h, which specifies d_QNAN0 and d_QNAN1.
* Formerly gdtoaimp.h recommended supplying suitable -DNAN_WORD0=...
* and -DNAN_WORD1=... values if necessary. This should still work.
* (On HP Series 700/800 machines, -DNAN_WORD0=0x7ff40000 works.)
*/
#ifdef IEEE_Arith
#ifdef IEEE_MC68k
#define _0 0
#define _1 1
#ifndef NAN_WORD0
#define NAN_WORD0 d_QNAN0
#endif
#ifndef NAN_WORD1
#define NAN_WORD1 d_QNAN1
#endif
#else
#define _0 1
#define _1 0
#ifndef NAN_WORD0
#define NAN_WORD0 d_QNAN1
#endif
#ifndef NAN_WORD1
#define NAN_WORD1 d_QNAN0
#endif
#endif
#else
#undef INFNAN_CHECK
#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
#else /* Just_16 */
#ifndef Pack_16
#define Pack_16
#endif
#endif /* Just_16 */
 
#ifdef Pack_32
#define ULbits 32
#define kshift 5
#define kmask 31
#define ALL_ON 0xffffffff
#else
#define ULbits 16
#define kshift 4
#define kmask 15
#define ALL_ON 0xffff
#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 any_on __any_on
#define gethex __gethex
#define copybits __copybits
#define hexnan __hexnan
#define hexdig_init __hexdig_init
 
#define hexdig __hexdig
 
#define tens __mprec_tens
#define bigtens __mprec_bigtens
#define tinytens __mprec_tinytens
 
struct _reent ;
struct FPI;
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));
int _EXFUN(gethex,(struct _reent *p, _CONST char **sp, struct FPI *fpi, Long *exp, _Bigint **bp, int sign));
double _EXFUN(ratio,(_Bigint *a, _Bigint *b));
__ULong _EXFUN(any_on,(_Bigint *b, int k));
void _EXFUN(copybits,(__ULong *c, int n, _Bigint *b));
void _EXFUN(hexdig_init,(void));
#ifdef INFNAN_CHECK
int _EXFUN(hexnan,(_CONST char **sp, struct FPI *fpi, __ULong *x0));
#endif
 
#define Bcopy(x,y) memcpy((char *)&x->_sign, (char *)&y->_sign, y->_wds*sizeof(__Long) + 2*sizeof(int))
 
extern _CONST double tinytens[];
extern _CONST double bigtens[];
extern _CONST double tens[];
extern unsigned char hexdig[];
 
 
double _EXFUN(_mprec_log10,(int));
/contrib/sdk/sources/newlib/libc/stdlib/rand.c
0,0 → 1,91
/*
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-threaded applications.
<<rand_r>> is thread-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_CHECK_RAND48(_REENT);
_REENT_RAND_NEXT(_REENT) = seed;
}
 
int
_DEFUN_VOID (rand)
{
/* This multiplier was obtained from Knuth, D.E., "The Art of
Computer Programming," Vol 2, Seminumerical Algorithms, Third
Edition, Addison-Wesley, 1998, p. 106 (line 26) & p. 108 */
_REENT_CHECK_RAND48(_REENT);
_REENT_RAND_NEXT(_REENT) =
_REENT_RAND_NEXT(_REENT) * __extension__ 6364136223846793005LL + 1;
return (int)((_REENT_RAND_NEXT(_REENT) >> 32) & RAND_MAX);
}
 
#endif /* _REENT_ONLY */
/contrib/sdk/sources/newlib/libc/stdlib/rand48.c
0,0 → 1,179
/*
* Copyright (c) 1993 Martin Birgmeier
* All rights reserved.
*
* You may redistribute unmodified or modified versions of this source
* code provided that the above copyright notice and this and the
* following conditions are retained.
*
* This software is provided ``as is'', and comes with no warranties
* of any kind. I shall in no event be liable for anything that happens
* to anyone/anything when using this software.
*/
 
/*
FUNCTION
<<rand48>>, <<drand48>>, <<erand48>>, <<lrand48>>, <<nrand48>>, <<mrand48>>, <<jrand48>>, <<srand48>>, <<seed48>>, <<lcong48>>---pseudo-random number generators and initialization routines
 
INDEX
rand48
INDEX
drand48
INDEX
erand48
INDEX
lrand48
INDEX
nrand48
INDEX
mrand48
INDEX
jrand48
INDEX
srand48
INDEX
seed48
INDEX
lcong48
 
ANSI_SYNOPSIS
#include <stdlib.h>
double drand48(void);
double erand48(unsigned short <[xseed]>[3]);
long lrand48(void);
long nrand48(unsigned short <[xseed]>[3]);
long mrand48(void);
long jrand48(unsigned short <[xseed]>[3]);
void srand48(long <[seed]>);
unsigned short *seed48(unsigned short <[xseed]>[3]);
void lcong48(unsigned short <[p]>[7]);
 
TRAD_SYNOPSIS
#include <stdlib.h>
double drand48();
 
double erand48(<[xseed]>)
unsigned short <[xseed]>[3];
 
long lrand48();
 
long nrand48(<[xseed]>)
unsigned short <[xseed]>[3];
 
long mrand48();
 
long jrand48(<[xseed]>)
unsigned short <[xseed]>[3];
 
void srand48(<[seed]>)
long <[seed]>;
 
unsigned short *seed48(<[xseed]>)
unsigned short <[xseed]>[3];
 
void lcong48(<[p]>)
unsigned short <[p]>[7];
 
DESCRIPTION
The <<rand48>> family of functions generates pseudo-random numbers
using a linear congruential algorithm working on integers 48 bits in size.
The particular formula employed is
r(n+1) = (a * r(n) + c) mod m
where the default values are
for the multiplicand a = 0xfdeece66d = 25214903917 and
the addend c = 0xb = 11. The modulo is always fixed at m = 2 ** 48.
r(n) is called the seed of the random number generator.
 
For all the six generator routines described next, the first
computational step is to perform a single iteration of the algorithm.
 
<<drand48>> and <<erand48>>
return values of type double. The full 48 bits of r(n+1) are
loaded into the mantissa of the returned value, with the exponent set
such that the values produced lie in the interval [0.0, 1.0].
 
<<lrand48>> and <<nrand48>>
return values of type long in the range
[0, 2**31-1]. The high-order (31) bits of
r(n+1) are loaded into the lower bits of the returned value, with
the topmost (sign) bit set to zero.
 
<<mrand48>> and <<jrand48>>
return values of type long in the range
[-2**31, 2**31-1]. The high-order (32) bits of
r(n+1) are loaded into the returned value.
 
<<drand48>>, <<lrand48>>, and <<mrand48>>
use an internal buffer to store r(n). For these functions
the initial value of r(0) = 0x1234abcd330e = 20017429951246.
 
On the other hand, <<erand48>>, <<nrand48>>, and <<jrand48>>
use a user-supplied buffer to store the seed r(n),
which consists of an array of 3 shorts, where the zeroth member
holds the least significant bits.
 
All functions share the same multiplicand and addend.
 
<<srand48>> is used to initialize the internal buffer r(n) of
<<drand48>>, <<lrand48>>, and <<mrand48>>
such that the 32 bits of the seed value are copied into the upper 32 bits
of r(n), with the lower 16 bits of r(n) arbitrarily being set to 0x330e.
Additionally, the constant multiplicand and addend of the algorithm are
reset to the default values given above.
 
<<seed48>> also initializes the internal buffer r(n) of
<<drand48>>, <<lrand48>>, and <<mrand48>>,
but here all 48 bits of the seed can be specified in an array of 3 shorts,
where the zeroth member specifies the lowest bits. Again,
the constant multiplicand and addend of the algorithm are
reset to the default values given above.
<<seed48>> returns a pointer to an array of 3 shorts which contains
the old seed.
This array is statically allocated, thus its contents are lost after
each new call to <<seed48>>.
 
Finally, <<lcong48>> allows full control over the multiplicand and
addend used in <<drand48>>, <<erand48>>, <<lrand48>>, <<nrand48>>,
<<mrand48>>, and <<jrand48>>,
and the seed used in <<drand48>>, <<lrand48>>, and <<mrand48>>.
An array of 7 shorts is passed as parameter; the first three shorts are
used to initialize the seed; the second three are used to initialize the
multiplicand; and the last short is used to initialize the addend.
It is thus not possible to use values greater than 0xffff as the addend.
 
Note that all three methods of seeding the random number generator
always also set the multiplicand and addend for any of the six
generator calls.
 
For a more powerful random number generator, see <<random>>.
 
PORTABILITY
SUS requires these functions.
 
No supporting OS subroutines are required.
*/
 
#include "rand48.h"
 
void
_DEFUN (__dorand48, (r, xseed),
struct _reent *r _AND
unsigned short xseed[3])
{
unsigned long accu;
unsigned short temp[2];
 
_REENT_CHECK_RAND48(r);
accu = (unsigned long) __rand48_mult[0] * (unsigned long) xseed[0] +
(unsigned long) __rand48_add;
temp[0] = (unsigned short) accu; /* lower 16 bits */
accu >>= sizeof(unsigned short) * 8;
accu += (unsigned long) __rand48_mult[0] * (unsigned long) xseed[1] +
(unsigned long) __rand48_mult[1] * (unsigned long) xseed[0];
temp[1] = (unsigned short) accu; /* middle 16 bits */
accu >>= sizeof(unsigned short) * 8;
accu += __rand48_mult[0] * xseed[2] + __rand48_mult[1] * xseed[1] + __rand48_mult[2] * xseed[0];
xseed[0] = temp[0];
xseed[1] = temp[1];
xseed[2] = (unsigned short) accu;
}
/contrib/sdk/sources/newlib/libc/stdlib/rand48.h
0,0 → 1,36
/*
* Copyright (c) 1993 Martin Birgmeier
* All rights reserved.
*
* You may redistribute unmodified or modified versions of this source
* code provided that the above copyright notice and this and the
* following conditions are retained.
*
* This software is provided ``as is'', and comes with no warranties
* of any kind. I shall in no event be liable for anything that happens
* to anyone/anything when using this software.
*/
 
#ifndef _RAND48_H_
#define _RAND48_H_
 
#include <math.h>
#include <stdlib.h>
 
extern void _EXFUN(__dorand48,(struct _reent *r, unsigned short[3]));
#define __rand48_seed _REENT_RAND48_SEED(r)
#define __rand48_mult _REENT_RAND48_MULT(r)
#define __rand48_add _REENT_RAND48_ADD(r)
 
#if 0
/* following values are defined in <sys/reent.h> */
#define RAND48_SEED_0 (0x330e)
#define RAND48_SEED_1 (0xabcd)
#define RAND48_SEED_2 (0x1234)
#define RAND48_MULT_0 (0xe66d)
#define RAND48_MULT_1 (0xdeec)
#define RAND48_MULT_2 (0x0005)
#define RAND48_ADD (0x000b)
#endif
 
#endif /* _RAND48_H_ */
/contrib/sdk/sources/newlib/libc/stdlib/rand_r.c
0,0 → 1,37
#include <stdlib.h>
 
/* Pseudo-random generator based on Minimal Standard by
Lewis, Goodman, and Miller in 1969.
I[j+1] = a*I[j] (mod m)
 
where a = 16807
m = 2147483647
 
Using Schrage's algorithm, a*I[j] (mod m) can be rewritten as:
a*(I[j] mod q) - r*{I[j]/q} if >= 0
a*(I[j] mod q) - r*{I[j]/q} + m otherwise
 
where: {} denotes integer division
q = {m/a} = 127773
r = m (mod a) = 2836
 
note that the seed value of 0 cannot be used in the calculation as
it results in 0 itself
*/
int
_DEFUN (rand_r, (seed), unsigned int *seed)
{
long k;
long s = (long)(*seed);
if (s == 0)
s = 0x12345987;
k = s / 127773;
s = 16807 * (s - k * 127773) - 2836 * k;
if (s < 0)
s += 2147483647;
(*seed) = (unsigned int)s;
return (int)(s & RAND_MAX);
}
/contrib/sdk/sources/newlib/libc/stdlib/realloc.c
0,0 → 1,22
#ifdef MALLOC_PROVIDED
int _dummy_calloc = 1;
#else
/* 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
#endif /* MALLOC_PROVIDED */
/contrib/sdk/sources/newlib/libc/stdlib/seed48.c
0,0 → 1,44
/*
* Copyright (c) 1993 Martin Birgmeier
* All rights reserved.
*
* You may redistribute unmodified or modified versions of this source
* code provided that the above copyright notice and this and the
* following conditions are retained.
*
* This software is provided ``as is'', and comes with no warranties
* of any kind. I shall in no event be liable for anything that happens
* to anyone/anything when using this software.
*/
 
#include "rand48.h"
 
unsigned short *
_DEFUN (_seed48_r, (r, xseed),
struct _reent *r _AND
unsigned short xseed[3])
{
static unsigned short sseed[3];
 
_REENT_CHECK_RAND48(r);
sseed[0] = __rand48_seed[0];
sseed[1] = __rand48_seed[1];
sseed[2] = __rand48_seed[2];
__rand48_seed[0] = xseed[0];
__rand48_seed[1] = xseed[1];
__rand48_seed[2] = xseed[2];
__rand48_mult[0] = _RAND48_MULT_0;
__rand48_mult[1] = _RAND48_MULT_1;
__rand48_mult[2] = _RAND48_MULT_2;
__rand48_add = _RAND48_ADD;
return sseed;
}
 
#ifndef _REENT_ONLY
unsigned short *
_DEFUN (seed48, (xseed),
unsigned short xseed[3])
{
return _seed48_r (_REENT, xseed);
}
#endif /* !_REENT_ONLY */
/contrib/sdk/sources/newlib/libc/stdlib/srand48.c
0,0 → 1,38
/*
* Copyright (c) 1993 Martin Birgmeier
* All rights reserved.
*
* You may redistribute unmodified or modified versions of this source
* code provided that the above copyright notice and this and the
* following conditions are retained.
*
* This software is provided ``as is'', and comes with no warranties
* of any kind. I shall in no event be liable for anything that happens
* to anyone/anything when using this software.
*/
 
#include "rand48.h"
 
_VOID
_DEFUN (_srand48_r, (r, seed),
struct _reent *r _AND
long seed)
{
_REENT_CHECK_RAND48(r);
__rand48_seed[0] = _RAND48_SEED_0;
__rand48_seed[1] = (unsigned short) seed;
__rand48_seed[2] = (unsigned short) ((unsigned long)seed >> 16);
__rand48_mult[0] = _RAND48_MULT_0;
__rand48_mult[1] = _RAND48_MULT_1;
__rand48_mult[2] = _RAND48_MULT_2;
__rand48_add = _RAND48_ADD;
}
 
#ifndef _REENT_ONLY
_VOID
_DEFUN (srand48, (seed),
long seed)
{
_srand48_r (_REENT, seed);
}
#endif /* !_REENT_ONLY */
/contrib/sdk/sources/newlib/libc/stdlib/std.h
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);
double __exp10(unsigned x);
#else
int __ten_mul();
double __adjust();
double __exp10();
#endif
/contrib/sdk/sources/newlib/libc/stdlib/strtod.c
0,0 → 1,1197
/*
FUNCTION
<<strtod>>, <<strtof>>---string to double or float
 
INDEX
strtod
INDEX
_strtod_r
INDEX
strtof
 
ANSI_SYNOPSIS
#include <stdlib.h>
double strtod(const char *<[str]>, char **<[tail]>);
float strtof(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 strtof(<[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 one of these formats:
.[+|-]<[digits]>[.[<[digits]>]][(e|E)[+|-]<[digits]>]
.[+|-].<[digits]>[(e|E)[+|-]<[digits]>]
.[+|-](i|I)(n|N)(f|F)[(i|I)(n|N)(i|I)(t|T)(y|Y)]
.[+|-](n|N)(a|A)(n|N)[<(>[<[hexdigits]>]<)>]
.[+|-]0(x|X)<[hexdigits]>[.[<[hexdigits]>]][(p|P)[+|-]<[digits]>]
.[+|-]0(x|X).<[hexdigits]>[(p|P)[+|-]<[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, and cannot be parsed as infinity or NaN. If the platform
does not support NaN, then NaN is treated as an empty substring.
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]>.
<<strtof>> 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. However, <<strtof>> is currently subject to
double rounding errors.
 
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) 1998-2001 by Lucent Technologies
All Rights Reserved
 
Permission to use, copy, modify, and distribute this software and
its documentation for any purpose and without fee is hereby
granted, provided that the above copyright notice appear in all
copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of Lucent or any of its entities
not be used in advertising or publicity pertaining to
distribution of the software without specific, written prior
permission.
 
LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
THIS SOFTWARE.
 
****************************************************************/
 
/* Please send bug reports to David M. Gay (dmg at acm dot org,
* with " at " changed at "@" and " dot " changed to "."). */
 
/* Original file gdtoa-strtod.c Modified 06-21-2006 by Jeff Johnston to work within newlib. */
 
#include <_ansi.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include "mprec.h"
#include "gdtoa.h"
#include "gd_qnan.h"
 
/* #ifndef NO_FENV_H */
/* #include <fenv.h> */
/* #endif */
 
#include "locale.h"
 
#ifdef IEEE_Arith
#ifndef NO_IEEE_Scale
#define Avoid_Underflow
#undef tinytens
/* The factor of 2^53 in tinytens[4] helps us avoid setting the underflow */
/* flag unnecessarily. It leads to a song and dance at the end of strtod. */
static _CONST double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128,
9007199254740992.e-256
};
#endif
#endif
 
#ifdef Honor_FLT_ROUNDS
#define Rounding rounding
#undef Check_FLT_ROUNDS
#define Check_FLT_ROUNDS
#else
#define Rounding Flt_Rounds
#endif
 
#ifndef NO_HEX_FP
 
static void
_DEFUN (ULtod, (L, bits, exp, k),
__ULong *L _AND
__ULong *bits _AND
Long exp _AND
int k)
{
switch(k & STRTOG_Retmask) {
case STRTOG_NoNumber:
case STRTOG_Zero:
L[0] = L[1] = 0;
break;
 
case STRTOG_Denormal:
L[_1] = bits[0];
L[_0] = bits[1];
break;
 
case STRTOG_Normal:
case STRTOG_NaNbits:
L[_1] = bits[0];
L[_0] = (bits[1] & ~0x100000) | ((exp + 0x3ff + 52) << 20);
break;
 
case STRTOG_Infinite:
L[_0] = 0x7ff00000;
L[_1] = 0;
break;
 
case STRTOG_NaN:
L[_0] = 0x7fffffff;
L[_1] = (__ULong)-1;
}
if (k & STRTOG_Neg)
L[_0] |= 0x80000000L;
}
#endif /* !NO_HEX_FP */
 
#ifdef INFNAN_CHECK
static int
_DEFUN (match, (sp, t),
_CONST char **sp _AND
char *t)
{
int c, d;
_CONST char *s = *sp;
 
while( (d = *t++) !=0) {
if ((c = *++s) >= 'A' && c <= 'Z')
c += 'a' - 'A';
if (c != d)
return 0;
}
*sp = s + 1;
return 1;
}
#endif /* INFNAN_CHECK */
 
 
double
_DEFUN (_strtod_r, (ptr, s00, se),
struct _reent *ptr _AND
_CONST char *s00 _AND
char **se)
{
#ifdef Avoid_Underflow
int scale;
#endif
int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, decpt, dsign,
e, e1, esign, i, j, k, nd, nd0, nf, nz, nz0, sign;
_CONST char *s, *s0, *s1;
double aadj, adj;
U aadj1, rv, rv0;
Long L;
__ULong y, z;
_Bigint *bb, *bb1, *bd, *bd0, *bs, *delta;
#ifdef SET_INEXACT
int inexact, oldinexact;
#endif
#ifdef Honor_FLT_ROUNDS
int rounding;
#endif
 
delta = bs = bd = NULL;
sign = nz0 = nz = decpt = 0;
dval(rv) = 0.;
for(s = s00;;s++) switch(*s) {
case '-':
sign = 1;
/* no break */
case '+':
if (*++s)
goto break2;
/* no break */
case 0:
goto ret0;
case '\t':
case '\n':
case '\v':
case '\f':
case '\r':
case ' ':
continue;
default:
goto break2;
}
break2:
if (*s == '0') {
#ifndef NO_HEX_FP
{
static FPI fpi = { 53, 1-1023-53+1, 2046-1023-53+1, 1, SI };
Long exp;
__ULong bits[2];
switch(s[1]) {
case 'x':
case 'X':
/* If the number is not hex, then the parse of
0 is still valid. */
s00 = s + 1;
{
#if defined(FE_DOWNWARD) && defined(FE_TONEAREST) && defined(FE_TOWARDZERO) && defined(FE_UPWARD)
FPI fpi1 = fpi;
switch(fegetround()) {
case FE_TOWARDZERO: fpi1.rounding = 0; break;
case FE_UPWARD: fpi1.rounding = 2; break;
case FE_DOWNWARD: fpi1.rounding = 3;
}
#else
#define fpi1 fpi
#endif
switch((i = gethex(ptr, &s, &fpi1, &exp, &bb, sign)) & STRTOG_Retmask) {
case STRTOG_NoNumber:
s = s00;
case STRTOG_Zero:
break;
default:
if (bb) {
copybits(bits, fpi.nbits, bb);
Bfree(ptr,bb);
}
ULtod(rv.i, bits, exp, i);
}}
goto ret;
}
}
#endif
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 < DBL_DIG + 1) {
if (nd < 9)
y = 10*y + c - '0';
else
z = 10*z + c - '0';
}
}
nd0 = nd;
if (strncmp (s, _localeconv_r (ptr)->decimal_point,
strlen (_localeconv_r (ptr)->decimal_point)) == 0) {
decpt = 1;
c = *(s += strlen (_localeconv_r (ptr)->decimal_point));
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') {
for(i = 1; i < nz; i++) {
if (nd <= DBL_DIG + 1) {
if (nd + i < 10)
y *= 10;
else
z *= 10;
}
}
if (nd <= DBL_DIG + 1) {
if (nd + i < 10)
y = 10*y + c;
else
z = 10*z + c;
}
if (nd <= DBL_DIG + 1) {
nf += nz;
nd += nz;
}
nz = 0;
}
}
}
dig_done:
e = 0;
if (c == 'e' || c == 'E') {
if (!nd && !nz && !nz0) {
goto ret0;
}
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') {
L = c - '0';
s1 = s;
while((c = *++s) >= '0' && c <= '9')
L = 10*L + c - '0';
if (s - s1 > 8 || L > 19999)
/* Avoid confusion from exponents
* so large that e might overflow.
*/
e = 19999; /* safe for 16 bit ints */
else
e = (int)L;
if (esign)
e = -e;
}
else
e = 0;
}
else
s = s00;
}
if (!nd) {
if (!nz && !nz0) {
#ifdef INFNAN_CHECK
/* Check for Nan and Infinity */
__ULong bits[2];
static FPI fpinan = /* only 52 explicit bits */
{ 52, 1-1023-53+1, 2046-1023-53+1, 1, SI };
if (!decpt)
switch(c) {
case 'i':
case 'I':
if (match(&s,"nf")) {
--s;
if (!match(&s,"inity"))
++s;
dword0(rv) = 0x7ff00000;
#ifndef _DOUBLE_IS_32BITS
dword1(rv) = 0;
#endif /*!_DOUBLE_IS_32BITS*/
goto ret;
}
break;
case 'n':
case 'N':
if (match(&s, "an")) {
#ifndef No_Hex_NaN
if (*s == '(' /*)*/
&& hexnan(&s, &fpinan, bits)
== STRTOG_NaNbits) {
dword0(rv) = 0x7ff00000 | bits[1];
#ifndef _DOUBLE_IS_32BITS
dword1(rv) = bits[0];
#endif /*!_DOUBLE_IS_32BITS*/
}
else {
#endif
dword0(rv) = NAN_WORD0;
#ifndef _DOUBLE_IS_32BITS
dword1(rv) = NAN_WORD1;
#endif /*!_DOUBLE_IS_32BITS*/
#ifndef No_Hex_NaN
}
#endif
goto ret;
}
}
#endif /* INFNAN_CHECK */
ret0:
s = s00;
sign = 0;
}
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;
dval(rv) = y;
if (k > 9) {
#ifdef SET_INEXACT
if (k > DBL_DIG)
oldinexact = get_inexact();
#endif
dval(rv) = tens[k - 9] * dval(rv) + z;
}
bd0 = 0;
if (nd <= DBL_DIG
#ifndef RND_PRODQUOT
#ifndef Honor_FLT_ROUNDS
&& Flt_Rounds == 1
#endif
#endif
) {
if (!e)
goto ret;
if (e > 0) {
if (e <= Ten_pmax) {
#ifdef VAX
goto vax_ovfl_check;
#else
#ifdef Honor_FLT_ROUNDS
/* round correctly FLT_ROUNDS = 2 or 3 */
if (sign) {
dval(rv) = -dval(rv);
sign = 0;
}
#endif
/* rv = */ rounded_product(dval(rv), 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.
*/
#ifdef Honor_FLT_ROUNDS
/* round correctly FLT_ROUNDS = 2 or 3 */
if (sign) {
dval(rv) = -dval(rv);
sign = 0;
}
#endif
e -= i;
dval(rv) *= tens[i];
#ifdef VAX
/* VAX exponent range is so narrow we must
* worry about overflow here...
*/
vax_ovfl_check:
dword0(rv) -= P*Exp_msk1;
/* rv = */ rounded_product(dval(rv), tens[e]);
if ((dword0(rv) & Exp_mask)
> Exp_msk1*(DBL_MAX_EXP+Bias-1-P))
goto ovfl;
dword0(rv) += P*Exp_msk1;
#else
/* rv = */ rounded_product(dval(rv), tens[e]);
#endif
goto ret;
}
}
#ifndef Inaccurate_Divide
else if (e >= -Ten_pmax) {
#ifdef Honor_FLT_ROUNDS
/* round correctly FLT_ROUNDS = 2 or 3 */
if (sign) {
dval(rv) = -dval(rv);
sign = 0;
}
#endif
/* rv = */ rounded_quotient(dval(rv), tens[-e]);
goto ret;
}
#endif
}
e1 += nd - k;
 
#ifdef IEEE_Arith
#ifdef SET_INEXACT
inexact = 1;
if (k <= DBL_DIG)
oldinexact = get_inexact();
#endif
#ifdef Avoid_Underflow
scale = 0;
#endif
#ifdef Honor_FLT_ROUNDS
if ((rounding = Flt_Rounds) >= 2) {
if (sign)
rounding = rounding == 2 ? 0 : 2;
else
if (rounding != 2)
rounding = 0;
}
#endif
#endif /*IEEE_Arith*/
 
/* Get starting approximation = rv * 10**e1 */
 
if (e1 > 0) {
if ( (i = e1 & 15) !=0)
dval(rv) *= tens[i];
if (e1 &= ~15) {
if (e1 > DBL_MAX_10_EXP) {
ovfl:
#ifndef NO_ERRNO
ptr->_errno = ERANGE;
#endif
/* Can't trust HUGE_VAL */
#ifdef IEEE_Arith
#ifdef Honor_FLT_ROUNDS
switch(rounding) {
case 0: /* toward 0 */
case 3: /* toward -infinity */
dword0(rv) = Big0;
#ifndef _DOUBLE_IS_32BITS
dword1(rv) = Big1;
#endif /*!_DOUBLE_IS_32BITS*/
break;
default:
dword0(rv) = Exp_mask;
#ifndef _DOUBLE_IS_32BITS
dword1(rv) = 0;
#endif /*!_DOUBLE_IS_32BITS*/
}
#else /*Honor_FLT_ROUNDS*/
dword0(rv) = Exp_mask;
#ifndef _DOUBLE_IS_32BITS
dword1(rv) = 0;
#endif /*!_DOUBLE_IS_32BITS*/
#endif /*Honor_FLT_ROUNDS*/
#ifdef SET_INEXACT
/* set overflow bit */
dval(rv0) = 1e300;
dval(rv0) *= dval(rv0);
#endif
#else /*IEEE_Arith*/
dword0(rv) = Big0;
#ifndef _DOUBLE_IS_32BITS
dword1(rv) = Big1;
#endif /*!_DOUBLE_IS_32BITS*/
#endif /*IEEE_Arith*/
if (bd0)
goto retfree;
goto ret;
}
e1 >>= 4;
for(j = 0; e1 > 1; j++, e1 >>= 1)
if (e1 & 1)
dval(rv) *= bigtens[j];
/* The last multiplication could overflow. */
dword0(rv) -= P*Exp_msk1;
dval(rv) *= bigtens[j];
if ((z = dword0(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) */
dword0(rv) = Big0;
#ifndef _DOUBLE_IS_32BITS
dword1(rv) = Big1;
#endif /*!_DOUBLE_IS_32BITS*/
}
else
dword0(rv) += P*Exp_msk1;
}
}
else if (e1 < 0) {
e1 = -e1;
if ( (i = e1 & 15) !=0)
dval(rv) /= tens[i];
if (e1 >>= 4) {
if (e1 >= 1 << n_bigtens)
goto undfl;
#ifdef Avoid_Underflow
if (e1 & Scale_Bit)
scale = 2*P;
for(j = 0; e1 > 0; j++, e1 >>= 1)
if (e1 & 1)
dval(rv) *= tinytens[j];
if (scale && (j = 2*P + 1 - ((dword0(rv) & Exp_mask)
>> Exp_shift)) > 0) {
/* scaled rv is denormal; zap j low bits */
if (j >= 32) {
#ifndef _DOUBLE_IS_32BITS
dword1(rv) = 0;
#endif /*!_DOUBLE_IS_32BITS*/
if (j >= 53)
dword0(rv) = (P+2)*Exp_msk1;
else
dword0(rv) &= 0xffffffff << (j-32);
}
#ifndef _DOUBLE_IS_32BITS
else
dword1(rv) &= 0xffffffff << j;
#endif /*!_DOUBLE_IS_32BITS*/
}
#else
for(j = 0; e1 > 1; j++, e1 >>= 1)
if (e1 & 1)
dval(rv) *= tinytens[j];
/* The last multiplication could underflow. */
dval(rv0) = dval(rv);
dval(rv) *= tinytens[j];
if (!dval(rv)) {
dval(rv) = 2.*dval(rv0);
dval(rv) *= tinytens[j];
#endif
if (!dval(rv)) {
undfl:
dval(rv) = 0.;
#ifndef NO_ERRNO
ptr->_errno = ERANGE;
#endif
if (bd0)
goto retfree;
goto ret;
}
#ifndef Avoid_Underflow
#ifndef _DOUBLE_IS_32BITS
dword0(rv) = Tiny0;
dword1(rv) = Tiny1;
#else
dword0(rv) = Tiny1;
#endif /*_DOUBLE_IS_32BITS*/
/* The refinement below will clean
* this approximation up.
*/
}
#endif
}
}
 
/* 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,dval(rv), &bbe, &bbbits); /* rv = 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 Honor_FLT_ROUNDS
if (rounding != 1)
bs2++;
#endif
#ifdef Avoid_Underflow
j = bbe - scale;
i = j + bbbits - 1; /* logb(rv) */
if (i < Emin) /* denormal */
j += P - Emin;
else
j = P + 1 - bbbits;
#else /*Avoid_Underflow*/
#ifdef Sudden_Underflow
#ifdef IBM
j = 1 + 4*P - 3 - bbbits + ((bbe + bbbits - 1) & 3);
#else
j = P + 1 - bbbits;
#endif
#else /*Sudden_Underflow*/
j = bbe;
i = j + bbbits - 1; /* logb(rv) */
if (i < Emin) /* denormal */
j += P - Emin;
else
j = P + 1 - bbbits;
#endif /*Sudden_Underflow*/
#endif /*Avoid_Underflow*/
bb2 += j;
bd2 += j;
#ifdef Avoid_Underflow
bd2 += scale;
#endif
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);
#ifdef Honor_FLT_ROUNDS
if (rounding != 1) {
if (i < 0) {
/* Error is less than an ulp */
if (!delta->_x[0] && delta->_wds <= 1) {
/* exact */
#ifdef SET_INEXACT
inexact = 0;
#endif
break;
}
if (rounding) {
if (dsign) {
adj = 1.;
goto apply_adj;
}
}
else if (!dsign) {
adj = -1.;
if (!dword1(rv)
&& !(dword0(rv) & Frac_mask)) {
y = dword0(rv) & Exp_mask;
#ifdef Avoid_Underflow
if (!scale || y > 2*P*Exp_msk1)
#else
if (y)
#endif
{
delta = lshift(ptr, delta,Log2P);
if (cmp(delta, bs) <= 0)
adj = -0.5;
}
}
apply_adj:
#ifdef Avoid_Underflow
if (scale && (y = dword0(rv) & Exp_mask)
<= 2*P*Exp_msk1)
dword0(adj) += (2*P+1)*Exp_msk1 - y;
#else
#ifdef Sudden_Underflow
if ((dword0(rv) & Exp_mask) <=
P*Exp_msk1) {
dword0(rv) += P*Exp_msk1;
dval(rv) += adj*ulp(dval(rv));
dword0(rv) -= P*Exp_msk1;
}
else
#endif /*Sudden_Underflow*/
#endif /*Avoid_Underflow*/
dval(rv) += adj*ulp(dval(rv));
}
break;
}
adj = ratio(delta, bs);
if (adj < 1.)
adj = 1.;
if (adj <= 0x7ffffffe) {
/* adj = rounding ? ceil(adj) : floor(adj); */
y = adj;
if (y != adj) {
if (!((rounding>>1) ^ dsign))
y++;
adj = y;
}
}
#ifdef Avoid_Underflow
if (scale && (y = dword0(rv) & Exp_mask) <= 2*P*Exp_msk1)
dword0(adj) += (2*P+1)*Exp_msk1 - y;
#else
#ifdef Sudden_Underflow
if ((dword0(rv) & Exp_mask) <= P*Exp_msk1) {
dword0(rv) += P*Exp_msk1;
adj *= ulp(dval(rv));
if (dsign)
dval(rv) += adj;
else
dval(rv) -= adj;
dword0(rv) -= P*Exp_msk1;
goto cont;
}
#endif /*Sudden_Underflow*/
#endif /*Avoid_Underflow*/
adj *= ulp(dval(rv));
if (dsign)
dval(rv) += adj;
else
dval(rv) -= adj;
goto cont;
}
#endif /*Honor_FLT_ROUNDS*/
 
if (i < 0) {
/* Error is less than half an ulp -- check for
* special case of mantissa a power of two.
*/
if (dsign || dword1(rv) || dword0(rv) & Bndry_mask
#ifdef IEEE_Arith
#ifdef Avoid_Underflow
|| (dword0(rv) & Exp_mask) <= (2*P+1)*Exp_msk1
#else
|| (dword0(rv) & Exp_mask) <= Exp_msk1
#endif
#endif
) {
#ifdef SET_INEXACT
if (!delta->x[0] && delta->wds <= 1)
inexact = 0;
#endif
break;
}
if (!delta->_x[0] && delta->_wds <= 1) {
/* exact result */
#ifdef SET_INEXACT
inexact = 0;
#endif
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 ((dword0(rv) & Bndry_mask1) == Bndry_mask1
&& dword1(rv) == (
#ifdef Avoid_Underflow
(scale && (y = dword0(rv) & Exp_mask) <= 2*P*Exp_msk1)
? (0xffffffff & (0xffffffff << (2*P+1-(y>>Exp_shift)))) :
#endif
0xffffffff)) {
/*boundary case -- increment exponent*/
dword0(rv) = (dword0(rv) & Exp_mask)
+ Exp_msk1
#ifdef IBM
| Exp_msk1 >> 4
#endif
;
#ifndef _DOUBLE_IS_32BITS
dword1(rv) = 0;
#endif /*!_DOUBLE_IS_32BITS*/
#ifdef Avoid_Underflow
dsign = 0;
#endif
break;
}
}
else if (!(dword0(rv) & Bndry_mask) && !dword1(rv)) {
drop_down:
/* boundary case -- decrement exponent */
#ifdef Sudden_Underflow /*{{*/
L = dword0(rv) & Exp_mask;
#ifdef IBM
if (L < Exp_msk1)
#else
#ifdef Avoid_Underflow
if (L <= (scale ? (2*P+1)*Exp_msk1 : Exp_msk1))
#else
if (L <= Exp_msk1)
#endif /*Avoid_Underflow*/
#endif /*IBM*/
goto undfl;
L -= Exp_msk1;
#else /*Sudden_Underflow}{*/
#ifdef Avoid_Underflow
if (scale) {
L = dword0(rv) & Exp_mask;
if (L <= (2*P+1)*Exp_msk1) {
if (L > (P+2)*Exp_msk1)
/* round even ==> */
/* accept rv */
break;
/* rv = smallest denormal */
goto undfl;
}
}
#endif /*Avoid_Underflow*/
L = (dword0(rv) & Exp_mask) - Exp_msk1;
#endif /*Sudden_Underflow}*/
dword0(rv) = L | Bndry_mask1;
#ifndef _DOUBLE_IS_32BITS
dword1(rv) = 0xffffffff;
#endif /*!_DOUBLE_IS_32BITS*/
#ifdef IBM
goto cont;
#else
break;
#endif
}
#ifndef ROUND_BIASED
if (!(dword1(rv) & LSB))
break;
#endif
if (dsign)
dval(rv) += ulp(dval(rv));
#ifndef ROUND_BIASED
else {
dval(rv) -= ulp(dval(rv));
#ifndef Sudden_Underflow
if (!dval(rv))
goto undfl;
#endif
}
#ifdef Avoid_Underflow
dsign = 1 - dsign;
#endif
#endif
break;
}
if ((aadj = ratio(delta, bs)) <= 2.) {
if (dsign)
aadj = dval(aadj1) = 1.;
else if (dword1(rv) || dword0(rv) & Bndry_mask) {
#ifndef Sudden_Underflow
if (dword1(rv) == Tiny1 && !dword0(rv))
goto undfl;
#endif
aadj = 1.;
dval(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;
dval(aadj1) = -aadj;
}
}
else {
aadj *= 0.5;
dval(aadj1) = dsign ? aadj : -aadj;
#ifdef Check_FLT_ROUNDS
switch(Rounding) {
case 2: /* towards +infinity */
dval(aadj1) -= 0.5;
break;
case 0: /* towards 0 */
case 3: /* towards -infinity */
dval(aadj1) += 0.5;
}
#else
if (Flt_Rounds == 0)
dval(aadj1) += 0.5;
#endif /*Check_FLT_ROUNDS*/
}
y = dword0(rv) & Exp_mask;
 
/* Check for overflow */
 
if (y == Exp_msk1*(DBL_MAX_EXP+Bias-1)) {
dval(rv0) = dval(rv);
dword0(rv) -= P*Exp_msk1;
adj = dval(aadj1) * ulp(dval(rv));
dval(rv) += adj;
if ((dword0(rv) & Exp_mask) >=
Exp_msk1*(DBL_MAX_EXP+Bias-P)) {
if (dword0(rv0) == Big0 && dword1(rv0) == Big1)
goto ovfl;
dword0(rv) = Big0;
#ifndef _DOUBLE_IS_32BITS
dword1(rv) = Big1;
#endif /*!_DOUBLE_IS_32BITS*/
goto cont;
}
else
dword0(rv) += P*Exp_msk1;
}
else {
#ifdef Avoid_Underflow
if (scale && y <= 2*P*Exp_msk1) {
if (aadj <= 0x7fffffff) {
if ((z = aadj) <= 0)
z = 1;
aadj = z;
dval(aadj1) = dsign ? aadj : -aadj;
}
dword0(aadj1) += (2*P+1)*Exp_msk1 - y;
}
adj = dval(aadj1) * ulp(dval(rv));
dval(rv) += adj;
#else
#ifdef Sudden_Underflow
if ((dword0(rv) & Exp_mask) <= P*Exp_msk1) {
dval(rv0) = dval(rv);
dword0(rv) += P*Exp_msk1;
adj = dval(aadj1) * ulp(dval(rv));
dval(rv) += adj;
#ifdef IBM
if ((dword0(rv) & Exp_mask) < P*Exp_msk1)
#else
if ((dword0(rv) & Exp_mask) <= P*Exp_msk1)
#endif
{
if (dword0(rv0) == Tiny0
&& dword1(rv0) == Tiny1)
goto undfl;
#ifndef _DOUBLE_IS_32BITS
dword0(rv) = Tiny0;
dword1(rv) = Tiny1;
#else
dword0(rv) = Tiny1;
#endif /*_DOUBLE_IS_32BITS*/
goto cont;
}
else
dword0(rv) -= P*Exp_msk1;
}
else {
adj = dval(aadj1) * ulp(dval(rv));
dval(rv) += adj;
}
#else /*Sudden_Underflow*/
/* Compute adj so that the IEEE rounding rules will
* correctly round rv + adj in some half-way cases.
* If rv * ulp(rv) 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.) {
dval(aadj1) = (double)(int)(aadj + 0.5);
if (!dsign)
dval(aadj1) = -dval(aadj1);
}
adj = dval(aadj1) * ulp(dval(rv));
dval(rv) += adj;
#endif /*Sudden_Underflow*/
#endif /*Avoid_Underflow*/
}
z = dword0(rv) & Exp_mask;
#ifndef SET_INEXACT
#ifdef Avoid_Underflow
if (!scale)
#endif
if (y == z) {
/* Can we stop now? */
L = (Long)aadj;
aadj -= L;
/* The tolerances below are conservative. */
if (dsign || dword1(rv) || dword0(rv) & Bndry_mask) {
if (aadj < .4999999 || aadj > .5000001)
break;
}
else if (aadj < .4999999/FLT_RADIX)
break;
}
#endif
cont:
Bfree(ptr,bb);
Bfree(ptr,bd);
Bfree(ptr,bs);
Bfree(ptr,delta);
}
#ifdef SET_INEXACT
if (inexact) {
if (!oldinexact) {
dword0(rv0) = Exp_1 + (70 << Exp_shift);
#ifndef _DOUBLE_IS_32BITS
dword1(rv0) = 0;
#endif /*!_DOUBLE_IS_32BITS*/
dval(rv0) += 1.;
}
}
else if (!oldinexact)
clear_inexact();
#endif
#ifdef Avoid_Underflow
if (scale) {
dword0(rv0) = Exp_1 - 2*P*Exp_msk1;
#ifndef _DOUBLE_IS_32BITS
dword1(rv0) = 0;
#endif /*!_DOUBLE_IS_32BITS*/
dval(rv) *= dval(rv0);
#ifndef NO_ERRNO
/* try to avoid the bug of testing an 8087 register value */
if (dword0(rv) == 0 && dword1(rv) == 0)
ptr->_errno = ERANGE;
#endif
}
#endif /* Avoid_Underflow */
#ifdef SET_INEXACT
if (inexact && !(dword0(rv) & Exp_mask)) {
/* set underflow bit */
dval(rv0) = 1e-300;
dval(rv0) *= dval(rv0);
}
#endif
retfree:
Bfree(ptr,bb);
Bfree(ptr,bd);
Bfree(ptr,bs);
Bfree(ptr,bd0);
Bfree(ptr,delta);
ret:
if (se)
*se = (char *)s;
return sign ? -dval(rv) : dval(rv);
}
 
#ifndef _REENT_ONLY
 
double
_DEFUN (strtod, (s00, se),
_CONST char *s00 _AND char **se)
{
return _strtod_r (_REENT, s00, se);
}
 
float
_DEFUN (strtof, (s00, se),
_CONST char *s00 _AND
char **se)
{
double retval = _strtod_r (_REENT, s00, se);
if (isnan (retval))
return nanf (NULL);
return (float)retval;
}
 
#endif
/contrib/sdk/sources/newlib/libc/stdlib/strtol.c
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 unsigned char *s = (const unsigned char *)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 ? (char *)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
/contrib/sdk/sources/newlib/libc/stdlib/strtold.c
0,0 → 1,42
/*
(C) Copyright IBM Corp. 2009
 
All rights reserved.
 
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
 
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* 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.
* Neither the name of IBM 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
 
#include <stdlib.h>
#include "local.h"
 
/* On platforms where long double is as wide as double. */
#ifdef _LDBL_EQ_DBL
long double
strtold (const char *s00, char **se)
{
return strtod(s00, se);
}
#endif /* _LDBL_EQ_DBL */
 
/contrib/sdk/sources/newlib/libc/stdlib/strtoll.c
0,0 → 1,138
/*
FUNCTION
<<strtoll>>---string to long long
 
INDEX
strtoll
INDEX
_strtoll_r
 
ANSI_SYNOPSIS
#include <stdlib.h>
long long strtoll(const char *<[s]>, char **<[ptr]>,int <[base]>);
 
long long _strtoll_r(void *<[reent]>,
const char *<[s]>, char **<[ptr]>,int <[base]>);
 
TRAD_SYNOPSIS
#include <stdlib.h>
long long strtoll (<[s]>, <[ptr]>, <[base]>)
const char *<[s]>;
char **<[ptr]>;
int <[base]>;
 
long long _strtoll_r (<[reent]>, <[s]>, <[ptr]>, <[base]>)
char *<[reent]>;
const char *<[s]>;
char **<[ptr]>;
int <[base]>;
 
DESCRIPTION
The function <<strtoll>> converts the string <<*<[s]>>> to
a <<long 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 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,
<<strtoll>> 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 <<_strtoll_r>> is a reentrant version. The
extra argument <[reent]> is a pointer to a reentrancy structure.
 
RETURNS
<<strtoll>> returns the converted value, if any. If no conversion was
made, 0 is returned.
 
<<strtoll>> returns <<LONG_LONG_MAX>> or <<LONG_LONG_MIN>> if the magnitude of
the converted value is too large, and sets <<errno>> to <<ERANGE>>.
 
PORTABILITY
<<strtoll>> 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>
 
#ifndef _REENT_ONLY
 
long long
_DEFUN (strtoll, (s, ptr, base),
_CONST char *s _AND
char **ptr _AND
int base)
{
return _strtoll_r (_REENT, s, ptr, base);
}
 
#endif
/contrib/sdk/sources/newlib/libc/stdlib/strtoll_r.c
0,0 → 1,140
/*
This code is based on strtoul.c which has the following copyright.
It is used to convert a string into a signed long long.
 
long long _strtoll_r (struct _reent *rptr, const char *s,
char **ptr, int base);
*/
 
/*-
* 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.
*/
 
#ifdef __GNUC__
 
#define _GNU_SOURCE
#include <_ansi.h>
#include <limits.h>
#include <ctype.h>
#include <errno.h>
#include <stdlib.h>
#include <reent.h>
 
/*
* Convert a string to a long long integer.
*
* Ignores `locale' stuff. Assumes that the upper and lower case
* alphabets and digits are each contiguous.
*/
long long
_DEFUN (_strtoll_r, (rptr, nptr, endptr, base),
struct _reent *rptr _AND
_CONST char *nptr _AND
char **endptr _AND
int base)
{
register const unsigned char *s = (const unsigned char *)nptr;
register unsigned long long acc;
register int c;
register unsigned long 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)LONG_LONG_MIN : LONG_LONG_MAX;
cutlim = cutoff % (unsigned long long)base;
cutoff /= (unsigned long 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_LONG_MIN : LONG_LONG_MAX;
rptr->_errno = ERANGE;
} else if (neg)
acc = -acc;
if (endptr != 0)
*endptr = (char *) (any ? (char *)s - 1 : nptr);
return (acc);
}
 
#endif /* __GNUC__ */
/contrib/sdk/sources/newlib/libc/stdlib/strtoul.c
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 unsigned char *s = (const unsigned char *)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 ? (char *)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
/contrib/sdk/sources/newlib/libc/stdlib/strtoull.c
0,0 → 1,139
/*
FUNCTION
<<strtoull>>---string to unsigned long long
 
INDEX
strtoull
INDEX
_strtoull_r
 
ANSI_SYNOPSIS
#include <stdlib.h>
unsigned long long strtoull(const char *<[s]>, char **<[ptr]>,
int <[base]>);
 
unsigned long long _strtoull_r(void *<[reent]>, const char *<[s]>,
char **<[ptr]>, int <[base]>);
 
TRAD_SYNOPSIS
#include <stdlib.h>
unsigned long long strtoull(<[s]>, <[ptr]>, <[base]>)
char *<[s]>;
char **<[ptr]>;
int <[base]>;
 
unsigned long long _strtoull_r(<[reent]>, <[s]>, <[ptr]>, <[base]>)
char *<[reent]>;
char *<[s]>;
char **<[ptr]>;
int <[base]>;
 
DESCRIPTION
The function <<strtoull>> converts the string <<*<[s]>>> to
an <<unsigned long 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 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,
<<strtoull>> 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 <<_strtoull_r>> is a reentrant version. The
extra argument <[reent]> is a pointer to a reentrancy structure.
 
 
RETURNS
<<strtoull>> returns the converted value, if any. If no conversion was
made, <<0>> is returned.
 
<<strtoull>> returns <<ULONG_LONG_MAX>> if the magnitude of the converted
value is too large, and sets <<errno>> to <<ERANGE>>.
 
PORTABILITY
<<strtoull>> is ANSI.
 
<<strtoull>> 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>
 
#ifndef _REENT_ONLY
 
unsigned long long
_DEFUN (strtoull, (s, ptr, base),
_CONST char *s _AND
char **ptr _AND
int base)
{
return _strtoull_r (_REENT, s, ptr, base);
}
 
#endif
/contrib/sdk/sources/newlib/libc/stdlib/strtoull_r.c
0,0 → 1,120
/*
This code is based on strtoul.c which has the following copyright.
It is used to convert a string into an unsigned long long.
long long _strtoull_r (struct _reent *rptr, const char *s,
char **ptr, int base);
 
*/
 
/*
* 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.
*/
 
#ifdef __GNUC__
 
#define _GNU_SOURCE
#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 long integer.
*
* Ignores `locale' stuff. Assumes that the upper and lower case
* alphabets and digits are each contiguous.
*/
unsigned long long
_DEFUN (_strtoull_r, (rptr, nptr, endptr, base),
struct _reent *rptr _AND
_CONST char *nptr _AND
char **endptr _AND
int base)
{
register const unsigned char *s = (const unsigned char *)nptr;
register unsigned long long acc;
register int c;
register unsigned long 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 long)ULONG_LONG_MAX / (unsigned long long)base;
cutlim = (unsigned long long)ULONG_LONG_MAX % (unsigned long 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_LONG_MAX;
rptr->_errno = ERANGE;
} else if (neg)
acc = -acc;
if (endptr != 0)
*endptr = (char *) (any ? (char *)s - 1 : nptr);
return (acc);
}
 
#endif /* __GNUC__ */
/contrib/sdk/sources/newlib/libc/stdlib/system.c
0,0 → 1,85
/*
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 <_ansi.h>
#include <errno.h>
#include <stddef.h>
#include <stdlib.h>
#include <unistd.h>
#include <_syslist.h>
#include <reent.h>
 
 
int
_DEFUN(_system_r, (ptr, s),
struct _reent *ptr _AND
_CONST char *s)
{
if (s == NULL)
return 0;
errno = ENOSYS;
return -1;
}
 
#ifndef _REENT_ONLY
 
int
_DEFUN(system, (s),
_CONST char *s)
{
return _system_r (_REENT, s);
}
 
#endif
/contrib/sdk/sources/newlib/libc/stdlib/wcrtomb.c
0,0 → 1,78
#include <reent.h>
#include <newlib.h>
#include <wchar.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include "local.h"
 
size_t
_DEFUN (_wcrtomb_r, (ptr, s, wc, ps),
struct _reent *ptr _AND
char *s _AND
wchar_t wc _AND
mbstate_t *ps)
{
int retval = 0;
char buf[10];
 
#ifdef _MB_CAPABLE
if (ps == NULL)
{
_REENT_CHECK_MISC(ptr);
ps = &(_REENT_WCRTOMB_STATE(ptr));
}
#endif
 
if (s == NULL)
retval = __wctomb (ptr, buf, L'\0', __locale_charset (), ps);
else
retval = __wctomb (ptr, s, wc, __locale_charset (), ps);
 
if (retval == -1)
{
ps->__count = 0;
ptr->_errno = EILSEQ;
return (size_t)(-1);
}
else
return (size_t)retval;
}
 
#ifndef _REENT_ONLY
size_t
_DEFUN (wcrtomb, (s, wc, ps),
char *s _AND
wchar_t wc _AND
mbstate_t *ps)
{
#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__)
return _wcrtomb_r (_REENT, s, wc, ps);
#else
int retval = 0;
char buf[10];
 
#ifdef _MB_CAPABLE
if (ps == NULL)
{
_REENT_CHECK_MISC(_REENT);
ps = &(_REENT_WCRTOMB_STATE(_REENT));
}
#endif
 
if (s == NULL)
retval = __wctomb (_REENT, buf, L'\0', __locale_charset (), ps);
else
retval = __wctomb (_REENT, s, wc, __locale_charset (), ps);
 
if (retval == -1)
{
ps->__count = 0;
_REENT->_errno = EILSEQ;
return (size_t)(-1);
}
else
return (size_t)retval;
#endif /* not PREFER_SIZE_OVER_SPEED */
}
#endif /* !_REENT_ONLY */
/contrib/sdk/sources/newlib/libc/stdlib/wctomb_r.c
0,0 → 1,376
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include <locale.h>
#include "mbctype.h"
#include "local.h"
 
int (*__wctomb) (struct _reent *, char *, wchar_t, const char *charset,
mbstate_t *)
#ifdef __CYGWIN__
/* Cygwin starts up in UTF-8 mode. */
= __utf8_wctomb;
#else
= __ascii_wctomb;
#endif
 
int
_DEFUN (_wctomb_r, (r, s, wchar, state),
struct _reent *r _AND
char *s _AND
wchar_t _wchar _AND
mbstate_t *state)
{
return __wctomb (r, s, _wchar, __locale_charset (), state);
}
 
int
_DEFUN (__ascii_wctomb, (r, s, wchar, charset, state),
struct _reent *r _AND
char *s _AND
wchar_t _wchar _AND
const char *charset _AND
mbstate_t *state)
{
/* Avoids compiler warnings about comparisons that are always false
due to limited range when sizeof(wchar_t) is 2 but sizeof(wint_t)
is 4, as is the case on cygwin. */
wint_t wchar = _wchar;
 
if (s == NULL)
return 0;
#ifdef __CYGWIN__
if ((size_t)wchar >= 0x80)
#else
if ((size_t)wchar >= 0x100)
#endif
{
r->_errno = EILSEQ;
return -1;
}
 
*s = (char) wchar;
return 1;
}
 
#ifdef _MB_CAPABLE
/* for some conversions, we use the __count field as a place to store a state value */
#define __state __count
 
int
_DEFUN (__utf8_wctomb, (r, s, wchar, charset, state),
struct _reent *r _AND
char *s _AND
wchar_t _wchar _AND
const char *charset _AND
mbstate_t *state)
{
wint_t wchar = _wchar;
int ret = 0;
 
if (s == NULL)
return 0; /* UTF-8 encoding is not state-dependent */
 
if (sizeof (wchar_t) == 2 && state->__count == -4
&& (wchar < 0xdc00 || wchar >= 0xdfff))
{
/* There's a leftover lone high surrogate. Write out the CESU-8 value
of the surrogate and proceed to convert the given character. Note
to return extra 3 bytes. */
wchar_t tmp;
tmp = (state->__value.__wchb[0] << 16 | state->__value.__wchb[1] << 8)
- 0x10000 >> 10 | 0xd80d;
*s++ = 0xe0 | ((tmp & 0xf000) >> 12);
*s++ = 0x80 | ((tmp & 0xfc0) >> 6);
*s++ = 0x80 | (tmp & 0x3f);
state->__count = 0;
ret = 3;
}
if (wchar <= 0x7f)
{
*s = wchar;
return ret + 1;
}
if (wchar >= 0x80 && wchar <= 0x7ff)
{
*s++ = 0xc0 | ((wchar & 0x7c0) >> 6);
*s = 0x80 | (wchar & 0x3f);
return ret + 2;
}
if (wchar >= 0x800 && wchar <= 0xffff)
{
/* No UTF-16 surrogate handling in UCS-4 */
if (sizeof (wchar_t) == 2 && wchar >= 0xd800 && wchar <= 0xdfff)
{
wint_t tmp;
if (wchar <= 0xdbff)
{
/* First half of a surrogate pair. Store the state and
return ret + 0. */
tmp = ((wchar & 0x3ff) << 10) + 0x10000;
state->__value.__wchb[0] = (tmp >> 16) & 0xff;
state->__value.__wchb[1] = (tmp >> 8) & 0xff;
state->__count = -4;
*s = (0xf0 | ((tmp & 0x1c0000) >> 18));
return ret;
}
if (state->__count == -4)
{
/* Second half of a surrogate pair. Reconstruct the full
Unicode value and return the trailing three bytes of the
UTF-8 character. */
tmp = (state->__value.__wchb[0] << 16)
| (state->__value.__wchb[1] << 8)
| (wchar & 0x3ff);
state->__count = 0;
*s++ = 0xf0 | ((tmp & 0x1c0000) >> 18);
*s++ = 0x80 | ((tmp & 0x3f000) >> 12);
*s++ = 0x80 | ((tmp & 0xfc0) >> 6);
*s = 0x80 | (tmp & 0x3f);
return 4;
}
/* Otherwise translate into CESU-8 value. */
}
*s++ = 0xe0 | ((wchar & 0xf000) >> 12);
*s++ = 0x80 | ((wchar & 0xfc0) >> 6);
*s = 0x80 | (wchar & 0x3f);
return ret + 3;
}
if (wchar >= 0x10000 && wchar <= 0x10ffff)
{
*s++ = 0xf0 | ((wchar & 0x1c0000) >> 18);
*s++ = 0x80 | ((wchar & 0x3f000) >> 12);
*s++ = 0x80 | ((wchar & 0xfc0) >> 6);
*s = 0x80 | (wchar & 0x3f);
return 4;
}
 
r->_errno = EILSEQ;
return -1;
}
 
/* Cygwin defines its own doublebyte charset conversion functions
because the underlying OS requires wchar_t == UTF-16. */
#ifndef __CYGWIN__
int
_DEFUN (__sjis_wctomb, (r, s, wchar, charset, state),
struct _reent *r _AND
char *s _AND
wchar_t _wchar _AND
const char *charset _AND
mbstate_t *state)
{
wint_t wchar = _wchar;
 
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
{
r->_errno = EILSEQ;
return -1;
}
}
*s = (char) wchar;
return 1;
}
 
int
_DEFUN (__eucjp_wctomb, (r, s, wchar, charset, state),
struct _reent *r _AND
char *s _AND
wchar_t _wchar _AND
const char *charset _AND
mbstate_t *state)
{
wint_t wchar = _wchar;
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 (_iseucjp1 (char1) && _iseucjp2 (char2))
{
*s++ = (char)char1;
*s = (char)char2;
return 2;
}
else if (_iseucjp2 (char1) && _iseucjp2 (char2 | 0x80))
{
*s++ = (char)0x8f;
*s++ = (char)char1;
*s = (char)(char2 | 0x80);
return 3;
}
else
{
r->_errno = EILSEQ;
return -1;
}
}
*s = (char) wchar;
return 1;
}
 
int
_DEFUN (__jis_wctomb, (r, s, wchar, charset, state),
struct _reent *r _AND
char *s _AND
wchar_t _wchar _AND
const char *charset _AND
mbstate_t *state)
{
wint_t wchar = _wchar;
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->__state == 0)
{
/* must switch from ASCII to JIS state */
state->__state = 1;
*s++ = ESC_CHAR;
*s++ = '$';
*s++ = 'B';
cnt = 3;
}
*s++ = (char)char1;
*s = (char)char2;
return cnt + 2;
}
r->_errno = EILSEQ;
return -1;
}
if (state->__state != 0)
{
/* must switch from JIS to ASCII state */
state->__state = 0;
*s++ = ESC_CHAR;
*s++ = '(';
*s++ = 'B';
cnt = 3;
}
*s = (char)char2;
return cnt + 1;
}
#endif /* !__CYGWIN__ */
 
#ifdef _MB_EXTENDED_CHARSETS_ISO
int
_DEFUN (__iso_wctomb, (r, s, wchar, charset, state),
struct _reent *r _AND
char *s _AND
wchar_t _wchar _AND
const char *charset _AND
mbstate_t *state)
{
wint_t wchar = _wchar;
 
if (s == NULL)
return 0;
 
/* wchars <= 0x9f translate to all ISO charsets directly. */
if (wchar >= 0xa0)
{
int iso_idx = __iso_8859_index (charset + 9);
if (iso_idx >= 0)
{
unsigned char mb;
 
if (s == NULL)
return 0;
 
for (mb = 0; mb < 0x60; ++mb)
if (__iso_8859_conv[iso_idx][mb] == wchar)
{
*s = (char) (mb + 0xa0);
return 1;
}
r->_errno = EILSEQ;
return -1;
}
}
if ((size_t)wchar >= 0x100)
{
r->_errno = EILSEQ;
return -1;
}
 
*s = (char) wchar;
return 1;
}
#endif /* _MB_EXTENDED_CHARSETS_ISO */
 
#ifdef _MB_EXTENDED_CHARSETS_WINDOWS
int
_DEFUN (__cp_wctomb, (r, s, wchar, charset, state),
struct _reent *r _AND
char *s _AND
wchar_t _wchar _AND
const char *charset _AND
mbstate_t *state)
{
wint_t wchar = _wchar;
 
if (s == NULL)
return 0;
 
if (wchar >= 0x80)
{
int cp_idx = __cp_index (charset + 2);
if (cp_idx >= 0)
{
unsigned char mb;
 
if (s == NULL)
return 0;
 
for (mb = 0; mb < 0x80; ++mb)
if (__cp_conv[cp_idx][mb] == wchar)
{
*s = (char) (mb + 0x80);
return 1;
}
r->_errno = EILSEQ;
return -1;
}
}
 
if ((size_t)wchar >= 0x100)
{
r->_errno = EILSEQ;
return -1;
}
 
*s = (char) wchar;
return 1;
}
#endif /* _MB_EXTENDED_CHARSETS_WINDOWS */
#endif /* _MB_CAPABLE */