Skip to content

Commit f73457d

Browse files
committed
add strtol and strtoul from newlib
1 parent f9f998f commit f73457d

File tree

1 file changed

+175
-53
lines changed

1 file changed

+175
-53
lines changed

hardware/esp8266com/esp8266/cores/esp8266/libc_replacements.c

Lines changed: 175 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -215,57 +215,6 @@ char* ICACHE_FLASH_ATTR strdup(const char *str) {
215215
return cstr;
216216
}
217217

218-
long int ICACHE_FLASH_ATTR strtol(const char* str, char** endptr, int base) {
219-
long int result = 0;
220-
int sign = 1;
221-
222-
while(isspace(*str)) {
223-
str++;
224-
}
225-
226-
if(*str == 0x00) {
227-
// only space in str?
228-
*endptr = (char*) str;
229-
return result;
230-
}
231-
232-
switch(base) {
233-
case 10:
234-
235-
if(*str == '-') {
236-
sign = -1;
237-
str++;
238-
} else if(*str == '+') {
239-
str++;
240-
}
241-
242-
for(uint8_t i = 0; *str; i++, str++) {
243-
int x = *str - '0';
244-
if(x < 0 || x > 9) {
245-
break;
246-
}
247-
result = result * 10 + x;
248-
}
249-
break;
250-
case 2:
251-
for(uint8_t i = 0; *str; i++, str++) {
252-
int x = *str - '0';
253-
if(x < 0 || x > 1) {
254-
break;
255-
}
256-
result = result * 2 + x;
257-
}
258-
break;
259-
case 16:
260-
default:
261-
os_printf("fnk: strtol() only supports base 10 and 2 ATM!\n");
262-
break;
263-
264-
}
265-
*endptr = (char*) str;
266-
return sign * result;
267-
}
268-
269218
// based on Source:
270219
// https://github.com/anakod/Sming/blob/master/Sming/system/stringconversion.cpp#L93
271220
double ICACHE_FLASH_ATTR strtod(const char* str, char** endptr) {
@@ -479,16 +428,189 @@ size_t ICACHE_FLASH_ATTR strlcpy(char* dst, const char* src, size_t size) {
479428
break;
480429
} while (--n != 0);
481430
}
482-
431+
483432
if (n == 0) {
484433
if (size != 0)
485434
*dst = 0;
486435
while (*s++);
487436
}
488-
437+
489438
return(s - src - 1);
490439
}
491440
/*
492441
* end of newlib/string/strlcpy.c
493442
*/
494443

