LCOV - code coverage report
Current view: top level - libreoffice/workdir/unxlngi6.pro/UnpackedTarball/python3/Python - mystrtoul.c (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 36 110 32.7 %
Date: 2012-12-17 Functions: 2 2 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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             : /* strtol and strtoul, renamed to avoid conflicts */
       9             : 
      10             : 
      11             : #include <ctype.h>
      12             : #ifdef HAVE_ERRNO_H
      13             : #include <errno.h>
      14             : #endif
      15             : 
      16             : /* Static overflow check values for bases 2 through 36.
      17             :  * smallmax[base] is the largest unsigned long i such that
      18             :  * i * base doesn't overflow unsigned long.
      19             :  */
      20             : static unsigned long smallmax[] = {
      21             :     0, /* bases 0 and 1 are invalid */
      22             :     0,
      23             :     ULONG_MAX / 2,
      24             :     ULONG_MAX / 3,
      25             :     ULONG_MAX / 4,
      26             :     ULONG_MAX / 5,
      27             :     ULONG_MAX / 6,
      28             :     ULONG_MAX / 7,
      29             :     ULONG_MAX / 8,
      30             :     ULONG_MAX / 9,
      31             :     ULONG_MAX / 10,
      32             :     ULONG_MAX / 11,
      33             :     ULONG_MAX / 12,
      34             :     ULONG_MAX / 13,
      35             :     ULONG_MAX / 14,
      36             :     ULONG_MAX / 15,
      37             :     ULONG_MAX / 16,
      38             :     ULONG_MAX / 17,
      39             :     ULONG_MAX / 18,
      40             :     ULONG_MAX / 19,
      41             :     ULONG_MAX / 20,
      42             :     ULONG_MAX / 21,
      43             :     ULONG_MAX / 22,
      44             :     ULONG_MAX / 23,
      45             :     ULONG_MAX / 24,
      46             :     ULONG_MAX / 25,
      47             :     ULONG_MAX / 26,
      48             :     ULONG_MAX / 27,
      49             :     ULONG_MAX / 28,
      50             :     ULONG_MAX / 29,
      51             :     ULONG_MAX / 30,
      52             :     ULONG_MAX / 31,
      53             :     ULONG_MAX / 32,
      54             :     ULONG_MAX / 33,
      55             :     ULONG_MAX / 34,
      56             :     ULONG_MAX / 35,
      57             :     ULONG_MAX / 36,
      58             : };
      59             : 
      60             : /* maximum digits that can't ever overflow for bases 2 through 36,
      61             :  * calculated by [int(math.floor(math.log(2**32, i))) for i in range(2, 37)].
      62             :  * Note that this is pessimistic if sizeof(long) > 4.
      63             :  */
      64             : #if SIZEOF_LONG == 4
      65             : static int digitlimit[] = {
      66             :     0,  0, 32, 20, 16, 13, 12, 11, 10, 10,  /*  0 -  9 */
      67             :     9,  9,  8,  8,  8,  8,  8,  7,  7,  7,  /* 10 - 19 */
      68             :     7,  7,  7,  7,  6,  6,  6,  6,  6,  6,  /* 20 - 29 */
      69             :     6,  6,  6,  6,  6,  6,  6};             /* 30 - 36 */
      70             : #elif SIZEOF_LONG == 8
      71             : /* [int(math.floor(math.log(2**64, i))) for i in range(2, 37)] */
      72             : static int digitlimit[] = {
      73             :          0,   0, 64, 40, 32, 27, 24, 22, 21, 20,  /*  0 -  9 */
      74             :     19,  18, 17, 17, 16, 16, 16, 15, 15, 15,  /* 10 - 19 */
      75             :     14,  14, 14, 14, 13, 13, 13, 13, 13, 13,  /* 20 - 29 */
      76             :     13,  12, 12, 12, 12, 12, 12};             /* 30 - 36 */
      77             : #else
      78             : #error "Need table for SIZEOF_LONG"
      79             : #endif
      80             : 
      81             : /*
      82             : **      strtoul
      83             : **              This is a general purpose routine for converting
      84             : **              an ascii string to an integer in an arbitrary base.
      85             : **              Leading white space is ignored.  If 'base' is zero
      86             : **              it looks for a leading 0b, 0o or 0x to tell which
      87             : **              base.  If these are absent it defaults to 10.
      88             : **              Base must be 0 or between 2 and 36 (inclusive).
      89             : **              If 'ptr' is non-NULL it will contain a pointer to
      90             : **              the end of the scan.
      91             : **              Errors due to bad pointers will probably result in
      92             : **              exceptions - we don't check for them.
      93             : */
      94             : unsigned long
      95          33 : PyOS_strtoul(register char *str, char **ptr, int base)
      96             : {
      97          33 :     register unsigned long result = 0; /* return value of the function */
      98             :     register int c;             /* current input character */
      99             :     register int ovlimit;       /* required digits to overflow */
     100             : 
     101             :     /* skip leading white space */
     102          66 :     while (*str && isspace(Py_CHARMASK(*str)))
     103           0 :         ++str;
     104             : 
     105             :     /* check for leading 0b, 0o or 0x for auto-base or base 16 */
     106          33 :     switch (base) {
     107             :     case 0:             /* look for leading 0b, 0o or 0x */
     108          33 :         if (*str == '0') {
     109           9 :             ++str;
     110           9 :             if (*str == 'x' || *str == 'X') {
     111             :                 /* there must be at least one digit after 0x */
     112           0 :                 if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 16) {
     113           0 :                     if (ptr)
     114           0 :                         *ptr = str;
     115           0 :                     return 0;
     116             :                 }
     117           0 :                 ++str;
     118           0 :                 base = 16;
     119           9 :             } else if (*str == 'o' || *str == 'O') {
     120             :                 /* there must be at least one digit after 0o */
     121           0 :                 if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 8) {
     122           0 :                     if (ptr)
     123           0 :                         *ptr = str;
     124           0 :                     return 0;
     125             :                 }
     126           0 :                 ++str;
     127           0 :                 base = 8;
     128           9 :             } else if (*str == 'b' || *str == 'B') {
     129             :                 /* there must be at least one digit after 0b */
     130           0 :                 if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 2) {
     131           0 :                     if (ptr)
     132           0 :                         *ptr = str;
     133           0 :                     return 0;
     134             :                 }
     135           0 :                 ++str;
     136           0 :                 base = 2;
     137             :             } else {
     138             :                 /* skip all zeroes... */
     139          18 :                 while (*str == '0')
     140           0 :                     ++str;
     141          18 :                 while (isspace(Py_CHARMASK(*str)))
     142           0 :                     ++str;
     143           9 :                 if (ptr)
     144           9 :                     *ptr = str;
     145           9 :                 return 0;
     146             :             }
     147             :         }
     148             :         else
     149          24 :             base = 10;
     150          24 :         break;
     151             : 
     152             :     /* even with explicit base, skip leading 0? prefix */
     153             :     case 16:
     154           0 :         if (*str == '0') {
     155           0 :             ++str;
     156           0 :             if (*str == 'x' || *str == 'X') {
     157             :                 /* there must be at least one digit after 0x */
     158           0 :                 if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 16) {
     159           0 :                     if (ptr)
     160           0 :                         *ptr = str;
     161           0 :                     return 0;
     162             :                 }
     163           0 :                 ++str;
     164             :             }
     165             :         }
     166           0 :         break;
     167             :     case 8:
     168           0 :         if (*str == '0') {
     169           0 :             ++str;
     170           0 :             if (*str == 'o' || *str == 'O') {
     171             :                 /* there must be at least one digit after 0o */
     172           0 :                 if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 8) {
     173           0 :                     if (ptr)
     174           0 :                         *ptr = str;
     175           0 :                     return 0;
     176             :                 }
     177           0 :                 ++str;
     178             :             }
     179             :         }
     180           0 :         break;
     181             :     case 2:
     182           0 :         if(*str == '0') {
     183           0 :             ++str;
     184           0 :             if (*str == 'b' || *str == 'B') {
     185             :                 /* there must be at least one digit after 0b */
     186           0 :                 if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 2) {
     187           0 :                     if (ptr)
     188           0 :                         *ptr = str;
     189           0 :                     return 0;
     190             :                 }
     191           0 :                 ++str;
     192             :             }
     193             :         }
     194           0 :         break;
     195             :     }
     196             : 
     197             :     /* catch silly bases */
     198          24 :     if (base < 2 || base > 36) {
     199           0 :         if (ptr)
     200           0 :             *ptr = str;
     201           0 :         return 0;
     202             :     }
     203             : 
     204             :     /* skip leading zeroes */
     205          48 :     while (*str == '0')
     206           0 :         ++str;
     207             : 
     208             :     /* base is guaranteed to be in [2, 36] at this point */
     209          24 :     ovlimit = digitlimit[base];
     210             : 
     211             :     /* do the conversion until non-digit character encountered */
     212          72 :     while ((c = _PyLong_DigitValue[Py_CHARMASK(*str)]) < base) {
     213          24 :         if (ovlimit > 0) /* no overflow check required */
     214          24 :             result = result * base + c;
     215             :         else { /* requires overflow check */
     216             :             register unsigned long temp_result;
     217             : 
     218           0 :             if (ovlimit < 0) /* guaranteed overflow */
     219           0 :                 goto overflowed;
     220             : 
     221             :             /* there could be an overflow */
     222             :             /* check overflow just from shifting */
     223           0 :             if (result > smallmax[base])
     224           0 :                 goto overflowed;
     225             : 
     226           0 :             result *= base;
     227             : 
     228             :             /* check overflow from the digit's value */
     229           0 :             temp_result = result + c;
     230           0 :             if (temp_result < result)
     231           0 :                 goto overflowed;
     232             : 
     233           0 :             result = temp_result;
     234             :         }
     235             : 
     236          24 :         ++str;
     237          24 :         --ovlimit;
     238             :     }
     239             : 
     240             :     /* set pointer to point to the last character scanned */
     241          24 :     if (ptr)
     242          24 :         *ptr = str;
     243             : 
     244          24 :     return result;
     245             : 
     246             : overflowed:
     247           0 :     if (ptr) {
     248             :         /* spool through remaining digit characters */
     249           0 :         while (_PyLong_DigitValue[Py_CHARMASK(*str)] < base)
     250           0 :             ++str;
     251           0 :         *ptr = str;
     252             :     }
     253           0 :     errno = ERANGE;
     254           0 :     return (unsigned long)-1;
     255             : }
     256             : 
     257             : /* Checking for overflow in PyOS_strtol is a PITA; see comments
     258             :  * about PY_ABS_LONG_MIN in longobject.c.
     259             :  */
     260             : #define PY_ABS_LONG_MIN         (0-(unsigned long)LONG_MIN)
     261             : 
     262             : long
     263          24 : PyOS_strtol(char *str, char **ptr, int base)
     264             : {
     265             :     long result;
     266             :     unsigned long uresult;
     267             :     char sign;
     268             : 
     269          48 :     while (*str && isspace(Py_CHARMASK(*str)))
     270           0 :         str++;
     271             : 
     272          24 :     sign = *str;
     273          24 :     if (sign == '+' || sign == '-')
     274           0 :         str++;
     275             : 
     276          24 :     uresult = PyOS_strtoul(str, ptr, base);
     277             : 
     278          24 :     if (uresult <= (unsigned long)LONG_MAX) {
     279          24 :         result = (long)uresult;
     280          24 :         if (sign == '-')
     281           0 :             result = -result;
     282             :     }
     283           0 :     else if (sign == '-' && uresult == PY_ABS_LONG_MIN) {
     284           0 :         result = LONG_MIN;
     285             :     }
     286             :     else {
     287           0 :         errno = ERANGE;
     288           0 :         result = LONG_MAX;
     289             :     }
     290          24 :     return result;
     291             : }

Generated by: LCOV version 1.10