Standard Libraries for EDK II.

This set of three packages: AppPkg, StdLib, StdLibPrivateInternalFiles; contains the implementation of libraries based upon non-UEFI standards such as ISO/IEC-9899, the library portion of the C Language Standard, POSIX, etc.

AppPkg contains applications that make use of the standard libraries defined in the StdLib Package.

StdLib contains header (include) files and the implementations of the standard libraries.

StdLibPrivateInternalFiles contains files for the exclusive use of the library implementations in StdLib.  These files should never be directly referenced from applications or other code.


git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@11600 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
darylm503
2011-04-27 21:42:16 +00:00
parent 98790d8148
commit 2aa62f2bc9
503 changed files with 67344 additions and 0 deletions

View File

@@ -0,0 +1,105 @@
/** @file
Binary search utility function.
This utility makes use of a comparison function to search arrays of
unspecified type. Where an argument declared as size_t nmemb specifies the
length of the array for a function, nmemb can have the value zero on a call
to that function; the comparison function is not called, a search finds no
matching element. Pointer arguments on such a call shall still have valid
values.
The implementation shall ensure that the second argument of the comparison
function is a pointer to an element of the array. The first argument shall
equal key.
The comparison function shall not alter the contents of the array. The
implementation may reorder elements of the array between calls to the
comparison function, but shall not alter the contents of any individual
element.
When the same objects (consisting of size bytes, irrespective of their
current positions in the array) are passed more than once to the comparison
function, the results shall be consistent with one another. That is, the same
object shall always compare the same way with the key.
A sequence point occurs immediately before and immediately after each call to
the comparison function, and also between any call to the comparison function
and any movement of the objects passed as arguments to that call.
Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 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.
("$FreeBSD: src/lib/libc/stdlib/bsearch.c,v 1.4.10.1.2.1 2009/10/25 01:10:29 kensmith Exp $");
**/
#include <LibConfig.h>
#include <sys/EfiCdefs.h>
#include <stdlib.h>
/*
* Perform a binary search.
*
* The code below is a bit sneaky. After a comparison fails, we
* divide the work in half by moving either left or right. If lim
* is odd, moving left simply involves halving lim: e.g., when lim
* is 5 we look at item 2, so we change lim to 2 so that we will
* look at items 0 & 1. If lim is even, the same applies. If lim
* is odd, moving right again involes halving lim, this time moving
* the base up one item past p: e.g., when lim is 5 we change base
* to item 3 and make lim 2 so that we will look at items 3 and 4.
* If lim is even, however, we have to shrink it by one before
* halving: e.g., when lim is 4, we still looked at item 2, so we
* have to make lim 3, then halve, obtaining 1, so that we will only
* look at item 3.
*/
void *
bsearch(
const void *key,
const void *base0,
size_t nmemb,
size_t size,
int (*compar)(const void *, const void *)
)
{
const char *base = base0;
size_t lim;
int cmp;
const void *p;
for (lim = nmemb; lim != 0; lim >>= 1) {
p = base + (lim >> 1) * size;
cmp = (*compar)(key, p);
if (cmp == 0)
return ((void *)p);
if (cmp > 0) { /* key > p: move right */
base = (char *)p + size;
lim--;
} /* else move left */
}
return (NULL);
}

View File

