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