1 #include <stdio.h>
2 #include <ctype.h>
3
4 /*
5 * digit_a2d[c] maps ascii characters 0..9, a-f, A-F into the corresponding
6 * integer digits. It is NOT ok to give it anything but a digit character
7 * as an argument.
8 */
9 static int digit_a2d[104] = {
10 0, 0, 0, 0, 0, 0, 0, 0, /* 0 - 7 */
11 0, 0, 0, 0, 0, 0, 0, 0, /* 8 - 15 */
12 0, 0, 0, 0, 0, 0, 0, 0, /* 16 - 23 */
13 0, 0, 0, 0, 0, 0, 0, 0, /* 24 - 31 */
14 0, 0, 0, 0, 0, 0, 0, 0, /* 32 - 39 */
15 0, 0, 0, 0, 0, 0, 0, 0, /* 40 - 47 */
16 0, 1, 2, 3, 4, 5, 6, 7, /* 48 - 55 */
17 8, 9, 0, 0, 0, 0, 0, 0, /* 56 - 63 */
18 0,10,11,12,13,14,15, 0, /* 64 - 71 */
19 0, 0, 0, 0, 0, 0, 0, 0, /* 72 - 79 */
20 0, 0, 0, 0, 0, 0, 0, 0, /* 80 - 87 */
21 0, 0, 0, 0, 0, 0, 0, 0, /* 88 - 95 */
22 0,10,11,12,13,14,15, 0, }; /* 96 -103 */
23
strtou(str,ptr,base)24 unsigned long strtou(str, ptr, base)
25
26 /* Converts a string representation of a number to an unsigned long. Leading
27 * whitespace is ignored. The string is scanned up to the first character
28 * inconsistent with the base. Valid numbers have one of the following
29 * formats:
30 * 0[xX]ddd -- hex number; ddd are 0-9, a-f, and A-F
31 * 0[bB]ddd -- binary number; ddd are 0's and 1's
32 * 0ddd -- octal number; ddd are octal digits
33 * dddd -- decimal number; ddd are decimal digits
34 */
35
36 register char *str; /* string to be converted */
37
38 char **ptr; /* if not (char **)NULL, ptr to char terminating scan is returned
39 * in *ptr.
40 */
41
42 int base; /* must be one of 0, 2, 8, 10, or 16, else function returns 0
43 * If the base is zero, the correct base is determined according
44 * as the string has one of the formats given above.
45 */
46
47 {
48 unsigned long value=0;
49
50 if (ptr)
51 *ptr = str;
52
53 /* Special case: null string */
54 if (! *str)
55 return 0;
56
57 /* skip leading whitespace */
58 while (isspace(*str))
59 ++str;
60
61 /* Check for end of string */
62 if (*str == '\0')
63 return 0;
64
65 /* Determine base */
66 if (base == 0) {
67 if (*str != '0')
68 base = 10;
69 else if (*++str == 0) {
70 /* Special case: string is '0' */
71 if (ptr)
72 *ptr = str;
73 return 0;
74 } else if (*str == 'x' || *str == 'X') {
75 base = 16;
76 ++str;
77 } else if (*str == 'b' || *str == 'B') {
78 base = 2;
79 ++str;
80 } else {
81 base = 8;
82 }
83 }
84
85 /* Convert string */
86 switch (base) {
87 case 2:
88 /* Skip 0[bB], if present */
89 if (*str == '0')
90 if (*++str == 'b' || *str == 'B')
91 ++str;
92 more2: while (*str == '0' || *str == '1') {
93 value = value<<1 | digit_a2d[*str];
94 ++str;
95 }
96 if (*str == ',') { /* allow for comma-separated numbers */
97 str++;
98 goto more2;
99 }
100 break;
101 case 8:
102 while (*str >= '0' && *str <= '7') {
103 value = value<<3 | digit_a2d[*str];
104 ++str;
105 }
106 break;
107 case 10:
108 while (isdigit(*str)) {
109 value = value*10 + digit_a2d[*str];
110 ++str;
111 }
112 break;
113 case 16:
114 /* Skip 0[xX], if present */
115 if (*str == '0')
116 if (*++str == 'x' || *str == 'X')
117 ++str;
118 while (isxdigit(*str)) {
119 value = value<<4 | digit_a2d[*str];
120 ++str;
121 }
122 break;
123 default:
124 return 0;
125 }
126
127 if (ptr)
128 *ptr = str;
129
130 return value;
131 }
132