@@ -0,0 +1,208 @@
/** @file
Implementation of the <stdlib.h> functions responsible for communication with
the environment:
- abort(void)
- atexit(void(*handler)(void))
- exit(int status)
- _Exit(int status)
Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials are licensed and made available under
the terms and conditions of the BSD License that accompanies this distribution.
The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include <Uefi.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/BaseLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/ShellLib.h>
#include <LibConfig.h>
#include <errno.h>
#include <signal.h>
#include <stdlib.h>
#include <MainData.h>
/* ################# Public Functions ################################### */
/** The abort function causes abnormal program termination to occur, unless
the signal SIGABRT is being caught and the signal handler does not return.
Open streams with unwritten buffered data are not flushed, open
streams are not closed, and temporary files are not removed by abort.
**/
void
abort(void)
{
if (!gMD->aborting) {
gMD->aborting = TRUE;
if (gMD->cleanup != NULL) {
gMD->cleanup();
}
}
raise(SIGABRT);
_Exit(EXIT_FAILURE); // In case raise returns.
}
/** The atexit function registers the function pointed to by func, to be
called without arguments at normal program termination.
The implementation shall support the registration of
at least 32 functions.
@return The atexit function returns zero if the registration succeeds,
nonzero if it fails.
**/
int
atexit(void (*handler)(void))
{
int retval = 1;
if((handler != NULL) && (gMD->num_atexit < ATEXIT_MAX)) {
gMD->atexit_handler[gMD->num_atexit++] = handler;
retval = 0;
}
return retval;
}
/** The exit function causes normal program termination to occur. If more than
one call to the exit function is executed by a program,
the behavior is undefined.
First, all functions registered by the atexit function are called, in the
reverse order of their registration. If, during the call to any such function, a
call to the longjmp function is made that would terminate the call to the
registered function, the behavior is undefined.
Next, all open streams with unwritten buffered data are flushed, all open
streams are closed, and all files created by the tmpfile function
are removed.
The status returned to the host environment is determined in the same way
as for the _Exit function.
**/
void
exit(int status)
{
int i = gMD->num_atexit;
// Call all registered atexit functions in reverse order
if( i > 0) {
do {
(gMD->atexit_handler[--i])();
} while( i > 0);
}
if (gMD->cleanup != NULL) {
gMD->cleanup();
}
_Exit(status);
}
typedef
EFI_STATUS
(EFIAPI *ExitFuncPtr)(
IN EFI_HANDLE ImageHandle,
IN EFI_STATUS ExitStatus,
IN UINTN ExitDataSize,
IN CHAR16 *ExitData OPTIONAL
) __noreturn;
/** The _Exit function causes normal program termination to occur and control
to be returned to the host environment.
No functions registered by the atexit function or signal handlers
registered by the signal function are called. Open streams with unwritten
buffered data are not flushed, open streams are not closed, and temporary
files are not removed by abort.
Finally, control is returned to the host environment. If the value of
status is zero, or EXIT_SUCCESS, status is returned unchanged. If the value
of status is EXIT_FAILURE, RETURN_ABORTED is returned.
Otherwise, status is returned unchanged.
**/
void
_Exit(int status)
{
RETURN_STATUS ExitVal = (RETURN_STATUS)status;
ExitFuncPtr ExitFunc;
if( ExitVal == EXIT_FAILURE) {
ExitVal = RETURN_ABORTED;
}
ExitFunc = (ExitFuncPtr)gBS->Exit;
//gBS->Exit(gImageHandle, ExitVal, 0, NULL); /* abort() */
ExitFunc(gImageHandle, ExitVal, 0, NULL); /* abort() */
}
/** If string is a null pointer, the system function determines whether the
host environment has a command processor. If string is not a null pointer,
the system function passes the string pointed to by string to that command
processor to be executed in a manner which the implementation shall
document; this might then cause the program calling system to behave in a
non-conforming manner or to terminate.
@retval EXIT_FAILURE EFIerrno will contain the EFI status code
indicating the cause of failure.
@retval EXIT_SUCCESS EFIerrno will contain the EFI status returned
by the executed command string.
@retval 0 If string is NULL, 0 means a command processor
is not available.
@retval 1 If string is NULL, 1 means a command processor
is available.
**/
int
system(const char *string)
{
EFI_STATUS CmdStat;
EFI_STATUS OpStat;
EFI_HANDLE MyHandle = gImageHandle;
if( string == NULL) {
return 1;
}
(void)AsciiStrToUnicodeStr( string, gMD->UString);
OpStat = ShellExecute( &MyHandle, gMD->UString, FALSE, NULL, &CmdStat);
if(OpStat == RETURN_SUCCESS) {
EFIerrno = CmdStat;
return EXIT_SUCCESS;
}
EFIerrno = OpStat;
return EXIT_FAILURE;
}
/** The getenv function searches an environment list, provided by the host
environment, for a string that matches the string pointed to by name. The
set of environment names and the method for altering the environment list
are determined by the underlying UEFI Shell implementation.
@return The getenv function returns a pointer to a string associated with
the matched list member. The string pointed to shall not be
modified by the program, but may be overwritten by a subsequent
call to the getenv function. If the specified name cannot be
found, a null pointer is returned.
**/
char *getenv(const char *name)
{
const CHAR16 *EfiEnv;
char *retval = NULL;
(void)AsciiStrToUnicodeStr( name, gMD->UString);
EfiEnv = ShellGetEnvironmentVariable(gMD->UString);
if(EfiEnv != NULL) {
retval = UnicodeStrToAsciiStr( EfiEnv, gMD->ASgetenv);
}
return retval;
}

226
StdLib/LibC/StdLib/Malloc.c Normal file
View File

@@ -0,0 +1,226 @@
/** @file
Definitions for memory allocation routines: calloc, malloc, realloc, free.
The order and contiguity of storage allocated by successive calls to the
calloc, malloc, and realloc functions is unspecified. The pointer returned
if the allocation succeeds is suitably aligned so that it may be assigned to
a pointer of any type of object and then used to access such an object or an
array of such objects in the space allocated (until the space is explicitly
freed or reallocated). Each such allocation shall yield a pointer to an
object disjoint from any other object. The pointer returned points to the
start (lowest byte address) of the allocated space. If the space can not be
allocated, a null pointer is returned. If the size of the space requested
is zero, the behavior is implementation-defined; the value returned shall be
either a null pointer or a unique pointer. The value of a pointer that
refers to freed space is indeterminate.
Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
*/
#include <Base.h>
#include <Uefi.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include <LibConfig.h>
#include <assert.h>
#include <stdlib.h>
#include <errno.h>
/** The UEFI functions do not provide a way to determine the size of an
allocated region of memory given just a pointer to the start of that
region. Since this is required for the implementation of realloc,
the memory head structure from Core/Dxe/Mem/Pool.c has been reproduced
here.
NOTE: If the UEFI implementation is changed, the realloc function may cease
to function properly.
**/
#define POOL_HEAD_SIGNATURE SIGNATURE_32('p','h','d','0')
typedef struct {
UINT32 Signature;
UINT32 Size;
EFI_MEMORY_TYPE Type;
UINTN Reserved;
CHAR8 Data[1];
} POOL_HEAD;
/****************************/
/** The malloc function allocates space for an object whose size is specified
by size and whose value is indeterminate.
This implementation uses the UEFI memory allocation boot services to get a
region of memory that is 8-byte aligned and of the specified size. The
region is allocated with type EfiLoaderData.
@param size Size, in bytes, of the region to allocate.
@return NULL is returned if the space could not be allocated and errno
contains the cause. Otherwise, a pointer to an 8-byte aligned
region of the requested size is returned.<BR>
If NULL is returned, errno may contain:
- EINVAL: Requested Size is zero.
- ENOMEM: Memory could not be allocated.
**/
void *
malloc(size_t Size)
{
void *RetVal;
EFI_STATUS Status;
if( Size == 0) {
errno = EINVAL; // Make errno diffenent, just in case of a lingering ENOMEM.
return NULL;
}
Status = gBS->AllocatePool( EfiLoaderData, (UINTN)Size, &RetVal);
if( Status != EFI_SUCCESS) {
RetVal = NULL;
errno = ENOMEM;
}
return RetVal;
}
/** The calloc function allocates space for an array of Num objects, each of
whose size is Size. The space is initialized to all bits zero.
This implementation uses the UEFI memory allocation boot services to get a
region of memory that is 8-byte aligned and of the specified size. The
region is allocated with type EfiLoaderData.
@param Num Number of objects to allocate.
@param Size Size, in bytes, of the objects to allocate space for.
@return NULL is returned if the space could not be allocated and errno
contains the cause. Otherwise, a pointer to an 8-byte aligned
region of the requested size is returned.
**/
void *
calloc(size_t Num, size_t Size)
{
void *RetVal;
size_t NumSize;
NumSize = Num * Size;
if (NumSize == 0) {
return NULL;
}
RetVal = malloc(NumSize);
if( RetVal != NULL) {
(VOID)ZeroMem( RetVal, NumSize);
}
return RetVal;
}
/** The free function causes the space pointed to by Ptr to be deallocated,
that is, made available for further allocation.
If Ptr is a null pointer, no action occurs. Otherwise, if the argument
does not match a pointer earlier returned by the calloc, malloc, or realloc
function, or if the space has been deallocated by a call to free or
realloc, the behavior is undefined.
@param Ptr Pointer to a previously allocated region of memory to be freed.
**/
void
free(void *Ptr)
{
(void) gBS->FreePool (Ptr);
}
/** The realloc function changes the size of the object pointed to by Ptr to
the size specified by NewSize.
The contents of the object are unchanged up to the lesser of the new and
old sizes. If the new size is larger, the value of the newly allocated
portion of the object is indeterminate.
If Ptr is a null pointer, the realloc function behaves like the malloc
function for the specified size.
If Ptr does not match a pointer earlier returned by the calloc, malloc, or
realloc function, or if the space has been deallocated by a call to the free
or realloc function, the behavior is undefined.
If the space cannot be allocated, the object pointed to by Ptr is unchanged.
If NewSize is zero and Ptr is not a null pointer, the object it points to
is freed.
This implementation uses the UEFI memory allocation boot services to get a
region of memory that is 8-byte aligned and of the specified size. The
region is allocated with type EfiLoaderData.
The following combinations of Ptr and NewSize can occur:<BR>
Ptr NewSize<BR>
-------- -------------------<BR>
- NULL 0 Returns NULL;
- NULL > 0 Same as malloc(NewSize)
- invalid X Returns NULL;
- valid NewSize >= OldSize Returns malloc(NewSize) with Oldsize bytes copied from Ptr
- valid NewSize < OldSize Returns new buffer with Oldsize bytes copied from Ptr
- valid 0 Return NULL. Frees Ptr.
@param Ptr Pointer to a previously allocated region of memory to be resized.
@param NewSize Size, in bytes, of the new object to allocate space for.
@return NULL is returned if the space could not be allocated and errno
contains the cause. Otherwise, a pointer to an 8-byte aligned
region of the requested size is returned. If NewSize is zero,
NULL is returned and errno will be unchanged.
**/
void *
realloc(void *Ptr, size_t NewSize)
{
void *RetVal = NULL;
POOL_HEAD *Head;
UINTN OldSize = 0;
UINTN NumCpy;
// Find out the size of the OLD memory region
if( Ptr != NULL) {
Head = BASE_CR (Ptr, POOL_HEAD, Data);
assert(Head != NULL);
if (Head->Signature != POOL_HEAD_SIGNATURE) {
errno = EFAULT;
return NULL;
}
OldSize = Head->Size;
}
// At this point, Ptr is either NULL or a valid pointer to an allocated space
if( NewSize > 0) {
RetVal = malloc(NewSize); // Get the NEW memory region
if( Ptr != NULL) { // If there is an OLD region...
if( RetVal != NULL) { // and the NEW region was successfully allocated
NumCpy = OldSize;
if( OldSize > NewSize) {
NumCpy = NewSize;
}
(VOID)CopyMem( RetVal, Ptr, NumCpy); // Copy old data to the new region.
free( Ptr); // and reclaim the old region.
}
}
}
else {
if( Ptr != NULL) {
free( Ptr); // Reclaim the old region.
}
}
return RetVal;
}

View File

