home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 15 / AACD15.ISO / AACD / Programming / Python2 / Python20_source / Python / mystrtoul.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-10-25  |  3.1 KB  |  154 lines

  1.  
  2. #include "Python.h"
  3.  
  4. #if defined(__sgi) && defined(WITH_THREAD) && !defined(_SGI_MP_SOURCE)
  5. #define _SGI_MP_SOURCE
  6. #endif
  7.  
  8. /* Convert a possibly signed character to a nonnegative int */
  9. /* XXX This assumes characters are 8 bits wide */
  10. #ifdef __CHAR_UNSIGNED__
  11. #define Py_CHARMASK(c)        (c)
  12. #else
  13. #define Py_CHARMASK(c)        ((c) & 0xff)
  14. #endif
  15.  
  16. /* strtol and strtoul, renamed to avoid conflicts */
  17.  
  18. /*
  19. **    strtoul
  20. **        This is a general purpose routine for converting
  21. **        an ascii string to an integer in an arbitrary base.
  22. **        Leading white space is ignored.  If 'base' is zero
  23. **        it looks for a leading 0, 0x or 0X to tell which
  24. **        base.  If these are absent it defaults to 10.
  25. **        Base must be 0 or between 2 and 36 (inclusive).
  26. **        If 'ptr' is non-NULL it will contain a pointer to
  27. **        the end of the scan.
  28. **        Errors due to bad pointers will probably result in
  29. **        exceptions - we don't check for them.
  30. */
  31.  
  32. #include <ctype.h>
  33. #ifndef DONT_HAVE_ERRNO_H
  34. #include <errno.h>
  35. #endif
  36.  
  37. unsigned long
  38. PyOS_strtoul(register char *str, char **ptr, int base)
  39. {
  40.     register unsigned long    result;    /* return value of the function */
  41.     register int        c;    /* current input character */
  42.     register unsigned long    temp;    /* used in overflow testing */
  43.     int                ovf;    /* true if overflow occurred */
  44.  
  45.     result = 0;
  46.     ovf = 0;
  47.  
  48. /* catch silly bases */
  49.     if (base != 0 && (base < 2 || base > 36))
  50.     {
  51.     if (ptr)
  52.         *ptr = str;
  53.     return 0;
  54.     }
  55.  
  56. /* skip leading white space */
  57.     while (*str && isspace(Py_CHARMASK(*str)))
  58.     str++;
  59.  
  60. /* check for leading 0 or 0x for auto-base or base 16 */
  61.     switch (base)
  62.     {
  63.     case 0:        /* look for leading 0, 0x or 0X */
  64.     if (*str == '0')
  65.     {
  66.         str++;
  67.         if (*str == 'x' || *str == 'X')
  68.         {
  69.         str++;
  70.         base = 16;
  71.         }
  72.         else
  73.         base = 8;
  74.     }
  75.     else
  76.         base = 10;
  77.     break;
  78.  
  79.     case 16:    /* skip leading 0x or 0X */
  80.     if (*str == '0' && (*(str+1) == 'x' || *(str+1) == 'X'))
  81.         str += 2;
  82.     break;
  83.     }
  84.  
  85. /* do the conversion */
  86.     while ((c = Py_CHARMASK(*str)) != '\0')
  87.     {
  88.     if (isdigit(c) && c - '0' < base)
  89.         c -= '0';
  90.     else
  91.     {
  92.         if (isupper(c))
  93.         c = tolower(c);
  94.         if (c >= 'a' && c <= 'z')
  95.         c -= 'a' - 10;
  96.         else    /* non-"digit" character */
  97.         break;
  98.         if (c >= base)    /* non-"digit" character */
  99.         break;
  100.     }
  101.     temp = result;
  102.     result = result * base + c;
  103. #ifndef MPW
  104.     if(base == 10) {
  105.         if(((long)(result - c) / base != (long)temp))    /* overflow */
  106.             ovf = 1;
  107.     }
  108.     else {
  109.         if ((result - c) / base != temp)    /* overflow */
  110.             ovf = 1;
  111.     }
  112. #endif
  113.     str++;
  114.     }
  115.  
  116. /* set pointer to point to the last character scanned */
  117.     if (ptr)
  118.     *ptr = str;
  119.     if (ovf)
  120.     {
  121.     result = (unsigned long) ~0L;
  122.     errno = ERANGE;
  123.     }
  124.     return result;
  125. }
  126.  
  127. long
  128. PyOS_strtol(char *str, char **ptr, int base)
  129. {
  130.     long result;
  131.     char sign;
  132.     
  133.     while (*str && isspace(Py_CHARMASK(*str)))
  134.         str++;
  135.     
  136.     sign = *str;
  137.     if (sign == '+' || sign == '-')
  138.         str++;
  139.     
  140.     result = (long) PyOS_strtoul(str, ptr, base);
  141.     
  142.     /* Signal overflow if the result appears negative,
  143.        except for the largest negative integer */
  144.     if (result < 0 && !(sign == '-' && result == -result)) {
  145.         errno = ERANGE;
  146.         result = 0x7fffffff;
  147.     }
  148.     
  149.     if (sign == '-')
  150.         result = -result;
  151.     
  152.     return result;
  153. }
  154.