scoutos / prex0.9.0 / usr / lib / libc / stdlib / strtol.c @ 03e9c04a
History  View  Annotate  Download (4.1 KB)
1 
/*


2 
* Copyright (c) 1990, 1993

3 
* The Regents of the University of California. All rights reserved.

4 
*

5 
* Redistribution and use in source and binary forms, with or without

6 
* modification, are permitted provided that the following conditions

7 
* are met:

8 
* 1. Redistributions of source code must retain the above copyright

9 
* notice, this list of conditions and the following disclaimer.

10 
* 2. Redistributions in binary form must reproduce the above copyright

11 
* notice, this list of conditions and the following disclaimer in the

12 
* documentation and/or other materials provided with the distribution.

13 
* 3. Neither the name of the University nor the names of its contributors

14 
* may be used to endorse or promote products derived from this software

15 
* without specific prior written permission.

16 
*

17 
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND

18 
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

19 
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

20 
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE

21 
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL

22 
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS

23 
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)

24 
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT

25 
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY

26 
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF

27 
* SUCH DAMAGE.

28 
*/

29  
30 
#include <limits.h> 
31 
#include <ctype.h> 
32 
#include <errno.h> 
33 
#include <stdlib.h> 
34  
35  
36 
/*

37 
* Convert a string to a long integer.

38 
*

39 
* Ignores `locale' stuff. Assumes that the upper and lower case

40 
* alphabets and digits are each contiguous.

41 
*/

42 
long

43 
strtol(nptr, endptr, base) 
44 
const char *nptr; 
45 
char **endptr;

46 
int base;

47 
{ 
48 
const char *s; 
49 
long acc, cutoff;

50 
int c;

51 
int neg, any, cutlim;

52  
53 
/*

54 
* Skip white space and pick up leading +/ sign if any.

55 
* If base is 0, allow 0x for hex and 0 for octal, else

56 
* assume decimal; if base is already 16, allow 0x.

57 
*/

58 
s = nptr; 
59 
do {

60 
c = (unsigned char) *s++; 
61 
} while (isspace(c));

62 
if (c == '') { 
63 
neg = 1;

64 
c = *s++; 
65 
} else {

66 
neg = 0;

67 
if (c == '+') 
68 
c = *s++; 
69 
} 
70 
if ((base == 0  base == 16) && 
71 
c == '0' && (*s == 'x'  *s == 'X')) { 
72 
c = s[1];

73 
s += 2;

74 
base = 16;

75 
} 
76 
if (base == 0) 
77 
base = c == '0' ? 8 : 10; 
78  
79 
/*

80 
* Compute the cutoff value between legal numbers and illegal

81 
* numbers. That is the largest legal value, divided by the

82 
* base. An input number that is greater than this value, if

83 
* followed by a legal input character, is too big. One that

84 
* is equal to this value may be valid or not; the limit

85 
* between valid and invalid numbers is then based on the last

86 
* digit. For instance, if the range for longs is

87 
* [2147483648..2147483647] and the input base is 10,

88 
* cutoff will be set to 214748364 and cutlim to either

89 
* 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated

90 
* a value > 214748364, or equal but the next digit is > 7 (or 8),

91 
* the number is too big, and we will return a range error.

92 
*

93 
* Set any if any `digits' consumed; make it negative to indicate

94 
* overflow.

95 
*/

96 
cutoff = neg ? LONG_MIN : LONG_MAX; 
97 
cutlim = (int)(cutoff % base);

98 
cutoff /= base; 
99 
if (neg) {

100 
if (cutlim > 0) { 
101 
cutlim = base; 
102 
cutoff += 1;

103 
} 
104 
cutlim = cutlim; 
105 
} 
106 
for (acc = 0, any = 0;; c = (unsigned char) *s++) { 
107 
if (isdigit(c))

108 
c = '0';

109 
else if (isalpha(c)) 
110 
c = isupper(c) ? 'A'  10 : 'a'  10; 
111 
else

112 
break;

113 
if (c >= base)

114 
break;

115 
if (any < 0) 
116 
continue;

117 
if (neg) {

118 
if (acc < cutoff  (acc == cutoff && c > cutlim)) {

119 
any = 1;

120 
acc = LONG_MIN; 
121 
errno = ERANGE; 
122 
} else {

123 
any = 1;

124 
acc *= base; 
125 
acc = c; 
126 
} 
127 
} else {

128 
if (acc > cutoff  (acc == cutoff && c > cutlim)) {

129 
any = 1;

130 
acc = LONG_MAX; 
131 
errno = ERANGE; 
132 
} else {

133 
any = 1;

134 
acc *= base; 
135 
acc += c; 
136 
} 
137 
} 
138 
} 
139 
if (endptr != 0) 
140 
/* LINTED interface specification */

141 
*endptr = (char *)(any ? s  1 : nptr); 
142 
return (acc);

143 
} 