@@ -0,0 +1,398 @@
/** @file
Integer Numeric Conversion Functions.
The atoi, atol, and atoll functions convert the initial portion of the string
pointed to by nptr to int, long int, and long long int representation,
respectively. They are equivalent to:
- atoi: (int)strtol(nptr, (char **)NULL, 10)
- atol: strtol(nptr, (char **)NULL, 10)
- atoll: strtoll(nptr, (char **)NULL, 10)
Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials are licensed and made available under
the terms and conditions of the BSD License that accompanies this distribution.
The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include <Uefi.h>
#include <Library/BaseLib.h>
#include <LibConfig.h>
#include <ctype.h>
#include <errno.h>
#include <limits.h>
#include <stdlib.h>
/** The atoi function converts the initial portion of the string pointed to by
nptr to int representation. Except for the behavior on error, it is
equivalent to:
- (int)strtol(nptr, (char **)NULL, 10)
@return The atoi function returns the converted value.
**/
int
atoi(const char *nptr)
{
int Retval;
BOOLEAN Negative = FALSE;
while(isspace((const unsigned char)*nptr)) ++nptr; // Skip leading spaces
if(*nptr == '+') {
Negative = FALSE;
++nptr;
}
else if(*nptr == '-') {
Negative = TRUE;
++nptr;
}
Retval = (int)AsciiStrDecimalToUintn(nptr);
if(Negative) {
Retval = -Retval;
}
return Retval;
}
/** The atol function converts the initial portion of the string pointed to by
nptr to long int representation. Except for the behavior on error, it is
equivalent to:
- strtol(nptr, (char **)NULL, 10)
@return The atol function returns the converted value.
**/
long int
atol(const char *nptr)
{
long int Retval;
BOOLEAN Negative = FALSE;
while(isspace(*nptr)) ++nptr; // Skip leading spaces
if(*nptr == '+') {
Negative = FALSE;
++nptr;
}
else if(*nptr == '-') {
Negative = TRUE;
++nptr;
}
Retval = (long int)AsciiStrDecimalToUint64(nptr);
if(Negative) {
Retval = -Retval;
}
return Retval;
}
/** The atoll function converts the initial portion of the string pointed to by
nptr to long long int representation. Except for the behavior on error, it
is equivalent to:
- strtoll(nptr, (char **)NULL, 10)
@return The atoll function returns the converted value.
**/
long long int
atoll(const char *nptr)
{
long long int Retval;
BOOLEAN Negative = FALSE;
while(isspace(*nptr)) ++nptr; // Skip leading spaces
if(*nptr == '+') {
Negative = FALSE;
++nptr;
}
else if(*nptr == '-') {
Negative = TRUE;
++nptr;
}
Retval = (long long int)AsciiStrDecimalToUint64(nptr);
if(Negative) {
Retval = -Retval;
}
return Retval;
}
static int
Digit2Val( int c)
{
if(__isHexLetter(c)) { /* If c is one of [A-Fa-f]... */
c = toupper(c) - 7; // Adjust so 'A' is ('9' + 1)
}
return c - '0'; // Value returned is between 0 and 35, inclusive.
}
/** The strtol, strtoll, strtoul, and strtoull functions convert the initial
portion of the string pointed to by nptr to long int, long long int,
unsigned long int, and unsigned long long int representation, respectively.
First, they decompose the input string into three parts: an initial,
possibly empty, sequence of white-space characters (as specified by the
isspace function), a subject sequence resembling an integer represented in
some radix determined by the value of base, and a final string of one or
more unrecognized characters, including the terminating null character of
the input string. Then, they attempt to convert the subject sequence to an
integer, and return the result.
If the value of base is zero, the expected form of the subject sequence is
that of an integer constant, optionally preceded
by a plus or minus sign, but not including an integer suffix. If the value
of base is between 2 and 36 (inclusive), the expected form of the subject
sequence is a sequence of letters and digits representing an integer with
the radix specified by base, optionally preceded by a plus or minus sign,
but not including an integer suffix. The letters from a (or A) through z
(or Z) are ascribed the values 10 through 35; only letters and digits whose
ascribed values are less than that of base are permitted. If the value of
base is 16, the characters 0x or 0X may optionally precede the sequence of
letters and digits, following the sign if present.
The subject sequence is defined as the longest initial subsequence of the
input string, starting with the first non-white-space character, that is of
the expected form. The subject sequence contains no characters if the input
string is empty or consists entirely of white space, or if the first
non-white-space character is other than a sign or a permissible letter or digit.
If the subject sequence has the expected form and the value of base is
zero, the sequence of characters starting with the first digit is
interpreted as an integer constant. If the subject sequence has the
expected form and the value of base is between 2 and 36, it is used as the
base for conversion, ascribing to each letter its value as given above. If
the subject sequence begins with a minus sign, the value resulting from the
conversion is negated (in the return type). A pointer to the final string
is stored in the object pointed to by endptr, provided that endptr is
not a null pointer.
In other than the "C" locale, additional locale-specific subject sequence
forms may be accepted.
If the subject sequence is empty or does not have the expected form, no
conversion is performed; the value of nptr is stored in the object pointed
to by endptr, provided that endptr is not a null pointer.
@return The strtol, strtoll, strtoul, and strtoull functions return the
converted value, if any. If no conversion could be performed, zero
is returned. If the correct value is outside the range of
representable values, LONG_MIN, LONG_MAX, LLONG_MIN, LLONG_MAX,
ULONG_MAX, or ULLONG_MAX is returned (according to the return type
and sign of the value, if any), and the value of the macro ERANGE
is stored in errno.
**/
long
strtol(const char * __restrict nptr, char ** __restrict endptr, int base)
{
long Result = 0;
long Previous;
int temp;
BOOLEAN Negative = FALSE;
if((base < 0) || (base == 1) || (base > 36)) {
*endptr = NULL;
return 0;
}
// Skip leading spaces.
while(isspace(*nptr)) ++nptr;
// Process Subject sequence: optional sign followed by digits.
if(*nptr == '+') {
Negative = FALSE;
++nptr;
}
else if(*nptr == '-') {
Negative = TRUE;
++nptr;
}
if( (base == 16) && (*nptr == '0') && (toupper(nptr[1]) == 'X')) {
nptr += 2;
}
while( isalnum(*nptr) && ((temp = Digit2Val(*nptr)) < base)) {
Previous = Result;
Result = (Result * base) + (long int)temp;
if( Result <= Previous) { // Detect Overflow
if(Negative) {
Result = LONG_MIN;
}
else {
Result = LONG_MAX;
}
Negative = FALSE;
errno = ERANGE;
break;
}
++nptr;
}
if(Negative) {
Result = -Result;
}
// Save pointer to final sequence
if( endptr != NULL) {
*endptr = (char *)nptr;
}
return Result;
}
/** The strtoul function converts the initial portion of the string pointed to
by nptr to unsigned long int representation.
See the description for strtol for more information.
@return The strtoul function returns the converted value, if any. If no
conversion could be performed, zero is returned. If the correct
value is outside the range of representable values, ULONG_MAX is
returned and the value of the macro ERANGE is stored in errno.
**/
unsigned long
strtoul(const char * __restrict nptr, char ** __restrict endptr, int base)
{
unsigned long Result = 0;
unsigned long Previous;
int temp;
if((base < 0) || (base == 1) || (base > 36)) {
*endptr = NULL;
return 0;
}
// Skip leading spaces.
while(isspace(*nptr)) ++nptr;
// Process Subject sequence: optional + sign followed by digits.
if(*nptr == '+') {
++nptr;
}
if( (base == 16) && (*nptr == '0') && (toupper(nptr[1]) == 'X')) {
nptr += 2;
}
while( isalnum(*nptr) && ((temp = Digit2Val(*nptr)) < base)) {
Previous = Result;
Result = (Result * base) + (unsigned long)temp;
if( Result < Previous) { // If we overflowed
Result = ULONG_MAX;
errno = ERANGE;
break;
}
++nptr;
}
// Save pointer to final sequence
if( endptr != NULL) {
*endptr = (char *)nptr;
}
return Result;
}
/** The strtoll function converts the initial portion of the string pointed to
by nptr to long long int representation.
See the description for strtol for more information.
@return The strtoll function returns the converted value, if any. If no
conversion could be performed, zero is returned. If the correct
value is outside the range of representable values, LLONG_MIN or
LLONG_MAX is returned (according to the sign of the value, if any),
and the value of the macro ERANGE is stored in errno.
**/
long long
strtoll(const char * __restrict nptr, char ** __restrict endptr, int base)
{
long long Result = 0;
long long Previous;
int temp;
BOOLEAN Negative = FALSE;
if((base < 0) || (base == 1) || (base > 36)) {
*endptr = NULL;
return 0;
}
// Skip leading spaces.
while(isspace(*nptr)) ++nptr;
// Process Subject sequence: optional sign followed by digits.
if(*nptr == '+') {
Negative = FALSE;
++nptr;
}
else if(*nptr == '-') {
Negative = TRUE;
++nptr;
}
if( (base == 16) && (*nptr == '0') && (toupper(nptr[1]) == 'X')) {
nptr += 2;
}
while( isalnum(*nptr) && ((temp = Digit2Val(*nptr)) < base)) {
Previous = Result;
Result = (Result * base) + (long long int)temp;
if( Result <= Previous) { // Detect Overflow
if(Negative) {
Result = LLONG_MIN;
}
else {
Result = LLONG_MAX;
}
Negative = FALSE;
errno = ERANGE;
break;
}
++nptr;
}
if(Negative) {
Result = -Result;
}
// Save pointer to final sequence
if( endptr != NULL) {
*endptr = (char *)nptr;
}
return Result;
}
/** The strtoull function converts the initial portion of the string pointed to
by nptr to unsigned long long int representation.
See the description for strtol for more information.
@return The strtoull function returns the converted value, if any. If no
conversion could be performed, zero is returned. If the correct
value is outside the range of representable values, ULLONG_MAX is
returned and the value of the macro ERANGE is stored in errno.
**/
unsigned long long
strtoull(const char * __restrict nptr, char ** __restrict endptr, int base)
{
unsigned long long Result = 0;
unsigned long long Previous;
int temp;
if((base < 0) || (base == 1) || (base > 36)) {
*endptr = NULL;
return 0;
}
// Skip leading spaces.
while(isspace(*nptr)) ++nptr;
// Process Subject sequence: optional + sign followed by digits.
if(*nptr == '+') {
++nptr;
}
if( (base == 16) && (*nptr == '0') && (toupper(nptr[1]) == 'X')) {
nptr += 2;
}
while( isalnum(*nptr) && ((temp = Digit2Val(*nptr)) < base)) {
Previous = Result;
Result = (Result * base) + (unsigned long long)temp;
if( Result < Previous) { // If we overflowed
Result = ULLONG_MAX;
errno = ERANGE;
break;
}
++nptr;
}
// Save pointer to final sequence
if( endptr != NULL) {
*endptr = (char *)nptr;
}
return Result;
}

205
StdLib/LibC/StdLib/Qsort.c Normal file
View File

@@ -0,0 +1,205 @@
/** @file
Quick Sort utility function.
This utility makes use of a comparison function to search arrays of
unspecified type. Where an argument declared as size_t nmemb specifies the
length of the array for a function, nmemb can have the value zero on a call
to that function; the comparison function is not called, a search finds no
matching element. Pointer arguments on such a call shall still have valid
values.
The implementation shall ensure that both arguments of the comparison
function are pointers to elements of the array.
The comparison function shall not alter the contents of the array. The
implementation may reorder elements of the array between calls to the
comparison function, but shall not alter the contents of any individual
element.
When the same objects (consisting of size bytes, irrespective of their
current positions in the array) are passed more than once to the comparison
function, the results shall be consistent with one another. That is, they
define a total ordering on the array.
A sequence point occurs immediately before and immediately after each call to
the comparison function, and also between any call to the comparison function
and any movement of the objects passed as arguments to that call.
Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 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.
("$FreeBSD: src/lib/libc/stdlib/qsort.c,v 1.15.2.1.2.1 2009/10/25 01:10:29 kensmith Exp $");
*/
#include <LibConfig.h>
#include <stdlib.h>
typedef int cmp_t(const void *, const void *);
static __inline char *med3(char *, char *, char *, cmp_t *);
static __inline void swapfunc(char *, char *, size_t, int);
/*
* Qsort routine from Bentley & McIlroy's "Engineering a Sort Function".
*/
#define swapcode(TYPE, parmi, parmj, n) { \
size_t i = (n) / sizeof (TYPE); \
TYPE *pi = (TYPE *) (parmi); \
TYPE *pj = (TYPE *) (parmj); \
do { \
TYPE t = *pi; \
*pi++ = *pj; \
*pj++ = t; \
} while (--i > 0); \
}
#define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \
es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1;
static __inline void
swapfunc(char *a, char *b, size_t n, int swaptype)
{
if(swaptype <= 1)
swapcode(long, a, b, n)
else
swapcode(char, a, b, n)
}
#define swap(a, b) \
if (swaptype == 0) { \
long t = *(long *)(a); \
*(long *)(a) = *(long *)(b); \
*(long *)(b) = t; \
} else \
swapfunc(a, b, es, swaptype)
#define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype)
static __inline char *
med3(char *a, char *b, char *c, cmp_t *cmp )
{
return cmp(a, b) < 0 ?
(cmp(b, c) < 0 ? b : (cmp(a, c) < 0 ? c : a ))
:(cmp(b, c) > 0 ? b : (cmp(a, c) < 0 ? a : c ));
}
/* The qsort function sorts an array of nmemb objects, the initial element of
which is pointed to by base. The size of each object is specified by size.
The contents of the array are sorted into ascending order according to a
comparison function pointed to by compar, which is called with two
arguments that point to the objects being compared. The function shall
return an integer less than, equal to, or greater than zero if the first
argument is considered to be respectively less than, equal to, or greater
than the second.
If two elements compare as equal, their order in the resulting sorted array
is unspecified.
*/
void
qsort(void *a, size_t n, size_t es, cmp_t *cmp)
{
char *pa, *pb, *pc, *pd, *pl, *pm, *pn;
size_t d, r;
int cmp_result;
int swaptype, swap_cnt;
loop: SWAPINIT(a, es);
swap_cnt = 0;
if (n < 7) {
for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es)
for (pl = pm;
pl > (char *)a && cmp(pl - es, pl) > 0;
pl -= es)
swap(pl, pl - es);
return;
}
pm = (char *)a + (n / 2) * es;
if (n > 7) {
pl = a;
pn = (char *)a + (n - 1) * es;
if (n > 40) {
d = (n / 8) * es;
pl = med3(pl, pl + d, pl + 2 * d, cmp);
pm = med3(pm - d, pm, pm + d, cmp);
pn = med3(pn - 2 * d, pn - d, pn, cmp);
}
pm = med3(pl, pm, pn, cmp);
}
swap(a, pm);
pa = pb = (char *)a + es;
pc = pd = (char *)a + (n - 1) * es;
for (;;) {
while (pb <= pc && (cmp_result = cmp(pb, a)) <= 0) {
if (cmp_result == 0) {
swap_cnt = 1;
swap(pa, pb);
pa += es;
}
pb += es;
}
while (pb <= pc && (cmp_result = cmp(pc, a)) >= 0) {
if (cmp_result == 0) {
swap_cnt = 1;
swap(pc, pd);
pd -= es;
}
pc -= es;
}
if (pb > pc)
break;
swap(pb, pc);
swap_cnt = 1;
pb += es;
pc -= es;
}
if (swap_cnt == 0) { /* Switch to insertion sort */
for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es)
for (pl = pm;
pl > (char *)a && cmp(pl - es, pl) > 0;
pl -= es)
swap(pl, pl - es);
return;
}
pn = (char *)a + n * es;
r = MIN(pa - (char *)a, pb - pa);
vecswap(a, pb - r, r);
r = MIN((size_t)(pd - pc), ((size_t)(pn - pd)) - es);
vecswap(pb, pn - r, r);
if ((size_t)(r = pb - pa) > es)
qsort(a, r / es, es, cmp);
if ((size_t)(r = pd - pc) > es) {
/* Iterate rather than recurse to save stack space */
a = pn - r;
n = r / es;
goto loop;
}
/* qsort(pn - r, r / es, es, cmp);*/
}

67
StdLib/LibC/StdLib/Rand.c Normal file
View File

@@ -0,0 +1,67 @@
/*-
* Portions Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 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.
*
*/
//__FBSDID("$FreeBSD: src/lib/libc/stdlib/rand.c,v 1.17.2.1.2.1 2009/10/25 01:10:29 kensmith Exp $");
#include <LibConfig.h>
#include <stdlib.h>
static UINT32 next = 1;
/** Compute a pseudo-random number.
*
* Compute x = (7^5 * x) mod (2^31 - 1)
* without overflowing 31 bits:
* (2^31 - 1) = 127773 * (7^5) + 2836
* From "Random number generators: good ones are hard to find",
* Park and Miller, Communications of the ACM, vol. 31, no. 10,
* October 1988, p. 1195.
**/
int
rand()
{
INT32 hi, lo, x;
/* Can't be initialized with 0, so use another value. */
if (next == 0)
next = 123459876;
hi = next / 127773;
lo = next % 127773;
x = 16807 * lo - 2836 * hi;
if (x < 0)
x += 0x7fffffff;
return ((next = x) % ((UINT32)RAND_MAX + 1));
}
void
srand(unsigned int seed)
{
next = (UINT32)seed;
}

View File

@@ -0,0 +1,67 @@
## @file
# Standard C library: StdLib implementations.
#
# Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
#
# This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
# which accompanies this distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php.
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
#
##
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = LibStdLib
FILE_GUID = f8a312f8-bccc-479f-b49b-ce129568b06a
MODULE_TYPE = UEFI_APPLICATION
VERSION_STRING = 1.0
LIBRARY_CLASS = LibStdLib
#
# VALID_ARCHITECTURES = IA32 X64 IPF
#
[Sources]
Bsearch.c
Environs.c
Malloc.c
NumericInt.c
Qsort.c
Rand.c
strtoimax.c
strtoumax.c
Xabs.c
Xdiv.c
[Packages]
StdLib/StdLib.dec
StdLibPrivateInternalFiles/DoNotUse.dec
MdePkg/MdePkg.dec
ShellPkg/ShellPkg.dec
[LibraryClasses]
UefiBootServicesTableLib
DebugLib
BaseLib
BaseMemoryLib
MemoryAllocationLib
ShellLib
LibC
LibCType
LibSignal
################################################################
#
# The Build Options, below, are only used when building the C library.
# DO NOT use them when building your application!
# Nasty things could happen if you do.
#
# /Oi- is required for Microsoft VC++ to allow "intrinsic" functions to be
# defined in this library.
#
[BuildOptions]
MSFT:*_*_*_CC_FLAGS = /Oi-

36
StdLib/LibC/StdLib/Xabs.c Normal file
View File

@@ -0,0 +1,36 @@
/** @file
The abs, labs, and llabs functions compute the absolute value of an integer j.
If the result cannot be represented, the behavior is undefined.
The abs, labs, and llabs, functions return the absolute value of their
parameter.
Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials are licensed and made available under
the terms and conditions of the BSD License that accompanies this distribution.
The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include <LibConfig.h>
#include <sys/EfiCdefs.h>
int
abs(int j)
{
return(j < 0 ? -j : j);
}
long
labs(long j)
{
return(j < 0 ? -j : j);
}
long long
llabs(long long j)
{
return (j < 0 ? -j : j);
}

76
StdLib/LibC/StdLib/Xdiv.c Normal file
View File

@@ -0,0 +1,76 @@
/** @file
The div, ldiv, and lldiv, functions compute numer / denom and
numer % denom in a single operation.
The div, ldiv, and lldiv functions return a structure of type div_t, ldiv_t,
and lldiv_t, respectively, comprising both the quotient and the remainder.
The structures shall contain (in either order) the members quot
(the quotient) and rem (the remainder), each of which has the same type as
the arguments numer and denom. If either part of the result cannot be
represented, the behavior is undefined.
Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials are licensed and made available under
the terms and conditions of the BSD License that accompanies this distribution.
The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include <LibConfig.h>
#include <sys/EfiCdefs.h>
#include <Library/BaseLib.h>
#include <stdlib.h> /* div_t, ldiv_t, lldiv_t */
/* DivS64x64Remainder will write the remainder as a 64-bit value, so we store
it first into bigrem and then into r.rem. This avoids writing the remainder
beyond the end of the div_t structure.
*/
div_t
div(int num, int denom)
{
div_t r;
INT64 bigrem;
r.quot = (int)DivS64x64Remainder( (INT64)num, (INT64)denom, &bigrem);
r.rem = (int)bigrem;
return (r);
}
/* DivS64x64Remainder will write the remainder as a 64-bit value, so we store
it first into bigrem and then into r.rem. This avoids writing the remainder
beyond the end of the div_t structure.
*/
ldiv_t
ldiv(long num, long denom)
{
ldiv_t r;
INT64 bigrem;
r.quot = (long)DivS64x64Remainder( (INT64)num, (INT64)denom, &bigrem);
r.rem = (long)bigrem;
return (r);
}
/* DivS64x64Remainder will write the remainder as a 64-bit value, so we store
it first into bigrem and then into r.rem. This avoids writing the remainder
beyond the end of the div_t structure if r.rem is narrower than 64-bits.
Even though most implementations make long long 64 bits wide, we still go
through bigrem, just-in-case.
*/
lldiv_t
lldiv(long long num, long long denom)
{
lldiv_t r;
INT64 bigrem;
r.quot = (long long)DivS64x64Remainder( (INT64)num, (INT64)denom, &bigrem);
r.rem = (long long)bigrem;
return (r);
}

View File

