/* ** 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 0, 0b, 0B, 0o, 0O, 0x 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 Ta27OS_strtoul(register char *str, char **ptr, int base) { register unsigned long result = 0; /* return value of the function */ register int c; /* current input character */ register int ovlimit; /* required digits to overflow */ /* skip leading white space */ while (*str && isspace(Py_CHARMASK(*str))) ++str; /* check for leading 0 or 0x for auto-base or base 16 */ switch (base) { case 0: /* look for leading 0, 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 = 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 = 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 = str; return 0; } ++str; base = 2; } else { base = 8; } } else base = 10; break; case 2: /* skip leading 0b or 0B */ 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 = str; return 0; } ++str; } } break; case 8: /* skip leading 0o or 0O */ 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 = str; return 0; } ++str; } } break; case 16: /* skip leading 0x 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 = str; return 0; } ++str; } } break; } /* catch silly bases */ if (base < 2 || base > 36) { if (ptr) *ptr = 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 */ register 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 = str; return result; overflowed: if (ptr) { /* spool through remaining digit characters */ while (_PyLong_DigitValue[Py_CHARMASK(*str)] < base) ++str; *ptr = str; } errno = ERANGE; return (unsigned long)-1; }
static PyObject * strop_translate(PyObject *self, PyObject *args) { register char *input, *table, *output; Py_ssize_t i; int c, changed = 0; PyObject *input_obj; char *table1, *output_start, *del_table=NULL; Py_ssize_t inlen, tablen, dellen = 0; PyObject *result; int trans_table[256]; WARN; if (!PyArg_ParseTuple(args, "St#|t#:translate", &input_obj, &table1, &tablen, &del_table, &dellen)) return NULL; if (tablen != 256) { PyErr_SetString(PyExc_ValueError, "translation table must be 256 characters long"); return NULL; } table = table1; inlen = PyString_GET_SIZE(input_obj); result = PyString_FromStringAndSize((char *)NULL, inlen); if (result == NULL) return NULL; output_start = output = PyString_AsString(result); input = PyString_AsString(input_obj); if (dellen == 0) { /* If no deletions are required, use faster code */ for (i = inlen; --i >= 0; ) { c = Py_CHARMASK(*input++); if (Py_CHARMASK((*output++ = table[c])) != c) changed = 1; } if (changed) return result; Py_DECREF(result); Py_INCREF(input_obj); return input_obj; } for (i = 0; i < 256; i++) trans_table[i] = Py_CHARMASK(table[i]); for (i = 0; i < dellen; i++) trans_table[(int) Py_CHARMASK(del_table[i])] = -1; for (i = inlen; --i >= 0; ) { c = Py_CHARMASK(*input++); if (trans_table[c] != -1) if (Py_CHARMASK(*output++ = (char)trans_table[c]) == c) continue; changed = 1; } if (!changed) { Py_DECREF(result); Py_INCREF(input_obj); return input_obj; } /* Fix the size of the resulting string */ if (inlen > 0) _PyString_Resize(&result, output - output_start); return result; }
/* * Ensure that any exponent, if present, is at least MIN_EXPONENT_DIGITS * in length. */ static void _ensure_minimum_exponent_length(char* buffer, size_t buf_size) { char *p = strpbrk(buffer, "eE"); if (p && (*(p + 1) == '-' || *(p + 1) == '+')) { char *start = p + 2; int exponent_digit_cnt = 0; int leading_zero_cnt = 0; int in_leading_zeros = 1; int significant_digit_cnt; /* Skip over the exponent and the sign. */ p += 2; /* Find the end of the exponent, keeping track of leading zeros. */ while (*p && isdigit(Py_CHARMASK(*p))) { if (in_leading_zeros && *p == '0') { ++leading_zero_cnt; } if (*p != '0') { in_leading_zeros = 0; } ++p; ++exponent_digit_cnt; } significant_digit_cnt = exponent_digit_cnt - leading_zero_cnt; if (exponent_digit_cnt == MIN_EXPONENT_DIGITS) { /* * If there are 2 exactly digits, we're done, * regardless of what they contain */ } else if (exponent_digit_cnt > MIN_EXPONENT_DIGITS) { int extra_zeros_cnt; /* * There are more than 2 digits in the exponent. See * if we can delete some of the leading zeros */ if (significant_digit_cnt < MIN_EXPONENT_DIGITS) { significant_digit_cnt = MIN_EXPONENT_DIGITS; } extra_zeros_cnt = exponent_digit_cnt - significant_digit_cnt; /* * Delete extra_zeros_cnt worth of characters from the * front of the exponent */ assert(extra_zeros_cnt >= 0); /* * Add one to significant_digit_cnt to copy the * trailing 0 byte, thus setting the length */ memmove(start, start + extra_zeros_cnt, significant_digit_cnt + 1); } else { /* * If there are fewer than 2 digits, add zeros * until there are 2, if there's enough room */ int zeros = MIN_EXPONENT_DIGITS - exponent_digit_cnt; if (start + zeros + exponent_digit_cnt + 1 < buffer + buf_size) { memmove(start + zeros, start, exponent_digit_cnt + 1); memset(start, '0', zeros); } } } }
static PyObject * complex_subtype_from_string(PyTypeObject *type, PyObject *v) { const char *s, *start; char *end; double x=0.0, y=0.0, z; int got_re=0, got_im=0, done=0; int digit_or_dot; int sw_error=0; int sign; char buffer[256]; /* For errors */ #ifdef Py_USING_UNICODE char s_buffer[256]; #endif Py_ssize_t len; if (PyString_Check(v)) { s = PyString_AS_STRING(v); len = PyString_GET_SIZE(v); } #ifdef Py_USING_UNICODE else if (PyUnicode_Check(v)) { if (PyUnicode_GET_SIZE(v) >= (Py_ssize_t)sizeof(s_buffer)) { PyErr_SetString(PyExc_ValueError, "complex() literal too large to convert"); return NULL; } if (PyUnicode_EncodeDecimal(PyUnicode_AS_UNICODE(v), PyUnicode_GET_SIZE(v), s_buffer, NULL)) return NULL; s = s_buffer; len = strlen(s); } #endif else if (PyObject_AsCharBuffer(v, &s, &len)) { PyErr_SetString(PyExc_TypeError, "complex() arg is not a string"); return NULL; } /* position on first nonblank */ start = s; while (*s && isspace(Py_CHARMASK(*s))) s++; if (s[0] == '\0') { PyErr_SetString(PyExc_ValueError, "complex() arg is an empty string"); return NULL; } z = -1.0; sign = 1; do { switch (*s) { case '\0': if (s-start != len) { PyErr_SetString( PyExc_ValueError, "complex() arg contains a null byte"); return NULL; } if(!done) sw_error=1; break; case '-': sign = -1; /* Fallthrough */ case '+': if (done) sw_error=1; s++; if ( *s=='\0'||*s=='+'||*s=='-' || isspace(Py_CHARMASK(*s)) ) sw_error=1; break; case 'J': case 'j': if (got_im || done) { sw_error = 1; break; } if (z<0.0) { y=sign; } else{ y=sign*z; } got_im=1; s++; if (*s!='+' && *s!='-' ) done=1; break; default: if (isspace(Py_CHARMASK(*s))) { while (*s && isspace(Py_CHARMASK(*s))) s++; if (s[0] != '\0') sw_error=1; else done = 1; break; } digit_or_dot = (*s=='.' || isdigit(Py_CHARMASK(*s))); if (done||!digit_or_dot) { sw_error=1; break; } errno = 0; PyFPE_START_PROTECT("strtod", return 0) z = PyOS_ascii_strtod(s, &end) ; PyFPE_END_PROTECT(z) if (errno != 0) { PyOS_snprintf(buffer, sizeof(buffer), "float() out of range: %.150s", s); PyErr_SetString( PyExc_ValueError, buffer); return NULL; } s=end; if (*s=='J' || *s=='j') { break; } if (got_re) { sw_error=1; break; } /* accept a real part */ x=sign*z; got_re=1; if (got_im) done=1; z = -1.0; sign = 1; break; } /* end of switch */ } while (s - start < len && !sw_error); if (sw_error) { PyErr_SetString(PyExc_ValueError, "complex() arg is a malformed string"); return NULL; } return complex_subtype_from_doubles(type, x, y); }
static int vgetargs1(PyObject *args, const char *format, va_list *p_va, int flags) { char msgbuf[256]; int levels[32]; const char *fname = NULL; const char *message = NULL; int min = -1; int max = 0; int level = 0; int endfmt = 0; const char *formatsave = format; Py_ssize_t i, len; char *msg; PyObject *freelist = NULL; int compat = flags & FLAG_COMPAT; assert(compat || (args != (PyObject*)NULL)); flags = flags & ~FLAG_COMPAT; while (endfmt == 0) { int c = *format++; switch (c) { case '(': if (level == 0) max++; level++; if (level >= 30) Py_FatalError("too many tuple nesting levels " "in argument format string"); break; case ')': if (level == 0) Py_FatalError("excess ')' in getargs format"); else level--; break; case '\0': endfmt = 1; break; case ':': fname = format; endfmt = 1; break; case ';': message = format; endfmt = 1; break; default: if (level == 0) { if (c == 'O') max++; else if (isalpha(Py_CHARMASK(c))) { if (c != 'e') /* skip encoded */ max++; } else if (c == '|') min = max; } break; } } if (level != 0) Py_FatalError(/* '(' */ "missing ')' in getargs format"); if (min < 0) min = max; format = formatsave; if (compat) { if (max == 0) { if (args == NULL) return 1; PyOS_snprintf(msgbuf, sizeof(msgbuf), "%.200s%s takes no arguments", fname==NULL ? "function" : fname, fname==NULL ? "" : "()"); PyErr_SetString(PyExc_TypeError, msgbuf); return 0; } else if (min == 1 && max == 1) { if (args == NULL) { PyOS_snprintf(msgbuf, sizeof(msgbuf), "%.200s%s takes at least one argument", fname==NULL ? "function" : fname, fname==NULL ? "" : "()"); PyErr_SetString(PyExc_TypeError, msgbuf); return 0; } msg = convertitem(args, &format, p_va, flags, levels, msgbuf, sizeof(msgbuf), &freelist); if (msg == NULL) return cleanreturn(1, freelist); seterror(levels[0], msg, levels+1, fname, message); return cleanreturn(0, freelist); } else { PyErr_SetString(PyExc_SystemError, "old style getargs format uses new features"); return 0; } } if (!PyTuple_Check(args)) { PyErr_SetString(PyExc_SystemError, "new style getargs format but argument is not a tuple"); return 0; } len = PyTuple_GET_SIZE(args); if (len < min || max < len) { if (message == NULL) { PyOS_snprintf(msgbuf, sizeof(msgbuf), "%.150s%s takes %s %d argument%s " "(%ld given)", fname==NULL ? "function" : fname, fname==NULL ? "" : "()", min==max ? "exactly" : len < min ? "at least" : "at most", len < min ? min : max, (len < min ? min : max) == 1 ? "" : "s", Py_SAFE_DOWNCAST(len, Py_ssize_t, long)); message = msgbuf; } PyErr_SetString(PyExc_TypeError, message); return 0; }
static void translabel(grammar *g, label *lb) { int i; if (lb->lb_type == NAME) { for (i = 0; i < g->g_ndfas; i++) { if (lb->lb_str_length == g->g_dfa[i].d_name_length && memcmp(lb->lb_str, g->g_dfa[i].d_name, lb->lb_str_length) == 0) { #ifndef NDEBUG printf("Label %.*s is non-terminal %d.\n", (int)lb->lb_str_length, lb->lb_str, g->g_dfa[i].d_type); #endif lb->lb_type = g->g_dfa[i].d_type; lb->lb_str = NULL; lb->lb_str_length = 0; return; } } for (i = 0; i < (int)N_TOKENS; i++) { if (lb->lb_str_length == strlen((const char*)_PyParser_TokenNames[i]) && memcmp(lb->lb_str, _PyParser_TokenNames[i], lb->lb_str_length) == 0) { #ifndef NDEBUG printf("Label %.*s is terminal %d.\n", (int)lb->lb_str_length, lb->lb_str, i); #endif lb->lb_type = i; lb->lb_str = NULL; lb->lb_str_length = 0; return; } } printf("Can't translate NAME label '%.*s'\n", (int)lb->lb_str_length, lb->lb_str); return; } if (lb->lb_type == STRING) { if (isalpha(Py_CHARMASK(lb->lb_str[1])) || lb->lb_str[1] == '_') { // Maintain the constraint of keywords to the ASCII character set. const unsigned char *p; #ifndef NDEBUG printf("Label %.*s is a keyword\n", (int)lb->lb_str_length, lb->lb_str); #endif lb->lb_type = NAME; lb->lb_str += 1; p = CUC(strchr((const char *)lb->lb_str, '\'')); if (p != NULL) lb->lb_str_length = p - lb->lb_str; } else { int type; unsigned int *utf; // Limit strings to `maximum_string_length` (+2 quotes). unsigned int utf_data[maximum_string_length+2]; // Decode the label and bracket it [`utf`, `utf_end`). unsigned int *utf_end = &utf_data[0]; const unsigned char *i=lb->lb_str; while (i - lb->lb_str < lb->lb_str_length) { i = decode(i, utf_end++); assert(utf_end - utf_data < maximum_string_length); } assert(utf_data[0] == (unsigned int)(unsigned char)'\''); utf_end -= 1; assert(*utf_end == (unsigned int)(unsigned char)'\''); utf = &utf_data[1]; switch (utf_end - utf) { /* * Operators from the grammar are wrapped by single quotes, so I'm * looking for the operator's length plus two. */ case 1: type = (int) PyToken_OneChar(utf[0]); if (type != OP) { lb->lb_type = type; lb->lb_str = NULL; lb->lb_str_length = 0; } else printf("Unknown OP label %.*s\n", (int)lb->lb_str_length, (const char *)lb->lb_str); break; case 2: type = (int) PyToken_TwoChars(utf[0], utf[1]); if (type != OP) { lb->lb_type = type; lb->lb_str = NULL; lb->lb_str_length = 0; } else printf("Unknown OP label %.*s\n", (int)lb->lb_str_length, (const char *)lb->lb_str); break; case 3: type = (int) PyToken_ThreeChars(utf[0], utf[1], utf[2]); if (type != OP) { lb->lb_type = type; lb->lb_str = NULL; lb->lb_str_length = 0; } else printf("Unknown OP label %.*s\n", (int)lb->lb_str_length, (const char *)lb->lb_str); break; default: printf("Can't translate STRING label %.*s\n", (int)lb->lb_str_length, (const char*)lb->lb_str); } } } else printf("Can't translate label of type '%i'\n", lb->lb_type); }
static int tok_nextc(register struct tok_state *tok) { for (;;) { if (tok->cur != tok->inp) { return Py_CHARMASK(*tok->cur++); /* Fast path */ } if (tok->done != E_OK) return EOF; if (tok->fp == NULL) { char *end = strchr(tok->inp, '\n'); if (end != NULL) end++; else { end = strchr(tok->inp, '\0'); if (end == tok->inp) { tok->done = E_EOF; return EOF; } } if (tok->start == NULL) tok->buf = tok->cur; tok->line_start = tok->cur; tok->lineno++; tok->inp = end; return Py_CHARMASK(*tok->cur++); } if (tok->prompt != NULL) { char *newtok = PyOS_Readline(stdin, stdout, tok->prompt); if (tok->nextprompt != NULL) tok->prompt = tok->nextprompt; if (newtok == NULL) tok->done = E_INTR; else if (*newtok == '\0') { PyMem_FREE(newtok); tok->done = E_EOF; } #if !defined(PGEN) && defined(Py_USING_UNICODE) else if (tok_stdin_decode(tok, &newtok) != 0) PyMem_FREE(newtok); #endif else if (tok->start != NULL) { size_t start = tok->start - tok->buf; size_t oldlen = tok->cur - tok->buf; size_t newlen = oldlen + strlen(newtok); char *buf = tok->buf; buf = (char *)PyMem_REALLOC(buf, newlen+1); tok->lineno++; if (buf == NULL) { PyMem_FREE(tok->buf); tok->buf = NULL; PyMem_FREE(newtok); tok->done = E_NOMEM; return EOF; } tok->buf = buf; tok->cur = tok->buf + oldlen; tok->line_start = tok->cur; strcpy(tok->buf + oldlen, newtok); PyMem_FREE(newtok); tok->inp = tok->buf + newlen; tok->end = tok->inp + 1; tok->start = tok->buf + start; } else { tok->lineno++; if (tok->buf != NULL) PyMem_FREE(tok->buf); tok->buf = newtok; tok->line_start = tok->buf; tok->cur = tok->buf; tok->line_start = tok->buf; tok->inp = strchr(tok->buf, '\0'); tok->end = tok->inp + 1; } } else { int done = 0; Py_ssize_t cur = 0; char *pt; if (tok->start == NULL) { if (tok->buf == NULL) { tok->buf = (char *) PyMem_MALLOC(BUFSIZ); if (tok->buf == NULL) { tok->done = E_NOMEM; return EOF; } tok->end = tok->buf + BUFSIZ; } if (decoding_fgets(tok->buf, (int)(tok->end - tok->buf), tok) == NULL) { tok->done = E_EOF; done = 1; } else { tok->done = E_OK; tok->inp = strchr(tok->buf, '\0'); done = tok->inp[-1] == '\n'; } } else { cur = tok->cur - tok->buf; if (decoding_feof(tok)) { tok->done = E_EOF; done = 1; } else tok->done = E_OK; } tok->lineno++; /* Read until '\n' or EOF */ while (!done) { Py_ssize_t curstart = tok->start == NULL ? -1 : tok->start - tok->buf; Py_ssize_t curvalid = tok->inp - tok->buf; Py_ssize_t newsize = curvalid + BUFSIZ; char *newbuf = tok->buf; newbuf = (char *)PyMem_REALLOC(newbuf, newsize); if (newbuf == NULL) { tok->done = E_NOMEM; tok->cur = tok->inp; return EOF; } tok->buf = newbuf; tok->inp = tok->buf + curvalid; tok->end = tok->buf + newsize; tok->start = curstart < 0 ? NULL : tok->buf + curstart; if (decoding_fgets(tok->inp, (int)(tok->end - tok->inp), tok) == NULL) { /* Break out early on decoding errors, as tok->buf will be NULL */ if (tok->decoding_erred) return EOF; /* Last line does not end in \n, fake one */ strcpy(tok->inp, "\n"); } tok->inp = strchr(tok->inp, '\0'); done = tok->inp[-1] == '\n'; } if (tok->buf != NULL) { tok->cur = tok->buf + cur; tok->line_start = tok->cur; /* replace "\r\n" with "\n" */ /* For Mac leave the \r, giving a syntax error */ pt = tok->inp - 2; if (pt >= tok->buf && *pt == '\r') { *pt++ = '\n'; *pt = '\0'; tok->inp = pt; } } } if (tok->done != E_OK) { if (tok->prompt != NULL) PySys_WriteStderr("\n"); tok->cur = tok->inp; return EOF; } } /*NOTREACHED*/ }
static void buf_ungetc(int c, struct tok_state *tok) { tok->str--; assert(Py_CHARMASK(*tok->str) == c); /* tok->cur may point to read-only segment */ }
static int buf_getc(struct tok_state *tok) { return Py_CHARMASK(*tok->str++); }
static void translabel(grammar *g, label *lb) { int i; if (Py_DebugFlag) printf("Translating label %s ...\n", PyGrammar_LabelRepr(lb)); if (lb->lb_type == NAME) { for (i = 0; i < g->g_ndfas; i++) { if (strcmp(lb->lb_str, g->g_dfa[i].d_name) == 0) { if (Py_DebugFlag) printf( "Label %s is non-terminal %d.\n", lb->lb_str, g->g_dfa[i].d_type); lb->lb_type = g->g_dfa[i].d_type; free(lb->lb_str); lb->lb_str = NULL; return; } } for (i = 0; i < (int)N_TOKENS; i++) { if (strcmp(lb->lb_str, _PyParser_TokenNames[i]) == 0) { if (Py_DebugFlag) printf("Label %s is terminal %d.\n", lb->lb_str, i); lb->lb_type = i; free(lb->lb_str); lb->lb_str = NULL; return; } } printf("Can't translate NAME label '%s'\n", lb->lb_str); return; } if (lb->lb_type == STRING) { if (isalpha(Py_CHARMASK(lb->lb_str[1])) || lb->lb_str[1] == '_') { char *p; char *src; char *dest; size_t name_len; if (Py_DebugFlag) printf("Label %s is a keyword\n", lb->lb_str); lb->lb_type = NAME; src = lb->lb_str + 1; p = strchr(src, '\''); if (p) name_len = p - src; else name_len = strlen(src); dest = (char *)malloc(name_len + 1); if (!dest) { printf("Can't alloc dest '%s'\n", src); return; } strncpy(dest, src, name_len); dest[name_len] = '\0'; free(lb->lb_str); lb->lb_str = dest; } else if (lb->lb_str[2] == lb->lb_str[0]) { int type = (int) PyToken_OneChar(lb->lb_str[1]); if (type != OP) { lb->lb_type = type; free(lb->lb_str); lb->lb_str = NULL; } else printf("Unknown OP label %s\n", lb->lb_str); } else if (lb->lb_str[2] && lb->lb_str[3] == lb->lb_str[0]) { int type = (int) PyToken_TwoChars(lb->lb_str[1], lb->lb_str[2]); if (type != OP) { lb->lb_type = type; free(lb->lb_str); lb->lb_str = NULL; } else printf("Unknown OP label %s\n", lb->lb_str); } else if (lb->lb_str[2] && lb->lb_str[3] && lb->lb_str[4] == lb->lb_str[0]) { int type = (int) PyToken_ThreeChars(lb->lb_str[1], lb->lb_str[2], lb->lb_str[3]); if (type != OP) { lb->lb_type = type; free(lb->lb_str); lb->lb_str = NULL; } else printf("Unknown OP label %s\n", lb->lb_str); } else printf("Can't translate STRING label %s\n", lb->lb_str); } else printf("Can't translate label '%s'\n", PyGrammar_LabelRepr(lb)); }
unsigned long PyOS_strtoul(register char *str, char **ptr, int base) { register unsigned long result; /* return value of the function */ register int c; /* current input character */ register unsigned long temp; /* used in overflow testing */ int ovf; /* true if overflow occurred */ result = 0; ovf = 0; /* catch silly bases */ if (base != 0 && (base < 2 || base > 36)) { if (ptr) *ptr = str; return 0; } /* skip leading white space */ while (*str && isspace(Py_CHARMASK(*str))) str++; /* check for leading 0 or 0x for auto-base or base 16 */ switch (base) { case 0: /* look for leading 0, 0x or 0X */ if (*str == '0') { str++; if (*str == 'x' || *str == 'X') { str++; base = 16; } else base = 8; } else base = 10; break; case 16: /* skip leading 0x or 0X */ if (*str == '0' && (*(str+1) == 'x' || *(str+1) == 'X')) str += 2; break; } /* do the conversion */ while ((c = Py_CHARMASK(*str)) != '\0') { if (isdigit(c) && c - '0' < base) c -= '0'; else { if (isupper(c)) c = tolower(c); if (c >= 'a' && c <= 'z') c -= 'a' - 10; else /* non-"digit" character */ break; if (c >= base) /* non-"digit" character */ break; } temp = result; result = result * base + c; if(base == 10) { if(((long)(result - c) / base != (long)temp)) /* overflow */ ovf = 1; } else { if ((result - c) / base != temp) /* overflow */ ovf = 1; } str++; } /* set pointer to point to the last character scanned */ if (ptr) *ptr = str; if (ovf) { result = (unsigned long) ~0L; errno = ERANGE; } return result; }