audk/MdePkg/Library/BaseFdtLib/LibFdtWrapper.c
Benny Lin 5d586606c7 MdePkg: Support FDT library.
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4392
Add FDT support in EDK2 by submodule 3rd party libfdt
(https://github.com/devicetree-org/pylibfdt/tree/main/libfdt)
and refer to LibcLib implementation by Pedro.

Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Zhiguang Liu <zhiguang.liu@intel.com>
Signed-off-by: Benny Lin <benny.lin@intel.com>
Acked-by: Pedro Falcato <pedro.falcato@gmail.com>
Reviewed-by: Michael D Kinney <michael.d.kinney@intel.com>
2023-05-05 03:45:21 +00:00

174 lines
3.2 KiB
C

/** @file
ISO C implementations of strchr, strrchr and strtoul.
Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2023 Pedro Falcato All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include <Base.h>
#define ULONG_MAX 0xFFFFFFFF /* Maximum unsigned long value */
// Very quick notes:
// We only go through the string once for both functions
// They are minimal implementations (not speed optimized) of ISO C semantics
// strchr and strrchr also include the null terminator as part of the string
// so the code gets a bit clunky to handle that case specifically.
char *
strchr (
const char *Str,
int Char
)
{
char *S;
S = (char *)Str;
for ( ; ; S++) {
if (*S == Char) {
return S;
}
if (*S == '\0') {
return NULL;
}
}
}
char *
strrchr (
const char *Str,
int Char
)
{
char *S, *last;
S = (char *)Str;
last = NULL;
for ( ; ; S++) {
if (*S == Char) {
last = S;
}
if (*S == '\0') {
return last;
}
}
}
STATIC
int
__isspace (
int ch
)
{
// basic ASCII ctype.h:isspace(). Not efficient
return ch == '\r' || ch == '\n' || ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f';
}
unsigned long
strtoul (
const char *Nptr,
char **EndPtr,
int Base
)
{
BOOLEAN Negate;
BOOLEAN Overflow;
unsigned long Val;
Negate = FALSE;
Overflow = FALSE;
Val = 0;
// Reject bad numeric bases
if ((Base < 0) || (Base == 1) || (Base > 36)) {
return 0;
}
// Skip whitespace
while (__isspace (*Nptr)) {
Nptr++;
}
// Check for + or - prefixes
if (*Nptr == '-') {
Negate = TRUE;
Nptr++;
} else if (*Nptr == '+') {
Nptr++;
}
// Consume the start, autodetecting base if needed
if ((Nptr[0] == '0') && ((Nptr[1] == 'x') || (Nptr[1] == 'X')) && ((Base == 0) || (Base == 16))) {
// Hex
Nptr += 2;
Base = 16;
} else if ((Nptr[0] == '0') && ((Nptr[1] == 'b') || (Nptr[1] == 'B')) && ((Base == 0) || (Base == 2))) {
// Binary (standard pending C23)
Nptr += 2;
Base = 2;
} else if ((Nptr[0] == '0') && ((Base == 0) || (Base == 8))) {
// Octal
Nptr++;
Base = 8;
} else {
if (Base == 0) {
// Assume decimal
Base = 10;
}
}
while (TRUE) {
int Digit;
char C;
unsigned long NewVal;
C = *Nptr;
Digit = -1;
if ((C >= '0') && (C <= '9')) {
Digit = C - '0';
} else if ((C >= 'a') && (C <= 'z')) {
Digit = C - 'a' + 10;
} else if ((C >= 'A') && (C <= 'Z')) {
Digit = C - 'A' + 10;
}
if ((Digit == -1) || (Digit >= Base)) {
// Note that this case also handles the \0
if (EndPtr) {
*EndPtr = (char *)Nptr;
}
break;
}
NewVal = Val * Base + Digit;
if (NewVal < Val) {
// Overflow
Overflow = TRUE;
}
Val = NewVal;
Nptr++;
}
if (Negate) {
Val = -Val;
}
if (Overflow) {
Val = ULONG_MAX;
}
// TODO: We're lacking errno here.
return Val;
}