@@ -0,0 +1,166 @@
/* $NetBSD: strtoimax.c,v 1.4 2005/11/29 03:12:00 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. 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 <LibConfig.h>
#include <sys/EfiCdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
#if 0
static char sccsid[] = "from: @(#)strtoq.c 8.1 (Berkeley) 6/4/93";
#else
__RCSID("$NetBSD: strtoimax.c,v 1.4 2005/11/29 03:12:00 christos Exp $");
#endif
#endif /* LIBC_SCCS and not lint */
#include "namespace.h"
#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <inttypes.h>
#include <stddef.h>
#ifdef __weak_alias
__weak_alias(strtoimax, _strtoimax)
#endif
/*
* Convert a string to an intmax_t.
*
* Ignores `locale' stuff. Assumes that the upper and lower case
* alphabets and digits are each contiguous.
*/
intmax_t
_strtoimax(const char *nptr, char **endptr, int base)
{
const char *s;
intmax_t acc, cutoff;
int c;
int neg, any, cutlim;
_DIAGASSERT(nptr != NULL);
/* endptr may be NULL */
#ifdef __GNUC__
/* This outrageous construct just to shut up a GCC warning. */
(void) &acc; (void) &cutoff;
#endif
/*
* 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.
*/
s = nptr;
do {
c = (unsigned char) *s++;
} while (isspace(c));
if (c == '-') {
neg = 1;
c = *s++;
} else {
neg = 0;
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 intmax_t is
* [-9223372036854775808..9223372036854775807] and the input base
* is 10, cutoff will be set to 922337203685477580 and cutlim to
* either 7 (neg==0) or 8 (neg==1), meaning that if we have
* accumulated a value > 922337203685477580, 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 ? INTMAX_MIN : INTMAX_MAX;
cutlim = (int)(cutoff % base);
cutoff /= base;
if (neg) {
if (cutlim > 0) {
cutlim -= base;
cutoff += 1;
}
cutlim = -cutlim;
}
for (acc = 0, any = 0;; c = (unsigned char) *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)
continue;
if (neg) {
if (acc < cutoff || (acc == cutoff && c > cutlim)) {
any = -1;
acc = INTMAX_MIN;
errno = ERANGE;
} else {
any = 1;
acc *= base;
acc -= c;
}
} else {
if (acc > cutoff || (acc == cutoff && c > cutlim)) {
any = -1;
acc = INTMAX_MAX;
errno = ERANGE;
} else {
any = 1;
acc *= base;
acc += c;
}
}
}
if (endptr != 0)
*endptr = (char *)(any ? s - 1 : nptr);
//*endptr = __UNCONST(any ? s - 1 : nptr);
return (acc);
}

View File

@@ -0,0 +1,139 @@
/* $NetBSD: strtoumax.c,v 1.1 2006/04/22 15:33:33 thorpej Exp $ */
/*
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. 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 <LibConfig.h>
#include <sys/EfiCdefs.h>
#if !defined(_KERNEL) && !defined(_STANDALONE)
#if defined(LIBC_SCCS) && !defined(lint)
#if 0
static char sccsid[] = "from: @(#)strtoul.c 8.1 (Berkeley) 6/4/93";
#else
__RCSID("$NetBSD: strtoumax.c,v 1.1 2006/04/22 15:33:33 thorpej Exp $");
#endif
#endif /* LIBC_SCCS and not lint */
#include "namespace.h"
#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <inttypes.h>
#include <stddef.h>
#ifdef __weak_alias
__weak_alias(strtoumax, _strtoumax)
#endif
#else /* !_KERNEL && !_STANDALONE */
#include <sys/param.h>
#include <lib/libkern/libkern.h>
#endif /* !_KERNEL && !_STANDALONE */
/*
* Convert a string to an uintmax_t.
*
* Ignores `locale' stuff. Assumes that the upper and lower case
* alphabets and digits are each contiguous.
*/
uintmax_t
strtoumax(const char *nptr, char **endptr, int base)
{
const char *s;
uintmax_t acc, cutoff;
int c;
int neg, any, cutlim;
_DIAGASSERT(nptr != NULL);
/* endptr may be NULL */
/*
* See strtol for comments as to the logic used.
*/
s = nptr;
do {
c = (unsigned char) *s++;
} while (isspace(c));
if (c == '-') {
neg = 1;
c = *s++;
} else {
neg = 0;
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 = UINTMAX_MAX / (uintmax_t)base;
cutlim = (int)(UINTMAX_MAX % (uintmax_t)base);
for (acc = 0, any = 0;; c = (unsigned char) *s++) {
if (isdigit(c))
c -= '0';
else if (isalpha(c)) {
#if defined(_KERNEL) || defined(_STANDALONE)
c = toupper(c) - 'A' + 10;
#else
c -= isupper(c) ? 'A' - 10 : 'a' - 10;
#endif
} else
break;
if (c >= base)
break;
if (any < 0)
continue;
if (acc > cutoff || (acc == cutoff && c > cutlim)) {
#if defined(_KERNEL) || defined(_STANDALONE)
if (endptr)
*endptr = __UNCONST(nptr);
return UINTMAX_MAX;
#else
any = -1;
acc = UINTMAX_MAX;
errno = ERANGE;
#endif
} else {
any = 1;
acc *= (uintmax_t)base;
acc += c;
}
}
if (neg && any > 0)
acc = (uintmax_t)(-((intmax_t)acc));
if (endptr != 0)
*endptr = __UNCONST(any ? s - 1 : nptr);
return (acc);
}