444+
445+
446+
/**
447+
* strtol() and strtoul() implementations borrowed from newlib:
448+
* http://www.sourceware.org/newlib/
449+
* newlib/libc/stdlib/strtol.c
450+
* newlib/libc/stdlib/strtoul.c
451+
*
452+
* Adapted for ESP8266 by Kiril Zyapkov <[email protected]>
453+
*
454+
* Copyright (c) 1990 The Regents of the University of California.
455+
* All rights reserved.
456+
*
457+
* Redistribution and use in source and binary forms, with or without
458+
* modification, are permitted provided that the following conditions
459+
* are met:
460+
* 1. Redistributions of source code must retain the above copyright
461+
* notice, this list of conditions and the following disclaimer.
462+
* 2. Redistributions in binary form must reproduce the above copyright
463+
* notice, this list of conditions and the following disclaimer in the
464+
* documentation and/or other materials provided with the distribution.
465+
* 3. All advertising materials mentioning features or use of this software
466+
* must display the following acknowledgement:
467+
* This product includes software developed by the University of
468+
* California, Berkeley and its contributors.
469+
* 4. Neither the name of the University nor the names of its contributors
470+
* may be used to endorse or promote products derived from this software
471+
* without specific prior written permission.
472+
*
473+
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
474+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
475+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
476+
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
477+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
478+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
479+
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
480+
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
481+
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
482+
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
483+
* SUCH DAMAGE.
484+
*/
485+
486+
long strtol(const char *nptr, char **endptr, int base) {
487+
const unsigned char *s = (const unsigned char *)nptr;
488+
unsigned long acc;
489+
int c;
490+
unsigned long cutoff;
491+
int neg = 0, any, cutlim;
492+
493+
/*
494+
* Skip white space and pick up leading +/- sign if any.
495+
* If base is 0, allow 0x for hex and 0 for octal, else
496+
* assume decimal; if base is already 16, allow 0x.
497+
*/
498+
do {
499+
c = *s++;
500+
} while (isspace(c));
501+
if (c == '-') {
502+
neg = 1;
503+
c = *s++;
504+
} else if (c == '+')
505+
c = *s++;
506+
if ((base == 0 || base == 16) &&
507+
c == '0' && (*s == 'x' || *s == 'X')) {
508+
c = s[1];
509+
s += 2;
510+
base = 16;
511+
}
512+
if (base == 0)
513+
base = c == '0' ? 8 : 10;
514+
515+
/*
516+
* Compute the cutoff value between legal numbers and illegal
517+
* numbers. That is the largest legal value, divided by the
518+
* base. An input number that is greater than this value, if
519+
* followed by a legal input character, is too big. One that
520+
* is equal to this value may be valid or not; the limit
521+
* between valid and invalid numbers is then based on the last
522+
* digit. For instance, if the range for longs is
523+
* [-2147483648..2147483647] and the input base is 10,
524+
* cutoff will be set to 214748364 and cutlim to either
525+
* 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
526+
* a value > 214748364, or equal but the next digit is > 7 (or 8),
527+
* the number is too big, and we will return a range error.
528+
*
529+
* Set any if any `digits' consumed; make it negative to indicate
530+
* overflow.
531+
*/
532+
cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX;
533+
cutlim = cutoff % (unsigned long)base;
534+
cutoff /= (unsigned long)base;
535+
for (acc = 0, any = 0;; c = *s++) {
536+
if (isdigit(c))
537+
c -= '0';
538+
else if (isalpha(c))
539+
c -= isupper(c) ? 'A' - 10 : 'a' - 10;
540+
else
541+
break;
542+
if (c >= base)
543+
break;
544+
if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
545+
any = -1;
546+
else {
547+
any = 1;
548+
acc *= base;
549+
acc += c;
550+
}
551+
}
552+
if (any < 0) {
553+
acc = neg ? LONG_MIN : LONG_MAX;
554+
errno = ERANGE;
555+
} else if (neg)
556+
acc = -acc;
557+
if (endptr != 0)
558+
*endptr = (char *) (any ? (char *)s - 1 : nptr);
559+
return (acc);
560+
}
561+
562+
unsigned long strtoul(const char *nptr, char **endptr, int base)
563+
{
564+
const unsigned char *s = (const unsigned char *)nptr;
565+
unsigned long acc;
566+
int c;
567+
unsigned long cutoff;
568+
int neg = 0, any, cutlim;
569+
570+
/*
571+
* See strtol for comments as to the logic used.
572+
*/
573+
do {
574+
c = *s++;
575+
} while (isspace(c));
576+
if (c == '-') {
577+
neg = 1;
578+
c = *s++;
579+
} else if (c == '+')
580+
c = *s++;
581+
if ((base == 0 || base == 16) &&
582+
c == '0' && (*s == 'x' || *s == 'X')) {
583+
c = s[1];
584+
s += 2;
585+
base = 16;
586+
}
587+
if (base == 0)
588+
base = c == '0' ? 8 : 10;
589+
cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
590+
cutlim = (unsigned long)ULONG_MAX % (unsigned long)base;
591+
for (acc = 0, any = 0;; c = *s++) {
592+
if (isdigit(c))
593+
c -= '0';
594+
else if (isalpha(c))
595+
c -= isupper(c) ? 'A' - 10 : 'a' - 10;
596+
else
597+
break;
598+
if (c >= base)
599+
break;
600+
if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
601+
any = -1;
602+
else {
603+
any = 1;
604+
acc *= base;
605+
acc += c;
606+
}
607+
}
608+
if (any < 0) {
609+
acc = ULONG_MAX;
610+
errno = ERANGE;
611+
} else if (neg)
612+
acc = -acc;
613+
if (endptr != 0)
614+
*endptr = (char *) (any ? (char *)s - 1 : nptr);
615+
return (acc);
616+
}

0 commit comments

Comments
 (0)