diff --git a/apps/plugin.c b/apps/plugin.c index 0f7074f32d..04e664674a 100644 --- a/apps/plugin.c +++ b/apps/plugin.c @@ -571,6 +571,8 @@ static const struct plugin_api rockbox_api = { _ctype_, #endif atoi, + strtol, + strtoul, strchr, strcat, strlcat, diff --git a/apps/plugin.h b/apps/plugin.h index 8c5d4599f2..98b4e3e70c 100644 --- a/apps/plugin.h +++ b/apps/plugin.h @@ -658,6 +658,8 @@ struct plugin_api { const unsigned char *_rbctype_; #endif int (*atoi)(const char *str); + long int (*strtol)(const char *ptr, char **endptr, int base); + unsigned long int (*strtoul)(const char *ptr, char **endptr, int base); char *(*strchr)(const char *s, int c); char *(*strcat)(char *s1, const char *s2); size_t (*strlcat)(char *dst, const char *src, size_t length); diff --git a/apps/plugins/doom/d_deh.c b/apps/plugins/doom/d_deh.c index 822555105e..92ea91b6ae 100644 --- a/apps/plugins/doom/d_deh.c +++ b/apps/plugins/doom/d_deh.c @@ -2882,7 +2882,7 @@ boolean deh_GetData(char *s, char *k, uint_64_t *l, char **strval, int fpout) okrc = FALSE; } // we've incremented t - val = atoi(t);//strtol(t,NULL,0); // killough 8/9/98: allow hex or octal input + val = strtol(t,NULL,0); // killough 8/9/98: allow hex or octal input } // go put the results in the passed pointers diff --git a/apps/plugins/doom/rockmacros.h b/apps/plugins/doom/rockmacros.h index 3276aa1539..c749382952 100644 --- a/apps/plugins/doom/rockmacros.h +++ b/apps/plugins/doom/rockmacros.h @@ -87,6 +87,7 @@ int my_close(int id); #define srand(a) rb->srand((a)) #define rand() rb->rand() #define atoi(a) rb->atoi((a)) +#define strtol(a,b,c) rb->strtol((a),(b),(c)) #define strcat(a,b) rb->strcat((a),(b)) #define snprintf rb->snprintf diff --git a/apps/plugins/lua/rocklib_aux.pl b/apps/plugins/lua/rocklib_aux.pl index f53fc7bd61..85beb82237 100755 --- a/apps/plugins/lua/rocklib_aux.pl +++ b/apps/plugins/lua/rocklib_aux.pl @@ -51,6 +51,8 @@ my @ported_functions; # you want to manually port them to Lua. The format is a standard Perl regular # expression. my @forbidden_functions = ('^atoi$', + '^strtol$', + '^strtoul$', '^open$', '^open_utf8$', '^close$', diff --git a/apps/plugins/puzzles/rbcompat.h b/apps/plugins/puzzles/rbcompat.h index f37ac8068e..c438a6e110 100644 --- a/apps/plugins/puzzles/rbcompat.h +++ b/apps/plugins/puzzles/rbcompat.h @@ -22,7 +22,6 @@ float floor_wrapper(float n); float atan_wrapper(float x); float atan2_wrapper(float y, float x); float sqrt_wrapper(float x); -long strtol_wrapper(const char *nptr, char **endptr, int base); int64_t strtoq_wrapper(const char *nptr, char **endptr, int base); uint64_t strtouq_wrapper(const char *nptr, char **endptr, int base); float pow_wrapper(float x, float y); @@ -66,7 +65,7 @@ double acos_wrapper(double x); #define strcmp rb->strcmp #define strcpy rb->strcpy #define strlen rb->strlen -#define strtol strtol_wrapper +#define strtol rb->strtol #define strtoq strtoq_wrapper #define strtouq strtouq_wrapper #define vsprintf vsprintf_wrapper diff --git a/apps/plugins/puzzles/rbwrappers.c b/apps/plugins/puzzles/rbwrappers.c index ed1aa06f59..14641dd084 100644 --- a/apps/plugins/puzzles/rbwrappers.c +++ b/apps/plugins/puzzles/rbwrappers.c @@ -437,101 +437,6 @@ double acos_wrapper(double x) */ #define CONST const -long strtol_wrapper(CONST char *nptr, char **endptr, int base) -{ - register CONST char *s; - register long acc, cutoff; - register int c; - register int neg, any, cutlim; - - /* - * 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 longs is - * [-2147483648..2147483647] and the input base is 10, - * cutoff will be set to 214748364 and cutlim to either - * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated - * a value > 214748364, 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 ? LONG_MIN : LONG_MAX; - cutlim = 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 = LONG_MIN; - } else { - any = 1; - acc *= base; - acc -= c; - } - } else { - if ((acc > cutoff || acc == cutoff) && c > cutlim) { - any = -1; - acc = LONG_MAX; - } else { - any = 1; - acc *= base; - acc += c; - } - } - } - if (endptr != 0) - *endptr = (char *) (any ? s - 1 : nptr); - return (acc); -} - int64_t strtoq_wrapper(CONST char *nptr, char **endptr, int base) { return strtol(nptr, endptr, base); diff --git a/apps/plugins/sdl/include/SDL_config_rockbox.h b/apps/plugins/sdl/include/SDL_config_rockbox.h index e415421a5a..18057d800b 100644 --- a/apps/plugins/sdl/include/SDL_config_rockbox.h +++ b/apps/plugins/sdl/include/SDL_config_rockbox.h @@ -117,6 +117,7 @@ #define atexit rb_atexit #define atof atof_wrapper #define atoi rb->atoi +#define HAVE_ATOI 1 #define atol atoi #define calloc tlsf_calloc #define ceil ceil_wrapper @@ -174,7 +175,8 @@ #define strstr SDL_strstr #define strtok strtok_wrapper #define strtok_r rb->strtok_r -#define strtol SDL_strtol +#define HAVE_STRTOL 1 +#define strtol rb->strtol #define tan tan_wrapper #define time(x) (*rb->current_tick/HZ) #define unlink remove diff --git a/firmware/SOURCES b/firmware/SOURCES index f2b3811fd2..d878acc85d 100644 --- a/firmware/SOURCES +++ b/firmware/SOURCES @@ -300,6 +300,8 @@ common/inflate.c /* Standard library */ #if (CONFIG_PLATFORM & PLATFORM_NATIVE) || defined(HAVE_ROCKBOX_C_LIBRARY) libc/atoi.c +libc/strtol.c +libc/strtoul.c libc/errno.c #if (CONFIG_PLATFORM & PLATFORM_NATIVE) /* our ctype.[ch] comes from newlib and is incompitble with most desktop's ctype */ diff --git a/firmware/libc/include/stdlib.h b/firmware/libc/include/stdlib.h index 855663efac..ea20eac1a3 100644 --- a/firmware/libc/include/stdlib.h +++ b/firmware/libc/include/stdlib.h @@ -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 } diff --git a/firmware/libc/strtol.c b/firmware/libc/strtol.c new file mode 100644 index 0000000000..a38acac025 --- /dev/null +++ b/firmware/libc/strtol.c @@ -0,0 +1,29 @@ +#include +#include +#include +#include +#include + +#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); +} + diff --git a/firmware/libc/strtoul.c b/firmware/libc/strtoul.c new file mode 100644 index 0000000000..34a8ae47c2 --- /dev/null +++ b/firmware/libc/strtoul.c @@ -0,0 +1,57 @@ +#include +#include +#include +#include +#include + +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); +} diff --git a/lib/rbcodec/rbcodecplatform-unix.h b/lib/rbcodec/rbcodecplatform-unix.h index 2df0a50221..9ce01a0035 100644 --- a/lib/rbcodec/rbcodecplatform-unix.h +++ b/lib/rbcodec/rbcodecplatform-unix.h @@ -17,7 +17,7 @@ /* strcasecmp */ #include -/* abs, atoi, labs, rand */ +/* abs, atoi, strtol, strtoul, labs, rand */ #include /* swap16, swap32 */