]> git.lizzy.rs Git - plan9front.git/blob - sys/src/libc/port/strtol.c
libregexp: improve the transition to next available thread, instruction, and generation
[plan9front.git] / sys / src / libc / port / strtol.c
1 #include <u.h>
2 #include <libc.h>
3
4 #define LONG_MAX        2147483647L
5 #define LONG_MIN        -2147483648L
6
7 long
8 strtol(char *nptr, char **endptr, int base)
9 {
10         char *p;
11         long n, nn, m;
12         int c, ovfl, v, neg, ndig;
13
14         p = nptr;
15         neg = 0;
16         n = 0;
17         ndig = 0;
18         ovfl = 0;
19
20         /*
21          * White space
22          */
23         for(;; p++) {
24                 switch(*p) {
25                 case ' ':
26                 case '\t':
27                 case '\n':
28                 case '\f':
29                 case '\r':
30                 case '\v':
31                         continue;
32                 }
33                 break;
34         }
35
36         /*
37          * Sign
38          */
39         if(*p=='-' || *p=='+')
40                 if(*p++ == '-')
41                         neg = 1;
42
43         /*
44          * Base
45          */
46         if(base==0) {
47                 base = 10;
48                 if(*p == '0') {
49                         base = 8;
50                         if(p[1]=='x' || p[1]=='X') {
51                                 p += 2;
52                                 base = 16;
53                         }
54                 }
55         } else
56         if(base==16 && *p=='0'){
57                 if(p[1]=='x' || p[1]=='X')
58                         p += 2;
59         } else
60         if(base<0 || 36<base)
61                 goto Return;
62
63         /*
64          * Non-empty sequence of digits
65          */
66         m = LONG_MAX/base;
67         for(;; p++,ndig++){
68                 c = *p;
69                 v = base;
70                 if('0'<=c && c<='9')
71                         v = c - '0';
72                 else
73                 if('a'<=c && c<='z')
74                         v = c - 'a' + 10;
75                 else
76                 if('A'<=c && c<='Z')
77                         v = c - 'A' + 10;
78                 if(v >= base)
79                         break;
80                 if(n > m)
81                         ovfl = 1;
82                 nn = n*base + v;
83                 if(nn < n)
84                         ovfl = 1;
85                 n = nn;
86         }
87
88 Return:
89         if(ndig == 0)
90                 p = nptr;
91         if(endptr)
92                 *endptr = p;
93         if(ovfl){
94                 if(neg)
95                         return LONG_MIN;
96                 return LONG_MAX;
97         }
98         if(neg)
99                 return -n;
100         return n;
101 }