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:
105
StdLib/LibC/StdLib/Bsearch.c
Normal file
105
StdLib/LibC/StdLib/Bsearch.c
Normal 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);
|
||||
}
|
208
StdLib/LibC/StdLib/Environs.c
Normal file
208
StdLib/LibC/StdLib/Environs.c
Normal 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
226
StdLib/LibC/StdLib/Malloc.c
Normal 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;
|
||||
}
|
398
StdLib/LibC/StdLib/NumericInt.c
Normal file
398
StdLib/LibC/StdLib/NumericInt.c
Normal 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
205
StdLib/LibC/StdLib/Qsort.c
Normal 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
67
StdLib/LibC/StdLib/Rand.c
Normal 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;
|
||||
}
|
67
StdLib/LibC/StdLib/StdLib.inf
Normal file
67
StdLib/LibC/StdLib/StdLib.inf
Normal 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
36
StdLib/LibC/StdLib/Xabs.c
Normal 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
76
StdLib/LibC/StdLib/Xdiv.c
Normal 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);
|
||||
}
|
166
StdLib/LibC/StdLib/strtoimax.c
Normal file
166
StdLib/LibC/StdLib/strtoimax.c
Normal 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);
|
||||
}
|
139
StdLib/LibC/StdLib/strtoumax.c
Normal file
139
StdLib/LibC/StdLib/strtoumax.c
Normal 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);
|
||||
}
|
Reference in New Issue
Block a user