* Match mtx and Padclamp.c * Match the rest of GX * Import TRK 2.6 * Import MSL headers and files * Merge some MSL headers into ours
199 lines
4 KiB
C
199 lines
4 KiB
C
#include "PowerPC_EABI_Support/Msl/MSL_C/MSL_Common/strtoul.h"
|
|
#include "PowerPC_EABI_Support/Msl/MSL_C/MSL_Common/ctype.h"
|
|
#include "PowerPC_EABI_Support/Msl/MSL_C/MSL_Common/errno.h"
|
|
#include "PowerPC_EABI_Support/Msl/MSL_C/MSL_Common/limits.h"
|
|
#include "PowerPC_EABI_Support/Msl/MSL_C/MSL_Common/scanf.h"
|
|
|
|
enum scan_states {
|
|
start = 0x01,
|
|
check_for_zero = 0x02,
|
|
leading_zero = 0x04,
|
|
need_digit = 0x08,
|
|
digit_loop = 0x10,
|
|
finished = 0x20,
|
|
failure = 0x40
|
|
};
|
|
|
|
#define final_state(scan_state) (scan_state & (finished | failure))
|
|
#define success(scan_state) \
|
|
(scan_state & (leading_zero | digit_loop | finished))
|
|
#define fetch() (count++, (*ReadProc)(ReadProcArg, 0, __GetAChar))
|
|
#define unfetch(c) (*ReadProc)(ReadProcArg, c, __UngetAChar)
|
|
|
|
unsigned long __strtoul(int base, int max_width,
|
|
int (*ReadProc)(void*, int, int), void* ReadProcArg,
|
|
int* chars_scanned, int* negative, int* overflow)
|
|
{
|
|
int scan_state = start;
|
|
int count = 0;
|
|
unsigned long value = 0;
|
|
unsigned long value_max = 0;
|
|
int c;
|
|
|
|
*negative = *overflow = 0;
|
|
|
|
if (base < 0 || base == 1 || base > 36 || max_width < 1) {
|
|
scan_state = failure;
|
|
} else {
|
|
c = fetch();
|
|
}
|
|
|
|
if (base != 0)
|
|
value_max = ULONG_MAX / base;
|
|
|
|
while (count <= max_width && c != -1 && !final_state(scan_state)) {
|
|
switch (scan_state) {
|
|
case start:
|
|
if (isspace(c)) {
|
|
c = fetch();
|
|
break;
|
|
}
|
|
|
|
if (c == '+') {
|
|
c = fetch();
|
|
} else if (c == '-') {
|
|
c = fetch();
|
|
*negative = 1;
|
|
}
|
|
|
|
scan_state = check_for_zero;
|
|
break;
|
|
|
|
case check_for_zero:
|
|
if (base == 0 || base == 16) {
|
|
if (c == '0') {
|
|
scan_state = leading_zero;
|
|
c = fetch();
|
|
break;
|
|
}
|
|
}
|
|
|
|
scan_state = need_digit;
|
|
break;
|
|
|
|
case 4:
|
|
if (c == 'X' || c == 'x') {
|
|
base = 16;
|
|
scan_state = need_digit;
|
|
c = fetch();
|
|
break;
|
|
}
|
|
|
|
if (base == 0)
|
|
base = 8;
|
|
|
|
scan_state = digit_loop;
|
|
break;
|
|
|
|
case need_digit:
|
|
case digit_loop:
|
|
if (base == 0)
|
|
base = 10;
|
|
|
|
if (!value_max) {
|
|
value_max = ULONG_MAX / base;
|
|
}
|
|
|
|
if (isdigit(c)) {
|
|
if ((c -= '0') >= base) {
|
|
if (scan_state == digit_loop)
|
|
scan_state = finished;
|
|
else
|
|
scan_state = failure;
|
|
|
|
c += '0';
|
|
break;
|
|
}
|
|
} else if (!isalpha(c) || (toupper(c) - 'A' + 10) >= base) {
|
|
if (scan_state == digit_loop)
|
|
scan_state = finished;
|
|
else
|
|
scan_state = failure;
|
|
|
|
break;
|
|
} else {
|
|
c = toupper(c) - 'A' + 10;
|
|
}
|
|
|
|
if (value > value_max)
|
|
*overflow = 1;
|
|
|
|
value *= base;
|
|
|
|
if (c > (ULONG_MAX - value))
|
|
*overflow = 1;
|
|
|
|
value += c;
|
|
scan_state = digit_loop;
|
|
c = fetch();
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!success(scan_state)) {
|
|
value = 0;
|
|
count = 0;
|
|
} else {
|
|
count--;
|
|
}
|
|
|
|
*chars_scanned = count;
|
|
|
|
unfetch(c);
|
|
|
|
return value;
|
|
}
|
|
|
|
unsigned long strtoul(const char* str, char** end, int base)
|
|
{
|
|
unsigned long value;
|
|
int count, negative, overflow;
|
|
|
|
__InStrCtrl isc;
|
|
isc.NextChar = (char*)str;
|
|
isc.NullCharDetected = 0;
|
|
|
|
value = __strtoul(base, 0x7FFFFFFF, &__StringRead, (void*)&isc, &count,
|
|
&negative, &overflow);
|
|
|
|
if (end) {
|
|
*end = (char*)str + count;
|
|
}
|
|
|
|
if (overflow) {
|
|
value = ULONG_MAX;
|
|
errno = 0x22;
|
|
} else if (negative) {
|
|
value = -value;
|
|
}
|
|
|
|
return value;
|
|
}
|
|
|
|
long strtol(const char* str, char** end, int base)
|
|
{
|
|
unsigned long uvalue;
|
|
long svalue;
|
|
int count, negative, overflow;
|
|
|
|
__InStrCtrl isc;
|
|
isc.NextChar = (char*)str;
|
|
isc.NullCharDetected = 0;
|
|
|
|
uvalue = __strtoul(base, 0x7FFFFFFF, &__StringRead, (void*)&isc, &count,
|
|
&negative, &overflow);
|
|
|
|
if (end) {
|
|
*end = (char*)str + count;
|
|
}
|
|
|
|
if (overflow || (!negative && uvalue > LONG_MAX)
|
|
|| (negative && uvalue > -LONG_MIN)) {
|
|
svalue = (negative ? -LONG_MIN : LONG_MAX);
|
|
errno = ERANGE;
|
|
} else {
|
|
svalue = (negative ? (long)-uvalue : (long)uvalue);
|
|
}
|
|
|
|
return svalue;
|
|
}
|