/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 */ |