mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-05-24 06:12:27 +00:00
python-3.6.zip added from Github
README.cosmo contains the necessary links.
This commit is contained in:
parent
75fc601ff5
commit
0c4c56ff39
4219 changed files with 1968626 additions and 0 deletions
291
third_party/python/Python/mystrtoul.c
vendored
Normal file
291
third_party/python/Python/mystrtoul.c
vendored
Normal file
|
@ -0,0 +1,291 @@
|
|||
|
||||
#include "Python.h"
|
||||
|
||||
#if defined(__sgi) && defined(WITH_THREAD) && !defined(_SGI_MP_SOURCE)
|
||||
#define _SGI_MP_SOURCE
|
||||
#endif
|
||||
|
||||
/* strtol and strtoul, renamed to avoid conflicts */
|
||||
|
||||
|
||||
#include <ctype.h>
|
||||
#ifdef HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
|
||||
/* Static overflow check values for bases 2 through 36.
|
||||
* smallmax[base] is the largest unsigned long i such that
|
||||
* i * base doesn't overflow unsigned long.
|
||||
*/
|
||||
static const unsigned long smallmax[] = {
|
||||
0, /* bases 0 and 1 are invalid */
|
||||
0,
|
||||
ULONG_MAX / 2,
|
||||
ULONG_MAX / 3,
|
||||
ULONG_MAX / 4,
|
||||
ULONG_MAX / 5,
|
||||
ULONG_MAX / 6,
|
||||
ULONG_MAX / 7,
|
||||
ULONG_MAX / 8,
|
||||
ULONG_MAX / 9,
|
||||
ULONG_MAX / 10,
|
||||
ULONG_MAX / 11,
|
||||
ULONG_MAX / 12,
|
||||
ULONG_MAX / 13,
|
||||
ULONG_MAX / 14,
|
||||
ULONG_MAX / 15,
|
||||
ULONG_MAX / 16,
|
||||
ULONG_MAX / 17,
|
||||
ULONG_MAX / 18,
|
||||
ULONG_MAX / 19,
|
||||
ULONG_MAX / 20,
|
||||
ULONG_MAX / 21,
|
||||
ULONG_MAX / 22,
|
||||
ULONG_MAX / 23,
|
||||
ULONG_MAX / 24,
|
||||
ULONG_MAX / 25,
|
||||
ULONG_MAX / 26,
|
||||
ULONG_MAX / 27,
|
||||
ULONG_MAX / 28,
|
||||
ULONG_MAX / 29,
|
||||
ULONG_MAX / 30,
|
||||
ULONG_MAX / 31,
|
||||
ULONG_MAX / 32,
|
||||
ULONG_MAX / 33,
|
||||
ULONG_MAX / 34,
|
||||
ULONG_MAX / 35,
|
||||
ULONG_MAX / 36,
|
||||
};
|
||||
|
||||
/* maximum digits that can't ever overflow for bases 2 through 36,
|
||||
* calculated by [int(math.floor(math.log(2**32, i))) for i in range(2, 37)].
|
||||
* Note that this is pessimistic if sizeof(long) > 4.
|
||||
*/
|
||||
#if SIZEOF_LONG == 4
|
||||
static const int digitlimit[] = {
|
||||
0, 0, 32, 20, 16, 13, 12, 11, 10, 10, /* 0 - 9 */
|
||||
9, 9, 8, 8, 8, 8, 8, 7, 7, 7, /* 10 - 19 */
|
||||
7, 7, 7, 7, 6, 6, 6, 6, 6, 6, /* 20 - 29 */
|
||||
6, 6, 6, 6, 6, 6, 6}; /* 30 - 36 */
|
||||
#elif SIZEOF_LONG == 8
|
||||
/* [int(math.floor(math.log(2**64, i))) for i in range(2, 37)] */
|
||||
static const int digitlimit[] = {
|
||||
0, 0, 64, 40, 32, 27, 24, 22, 21, 20, /* 0 - 9 */
|
||||
19, 18, 17, 17, 16, 16, 16, 15, 15, 15, /* 10 - 19 */
|
||||
14, 14, 14, 14, 13, 13, 13, 13, 13, 13, /* 20 - 29 */
|
||||
13, 12, 12, 12, 12, 12, 12}; /* 30 - 36 */
|
||||
#else
|
||||
#error "Need table for SIZEOF_LONG"
|
||||
#endif
|
||||
|
||||
/*
|
||||
** strtoul
|
||||
** This is a general purpose routine for converting
|
||||
** an ascii string to an integer in an arbitrary base.
|
||||
** Leading white space is ignored. If 'base' is zero
|
||||
** it looks for a leading 0b, 0o or 0x to tell which
|
||||
** base. If these are absent it defaults to 10.
|
||||
** Base must be 0 or between 2 and 36 (inclusive).
|
||||
** If 'ptr' is non-NULL it will contain a pointer to
|
||||
** the end of the scan.
|
||||
** Errors due to bad pointers will probably result in
|
||||
** exceptions - we don't check for them.
|
||||
*/
|
||||
unsigned long
|
||||
PyOS_strtoul(const char *str, char **ptr, int base)
|
||||
{
|
||||
unsigned long result = 0; /* return value of the function */
|
||||
int c; /* current input character */
|
||||
int ovlimit; /* required digits to overflow */
|
||||
|
||||
/* skip leading white space */
|
||||
while (*str && Py_ISSPACE(Py_CHARMASK(*str)))
|
||||
++str;
|
||||
|
||||
/* check for leading 0b, 0o or 0x for auto-base or base 16 */
|
||||
switch (base) {
|
||||
case 0: /* look for leading 0b, 0o or 0x */
|
||||
if (*str == '0') {
|
||||
++str;
|
||||
if (*str == 'x' || *str == 'X') {
|
||||
/* there must be at least one digit after 0x */
|
||||
if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 16) {
|
||||
if (ptr)
|
||||
*ptr = (char *)str;
|
||||
return 0;
|
||||
}
|
||||
++str;
|
||||
base = 16;
|
||||
} else if (*str == 'o' || *str == 'O') {
|
||||
/* there must be at least one digit after 0o */
|
||||
if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 8) {
|
||||
if (ptr)
|
||||
*ptr = (char *)str;
|
||||
return 0;
|
||||
}
|
||||
++str;
|
||||
base = 8;
|
||||
} else if (*str == 'b' || *str == 'B') {
|
||||
/* there must be at least one digit after 0b */
|
||||
if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 2) {
|
||||
if (ptr)
|
||||
*ptr = (char *)str;
|
||||
return 0;
|
||||
}
|
||||
++str;
|
||||
base = 2;
|
||||
} else {
|
||||
/* skip all zeroes... */
|
||||
while (*str == '0')
|
||||
++str;
|
||||
while (Py_ISSPACE(Py_CHARMASK(*str)))
|
||||
++str;
|
||||
if (ptr)
|
||||
*ptr = (char *)str;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
base = 10;
|
||||
break;
|
||||
|
||||
/* even with explicit base, skip leading 0? prefix */
|
||||
case 16:
|
||||
if (*str == '0') {
|
||||
++str;
|
||||
if (*str == 'x' || *str == 'X') {
|
||||
/* there must be at least one digit after 0x */
|
||||
if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 16) {
|
||||
if (ptr)
|
||||
*ptr = (char *)str;
|
||||
return 0;
|
||||
}
|
||||
++str;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
if (*str == '0') {
|
||||
++str;
|
||||
if (*str == 'o' || *str == 'O') {
|
||||
/* there must be at least one digit after 0o */
|
||||
if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 8) {
|
||||
if (ptr)
|
||||
*ptr = (char *)str;
|
||||
return 0;
|
||||
}
|
||||
++str;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if(*str == '0') {
|
||||
++str;
|
||||
if (*str == 'b' || *str == 'B') {
|
||||
/* there must be at least one digit after 0b */
|
||||
if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 2) {
|
||||
if (ptr)
|
||||
*ptr = (char *)str;
|
||||
return 0;
|
||||
}
|
||||
++str;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* catch silly bases */
|
||||
if (base < 2 || base > 36) {
|
||||
if (ptr)
|
||||
*ptr = (char *)str;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* skip leading zeroes */
|
||||
while (*str == '0')
|
||||
++str;
|
||||
|
||||
/* base is guaranteed to be in [2, 36] at this point */
|
||||
ovlimit = digitlimit[base];
|
||||
|
||||
/* do the conversion until non-digit character encountered */
|
||||
while ((c = _PyLong_DigitValue[Py_CHARMASK(*str)]) < base) {
|
||||
if (ovlimit > 0) /* no overflow check required */
|
||||
result = result * base + c;
|
||||
else { /* requires overflow check */
|
||||
unsigned long temp_result;
|
||||
|
||||
if (ovlimit < 0) /* guaranteed overflow */
|
||||
goto overflowed;
|
||||
|
||||
/* there could be an overflow */
|
||||
/* check overflow just from shifting */
|
||||
if (result > smallmax[base])
|
||||
goto overflowed;
|
||||
|
||||
result *= base;
|
||||
|
||||
/* check overflow from the digit's value */
|
||||
temp_result = result + c;
|
||||
if (temp_result < result)
|
||||
goto overflowed;
|
||||
|
||||
result = temp_result;
|
||||
}
|
||||
|
||||
++str;
|
||||
--ovlimit;
|
||||
}
|
||||
|
||||
/* set pointer to point to the last character scanned */
|
||||
if (ptr)
|
||||
*ptr = (char *)str;
|
||||
|
||||
return result;
|
||||
|
||||
overflowed:
|
||||
if (ptr) {
|
||||
/* spool through remaining digit characters */
|
||||
while (_PyLong_DigitValue[Py_CHARMASK(*str)] < base)
|
||||
++str;
|
||||
*ptr = (char *)str;
|
||||
}
|
||||
errno = ERANGE;
|
||||
return (unsigned long)-1;
|
||||
}
|
||||
|
||||
/* Checking for overflow in PyOS_strtol is a PITA; see comments
|
||||
* about PY_ABS_LONG_MIN in longobject.c.
|
||||
*/
|
||||
#define PY_ABS_LONG_MIN (0-(unsigned long)LONG_MIN)
|
||||
|
||||
long
|
||||
PyOS_strtol(const char *str, char **ptr, int base)
|
||||
{
|
||||
long result;
|
||||
unsigned long uresult;
|
||||
char sign;
|
||||
|
||||
while (*str && Py_ISSPACE(Py_CHARMASK(*str)))
|
||||
str++;
|
||||
|
||||
sign = *str;
|
||||
if (sign == '+' || sign == '-')
|
||||
str++;
|
||||
|
||||
uresult = PyOS_strtoul(str, ptr, base);
|
||||
|
||||
if (uresult <= (unsigned long)LONG_MAX) {
|
||||
result = (long)uresult;
|
||||
if (sign == '-')
|
||||
result = -result;
|
||||
}
|
||||
else if (sign == '-' && uresult == PY_ABS_LONG_MIN) {
|
||||
result = LONG_MIN;
|
||||
}
|
||||
else {
|
||||
errno = ERANGE;
|
||||
result = LONG_MAX;
|
||||
}
|
||||
return result;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue