#include <my_global.h>#include "m_string.h"#include "m_ctype.h"#include "my_sys.h"#include <errno.h>Include dependency graph for str2int.c:

Go to the source code of this file.
Defines | |
| #define | char_val(X) |
Functions | |
| char * | str2int (register const char *src, register int radix, long int lower, long int upper, long int *val) |
| #define char_val | ( | X | ) |
| char* str2int | ( | register const char * | src, | |
| register int | radix, | |||
| long int | lower, | |||
| long int | upper, | |||
| long int * | val | |||
| ) |
Definition at line 52 of file str2int.c.
References char_val, errno, my_charset_latin1, my_isspace, n, NullS, and start().
00054 { 00055 int sign; /* is number negative (+1) or positive (-1) */ 00056 int n; /* number of digits yet to be converted */ 00057 long limit; /* "largest" possible valid input */ 00058 long scale; /* the amount to multiply next digit by */ 00059 long sofar; /* the running value */ 00060 register int d; /* (negative of) next digit */ 00061 char *start; 00062 int digits[32]; /* Room for numbers */ 00063 00064 /* Make sure *val is sensible in case of error */ 00065 00066 *val = 0; 00067 00068 /* Check that the radix is in the range 2..36 */ 00069 00070 #ifndef DBUG_OFF 00071 if (radix < 2 || radix > 36) { 00072 errno=EDOM; 00073 return NullS; 00074 } 00075 #endif 00076 00077 /* The basic problem is: how do we handle the conversion of 00078 a number without resorting to machine-specific code to 00079 check for overflow? Obviously, we have to ensure that 00080 no calculation can overflow. We are guaranteed that the 00081 "lower" and "upper" arguments are valid machine integers. 00082 On sign-and-magnitude, twos-complement, and ones-complement 00083 machines all, if +|n| is representable, so is -|n|, but on 00084 twos complement machines the converse is not true. So the 00085 "maximum" representable number has a negative representative. 00086 Limit is set to min(-|lower|,-|upper|); this is the "largest" 00087 number we are concerned with. */ 00088 00089 /* Calculate Limit using Scale as a scratch variable */ 00090 00091 if ((limit = lower) > 0) limit = -limit; 00092 if ((scale = upper) > 0) scale = -scale; 00093 if (scale < limit) limit = scale; 00094 00095 /* Skip leading spaces and check for a sign. 00096 Note: because on a 2s complement machine MinLong is a valid 00097 integer but |MinLong| is not, we have to keep the current 00098 converted value (and the scale!) as *negative* numbers, 00099 so the sign is the opposite of what you might expect. 00100 */ 00101 while (my_isspace(&my_charset_latin1,*src)) src++; 00102 sign = -1; 00103 if (*src == '+') src++; else 00104 if (*src == '-') src++, sign = 1; 00105 00106 /* Skip leading zeros so that we never compute a power of radix 00107 in scale that we won't have a need for. Otherwise sticking 00108 enough 0s in front of a number could cause the multiplication 00109 to overflow when it neededn't. 00110 */ 00111 start=(char*) src; 00112 while (*src == '0') src++; 00113 00114 /* Move over the remaining digits. We have to convert from left 00115 to left in order to avoid overflow. Answer is after last digit. 00116 */ 00117 00118 for (n = 0; (digits[n]=char_val(*src)) < radix && n < 20; n++,src++) ; 00119 00120 /* Check that there is at least one digit */ 00121 00122 if (start == src) { 00123 errno=EDOM; 00124 return NullS; 00125 } 00126 00127 /* The invariant we want to maintain is that src is just 00128 to the right of n digits, we've converted k digits to 00129 sofar, scale = -radix**k, and scale < sofar < 0. Now 00130 if the final number is to be within the original 00131 Limit, we must have (to the left)*scale+sofar >= Limit, 00132 or (to the left)*scale >= Limit-sofar, i.e. the digits 00133 to the left of src must form an integer <= (Limit-sofar)/(scale). 00134 In particular, this is true of the next digit. In our 00135 incremental calculation of Limit, 00136 00137 IT IS VITAL that (-|N|)/(-|D|) = |N|/|D| 00138 */ 00139 00140 for (sofar = 0, scale = -1; --n >= 1;) 00141 { 00142 if ((long) -(d=digits[n]) < limit) { 00143 errno=ERANGE; 00144 return NullS; 00145 } 00146 limit = (limit+d)/radix, sofar += d*scale; scale *= radix; 00147 } 00148 if (n == 0) 00149 { 00150 if ((long) -(d=digits[n]) < limit) /* get last digit */ 00151 { 00152 errno=ERANGE; 00153 return NullS; 00154 } 00155 sofar+=d*scale; 00156 } 00157 00158 /* Now it might still happen that sofar = -32768 or its equivalent, 00159 so we can't just multiply by the sign and check that the result 00160 is in the range lower..upper. All of this caution is a right 00161 pain in the neck. If only there were a standard routine which 00162 says generate thus and such a signal on integer overflow... 00163 But not enough machines can do it *SIGH*. 00164 */ 00165 if (sign < 0) 00166 { 00167 if (sofar < -LONG_MAX || (sofar= -sofar) > upper) 00168 { 00169 errno=ERANGE; 00170 return NullS; 00171 } 00172 } 00173 else if (sofar < lower) 00174 { 00175 errno=ERANGE; 00176 return NullS; 00177 } 00178 *val = sofar; 00179 errno=0; /* indicate that all went well */ 00180 return (char*) src; 00181 }
Here is the call graph for this function:

1.4.7

