mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-12-07 13:45:03 -05:00
libc: Add an implementation of strtol/strtoul and export it via plugins
These were lifted from the lua plugin. sdl, doom, puzzles updated to use the exported version todo: lua, maybe? also: convert uses of atoi [back] to strtol Change-Id: I5a1ebbe8d8c99349e594ab9bbbce474e7645b4e9
This commit is contained in:
parent
32edbd430d
commit
481cc70fe0
13 changed files with 103 additions and 100 deletions
|
|
@ -58,6 +58,8 @@ void exit(int status);
|
|||
#endif
|
||||
|
||||
int atoi (const char *str);
|
||||
unsigned long int strtoul(const char *ptr, char **endptr, int base);
|
||||
long int strtol(const char *ptr, char **endptr, int base);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
|||
29
firmware/libc/strtol.c
Normal file
29
firmware/libc/strtol.c
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <ctype.h>
|
||||
#include <gcc_extensions.h>
|
||||
|
||||
#define ABS_LONG_MIN LONG_MAX
|
||||
long int strtol(const char *nptr, char **endptr, int base)
|
||||
{
|
||||
int neg=0;
|
||||
unsigned long int v;
|
||||
const char*orig=nptr;
|
||||
|
||||
while(UNLIKELY(isspace(*nptr))) nptr++;
|
||||
|
||||
if (*nptr == '-' && isalnum(nptr[1])) { neg=-1; ++nptr; }
|
||||
v=strtoul(nptr,endptr,base);
|
||||
if (endptr && *endptr==nptr) *endptr=(char *)orig;
|
||||
if (UNLIKELY(v>=ABS_LONG_MIN)) {
|
||||
if (v==ABS_LONG_MIN && neg) {
|
||||
errno=0;
|
||||
return v;
|
||||
}
|
||||
errno=ERANGE;
|
||||
return (neg?LONG_MIN:LONG_MAX);
|
||||
}
|
||||
return (neg?-v:v);
|
||||
}
|
||||
|
||||
57
firmware/libc/strtoul.c
Normal file
57
firmware/libc/strtoul.c
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
#include <gcc_extensions.h>
|
||||
|
||||
unsigned long int strtoul(const char *ptr, char **endptr, int base)
|
||||
{
|
||||
int neg = 0, overflow = 0;
|
||||
unsigned long int v=0;
|
||||
const char* orig;
|
||||
const char* nptr=ptr;
|
||||
|
||||
while(UNLIKELY(isspace(*nptr))) ++nptr;
|
||||
|
||||
if (*nptr == '-') { neg=1; nptr++; }
|
||||
else if (*nptr == '+') ++nptr;
|
||||
orig=nptr;
|
||||
if (base==16 && nptr[0]=='0') goto skip0x;
|
||||
if (base) {
|
||||
register unsigned int b=base-2;
|
||||
if (UNLIKELY(b>34)) { errno=EINVAL; return 0; }
|
||||
} else {
|
||||
if (*nptr=='0') {
|
||||
base=8;
|
||||
skip0x:
|
||||
if ((nptr[1]=='x'||nptr[1]=='X') && isxdigit(nptr[2])) {
|
||||
nptr+=2;
|
||||
base=16;
|
||||
}
|
||||
} else
|
||||
base=10;
|
||||
}
|
||||
while(LIKELY(*nptr)) {
|
||||
register unsigned char c=*nptr;
|
||||
c=(c>='a'?c-'a'+10:c>='A'?c-'A'+10:c<='9'?c-'0':0xff);
|
||||
if (UNLIKELY(c>=base)) break; /* out of base */
|
||||
{
|
||||
register unsigned long x=(v&0xff)*base+c;
|
||||
register unsigned long w=(v>>8)*base+(x>>8);
|
||||
if (w>(ULONG_MAX>>8)) overflow=1;
|
||||
v=(w<<8)+(x&0xff);
|
||||
}
|
||||
++nptr;
|
||||
}
|
||||
if (UNLIKELY(nptr==orig)) { /* no conversion done */
|
||||
nptr=ptr;
|
||||
errno=EINVAL;
|
||||
v=0;
|
||||
}
|
||||
if (endptr) *endptr=(char *)nptr;
|
||||
if (overflow) {
|
||||
errno=ERANGE;
|
||||
return ULONG_MAX;
|
||||
}
|
||||
return (neg?-v:v);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue